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

Side by Side 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 some includes. Created 5 years, 2 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/spdy/spdy_header_block.h" 5 #include "net/spdy/spdy_header_block.h"
6 6
7 #include <algorithm>
8 #include <ios>
9 #include <utility>
10 #include <vector>
11
12 #include "base/logging.h"
7 #include "base/values.h" 13 #include "base/values.h"
8 #include "net/http/http_log_util.h" 14 #include "net/http/http_log_util.h"
9 15
16 using std::dec;
17 using std::hex;
18 using std::max;
19 using std::min;
20
10 namespace net { 21 namespace net {
22 namespace {
23
24 // SpdyHeaderBlock::Storage uses a small initial block in case we only have a
25 // minimal set of headers.
26 const size_t kInitialStorageBlockSize = 512;
27
28 // SpdyHeaderBlock::Storage allocates blocks of this size by default.
29 const size_t kDefaultStorageBlockSize = 2048;
30
31 // When copying a SpdyHeaderBlock, the new block will allocate at most this
32 // much memory for the initial contiguous block.
33 const size_t kMaxContiguousAllocation = 16 * 1024;
34
35 } // namespace
36
37 // This class provides a backing store for StringPieces. It uses a sequence of
38 // large, contiguous blocks. It has the property that StringPieces that refer
39 // to data in Storage are never invalidated until the Storage is deleted.
40 //
41 // Write operations always append to the last block. If there is not enough
42 // space to perform the write, a new block is allocated, and any unused space
43 // is wasted.
44 class SpdyHeaderBlock::Storage {
45 public:
46 Storage() : bytes_used_(0) {}
47 ~Storage() { Clear(); }
48
49 void Reserve(size_t additional_space) {
50 if (blocks_.empty()) {
51 AllocBlock(max(additional_space, kInitialStorageBlockSize));
52 } else {
53 const Block& last = blocks_.back();
54 if (last.size - last.used < additional_space) {
55 AllocBlock(max(additional_space, kDefaultStorageBlockSize));
56 }
57 }
58 }
59
60 StringPiece Write(const StringPiece s) {
61 Reserve(s.size());
62 Block* last = &blocks_.back();
63 memcpy(last->data + last->used, s.data(), s.size());
64 StringPiece out(last->data + last->used, s.size());
65 VLOG(3) << "Write result: " << hex
66 << reinterpret_cast<const void*>(out.data()) << ", " << dec
67 << out.size();
68 last->used += s.size();
69 bytes_used_ += s.size();
70 return out;
71 }
72
73 void Clear() {
74 while (!blocks_.empty()) {
75 delete[] blocks_.back().data;
76 blocks_.pop_back();
77 }
78 bytes_used_ = 0;
79 }
80
81 size_t BytesUsed() const { return bytes_used_; }
82
83 private:
84 // TODO(bnc): As soon as move semantics are allowed, change from naked pointer
85 // to scoped_ptr<>, or better yet, unique_ptr<>.
86 struct Block {
87 char* data;
88 size_t size = 0;
89 size_t used = 0;
90
91 Block(char* data, size_t s) : data(data), size(s), used(0) {}
92 };
93
94 void AllocBlock(size_t size) {
95 blocks_.push_back(Block(new char[size], size));
96 }
97
98 std::vector<Block> blocks_;
99 size_t bytes_used_;
100
101 DISALLOW_COPY_AND_ASSIGN(Storage);
102 };
103
104 SpdyHeaderBlock::StringPieceProxy::StringPieceProxy(
105 SpdyHeaderBlock::MapType* block,
106 SpdyHeaderBlock::Storage* storage,
107 SpdyHeaderBlock::MapType::iterator lookup_result,
108 const StringPiece key)
109 : block_(block),
110 storage_(storage),
111 lookup_result_(lookup_result),
112 key_(key) {}
113
114 SpdyHeaderBlock::StringPieceProxy::~StringPieceProxy() {}
115
116 SpdyHeaderBlock::StringPieceProxy& SpdyHeaderBlock::StringPieceProxy::operator=(
117 const StringPiece value) {
118 if (lookup_result_ == block_->end()) {
119 VLOG(1) << "Inserting: (" << key_ << ", " << value << ")";
120 lookup_result_ =
121 block_->insert(std::make_pair(key_, storage_->Write(value))).first;
122 } else {
123 VLOG(1) << "Updating key: " << key_ << " with value: " << value;
124 lookup_result_->second = storage_->Write(value);
125 }
126 return *this;
127 }
128
129 SpdyHeaderBlock::StringPieceProxy::operator StringPiece() const {
130 return (lookup_result_ == block_->end()) ? StringPiece()
131 : lookup_result_->second;
132 }
133
134 void SpdyHeaderBlock::StringPieceProxy::reserve(size_t size) {
135 storage_->Reserve(size);
136 }
137
138 SpdyHeaderBlock::SpdyHeaderBlock() : storage_(new Storage) {}
139
140 SpdyHeaderBlock::~SpdyHeaderBlock() {}
141
142 SpdyHeaderBlock::SpdyHeaderBlock(const SpdyHeaderBlock& other)
143 : storage_(new Storage) {
144 storage_->Reserve(min(other.storage_->BytesUsed(), kMaxContiguousAllocation));
145 for (auto iter : other) {
146 AppendHeader(iter.first, iter.second);
147 }
148 }
149
150 SpdyHeaderBlock& SpdyHeaderBlock::operator=(const SpdyHeaderBlock& other) {
151 clear();
152 storage_->Reserve(min(other.storage_->BytesUsed(), kMaxContiguousAllocation));
153 for (auto iter : other) {
154 AppendHeader(iter.first, iter.second);
155 }
156 return *this;
157 }
158
159 void SpdyHeaderBlock::clear() {
160 block_.clear();
161 storage_->Clear();
162 }
163
164 void SpdyHeaderBlock::insert(
165 const SpdyHeaderBlock::MapType::value_type& value) {
166 ReplaceOrAppendHeader(value.first, value.second);
167 }
168
169 SpdyHeaderBlock::StringPieceProxy SpdyHeaderBlock::operator[](
170 const StringPiece key) {
171 VLOG(2) << "Operator[] saw key: " << key;
172 StringPiece out_key;
173 auto iter = block_.find(key);
174 if (iter == block_.end()) {
175 // We write the key first, to assure that the StringPieceProxy has a
176 // reference to a valid StringPiece in its operator=.
177 out_key = storage_->Write(key);
178 VLOG(2) << "Key written as: " << hex << static_cast<const void*>(key.data())
179 << ", " << dec << key.size();
180 } else {
181 out_key = iter->first;
182 }
183 return StringPieceProxy(&block_, storage_.get(), iter, out_key);
184 }
185
186 bool SpdyHeaderBlock::operator==(const SpdyHeaderBlock& other) const {
187 return size() == other.size() && std::equal(begin(), end(), other.begin());
188 }
189
190 void SpdyHeaderBlock::ReplaceOrAppendHeader(const StringPiece key,
191 const StringPiece value) {
192 // TODO(birenroy): Write new value in place of old value, if it fits.
193 auto iter = block_.find(key);
194 if (iter == block_.end()) {
195 VLOG(1) << "Inserting: (" << key << ", " << value << ")";
196 AppendHeader(key, value);
197 } else {
198 VLOG(1) << "Updating key: " << iter->first << " with value: " << value;
199 iter->second = storage_->Write(value);
200 }
201 }
202
203 void SpdyHeaderBlock::AppendHeader(const StringPiece key,
204 const StringPiece value) {
205 block_.insert(make_pair(storage_->Write(key), storage_->Write(value)));
206 }
11 207
12 scoped_ptr<base::Value> SpdyHeaderBlockNetLogCallback( 208 scoped_ptr<base::Value> SpdyHeaderBlockNetLogCallback(
13 const SpdyHeaderBlock* headers, 209 const SpdyHeaderBlock* headers,
14 NetLogCaptureMode capture_mode) { 210 NetLogCaptureMode capture_mode) {
15 scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); 211 scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
16 base::DictionaryValue* headers_dict = new base::DictionaryValue(); 212 base::DictionaryValue* headers_dict = new base::DictionaryValue();
17 for (SpdyHeaderBlock::const_iterator it = headers->begin(); 213 for (SpdyHeaderBlock::const_iterator it = headers->begin();
18 it != headers->end(); ++it) { 214 it != headers->end(); ++it) {
19 headers_dict->SetWithoutPathExpansion( 215 headers_dict->SetWithoutPathExpansion(
20 it->first, new base::StringValue(ElideHeaderValueForNetLog( 216 it->first.as_string(),
21 capture_mode, it->first, it->second))); 217 new base::StringValue(ElideHeaderValueForNetLog(
218 capture_mode, it->first.as_string(), it->second.as_string())));
22 } 219 }
23 dict->Set("headers", headers_dict); 220 dict->Set("headers", headers_dict);
24 return dict.Pass(); 221 return dict.Pass();
25 } 222 }
26 223
27 bool SpdyHeaderBlockFromNetLogParam( 224 bool SpdyHeaderBlockFromNetLogParam(
28 const base::Value* event_param, 225 const base::Value* event_param,
29 SpdyHeaderBlock* headers) { 226 SpdyHeaderBlock* headers) {
30 headers->clear(); 227 headers->clear();
31 228
32 const base::DictionaryValue* dict = NULL; 229 const base::DictionaryValue* dict = NULL;
33 const base::DictionaryValue* header_dict = NULL; 230 const base::DictionaryValue* header_dict = NULL;
34 231
35 if (!event_param || 232 if (!event_param ||
36 !event_param->GetAsDictionary(&dict) || 233 !event_param->GetAsDictionary(&dict) ||
37 !dict->GetDictionary("headers", &header_dict)) { 234 !dict->GetDictionary("headers", &header_dict)) {
38 return false; 235 return false;
39 } 236 }
40 237
41 for (base::DictionaryValue::Iterator it(*header_dict); !it.IsAtEnd(); 238 for (base::DictionaryValue::Iterator it(*header_dict); !it.IsAtEnd();
42 it.Advance()) { 239 it.Advance()) {
43 if (!it.value().GetAsString(&(*headers)[it.key()])) { 240 std::string value;
241 if (!it.value().GetAsString(&value)) {
44 headers->clear(); 242 headers->clear();
45 return false; 243 return false;
46 } 244 }
245 (*headers)[it.key()] = value;
47 } 246 }
48 return true; 247 return true;
49 } 248 }
50 249
51 } // namespace net 250 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698