Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(440)

Unified Diff: net/spdy/spdy_header_block.cc

Issue 1357953002: Replace the existing SpdyHeaderBlock typedef with a class. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add NET_EXPORT to fix compile error on win_chromium_compile_dbg_ng. Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/spdy/spdy_header_block.h ('k') | net/spdy/spdy_header_block_test.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/spdy/spdy_header_block.cc
diff --git a/net/spdy/spdy_header_block.cc b/net/spdy/spdy_header_block.cc
index 6e72451112d96c7d982070976b2fbbd6003f6df0..d12ab70cb9000c78e4d3bd0da1224cdc1bb31485 100644
--- a/net/spdy/spdy_header_block.cc
+++ b/net/spdy/spdy_header_block.cc
@@ -4,10 +4,207 @@
#include "net/spdy/spdy_header_block.h"
+#include <algorithm>
+#include <ios>
+#include <utility>
+#include <vector>
+
+#include "base/logging.h"
#include "base/values.h"
#include "net/http/http_log_util.h"
+using base::StringPiece;
+using std::dec;
+using std::hex;
+using std::max;
+using std::min;
+
namespace net {
+namespace {
+
+// SpdyHeaderBlock::Storage uses a small initial block in case we only have a
+// minimal set of headers.
+const size_t kInitialStorageBlockSize = 512;
+
+// SpdyHeaderBlock::Storage allocates blocks of this size by default.
+const size_t kDefaultStorageBlockSize = 2048;
+
+// When copying a SpdyHeaderBlock, the new block will allocate at most this
+// much memory for the initial contiguous block.
+const size_t kMaxContiguousAllocation = 16 * 1024;
+
+} // namespace
+
+// This class provides a backing store for StringPieces. It uses a sequence of
+// large, contiguous blocks. It has the property that StringPieces that refer
+// to data in Storage are never invalidated until the Storage is deleted.
+//
+// Write operations always append to the last block. If there is not enough
+// space to perform the write, a new block is allocated, and any unused space
+// is wasted.
+class SpdyHeaderBlock::Storage {
+ public:
+ Storage() : bytes_used_(0) {}
+ ~Storage() { Clear(); }
+
+ void Reserve(size_t additional_space) {
+ if (blocks_.empty()) {
+ AllocBlock(max(additional_space, kInitialStorageBlockSize));
+ } else {
+ const Block& last = blocks_.back();
+ if (last.size - last.used < additional_space) {
+ AllocBlock(max(additional_space, kDefaultStorageBlockSize));
+ }
+ }
+ }
+
+ StringPiece Write(const StringPiece s) {
+ Reserve(s.size());
+ Block* last = &blocks_.back();
+ memcpy(last->data + last->used, s.data(), s.size());
+ StringPiece out(last->data + last->used, s.size());
+ VLOG(3) << "Write result: " << hex
+ << reinterpret_cast<const void*>(out.data()) << ", " << dec
+ << out.size();
+ last->used += s.size();
+ bytes_used_ += s.size();
+ return out;
+ }
+
+ void Clear() {
+ while (!blocks_.empty()) {
+ delete[] blocks_.back().data;
+ blocks_.pop_back();
+ }
+ bytes_used_ = 0;
+ }
+
+ size_t BytesUsed() const { return bytes_used_; }
+
+ private:
+ // TODO(bnc): As soon as move semantics are allowed, change from naked pointer
+ // to scoped_ptr<>, or better yet, unique_ptr<>.
+ struct Block {
+ char* data;
+ size_t size = 0;
+ size_t used = 0;
+
+ Block(char* data, size_t s) : data(data), size(s), used(0) {}
+ };
+
+ void AllocBlock(size_t size) {
+ blocks_.push_back(Block(new char[size], size));
+ }
+
+ std::vector<Block> blocks_;
+ size_t bytes_used_;
+
+ DISALLOW_COPY_AND_ASSIGN(Storage);
+};
+
+SpdyHeaderBlock::StringPieceProxy::StringPieceProxy(
+ SpdyHeaderBlock::MapType* block,
+ SpdyHeaderBlock::Storage* storage,
+ SpdyHeaderBlock::MapType::iterator lookup_result,
+ const StringPiece key)
+ : block_(block),
+ storage_(storage),
+ lookup_result_(lookup_result),
+ key_(key) {}
+
+SpdyHeaderBlock::StringPieceProxy::~StringPieceProxy() {}
+
+SpdyHeaderBlock::StringPieceProxy& SpdyHeaderBlock::StringPieceProxy::operator=(
+ const StringPiece value) {
+ if (lookup_result_ == block_->end()) {
+ VLOG(1) << "Inserting: (" << key_ << ", " << value << ")";
+ lookup_result_ =
+ block_->insert(std::make_pair(key_, storage_->Write(value))).first;
+ } else {
+ VLOG(1) << "Updating key: " << key_ << " with value: " << value;
+ lookup_result_->second = storage_->Write(value);
+ }
+ return *this;
+}
+
+SpdyHeaderBlock::StringPieceProxy::operator StringPiece() const {
+ return (lookup_result_ == block_->end()) ? StringPiece()
+ : lookup_result_->second;
+}
+
+void SpdyHeaderBlock::StringPieceProxy::reserve(size_t size) {
+ storage_->Reserve(size);
+}
+
+SpdyHeaderBlock::SpdyHeaderBlock() : storage_(new Storage) {}
+
+SpdyHeaderBlock::~SpdyHeaderBlock() {}
+
+SpdyHeaderBlock::SpdyHeaderBlock(const SpdyHeaderBlock& other)
+ : storage_(new Storage) {
+ storage_->Reserve(min(other.storage_->BytesUsed(), kMaxContiguousAllocation));
+ for (auto iter : other) {
+ AppendHeader(iter.first, iter.second);
+ }
+}
+
+SpdyHeaderBlock& SpdyHeaderBlock::operator=(const SpdyHeaderBlock& other) {
+ clear();
+ storage_->Reserve(min(other.storage_->BytesUsed(), kMaxContiguousAllocation));
+ for (auto iter : other) {
+ AppendHeader(iter.first, iter.second);
+ }
+ return *this;
+}
+
+void SpdyHeaderBlock::clear() {
+ block_.clear();
+ storage_->Clear();
+}
+
+void SpdyHeaderBlock::insert(
+ const SpdyHeaderBlock::MapType::value_type& value) {
+ ReplaceOrAppendHeader(value.first, value.second);
+}
+
+SpdyHeaderBlock::StringPieceProxy SpdyHeaderBlock::operator[](
+ const StringPiece key) {
+ VLOG(2) << "Operator[] saw key: " << key;
+ StringPiece out_key;
+ auto iter = block_.find(key);
+ if (iter == block_.end()) {
+ // We write the key first, to assure that the StringPieceProxy has a
+ // reference to a valid StringPiece in its operator=.
+ out_key = storage_->Write(key);
+ VLOG(2) << "Key written as: " << hex << static_cast<const void*>(key.data())
+ << ", " << dec << key.size();
+ } else {
+ out_key = iter->first;
+ }
+ return StringPieceProxy(&block_, storage_.get(), iter, out_key);
+}
+
+bool SpdyHeaderBlock::operator==(const SpdyHeaderBlock& other) const {
+ return size() == other.size() && std::equal(begin(), end(), other.begin());
+}
+
+void SpdyHeaderBlock::ReplaceOrAppendHeader(const StringPiece key,
+ const StringPiece value) {
+ // TODO(birenroy): Write new value in place of old value, if it fits.
+ auto iter = block_.find(key);
+ if (iter == block_.end()) {
+ VLOG(1) << "Inserting: (" << key << ", " << value << ")";
+ AppendHeader(key, value);
+ } else {
+ VLOG(1) << "Updating key: " << iter->first << " with value: " << value;
+ iter->second = storage_->Write(value);
+ }
+}
+
+void SpdyHeaderBlock::AppendHeader(const StringPiece key,
+ const StringPiece value) {
+ block_.insert(make_pair(storage_->Write(key), storage_->Write(value)));
+}
scoped_ptr<base::Value> SpdyHeaderBlockNetLogCallback(
const SpdyHeaderBlock* headers,
@@ -17,8 +214,9 @@ scoped_ptr<base::Value> SpdyHeaderBlockNetLogCallback(
for (SpdyHeaderBlock::const_iterator it = headers->begin();
it != headers->end(); ++it) {
headers_dict->SetWithoutPathExpansion(
- it->first, new base::StringValue(ElideHeaderValueForNetLog(
- capture_mode, it->first, it->second)));
+ it->first.as_string(),
+ new base::StringValue(ElideHeaderValueForNetLog(
+ capture_mode, it->first.as_string(), it->second.as_string())));
}
dict->Set("headers", headers_dict);
return dict.Pass();
@@ -40,10 +238,12 @@ bool SpdyHeaderBlockFromNetLogParam(
for (base::DictionaryValue::Iterator it(*header_dict); !it.IsAtEnd();
it.Advance()) {
- if (!it.value().GetAsString(&(*headers)[it.key()])) {
+ std::string value;
+ if (!it.value().GetAsString(&value)) {
headers->clear();
return false;
}
+ (*headers)[it.key()] = value;
}
return true;
}
« no previous file with comments | « net/spdy/spdy_header_block.h ('k') | net/spdy/spdy_header_block_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698