/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "MemoryOutputStream.h"

namespace rocketmq {
MemoryOutputStream::MemoryOutputStream(const size_t initialSize)
    : blockToUse(&internalBlock), externalData(NULL), position(0), size(0), availableSize(0) {
  internalBlock.setSize(initialSize, false);
}

MemoryOutputStream::MemoryOutputStream(MemoryBlock& memoryBlockToWriteTo, const bool appendToExistingBlockContent)
    : blockToUse(&memoryBlockToWriteTo), externalData(NULL), position(0), size(0), availableSize(0) {
  if (appendToExistingBlockContent)
    position = size = memoryBlockToWriteTo.getSize();
}

MemoryOutputStream::MemoryOutputStream(void* destBuffer, size_t destBufferSize)
    : blockToUse(NULL), externalData(destBuffer), position(0), size(0), availableSize(destBufferSize) {}

MemoryOutputStream::~MemoryOutputStream() {
  trimExternalBlockSize();
}

void MemoryOutputStream::flush() {
  trimExternalBlockSize();
}

void MemoryOutputStream::trimExternalBlockSize() {
  if (blockToUse != &internalBlock && blockToUse != NULL)
    blockToUse->setSize(size, false);
}

void MemoryOutputStream::preallocate(const size_t bytesToPreallocate) {
  if (blockToUse != NULL)
    blockToUse->ensureSize(bytesToPreallocate + 1);
}

void MemoryOutputStream::reset() {
  position = 0;
  size = 0;
}

char* MemoryOutputStream::prepareToWrite(size_t numBytes) {
  size_t storageNeeded = position + numBytes;

  char* data;

  if (blockToUse != NULL) {
    if (storageNeeded >= (unsigned int)(blockToUse->getSize()))
      blockToUse->ensureSize((storageNeeded + std::min(storageNeeded / 2, (size_t)(1024 * 1024)) + 32) & ~31u);

    data = static_cast<char*>(blockToUse->getData());
  } else {
    if (storageNeeded > availableSize)
      return NULL;

    data = static_cast<char*>(externalData);
  }

  char* const writePointer = data + position;
  position += numBytes;
  size = std::max(size, position);
  return writePointer;
}

bool MemoryOutputStream::write(const void* const buffer, size_t howMany) {
  if (howMany == 0)
    return true;

  if (char* dest = prepareToWrite(howMany)) {
    memcpy(dest, buffer, howMany);
    return true;
  }

  return false;
}

bool MemoryOutputStream::writeRepeatedByte(uint8 byte, size_t howMany) {
  if (howMany == 0)
    return true;

  if (char* dest = prepareToWrite(howMany)) {
    memset(dest, byte, howMany);
    return true;
  }

  return false;
}

MemoryBlock MemoryOutputStream::getMemoryBlock() const {
  return MemoryBlock(getData(), getDataSize());
}

const void* MemoryOutputStream::getData() const {
  if (blockToUse == NULL)
    return externalData;

  if ((unsigned int)blockToUse->getSize() > size)
    static_cast<char*>(blockToUse->getData())[size] = 0;

  return blockToUse->getData();
}

bool MemoryOutputStream::setPosition(int64 newPosition) {
  if (newPosition <= (int64)size) {
    // ok to seek backwards
    if (newPosition < 0)
      position = 0;
    else
      position = (int64)size < newPosition ? size : newPosition;
    return true;
  }

  // can't move beyond the end of the stream..
  return false;
}

int64 MemoryOutputStream::writeFromInputStream(InputStream& source, int64 maxNumBytesToWrite) {
  // before writing from an input, see if we can preallocate to make it more
  // efficient..
  int64 availableData = source.getTotalLength() - source.getPosition();

  if (availableData > 0) {
    if (maxNumBytesToWrite > availableData || maxNumBytesToWrite < 0)
      maxNumBytesToWrite = availableData;

    if (blockToUse != NULL)
      preallocate(blockToUse->getSize() + (size_t)maxNumBytesToWrite);
  }

  return OutputStream::writeFromInputStream(source, maxNumBytesToWrite);
}

OutputStream& operator<<(OutputStream& stream, const MemoryOutputStream& streamToRead) {
  const size_t dataSize = streamToRead.getDataSize();

  if (dataSize > 0)
    stream.write(streamToRead.getData(), dataSize);

  return stream;
}
}  // namespace rocketmq
