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

Side by Side Diff: base/pickle.cc

Issue 9447084: Refactor Pickle Read methods to use higher performance PickleIterator. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: compile (racing with incoming CLs) 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
« no previous file with comments | « base/pickle.h ('k') | base/pickle_unittest.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) 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 #include "base/pickle.h" 5 #include "base/pickle.h"
6 6
7 #include <stdlib.h> 7 #include <stdlib.h>
8 8
9 #include <algorithm> // for max() 9 #include <algorithm> // for max()
10 10
11 //------------------------------------------------------------------------------ 11 //------------------------------------------------------------------------------
12 12
13 // static 13 // static
14 const int Pickle::kPayloadUnit = 64; 14 const int Pickle::kPayloadUnit = 64;
15 15
16 static const size_t kCapacityReadOnly = static_cast<size_t>(-1); 16 static const size_t kCapacityReadOnly = static_cast<size_t>(-1);
17 17
18 PickleIterator::PickleIterator(const Pickle& pickle)
19 : read_ptr_(pickle.payload()),
20 read_end_ptr_(pickle.end_of_payload()) {
21 }
22
23 template <typename Type>
24 inline bool PickleIterator::ReadBuiltinType(Type* result) {
25 const char* read_from = GetReadPointerAndAdvance<Type>();
26 if (!read_from)
27 return false;
28 if (sizeof(Type) > sizeof(uint32))
29 memcpy(result, read_from, sizeof(*result));
30 else
31 *result = *reinterpret_cast<const Type*>(read_from);
32 return true;
33 }
34
35 template<typename Type>
36 inline const char* PickleIterator::GetReadPointerAndAdvance() {
37 const char* current_read_ptr = read_ptr_;
38 if (read_ptr_ + sizeof(Type) > read_end_ptr_)
39 return NULL;
40 if (sizeof(Type) < sizeof(uint32))
41 read_ptr_ += AlignInt(sizeof(Type), sizeof(uint32));
42 else
43 read_ptr_ += sizeof(Type);
44 return current_read_ptr;
45 }
46
47 const char* PickleIterator::GetReadPointerAndAdvance(int num_bytes) {
48 const char* current_read_ptr = read_ptr_;
49 const char* end_data_ptr = read_ptr_ + num_bytes;
50 if (num_bytes < 0)
51 return NULL;
52 // Check for enough space and for wrapping.
53 if (end_data_ptr > read_end_ptr_ || end_data_ptr < current_read_ptr)
54 return NULL;
55 read_ptr_ += AlignInt(num_bytes, sizeof(uint32));
56 return current_read_ptr;
57 }
58
59 inline const char* PickleIterator::GetReadPointerAndAdvance(int num_elements,
60 size_t size_element) {
61 // Check for int32 overflow.
62 int64 num_bytes = static_cast<int64>(num_elements) * size_element;
63 int num_bytes32 = static_cast<int>(num_bytes);
64 if (num_bytes != static_cast<int64>(num_bytes32))
65 return NULL;
66 return GetReadPointerAndAdvance(num_bytes32);
67 }
68
69 bool PickleIterator::ReadBool(bool* result) {
70 return ReadBuiltinType(result);
71 }
72
73 bool PickleIterator::ReadInt(int* result) {
74 return ReadBuiltinType(result);
75 }
76
77 bool PickleIterator::ReadLong(long* result) {
78 return ReadBuiltinType(result);
79 }
80
81 bool PickleIterator::ReadSize(size_t* result) {
82 return ReadBuiltinType(result);
83 }
84
85 bool PickleIterator::ReadUInt16(uint16* result) {
86 return ReadBuiltinType(result);
87 }
88
89 bool PickleIterator::ReadUInt32(uint32* result) {
90 return ReadBuiltinType(result);
91 }
92
93 bool PickleIterator::ReadInt64(int64* result) {
94 return ReadBuiltinType(result);
95 }
96
97 bool PickleIterator::ReadUInt64(uint64* result) {
98 return ReadBuiltinType(result);
99 }
100
101 bool PickleIterator::ReadString(std::string* result) {
102 int len;
103 if (!ReadInt(&len))
104 return false;
105 const char* read_from = GetReadPointerAndAdvance(len);
106 if (!read_from)
107 return false;
108
109 result->assign(read_from, len);
110 return true;
111 }
112
113 bool PickleIterator::ReadWString(std::wstring* result) {
114 int len;
115 if (!ReadInt(&len))
116 return false;
117 const char* read_from = GetReadPointerAndAdvance(len, sizeof(wchar_t));
118 if (!read_from)
119 return false;
120
121 result->assign(reinterpret_cast<const wchar_t*>(read_from), len);
122 return true;
123 }
124
125 bool PickleIterator::ReadString16(string16* result) {
126 int len;
127 if (!ReadInt(&len))
128 return false;
129 const char* read_from = GetReadPointerAndAdvance(len, sizeof(char16));
130 if (!read_from)
131 return false;
132
133 result->assign(reinterpret_cast<const char16*>(read_from), len);
134 return true;
135 }
136
137 bool PickleIterator::ReadData(const char** data, int* length) {
138 *length = 0;
139 *data = 0;
140
141 if (!ReadInt(length))
142 return false;
143
144 return ReadBytes(data, *length);
145 }
146
147 bool PickleIterator::ReadBytes(const char** data, int length) {
148 const char* read_from = GetReadPointerAndAdvance(length);
149 if (!read_from)
150 return false;
151 *data = read_from;
152 return true;
153 }
154
18 // Payload is uint32 aligned. 155 // Payload is uint32 aligned.
19 156
20 Pickle::Pickle() 157 Pickle::Pickle()
21 : header_(NULL), 158 : header_(NULL),
22 header_size_(sizeof(Header)), 159 header_size_(sizeof(Header)),
23 capacity_(0), 160 capacity_(0),
24 variable_buffer_offset_(0) { 161 variable_buffer_offset_(0) {
25 Resize(kPayloadUnit); 162 Resize(kPayloadUnit);
26 header_->payload_size = 0; 163 header_->payload_size = 0;
27 } 164 }
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
87 header_size_ = other.header_size_; 224 header_size_ = other.header_size_;
88 } 225 }
89 bool resized = Resize(other.header_size_ + other.header_->payload_size); 226 bool resized = Resize(other.header_size_ + other.header_->payload_size);
90 CHECK(resized); // Realloc failed. 227 CHECK(resized); // Realloc failed.
91 memcpy(header_, other.header_, 228 memcpy(header_, other.header_,
92 other.header_size_ + other.header_->payload_size); 229 other.header_size_ + other.header_->payload_size);
93 variable_buffer_offset_ = other.variable_buffer_offset_; 230 variable_buffer_offset_ = other.variable_buffer_offset_;
94 return *this; 231 return *this;
95 } 232 }
96 233
97 bool Pickle::ReadBool(void** iter, bool* result) const {
98 DCHECK(iter);
99
100 int tmp;
101 if (!ReadInt(iter, &tmp))
102 return false;
103 DCHECK(0 == tmp || 1 == tmp);
104 *result = tmp ? true : false;
105 return true;
106 }
107
108 bool Pickle::ReadInt(void** iter, int* result) const {
109 DCHECK(iter);
110 if (!*iter)
111 *iter = const_cast<char*>(payload());
112
113 if (!IteratorHasRoomFor(*iter, sizeof(*result)))
114 return false;
115
116 // TODO(jar): http://crbug.com/13108 Pickle should be cleaned up, and not
117 // dependent on alignment.
118 // Next line is otherwise the same as: memcpy(result, *iter, sizeof(*result));
119 *result = *reinterpret_cast<int*>(*iter);
120
121 UpdateIter(iter, sizeof(*result));
122 return true;
123 }
124
125 bool Pickle::ReadLong(void** iter, long* result) const {
126 DCHECK(iter);
127 if (!*iter)
128 *iter = const_cast<char*>(payload());
129
130 if (!IteratorHasRoomFor(*iter, sizeof(*result)))
131 return false;
132
133 // TODO(jar): http://crbug.com/13108 Pickle should be cleaned up, and not
134 // dependent on alignment.
135 memcpy(result, *iter, sizeof(*result));
136
137 UpdateIter(iter, sizeof(*result));
138 return true;
139 }
140
141 bool Pickle::ReadSize(void** iter, size_t* result) const {
142 DCHECK(iter);
143 if (!*iter)
144 *iter = const_cast<char*>(payload());
145
146 if (!IteratorHasRoomFor(*iter, sizeof(*result)))
147 return false;
148
149 // TODO(jar): http://crbug.com/13108 Pickle should be cleaned up, and not
150 // dependent on alignment.
151 // Next line is otherwise the same as: memcpy(result, *iter, sizeof(*result));
152 *result = *reinterpret_cast<size_t*>(*iter);
153
154 UpdateIter(iter, sizeof(*result));
155 return true;
156 }
157
158 bool Pickle::ReadUInt16(void** iter, uint16* result) const {
159 DCHECK(iter);
160 if (!*iter)
161 *iter = const_cast<char*>(payload());
162
163 if (!IteratorHasRoomFor(*iter, sizeof(*result)))
164 return false;
165
166 memcpy(result, *iter, sizeof(*result));
167
168 UpdateIter(iter, sizeof(*result));
169 return true;
170 }
171
172 bool Pickle::ReadUInt32(void** iter, uint32* result) const {
173 DCHECK(iter);
174 if (!*iter)
175 *iter = const_cast<char*>(payload());
176
177 if (!IteratorHasRoomFor(*iter, sizeof(*result)))
178 return false;
179
180 memcpy(result, *iter, sizeof(*result));
181
182 UpdateIter(iter, sizeof(*result));
183 return true;
184 }
185
186 bool Pickle::ReadInt64(void** iter, int64* result) const {
187 DCHECK(iter);
188 if (!*iter)
189 *iter = const_cast<char*>(payload());
190
191 if (!IteratorHasRoomFor(*iter, sizeof(*result)))
192 return false;
193
194 memcpy(result, *iter, sizeof(*result));
195
196 UpdateIter(iter, sizeof(*result));
197 return true;
198 }
199
200 bool Pickle::ReadUInt64(void** iter, uint64* result) const {
201 DCHECK(iter);
202 if (!*iter)
203 *iter = const_cast<char*>(payload());
204
205 if (!IteratorHasRoomFor(*iter, sizeof(*result)))
206 return false;
207
208 memcpy(result, *iter, sizeof(*result));
209
210 UpdateIter(iter, sizeof(*result));
211 return true;
212 }
213
214 bool Pickle::ReadString(void** iter, std::string* result) const {
215 DCHECK(iter);
216
217 int len;
218 if (!ReadLength(iter, &len))
219 return false;
220 if (!IteratorHasRoomFor(*iter, len))
221 return false;
222
223 char* chars = reinterpret_cast<char*>(*iter);
224 result->assign(chars, len);
225
226 UpdateIter(iter, len);
227 return true;
228 }
229
230 bool Pickle::ReadWString(void** iter, std::wstring* result) const {
231 DCHECK(iter);
232
233 int len;
234 if (!ReadLength(iter, &len))
235 return false;
236 // Avoid integer overflow.
237 if (len > INT_MAX / static_cast<int>(sizeof(wchar_t)))
238 return false;
239 if (!IteratorHasRoomFor(*iter, len * sizeof(wchar_t)))
240 return false;
241
242 wchar_t* chars = reinterpret_cast<wchar_t*>(*iter);
243 result->assign(chars, len);
244
245 UpdateIter(iter, len * sizeof(wchar_t));
246 return true;
247 }
248
249 bool Pickle::ReadString16(void** iter, string16* result) const {
250 DCHECK(iter);
251
252 int len;
253 if (!ReadLength(iter, &len))
254 return false;
255 if (!IteratorHasRoomFor(*iter, len * sizeof(char16)))
256 return false;
257
258 char16* chars = reinterpret_cast<char16*>(*iter);
259 result->assign(chars, len);
260
261 UpdateIter(iter, len * sizeof(char16));
262 return true;
263 }
264
265 bool Pickle::ReadData(void** iter, const char** data, int* length) const {
266 DCHECK(iter);
267 DCHECK(data);
268 DCHECK(length);
269 *length = 0;
270 *data = 0;
271
272 if (!ReadLength(iter, length))
273 return false;
274
275 return ReadBytes(iter, data, *length);
276 }
277
278 bool Pickle::ReadBytes(void** iter, const char** data, int length) const {
279 DCHECK(iter);
280 DCHECK(data);
281 *data = 0;
282 if (!*iter)
283 *iter = const_cast<char*>(payload());
284
285 if (!IteratorHasRoomFor(*iter, length))
286 return false;
287
288 *data = reinterpret_cast<const char*>(*iter);
289
290 UpdateIter(iter, length);
291 return true;
292 }
293
294 bool Pickle::ReadLength(void** iter, int* result) const {
295 if (!ReadInt(iter, result))
296 return false;
297 return ((*result) >= 0);
298 }
299
300 bool Pickle::WriteString(const std::string& value) { 234 bool Pickle::WriteString(const std::string& value) {
301 if (!WriteInt(static_cast<int>(value.size()))) 235 if (!WriteInt(static_cast<int>(value.size())))
302 return false; 236 return false;
303 237
304 return WriteBytes(value.data(), static_cast<int>(value.size())); 238 return WriteBytes(value.data(), static_cast<int>(value.size()));
305 } 239 }
306 240
307 bool Pickle::WriteWString(const std::wstring& value) { 241 bool Pickle::WriteWString(const std::wstring& value) {
308 if (!WriteInt(static_cast<int>(value.size()))) 242 if (!WriteInt(static_cast<int>(value.size())))
309 return false; 243 return false;
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
422 return NULL; 356 return NULL;
423 357
424 const Header* hdr = reinterpret_cast<const Header*>(start); 358 const Header* hdr = reinterpret_cast<const Header*>(start);
425 const char* payload_base = start + header_size; 359 const char* payload_base = start + header_size;
426 const char* payload_end = payload_base + hdr->payload_size; 360 const char* payload_end = payload_base + hdr->payload_size;
427 if (payload_end < payload_base) 361 if (payload_end < payload_base)
428 return NULL; 362 return NULL;
429 363
430 return (payload_end > end) ? NULL : payload_end; 364 return (payload_end > end) ? NULL : payload_end;
431 } 365 }
OLDNEW
« no previous file with comments | « base/pickle.h ('k') | base/pickle_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698