// 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.

#ifndef NET_TOOLS_BALSA_BALSA_HEADERS_H_
#define NET_TOOLS_BALSA_BALSA_HEADERS_H_

#include <algorithm>
#include <iosfwd>
#include <iterator>
#include <string>
#include <utility>
#include <vector>

#include "base/logging.h"
#include "base/port.h"
#include "base/strings/string_piece.h"
#include "net/tools/balsa/balsa_enums.h"
#include "net/tools/balsa/string_piece_utils.h"

namespace net {

// WARNING:
// Note that -no- char* returned by any function in this
// file is null-terminated.

// This class exists to service the specific needs of BalsaHeaders.
//
// Functional goals:
//   1) provide a backing-store for all of the StringPieces that BalsaHeaders
//      returns. Every StringPiece returned from BalsaHeaders should remain
//      valid until the BalsaHeader's object is cleared, or the header-line is
//      erased.
//   2) provide a backing-store for BalsaFrame, which requires contiguous memory
//      for its fast-path parsing functions. Note that the cost of copying is
//      less than the cost of requiring the parser to do slow-path parsing, as
//      it would have to check for bounds every byte, instead of every 16 bytes.
//
// This class is optimized for the case where headers are stored in one of two
// buffers. It doesn't make a lot of effort to densely pack memory-- in fact,
// it -may- be somewhat memory inefficient. This possible inefficiency allows a
// certain simplicity of implementation and speed which makes it worthwhile.
// If, in the future, better memory density is required, it should be possible
// to reuse the abstraction presented by this object to achieve those goals.
//
// In the most common use-case, this memory inefficiency should be relatively
// small.
//
// Alternate implementations of BalsaBuffer may include:
//  - vector of strings, one per header line (similar to HTTPHeaders)
//  - densely packed strings:
//    - keep a sorted array/map of free-space linked lists or numbers.
//      - use the entry that most closely first your needs.
//    - at this point, perhaps just use a vector of strings, and let
//      the allocator do the right thing.
//
class BalsaBuffer {
 public:
  static const size_t kDefaultBlocksize = 4096;
  // We have two friends here. These exist as friends as we
  // want to allow access to the constructors for the test
  // class and the Balsa* classes. We put this into the
  // header file as we want this class to be inlined into the
  // BalsaHeaders implementation, yet be testable.
  friend class BalsaBufferTestSpouse;
  friend class BalsaHeaders;
  friend class BalsaBufferTest;

  // The BufferBlock is a structure used internally by the
  // BalsaBuffer class to store the base buffer pointers to
  // each block, as well as the important metadata for buffer
  // sizes and bytes free.
  struct BufferBlock {
   public:
    char* buffer;
    size_t buffer_size;
    size_t bytes_free;

    size_t bytes_used() const {
      return buffer_size - bytes_free;
    }
    char* start_of_unused_bytes() const {
      return buffer + bytes_used();
    }

    BufferBlock() : buffer(NULL), buffer_size(0), bytes_free(0) {}
    ~BufferBlock() {}

    BufferBlock(char* buf, size_t size, size_t free) :
        buffer(buf), buffer_size(size), bytes_free(free) {}
    // Yes we want this to be copyable (it gets stuck into vectors).
    // For this reason, we don't use scoped ptrs, etc. here-- it
    // is more efficient to manage this memory externally to this
    // object.
  };

  typedef std::vector<BufferBlock> Blocks;

  ~BalsaBuffer();

  // Returns the total amount of memory used by the buffer blocks.
  size_t GetTotalBufferBlockSize() const;

  const char* GetPtr(Blocks::size_type block_idx) const {
    DCHECK_LT(block_idx, blocks_.size())
      << block_idx << ", " << blocks_.size();
    return blocks_[block_idx].buffer;
  }

  char* GetPtr(Blocks::size_type block_idx) {
    DCHECK_LT(block_idx, blocks_.size())
      << block_idx << ", " << blocks_.size();
    return blocks_[block_idx].buffer;
  }

  // This function is different from Write(), as it ensures that the data
  // stored via subsequent calls to this function are all contiguous (and in
  // the order in which these writes happened). This is essentially the same
  // as a string append.
  //
  // You may call this function at any time between object
  // construction/Clear(), and the calling of the
  // NoMoreWriteToContiguousBuffer() function.
  //
  // You must not call this function after the NoMoreWriteToContiguousBuffer()
  // function is called, unless a Clear() has been called since.
  // If you do, the program will abort().
  //
  // This condition is placed upon this code so that calls to Write() can
  // append to the buffer in the first block safely, and without invaliding
  // the StringPiece which it returns.
  //
  // This function's main intended user is the BalsaFrame class, which,
  // for reasons of efficiency, requires that the buffer from which it parses
  // the headers be contiguous.
  //
  void WriteToContiguousBuffer(const base::StringPiece& sp);

  void NoMoreWriteToContiguousBuffer() {
    can_write_to_contiguous_buffer_ = false;
  }

  // Takes a StringPiece and writes it to "permanent" storage, then returns a
  // StringPiece which points to that data.  If block_idx != NULL, it will be
  // assigned the index of the block into which the data was stored.
  // Note that the 'permanent' storage in which it stores data may be in
  // the first block IFF the NoMoreWriteToContiguousBuffer function has
  // been called since the last Clear/Construction.
  base::StringPiece Write(const base::StringPiece& sp,
                          Blocks::size_type* block_buffer_idx);

  // Reserves "permanent" storage of the size indicated. Returns a pointer to
  // the beginning of that storage, and assigns the index of the block used to
  // block_buffer_idx. This function uses the first block IFF the
  // NoMoreWriteToContiguousBuffer function has been called since the last
  // Clear/Construction.
  char* Reserve(size_t size, Blocks::size_type* block_buffer_idx);

  void Clear();

  void Swap(BalsaBuffer* b);

  void CopyFrom(const BalsaBuffer& b);

  const char* StartOfFirstBlock() const {
    return blocks_[0].buffer;
  }

  const char* EndOfFirstBlock() const {
    return blocks_[0].buffer + blocks_[0].bytes_used();
  }

  bool can_write_to_contiguous_buffer() const {
    return can_write_to_contiguous_buffer_;
  }
  size_t blocksize() const { return blocksize_; }
  Blocks::size_type num_blocks() const { return blocks_.size(); }
  size_t buffer_size(size_t idx) const { return blocks_[idx].buffer_size; }
  size_t bytes_used(size_t idx) const { return blocks_[idx].bytes_used(); }

 protected:
  BalsaBuffer();

  explicit BalsaBuffer(size_t blocksize);

  BufferBlock AllocBlock();

  BufferBlock AllocCustomBlock(size_t blocksize);

  BufferBlock CopyBlock(const BufferBlock& b);

  // Cleans up the object.
  // The block at start_idx, and all subsequent blocks
  // will be cleared and have associated memory deleted.
  void CleanupBlocksStartingFrom(Blocks::size_type start_idx);

  // A container of BufferBlocks
  Blocks blocks_;

  // The default allocation size for a block.
  // In general, blocksize_ bytes will be allocated for
  // each buffer.
  size_t blocksize_;

  // If set to true, then the first block cannot be used for Write() calls as
  // the WriteToContiguous... function will modify the base pointer for this
  // block, and the Write() calls need to be sure that the base pointer will
  // not be changing in order to provide the user with StringPieces which
  // continue to be valid.
  bool can_write_to_contiguous_buffer_;
};

////////////////////////////////////////////////////////////////////////////////

// All of the functions in the BalsaHeaders class use string pieces, by either
// using the StringPiece class, or giving an explicit size and char* (as these
// are the native representation for these string pieces).
// This is done for several reasons.
//  1) This minimizes copying/allocation/deallocation as compared to using
//  string parameters
//  2) This reduces the number of strlen() calls done (as the length of any
//  string passed in is relatively likely to be known at compile time, and for
//  those strings passed back we obviate the need for a strlen() to determine
//  the size of new storage allocations if a new allocation is required.
//  3) This class attempts to store all of its data in two linear buffers in
//  order to enhance the speed of parsing and writing out to a buffer. As a
//  result, many string pieces are -not- terminated by '\0', and are not
//  c-strings.  Since this is the case, we must delineate the length of the
//  string explicitly via a length.
//
//  WARNING:  The side effect of using StringPiece is that if the underlying
//  buffer changes (due to modifying the headers) the StringPieces which point
//  to the data which was modified, may now contain "garbage", and should not
//  be dereferenced.
//  For example, If you fetch some component of the first-line, (request or
//  response), and then you modify the first line, the StringPieces you
//  originally received from the original first-line may no longer be valid).
//
//  StringPieces pointing to pieces of header lines which have not been
//  erased() or modified should be valid until the object is cleared or
//  destroyed.

class BalsaHeaders {
 public:
  struct HeaderLineDescription {
    HeaderLineDescription(size_t first_character_index,
                          size_t key_end_index,
                          size_t value_begin_index,
                          size_t last_character_index,
                          size_t buffer_base_index) :
        first_char_idx(first_character_index),
        key_end_idx(key_end_index),
        value_begin_idx(value_begin_index),
        last_char_idx(last_character_index),
        buffer_base_idx(buffer_base_index),
        skip(false) {}

    HeaderLineDescription() :
        first_char_idx(0),
        key_end_idx(0),
        value_begin_idx(0),
        last_char_idx(0),
        buffer_base_idx(0),
        skip(false) {}

    size_t first_char_idx;
    size_t key_end_idx;
    size_t value_begin_idx;
    size_t last_char_idx;
    BalsaBuffer::Blocks::size_type buffer_base_idx;
    bool skip;
  };

  typedef std::vector<base::StringPiece> HeaderTokenList;
  friend bool ParseHTTPFirstLine(const char* begin,
                                 const char* end,
                                 bool is_request,
                                 size_t max_request_uri_length,
                                 BalsaHeaders* headers,
                                 BalsaFrameEnums::ErrorCode* error_code);

 protected:
  typedef std::vector<HeaderLineDescription> HeaderLines;

  // Why these base classes (iterator_base, reverse_iterator_base)?  Well, if
  // we do want to export both iterator and const_iterator types (currently we
  // only have const_iterator), then this is useful to avoid code duplication.
  // Additionally, having this base class makes comparisons of iterators of
  // different types (they're different types to ensure that operator= and
  // constructors do not work in the places where they're expected to not work)
  // work properly. There could be as many as 4 iterator types, all based on
  // the same data as iterator_base... so it makes sense to simply have some
  // base classes.

  class iterator_base {
   public:
    friend class BalsaHeaders;
    friend class reverse_iterator_base;
    typedef std::pair<base::StringPiece, base::StringPiece> StringPiecePair;
    typedef StringPiecePair value_type;
    typedef value_type& reference;
    typedef value_type* pointer;

    typedef std::forward_iterator_tag iterator_category;
    typedef ptrdiff_t difference_type;

    typedef iterator_base self;

    // default constructor.
    iterator_base();

    // copy constructor.
    iterator_base(const iterator_base& it);

    reference operator*() const {
      return Lookup(idx_);
    }

    pointer operator->() const {
      return &(this->operator*());
    }

    bool operator==(const self& it) const {
      return idx_ == it.idx_;
    }

    bool operator<(const self& it) const {
      return idx_ < it.idx_;
    }

    bool operator<=(const self& it) const {
      return idx_ <= it.idx_;
    }

    bool operator!=(const self& it) const {
      return !(*this == it);
    }

    bool operator>(const self& it) const {
      return it < *this;
    }

    bool operator>=(const self& it) const {
      return it <= *this;
    }

    // This mainly exists so that we can have interesting output for
    // unittesting. The EXPECT_EQ, EXPECT_NE functions require that
    // operator<< work for the classes it sees.  It would be better if there
    // was an additional traits-like system for the gUnit output... but oh
    // well.
    std::ostream& operator<<(std::ostream& os) const;

   protected:
    iterator_base(const BalsaHeaders* headers, HeaderLines::size_type index);

    void increment() {
      const HeaderLines& header_lines = headers_->header_lines_;
      const HeaderLines::size_type header_lines_size = header_lines.size();
      const HeaderLines::size_type original_idx = idx_;
      do {
        ++idx_;
      } while (idx_ < header_lines_size && header_lines[idx_].skip == true);
      // The condition below exists so that ++(end() - 1) == end(), even
      // if there are only 'skip == true' elements between the end() iterator
      // and the end of the vector of HeaderLineDescriptions.
      // TODO(fenix): refactor this list so that we don't have to do
      // linear scanning through skipped headers (and this condition is
      // then unnecessary)
      if (idx_ == header_lines_size) {
        idx_ = original_idx + 1;
      }
    }

    void decrement() {
      const HeaderLines& header_lines = headers_->header_lines_;
      const HeaderLines::size_type header_lines_size = header_lines.size();
      const HeaderLines::size_type original_idx = idx_;
      do {
        --idx_;
      } while (idx_ < header_lines_size && header_lines[idx_].skip == true);
      // The condition below exists so that --(rbegin() + 1) == rbegin(), even
      // if there are only 'skip == true' elements between the rbegin() iterator
      // and the beginning of the vector of HeaderLineDescriptions.
      // TODO(fenix): refactor this list so that we don't have to do
      // linear scanning through skipped headers (and this condition is
      // then unnecessary)
      if (idx_ > header_lines_size) {
        idx_ = original_idx - 1;
      }
    }

    reference Lookup(HeaderLines::size_type index) const {
      DCHECK_LT(index, headers_->header_lines_.size());
      const HeaderLineDescription& line = headers_->header_lines_[index];
      const char* stream_begin = headers_->GetPtr(line.buffer_base_idx);
      value_ = value_type(
          base::StringPiece(stream_begin + line.first_char_idx,
                      line.key_end_idx - line.first_char_idx),
          base::StringPiece(stream_begin + line.value_begin_idx,
                      line.last_char_idx - line.value_begin_idx));
      DCHECK_GE(line.key_end_idx, line.first_char_idx);
      DCHECK_GE(line.last_char_idx, line.value_begin_idx);
      return value_;
    }

    const BalsaHeaders* headers_;
    HeaderLines::size_type idx_;
    mutable StringPiecePair value_;
  };

  class reverse_iterator_base : public iterator_base {
   public:
    typedef reverse_iterator_base self;
    typedef iterator_base::reference reference;
    typedef iterator_base::pointer pointer;
    using iterator_base::headers_;
    using iterator_base::idx_;

    reverse_iterator_base() : iterator_base() {}

    // This constructor is no explicit purposely.
    reverse_iterator_base(const iterator_base& it) :  // NOLINT
        iterator_base(it) {
    }

    self& operator=(const iterator_base& it) {
      idx_ = it.idx_;
      headers_ = it.headers_;
      return *this;
    }

    self& operator=(const reverse_iterator_base& it) {
      idx_ = it.idx_;
      headers_ = it.headers_;
      return *this;
    }

    reference operator*() const {
      return Lookup(idx_ - 1);
    }

    pointer operator->() const {
      return &(this->operator*());
    }

    reverse_iterator_base(const reverse_iterator_base& it) :
        iterator_base(it) { }

   protected:
    void increment() {
      --idx_;
      iterator_base::decrement();
      ++idx_;
    }

    void decrement() {
      ++idx_;
      iterator_base::increment();
      --idx_;
    }

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

 public:
  class const_header_lines_iterator : public iterator_base {
    friend class BalsaHeaders;
   public:
    typedef const_header_lines_iterator self;
    const_header_lines_iterator() : iterator_base() {}

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

    self& operator++() {
      iterator_base::increment();
      return *this;
    }

    self& operator--() {
      iterator_base::decrement();
      return *this;
    }
   protected:
    const_header_lines_iterator(const BalsaHeaders* headers,
                                HeaderLines::size_type index) :
        iterator_base(headers, index) {}
  };

  class const_reverse_header_lines_iterator : public reverse_iterator_base {
   public:
    typedef const_reverse_header_lines_iterator self;
    const_reverse_header_lines_iterator() : reverse_iterator_base() {}

    const_reverse_header_lines_iterator(
      const const_header_lines_iterator& it) :
        reverse_iterator_base(it.headers_, it.idx_) {}

    const_reverse_header_lines_iterator(
      const const_reverse_header_lines_iterator& it) :
        reverse_iterator_base(it.headers_, it.idx_) {}

    const_header_lines_iterator base() {
      return const_header_lines_iterator(headers_, idx_);
    }

    self& operator++() {
      reverse_iterator_base::increment();
      return *this;
    }

    self& operator--() {
      reverse_iterator_base::decrement();
      return *this;
    }
   protected:
    const_reverse_header_lines_iterator(const BalsaHeaders* headers,
                                        HeaderLines::size_type index) :
        reverse_iterator_base(headers, index) {}

    friend class BalsaHeaders;
  };

  // An iterator that only stops at lines with a particular key.
  // See also GetIteratorForKey.
  //
  // Check against header_lines_key_end() to determine when iteration is
  // finished. header_lines_end() will also work.
  class const_header_lines_key_iterator : public iterator_base {
    friend class BalsaHeaders;
   public:
    typedef const_header_lines_key_iterator self;
    const_header_lines_key_iterator(const const_header_lines_key_iterator&);

    self& operator++() {
      do {
        iterator_base::increment();
      } while (!AtEnd() &&
               !StringPieceUtils::EqualIgnoreCase(key_, (**this).first));
      return *this;
    }

    void operator++(int ignore) {
      ++(*this);
    }

    // Only forward-iteration makes sense, so no operator-- defined.

   private:
    const_header_lines_key_iterator(const BalsaHeaders* headers,
                                    HeaderLines::size_type index,
                                    const base::StringPiece& key);

    // Should only be used for creating an end iterator.
    const_header_lines_key_iterator(const BalsaHeaders* headers,
                                    HeaderLines::size_type index);

    bool AtEnd() const {
      return *this >= headers_->header_lines_end();
    }

    base::StringPiece key_;
  };

  // TODO(fenix): Revisit the amount of bytes initially allocated to the second
  // block of the balsa_buffer_. It may make sense to pre-allocate some amount
  // (roughly the amount we'd append in new headers such as X-User-Ip, etc.)
  BalsaHeaders();
  ~BalsaHeaders();

  const_header_lines_iterator header_lines_begin() {
    return HeaderLinesBeginHelper<const_header_lines_iterator>();
  }

  const_header_lines_iterator header_lines_begin() const {
    return HeaderLinesBeginHelper<const_header_lines_iterator>();
  }

  const_header_lines_iterator header_lines_end() {
    return HeaderLinesEndHelper<const_header_lines_iterator>();
  }

  const_header_lines_iterator header_lines_end() const {
    return HeaderLinesEndHelper<const_header_lines_iterator>();
  }

  const_reverse_header_lines_iterator header_lines_rbegin() {
    return const_reverse_header_lines_iterator(header_lines_end());
  }

  const_reverse_header_lines_iterator header_lines_rbegin() const {
    return const_reverse_header_lines_iterator(header_lines_end());
  }

  const_reverse_header_lines_iterator header_lines_rend() {
    return const_reverse_header_lines_iterator(header_lines_begin());
  }

  const_reverse_header_lines_iterator header_lines_rend() const {
    return const_reverse_header_lines_iterator(header_lines_begin());
  }

  const_header_lines_key_iterator header_lines_key_end() const {
    return HeaderLinesEndHelper<const_header_lines_key_iterator>();
  }

  void erase(const const_header_lines_iterator& it) {
    DCHECK_EQ(it.headers_, this);
    DCHECK_LT(it.idx_, header_lines_.size());
    DCHECK_GE(it.idx_, 0u);
    header_lines_[it.idx_].skip = true;
  }

  void Clear();

  void Swap(BalsaHeaders* other);

  void CopyFrom(const BalsaHeaders& other);

  void HackHeader(const base::StringPiece& key, const base::StringPiece& value);

  // Same as AppendToHeader, except that it will attempt to preserve
  // header ordering.
  // Note that this will always append to an existing header, if available,
  // without moving the header around, or collapsing multiple header lines
  // with the same key together. For this reason, it only 'attempts' to
  // preserve header ordering.
  // TODO(fenix): remove this function and rename all occurances
  // of it in the code to AppendToHeader when the condition above
  // has been satisified.
  void HackAppendToHeader(const base::StringPiece& key,
                          const base::StringPiece& value);

  // Replaces header entries with key 'key' if they exist, or appends
  // a new header if none exist.  See 'AppendHeader' below for additional
  // comments about ContentLength and TransferEncoding headers. Note that this
  // will allocate new storage every time that it is called.
  // TODO(fenix): modify this function to reuse existing storage
  // if it is available.
  void ReplaceOrAppendHeader(const base::StringPiece& key,
                             const base::StringPiece& value);

  // Append a new header entry to the header object. Clients who wish to append
  // Content-Length header should use SetContentLength() method instead of
  // adding the content length header using AppendHeader (manually adding the
  // content length header will not update the content_length_ and
  // content_length_status_ values).
  // Similarly, clients who wish to add or remove the transfer encoding header
  // in order to apply or remove chunked encoding should use SetChunkEncoding()
  // instead.
  void AppendHeader(const base::StringPiece& key,
                    const base::StringPiece& value);

  // Appends ',value' to an existing header named 'key'.  If no header with the
  // correct key exists, it will call AppendHeader(key, value).  Calling this
  // function on a key which exists several times in the headers will produce
  // unpredictable results.
  void AppendToHeader(const base::StringPiece& key,
                      const base::StringPiece& value);

  // Prepends 'value,' to an existing header named 'key'.  If no header with the
  // correct key exists, it will call AppendHeader(key, value).  Calling this
  // function on a key which exists several times in the headers will produce
  // unpredictable results.
  void PrependToHeader(const base::StringPiece& key,
                       const base::StringPiece& value);

  const base::StringPiece GetHeader(const base::StringPiece& key) const;

  // Iterates over all currently valid header lines, appending their
  // values into the vector 'out', in top-to-bottom order.
  // Header-lines which have been erased are not currently valid, and
  // will not have their values appended. Empty values will be
  // represented as empty string. If 'key' doesn't exist in the headers at
  // all, out will not be changed. We do not clear the vector out
  // before adding new entries. If there are header lines with matching
  // key but empty value then they are also added to the vector out.
  // (Basically empty values are not treated in any special manner).
  //
  // Example:
  // Input header:
  // "GET / HTTP/1.0\r\n"
  //    "key1: v1\r\n"
  //    "key1: \r\n"
  //    "key1:\r\n"
  //    "key1:  v1\r\n"
  //    "key1:v2\r\n"
  //
  //  vector out is initially: ["foo"]
  //  vector out after GetAllOfHeader("key1", &out) is:
  // ["foo", "v1", "", "", "v2", "v1", "v2"]

  void GetAllOfHeader(const base::StringPiece& key,
                      std::vector<base::StringPiece>* out) const;

  // Joins all values for key into a comma-separated string in out.
  // More efficient than calling JoinStrings on result of GetAllOfHeader if
  // you don't need the intermediate vector<StringPiece>.
  void GetAllOfHeaderAsString(const base::StringPiece& key,
                              std::string* out) const;

  // Returns true if RFC 2616 Section 14 indicates that header can
  // have multiple values.
  static bool IsMultivaluedHeader(const base::StringPiece& header);

  // Determine if a given header is present.
  inline bool HasHeader(const base::StringPiece& key) const {
    return (GetConstHeaderLinesIterator(key, header_lines_.begin()) !=
            header_lines_.end());
  }

  // Returns true iff any header 'key' exists with non-empty value.
  bool HasNonEmptyHeader(const base::StringPiece& key) const;

  const_header_lines_iterator GetHeaderPosition(
      const base::StringPiece& key) const;

  // Returns a forward-only iterator that only stops at lines matching key.
  // String backing 'key' must remain valid for lifetime of iterator.
  //
  // Check returned iterator against header_lines_key_end() to determine when
  // iteration is finished.
  const_header_lines_key_iterator GetIteratorForKey(
      const base::StringPiece& key) const;

  void RemoveAllOfHeader(const base::StringPiece& key);

  // Removes all headers starting with 'key' [case insensitive]
  void RemoveAllHeadersWithPrefix(const base::StringPiece& key);

  // Returns the lower bound of memory  used by this header object, including
  // all internal buffers and data structure. Some of the memory used cannot be
  // directly measure. For example, memory used for bookkeeping by standard
  // containers.
  size_t GetMemoryUsedLowerBound() const;

  // Returns the upper bound on the required buffer space to fully write out
  // the header object (this include the first line, all header lines, and the
  // final CRLF that marks the ending of the header).
  size_t GetSizeForWriteBuffer() const;

  // The following WriteHeader* methods are template member functions that
  // place one requirement on the Buffer class: it must implement a Write
  // method that takes a pointer and a length. The buffer passed in is not
  // required to be stretchable. For non-stretchable buffers, the user must
  // call GetSizeForWriteBuffer() to find out the upper bound on the output
  // buffer space required to make sure that the entire header is serialized.
  // BalsaHeaders will not check that there is adequate space in the buffer
  // object during the write.

  // Writes the entire header and the final CRLF that marks the end of the HTTP
  // header section to the buffer. After this method returns, no more header
  // data should be written to the buffer.
  template <typename Buffer>
  void WriteHeaderAndEndingToBuffer(Buffer* buffer) const {
    WriteToBuffer(buffer);
    WriteHeaderEndingToBuffer(buffer);
  }

  // Writes the final CRLF to the buffer to terminate the HTTP header section.
  // After this method returns, no more header data should be written to the
  // buffer.
  template <typename Buffer>
  static void WriteHeaderEndingToBuffer(Buffer* buffer) {
    buffer->Write("\r\n", 2);
  }

  // Writes the entire header to the buffer without the CRLF that terminates
  // the HTTP header. This lets users append additional header lines using
  // WriteHeaderLineToBuffer and then terminate the header with
  // WriteHeaderEndingToBuffer as the header is serialized to the
  // buffer, without having to first copy the header.
  template <typename Buffer>
  void WriteToBuffer(Buffer* buffer) const {
    // write the first line.
    const size_t firstline_len = whitespace_4_idx_ - non_whitespace_1_idx_;
    const char* stream_begin = GetPtr(firstline_buffer_base_idx_);
    buffer->Write(stream_begin + non_whitespace_1_idx_, firstline_len);
    buffer->Write("\r\n", 2);
    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) {
        continue;
      }
      const char* line_ptr = GetPtr(line.buffer_base_idx);
      WriteHeaderLineToBuffer(
          buffer,
          base::StringPiece(line_ptr + line.first_char_idx,
                      line.key_end_idx - line.first_char_idx),
          base::StringPiece(line_ptr + line.value_begin_idx,
                      line.last_char_idx - line.value_begin_idx));
    }
  }

  // Takes a header line in the form of a key/value pair and append it to the
  // buffer. This function should be called after WriteToBuffer to
  // append additional header lines to the header without copying the header.
  // When the user is done with appending to the buffer,
  // WriteHeaderEndingToBuffer must be used to terminate the HTTP
  // header in the buffer. This method is a no-op if key is empty.
  template <typename Buffer>
  static void WriteHeaderLineToBuffer(Buffer* buffer,
                                      const base::StringPiece& key,
                                      const base::StringPiece& value) {
    // if the key is empty, we don't want to write the rest because it
    // will not be a well-formed header line.
    if (!key.empty()) {
      buffer->Write(key.data(), key.size());
      buffer->Write(": ", 2);
      buffer->Write(value.data(), value.size());
      buffer->Write("\r\n", 2);
    }
  }

  // Dump the textural representation of the header object to a string, which
  // is suitable for writing out to logs. All CRLF will be printed out as \n.
  // This function can be called on a header object in any state. Raw header
  // data will be printed out if the header object is not completely parsed,
  // e.g., when there was an error in the middle of parsing.
  // The header content is appended to the string; the original content is not
  // cleared.
  void DumpToString(std::string* str) const;

  const base::StringPiece first_line() const {
    DCHECK_GE(whitespace_4_idx_, non_whitespace_1_idx_);
    return base::StringPiece(BeginningOfFirstLine() + non_whitespace_1_idx_,
                       whitespace_4_idx_ - non_whitespace_1_idx_);
  }

  // Returns the parsed value of the response code if it has been parsed.
  // Guaranteed to return 0 when unparsed (though it is a much better idea to
  // verify that the BalsaFrame had no errors while parsing).
  // This may return response codes which are outside the normal bounds of
  // HTTP response codes-- it is up to the user of this class to ensure that
  // the response code is one which is interpretable.
  size_t parsed_response_code() const { return parsed_response_code_; }

  const base::StringPiece request_method() const {
    DCHECK_GE(whitespace_2_idx_, non_whitespace_1_idx_);
    return base::StringPiece(BeginningOfFirstLine() + non_whitespace_1_idx_,
                       whitespace_2_idx_ - non_whitespace_1_idx_);
  }

  const base::StringPiece response_version() const {
    // Note: There is no difference between request_method() and
    // response_version(). They both could be called
    // GetFirstTokenFromFirstline()... but that wouldn't be anywhere near as
    // descriptive.
    return request_method();
  }

  const base::StringPiece request_uri() const {
    DCHECK_GE(whitespace_3_idx_, non_whitespace_2_idx_);
    return base::StringPiece(BeginningOfFirstLine() + non_whitespace_2_idx_,
                       whitespace_3_idx_ - non_whitespace_2_idx_);
  }

  const base::StringPiece response_code() const {
    // Note: There is no difference between request_uri() and response_code().
    // They both could be called GetSecondtTokenFromFirstline(), but, as noted
    // in an earlier comment, that wouldn't be as descriptive.
    return request_uri();
  }

  const base::StringPiece request_version() const {
    DCHECK_GE(whitespace_4_idx_, non_whitespace_3_idx_);
    return base::StringPiece(BeginningOfFirstLine() + non_whitespace_3_idx_,
                       whitespace_4_idx_ - non_whitespace_3_idx_);
  }

  const base::StringPiece response_reason_phrase() const {
    // Note: There is no difference between request_version() and
    // response_reason_phrase(). They both could be called
    // GetThirdTokenFromFirstline(), but, as noted in an earlier comment, that
    // wouldn't be as descriptive.
    return request_version();
  }

  // Note that SetFirstLine will not update the internal indices for the
  // various bits of the first-line (and may set them all to zero).
  // If you'd like to use the accessors for the various bits of the firstline,
  // then you should use the Set* functions, or SetFirstlineFromStringPieces,
  // below, instead.
  //
  void SetFirstlineFromStringPieces(const base::StringPiece& firstline_a,
                                    const base::StringPiece& firstline_b,
                                    const base::StringPiece& firstline_c);

  void SetRequestFirstlineFromStringPieces(const base::StringPiece& method,
                                           const base::StringPiece& uri,
                                           const base::StringPiece& version) {
    SetFirstlineFromStringPieces(method, uri, version);
  }

  void SetResponseFirstlineFromStringPieces(
      const base::StringPiece& version,
      const base::StringPiece& code,
      const base::StringPiece& reason_phrase) {
    SetFirstlineFromStringPieces(version, code, reason_phrase);
  }

  // These functions are exactly the same, except that their names are
  // different. This is done so that the code using this class is more
  // expressive.
  void SetRequestMethod(const base::StringPiece& method);
  void SetResponseVersion(const base::StringPiece& version);

  void SetRequestUri(const base::StringPiece& uri);
  void SetResponseCode(const base::StringPiece& code);
  void set_parsed_response_code(size_t parsed_response_code) {
    parsed_response_code_ = parsed_response_code;
  }
  void SetParsedResponseCodeAndUpdateFirstline(size_t parsed_response_code);

  // These functions are exactly the same, except that their names are
  // different. This is done so that the code using this class is more
  // expressive.
  void SetRequestVersion(const base::StringPiece& version);
  void SetResponseReasonPhrase(const base::StringPiece& reason_phrase);

  // The biggest problem with SetFirstLine is that we don't want to use a
  // separate buffer for it.  The second biggest problem with it is that the
  // first biggest problem requires that we store offsets into a buffer instead
  // of pointers into a buffer. Cuteness aside, SetFirstLine doesn't parse
  // the individual fields of the firstline, and so accessors to those fields
  // will not work properly after calling SetFirstLine. If you want those
  // accessors to work, use the Set* functions above this one.
  // SetFirstLine is stuff useful, however, if all you care about is correct
  // serialization with the rest of the header object.
  void SetFirstLine(const base::StringPiece& line);

  // Simple accessors to some of the internal state
  bool transfer_encoding_is_chunked() const {
    return transfer_encoding_is_chunked_;
  }

  static bool ResponseCodeImpliesNoBody(size_t code) {
    // From HTTP spec section 6.1.1 all 1xx responses must not have a body,
    // as well as 204 No Content and 304 Not Modified.
    return ((code >= 100) && (code <= 199)) || (code == 204) || (code == 304);
  }

  // Note: never check this for requests. Nothing bad will happen if you do,
  // but spec does not allow requests framed by connection close.
  // TODO(vitaliyl): refactor.
  bool is_framed_by_connection_close() const {
    // We declare that response is framed by connection close if it has no
    // content-length, no transfer encoding, and is allowed to have a body by
    // the HTTP spec.
    // parsed_response_code_ is 0 for requests, so ResponseCodeImpliesNoBody
    // will return false.
    return (content_length_status_ == BalsaHeadersEnums::NO_CONTENT_LENGTH) &&
        !transfer_encoding_is_chunked_ &&
        !ResponseCodeImpliesNoBody(parsed_response_code_);
  }

  size_t content_length() const { return content_length_; }
  BalsaHeadersEnums::ContentLengthStatus content_length_status() const {
    return content_length_status_;
  }

  // SetContentLength and SetChunkEncoding modifies the header object to use
  // content-length and transfer-encoding headers in a consistent manner. They
  // set all internal flags and status so client can get a consistent view from
  // various accessors.
  void SetContentLength(size_t length);
  void SetChunkEncoding(bool chunk_encode);

 protected:
  friend class BalsaFrame;
  friend class SpdyFrame;
  friend class HTTPMessage;
  friend class BalsaHeadersTokenUtils;

  const char* BeginningOfFirstLine() const {
    return GetPtr(firstline_buffer_base_idx_);
  }

  char* GetPtr(BalsaBuffer::Blocks::size_type block_idx) {
    return balsa_buffer_.GetPtr(block_idx);
  }

  const char* GetPtr(BalsaBuffer::Blocks::size_type block_idx) const {
    return balsa_buffer_.GetPtr(block_idx);
  }

  void WriteFromFramer(const char* ptr, size_t size) {
    balsa_buffer_.WriteToContiguousBuffer(base::StringPiece(ptr, size));
  }

  void DoneWritingFromFramer() {
    balsa_buffer_.NoMoreWriteToContiguousBuffer();
  }

  const char* OriginalHeaderStreamBegin() const {
    return balsa_buffer_.StartOfFirstBlock();
  }

  const char* OriginalHeaderStreamEnd() const {
    return balsa_buffer_.EndOfFirstBlock();
  }

  size_t GetReadableBytesFromHeaderStream() const {
    return OriginalHeaderStreamEnd() - OriginalHeaderStreamBegin();
  }

  void GetReadablePtrFromHeaderStream(const char** p, size_t* s) {
    *p = OriginalHeaderStreamBegin();
    *s = GetReadableBytesFromHeaderStream();
  }

  base::StringPiece GetValueFromHeaderLineDescription(
      const HeaderLineDescription& line) const;

  void AddAndMakeDescription(const base::StringPiece& key,
                             const base::StringPiece& value,
                             HeaderLineDescription* d);

  void AppendOrPrependAndMakeDescription(const base::StringPiece& key,
                                         const base::StringPiece& value,
                                         bool append,
                                         HeaderLineDescription* d);

  // Removes all header lines with the given key starting at start.
  void RemoveAllOfHeaderStartingAt(const base::StringPiece& key,
                                   HeaderLines::iterator start);

  // If the 'key' does not exist in the headers, calls
  // AppendHeader(key, value).  Otherwise if append is true, appends ',value'
  // to the first existing header with key 'key'.  If append is false, prepends
  // 'value,' to the first existing header with key 'key'.
  void AppendOrPrependToHeader(const base::StringPiece& key,
                               const base::StringPiece& value,
                               bool append);

  HeaderLines::const_iterator GetConstHeaderLinesIterator(
      const base::StringPiece& key,
      HeaderLines::const_iterator start) const;

  HeaderLines::iterator GetHeaderLinesIteratorNoSkip(
      const base::StringPiece& key,
      HeaderLines::iterator start);

  HeaderLines::iterator GetHeaderLinesIterator(
      const base::StringPiece& key,
      HeaderLines::iterator start);

  template <typename IteratorType>
  const IteratorType HeaderLinesBeginHelper() const {
    if (header_lines_.empty()) {
      return IteratorType(this, 0);
    }
    const HeaderLines::size_type header_lines_size = header_lines_.size();
    for (HeaderLines::size_type i = 0; i < header_lines_size; ++i) {
      if (header_lines_[i].skip == false) {
        return IteratorType(this, i);
      }
    }
    return IteratorType(this, 0);
  }

  template <typename IteratorType>
  const IteratorType HeaderLinesEndHelper() const {
    if (header_lines_.empty()) {
      return IteratorType(this, 0);
    }
    const HeaderLines::size_type header_lines_size = header_lines_.size();
    HeaderLines::size_type i = header_lines_size;
    do {
      --i;
      if (header_lines_[i].skip == false) {
        return IteratorType(this, i + 1);
      }
    } while (i != 0);
    return IteratorType(this, 0);
  }

  // At the moment, this function will always return the original headers.
  // In the future, it may not do so after erasing header lines, modifying
  // header lines, or modifying the first line.
  // For this reason, it is strongly suggested that use of this function is
  // only acceptable for the purpose of debugging parse errors seen by the
  // BalsaFrame class.
  base::StringPiece OriginalHeadersForDebugging() const {
    return base::StringPiece(OriginalHeaderStreamBegin(),
                       OriginalHeaderStreamEnd() - OriginalHeaderStreamBegin());
  }

  BalsaBuffer balsa_buffer_;

  size_t content_length_;
  BalsaHeadersEnums::ContentLengthStatus content_length_status_;
  size_t parsed_response_code_;
  // HTTP firstlines all have the following structure:
  //  LWS         NONWS  LWS    NONWS   LWS    NONWS   NOTCRLF  CRLF
  //  [\t \r\n]+ [^\t ]+ [\t ]+ [^\t ]+ [\t ]+ [^\t ]+ [^\r\n]+ "\r\n"
  //  ws1        nws1    ws2    nws2    ws3    nws3             ws4
  //  |          [-------)      [-------)      [----------------)
  //    REQ:     method         request_uri    version
  //   RESP:     version        statuscode     reason
  //
  //   The first NONWS->LWS component we'll call firstline_a.
  //   The second firstline_b, and the third firstline_c.
  //
  //   firstline_a goes from nws1 to (but not including) ws2
  //   firstline_b goes from nws2 to (but not including) ws3
  //   firstline_c goes from nws3 to (but not including) ws4
  //
  // In the code:
  //    ws1 == whitespace_1_idx_
  //   nws1 == non_whitespace_1_idx_
  //    ws2 == whitespace_2_idx_
  //   nws2 == non_whitespace_2_idx_
  //    ws3 == whitespace_3_idx_
  //   nws3 == non_whitespace_3_idx_
  //    ws4 == whitespace_4_idx_
  BalsaBuffer::Blocks::size_type firstline_buffer_base_idx_;
  size_t whitespace_1_idx_;
  size_t non_whitespace_1_idx_;
  size_t whitespace_2_idx_;
  size_t non_whitespace_2_idx_;
  size_t whitespace_3_idx_;
  size_t non_whitespace_3_idx_;
  size_t whitespace_4_idx_;
  size_t end_of_firstline_idx_;

  bool transfer_encoding_is_chunked_;

  HeaderLines header_lines_;
};

}  // namespace net

#endif  // NET_TOOLS_BALSA_BALSA_HEADERS_H_
