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

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