// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/third_party/quiche/src/spdy/core/spdy_header_block.h"

#include <string.h>

#include <algorithm>
#include <utility>

#include "base/logging.h"
#include "base/macros.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_estimate_memory_usage.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_ptr_util.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_string_utils.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_unsafe_arena.h"

namespace spdy {
namespace {

// By default, linked_hash_map's internal map allocates space for 100 map
// buckets on construction, which is larger than necessary.  Standard library
// unordered map implementations use a list of prime numbers to set the bucket
// count for a particular capacity.  |kInitialMapBuckets| is chosen to reduce
// memory usage for small header blocks, at the cost of having to rehash for
// large header blocks.
const size_t kInitialMapBuckets = 11;

// SpdyHeaderBlock::Storage allocates blocks of this size by default.
const size_t kDefaultStorageBlockSize = 2048;

const char kCookieKey[] = "cookie";
const char kNullSeparator = 0;

SpdyStringPiece SeparatorForKey(SpdyStringPiece key) {
  if (key == kCookieKey) {
    static SpdyStringPiece cookie_separator = "; ";
    return cookie_separator;
  } else {
    return SpdyStringPiece(&kNullSeparator, 1);
  }
}

}  // namespace

// This class provides a backing store for SpdyStringPieces. It previously used
// custom allocation logic, but now uses an UnsafeArena instead. It has the
// property that SpdyStringPieces that refer to data in Storage are never
// invalidated until the Storage is deleted or Clear() is called.
//
// Write operations always append to the last block. If there is not enough
// space to perform the write, a new block is allocated, and any unused space
// is wasted.
class SpdyHeaderBlock::Storage {
 public:
  Storage() : arena_(kDefaultStorageBlockSize) {}
  Storage(const Storage&) = delete;
  Storage& operator=(const Storage&) = delete;

  SpdyStringPiece Write(const SpdyStringPiece s) {
    return SpdyStringPiece(arena_.Memdup(s.data(), s.size()), s.size());
  }

  // If |s| points to the most recent allocation from arena_, the arena will
  // reclaim the memory. Otherwise, this method is a no-op.
  void Rewind(const SpdyStringPiece s) {
    arena_.Free(const_cast<char*>(s.data()), s.size());
  }

  void Clear() { arena_.Reset(); }

  // Given a list of fragments and a separator, writes the fragments joined by
  // the separator to a contiguous region of memory. Returns a SpdyStringPiece
  // pointing to the region of memory.
  SpdyStringPiece WriteFragments(const std::vector<SpdyStringPiece>& fragments,
                                 SpdyStringPiece separator) {
    if (fragments.empty()) {
      return SpdyStringPiece();
    }
    size_t total_size = separator.size() * (fragments.size() - 1);
    for (const auto fragment : fragments) {
      total_size += fragment.size();
    }
    char* dst = arena_.Alloc(total_size);
    size_t written = Join(dst, fragments, separator);
    DCHECK_EQ(written, total_size);
    return SpdyStringPiece(dst, total_size);
  }

  size_t bytes_allocated() const { return arena_.status().bytes_allocated(); }

  // TODO(xunjieli): https://crbug.com/669108. Merge this with bytes_allocated()
  size_t EstimateMemoryUsage() const {
    return arena_.status().bytes_allocated();
  }

 private:
  SpdyUnsafeArena arena_;
};

SpdyHeaderBlock::HeaderValue::HeaderValue(Storage* storage,
                                          SpdyStringPiece key,
                                          SpdyStringPiece initial_value)
    : storage_(storage),
      fragments_({initial_value}),
      pair_({key, {}}),
      size_(initial_value.size()),
      separator_size_(SeparatorForKey(key).size()) {}

SpdyHeaderBlock::HeaderValue::HeaderValue(HeaderValue&& other)
    : storage_(other.storage_),
      fragments_(std::move(other.fragments_)),
      pair_(std::move(other.pair_)),
      size_(other.size_),
      separator_size_(other.separator_size_) {}

SpdyHeaderBlock::HeaderValue& SpdyHeaderBlock::HeaderValue::operator=(
    HeaderValue&& other) {
  storage_ = other.storage_;
  fragments_ = std::move(other.fragments_);
  pair_ = std::move(other.pair_);
  size_ = other.size_;
  separator_size_ = other.separator_size_;
  return *this;
}

SpdyHeaderBlock::HeaderValue::~HeaderValue() = default;

SpdyStringPiece SpdyHeaderBlock::HeaderValue::ConsolidatedValue() const {
  if (fragments_.empty()) {
    return SpdyStringPiece();
  }
  if (fragments_.size() > 1) {
    fragments_ = {
        storage_->WriteFragments(fragments_, SeparatorForKey(pair_.first))};
  }
  return fragments_[0];
}

void SpdyHeaderBlock::HeaderValue::Append(SpdyStringPiece fragment) {
  size_ += (fragment.size() + separator_size_);
  fragments_.push_back(fragment);
}

const std::pair<SpdyStringPiece, SpdyStringPiece>&
SpdyHeaderBlock::HeaderValue::as_pair() const {
  pair_.second = ConsolidatedValue();
  return pair_;
}

SpdyHeaderBlock::iterator::iterator(MapType::const_iterator it) : it_(it) {}

SpdyHeaderBlock::iterator::iterator(const iterator& other) = default;

SpdyHeaderBlock::iterator::~iterator() = default;

SpdyHeaderBlock::ValueProxy::ValueProxy(
    SpdyHeaderBlock::MapType* block,
    SpdyHeaderBlock::Storage* storage,
    SpdyHeaderBlock::MapType::iterator lookup_result,
    const SpdyStringPiece key,
    size_t* spdy_header_block_value_size)
    : block_(block),
      storage_(storage),
      lookup_result_(lookup_result),
      key_(key),
      spdy_header_block_value_size_(spdy_header_block_value_size),
      valid_(true) {}

SpdyHeaderBlock::ValueProxy::ValueProxy(ValueProxy&& other)
    : block_(other.block_),
      storage_(other.storage_),
      lookup_result_(other.lookup_result_),
      key_(other.key_),
      spdy_header_block_value_size_(other.spdy_header_block_value_size_),
      valid_(true) {
  other.valid_ = false;
}

SpdyHeaderBlock::ValueProxy& SpdyHeaderBlock::ValueProxy::operator=(
    SpdyHeaderBlock::ValueProxy&& other) {
  block_ = other.block_;
  storage_ = other.storage_;
  lookup_result_ = other.lookup_result_;
  key_ = other.key_;
  valid_ = true;
  other.valid_ = false;
  spdy_header_block_value_size_ = other.spdy_header_block_value_size_;
  return *this;
}

SpdyHeaderBlock::ValueProxy::~ValueProxy() {
  // If the ValueProxy is destroyed while lookup_result_ == block_->end(),
  // the assignment operator was never used, and the block's Storage can
  // reclaim the memory used by the key. This makes lookup-only access to
  // SpdyHeaderBlock through operator[] memory-neutral.
  if (valid_ && lookup_result_ == block_->end()) {
    storage_->Rewind(key_);
  }
}

SpdyHeaderBlock::ValueProxy& SpdyHeaderBlock::ValueProxy::operator=(
    const SpdyStringPiece value) {
  *spdy_header_block_value_size_ += value.size();
  if (lookup_result_ == block_->end()) {
    DVLOG(1) << "Inserting: (" << key_ << ", " << value << ")";
    lookup_result_ =
        block_
            ->emplace(std::make_pair(
                key_, HeaderValue(storage_, key_, storage_->Write(value))))
            .first;
  } else {
    DVLOG(1) << "Updating key: " << key_ << " with value: " << value;
    *spdy_header_block_value_size_ -= lookup_result_->second.SizeEstimate();
    lookup_result_->second =
        HeaderValue(storage_, key_, storage_->Write(value));
  }
  return *this;
}

SpdyString SpdyHeaderBlock::ValueProxy::as_string() const {
  if (lookup_result_ == block_->end()) {
    return "";
  } else {
    return SpdyString(lookup_result_->second.value());
  }
}

SpdyHeaderBlock::SpdyHeaderBlock() : block_(kInitialMapBuckets) {}

SpdyHeaderBlock::SpdyHeaderBlock(SpdyHeaderBlock&& other)
    : block_(kInitialMapBuckets) {
  block_.swap(other.block_);
  storage_.swap(other.storage_);
  key_size_ = other.key_size_;
  value_size_ = other.value_size_;
}

SpdyHeaderBlock::~SpdyHeaderBlock() = default;

SpdyHeaderBlock& SpdyHeaderBlock::operator=(SpdyHeaderBlock&& other) {
  block_.swap(other.block_);
  storage_.swap(other.storage_);
  key_size_ = other.key_size_;
  value_size_ = other.value_size_;
  return *this;
}

SpdyHeaderBlock SpdyHeaderBlock::Clone() const {
  SpdyHeaderBlock copy;
  for (const auto& p : *this) {
    copy.AppendHeader(p.first, p.second);
  }
  return copy;
}

bool SpdyHeaderBlock::operator==(const SpdyHeaderBlock& other) const {
  return size() == other.size() && std::equal(begin(), end(), other.begin());
}

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

SpdyString SpdyHeaderBlock::DebugString() const {
  if (empty()) {
    return "{}";
  }

  SpdyString output = "\n{\n";
  for (auto it = begin(); it != end(); ++it) {
    SpdyStrAppend(&output, "  ", it->first, " ", it->second, "\n");
  }
  SpdyStrAppend(&output, "}\n");
  return output;
}

void SpdyHeaderBlock::erase(SpdyStringPiece key) {
  auto iter = block_.find(key);
  if (iter != block_.end()) {
    DVLOG(1) << "Erasing header with name: " << key;
    key_size_ -= key.size();
    value_size_ -= iter->second.SizeEstimate();
    block_.erase(iter);
  }
}

void SpdyHeaderBlock::clear() {
  key_size_ = 0;
  value_size_ = 0;
  block_.clear();
  storage_.reset();
}

void SpdyHeaderBlock::insert(const SpdyHeaderBlock::value_type& value) {
  // TODO(birenroy): Write new value in place of old value, if it fits.
  value_size_ += value.second.size();

  auto iter = block_.find(value.first);
  if (iter == block_.end()) {
    DVLOG(1) << "Inserting: (" << value.first << ", " << value.second << ")";
    AppendHeader(value.first, value.second);
  } else {
    DVLOG(1) << "Updating key: " << iter->first
             << " with value: " << value.second;
    value_size_ -= iter->second.SizeEstimate();
    auto* storage = GetStorage();
    iter->second =
        HeaderValue(storage, iter->first, storage->Write(value.second));
  }
}

SpdyHeaderBlock::ValueProxy SpdyHeaderBlock::operator[](
    const SpdyStringPiece key) {
  DVLOG(2) << "Operator[] saw key: " << key;
  SpdyStringPiece out_key;
  auto iter = block_.find(key);
  if (iter == block_.end()) {
    // We write the key first, to assure that the ValueProxy has a
    // reference to a valid SpdyStringPiece in its operator=.
    out_key = WriteKey(key);
    DVLOG(2) << "Key written as: " << std::hex
             << static_cast<const void*>(key.data()) << ", " << std::dec
             << key.size();
  } else {
    out_key = iter->first;
  }
  return ValueProxy(&block_, GetStorage(), iter, out_key, &value_size_);
}

void SpdyHeaderBlock::AppendValueOrAddHeader(const SpdyStringPiece key,
                                             const SpdyStringPiece value) {
  value_size_ += value.size();

  auto iter = block_.find(key);
  if (iter == block_.end()) {
    DVLOG(1) << "Inserting: (" << key << ", " << value << ")";

    AppendHeader(key, value);
    return;
  }
  DVLOG(1) << "Updating key: " << iter->first << "; appending value: " << value;
  value_size_ += SeparatorForKey(key).size();
  iter->second.Append(GetStorage()->Write(value));
}

size_t SpdyHeaderBlock::EstimateMemoryUsage() const {
  // TODO(xunjieli): https://crbug.com/669108. Also include |block_| when EMU()
  // supports linked_hash_map.
  return SpdyEstimateMemoryUsage(storage_);
}

void SpdyHeaderBlock::AppendHeader(const SpdyStringPiece key,
                                   const SpdyStringPiece value) {
  auto backed_key = WriteKey(key);
  auto* storage = GetStorage();
  block_.emplace(std::make_pair(
      backed_key, HeaderValue(storage, backed_key, storage->Write(value))));
}

SpdyHeaderBlock::Storage* SpdyHeaderBlock::GetStorage() {
  if (storage_ == nullptr) {
    storage_ = SpdyMakeUnique<Storage>();
  }
  return storage_.get();
}

SpdyStringPiece SpdyHeaderBlock::WriteKey(const SpdyStringPiece key) {
  key_size_ += key.size();
  return GetStorage()->Write(key);
}

size_t SpdyHeaderBlock::bytes_allocated() const {
  if (storage_ == nullptr) {
    return 0;
  } else {
    return storage_->bytes_allocated();
  }
}

size_t Join(char* dst,
            const std::vector<SpdyStringPiece>& fragments,
            SpdyStringPiece separator) {
  if (fragments.empty()) {
    return 0;
  }
  auto* original_dst = dst;
  auto it = fragments.begin();
  memcpy(dst, it->data(), it->size());
  dst += it->size();
  for (++it; it != fragments.end(); ++it) {
    memcpy(dst, separator.data(), separator.size());
    dst += separator.size();
    memcpy(dst, it->data(), it->size());
    dst += it->size();
  }
  return dst - original_dst;
}

}  // namespace spdy
