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