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

Side by Side Diff: base/pickle.h

Issue 9447084: Refactor Pickle Read methods to use higher performance PickleIterator. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: jar feedback Created 8 years, 9 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 | Annotate | Revision Log
OLDNEW
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
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
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
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__
OLDNEW
« no previous file with comments | « base/metrics/histogram.cc ('k') | base/pickle.cc » ('j') | base/pickle.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698