/*
 * 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 "dataBlock.h"
#include <algorithm>

namespace rocketmq {

MemoryBlock::MemoryBlock() : size(0), data(NULL) {}

MemoryBlock::MemoryBlock(const int initialSize, const bool initialiseToZero) : size(0), data(NULL) {
  if (initialSize > 0) {
    size = initialSize;
    data = static_cast<char*>(initialiseToZero ? std::calloc(initialSize, sizeof(char))
                                               : std::malloc(initialSize * sizeof(char)));
  }
}

MemoryBlock::MemoryBlock(const void* const dataToInitialiseFrom, const size_t sizeInBytes)
    : size(sizeInBytes), data(NULL) {
  if (size > 0) {
    data = static_cast<char*>(std::malloc(size * sizeof(char)));

    if (dataToInitialiseFrom != NULL)
      memcpy(data, dataToInitialiseFrom, size);
  }
}

MemoryBlock::MemoryBlock(const MemoryBlock& other) : size(other.size), data(NULL) {
  if (size > 0) {
    data = static_cast<char*>(std::malloc(size * sizeof(char)));
    memcpy(data, other.data, size);
  }
}

MemoryBlock::MemoryBlock(MemoryBlock&& other) : size(other.size), data(other.data) {
  other.size = 0;
  other.data = NULL;
}

MemoryBlock::~MemoryBlock() {
  std::free(data);
}

MemoryBlock& MemoryBlock::operator=(const MemoryBlock& other) {
  if (this != &other) {
    setSize(other.size, false);
    memcpy(data, other.data, size);
  }

  return *this;
}

MemoryBlock& MemoryBlock::operator=(MemoryBlock&& other) {
  if (this != &other) {
    std::free(data);

    size = other.size;
    data = other.data;

    other.size = 0;
    other.data = NULL;
  }

  return *this;
}

//==============================================================================
bool MemoryBlock::operator==(const MemoryBlock& other) const {
  return matches(other.data, other.size);
}

bool MemoryBlock::operator!=(const MemoryBlock& other) const {
  return !operator==(other);
}

bool MemoryBlock::matches(const void* dataToCompare, int dataSize) const {
  return size == dataSize && memcmp(data, dataToCompare, size) == 0;
}

//==============================================================================
// this will resize the block to this size
void MemoryBlock::setSize(const int newSize, const bool initialiseToZero) {
  if (size != newSize) {
    if (newSize <= 0) {
      reset();
    } else {
      if (data != NULL) {
        data = static_cast<char*>(data == NULL ? std::malloc(newSize * sizeof(char))
                                               : std::realloc(data, newSize * sizeof(char)));

        if (initialiseToZero && (newSize > size))
          memset(data + size, 0, newSize - size);
      } else {
        std::free(data);
        data = static_cast<char*>(initialiseToZero ? std::calloc(newSize, sizeof(char))
                                                   : std::malloc(newSize * sizeof(char)));
      }

      size = newSize;
    }
  }
}

void MemoryBlock::reset() {
  std::free(data);
  data = NULL;
  size = 0;
}

void MemoryBlock::ensureSize(const int minimumSize, const bool initialiseToZero) {
  if (size < minimumSize)
    setSize(minimumSize, initialiseToZero);
}

//==============================================================================
void MemoryBlock::fillWith(const int value) {
  memset(data, (int)value, size);
}

void MemoryBlock::append(const void* const srcData, const int numBytes) {
  if (numBytes > 0) {
    const int oldSize = size;
    setSize(size + numBytes);
    memcpy(data + oldSize, srcData, numBytes);
  }
}

void MemoryBlock::replaceWith(const void* const srcData, const int numBytes) {
  if (numBytes > 0) {
    setSize(numBytes);
    memcpy(data, srcData, numBytes);
  }
}

void MemoryBlock::insert(const void* const srcData, const int numBytes, int insertPosition) {
  if (numBytes > 0) {
    insertPosition = std::min(insertPosition, size);
    const int trailingDataSize = size - insertPosition;
    setSize(size + numBytes, false);

    if (trailingDataSize > 0)
      memmove(data + insertPosition + numBytes, data + insertPosition, trailingDataSize);

    memcpy(data + insertPosition, srcData, numBytes);
  }
}

void MemoryBlock::removeSection(const int startByte, const int numBytesToRemove) {
  if (startByte + numBytesToRemove >= size) {
    setSize(startByte);
  } else if (numBytesToRemove > 0) {
    memmove(data + startByte, data + startByte + numBytesToRemove, size - (startByte + numBytesToRemove));

    setSize(size - numBytesToRemove);
  }
}

void MemoryBlock::copyFrom(const void* const src, int offset, int num) {
  const char* d = static_cast<const char*>(src);

  if (offset < 0) {
    d -= offset;
    num += (size_t)-offset;
    offset = 0;
  }

  if ((size_t)offset + num > (unsigned int)size)
    num = size - (size_t)offset;

  if (num > 0)
    memcpy(data + offset, d, num);
}

void MemoryBlock::copyTo(void* const dst, int offset, int num) const {
  char* d = static_cast<char*>(dst);

  if (offset < 0) {
    memset(d, 0, (size_t)-offset);
    d -= offset;
    num -= (size_t)-offset;
    offset = 0;
  }

  if ((size_t)offset + num > (unsigned int)size) {
    const int newNum = (size_t)size - (size_t)offset;
    memset(d + newNum, 0, num - newNum);
    num = newNum;
  }

  if (num > 0)
    memcpy(d, data + offset, num);
}
}  // namespace rocketmq
