| 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 |