// Copyright 2013 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/tools/balsa/balsa_headers.h"

#include <stdio.h>
#include <algorithm>
#include <string>
#include <utility>
#include <vector>

#include "base/containers/hash_tables.h"
#include "base/logging.h"
#include "base/port.h"
#include "base/strings/string_piece.h"
#include "base/strings/stringprintf.h"
#include "net/tools/balsa/balsa_enums.h"
#include "net/tools/balsa/buffer_interface.h"
#include "net/tools/balsa/simple_buffer.h"
#include "third_party/tcmalloc/chromium/src/base/googleinit.h"

#if defined(COMPILER_MSVC)
#include <string.h>
#define snprintf _snprintf
#define strncasecmp _strnicmp
#else
#include <strings.h>
#endif

namespace {

const char kContentLength[] = "Content-Length";
const char kTransferEncoding[] = "Transfer-Encoding";
const char kSpaceChar = ' ';

#if defined(COMPILER_MSVC)
base::hash_set<base::StringPiece,
               net::StringPieceCaseCompare> g_multivalued_headers;
#else
base::hash_set<base::StringPiece,
               net::StringPieceCaseHash,
               net::StringPieceCaseEqual> g_multivalued_headers;
#endif

void InitMultivaluedHeaders() {
  g_multivalued_headers.insert("accept");
  g_multivalued_headers.insert("accept-charset");
  g_multivalued_headers.insert("accept-encoding");
  g_multivalued_headers.insert("accept-language");
  g_multivalued_headers.insert("accept-ranges");
  g_multivalued_headers.insert("allow");
  g_multivalued_headers.insert("cache-control");
  g_multivalued_headers.insert("connection");
  g_multivalued_headers.insert("content-encoding");
  g_multivalued_headers.insert("content-language");
  g_multivalued_headers.insert("expect");
  g_multivalued_headers.insert("if-match");
  g_multivalued_headers.insert("if-none-match");
  g_multivalued_headers.insert("pragma");
  g_multivalued_headers.insert("proxy-authenticate");
  g_multivalued_headers.insert("te");
  g_multivalued_headers.insert("trailer");
  g_multivalued_headers.insert("transfer-encoding");
  g_multivalued_headers.insert("upgrade");
  g_multivalued_headers.insert("vary");
  g_multivalued_headers.insert("via");
  g_multivalued_headers.insert("warning");
  g_multivalued_headers.insert("www-authenticate");
  // Not mentioned in RFC 2616, but it can have multiple values.
  g_multivalued_headers.insert("set-cookie");
}

REGISTER_MODULE_INITIALIZER(multivalued_headers, InitMultivaluedHeaders());

const int kFastToBufferSize = 32;  // I think 22 is adequate, but anyway..

}  // namespace

namespace net {

BalsaHeaders::iterator_base::iterator_base() : headers_(NULL), idx_(0) { }

BalsaHeaders::iterator_base::iterator_base(const iterator_base& it)
    : headers_(it.headers_),
      idx_(it.idx_) {
}

std::ostream& BalsaHeaders::iterator_base::operator<<(std::ostream& os) const {
  os << "[" << this->headers_ << ", " << this->idx_ << "]";
  return os;
}

BalsaHeaders::iterator_base::iterator_base(const BalsaHeaders* headers,
                                           HeaderLines::size_type index)
    : headers_(headers),
      idx_(index) {
}

BalsaBuffer::~BalsaBuffer() {
  CleanupBlocksStartingFrom(0);
}

// Returns the total amount of memory used by the buffer blocks.
size_t BalsaBuffer::GetTotalBufferBlockSize() const {
  size_t buffer_size = 0;
  for (Blocks::const_iterator iter = blocks_.begin();
       iter != blocks_.end();
       ++iter) {
    buffer_size += iter->buffer_size;
  }
  return buffer_size;
}

void BalsaBuffer::WriteToContiguousBuffer(const base::StringPiece& sp) {
  if (sp.empty()) {
    return;
  }
  CHECK(can_write_to_contiguous_buffer_);
  DCHECK_GE(blocks_.size(), 1u);
  if (blocks_[0].buffer == NULL && sp.size() <= blocksize_) {
    blocks_[0] = AllocBlock();
    memcpy(blocks_[0].start_of_unused_bytes(), sp.data(), sp.size());
  } else if (blocks_[0].bytes_free < sp.size()) {
    // the first block isn't big enough, resize it.
    const size_t old_storage_size_used = blocks_[0].bytes_used();
    const size_t new_storage_size = old_storage_size_used + sp.size();
    char* new_storage = new char[new_storage_size];
    char* old_storage = blocks_[0].buffer;
    if (old_storage_size_used) {
      memcpy(new_storage, old_storage, old_storage_size_used);
    }
    memcpy(new_storage + old_storage_size_used, sp.data(), sp.size());
    blocks_[0].buffer = new_storage;
    blocks_[0].bytes_free = sp.size();
    blocks_[0].buffer_size = new_storage_size;
    delete[] old_storage;
  } else {
    memcpy(blocks_[0].start_of_unused_bytes(), sp.data(), sp.size());
  }
  blocks_[0].bytes_free -= sp.size();
}

base::StringPiece BalsaBuffer::Write(const base::StringPiece& sp,
                                     Blocks::size_type* block_buffer_idx) {
  if (sp.empty()) {
    return sp;
  }
  char* storage = Reserve(sp.size(), block_buffer_idx);
  memcpy(storage, sp.data(), sp.size());
  return base::StringPiece(storage, sp.size());
}

char* BalsaBuffer::Reserve(size_t size,
                           Blocks::size_type* block_buffer_idx) {
  // There should always be a 'first_block', even if it
  // contains nothing.
  DCHECK_GE(blocks_.size(), 1u);
  BufferBlock* block = NULL;
  Blocks::size_type block_idx = can_write_to_contiguous_buffer_ ? 1 : 0;
  for (; block_idx < blocks_.size(); ++block_idx) {
    if (blocks_[block_idx].bytes_free >= size) {
      block = &blocks_[block_idx];
      break;
    }
  }
  if (block == NULL) {
    if (blocksize_ < size) {
      blocks_.push_back(AllocCustomBlock(size));
    } else {
      blocks_.push_back(AllocBlock());
    }
    block = &blocks_.back();
  }

  char* storage = block->start_of_unused_bytes();
  block->bytes_free -= size;
  if (block_buffer_idx) {
    *block_buffer_idx = block_idx;
  }
  return storage;
}

void BalsaBuffer::Clear() {
  CHECK(!blocks_.empty());
  if (blocksize_ == blocks_[0].buffer_size) {
    CleanupBlocksStartingFrom(1);
    blocks_[0].bytes_free = blocks_[0].buffer_size;
  } else {
    CleanupBlocksStartingFrom(0);
    blocks_.push_back(AllocBlock());
  }
  DCHECK_GE(blocks_.size(), 1u);
  can_write_to_contiguous_buffer_ = true;
}

void BalsaBuffer::Swap(BalsaBuffer* b) {
  blocks_.swap(b->blocks_);
  std::swap(can_write_to_contiguous_buffer_,
            b->can_write_to_contiguous_buffer_);
  std::swap(blocksize_, b->blocksize_);
}

void BalsaBuffer::CopyFrom(const BalsaBuffer& b) {
  CleanupBlocksStartingFrom(0);
  blocks_.resize(b.blocks_.size());
  for (Blocks::size_type i = 0; i < blocks_.size(); ++i) {
    blocks_[i] = CopyBlock(b.blocks_[i]);
  }
  blocksize_ = b.blocksize_;
  can_write_to_contiguous_buffer_ = b.can_write_to_contiguous_buffer_;
}

BalsaBuffer::BalsaBuffer()
    : blocksize_(kDefaultBlocksize), can_write_to_contiguous_buffer_(true) {
  blocks_.push_back(AllocBlock());
}

BalsaBuffer::BalsaBuffer(size_t blocksize) :
    blocksize_(blocksize), can_write_to_contiguous_buffer_(true) {
  blocks_.push_back(AllocBlock());
}

BalsaBuffer::BufferBlock BalsaBuffer::AllocBlock() {
  return AllocCustomBlock(blocksize_);
}

BalsaBuffer::BufferBlock BalsaBuffer::AllocCustomBlock(size_t blocksize) {
  return BufferBlock(new char[blocksize], blocksize, blocksize);
}

BalsaBuffer::BufferBlock BalsaBuffer::CopyBlock(const BufferBlock& b) {
  BufferBlock block = b;
  if (b.buffer == NULL) {
    return block;
  }

  block.buffer = new char[b.buffer_size];
  memcpy(block.buffer, b.buffer, b.bytes_used());
  return block;
}

void BalsaBuffer::CleanupBlocksStartingFrom(Blocks::size_type start_idx) {
  for (Blocks::size_type i = start_idx; i < blocks_.size(); ++i) {
    delete[] blocks_[i].buffer;
  }
  blocks_.resize(start_idx);
}

BalsaHeaders::const_header_lines_key_iterator::const_header_lines_key_iterator(
    const const_header_lines_key_iterator& other)
    : iterator_base(other),
      key_(other.key_) {
}

BalsaHeaders::const_header_lines_key_iterator::const_header_lines_key_iterator(
    const BalsaHeaders* headers,
    HeaderLines::size_type index,
    const base::StringPiece& key)
    : iterator_base(headers, index),
      key_(key) {
}

BalsaHeaders::const_header_lines_key_iterator::const_header_lines_key_iterator(
    const BalsaHeaders* headers,
    HeaderLines::size_type index)
    : iterator_base(headers, index) {
}

BalsaHeaders::BalsaHeaders()
    : balsa_buffer_(4096),
      content_length_(0),
      content_length_status_(BalsaHeadersEnums::NO_CONTENT_LENGTH),
      parsed_response_code_(0),
      firstline_buffer_base_idx_(0),
      whitespace_1_idx_(0),
      non_whitespace_1_idx_(0),
      whitespace_2_idx_(0),
      non_whitespace_2_idx_(0),
      whitespace_3_idx_(0),
      non_whitespace_3_idx_(0),
      whitespace_4_idx_(0),
      end_of_firstline_idx_(0),
      transfer_encoding_is_chunked_(false) {
}

BalsaHeaders::~BalsaHeaders() {}

void BalsaHeaders::Clear() {
  balsa_buffer_.Clear();
  transfer_encoding_is_chunked_ = false;
  content_length_ = 0;
  content_length_status_ = BalsaHeadersEnums::NO_CONTENT_LENGTH;
  parsed_response_code_ = 0;
  firstline_buffer_base_idx_ = 0;
  whitespace_1_idx_ = 0;
  non_whitespace_1_idx_ = 0;
  whitespace_2_idx_ = 0;
  non_whitespace_2_idx_ = 0;
  whitespace_3_idx_ = 0;
  non_whitespace_3_idx_ = 0;
  whitespace_4_idx_ = 0;
  end_of_firstline_idx_ = 0;
  header_lines_.clear();
}

void BalsaHeaders::Swap(BalsaHeaders* other) {
  // Protect against swapping with self.
  if (this == other) return;

  balsa_buffer_.Swap(&other->balsa_buffer_);

  bool tmp_bool = transfer_encoding_is_chunked_;
  transfer_encoding_is_chunked_ = other->transfer_encoding_is_chunked_;
  other->transfer_encoding_is_chunked_ = tmp_bool;

  size_t tmp_size_t = content_length_;
  content_length_ = other->content_length_;
  other->content_length_ = tmp_size_t;

  BalsaHeadersEnums::ContentLengthStatus tmp_status =
      content_length_status_;
  content_length_status_ = other->content_length_status_;
  other->content_length_status_ = tmp_status;

  tmp_size_t = parsed_response_code_;
  parsed_response_code_ = other->parsed_response_code_;
  other->parsed_response_code_ = tmp_size_t;

  BalsaBuffer::Blocks::size_type tmp_blk_idx = firstline_buffer_base_idx_;
  firstline_buffer_base_idx_ = other->firstline_buffer_base_idx_;
  other->firstline_buffer_base_idx_ = tmp_blk_idx;

  tmp_size_t = whitespace_1_idx_;
  whitespace_1_idx_ = other->whitespace_1_idx_;
  other->whitespace_1_idx_ = tmp_size_t;

  tmp_size_t = non_whitespace_1_idx_;
  non_whitespace_1_idx_ = other->non_whitespace_1_idx_;
  other->non_whitespace_1_idx_ = tmp_size_t;

  tmp_size_t = whitespace_2_idx_;
  whitespace_2_idx_ = other->whitespace_2_idx_;
  other->whitespace_2_idx_ = tmp_size_t;

  tmp_size_t = non_whitespace_2_idx_;
  non_whitespace_2_idx_ = other->non_whitespace_2_idx_;
  other->non_whitespace_2_idx_ = tmp_size_t;

  tmp_size_t = whitespace_3_idx_;
  whitespace_3_idx_ = other->whitespace_3_idx_;
  other->whitespace_3_idx_ = tmp_size_t;

  tmp_size_t = non_whitespace_3_idx_;
  non_whitespace_3_idx_ = other->non_whitespace_3_idx_;
  other->non_whitespace_3_idx_ = tmp_size_t;

  tmp_size_t = whitespace_4_idx_;
  whitespace_4_idx_ = other->whitespace_4_idx_;
  other->whitespace_4_idx_ = tmp_size_t;

  tmp_size_t = end_of_firstline_idx_;
  end_of_firstline_idx_ = other->end_of_firstline_idx_;
  other->end_of_firstline_idx_ = tmp_size_t;

  swap(header_lines_, other->header_lines_);
}

void BalsaHeaders::CopyFrom(const BalsaHeaders& other) {
  // Protect against copying with self.
  if (this == &other) return;

  balsa_buffer_.CopyFrom(other.balsa_buffer_);
  transfer_encoding_is_chunked_ = other.transfer_encoding_is_chunked_;
  content_length_ = other.content_length_;
  content_length_status_ = other.content_length_status_;
  parsed_response_code_ = other.parsed_response_code_;
  firstline_buffer_base_idx_ = other.firstline_buffer_base_idx_;
  whitespace_1_idx_ = other.whitespace_1_idx_;
  non_whitespace_1_idx_ = other.non_whitespace_1_idx_;
  whitespace_2_idx_ = other.whitespace_2_idx_;
  non_whitespace_2_idx_ = other.non_whitespace_2_idx_;
  whitespace_3_idx_ = other.whitespace_3_idx_;
  non_whitespace_3_idx_ = other.non_whitespace_3_idx_;
  whitespace_4_idx_ = other.whitespace_4_idx_;
  end_of_firstline_idx_ = other.end_of_firstline_idx_;
  header_lines_ = other.header_lines_;
}

void BalsaHeaders::AddAndMakeDescription(const base::StringPiece& key,
                                         const base::StringPiece& value,
                                         HeaderLineDescription* d) {
  CHECK(d != NULL);
  // + 2 to size for ": "
  size_t line_size = key.size() + 2 + value.size();
  BalsaBuffer::Blocks::size_type block_buffer_idx = 0;
  char* storage = balsa_buffer_.Reserve(line_size, &block_buffer_idx);
  size_t base_idx = storage - GetPtr(block_buffer_idx);

  char* cur_loc = storage;
  memcpy(cur_loc, key.data(), key.size());
  cur_loc += key.size();
  *cur_loc = ':';
  ++cur_loc;
  *cur_loc = ' ';
  ++cur_loc;
  memcpy(cur_loc, value.data(), value.size());
  *d = HeaderLineDescription(base_idx,
                             base_idx + key.size(),
                             base_idx + key.size() + 2,
                             base_idx + key.size() + 2 + value.size(),
                             block_buffer_idx);
}

void BalsaHeaders::AppendOrPrependAndMakeDescription(
    const base::StringPiece& key,
    const base::StringPiece& value,
    bool append,
    HeaderLineDescription* d) {
  // Figure out how much space we need to reserve for the new header size.
  size_t old_value_size = d->last_char_idx - d->value_begin_idx;
  if (old_value_size == 0) {
    AddAndMakeDescription(key, value, d);
    return;
  }
  base::StringPiece old_value(GetPtr(d->buffer_base_idx) + d->value_begin_idx,
                        old_value_size);

  BalsaBuffer::Blocks::size_type block_buffer_idx = 0;
  // + 3 because we potentially need to add ": ", and "," to the line.
  size_t new_size = key.size() + 3 + old_value_size + value.size();
  char* storage = balsa_buffer_.Reserve(new_size, &block_buffer_idx);
  size_t base_idx = storage - GetPtr(block_buffer_idx);

  base::StringPiece first_value = old_value;
  base::StringPiece second_value = value;
  if (!append) {  // !append == prepend
    first_value = value;
    second_value = old_value;
  }
  char* cur_loc = storage;
  memcpy(cur_loc, key.data(), key.size());
  cur_loc += key.size();
  *cur_loc = ':';
  ++cur_loc;
  *cur_loc = ' ';
  ++cur_loc;
  memcpy(cur_loc, first_value.data(), first_value.size());
  cur_loc += first_value.size();
  *cur_loc = ',';
  ++cur_loc;
  memcpy(cur_loc, second_value.data(), second_value.size());

  *d = HeaderLineDescription(base_idx,
                             base_idx + key.size(),
                             base_idx + key.size() + 2,
                             base_idx + new_size,
                             block_buffer_idx);
}

// Removes all keys value pairs with key 'key' starting at 'start'.
void BalsaHeaders::RemoveAllOfHeaderStartingAt(const base::StringPiece& key,
                                               HeaderLines::iterator start) {
  while (start != header_lines_.end()) {
    start->skip = true;
    ++start;
    start = GetHeaderLinesIterator(key, start);
  }
}

void BalsaHeaders::HackHeader(const base::StringPiece& key,
                              const base::StringPiece& value) {
  // See TODO in balsa_headers.h
  const HeaderLines::iterator end = header_lines_.end();
  const HeaderLines::iterator begin = header_lines_.begin();
  HeaderLines::iterator i = GetHeaderLinesIteratorNoSkip(key, begin);
  if (i != end) {
    // First, remove all of the header lines including this one.  We want to
    // remove before replacing, in case our replacement ends up being appended
    // at the end (and thus would be removed by this call)
    RemoveAllOfHeaderStartingAt(key, i);
    // Now add the replacement, at this location.
    AddAndMakeDescription(key, value, &(*i));
    return;
  }
  AppendHeader(key, value);
}

void BalsaHeaders::HackAppendToHeader(const base::StringPiece& key,
                                      const base::StringPiece& append_value) {
  // See TODO in balsa_headers.h
  const HeaderLines::iterator end = header_lines_.end();
  const HeaderLines::iterator begin = header_lines_.begin();

  HeaderLines::iterator i = GetHeaderLinesIterator(key, begin);
  if (i == end) {
    HackHeader(key, append_value);
    return;
  }

  AppendOrPrependAndMakeDescription(key, append_value, true, &(*i));
}

void BalsaHeaders::ReplaceOrAppendHeader(const base::StringPiece& key,
                                         const base::StringPiece& value) {
  const HeaderLines::iterator end = header_lines_.end();
  const HeaderLines::iterator begin = header_lines_.begin();
  HeaderLines::iterator i = GetHeaderLinesIterator(key, begin);
  if (i != end) {
    // First, remove all of the header lines including this one.  We want to
    // remove before replacing, in case our replacement ends up being appended
    // at the end (and thus would be removed by this call)
    RemoveAllOfHeaderStartingAt(key, i);
    // Now, take the first instance and replace it.  This will remove the
    // 'skipped' tag if the replacement is done in-place.
    AddAndMakeDescription(key, value, &(*i));
    return;
  }
  AppendHeader(key, value);
}

void BalsaHeaders::AppendHeader(const base::StringPiece& key,
                                const base::StringPiece& value) {
  HeaderLineDescription hld;
  AddAndMakeDescription(key, value, &hld);
  header_lines_.push_back(hld);
}

void BalsaHeaders::AppendToHeader(const base::StringPiece& key,
                                  const base::StringPiece& value) {
  AppendOrPrependToHeader(key, value, true);
}

void BalsaHeaders::PrependToHeader(const base::StringPiece& key,
                                   const base::StringPiece& value) {
  AppendOrPrependToHeader(key, value, false);
}

base::StringPiece BalsaHeaders::GetValueFromHeaderLineDescription(
    const HeaderLineDescription& line) const {
  DCHECK_GE(line.last_char_idx, line.value_begin_idx);
  return base::StringPiece(GetPtr(line.buffer_base_idx) + line.value_begin_idx,
                     line.last_char_idx - line.value_begin_idx);
}

const base::StringPiece BalsaHeaders::GetHeader(
    const base::StringPiece& key) const {
  DCHECK(!IsMultivaluedHeader(key))
      << "Header '" << key << "' may consist of multiple lines. Do not "
      << "use BalsaHeaders::GetHeader() or you may be missing some of its "
      << "values.";
  const HeaderLines::const_iterator end = header_lines_.end();
  const HeaderLines::const_iterator begin = header_lines_.begin();
  HeaderLines::const_iterator i = GetConstHeaderLinesIterator(key, begin);
  if (i == end) {
    return base::StringPiece();
  }
  return GetValueFromHeaderLineDescription(*i);
}

BalsaHeaders::const_header_lines_iterator BalsaHeaders::GetHeaderPosition(
    const base::StringPiece& key) const {
  const HeaderLines::const_iterator end = header_lines_.end();
  const HeaderLines::const_iterator begin = header_lines_.begin();
  HeaderLines::const_iterator i = GetConstHeaderLinesIterator(key, begin);
  if (i == end) {
    return header_lines_end();
  }

  return const_header_lines_iterator(this, (i - begin));
}

BalsaHeaders::const_header_lines_key_iterator BalsaHeaders::GetIteratorForKey(
    const base::StringPiece& key) const {
  HeaderLines::const_iterator i =
      GetConstHeaderLinesIterator(key, header_lines_.begin());
  if (i == header_lines_.end()) {
    return header_lines_key_end();
  }

  const HeaderLines::const_iterator begin = header_lines_.begin();
  return const_header_lines_key_iterator(this, (i - begin), key);
}

void BalsaHeaders::AppendOrPrependToHeader(const base::StringPiece& key,
                                           const base::StringPiece& value,
                                           bool append) {
  HeaderLines::iterator i = GetHeaderLinesIterator(key, header_lines_.begin());
  if (i == header_lines_.end()) {
    // The header did not exist already.  Instead of appending to an existing
    // header simply append the key/value pair to the headers.
    AppendHeader(key, value);
    return;
  }
  HeaderLineDescription hld = *i;

  AppendOrPrependAndMakeDescription(key, value, append, &hld);

  // Invalidate the old header line and add the new one.
  i->skip = true;
  header_lines_.push_back(hld);
}

BalsaHeaders::HeaderLines::const_iterator
BalsaHeaders::GetConstHeaderLinesIterator(
    const base::StringPiece& key,
    BalsaHeaders::HeaderLines::const_iterator start) const {
  const HeaderLines::const_iterator end = header_lines_.end();
  for (HeaderLines::const_iterator i = start; i != end; ++i) {
    const HeaderLineDescription& line = *i;
    if (line.skip) {
      continue;
    }
    const size_t key_len = line.key_end_idx - line.first_char_idx;

    if (key_len != key.size()) {
      continue;
    }
    if (strncasecmp(GetPtr(line.buffer_base_idx) + line.first_char_idx,
                    key.data(), key_len) == 0) {
      DCHECK_GE(line.last_char_idx, line.value_begin_idx);
      return i;
    }
  }
  return end;
}

BalsaHeaders::HeaderLines::iterator BalsaHeaders::GetHeaderLinesIteratorNoSkip(
    const base::StringPiece& key,
    BalsaHeaders::HeaderLines::iterator start) {
  const HeaderLines::iterator end = header_lines_.end();
  for (HeaderLines::iterator i = start; i != end; ++i) {
    const HeaderLineDescription& line = *i;
    const size_t key_len = line.key_end_idx - line.first_char_idx;

    if (key_len != key.size()) {
      continue;
    }
    if (strncasecmp(GetPtr(line.buffer_base_idx) + line.first_char_idx,
                    key.data(), key_len) == 0) {
      DCHECK_GE(line.last_char_idx, line.value_begin_idx);
      return i;
    }
  }
  return end;
}

BalsaHeaders::HeaderLines::iterator BalsaHeaders::GetHeaderLinesIterator(
    const base::StringPiece& key,
    BalsaHeaders::HeaderLines::iterator start) {
  const HeaderLines::iterator end = header_lines_.end();
  for (HeaderLines::iterator i = start; i != end; ++i) {
    const HeaderLineDescription& line = *i;
    if (line.skip) {
      continue;
    }
    const size_t key_len = line.key_end_idx - line.first_char_idx;

    if (key_len != key.size()) {
      continue;
    }
    if (strncasecmp(GetPtr(line.buffer_base_idx) + line.first_char_idx,
                    key.data(), key_len) == 0) {
      DCHECK_GE(line.last_char_idx, line.value_begin_idx);
      return i;
    }
  }
  return end;
}

void BalsaHeaders::GetAllOfHeader(
    const base::StringPiece& key, std::vector<base::StringPiece>* out) const {
  for (const_header_lines_key_iterator it = GetIteratorForKey(key);
       it != header_lines_end(); ++it) {
    out->push_back(it->second);
  }
}

bool BalsaHeaders::HasNonEmptyHeader(const base::StringPiece& key) const {
  for (const_header_lines_key_iterator it = GetIteratorForKey(key);
       it != header_lines_key_end(); ++it) {
    if (!it->second.empty())
      return true;
  }
  return false;
}

void BalsaHeaders::GetAllOfHeaderAsString(const base::StringPiece& key,
                                          std::string* out) const {
  const_header_lines_iterator it = header_lines_begin();
  const_header_lines_iterator end = header_lines_end();

  for (; it != end; ++it) {
    if (key == it->first) {
      if (!out->empty()) {
        out->append(",");
      }
      out->append(std::string(it->second.data(), it->second.size()));
    }
  }
}

// static
bool BalsaHeaders::IsMultivaluedHeader(const base::StringPiece& header) {
  return g_multivalued_headers.find(header) != g_multivalued_headers.end();
}

void BalsaHeaders::RemoveAllOfHeader(const base::StringPiece& key) {
  HeaderLines::iterator it = GetHeaderLinesIterator(key, header_lines_.begin());
  RemoveAllOfHeaderStartingAt(key, it);
}

void BalsaHeaders::RemoveAllHeadersWithPrefix(const base::StringPiece& key) {
  for (HeaderLines::size_type i = 0; i < header_lines_.size(); ++i) {
    if (header_lines_[i].skip) {
      continue;
    }
    HeaderLineDescription& line = header_lines_[i];
    const size_t key_len = line.key_end_idx - line.first_char_idx;
    if (key_len < key.size()) {
      // If the key given to us is longer than this header, don't consider it.
      continue;
    }
    if (!strncasecmp(GetPtr(line.buffer_base_idx) + line.first_char_idx,
                     key.data(), key.size())) {
      line.skip = true;
    }
  }
}

size_t BalsaHeaders::GetMemoryUsedLowerBound() const {
  return (sizeof(*this) +
          balsa_buffer_.GetTotalBufferBlockSize() +
          header_lines_.capacity() * sizeof(HeaderLineDescription));
}

size_t BalsaHeaders::GetSizeForWriteBuffer() const {
  // First add the space required for the first line + CRLF
  size_t write_buf_size = whitespace_4_idx_ - non_whitespace_1_idx_ + 2;
  // Then add the space needed for each header line to write out + CRLF.
  const HeaderLines::size_type end = header_lines_.size();
  for (HeaderLines::size_type i = 0; i < end; ++i) {
    const HeaderLineDescription& line = header_lines_[i];
    if (!line.skip) {
      // Add the key size and ": ".
      write_buf_size += line.key_end_idx - line.first_char_idx + 2;
      // Add the value size and the CRLF
      write_buf_size += line.last_char_idx - line.value_begin_idx + 2;
    }
  }
  // Finally tag on the terminal CRLF.
  return write_buf_size + 2;
}

void BalsaHeaders::DumpToString(std::string* str) const {
  const base::StringPiece firstline = first_line();
  const int buffer_length =
      OriginalHeaderStreamEnd() - OriginalHeaderStreamBegin();
  // First check whether the header object is empty.
  if (firstline.empty() && buffer_length == 0) {
    str->append("\n<empty header>\n");
    return;
  }

  // Then check whether the header is in a partially parsed state. If so, just
  // dump the raw data.
  if (balsa_buffer_.can_write_to_contiguous_buffer()) {
    base::StringAppendF(str, "\n<incomplete header len: %d>\n%.*s\n",
                        buffer_length, buffer_length,
                        OriginalHeaderStreamBegin());
    return;
  }

  DumpHeadersToString(str);
}

void BalsaHeaders::DumpHeadersToString(std::string* str) const {
  const base::StringPiece firstline = first_line();
  // If the header is complete, then just dump them with the logical key value
  // pair.
  str->reserve(str->size() + GetSizeForWriteBuffer());
  base::StringAppendF(str, "\n %.*s\n",
                      static_cast<int>(firstline.size()),
                      firstline.data());
  BalsaHeaders::const_header_lines_iterator i = header_lines_begin();
  for (; i != header_lines_end(); ++i) {
    base::StringAppendF(str, " %.*s: %.*s\n",
                        static_cast<int>(i->first.size()), i->first.data(),
                        static_cast<int>(i->second.size()), i->second.data());
  }
}

void BalsaHeaders::SetFirstLine(const base::StringPiece& line) {
  base::StringPiece new_line = balsa_buffer_.Write(line,
                                                   &firstline_buffer_base_idx_);
  whitespace_1_idx_ = new_line.data() - GetPtr(firstline_buffer_base_idx_);
  non_whitespace_1_idx_ = whitespace_1_idx_;
  whitespace_4_idx_ = whitespace_1_idx_ + line.size();
  whitespace_2_idx_ = whitespace_4_idx_;
  non_whitespace_2_idx_ = whitespace_4_idx_;
  whitespace_3_idx_ = whitespace_4_idx_;
  non_whitespace_3_idx_ = whitespace_4_idx_;
  end_of_firstline_idx_ = whitespace_4_idx_;
}

void BalsaHeaders::SetContentLength(size_t length) {
  // If the content-length is already the one we want, don't do anything.
  if (content_length_status_ == BalsaHeadersEnums::VALID_CONTENT_LENGTH &&
      content_length_ == length) {
    return;
  }
  const base::StringPiece content_length(kContentLength,
                                         sizeof(kContentLength) - 1);
  // If header state indicates that there is either a content length or
  // transfer encoding header, remove them before adding the new content
  // length. There is always the possibility that client can manually add
  // either header directly and cause content_length_status_ or
  // transfer_encoding_is_chunked_ to be inconsistent with the actual header.
  // In the interest of efficiency, however, we will assume that clients will
  // use the header object correctly and thus we will not scan the all headers
  // each time this function is called.
  if (content_length_status_ != BalsaHeadersEnums::NO_CONTENT_LENGTH) {
    RemoveAllOfHeader(content_length);
  } else if (transfer_encoding_is_chunked_) {
    const base::StringPiece transfer_encoding(kTransferEncoding,
                                        sizeof(kTransferEncoding) - 1);
    RemoveAllOfHeader(transfer_encoding);
    transfer_encoding_is_chunked_ = false;
  }
  content_length_status_ = BalsaHeadersEnums::VALID_CONTENT_LENGTH;
  content_length_ = length;
  // FastUInt64ToBuffer is supposed to use a maximum of kFastToBufferSize bytes.
  char buffer[kFastToBufferSize];
  int len_converted = snprintf(buffer, sizeof(buffer), "%zd", length);
  CHECK_GT(len_converted, 0);
  const base::StringPiece length_str(buffer, len_converted);
  AppendHeader(content_length, length_str);
}

void BalsaHeaders::SetChunkEncoding(bool chunk_encode) {
  if (transfer_encoding_is_chunked_ == chunk_encode) {
    return;
  }
  if (content_length_status_ != BalsaHeadersEnums::NO_CONTENT_LENGTH &&
      chunk_encode) {
    // Want to change to chunk encoding, but have content length. Arguably we
    // can leave this step out, since transfer-encoding overrides
    // content-length.
    const base::StringPiece content_length(kContentLength,
                                     sizeof(kContentLength) - 1);
    RemoveAllOfHeader(content_length);
    content_length_status_ = BalsaHeadersEnums::NO_CONTENT_LENGTH;
    content_length_ = 0;
  }
  const base::StringPiece transfer_encoding(kTransferEncoding,
                                      sizeof(kTransferEncoding) - 1);
  if (chunk_encode) {
    const char kChunked[] = "chunked";
    const base::StringPiece chunked(kChunked, sizeof(kChunked) - 1);
    AppendHeader(transfer_encoding, chunked);
  } else {
    RemoveAllOfHeader(transfer_encoding);
  }
  transfer_encoding_is_chunked_ = chunk_encode;
}

// See the comment about this function in the header file for a
// warning about its usage.
void BalsaHeaders::SetFirstlineFromStringPieces(
    const base::StringPiece& firstline_a,
    const base::StringPiece& firstline_b,
    const base::StringPiece& firstline_c) {
  size_t line_size = (firstline_a.size() +
                      firstline_b.size() +
                      firstline_c.size() +
                      2);
  char* storage = balsa_buffer_.Reserve(line_size, &firstline_buffer_base_idx_);
  char* cur_loc = storage;

  memcpy(cur_loc, firstline_a.data(), firstline_a.size());
  cur_loc += firstline_a.size();

  *cur_loc = ' ';
  ++cur_loc;

  memcpy(cur_loc, firstline_b.data(), firstline_b.size());
  cur_loc += firstline_b.size();

  *cur_loc = ' ';
  ++cur_loc;

  memcpy(cur_loc, firstline_c.data(), firstline_c.size());

  whitespace_1_idx_ = storage - GetPtr(firstline_buffer_base_idx_);
  non_whitespace_1_idx_ = whitespace_1_idx_;
  whitespace_2_idx_ = non_whitespace_1_idx_ + firstline_a.size();
  non_whitespace_2_idx_ = whitespace_2_idx_ + 1;
  whitespace_3_idx_ = non_whitespace_2_idx_ + firstline_b.size();
  non_whitespace_3_idx_ = whitespace_3_idx_ + 1;
  whitespace_4_idx_ = non_whitespace_3_idx_ + firstline_c.size();
  end_of_firstline_idx_ = whitespace_4_idx_;
}

void BalsaHeaders::SetRequestMethod(const base::StringPiece& method) {
  // This is the first of the three parts of the firstline.
  if (method.size() <= (whitespace_2_idx_ - non_whitespace_1_idx_)) {
    non_whitespace_1_idx_ = whitespace_2_idx_ - method.size();
    char* stream_begin = GetPtr(firstline_buffer_base_idx_);
    memcpy(stream_begin + non_whitespace_1_idx_,
           method.data(),
           method.size());
  } else {
    // The new method is too large to fit in the space available for the old
    // one, so we have to reformat the firstline.
    SetFirstlineFromStringPieces(method, request_uri(), request_version());
  }
}

void BalsaHeaders::SetResponseVersion(const base::StringPiece& version) {
  // Note: There is no difference between request_method() and
  // response_Version(). Thus, a function to set one is equivalent to a
  // function to set the other. We maintain two functions for this as it is
  // much more descriptive, and makes code more understandable.
  SetRequestMethod(version);
}

void BalsaHeaders::SetRequestUri(const base::StringPiece& uri) {
  SetFirstlineFromStringPieces(request_method(), uri, request_version());
}

void BalsaHeaders::SetResponseCode(const base::StringPiece& code) {
  // Note: There is no difference between request_uri() and response_code().
  // Thus, a function to set one is equivalent to a function to set the other.
  // We maintain two functions for this as it is much more descriptive, and
  // makes code more understandable.
  SetRequestUri(code);
}

void BalsaHeaders::SetParsedResponseCodeAndUpdateFirstline(
    size_t parsed_response_code) {
  char buffer[kFastToBufferSize];
  int len_converted = snprintf(buffer, sizeof(buffer),
                               "%zd", parsed_response_code);
  CHECK_GT(len_converted, 0);
  SetResponseCode(base::StringPiece(buffer, len_converted));
}

void BalsaHeaders::SetRequestVersion(const base::StringPiece& version) {
  // This is the last of the three parts of the firstline.
  // Since whitespace_3_idx and non_whitespace_3_idx may point to the same
  // place, we ensure below that any available space includes space for a
  // litteral space (' ') character between the second component and the third
  // component. If the space between whitespace_3_idx_ and
  // end_of_firstline_idx_ is >= to version.size() + 1 (for the space), then we
  // can update the firstline in-place.
  char* stream_begin = GetPtr(firstline_buffer_base_idx_);
  if (version.size() + 1 <= end_of_firstline_idx_ - whitespace_3_idx_) {
    *(stream_begin + whitespace_3_idx_) = kSpaceChar;
    non_whitespace_3_idx_ = whitespace_3_idx_ + 1;
    whitespace_4_idx_ = non_whitespace_3_idx_ + version.size();
    memcpy(stream_begin + non_whitespace_3_idx_,
           version.data(),
           version.size());
  } else {
    // The new version is to large to fit in the space available for the old
    // one, so we have to reformat the firstline.
    SetFirstlineFromStringPieces(request_method(), request_uri(), version);
  }
}

void BalsaHeaders::SetResponseReasonPhrase(const base::StringPiece& reason) {
  // Note: There is no difference between request_version() and
  // response_reason_phrase(). Thus, a function to set one is equivalent to a
  // function to set the other. We maintain two functions for this as it is
  // much more descriptive, and makes code more understandable.
  SetRequestVersion(reason);
}

}  // namespace net
