// Copyright 2017 PDFium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

#include "core/fxcrt/cfx_binarybuf.h"

#include <algorithm>
#include <utility>

#include "core/fxcrt/fx_safe_types.h"

CFX_BinaryBuf::CFX_BinaryBuf() = default;

CFX_BinaryBuf::CFX_BinaryBuf(CFX_BinaryBuf&& that) noexcept
    : m_AllocStep(that.m_AllocStep),
      m_AllocSize(that.m_AllocSize),
      m_DataSize(that.m_DataSize),
      m_pBuffer(std::move(that.m_pBuffer)) {
  // Can't just default, need to leave |that| in a valid state, which means
  // that the size members reflect the (null) moved-from buffer.
  that.m_AllocStep = 0;
  that.m_AllocSize = 0;
  that.m_DataSize = 0;
}

CFX_BinaryBuf::~CFX_BinaryBuf() = default;

CFX_BinaryBuf& CFX_BinaryBuf::operator=(CFX_BinaryBuf&& that) noexcept {
  // Can't just default, need to leave |that| in a valid state, which means
  // that the size members reflect the (null) moved-from buffer.
  m_AllocStep = that.m_AllocStep;
  m_AllocSize = that.m_AllocSize;
  m_DataSize = that.m_DataSize;
  m_pBuffer = std::move(that.m_pBuffer);
  that.m_AllocStep = 0;
  that.m_AllocSize = 0;
  that.m_DataSize = 0;
  return *this;
}

void CFX_BinaryBuf::Delete(size_t start_index, size_t count) {
  if (!m_pBuffer || count > m_DataSize || start_index > m_DataSize - count)
    return;

  memmove(m_pBuffer.get() + start_index, m_pBuffer.get() + start_index + count,
          m_DataSize - start_index - count);
  m_DataSize -= count;
}

pdfium::span<uint8_t> CFX_BinaryBuf::GetSpan() {
  return {GetBuffer(), GetSize()};
}

pdfium::span<const uint8_t> CFX_BinaryBuf::GetSpan() const {
  return {GetBuffer(), GetSize()};
}

size_t CFX_BinaryBuf::GetLength() const {
  return m_DataSize;
}

void CFX_BinaryBuf::Clear() {
  m_DataSize = 0;
}

std::unique_ptr<uint8_t, FxFreeDeleter> CFX_BinaryBuf::DetachBuffer() {
  m_DataSize = 0;
  m_AllocSize = 0;
  return std::move(m_pBuffer);
}

void CFX_BinaryBuf::EstimateSize(size_t size) {
  if (m_AllocSize < size)
    ExpandBuf(size - m_DataSize);
}

void CFX_BinaryBuf::ExpandBuf(size_t add_size) {
  FX_SAFE_SIZE_T new_size = m_DataSize;
  new_size += add_size;
  if (m_AllocSize >= new_size.ValueOrDie())
    return;

  size_t alloc_step = std::max(static_cast<size_t>(128),
                               m_AllocStep ? m_AllocStep : m_AllocSize / 4);
  new_size += alloc_step - 1;  // Quantize, don't combine these lines.
  new_size /= alloc_step;
  new_size *= alloc_step;
  m_AllocSize = new_size.ValueOrDie();
  m_pBuffer.reset(m_pBuffer
                      ? FX_Realloc(uint8_t, m_pBuffer.release(), m_AllocSize)
                      : FX_Alloc(uint8_t, m_AllocSize));
}

void CFX_BinaryBuf::AppendSpan(pdfium::span<const uint8_t> span) {
  return AppendBlock(span.data(), span.size());
}

void CFX_BinaryBuf::AppendBlock(const void* pBuf, size_t size) {
  if (size == 0)
    return;

  ExpandBuf(size);
  if (pBuf) {
    memcpy(m_pBuffer.get() + m_DataSize, pBuf, size);
  } else {
    memset(m_pBuffer.get() + m_DataSize, 0, size);
  }
  m_DataSize += size;
}
