OLD | NEW |
1 // Copyright (c) 2011 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 #ifndef BASE_PICKLE_H__ | 5 #ifndef BASE_PICKLE_H__ |
6 #define BASE_PICKLE_H__ | 6 #define BASE_PICKLE_H__ |
7 #pragma once | 7 #pragma once |
8 | 8 |
9 #include <string> | 9 #include <string> |
10 | 10 |
11 #include "base/base_export.h" | 11 #include "base/base_export.h" |
12 #include "base/basictypes.h" | 12 #include "base/basictypes.h" |
| 13 #include "base/compiler_specific.h" |
13 #include "base/gtest_prod_util.h" | 14 #include "base/gtest_prod_util.h" |
14 #include "base/logging.h" | 15 #include "base/logging.h" |
15 #include "base/string16.h" | 16 #include "base/string16.h" |
16 | 17 |
| 18 class Pickle; |
| 19 |
| 20 // PickleIterator reads data from a Pickle. The Pickle object must remain valid |
| 21 // while the PickleIterator object is in use. |
| 22 class BASE_EXPORT PickleIterator { |
| 23 public: |
| 24 PickleIterator() : read_ptr_(NULL), read_end_ptr_(NULL) {} |
| 25 explicit PickleIterator(const Pickle& pickle); |
| 26 |
| 27 // Methods for reading the payload of the Pickle. To read from the start of |
| 28 // the Pickle, create a PickleIterator from a Pickle. If successful, these |
| 29 // methods return true. Otherwise, false is returned to indicate that the |
| 30 // result could not be extracted. |
| 31 bool ReadBool(bool* result) WARN_UNUSED_RESULT; |
| 32 bool ReadInt(int* result) WARN_UNUSED_RESULT; |
| 33 bool ReadLong(long* result) WARN_UNUSED_RESULT; |
| 34 bool ReadSize(size_t* result) WARN_UNUSED_RESULT; |
| 35 bool ReadUInt16(uint16* result) WARN_UNUSED_RESULT; |
| 36 bool ReadUInt32(uint32* result) WARN_UNUSED_RESULT; |
| 37 bool ReadInt64(int64* result) WARN_UNUSED_RESULT; |
| 38 bool ReadUInt64(uint64* result) WARN_UNUSED_RESULT; |
| 39 bool ReadString(std::string* result) WARN_UNUSED_RESULT; |
| 40 bool ReadWString(std::wstring* result) WARN_UNUSED_RESULT; |
| 41 bool ReadString16(string16* result) WARN_UNUSED_RESULT; |
| 42 bool ReadData(const char** data, int* length) WARN_UNUSED_RESULT; |
| 43 bool ReadBytes(const char** data, int length) WARN_UNUSED_RESULT; |
| 44 |
| 45 // Safer version of ReadInt() checks for the result not being negative. |
| 46 // Use it for reading the object sizes. |
| 47 bool ReadLength(int* result) WARN_UNUSED_RESULT { |
| 48 return ReadInt(result) && *result >= 0; |
| 49 } |
| 50 |
| 51 // Skips bytes in the read buffer and returns true if there are at least |
| 52 // num_bytes available. Otherwise, does nothing and returns false. |
| 53 bool SkipBytes(int num_bytes) WARN_UNUSED_RESULT { |
| 54 return !!GetReadPointerAndAdvance(num_bytes); |
| 55 } |
| 56 |
| 57 private: |
| 58 // Aligns 'i' by rounding it up to the next multiple of 'alignment' |
| 59 static size_t AlignInt(size_t i, int alignment) { |
| 60 return i + (alignment - (i % alignment)) % alignment; |
| 61 } |
| 62 |
| 63 // Read Type from Pickle. |
| 64 template <typename Type> |
| 65 inline bool ReadBuiltinType(Type* result); |
| 66 |
| 67 // Get read pointer for Type and advance read pointer. |
| 68 template<typename Type> |
| 69 inline const char* GetReadPointerAndAdvance(); |
| 70 |
| 71 // Get read pointer for |num_bytes| and advance read pointer. This method |
| 72 // checks num_bytes for negativity and wrapping. |
| 73 const char* GetReadPointerAndAdvance(int num_bytes); |
| 74 |
| 75 // Get read pointer for (num_elements * size_element) bytes and advance read |
| 76 // pointer. This method checks for int overflow, negativity and wrapping. |
| 77 inline const char* GetReadPointerAndAdvance(int num_elements, |
| 78 size_t size_element); |
| 79 |
| 80 // Pointers to the Pickle data. |
| 81 const char* read_ptr_; |
| 82 const char* read_end_ptr_; |
| 83 |
| 84 FRIEND_TEST_ALL_PREFIXES(PickleTest, GetReadPointerAndAdvance); |
| 85 }; |
| 86 |
17 // This class provides facilities for basic binary value packing and unpacking. | 87 // This class provides facilities for basic binary value packing and unpacking. |
18 // | 88 // |
19 // The Pickle class supports appending primitive values (ints, strings, etc.) | 89 // The Pickle class supports appending primitive values (ints, strings, etc.) |
20 // to a pickle instance. The Pickle instance grows its internal memory buffer | 90 // to a pickle instance. The Pickle instance grows its internal memory buffer |
21 // dynamically to hold the sequence of primitive values. The internal memory | 91 // dynamically to hold the sequence of primitive values. The internal memory |
22 // buffer is exposed as the "data" of the Pickle. This "data" can be passed | 92 // buffer is exposed as the "data" of the Pickle. This "data" can be passed |
23 // to a Pickle object to initialize it for reading. | 93 // to a Pickle object to initialize it for reading. |
24 // | 94 // |
25 // When reading from a Pickle object, it is important for the consumer to know | 95 // When reading from a Pickle object, it is important for the consumer to know |
26 // what value types to read and in what order to read them as the Pickle does | 96 // what value types to read and in what order to read them as the Pickle does |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
59 | 129 |
60 // Performs a deep copy. | 130 // Performs a deep copy. |
61 Pickle& operator=(const Pickle& other); | 131 Pickle& operator=(const Pickle& other); |
62 | 132 |
63 // Returns the size of the Pickle's data. | 133 // Returns the size of the Pickle's data. |
64 size_t size() const { return header_size_ + header_->payload_size; } | 134 size_t size() const { return header_size_ + header_->payload_size; } |
65 | 135 |
66 // Returns the data for this Pickle. | 136 // Returns the data for this Pickle. |
67 const void* data() const { return header_; } | 137 const void* data() const { return header_; } |
68 | 138 |
69 // Methods for reading the payload of the Pickle. To read from the start of | 139 // For compatibility, these older style read methods pass through to the |
70 // the Pickle, initialize *iter to NULL. If successful, these methods return | 140 // PickleIterator methods. |
71 // true. Otherwise, false is returned to indicate that the result could not | 141 // TODO(jbates) Remove these methods. |
72 // be extracted. | 142 bool ReadBool(PickleIterator* iter, bool* result) const { |
73 bool ReadBool(void** iter, bool* result) const; | 143 return iter->ReadBool(result); |
74 bool ReadInt(void** iter, int* result) const; | 144 } |
75 bool ReadLong(void** iter, long* result) const; | 145 bool ReadInt(PickleIterator* iter, int* result) const { |
76 bool ReadSize(void** iter, size_t* result) const; | 146 return iter->ReadInt(result); |
77 bool ReadUInt16(void** iter, uint16* result) const; | 147 } |
78 bool ReadUInt32(void** iter, uint32* result) const; | 148 bool ReadLong(PickleIterator* iter, long* result) const { |
79 bool ReadInt64(void** iter, int64* result) const; | 149 return iter->ReadLong(result); |
80 bool ReadUInt64(void** iter, uint64* result) const; | 150 } |
81 bool ReadString(void** iter, std::string* result) const; | 151 bool ReadSize(PickleIterator* iter, size_t* result) const { |
82 bool ReadWString(void** iter, std::wstring* result) const; | 152 return iter->ReadSize(result); |
83 bool ReadString16(void** iter, string16* result) const; | 153 } |
84 bool ReadData(void** iter, const char** data, int* length) const; | 154 bool ReadUInt16(PickleIterator* iter, uint16* result) const { |
85 bool ReadBytes(void** iter, const char** data, int length) const; | 155 return iter->ReadUInt16(result); |
| 156 } |
| 157 bool ReadUInt32(PickleIterator* iter, uint32* result) const { |
| 158 return iter->ReadUInt32(result); |
| 159 } |
| 160 bool ReadInt64(PickleIterator* iter, int64* result) const { |
| 161 return iter->ReadInt64(result); |
| 162 } |
| 163 bool ReadUInt64(PickleIterator* iter, uint64* result) const { |
| 164 return iter->ReadUInt64(result); |
| 165 } |
| 166 bool ReadString(PickleIterator* iter, std::string* result) const { |
| 167 return iter->ReadString(result); |
| 168 } |
| 169 bool ReadWString(PickleIterator* iter, std::wstring* result) const { |
| 170 return iter->ReadWString(result); |
| 171 } |
| 172 bool ReadString16(PickleIterator* iter, string16* result) const { |
| 173 return iter->ReadString16(result); |
| 174 } |
| 175 bool ReadData(PickleIterator* iter, const char** data, int* length) const { |
| 176 return iter->ReadData(data, length); |
| 177 } |
| 178 bool ReadBytes(PickleIterator* iter, const char** data, int length) const { |
| 179 return iter->ReadBytes(data, length); |
| 180 } |
86 | 181 |
87 // Safer version of ReadInt() checks for the result not being negative. | 182 // Safer version of ReadInt() checks for the result not being negative. |
88 // Use it for reading the object sizes. | 183 // Use it for reading the object sizes. |
89 bool ReadLength(void** iter, int* result) const; | 184 bool ReadLength(PickleIterator* iter, int* result) const { |
| 185 return iter->ReadLength(result); |
| 186 } |
90 | 187 |
91 // Methods for adding to the payload of the Pickle. These values are | 188 // Methods for adding to the payload of the Pickle. These values are |
92 // appended to the end of the Pickle's payload. When reading values from a | 189 // appended to the end of the Pickle's payload. When reading values from a |
93 // Pickle, it is important to read them in the order in which they were added | 190 // Pickle, it is important to read them in the order in which they were added |
94 // to the Pickle. | 191 // to the Pickle. |
95 bool WriteBool(bool value) { | 192 bool WriteBool(bool value) { |
96 return WriteInt(value ? 1 : 0); | 193 return WriteInt(value ? 1 : 0); |
97 } | 194 } |
98 bool WriteInt(int value) { | 195 bool WriteInt(int value) { |
99 return WriteBytes(&value, sizeof(value)); | 196 return WriteBytes(&value, sizeof(value)); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
155 T* headerT() { | 252 T* headerT() { |
156 DCHECK_EQ(header_size_, sizeof(T)); | 253 DCHECK_EQ(header_size_, sizeof(T)); |
157 return static_cast<T*>(header_); | 254 return static_cast<T*>(header_); |
158 } | 255 } |
159 template <class T> | 256 template <class T> |
160 const T* headerT() const { | 257 const T* headerT() const { |
161 DCHECK_EQ(header_size_, sizeof(T)); | 258 DCHECK_EQ(header_size_, sizeof(T)); |
162 return static_cast<const T*>(header_); | 259 return static_cast<const T*>(header_); |
163 } | 260 } |
164 | 261 |
165 // Returns true if the given iterator could point to data with the given | |
166 // length. If there is no room for the given data before the end of the | |
167 // payload, returns false. | |
168 bool IteratorHasRoomFor(const void* iter, int len) const { | |
169 if ((len < 0) || (iter < header_) || iter > end_of_payload()) | |
170 return false; | |
171 const char* end_of_region = reinterpret_cast<const char*>(iter) + len; | |
172 // Watch out for overflow in pointer calculation, which wraps. | |
173 return (iter <= end_of_region) && (end_of_region <= end_of_payload()); | |
174 } | |
175 | |
176 protected: | 262 protected: |
177 size_t payload_size() const { return header_->payload_size; } | 263 size_t payload_size() const { return header_->payload_size; } |
178 | 264 |
179 char* payload() { | 265 char* payload() { |
180 return reinterpret_cast<char*>(header_) + header_size_; | 266 return reinterpret_cast<char*>(header_) + header_size_; |
181 } | 267 } |
182 const char* payload() const { | 268 const char* payload() const { |
183 return reinterpret_cast<const char*>(header_) + header_size_; | 269 return reinterpret_cast<const char*>(header_) + header_size_; |
184 } | 270 } |
185 | 271 |
(...skipping 27 matching lines...) Expand all Loading... |
213 // the header: new_capacity = sizeof(Header) + desired_payload_capacity. | 299 // the header: new_capacity = sizeof(Header) + desired_payload_capacity. |
214 // A realloc() failure will cause a Resize failure... and caller should check | 300 // A realloc() failure will cause a Resize failure... and caller should check |
215 // the return result for true (i.e., successful resizing). | 301 // the return result for true (i.e., successful resizing). |
216 bool Resize(size_t new_capacity); | 302 bool Resize(size_t new_capacity); |
217 | 303 |
218 // Aligns 'i' by rounding it up to the next multiple of 'alignment' | 304 // Aligns 'i' by rounding it up to the next multiple of 'alignment' |
219 static size_t AlignInt(size_t i, int alignment) { | 305 static size_t AlignInt(size_t i, int alignment) { |
220 return i + (alignment - (i % alignment)) % alignment; | 306 return i + (alignment - (i % alignment)) % alignment; |
221 } | 307 } |
222 | 308 |
223 // Moves the iterator by the given number of bytes, making sure it is aligned. | |
224 // Pointer (iterator) is NOT aligned, but the change in the pointer | |
225 // is guaranteed to be a multiple of sizeof(uint32). | |
226 static void UpdateIter(void** iter, int bytes) { | |
227 *iter = static_cast<char*>(*iter) + AlignInt(bytes, sizeof(uint32)); | |
228 } | |
229 | |
230 // Find the end of the pickled data that starts at range_start. Returns NULL | 309 // Find the end of the pickled data that starts at range_start. Returns NULL |
231 // if the entire Pickle is not found in the given data range. | 310 // if the entire Pickle is not found in the given data range. |
232 static const char* FindNext(size_t header_size, | 311 static const char* FindNext(size_t header_size, |
233 const char* range_start, | 312 const char* range_start, |
234 const char* range_end); | 313 const char* range_end); |
235 | 314 |
236 // The allocation granularity of the payload. | 315 // The allocation granularity of the payload. |
237 static const int kPayloadUnit; | 316 static const int kPayloadUnit; |
238 | 317 |
239 private: | 318 private: |
| 319 friend class PickleIterator; |
| 320 |
240 Header* header_; | 321 Header* header_; |
241 size_t header_size_; // Supports extra data between header and payload. | 322 size_t header_size_; // Supports extra data between header and payload. |
242 // Allocation size of payload (or -1 if allocation is const). | 323 // Allocation size of payload (or -1 if allocation is const). |
243 size_t capacity_; | 324 size_t capacity_; |
244 size_t variable_buffer_offset_; // IF non-zero, then offset to a buffer. | 325 size_t variable_buffer_offset_; // IF non-zero, then offset to a buffer. |
245 | 326 |
246 FRIEND_TEST_ALL_PREFIXES(PickleTest, Resize); | 327 FRIEND_TEST_ALL_PREFIXES(PickleTest, Resize); |
247 FRIEND_TEST_ALL_PREFIXES(PickleTest, FindNext); | 328 FRIEND_TEST_ALL_PREFIXES(PickleTest, FindNext); |
248 FRIEND_TEST_ALL_PREFIXES(PickleTest, FindNextWithIncompleteHeader); | 329 FRIEND_TEST_ALL_PREFIXES(PickleTest, FindNextWithIncompleteHeader); |
249 FRIEND_TEST_ALL_PREFIXES(PickleTest, IteratorHasRoom); | |
250 }; | 330 }; |
251 | 331 |
252 #endif // BASE_PICKLE_H__ | 332 #endif // BASE_PICKLE_H__ |
OLD | NEW |