| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #ifndef NET_SPDY_SPDY_HEADER_BLOCK_H_ | |
| 6 #define NET_SPDY_SPDY_HEADER_BLOCK_H_ | |
| 7 | |
| 8 #include <stddef.h> | |
| 9 | |
| 10 #include <list> | |
| 11 #include <map> | |
| 12 #include <memory> | |
| 13 #include <utility> | |
| 14 #include <vector> | |
| 15 | |
| 16 #include "base/macros.h" | |
| 17 #include "net/base/linked_hash_map.h" | |
| 18 #include "net/base/net_export.h" | |
| 19 #include "net/log/net_log.h" | |
| 20 #include "net/spdy/platform/api/spdy_string.h" | |
| 21 #include "net/spdy/platform/api/spdy_string_piece.h" | |
| 22 | |
| 23 namespace base { | |
| 24 class Value; | |
| 25 } | |
| 26 | |
| 27 namespace net { | |
| 28 | |
| 29 class NetLogCaptureMode; | |
| 30 | |
| 31 namespace test { | |
| 32 class SpdyHeaderBlockPeer; | |
| 33 class ValueProxyPeer; | |
| 34 } | |
| 35 | |
| 36 // This class provides a key-value map that can be used to store SPDY header | |
| 37 // names and values. This data structure preserves insertion order. | |
| 38 // | |
| 39 // Under the hood, this data structure uses large, contiguous blocks of memory | |
| 40 // to store names and values. Lookups may be performed with SpdyStringPiece | |
| 41 // keys, and values are returned as SpdyStringPieces (via ValueProxy, below). | |
| 42 // Value SpdyStringPieces are valid as long as the SpdyHeaderBlock exists; | |
| 43 // allocated memory is never freed until SpdyHeaderBlock's destruction. | |
| 44 // | |
| 45 // This implementation does not make much of an effort to minimize wasted space. | |
| 46 // It's expected that keys are rarely deleted from a SpdyHeaderBlock. | |
| 47 class NET_EXPORT SpdyHeaderBlock { | |
| 48 private: | |
| 49 class Storage; | |
| 50 | |
| 51 // Stores a list of value fragments that can be joined later with a | |
| 52 // key-dependent separator. | |
| 53 class NET_EXPORT HeaderValue { | |
| 54 public: | |
| 55 HeaderValue(Storage* storage, | |
| 56 SpdyStringPiece key, | |
| 57 SpdyStringPiece initial_value); | |
| 58 | |
| 59 // Moves are allowed. | |
| 60 HeaderValue(HeaderValue&& other); | |
| 61 HeaderValue& operator=(HeaderValue&& other); | |
| 62 | |
| 63 // Copies are not. | |
| 64 HeaderValue(const HeaderValue& other) = delete; | |
| 65 HeaderValue& operator=(const HeaderValue& other) = delete; | |
| 66 | |
| 67 ~HeaderValue(); | |
| 68 | |
| 69 // Consumes at most |fragment.size()| bytes of memory. | |
| 70 void Append(SpdyStringPiece fragment); | |
| 71 | |
| 72 SpdyStringPiece value() const { return as_pair().second; } | |
| 73 const std::pair<SpdyStringPiece, SpdyStringPiece>& as_pair() const; | |
| 74 | |
| 75 private: | |
| 76 // May allocate a large contiguous region of memory to hold the concatenated | |
| 77 // fragments and separators. | |
| 78 SpdyStringPiece ConsolidatedValue() const; | |
| 79 | |
| 80 mutable Storage* storage_; | |
| 81 mutable std::vector<SpdyStringPiece> fragments_; | |
| 82 // The first element is the key; the second is the consolidated value. | |
| 83 mutable std::pair<SpdyStringPiece, SpdyStringPiece> pair_; | |
| 84 }; | |
| 85 | |
| 86 typedef linked_hash_map<SpdyStringPiece, HeaderValue, base::StringPieceHash> | |
| 87 MapType; | |
| 88 | |
| 89 public: | |
| 90 typedef std::pair<SpdyStringPiece, SpdyStringPiece> value_type; | |
| 91 | |
| 92 // Provides iteration over a sequence of std::pair<SpdyStringPiece, | |
| 93 // SpdyStringPiece>, even though the underlying MapType::value_type is | |
| 94 // different. Dereferencing the iterator will result in memory allocation for | |
| 95 // multi-value headers. | |
| 96 class NET_EXPORT iterator { | |
| 97 public: | |
| 98 // The following type definitions fulfill the requirements for iterator | |
| 99 // implementations. | |
| 100 typedef std::pair<SpdyStringPiece, SpdyStringPiece> value_type; | |
| 101 typedef value_type& reference; | |
| 102 typedef value_type* pointer; | |
| 103 typedef std::forward_iterator_tag iterator_category; | |
| 104 typedef MapType::iterator::difference_type difference_type; | |
| 105 | |
| 106 // In practice, this iterator only offers access to const value_type. | |
| 107 typedef const value_type& const_reference; | |
| 108 typedef const value_type* const_pointer; | |
| 109 | |
| 110 explicit iterator(MapType::const_iterator it); | |
| 111 iterator(const iterator& other); | |
| 112 ~iterator(); | |
| 113 | |
| 114 // This will result in memory allocation if the value consists of multiple | |
| 115 // fragments. | |
| 116 const_reference operator*() const { return it_->second.as_pair(); } | |
| 117 | |
| 118 const_pointer operator->() const { return &(this->operator*()); } | |
| 119 bool operator==(const iterator& it) const { return it_ == it.it_; } | |
| 120 bool operator!=(const iterator& it) const { return !(*this == it); } | |
| 121 | |
| 122 iterator& operator++() { | |
| 123 it_++; | |
| 124 return *this; | |
| 125 } | |
| 126 | |
| 127 iterator operator++(int) { | |
| 128 auto ret = *this; | |
| 129 this->operator++(); | |
| 130 return ret; | |
| 131 } | |
| 132 | |
| 133 private: | |
| 134 MapType::const_iterator it_; | |
| 135 }; | |
| 136 typedef iterator const_iterator; | |
| 137 | |
| 138 class ValueProxy; | |
| 139 | |
| 140 SpdyHeaderBlock(); | |
| 141 SpdyHeaderBlock(const SpdyHeaderBlock& other) = delete; | |
| 142 SpdyHeaderBlock(SpdyHeaderBlock&& other); | |
| 143 ~SpdyHeaderBlock(); | |
| 144 | |
| 145 SpdyHeaderBlock& operator=(const SpdyHeaderBlock& other) = delete; | |
| 146 SpdyHeaderBlock& operator=(SpdyHeaderBlock&& other); | |
| 147 SpdyHeaderBlock Clone() const; | |
| 148 | |
| 149 bool operator==(const SpdyHeaderBlock& other) const; | |
| 150 bool operator!=(const SpdyHeaderBlock& other) const; | |
| 151 | |
| 152 // Provides a human readable multi-line representation of the stored header | |
| 153 // keys and values. | |
| 154 SpdyString DebugString() const; | |
| 155 | |
| 156 iterator begin() { return iterator(block_.begin()); } | |
| 157 iterator end() { return iterator(block_.end()); } | |
| 158 const_iterator begin() const { return const_iterator(block_.begin()); } | |
| 159 const_iterator end() const { return const_iterator(block_.end()); } | |
| 160 bool empty() const { return block_.empty(); } | |
| 161 size_t size() const { return block_.size(); } | |
| 162 iterator find(SpdyStringPiece key) { return iterator(block_.find(key)); } | |
| 163 const_iterator find(SpdyStringPiece key) const { | |
| 164 return const_iterator(block_.find(key)); | |
| 165 } | |
| 166 void erase(SpdyStringPiece key) { block_.erase(key); } | |
| 167 | |
| 168 // Clears both our MapType member and the memory used to hold headers. | |
| 169 void clear(); | |
| 170 | |
| 171 // The next few methods copy data into our backing storage. | |
| 172 | |
| 173 // If key already exists in the block, replaces the value of that key. Else | |
| 174 // adds a new header to the end of the block. | |
| 175 void insert(const value_type& value); | |
| 176 | |
| 177 // If a header with the key is already present, then append the value to the | |
| 178 // existing header value, NUL ("\0") separated unless the key is cookie, in | |
| 179 // which case the separator is "; ". | |
| 180 // If there is no such key, a new header with the key and value is added. | |
| 181 void AppendValueOrAddHeader(const SpdyStringPiece key, | |
| 182 const SpdyStringPiece value); | |
| 183 | |
| 184 // Allows either lookup or mutation of the value associated with a key. | |
| 185 ValueProxy operator[](const SpdyStringPiece key); | |
| 186 | |
| 187 // This object provides automatic conversions that allow SpdyHeaderBlock to be | |
| 188 // nearly a drop-in replacement for linked_hash_map<SpdyString, SpdyString>. | |
| 189 // It reads data from or writes data to a SpdyHeaderBlock::Storage. | |
| 190 class NET_EXPORT ValueProxy { | |
| 191 public: | |
| 192 ~ValueProxy(); | |
| 193 | |
| 194 // Moves are allowed. | |
| 195 ValueProxy(ValueProxy&& other); | |
| 196 ValueProxy& operator=(ValueProxy&& other); | |
| 197 | |
| 198 // Copies are not. | |
| 199 ValueProxy(const ValueProxy& other) = delete; | |
| 200 ValueProxy& operator=(const ValueProxy& other) = delete; | |
| 201 | |
| 202 // Assignment modifies the underlying SpdyHeaderBlock. | |
| 203 ValueProxy& operator=(const SpdyStringPiece other); | |
| 204 | |
| 205 SpdyString as_string() const; | |
| 206 | |
| 207 private: | |
| 208 friend class SpdyHeaderBlock; | |
| 209 friend class test::ValueProxyPeer; | |
| 210 | |
| 211 ValueProxy(SpdyHeaderBlock::MapType* block, | |
| 212 SpdyHeaderBlock::Storage* storage, | |
| 213 SpdyHeaderBlock::MapType::iterator lookup_result, | |
| 214 const SpdyStringPiece key); | |
| 215 | |
| 216 SpdyHeaderBlock::MapType* block_; | |
| 217 SpdyHeaderBlock::Storage* storage_; | |
| 218 SpdyHeaderBlock::MapType::iterator lookup_result_; | |
| 219 SpdyStringPiece key_; | |
| 220 bool valid_; | |
| 221 }; | |
| 222 | |
| 223 // Returns the estimate of dynamically allocated memory in bytes. | |
| 224 size_t EstimateMemoryUsage() const; | |
| 225 | |
| 226 private: | |
| 227 friend class test::SpdyHeaderBlockPeer; | |
| 228 | |
| 229 void AppendHeader(const SpdyStringPiece key, const SpdyStringPiece value); | |
| 230 Storage* GetStorage(); | |
| 231 size_t bytes_allocated() const; | |
| 232 | |
| 233 // SpdyStringPieces held by |block_| point to memory owned by |*storage_|. | |
| 234 // |storage_| might be nullptr as long as |block_| is empty. | |
| 235 MapType block_; | |
| 236 std::unique_ptr<Storage> storage_; | |
| 237 }; | |
| 238 | |
| 239 // Writes |fragments| to |dst|, joined by |separator|. |dst| must be large | |
| 240 // enough to hold the result. Returns the number of bytes written. | |
| 241 NET_EXPORT size_t Join(char* dst, | |
| 242 const std::vector<SpdyStringPiece>& fragments, | |
| 243 SpdyStringPiece separator); | |
| 244 | |
| 245 // Converts a SpdyHeaderBlock into NetLog event parameters. | |
| 246 NET_EXPORT std::unique_ptr<base::Value> SpdyHeaderBlockNetLogCallback( | |
| 247 const SpdyHeaderBlock* headers, | |
| 248 NetLogCaptureMode capture_mode); | |
| 249 | |
| 250 // Converts NetLog event parameters into a SPDY header block and writes them | |
| 251 // to |headers|. |event_param| must have been created by | |
| 252 // SpdyHeaderBlockNetLogCallback. On failure, returns false and clears | |
| 253 // |headers|. | |
| 254 NET_EXPORT bool SpdyHeaderBlockFromNetLogParam( | |
| 255 const base::Value* event_param, | |
| 256 SpdyHeaderBlock* headers); | |
| 257 | |
| 258 } // namespace net | |
| 259 | |
| 260 #endif // NET_SPDY_SPDY_HEADER_BLOCK_H_ | |
| OLD | NEW |