15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/tools/flip_server/balsa_headers.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <ext/hash_set>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <utility>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/port.h"
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/string_piece.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/tools/flip_server/balsa_enums.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/tools/flip_server/buffer_interface.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/tools/flip_server/simple_buffer.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/tcmalloc/chromium/src/base/googleinit.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// #include "util/gtl/iterator_adaptors-inl.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// #include "util/gtl/map-util.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kContentLength[] = "Content-Length";
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kTransferEncoding[] = "Transfer-Encoding";
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kSpaceChar = ' ';
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)__gnu_cxx::hash_set<base::StringPiece,
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    net::StringPieceCaseHash,
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    net::StringPieceCaseEqual> g_multivalued_headers;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InitMultivaluedHeaders() {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_multivalued_headers.insert("accept");
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_multivalued_headers.insert("accept-charset");
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_multivalued_headers.insert("accept-encoding");
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_multivalued_headers.insert("accept-language");
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_multivalued_headers.insert("accept-ranges");
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_multivalued_headers.insert("allow");
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_multivalued_headers.insert("cache-control");
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_multivalued_headers.insert("connection");
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_multivalued_headers.insert("content-encoding");
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_multivalued_headers.insert("content-language");
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_multivalued_headers.insert("expect");
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_multivalued_headers.insert("if-match");
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_multivalued_headers.insert("if-none-match");
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_multivalued_headers.insert("pragma");
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_multivalued_headers.insert("proxy-authenticate");
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_multivalued_headers.insert("te");
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_multivalued_headers.insert("trailer");
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_multivalued_headers.insert("transfer-encoding");
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_multivalued_headers.insert("upgrade");
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_multivalued_headers.insert("vary");
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_multivalued_headers.insert("via");
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_multivalued_headers.insert("warning");
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_multivalued_headers.insert("www-authenticate");
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Not mentioned in RFC 2616, but it can have multiple values.
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_multivalued_headers.insert("set-cookie");
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_MODULE_INITIALIZER(multivalued_headers, InitMultivaluedHeaders());
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kFastToBufferSize = 32;  // I think 22 is adequate, but anyway..
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t BalsaBuffer::kDefaultBlocksize;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BalsaHeaders::iterator_base::iterator_base() : headers_(NULL), idx_(0) { }
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BalsaHeaders::iterator_base::iterator_base(const iterator_base& it)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : headers_(it.headers_),
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      idx_(it.idx_) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::ostream& BalsaHeaders::iterator_base::operator<<(std::ostream& os) const {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  os << "[" << this->headers_ << ", " << this->idx_ << "]";
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return os;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BalsaHeaders::iterator_base::iterator_base(const BalsaHeaders* headers,
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           HeaderLines::size_type index)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : headers_(headers),
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      idx_(index) {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BalsaBuffer::~BalsaBuffer() {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CleanupBlocksStartingFrom(0);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the total amount of memory used by the buffer blocks.
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t BalsaBuffer::GetTotalBufferBlockSize() const {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t buffer_size = 0;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (Blocks::const_iterator iter = blocks_.begin();
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != blocks_.end();
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++iter) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffer_size += iter->buffer_size;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return buffer_size;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaBuffer::WriteToContiguousBuffer(const base::StringPiece& sp) {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (sp.empty()) {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(can_write_to_contiguous_buffer_);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(blocks_.size(), 1u);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (blocks_[0].buffer == NULL && sp.size() <= blocksize_) {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    blocks_[0] = AllocBlock();
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(blocks_[0].start_of_unused_bytes(), sp.data(), sp.size());
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (blocks_[0].bytes_free < sp.size()) {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the first block isn't big enough, resize it.
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const size_t old_storage_size_used = blocks_[0].bytes_used();
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const size_t new_storage_size = old_storage_size_used + sp.size();
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char* new_storage = new char[new_storage_size];
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char* old_storage = blocks_[0].buffer;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (old_storage_size_used) {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memcpy(new_storage, old_storage, old_storage_size_used);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(new_storage + old_storage_size_used, sp.data(), sp.size());
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    blocks_[0].buffer = new_storage;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    blocks_[0].bytes_free = sp.size();
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    blocks_[0].buffer_size = new_storage_size;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete[] old_storage;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(blocks_[0].start_of_unused_bytes(), sp.data(), sp.size());
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocks_[0].bytes_free -= sp.size();
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::StringPiece BalsaBuffer::Write(const base::StringPiece& sp,
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     Blocks::size_type* block_buffer_idx) {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (sp.empty()) {
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return sp;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* storage = Reserve(sp.size(), block_buffer_idx);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(storage, sp.data(), sp.size());
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return base::StringPiece(storage, sp.size());
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)char* BalsaBuffer::Reserve(size_t size,
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           Blocks::size_type* block_buffer_idx) {
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // There should always be a 'first_block', even if it
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // contains nothing.
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(blocks_.size(), 1u);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BufferBlock* block = NULL;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Blocks::size_type block_idx = can_write_to_contiguous_buffer_ ? 1 : 0;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (; block_idx < blocks_.size(); ++block_idx) {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (blocks_[block_idx].bytes_free >= size) {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      block = &blocks_[block_idx];
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (block == NULL) {
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (blocksize_ < size) {
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      blocks_.push_back(AllocCustomBlock(size));
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      blocks_.push_back(AllocBlock());
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    block = &blocks_.back();
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* storage = block->start_of_unused_bytes();
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  block->bytes_free -= size;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (block_buffer_idx) {
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *block_buffer_idx = block_idx;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return storage;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaBuffer::Clear() {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(!blocks_.empty());
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (blocksize_ == blocks_[0].buffer_size) {
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CleanupBlocksStartingFrom(1);
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    blocks_[0].bytes_free = blocks_[0].buffer_size;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CleanupBlocksStartingFrom(0);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    blocks_.push_back(AllocBlock());
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(blocks_.size(), 1u);
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  can_write_to_contiguous_buffer_ = true;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaBuffer::Swap(BalsaBuffer* b) {
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocks_.swap(b->blocks_);
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::swap(can_write_to_contiguous_buffer_,
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            b->can_write_to_contiguous_buffer_);
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::swap(blocksize_, b->blocksize_);
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaBuffer::CopyFrom(const BalsaBuffer& b) {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CleanupBlocksStartingFrom(0);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocks_.resize(b.blocks_.size());
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (Blocks::size_type i = 0; i < blocks_.size(); ++i) {
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    blocks_[i] = CopyBlock(b.blocks_[i]);
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocksize_ = b.blocksize_;
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  can_write_to_contiguous_buffer_ = b.can_write_to_contiguous_buffer_;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BalsaBuffer::BalsaBuffer()
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : blocksize_(kDefaultBlocksize), can_write_to_contiguous_buffer_(true) {
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocks_.push_back(AllocBlock());
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BalsaBuffer::BalsaBuffer(size_t blocksize) :
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    blocksize_(blocksize), can_write_to_contiguous_buffer_(true) {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocks_.push_back(AllocBlock());
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BalsaBuffer::BufferBlock BalsaBuffer::AllocBlock() {
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return AllocCustomBlock(blocksize_);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BalsaBuffer::BufferBlock BalsaBuffer::AllocCustomBlock(size_t blocksize) {
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return BufferBlock(new char[blocksize], blocksize, blocksize);
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BalsaBuffer::BufferBlock BalsaBuffer::CopyBlock(const BufferBlock& b) {
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BufferBlock block = b;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (b.buffer == NULL) {
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return block;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  block.buffer = new char[b.buffer_size];
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(block.buffer, b.buffer, b.bytes_used());
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return block;
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaBuffer::CleanupBlocksStartingFrom(Blocks::size_type start_idx) {
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (Blocks::size_type i = start_idx; i < blocks_.size(); ++i) {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete[] blocks_[i].buffer;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocks_.resize(start_idx);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BalsaHeaders::const_header_lines_key_iterator::const_header_lines_key_iterator(
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const const_header_lines_key_iterator& other)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : iterator_base(other),
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      key_(other.key_) {
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BalsaHeaders::const_header_lines_key_iterator::const_header_lines_key_iterator(
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const BalsaHeaders* headers,
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HeaderLines::size_type index,
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::StringPiece& key)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : iterator_base(headers, index),
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      key_(key) {
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BalsaHeaders::const_header_lines_key_iterator::const_header_lines_key_iterator(
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const BalsaHeaders* headers,
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HeaderLines::size_type index)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : iterator_base(headers, index) {
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BalsaHeaders::BalsaHeaders()
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : balsa_buffer_(4096),
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content_length_(0),
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content_length_status_(BalsaHeadersEnums::NO_CONTENT_LENGTH),
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      parsed_response_code_(0),
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      firstline_buffer_base_idx_(0),
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      whitespace_1_idx_(0),
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      non_whitespace_1_idx_(0),
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      whitespace_2_idx_(0),
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      non_whitespace_2_idx_(0),
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      whitespace_3_idx_(0),
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      non_whitespace_3_idx_(0),
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      whitespace_4_idx_(0),
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      end_of_firstline_idx_(0),
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      transfer_encoding_is_chunked_(false) {
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BalsaHeaders::~BalsaHeaders() {}
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaHeaders::Clear() {
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  balsa_buffer_.Clear();
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transfer_encoding_is_chunked_ = false;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content_length_ = 0;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content_length_status_ = BalsaHeadersEnums::NO_CONTENT_LENGTH;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parsed_response_code_ = 0;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  firstline_buffer_base_idx_ = 0;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  whitespace_1_idx_ = 0;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  non_whitespace_1_idx_ = 0;
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  whitespace_2_idx_ = 0;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  non_whitespace_2_idx_ = 0;
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  whitespace_3_idx_ = 0;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  non_whitespace_3_idx_ = 0;
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  whitespace_4_idx_ = 0;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  end_of_firstline_idx_ = 0;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  header_lines_.clear();
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaHeaders::Swap(BalsaHeaders* other) {
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Protect against swapping with self.
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (this == other) return;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  balsa_buffer_.Swap(&other->balsa_buffer_);
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool tmp_bool = transfer_encoding_is_chunked_;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transfer_encoding_is_chunked_ = other->transfer_encoding_is_chunked_;
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  other->transfer_encoding_is_chunked_ = tmp_bool;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t tmp_size_t = content_length_;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content_length_ = other->content_length_;
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  other->content_length_ = tmp_size_t;
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BalsaHeadersEnums::ContentLengthStatus tmp_status =
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content_length_status_;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content_length_status_ = other->content_length_status_;
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  other->content_length_status_ = tmp_status;
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tmp_size_t = parsed_response_code_;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parsed_response_code_ = other->parsed_response_code_;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  other->parsed_response_code_ = tmp_size_t;
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BalsaBuffer::Blocks::size_type tmp_blk_idx = firstline_buffer_base_idx_;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  firstline_buffer_base_idx_ = other->firstline_buffer_base_idx_;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  other->firstline_buffer_base_idx_ = tmp_blk_idx;
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tmp_size_t = whitespace_1_idx_;
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  whitespace_1_idx_ = other->whitespace_1_idx_;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  other->whitespace_1_idx_ = tmp_size_t;
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tmp_size_t = non_whitespace_1_idx_;
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  non_whitespace_1_idx_ = other->non_whitespace_1_idx_;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  other->non_whitespace_1_idx_ = tmp_size_t;
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tmp_size_t = whitespace_2_idx_;
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  whitespace_2_idx_ = other->whitespace_2_idx_;
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  other->whitespace_2_idx_ = tmp_size_t;
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tmp_size_t = non_whitespace_2_idx_;
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  non_whitespace_2_idx_ = other->non_whitespace_2_idx_;
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  other->non_whitespace_2_idx_ = tmp_size_t;
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tmp_size_t = whitespace_3_idx_;
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  whitespace_3_idx_ = other->whitespace_3_idx_;
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  other->whitespace_3_idx_ = tmp_size_t;
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tmp_size_t = non_whitespace_3_idx_;
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  non_whitespace_3_idx_ = other->non_whitespace_3_idx_;
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  other->non_whitespace_3_idx_ = tmp_size_t;
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tmp_size_t = whitespace_4_idx_;
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  whitespace_4_idx_ = other->whitespace_4_idx_;
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  other->whitespace_4_idx_ = tmp_size_t;
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tmp_size_t = end_of_firstline_idx_;
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  end_of_firstline_idx_ = other->end_of_firstline_idx_;
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  other->end_of_firstline_idx_ = tmp_size_t;
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  swap(header_lines_, other->header_lines_);
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaHeaders::CopyFrom(const BalsaHeaders& other) {
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Protect against copying with self.
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (this == &other) return;
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  balsa_buffer_.CopyFrom(other.balsa_buffer_);
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transfer_encoding_is_chunked_ = other.transfer_encoding_is_chunked_;
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content_length_ = other.content_length_;
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content_length_status_ = other.content_length_status_;
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parsed_response_code_ = other.parsed_response_code_;
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  firstline_buffer_base_idx_ = other.firstline_buffer_base_idx_;
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  whitespace_1_idx_ = other.whitespace_1_idx_;
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  non_whitespace_1_idx_ = other.non_whitespace_1_idx_;
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  whitespace_2_idx_ = other.whitespace_2_idx_;
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  non_whitespace_2_idx_ = other.non_whitespace_2_idx_;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  whitespace_3_idx_ = other.whitespace_3_idx_;
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  non_whitespace_3_idx_ = other.non_whitespace_3_idx_;
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  whitespace_4_idx_ = other.whitespace_4_idx_;
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  end_of_firstline_idx_ = other.end_of_firstline_idx_;
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  header_lines_ = other.header_lines_;
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaHeaders::AddAndMakeDescription(const base::StringPiece& key,
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const base::StringPiece& value,
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         HeaderLineDescription* d) {
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(d != NULL);
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // + 2 to size for ": "
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t line_size = key.size() + 2 + value.size();
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BalsaBuffer::Blocks::size_type block_buffer_idx = 0;
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* storage = balsa_buffer_.Reserve(line_size, &block_buffer_idx);
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t base_idx = storage - GetPtr(block_buffer_idx);
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* cur_loc = storage;
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(cur_loc, key.data(), key.size());
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cur_loc += key.size();
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *cur_loc = ':';
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ++cur_loc;
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *cur_loc = ' ';
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ++cur_loc;
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(cur_loc, value.data(), value.size());
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *d = HeaderLineDescription(base_idx,
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             base_idx + key.size(),
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             base_idx + key.size() + 2,
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             base_idx + key.size() + 2 + value.size(),
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             block_buffer_idx);
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaHeaders::AppendOrPrependAndMakeDescription(
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::StringPiece& key,
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::StringPiece& value,
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool append,
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HeaderLineDescription* d) {
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Figure out how much space we need to reserve for the new header size.
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t old_value_size = d->last_char_idx - d->value_begin_idx;
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (old_value_size == 0) {
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddAndMakeDescription(key, value, d);
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StringPiece old_value(GetPtr(d->buffer_base_idx) + d->value_begin_idx,
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        old_value_size);
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BalsaBuffer::Blocks::size_type block_buffer_idx = 0;
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // + 3 because we potentially need to add ": ", and "," to the line.
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t new_size = key.size() + 3 + old_value_size + value.size();
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* storage = balsa_buffer_.Reserve(new_size, &block_buffer_idx);
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t base_idx = storage - GetPtr(block_buffer_idx);
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StringPiece first_value = old_value;
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StringPiece second_value = value;
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!append) {  // !append == prepend
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    first_value = value;
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    second_value = old_value;
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* cur_loc = storage;
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(cur_loc, key.data(), key.size());
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cur_loc += key.size();
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *cur_loc = ':';
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ++cur_loc;
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *cur_loc = ' ';
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ++cur_loc;
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(cur_loc, first_value.data(), first_value.size());
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cur_loc += first_value.size();
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *cur_loc = ',';
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ++cur_loc;
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(cur_loc, second_value.data(), second_value.size());
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *d = HeaderLineDescription(base_idx,
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             base_idx + key.size(),
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             base_idx + key.size() + 2,
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             base_idx + new_size,
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             block_buffer_idx);
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Removes all keys value pairs with key 'key' starting at 'start'.
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaHeaders::RemoveAllOfHeaderStartingAt(const base::StringPiece& key,
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               HeaderLines::iterator start) {
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (start != header_lines_.end()) {
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    start->skip = true;
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++start;
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    start = GetHeaderLinesIterator(key, start);
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaHeaders::HackHeader(const base::StringPiece& key,
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const base::StringPiece& value) {
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // See TODO in balsa_headers.h
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HeaderLines::iterator end = header_lines_.end();
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HeaderLines::iterator begin = header_lines_.begin();
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HeaderLines::iterator i = GetHeaderLinesIteratorNoSkip(key, begin);
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (i != end) {
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // First, remove all of the header lines including this one.  We want to
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // remove before replacing, in case our replacement ends up being appended
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // at the end (and thus would be removed by this call)
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RemoveAllOfHeaderStartingAt(key, i);
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Now add the replacement, at this location.
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddAndMakeDescription(key, value, &(*i));
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendHeader(key, value);
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaHeaders::HackAppendToHeader(const base::StringPiece& key,
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      const base::StringPiece& append_value) {
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // See TODO in balsa_headers.h
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HeaderLines::iterator end = header_lines_.end();
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HeaderLines::iterator begin = header_lines_.begin();
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HeaderLines::iterator i = GetHeaderLinesIterator(key, begin);
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (i == end) {
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HackHeader(key, append_value);
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendOrPrependAndMakeDescription(key, append_value, true, &(*i));
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaHeaders::ReplaceOrAppendHeader(const base::StringPiece& key,
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const base::StringPiece& value) {
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HeaderLines::iterator end = header_lines_.end();
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HeaderLines::iterator begin = header_lines_.begin();
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HeaderLines::iterator i = GetHeaderLinesIterator(key, begin);
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (i != end) {
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // First, remove all of the header lines including this one.  We want to
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // remove before replacing, in case our replacement ends up being appended
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // at the end (and thus would be removed by this call)
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RemoveAllOfHeaderStartingAt(key, i);
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Now, take the first instance and replace it.  This will remove the
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // 'skipped' tag if the replacement is done in-place.
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddAndMakeDescription(key, value, &(*i));
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendHeader(key, value);
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaHeaders::AppendHeader(const base::StringPiece& key,
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const base::StringPiece& value) {
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HeaderLineDescription hld;
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAndMakeDescription(key, value, &hld);
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  header_lines_.push_back(hld);
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaHeaders::AppendToHeader(const base::StringPiece& key,
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  const base::StringPiece& value) {
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendOrPrependToHeader(key, value, true);
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaHeaders::PrependToHeader(const base::StringPiece& key,
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   const base::StringPiece& value) {
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendOrPrependToHeader(key, value, false);
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::StringPiece BalsaHeaders::GetValueFromHeaderLineDescription(
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HeaderLineDescription& line) const {
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(line.last_char_idx, line.value_begin_idx);
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return base::StringPiece(GetPtr(line.buffer_base_idx) + line.value_begin_idx,
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     line.last_char_idx - line.value_begin_idx);
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const base::StringPiece BalsaHeaders::GetHeader(
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::StringPiece& key) const {
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!IsMultivaluedHeader(key))
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << "Header '" << key << "' may consist of multiple lines. Do not "
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << "use BalsaHeaders::GetHeader() or you may be missing some of its "
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << "values.";
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HeaderLines::const_iterator end = header_lines_.end();
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HeaderLines::const_iterator begin = header_lines_.begin();
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HeaderLines::const_iterator i = GetConstHeaderLinesIterator(key, begin);
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (i == end) {
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return base::StringPiece(NULL, 0);
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetValueFromHeaderLineDescription(*i);
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BalsaHeaders::const_header_lines_iterator BalsaHeaders::GetHeaderPosition(
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::StringPiece& key) const {
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HeaderLines::const_iterator end = header_lines_.end();
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HeaderLines::const_iterator begin = header_lines_.begin();
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HeaderLines::const_iterator i = GetConstHeaderLinesIterator(key, begin);
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (i == end) {
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return header_lines_end();
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return const_header_lines_iterator(this, (i - begin));
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BalsaHeaders::const_header_lines_key_iterator BalsaHeaders::GetIteratorForKey(
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::StringPiece& key) const {
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HeaderLines::const_iterator i =
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetConstHeaderLinesIterator(key, header_lines_.begin());
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (i == header_lines_.end()) {
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return header_lines_key_end();
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HeaderLines::const_iterator begin = header_lines_.begin();
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return const_header_lines_key_iterator(this, (i - begin), key);
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaHeaders::AppendOrPrependToHeader(const base::StringPiece& key,
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           const base::StringPiece& value,
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           bool append) {
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HeaderLines::iterator i = GetHeaderLinesIterator(key, header_lines_.begin());
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (i == header_lines_.end()) {
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The header did not exist already.  Instead of appending to an existing
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // header simply append the key/value pair to the headers.
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AppendHeader(key, value);
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HeaderLineDescription hld = *i;
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendOrPrependAndMakeDescription(key, value, append, &hld);
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Invalidate the old header line and add the new one.
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  i->skip = true;
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  header_lines_.push_back(hld);
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BalsaHeaders::HeaderLines::const_iterator
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BalsaHeaders::GetConstHeaderLinesIterator(
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::StringPiece& key,
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BalsaHeaders::HeaderLines::const_iterator start) const {
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HeaderLines::const_iterator end = header_lines_.end();
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (HeaderLines::const_iterator i = start; i != end; ++i) {
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HeaderLineDescription& line = *i;
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (line.skip) {
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const size_t key_len = line.key_end_idx - line.first_char_idx;
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (key_len != key.size()) {
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (strncasecmp(GetPtr(line.buffer_base_idx) + line.first_char_idx,
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    key.data(), key_len) == 0) {
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK_GE(line.last_char_idx, line.value_begin_idx);
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return i;
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return end;
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BalsaHeaders::HeaderLines::iterator BalsaHeaders::GetHeaderLinesIteratorNoSkip(
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::StringPiece& key,
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BalsaHeaders::HeaderLines::iterator start) {
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HeaderLines::iterator end = header_lines_.end();
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (HeaderLines::iterator i = start; i != end; ++i) {
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HeaderLineDescription& line = *i;
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const size_t key_len = line.key_end_idx - line.first_char_idx;
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (key_len != key.size()) {
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (strncasecmp(GetPtr(line.buffer_base_idx) + line.first_char_idx,
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    key.data(), key_len) == 0) {
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK_GE(line.last_char_idx, line.value_begin_idx);
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return i;
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return end;
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BalsaHeaders::HeaderLines::iterator BalsaHeaders::GetHeaderLinesIterator(
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::StringPiece& key,
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BalsaHeaders::HeaderLines::iterator start) {
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HeaderLines::iterator end = header_lines_.end();
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (HeaderLines::iterator i = start; i != end; ++i) {
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HeaderLineDescription& line = *i;
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (line.skip) {
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const size_t key_len = line.key_end_idx - line.first_char_idx;
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (key_len != key.size()) {
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (strncasecmp(GetPtr(line.buffer_base_idx) + line.first_char_idx,
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    key.data(), key_len) == 0) {
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK_GE(line.last_char_idx, line.value_begin_idx);
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return i;
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return end;
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaHeaders::GetAllOfHeader(
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::StringPiece& key, std::vector<base::StringPiece>* out) const {
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (const_header_lines_key_iterator it = GetIteratorForKey(key);
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != header_lines_end(); ++it) {
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out->push_back(it->second);
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BalsaHeaders::HasNonEmptyHeader(const base::StringPiece& key) const {
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (const_header_lines_key_iterator it = GetIteratorForKey(key);
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != header_lines_key_end(); ++it) {
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!it->second.empty())
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaHeaders::GetAllOfHeaderAsString(const base::StringPiece& key,
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          std::string* out) const {
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const_header_lines_iterator it = header_lines_begin();
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const_header_lines_iterator end = header_lines_end();
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (; it != end; ++it) {
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (key == it->first) {
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!out->empty()) {
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        out->append(",");
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      out->append(std::string(it->second.data(), it->second.size()));
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BalsaHeaders::IsMultivaluedHeader(const base::StringPiece& header) {
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return g_multivalued_headers.find(header) != g_multivalued_headers.end();
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaHeaders::RemoveAllOfHeader(const base::StringPiece& key) {
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HeaderLines::iterator it = GetHeaderLinesIterator(key, header_lines_.begin());
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RemoveAllOfHeaderStartingAt(key, it);
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaHeaders::RemoveAllHeadersWithPrefix(const base::StringPiece& key) {
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (HeaderLines::size_type i = 0; i < header_lines_.size(); ++i) {
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (header_lines_[i].skip) {
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HeaderLineDescription& line = header_lines_[i];
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const size_t key_len = line.key_end_idx - line.first_char_idx;
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (key_len < key.size()) {
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If the key given to us is longer than this header, don't consider it.
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!strncasecmp(GetPtr(line.buffer_base_idx) + line.first_char_idx,
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     key.data(), key.size())) {
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      line.skip = true;
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t BalsaHeaders::GetMemoryUsedLowerBound() const {
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (sizeof(*this) +
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          balsa_buffer_.GetTotalBufferBlockSize() +
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          header_lines_.capacity() * sizeof(HeaderLineDescription));
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t BalsaHeaders::GetSizeForWriteBuffer() const {
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First add the space required for the first line + CRLF
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t write_buf_size = whitespace_4_idx_ - non_whitespace_1_idx_ + 2;
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Then add the space needed for each header line to write out + CRLF.
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HeaderLines::size_type end = header_lines_.size();
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (HeaderLines::size_type i = 0; i < end; ++i) {
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HeaderLineDescription& line = header_lines_[i];
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!line.skip) {
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Add the key size and ": ".
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      write_buf_size += line.key_end_idx - line.first_char_idx + 2;
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Add the value size and the CRLF
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      write_buf_size += line.last_char_idx - line.value_begin_idx + 2;
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Finally tag on the terminal CRLF.
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return write_buf_size + 2;
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaHeaders::DumpToString(std::string* str) const {
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::StringPiece firstline = first_line();
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int buffer_length =
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OriginalHeaderStreamEnd() - OriginalHeaderStreamBegin();
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First check whether the header object is empty.
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (firstline.empty() && buffer_length == 0) {
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    str->append("\n<empty header>\n");
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Then check whether the header is in a partially parsed state. If so, just
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // dump the raw data.
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (balsa_buffer_.can_write_to_contiguous_buffer()) {
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::StringAppendF(str, "\n<incomplete header len: %d>\n%.*s\n",
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        buffer_length, buffer_length,
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        OriginalHeaderStreamBegin());
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the header is complete, then just dump them with the logical key value
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // pair.
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  str->reserve(str->size() + GetSizeForWriteBuffer());
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StringAppendF(str, "\n %.*s\n",
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      static_cast<int>(firstline.size()),
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      firstline.data());
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BalsaHeaders::const_header_lines_iterator i = header_lines_begin();
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (; i != header_lines_end(); ++i) {
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::StringAppendF(str, " %.*s: %.*s\n",
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        static_cast<int>(i->first.size()), i->first.data(),
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        static_cast<int>(i->second.size()), i->second.data());
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaHeaders::SetFirstLine(const base::StringPiece& line) {
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StringPiece new_line = balsa_buffer_.Write(line,
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   &firstline_buffer_base_idx_);
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  whitespace_1_idx_ = new_line.data() - GetPtr(firstline_buffer_base_idx_);
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  non_whitespace_1_idx_ = whitespace_1_idx_;
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  whitespace_4_idx_ = whitespace_1_idx_ + line.size();
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  whitespace_2_idx_ = whitespace_4_idx_;
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  non_whitespace_2_idx_ = whitespace_4_idx_;
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  whitespace_3_idx_ = whitespace_4_idx_;
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  non_whitespace_3_idx_ = whitespace_4_idx_;
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  end_of_firstline_idx_ = whitespace_4_idx_;
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaHeaders::SetContentLength(size_t length) {
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the content-length is already the one we want, don't do anything.
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (content_length_status_ == BalsaHeadersEnums::VALID_CONTENT_LENGTH &&
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content_length_ == length) {
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::StringPiece content_length(kContentLength,
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         sizeof(kContentLength) - 1);
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If header state indicates that there is either a content length or
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // transfer encoding header, remove them before adding the new content
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // length. There is always the possibility that client can manually add
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // either header directly and cause content_length_status_ or
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // transfer_encoding_is_chunked_ to be inconsistent with the actual header.
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In the interest of efficiency, however, we will assume that clients will
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // use the header object correctly and thus we will not scan the all headers
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // each time this function is called.
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (content_length_status_ != BalsaHeadersEnums::NO_CONTENT_LENGTH) {
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RemoveAllOfHeader(content_length);
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (transfer_encoding_is_chunked_) {
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::StringPiece transfer_encoding(kTransferEncoding,
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        sizeof(kTransferEncoding) - 1);
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RemoveAllOfHeader(transfer_encoding);
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    transfer_encoding_is_chunked_ = false;
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content_length_status_ = BalsaHeadersEnums::VALID_CONTENT_LENGTH;
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content_length_ = length;
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // FastUInt64ToBuffer is supposed to use a maximum of kFastToBufferSize bytes.
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char buffer[kFastToBufferSize];
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int len_converted = snprintf(buffer, sizeof(buffer), "%zd", length);
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_GT(len_converted, 0);
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::StringPiece length_str(buffer, len_converted);
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendHeader(content_length, length_str);
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaHeaders::SetChunkEncoding(bool chunk_encode) {
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transfer_encoding_is_chunked_ == chunk_encode) {
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (content_length_status_ != BalsaHeadersEnums::NO_CONTENT_LENGTH &&
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      chunk_encode) {
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Want to change to chunk encoding, but have content length. Arguably we
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // can leave this step out, since transfer-encoding overrides
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // content-length.
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::StringPiece content_length(kContentLength,
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     sizeof(kContentLength) - 1);
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RemoveAllOfHeader(content_length);
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content_length_status_ = BalsaHeadersEnums::NO_CONTENT_LENGTH;
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content_length_ = 0;
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::StringPiece transfer_encoding(kTransferEncoding,
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      sizeof(kTransferEncoding) - 1);
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (chunk_encode) {
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char kChunked[] = "chunked";
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::StringPiece chunked(kChunked, sizeof(kChunked) - 1);
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AppendHeader(transfer_encoding, chunked);
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RemoveAllOfHeader(transfer_encoding);
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transfer_encoding_is_chunked_ = chunk_encode;
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// See the comment about this function in the header file for a
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// warning about its usage.
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaHeaders::SetFirstlineFromStringPieces(
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::StringPiece& firstline_a,
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::StringPiece& firstline_b,
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::StringPiece& firstline_c) {
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t line_size = (firstline_a.size() +
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      firstline_b.size() +
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      firstline_c.size() +
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      2);
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* storage = balsa_buffer_.Reserve(line_size, &firstline_buffer_base_idx_);
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* cur_loc = storage;
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(cur_loc, firstline_a.data(), firstline_a.size());
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cur_loc += firstline_a.size();
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *cur_loc = ' ';
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ++cur_loc;
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(cur_loc, firstline_b.data(), firstline_b.size());
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cur_loc += firstline_b.size();
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *cur_loc = ' ';
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ++cur_loc;
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(cur_loc, firstline_c.data(), firstline_c.size());
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  whitespace_1_idx_ = storage - GetPtr(firstline_buffer_base_idx_);
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  non_whitespace_1_idx_ = whitespace_1_idx_;
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  whitespace_2_idx_ = non_whitespace_1_idx_ + firstline_a.size();
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  non_whitespace_2_idx_ = whitespace_2_idx_ + 1;
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  whitespace_3_idx_ = non_whitespace_2_idx_ + firstline_b.size();
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  non_whitespace_3_idx_ = whitespace_3_idx_ + 1;
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  whitespace_4_idx_ = non_whitespace_3_idx_ + firstline_c.size();
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  end_of_firstline_idx_ = whitespace_4_idx_;
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaHeaders::SetRequestMethod(const base::StringPiece& method) {
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is the first of the three parts of the firstline.
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (method.size() <= (whitespace_2_idx_ - non_whitespace_1_idx_)) {
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    non_whitespace_1_idx_ = whitespace_2_idx_ - method.size();
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char* stream_begin = GetPtr(firstline_buffer_base_idx_);
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(stream_begin + non_whitespace_1_idx_,
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           method.data(),
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           method.size());
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The new method is too large to fit in the space available for the old
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // one, so we have to reformat the firstline.
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetFirstlineFromStringPieces(method, request_uri(), request_version());
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaHeaders::SetResponseVersion(const base::StringPiece& version) {
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note: There is no difference between request_method() and
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // response_Version(). Thus, a function to set one is equivalent to a
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // function to set the other. We maintain two functions for this as it is
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // much more descriptive, and makes code more understandable.
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetRequestMethod(version);
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaHeaders::SetRequestUri(const base::StringPiece& uri) {
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetFirstlineFromStringPieces(request_method(), uri, request_version());
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaHeaders::SetResponseCode(const base::StringPiece& code) {
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note: There is no difference between request_uri() and response_code().
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Thus, a function to set one is equivalent to a function to set the other.
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We maintain two functions for this as it is much more descriptive, and
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // makes code more understandable.
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetRequestUri(code);
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaHeaders::SetParsedResponseCodeAndUpdateFirstline(
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t parsed_response_code) {
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char buffer[kFastToBufferSize];
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int len_converted = snprintf(buffer, sizeof(buffer),
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               "%zd", parsed_response_code);
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_GT(len_converted, 0);
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetResponseCode(base::StringPiece(buffer, len_converted));
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaHeaders::SetRequestVersion(const base::StringPiece& version) {
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is the last of the three parts of the firstline.
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Since whitespace_3_idx and non_whitespace_3_idx may point to the same
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // place, we ensure below that any available space includes space for a
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // litteral space (' ') character between the second component and the third
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // component. If the space between whitespace_3_idx_ and
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // end_of_firstline_idx_ is >= to version.size() + 1 (for the space), then we
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // can update the firstline in-place.
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* stream_begin = GetPtr(firstline_buffer_base_idx_);
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (version.size() + 1 <= end_of_firstline_idx_ - whitespace_3_idx_) {
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *(stream_begin + whitespace_3_idx_) = kSpaceChar;
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    non_whitespace_3_idx_ = whitespace_3_idx_ + 1;
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    whitespace_4_idx_ = non_whitespace_3_idx_ + version.size();
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(stream_begin + non_whitespace_3_idx_,
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           version.data(),
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           version.size());
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The new version is to large to fit in the space available for the old
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // one, so we have to reformat the firstline.
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetFirstlineFromStringPieces(request_method(), request_uri(), version);
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaHeaders::SetResponseReasonPhrase(const base::StringPiece& reason) {
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note: There is no difference between request_version() and
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // response_reason_phrase(). Thus, a function to set one is equivalent to a
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // function to set the other. We maintain two functions for this as it is
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // much more descriptive, and makes code more understandable.
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetRequestVersion(reason);
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
966