1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipc/chromium/src/base/pickle.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,640 @@ 1.4 +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1.5 +// Use of this source code is governed by a BSD-style license that can be 1.6 +// found in the LICENSE file. 1.7 + 1.8 +#include "base/pickle.h" 1.9 + 1.10 +#include "mozilla/Alignment.h" 1.11 +#include "mozilla/Endian.h" 1.12 +#include "mozilla/TypeTraits.h" 1.13 + 1.14 +#include <stdlib.h> 1.15 + 1.16 +#include <limits> 1.17 +#include <string> 1.18 +#include <algorithm> 1.19 + 1.20 +#include "nsDebug.h" 1.21 + 1.22 +//------------------------------------------------------------------------------ 1.23 + 1.24 +static_assert(MOZ_ALIGNOF(Pickle::memberAlignmentType) >= MOZ_ALIGNOF(uint32_t), 1.25 + "Insufficient alignment"); 1.26 + 1.27 +// static 1.28 +const int Pickle::kPayloadUnit = 64; 1.29 + 1.30 +// We mark a read only pickle with a special capacity_. 1.31 +static const uint32_t kCapacityReadOnly = (uint32_t) -1; 1.32 + 1.33 +static const char kBytePaddingMarker = char(0xbf); 1.34 + 1.35 +namespace { 1.36 + 1.37 +// We want to copy data to our payload as efficiently as possible. 1.38 +// memcpy fits the bill for copying, but not all compilers or 1.39 +// architectures support inlining memcpy from void*, which has unknown 1.40 +// static alignment. However, we know that all the members of our 1.41 +// payload will be aligned on memberAlignmentType boundaries. We 1.42 +// therefore use that knowledge to construct a copier that will copy 1.43 +// efficiently (via standard C++ assignment mechanisms) if the datatype 1.44 +// needs that alignment or less, and memcpy otherwise. (The compiler 1.45 +// may still inline memcpy, of course.) 1.46 + 1.47 +template<typename T, size_t size, bool hasSufficientAlignment> 1.48 +struct Copier 1.49 +{ 1.50 + static void Copy(T* dest, void** iter) { 1.51 + memcpy(dest, *iter, sizeof(T)); 1.52 + } 1.53 +}; 1.54 + 1.55 +// Copying 64-bit quantities happens often enough and can easily be made 1.56 +// worthwhile on 32-bit platforms, so handle it specially. Only do it 1.57 +// if 64-bit types aren't sufficiently aligned; the alignment 1.58 +// requirements for them vary between 32-bit platforms. 1.59 +#ifndef HAVE_64BIT_OS 1.60 +template<typename T> 1.61 +struct Copier<T, sizeof(uint64_t), false> 1.62 +{ 1.63 + static void Copy(T* dest, void** iter) { 1.64 +#if MOZ_LITTLE_ENDIAN 1.65 + static const int loIndex = 0, hiIndex = 1; 1.66 +#else 1.67 + static const int loIndex = 1, hiIndex = 0; 1.68 +#endif 1.69 + static_assert(MOZ_ALIGNOF(uint32_t*) == MOZ_ALIGNOF(void*), 1.70 + "Pointers have different alignments"); 1.71 + uint32_t* src = *reinterpret_cast<uint32_t**>(iter); 1.72 + uint32_t* uint32dest = reinterpret_cast<uint32_t*>(dest); 1.73 + uint32dest[loIndex] = src[loIndex]; 1.74 + uint32dest[hiIndex] = src[hiIndex]; 1.75 + } 1.76 +}; 1.77 +#endif 1.78 + 1.79 +template<typename T, size_t size> 1.80 +struct Copier<T, size, true> 1.81 +{ 1.82 + static void Copy(T* dest, void** iter) { 1.83 + // The reinterpret_cast is only safe if two conditions hold: 1.84 + // (1) If the alignment of T* is the same as void*; 1.85 + // (2) The alignment of the data in *iter is at least as 1.86 + // big as MOZ_ALIGNOF(T). 1.87 + // Check the first condition, as the second condition is already 1.88 + // known to be true, or we wouldn't be here. 1.89 + static_assert(MOZ_ALIGNOF(T*) == MOZ_ALIGNOF(void*), 1.90 + "Pointers have different alignments"); 1.91 + *dest = *(*reinterpret_cast<T**>(iter)); 1.92 + } 1.93 +}; 1.94 + 1.95 +template<typename T> 1.96 +void CopyFromIter(T* dest, void** iter) { 1.97 + static_assert(mozilla::IsPod<T>::value, "Copied type must be a POD type"); 1.98 + Copier<T, sizeof(T), (MOZ_ALIGNOF(T) <= sizeof(Pickle::memberAlignmentType))>::Copy(dest, iter); 1.99 +} 1.100 + 1.101 +} // anonymous namespace 1.102 + 1.103 +// Payload is sizeof(Pickle::memberAlignmentType) aligned. 1.104 + 1.105 +Pickle::Pickle() 1.106 + : header_(NULL), 1.107 + header_size_(sizeof(Header)), 1.108 + capacity_(0), 1.109 + variable_buffer_offset_(0) { 1.110 + Resize(kPayloadUnit); 1.111 + header_->payload_size = 0; 1.112 +} 1.113 + 1.114 +Pickle::Pickle(int header_size) 1.115 + : header_(NULL), 1.116 + header_size_(AlignInt(header_size)), 1.117 + capacity_(0), 1.118 + variable_buffer_offset_(0) { 1.119 + DCHECK(static_cast<memberAlignmentType>(header_size) >= sizeof(Header)); 1.120 + DCHECK(header_size <= kPayloadUnit); 1.121 + Resize(kPayloadUnit); 1.122 + if (!header_) { 1.123 + NS_ABORT_OOM(kPayloadUnit); 1.124 + } 1.125 + header_->payload_size = 0; 1.126 +} 1.127 + 1.128 +Pickle::Pickle(const char* data, int data_len) 1.129 + : header_(reinterpret_cast<Header*>(const_cast<char*>(data))), 1.130 + header_size_(data_len - header_->payload_size), 1.131 + capacity_(kCapacityReadOnly), 1.132 + variable_buffer_offset_(0) { 1.133 + DCHECK(header_size_ >= sizeof(Header)); 1.134 + DCHECK(header_size_ == AlignInt(header_size_)); 1.135 +} 1.136 + 1.137 +Pickle::Pickle(const Pickle& other) 1.138 + : header_(NULL), 1.139 + header_size_(other.header_size_), 1.140 + capacity_(0), 1.141 + variable_buffer_offset_(other.variable_buffer_offset_) { 1.142 + uint32_t payload_size = header_size_ + other.header_->payload_size; 1.143 + bool resized = Resize(payload_size); 1.144 + if (!resized) { 1.145 + NS_ABORT_OOM(payload_size); 1.146 + } 1.147 + memcpy(header_, other.header_, payload_size); 1.148 +} 1.149 + 1.150 +Pickle::~Pickle() { 1.151 + if (capacity_ != kCapacityReadOnly) 1.152 + free(header_); 1.153 +} 1.154 + 1.155 +Pickle& Pickle::operator=(const Pickle& other) { 1.156 + if (header_size_ != other.header_size_ && capacity_ != kCapacityReadOnly) { 1.157 + free(header_); 1.158 + header_ = NULL; 1.159 + header_size_ = other.header_size_; 1.160 + } 1.161 + bool resized = Resize(other.header_size_ + other.header_->payload_size); 1.162 + if (!resized) { 1.163 + NS_ABORT_OOM(other.header_size_ + other.header_->payload_size); 1.164 + } 1.165 + memcpy(header_, other.header_, header_size_ + other.header_->payload_size); 1.166 + variable_buffer_offset_ = other.variable_buffer_offset_; 1.167 + return *this; 1.168 +} 1.169 + 1.170 +bool Pickle::ReadBool(void** iter, bool* result) const { 1.171 + DCHECK(iter); 1.172 + 1.173 + int tmp; 1.174 + if (!ReadInt(iter, &tmp)) 1.175 + return false; 1.176 + DCHECK(0 == tmp || 1 == tmp); 1.177 + *result = tmp ? true : false; 1.178 + return true; 1.179 +} 1.180 + 1.181 +bool Pickle::ReadInt16(void** iter, int16_t* result) const { 1.182 + DCHECK(iter); 1.183 + if (!*iter) 1.184 + *iter = const_cast<char*>(payload()); 1.185 + 1.186 + if (!IteratorHasRoomFor(*iter, sizeof(*result))) 1.187 + return false; 1.188 + 1.189 + CopyFromIter(result, iter); 1.190 + 1.191 + UpdateIter(iter, sizeof(*result)); 1.192 + return true; 1.193 +} 1.194 + 1.195 +bool Pickle::ReadUInt16(void** iter, uint16_t* result) const { 1.196 + DCHECK(iter); 1.197 + if (!*iter) 1.198 + *iter = const_cast<char*>(payload()); 1.199 + 1.200 + if (!IteratorHasRoomFor(*iter, sizeof(*result))) 1.201 + return false; 1.202 + 1.203 + CopyFromIter(result, iter); 1.204 + 1.205 + UpdateIter(iter, sizeof(*result)); 1.206 + return true; 1.207 +} 1.208 + 1.209 +bool Pickle::ReadInt(void** iter, int* result) const { 1.210 + DCHECK(iter); 1.211 + if (!*iter) 1.212 + *iter = const_cast<char*>(payload()); 1.213 + 1.214 + if (!IteratorHasRoomFor(*iter, sizeof(*result))) 1.215 + return false; 1.216 + 1.217 + CopyFromIter(result, iter); 1.218 + 1.219 + UpdateIter(iter, sizeof(*result)); 1.220 + return true; 1.221 +} 1.222 + 1.223 +// Always written as a 64-bit value since the size for this type can 1.224 +// differ between architectures. 1.225 +bool Pickle::ReadLong(void** iter, long* result) const { 1.226 + DCHECK(iter); 1.227 + if (!*iter) 1.228 + *iter = const_cast<char*>(payload()); 1.229 + 1.230 + int64_t bigResult = 0; 1.231 + if (!IteratorHasRoomFor(*iter, sizeof(bigResult))) 1.232 + return false; 1.233 + 1.234 + CopyFromIter(&bigResult, iter); 1.235 + DCHECK(bigResult <= LONG_MAX && bigResult >= LONG_MIN); 1.236 + *result = static_cast<long>(bigResult); 1.237 + 1.238 + UpdateIter(iter, sizeof(bigResult)); 1.239 + return true; 1.240 +} 1.241 + 1.242 +// Always written as a 64-bit value since the size for this type can 1.243 +// differ between architectures. 1.244 +bool Pickle::ReadULong(void** iter, unsigned long* result) const { 1.245 + DCHECK(iter); 1.246 + if (!*iter) 1.247 + *iter = const_cast<char*>(payload()); 1.248 + 1.249 + uint64_t bigResult = 0; 1.250 + if (!IteratorHasRoomFor(*iter, sizeof(bigResult))) 1.251 + return false; 1.252 + 1.253 + CopyFromIter(&bigResult, iter); 1.254 + DCHECK(bigResult <= ULONG_MAX); 1.255 + *result = static_cast<unsigned long>(bigResult); 1.256 + 1.257 + UpdateIter(iter, sizeof(bigResult)); 1.258 + return true; 1.259 +} 1.260 + 1.261 +bool Pickle::ReadLength(void** iter, int* result) const { 1.262 + if (!ReadInt(iter, result)) 1.263 + return false; 1.264 + return ((*result) >= 0); 1.265 +} 1.266 + 1.267 +// Always written as a 64-bit value since the size for this type can 1.268 +// differ between architectures. 1.269 +bool Pickle::ReadSize(void** iter, size_t* result) const { 1.270 + DCHECK(iter); 1.271 + if (!*iter) 1.272 + *iter = const_cast<char*>(payload()); 1.273 + 1.274 + uint64_t bigResult = 0; 1.275 + if (!IteratorHasRoomFor(*iter, sizeof(bigResult))) 1.276 + return false; 1.277 + 1.278 + CopyFromIter(&bigResult, iter); 1.279 + DCHECK(bigResult <= std::numeric_limits<size_t>::max()); 1.280 + *result = static_cast<size_t>(bigResult); 1.281 + 1.282 + UpdateIter(iter, sizeof(bigResult)); 1.283 + return true; 1.284 +} 1.285 + 1.286 +bool Pickle::ReadInt32(void** iter, int32_t* result) const { 1.287 + DCHECK(iter); 1.288 + if (!*iter) 1.289 + *iter = const_cast<char*>(payload()); 1.290 + 1.291 + if (!IteratorHasRoomFor(*iter, sizeof(*result))) 1.292 + return false; 1.293 + 1.294 + CopyFromIter(result, iter); 1.295 + 1.296 + UpdateIter(iter, sizeof(*result)); 1.297 + return true; 1.298 +} 1.299 + 1.300 +bool Pickle::ReadUInt32(void** iter, uint32_t* result) const { 1.301 + DCHECK(iter); 1.302 + if (!*iter) 1.303 + *iter = const_cast<char*>(payload()); 1.304 + 1.305 + if (!IteratorHasRoomFor(*iter, sizeof(*result))) 1.306 + return false; 1.307 + 1.308 + CopyFromIter(result, iter); 1.309 + 1.310 + UpdateIter(iter, sizeof(*result)); 1.311 + return true; 1.312 +} 1.313 + 1.314 +bool Pickle::ReadInt64(void** iter, int64_t* result) const { 1.315 + DCHECK(iter); 1.316 + if (!*iter) 1.317 + *iter = const_cast<char*>(payload()); 1.318 + 1.319 + if (!IteratorHasRoomFor(*iter, sizeof(*result))) 1.320 + return false; 1.321 + 1.322 + CopyFromIter(result, iter); 1.323 + 1.324 + UpdateIter(iter, sizeof(*result)); 1.325 + return true; 1.326 +} 1.327 + 1.328 +bool Pickle::ReadUInt64(void** iter, uint64_t* result) const { 1.329 + DCHECK(iter); 1.330 + if (!*iter) 1.331 + *iter = const_cast<char*>(payload()); 1.332 + 1.333 + if (!IteratorHasRoomFor(*iter, sizeof(*result))) 1.334 + return false; 1.335 + 1.336 + CopyFromIter(result, iter); 1.337 + 1.338 + UpdateIter(iter, sizeof(*result)); 1.339 + return true; 1.340 +} 1.341 + 1.342 +bool Pickle::ReadDouble(void** iter, double* result) const { 1.343 + DCHECK(iter); 1.344 + if (!*iter) 1.345 + *iter = const_cast<char*>(payload()); 1.346 + 1.347 + if (!IteratorHasRoomFor(*iter, sizeof(*result))) 1.348 + return false; 1.349 + 1.350 + CopyFromIter(result, iter); 1.351 + 1.352 + UpdateIter(iter, sizeof(*result)); 1.353 + return true; 1.354 +} 1.355 + 1.356 +// Always written as a 64-bit value since the size for this type can 1.357 +// differ between architectures. 1.358 +bool Pickle::ReadIntPtr(void** iter, intptr_t* result) const { 1.359 + DCHECK(iter); 1.360 + if (!*iter) 1.361 + *iter = const_cast<char*>(payload()); 1.362 + 1.363 + int64_t bigResult = 0; 1.364 + if (!IteratorHasRoomFor(*iter, sizeof(bigResult))) 1.365 + return false; 1.366 + 1.367 + CopyFromIter(&bigResult, iter); 1.368 + DCHECK(bigResult <= std::numeric_limits<intptr_t>::max() && bigResult >= std::numeric_limits<intptr_t>::min()); 1.369 + *result = static_cast<intptr_t>(bigResult); 1.370 + 1.371 + UpdateIter(iter, sizeof(bigResult)); 1.372 + return true; 1.373 +} 1.374 + 1.375 +bool Pickle::ReadUnsignedChar(void** iter, unsigned char* result) const { 1.376 + DCHECK(iter); 1.377 + if (!*iter) 1.378 + *iter = const_cast<char*>(payload()); 1.379 + 1.380 + if (!IteratorHasRoomFor(*iter, sizeof(*result))) 1.381 + return false; 1.382 + 1.383 + CopyFromIter(result, iter); 1.384 + 1.385 + UpdateIter(iter, sizeof(*result)); 1.386 + return true; 1.387 +} 1.388 + 1.389 +bool Pickle::ReadString(void** iter, std::string* result) const { 1.390 + DCHECK(iter); 1.391 + if (!*iter) 1.392 + *iter = const_cast<char*>(payload()); 1.393 + 1.394 + int len; 1.395 + if (!ReadLength(iter, &len)) 1.396 + return false; 1.397 + if (!IteratorHasRoomFor(*iter, len)) 1.398 + return false; 1.399 + 1.400 + char* chars = reinterpret_cast<char*>(*iter); 1.401 + result->assign(chars, len); 1.402 + 1.403 + UpdateIter(iter, len); 1.404 + return true; 1.405 +} 1.406 + 1.407 +bool Pickle::ReadWString(void** iter, std::wstring* result) const { 1.408 + DCHECK(iter); 1.409 + if (!*iter) 1.410 + *iter = const_cast<char*>(payload()); 1.411 + 1.412 + int len; 1.413 + if (!ReadLength(iter, &len)) 1.414 + return false; 1.415 + if (!IteratorHasRoomFor(*iter, len * sizeof(wchar_t))) 1.416 + return false; 1.417 + 1.418 + wchar_t* chars = reinterpret_cast<wchar_t*>(*iter); 1.419 + result->assign(chars, len); 1.420 + 1.421 + UpdateIter(iter, len * sizeof(wchar_t)); 1.422 + return true; 1.423 +} 1.424 + 1.425 +bool Pickle::ReadString16(void** iter, string16* result) const { 1.426 + DCHECK(iter); 1.427 + if (!*iter) 1.428 + *iter = const_cast<char*>(payload()); 1.429 + 1.430 + int len; 1.431 + if (!ReadLength(iter, &len)) 1.432 + return false; 1.433 + if (!IteratorHasRoomFor(*iter, len)) 1.434 + return false; 1.435 + 1.436 + char16* chars = reinterpret_cast<char16*>(*iter); 1.437 + result->assign(chars, len); 1.438 + 1.439 + UpdateIter(iter, len * sizeof(char16)); 1.440 + return true; 1.441 +} 1.442 + 1.443 +bool Pickle::ReadBytes(void** iter, const char** data, int length, 1.444 + uint32_t alignment) const { 1.445 + DCHECK(iter); 1.446 + DCHECK(data); 1.447 + DCHECK(alignment == 4 || alignment == 8); 1.448 + DCHECK(intptr_t(header_) % alignment == 0); 1.449 + 1.450 + if (!*iter) 1.451 + *iter = const_cast<char*>(payload()); 1.452 + 1.453 + uint32_t paddingLen = intptr_t(*iter) % alignment; 1.454 + if (paddingLen) { 1.455 +#ifdef DEBUG 1.456 + { 1.457 + const char* padding = static_cast<const char*>(*iter); 1.458 + for (uint32_t i = 0; i < paddingLen; i++) { 1.459 + DCHECK(*(padding + i) == kBytePaddingMarker); 1.460 + } 1.461 + } 1.462 +#endif 1.463 + length += paddingLen; 1.464 + } 1.465 + 1.466 + if (!IteratorHasRoomFor(*iter, length)) 1.467 + return false; 1.468 + 1.469 + *data = static_cast<const char*>(*iter) + paddingLen; 1.470 + DCHECK(intptr_t(*data) % alignment == 0); 1.471 + 1.472 + UpdateIter(iter, length); 1.473 + return true; 1.474 +} 1.475 + 1.476 +bool Pickle::ReadData(void** iter, const char** data, int* length) const { 1.477 + DCHECK(iter); 1.478 + DCHECK(data); 1.479 + DCHECK(length); 1.480 + if (!*iter) 1.481 + *iter = const_cast<char*>(payload()); 1.482 + 1.483 + if (!ReadLength(iter, length)) 1.484 + return false; 1.485 + 1.486 + return ReadBytes(iter, data, *length); 1.487 +} 1.488 + 1.489 +char* Pickle::BeginWrite(uint32_t length, uint32_t alignment) { 1.490 + DCHECK(alignment % 4 == 0) << "Must be at least 32-bit aligned!"; 1.491 + 1.492 + // write at an alignment-aligned offset from the beginning of the header 1.493 + uint32_t offset = AlignInt(header_->payload_size); 1.494 + uint32_t padding = (header_size_ + offset) % alignment; 1.495 + uint32_t new_size = offset + padding + AlignInt(length); 1.496 + uint32_t needed_size = header_size_ + new_size; 1.497 + 1.498 + if (needed_size > capacity_ && !Resize(std::max(capacity_ * 2, needed_size))) 1.499 + return NULL; 1.500 + 1.501 + DCHECK(intptr_t(header_) % alignment == 0); 1.502 + 1.503 +#ifdef ARCH_CPU_64_BITS 1.504 + DCHECK_LE(length, std::numeric_limits<uint32_t>::max()); 1.505 +#endif 1.506 + 1.507 + char* buffer = payload() + offset; 1.508 + 1.509 + if (padding) { 1.510 + memset(buffer, kBytePaddingMarker, padding); 1.511 + buffer += padding; 1.512 + } 1.513 + 1.514 + DCHECK(intptr_t(buffer) % alignment == 0); 1.515 + 1.516 + header_->payload_size = new_size; 1.517 + 1.518 +#ifdef MOZ_VALGRIND 1.519 + // pad the trailing end as well, so that valgrind 1.520 + // doesn't complain when we write the buffer 1.521 + padding = AlignInt(length) - length; 1.522 + if (padding) { 1.523 + memset(buffer + length, kBytePaddingMarker, padding); 1.524 + } 1.525 +#endif 1.526 + 1.527 + return buffer; 1.528 +} 1.529 + 1.530 +void Pickle::EndWrite(char* dest, int length) { 1.531 + // Zero-pad to keep tools like purify from complaining about uninitialized 1.532 + // memory. 1.533 + if (length % sizeof(memberAlignmentType)) 1.534 + memset(dest + length, 0, 1.535 + sizeof(memberAlignmentType) - (length % sizeof(memberAlignmentType))); 1.536 +} 1.537 + 1.538 +bool Pickle::WriteBytes(const void* data, int data_len, uint32_t alignment) { 1.539 + DCHECK(capacity_ != kCapacityReadOnly) << "oops: pickle is readonly"; 1.540 + DCHECK(alignment == 4 || alignment == 8); 1.541 + DCHECK(intptr_t(header_) % alignment == 0); 1.542 + 1.543 + char* dest = BeginWrite(data_len, alignment); 1.544 + if (!dest) 1.545 + return false; 1.546 + 1.547 + memcpy(dest, data, data_len); 1.548 + 1.549 + EndWrite(dest, data_len); 1.550 + return true; 1.551 +} 1.552 + 1.553 +bool Pickle::WriteString(const std::string& value) { 1.554 + if (!WriteInt(static_cast<int>(value.size()))) 1.555 + return false; 1.556 + 1.557 + return WriteBytes(value.data(), static_cast<int>(value.size())); 1.558 +} 1.559 + 1.560 +bool Pickle::WriteWString(const std::wstring& value) { 1.561 + if (!WriteInt(static_cast<int>(value.size()))) 1.562 + return false; 1.563 + 1.564 + return WriteBytes(value.data(), 1.565 + static_cast<int>(value.size() * sizeof(wchar_t))); 1.566 +} 1.567 + 1.568 +bool Pickle::WriteString16(const string16& value) { 1.569 + if (!WriteInt(static_cast<int>(value.size()))) 1.570 + return false; 1.571 + 1.572 + return WriteBytes(value.data(), 1.573 + static_cast<int>(value.size()) * sizeof(char16)); 1.574 +} 1.575 + 1.576 +bool Pickle::WriteData(const char* data, int length) { 1.577 + return WriteInt(length) && WriteBytes(data, length); 1.578 +} 1.579 + 1.580 +char* Pickle::BeginWriteData(int length) { 1.581 + DCHECK_EQ(variable_buffer_offset_, 0U) << 1.582 + "There can only be one variable buffer in a Pickle"; 1.583 + 1.584 + if (!WriteInt(length)) 1.585 + return NULL; 1.586 + 1.587 + char *data_ptr = BeginWrite(length, sizeof(memberAlignmentType)); 1.588 + if (!data_ptr) 1.589 + return NULL; 1.590 + 1.591 + variable_buffer_offset_ = 1.592 + data_ptr - reinterpret_cast<char*>(header_) - sizeof(int); 1.593 + 1.594 + // EndWrite doesn't necessarily have to be called after the write operation, 1.595 + // so we call it here to pad out what the caller will eventually write. 1.596 + EndWrite(data_ptr, length); 1.597 + return data_ptr; 1.598 +} 1.599 + 1.600 +void Pickle::TrimWriteData(int new_length) { 1.601 + DCHECK(variable_buffer_offset_ != 0); 1.602 + 1.603 + // Fetch the the variable buffer size 1.604 + int* cur_length = reinterpret_cast<int*>( 1.605 + reinterpret_cast<char*>(header_) + variable_buffer_offset_); 1.606 + 1.607 + if (new_length < 0 || new_length > *cur_length) { 1.608 + NOTREACHED() << "Invalid length in TrimWriteData."; 1.609 + return; 1.610 + } 1.611 + 1.612 + // Update the payload size and variable buffer size 1.613 + header_->payload_size -= (*cur_length - new_length); 1.614 + *cur_length = new_length; 1.615 +} 1.616 + 1.617 +bool Pickle::Resize(uint32_t new_capacity) { 1.618 + new_capacity = ConstantAligner<kPayloadUnit>::align(new_capacity); 1.619 + 1.620 + void* p = realloc(header_, new_capacity); 1.621 + if (!p) 1.622 + return false; 1.623 + 1.624 + header_ = reinterpret_cast<Header*>(p); 1.625 + capacity_ = new_capacity; 1.626 + return true; 1.627 +} 1.628 + 1.629 +// static 1.630 +const char* Pickle::FindNext(uint32_t header_size, 1.631 + const char* start, 1.632 + const char* end) { 1.633 + DCHECK(header_size == AlignInt(header_size)); 1.634 + DCHECK(header_size <= static_cast<memberAlignmentType>(kPayloadUnit)); 1.635 + 1.636 + const Header* hdr = reinterpret_cast<const Header*>(start); 1.637 + const char* payload_base = start + header_size; 1.638 + const char* payload_end = payload_base + hdr->payload_size; 1.639 + if (payload_end < payload_base) 1.640 + return NULL; 1.641 + 1.642 + return (payload_end > end) ? NULL : payload_end; 1.643 +}