/*
 * Copyright 2015 Facebook, Inc.
 *
 * Licensed 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 <folly/io/IOBufQueue.h>

#include <string.h>

#include <stdexcept>

using std::make_pair;
using std::pair;
using std::unique_ptr;

namespace {

using folly::IOBuf;

const size_t MIN_ALLOC_SIZE = 2000;
const size_t MAX_ALLOC_SIZE = 8000;
const size_t MAX_PACK_COPY = 4096;

/**
 * Convenience function to append chain src to chain dst.
 */
void
appendToChain(unique_ptr<IOBuf>& dst, unique_ptr<IOBuf>&& src, bool pack) {
  if (dst == nullptr) {
    dst = std::move(src);
  } else {
    IOBuf* tail = dst->prev();
    if (pack) {
      // Copy up to MAX_PACK_COPY bytes if we can free buffers; this helps
      // reduce wastage (the tail's tailroom and the head's headroom) when
      // joining two IOBufQueues together.
      size_t copyRemaining = MAX_PACK_COPY;
      uint64_t n;
      while (src &&
             (n = src->length()) < copyRemaining &&
             n < tail->tailroom()) {
        memcpy(tail->writableTail(), src->data(), n);
        tail->append(n);
        copyRemaining -= n;
        src = src->pop();
      }
    }
    if (src) {
      tail->appendChain(std::move(src));
    }
  }
}

} // anonymous namespace

namespace folly {

IOBufQueue::IOBufQueue(const Options& options)
  : options_(options),
    chainLength_(0) {
}

IOBufQueue::IOBufQueue(IOBufQueue&& other) noexcept
  : options_(other.options_),
    chainLength_(other.chainLength_),
    head_(std::move(other.head_)) {
  other.chainLength_ = 0;
}

IOBufQueue& IOBufQueue::operator=(IOBufQueue&& other) {
  if (&other != this) {
    options_ = other.options_;
    chainLength_ = other.chainLength_;
    head_ = std::move(other.head_);
    other.chainLength_ = 0;
  }
  return *this;
}

std::pair<void*, uint64_t>
IOBufQueue::headroom() {
  if (head_) {
    return std::make_pair(head_->writableBuffer(), head_->headroom());
  } else {
    return std::make_pair(nullptr, 0);
  }
}

void
IOBufQueue::markPrepended(uint64_t n) {
  if (n == 0) {
    return;
  }
  assert(head_);
  head_->prepend(n);
  chainLength_ += n;
}

void
IOBufQueue::prepend(const void* buf, uint64_t n) {
  auto p = headroom();
  if (n > p.second) {
    throw std::overflow_error("Not enough room to prepend");
  }
  memcpy(static_cast<char*>(p.first) + p.second - n, buf, n);
  markPrepended(n);
}

void
IOBufQueue::append(unique_ptr<IOBuf>&& buf, bool pack) {
  if (!buf) {
    return;
  }
  if (options_.cacheChainLength) {
    chainLength_ += buf->computeChainDataLength();
  }
  appendToChain(head_, std::move(buf), pack);
}

void
IOBufQueue::append(IOBufQueue& other, bool pack) {
  if (!other.head_) {
    return;
  }
  if (options_.cacheChainLength) {
    if (other.options_.cacheChainLength) {
      chainLength_ += other.chainLength_;
    } else {
      chainLength_ += other.head_->computeChainDataLength();
    }
  }
  appendToChain(head_, std::move(other.head_), pack);
  other.chainLength_ = 0;
}

void
IOBufQueue::append(const void* buf, size_t len) {
  auto src = static_cast<const uint8_t*>(buf);
  while (len != 0) {
    if ((head_ == nullptr) || head_->prev()->isSharedOne() ||
        (head_->prev()->tailroom() == 0)) {
      appendToChain(head_, std::move(
          IOBuf::create(std::max(MIN_ALLOC_SIZE,
              std::min(len, MAX_ALLOC_SIZE)))),
          false);
    }
    IOBuf* last = head_->prev();
    uint64_t copyLen = std::min(len, (size_t)last->tailroom());
    memcpy(last->writableTail(), src, copyLen);
    src += copyLen;
    last->append(copyLen);
    chainLength_ += copyLen;
    len -= copyLen;
  }
}

void
IOBufQueue::wrapBuffer(const void* buf, size_t len, uint64_t blockSize) {
  auto src = static_cast<const uint8_t*>(buf);
  while (len != 0) {
    size_t n = std::min(len, size_t(blockSize));
    append(IOBuf::wrapBuffer(src, n));
    src += n;
    len -= n;
  }
}

pair<void*,uint64_t>
IOBufQueue::preallocateSlow(uint64_t min, uint64_t newAllocationSize,
                            uint64_t max) {
  // Allocate a new buffer of the requested max size.
  unique_ptr<IOBuf> newBuf(IOBuf::create(std::max(min, newAllocationSize)));
  appendToChain(head_, std::move(newBuf), false);
  IOBuf* last = head_->prev();
  return make_pair(last->writableTail(),
                   std::min(max, last->tailroom()));
}

unique_ptr<IOBuf>
IOBufQueue::split(size_t n) {
  unique_ptr<IOBuf> result;
  while (n != 0) {
    if (head_ == nullptr) {
      throw std::underflow_error(
          "Attempt to remove more bytes than are present in IOBufQueue");
    } else if (head_->length() <= n) {
      n -= head_->length();
      chainLength_ -= head_->length();
      unique_ptr<IOBuf> remainder = head_->pop();
      appendToChain(result, std::move(head_), false);
      head_ = std::move(remainder);
    } else {
      unique_ptr<IOBuf> clone = head_->cloneOne();
      clone->trimEnd(clone->length() - n);
      appendToChain(result, std::move(clone), false);
      head_->trimStart(n);
      chainLength_ -= n;
      break;
    }
  }
  return std::move(result);
}

void IOBufQueue::trimStart(size_t amount) {
  while (amount > 0) {
    if (!head_) {
      throw std::underflow_error(
        "Attempt to trim more bytes than are present in IOBufQueue");
    }
    if (head_->length() > amount) {
      head_->trimStart(amount);
      chainLength_ -= amount;
      break;
    }
    amount -= head_->length();
    chainLength_ -= head_->length();
    head_ = head_->pop();
  }
}

void IOBufQueue::trimEnd(size_t amount) {
  while (amount > 0) {
    if (!head_) {
      throw std::underflow_error(
        "Attempt to trim more bytes than are present in IOBufQueue");
    }
    if (head_->prev()->length() > amount) {
      head_->prev()->trimEnd(amount);
      chainLength_ -= amount;
      break;
    }
    amount -= head_->prev()->length();
    chainLength_ -= head_->prev()->length();

    if (head_->isChained()) {
      head_->prev()->unlink();
    } else {
      head_.reset();
    }
  }
}

std::unique_ptr<folly::IOBuf> IOBufQueue::pop_front() {
  if (!head_) {
    return nullptr;
  }
  chainLength_ -= head_->length();
  std::unique_ptr<folly::IOBuf> retBuf = std::move(head_);
  head_ = retBuf->pop();
  return retBuf;
}

void IOBufQueue::clear() {
  if (!head_) {
    return;
  }
  IOBuf* buf = head_.get();
  do {
    buf->clear();
    buf = buf->next();
  } while (buf != head_.get());
  chainLength_ = 0;
}

void IOBufQueue::appendToString(std::string& out) const {
  if (!head_) {
    return;
  }
  auto len =
    options_.cacheChainLength ? chainLength_ : head_->computeChainDataLength();
  out.reserve(out.size() + len);

  for (auto range : *head_) {
    out.append(reinterpret_cast<const char*>(range.data()), range.size());
  }
}

} // folly
