OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 #include <limits> | 10 #include <limits> |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
133 return false; | 133 return false; |
134 | 134 |
135 // TODO(jar): http://crbug.com/13108 Pickle should be cleaned up, and not | 135 // TODO(jar): http://crbug.com/13108 Pickle should be cleaned up, and not |
136 // dependent on alignment. | 136 // dependent on alignment. |
137 memcpy(result, *iter, sizeof(*result)); | 137 memcpy(result, *iter, sizeof(*result)); |
138 | 138 |
139 UpdateIter(iter, sizeof(*result)); | 139 UpdateIter(iter, sizeof(*result)); |
140 return true; | 140 return true; |
141 } | 141 } |
142 | 142 |
143 bool Pickle::ReadLength(void** iter, int* result) const { | |
144 if (!ReadInt(iter, result)) | |
145 return false; | |
146 return ((*result) >= 0); | |
147 } | |
148 | |
149 bool Pickle::ReadSize(void** iter, size_t* result) const { | 143 bool Pickle::ReadSize(void** iter, size_t* result) const { |
150 DCHECK(iter); | 144 DCHECK(iter); |
151 if (!*iter) | 145 if (!*iter) |
152 *iter = const_cast<char*>(payload()); | 146 *iter = const_cast<char*>(payload()); |
153 | 147 |
154 if (!IteratorHasRoomFor(*iter, sizeof(*result))) | 148 if (!IteratorHasRoomFor(*iter, sizeof(*result))) |
155 return false; | 149 return false; |
156 | 150 |
157 // TODO(jar): http://crbug.com/13108 Pickle should be cleaned up, and not | 151 // TODO(jar): http://crbug.com/13108 Pickle should be cleaned up, and not |
158 // dependent on alignment. | 152 // dependent on alignment. |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
249 if (!IteratorHasRoomFor(*iter, len * sizeof(char16))) | 243 if (!IteratorHasRoomFor(*iter, len * sizeof(char16))) |
250 return false; | 244 return false; |
251 | 245 |
252 char16* chars = reinterpret_cast<char16*>(*iter); | 246 char16* chars = reinterpret_cast<char16*>(*iter); |
253 result->assign(chars, len); | 247 result->assign(chars, len); |
254 | 248 |
255 UpdateIter(iter, len * sizeof(char16)); | 249 UpdateIter(iter, len * sizeof(char16)); |
256 return true; | 250 return true; |
257 } | 251 } |
258 | 252 |
259 bool Pickle::ReadBytes(void** iter, const char** data, int length) const { | |
260 DCHECK(iter); | |
261 DCHECK(data); | |
262 *data = 0; | |
263 if (!*iter) | |
264 *iter = const_cast<char*>(payload()); | |
265 | |
266 if (!IteratorHasRoomFor(*iter, length)) | |
267 return false; | |
268 | |
269 *data = reinterpret_cast<const char*>(*iter); | |
270 | |
271 UpdateIter(iter, length); | |
272 return true; | |
273 } | |
274 | |
275 bool Pickle::ReadData(void** iter, const char** data, int* length) const { | 253 bool Pickle::ReadData(void** iter, const char** data, int* length) const { |
276 DCHECK(iter); | 254 DCHECK(iter); |
277 DCHECK(data); | 255 DCHECK(data); |
278 DCHECK(length); | 256 DCHECK(length); |
279 *length = 0; | 257 *length = 0; |
280 *data = 0; | 258 *data = 0; |
281 | 259 |
282 if (!ReadLength(iter, length)) | 260 if (!ReadLength(iter, length)) |
283 return false; | 261 return false; |
284 | 262 |
285 return ReadBytes(iter, data, *length); | 263 return ReadBytes(iter, data, *length); |
286 } | 264 } |
287 | 265 |
288 char* Pickle::BeginWrite(size_t length) { | 266 bool Pickle::ReadBytes(void** iter, const char** data, int length) const { |
289 // write at a uint32-aligned offset from the beginning of the header | 267 DCHECK(iter); |
290 size_t offset = AlignInt(header_->payload_size, sizeof(uint32)); | 268 DCHECK(data); |
| 269 *data = 0; |
| 270 if (!*iter) |
| 271 *iter = const_cast<char*>(payload()); |
291 | 272 |
292 size_t new_size = offset + length; | 273 if (!IteratorHasRoomFor(*iter, length)) |
293 size_t needed_size = header_size_ + new_size; | |
294 if (needed_size > capacity_ && !Resize(std::max(capacity_ * 2, needed_size))) | |
295 return NULL; | |
296 | |
297 #ifdef ARCH_CPU_64_BITS | |
298 DCHECK_LE(length, std::numeric_limits<uint32>::max()); | |
299 #endif | |
300 | |
301 header_->payload_size = static_cast<uint32>(new_size); | |
302 return payload() + offset; | |
303 } | |
304 | |
305 void Pickle::EndWrite(char* dest, int length) { | |
306 // Zero-pad to keep tools like purify from complaining about uninitialized | |
307 // memory. | |
308 if (length % sizeof(uint32)) | |
309 memset(dest + length, 0, sizeof(uint32) - (length % sizeof(uint32))); | |
310 } | |
311 | |
312 bool Pickle::WriteBytes(const void* data, int data_len) { | |
313 DCHECK(capacity_ != kCapacityReadOnly) << "oops: pickle is readonly"; | |
314 | |
315 char* dest = BeginWrite(data_len); | |
316 if (!dest) | |
317 return false; | 274 return false; |
318 | 275 |
319 memcpy(dest, data, data_len); | 276 *data = reinterpret_cast<const char*>(*iter); |
320 | 277 |
321 EndWrite(dest, data_len); | 278 UpdateIter(iter, length); |
322 return true; | 279 return true; |
323 } | 280 } |
324 | 281 |
| 282 bool Pickle::ReadLength(void** iter, int* result) const { |
| 283 if (!ReadInt(iter, result)) |
| 284 return false; |
| 285 return ((*result) >= 0); |
| 286 } |
| 287 |
325 bool Pickle::WriteString(const std::string& value) { | 288 bool Pickle::WriteString(const std::string& value) { |
326 if (!WriteInt(static_cast<int>(value.size()))) | 289 if (!WriteInt(static_cast<int>(value.size()))) |
327 return false; | 290 return false; |
328 | 291 |
329 return WriteBytes(value.data(), static_cast<int>(value.size())); | 292 return WriteBytes(value.data(), static_cast<int>(value.size())); |
330 } | 293 } |
331 | 294 |
332 bool Pickle::WriteWString(const std::wstring& value) { | 295 bool Pickle::WriteWString(const std::wstring& value) { |
333 if (!WriteInt(static_cast<int>(value.size()))) | 296 if (!WriteInt(static_cast<int>(value.size()))) |
334 return false; | 297 return false; |
335 | 298 |
336 return WriteBytes(value.data(), | 299 return WriteBytes(value.data(), |
337 static_cast<int>(value.size() * sizeof(wchar_t))); | 300 static_cast<int>(value.size() * sizeof(wchar_t))); |
338 } | 301 } |
339 | 302 |
340 bool Pickle::WriteString16(const string16& value) { | 303 bool Pickle::WriteString16(const string16& value) { |
341 if (!WriteInt(static_cast<int>(value.size()))) | 304 if (!WriteInt(static_cast<int>(value.size()))) |
342 return false; | 305 return false; |
343 | 306 |
344 return WriteBytes(value.data(), | 307 return WriteBytes(value.data(), |
345 static_cast<int>(value.size()) * sizeof(char16)); | 308 static_cast<int>(value.size()) * sizeof(char16)); |
346 } | 309 } |
347 | 310 |
348 bool Pickle::WriteData(const char* data, int length) { | 311 bool Pickle::WriteData(const char* data, int length) { |
349 return length >= 0 && WriteInt(length) && WriteBytes(data, length); | 312 return length >= 0 && WriteInt(length) && WriteBytes(data, length); |
350 } | 313 } |
351 | 314 |
| 315 bool Pickle::WriteBytes(const void* data, int data_len) { |
| 316 DCHECK(capacity_ != kCapacityReadOnly) << "oops: pickle is readonly"; |
| 317 |
| 318 char* dest = BeginWrite(data_len); |
| 319 if (!dest) |
| 320 return false; |
| 321 |
| 322 memcpy(dest, data, data_len); |
| 323 |
| 324 EndWrite(dest, data_len); |
| 325 return true; |
| 326 } |
| 327 |
352 char* Pickle::BeginWriteData(int length) { | 328 char* Pickle::BeginWriteData(int length) { |
353 DCHECK_EQ(variable_buffer_offset_, 0U) << | 329 DCHECK_EQ(variable_buffer_offset_, 0U) << |
354 "There can only be one variable buffer in a Pickle"; | 330 "There can only be one variable buffer in a Pickle"; |
355 | 331 |
356 if (length < 0 || !WriteInt(length)) | 332 if (length < 0 || !WriteInt(length)) |
357 return NULL; | 333 return NULL; |
358 | 334 |
359 char *data_ptr = BeginWrite(length); | 335 char *data_ptr = BeginWrite(length); |
360 if (!data_ptr) | 336 if (!data_ptr) |
361 return NULL; | 337 return NULL; |
(...skipping 17 matching lines...) Expand all Loading... |
379 if (new_length < 0 || new_length > *cur_length) { | 355 if (new_length < 0 || new_length > *cur_length) { |
380 NOTREACHED() << "Invalid length in TrimWriteData."; | 356 NOTREACHED() << "Invalid length in TrimWriteData."; |
381 return; | 357 return; |
382 } | 358 } |
383 | 359 |
384 // Update the payload size and variable buffer size | 360 // Update the payload size and variable buffer size |
385 header_->payload_size -= (*cur_length - new_length); | 361 header_->payload_size -= (*cur_length - new_length); |
386 *cur_length = new_length; | 362 *cur_length = new_length; |
387 } | 363 } |
388 | 364 |
| 365 char* Pickle::BeginWrite(size_t length) { |
| 366 // write at a uint32-aligned offset from the beginning of the header |
| 367 size_t offset = AlignInt(header_->payload_size, sizeof(uint32)); |
| 368 |
| 369 size_t new_size = offset + length; |
| 370 size_t needed_size = header_size_ + new_size; |
| 371 if (needed_size > capacity_ && !Resize(std::max(capacity_ * 2, needed_size))) |
| 372 return NULL; |
| 373 |
| 374 #ifdef ARCH_CPU_64_BITS |
| 375 DCHECK_LE(length, std::numeric_limits<uint32>::max()); |
| 376 #endif |
| 377 |
| 378 header_->payload_size = static_cast<uint32>(new_size); |
| 379 return payload() + offset; |
| 380 } |
| 381 |
| 382 void Pickle::EndWrite(char* dest, int length) { |
| 383 // Zero-pad to keep tools like purify from complaining about uninitialized |
| 384 // memory. |
| 385 if (length % sizeof(uint32)) |
| 386 memset(dest + length, 0, sizeof(uint32) - (length % sizeof(uint32))); |
| 387 } |
| 388 |
389 bool Pickle::Resize(size_t new_capacity) { | 389 bool Pickle::Resize(size_t new_capacity) { |
390 new_capacity = AlignInt(new_capacity, kPayloadUnit); | 390 new_capacity = AlignInt(new_capacity, kPayloadUnit); |
391 | 391 |
392 CHECK_NE(capacity_, kCapacityReadOnly); | 392 CHECK_NE(capacity_, kCapacityReadOnly); |
393 void* p = realloc(header_, new_capacity); | 393 void* p = realloc(header_, new_capacity); |
394 if (!p) | 394 if (!p) |
395 return false; | 395 return false; |
396 | 396 |
397 header_ = reinterpret_cast<Header*>(p); | 397 header_ = reinterpret_cast<Header*>(p); |
398 capacity_ = new_capacity; | 398 capacity_ = new_capacity; |
399 return true; | 399 return true; |
400 } | 400 } |
401 | 401 |
402 // static | 402 // static |
403 const char* Pickle::FindNext(size_t header_size, | 403 const char* Pickle::FindNext(size_t header_size, |
404 const char* start, | 404 const char* start, |
405 const char* end) { | 405 const char* end) { |
406 DCHECK(header_size == AlignInt(header_size, sizeof(uint32))); | 406 DCHECK(header_size == AlignInt(header_size, sizeof(uint32))); |
407 DCHECK(header_size <= static_cast<size_t>(kPayloadUnit)); | 407 DCHECK(header_size <= static_cast<size_t>(kPayloadUnit)); |
408 | 408 |
409 const Header* hdr = reinterpret_cast<const Header*>(start); | 409 const Header* hdr = reinterpret_cast<const Header*>(start); |
410 const char* payload_base = start + header_size; | 410 const char* payload_base = start + header_size; |
411 const char* payload_end = payload_base + hdr->payload_size; | 411 const char* payload_end = payload_base + hdr->payload_size; |
412 if (payload_end < payload_base) | 412 if (payload_end < payload_base) |
413 return NULL; | 413 return NULL; |
414 | 414 |
415 return (payload_end > end) ? NULL : payload_end; | 415 return (payload_end > end) ? NULL : payload_end; |
416 } | 416 } |
OLD | NEW |