pickle.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/pickle.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> // for max() 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------ 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int Pickle::kPayloadUnit = 64; 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const size_t kCapacityReadOnly = static_cast<size_t>(-1); 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PickleIterator::PickleIterator(const Pickle& pickle) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : read_ptr_(pickle.payload()), 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_end_ptr_(pickle.end_of_payload()) { 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type> 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline bool PickleIterator::ReadBuiltinType(Type* result) { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* read_from = GetReadPointerAndAdvance<Type>(); 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!read_from) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sizeof(Type) > sizeof(uint32)) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(result, read_from, sizeof(*result)); 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *result = *reinterpret_cast<const Type*>(read_from); 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename Type> 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline const char* PickleIterator::GetReadPointerAndAdvance() { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* current_read_ptr = read_ptr_; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (read_ptr_ + sizeof(Type) > read_end_ptr_) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sizeof(Type) < sizeof(uint32)) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_ptr_ += AlignInt(sizeof(Type), sizeof(uint32)); 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_ptr_ += sizeof(Type); 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return current_read_ptr; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* PickleIterator::GetReadPointerAndAdvance(int num_bytes) { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (num_bytes < 0 || read_end_ptr_ - read_ptr_ < num_bytes) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* current_read_ptr = read_ptr_; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_ptr_ += AlignInt(num_bytes, sizeof(uint32)); 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return current_read_ptr; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline const char* PickleIterator::GetReadPointerAndAdvance(int num_elements, 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t size_element) { 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check for int32 overflow. 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 num_bytes = static_cast<int64>(num_elements) * size_element; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_bytes32 = static_cast<int>(num_bytes); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (num_bytes != static_cast<int64>(num_bytes32)) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetReadPointerAndAdvance(num_bytes32); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PickleIterator::ReadBool(bool* result) { 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ReadBuiltinType(result); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PickleIterator::ReadInt(int* result) { 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ReadBuiltinType(result); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PickleIterator::ReadLong(long* result) { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ReadBuiltinType(result); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PickleIterator::ReadUInt16(uint16* result) { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ReadBuiltinType(result); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PickleIterator::ReadUInt32(uint32* result) { 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ReadBuiltinType(result); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PickleIterator::ReadInt64(int64* result) { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ReadBuiltinType(result); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PickleIterator::ReadUInt64(uint64* result) { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ReadBuiltinType(result); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PickleIterator::ReadString(std::string* result) { 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int len; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ReadInt(&len)) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* read_from = GetReadPointerAndAdvance(len); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!read_from) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->assign(read_from, len); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PickleIterator::ReadWString(std::wstring* result) { 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int len; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ReadInt(&len)) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* read_from = GetReadPointerAndAdvance(len, sizeof(wchar_t)); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!read_from) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->assign(reinterpret_cast<const wchar_t*>(read_from), len); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PickleIterator::ReadString16(string16* result) { 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int len; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ReadInt(&len)) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* read_from = GetReadPointerAndAdvance(len, sizeof(char16)); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!read_from) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->assign(reinterpret_cast<const char16*>(read_from), len); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PickleIterator::ReadData(const char** data, int* length) { 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *length = 0; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *data = 0; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ReadInt(length)) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ReadBytes(data, *length); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PickleIterator::ReadBytes(const char** data, int length) { 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* read_from = GetReadPointerAndAdvance(length); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!read_from) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *data = read_from; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Payload is uint32 aligned. 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Pickle::Pickle() 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : header_(NULL), 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header_size_(sizeof(Header)), 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) capacity_(0), 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) variable_buffer_offset_(0) { 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Resize(kPayloadUnit); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header_->payload_size = 0; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Pickle::Pickle(int header_size) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : header_(NULL), 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header_size_(AlignInt(header_size, sizeof(uint32))), 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) capacity_(0), 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) variable_buffer_offset_(0) { 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GE(static_cast<size_t>(header_size), sizeof(Header)); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LE(header_size, kPayloadUnit); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Resize(kPayloadUnit); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header_->payload_size = 0; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Pickle::Pickle(const char* data, int data_len) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : header_(reinterpret_cast<Header*>(const_cast<char*>(data))), 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header_size_(0), 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) capacity_(kCapacityReadOnly), 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) variable_buffer_offset_(0) { 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (data_len >= static_cast<int>(sizeof(Header))) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header_size_ = data_len - header_->payload_size; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (header_size_ > static_cast<unsigned int>(data_len)) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header_size_ = 0; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (header_size_ != AlignInt(header_size_, sizeof(uint32))) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header_size_ = 0; 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If there is anything wrong with the data, we're not going to use it. 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!header_size_) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header_ = NULL; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Pickle::Pickle(const Pickle& other) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : header_(NULL), 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header_size_(other.header_size_), 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) capacity_(0), 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) variable_buffer_offset_(other.variable_buffer_offset_) { 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t payload_size = header_size_ + other.header_->payload_size; 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool resized = Resize(payload_size); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(resized); // Realloc failed. 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(header_, other.header_, payload_size); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Pickle::~Pickle() { 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (capacity_ != kCapacityReadOnly) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(header_); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Pickle& Pickle::operator=(const Pickle& other) { 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this == &other) { 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return *this; 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (capacity_ == kCapacityReadOnly) { 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header_ = NULL; 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) capacity_ = 0; 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (header_size_ != other.header_size_) { 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(header_); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header_ = NULL; 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header_size_ = other.header_size_; 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool resized = Resize(other.header_size_ + other.header_->payload_size); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(resized); // Realloc failed. 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(header_, other.header_, 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) other.header_size_ + other.header_->payload_size); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) variable_buffer_offset_ = other.variable_buffer_offset_; 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return *this; 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Pickle::WriteString(const std::string& value) { 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!WriteInt(static_cast<int>(value.size()))) 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return WriteBytes(value.data(), static_cast<int>(value.size())); 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Pickle::WriteWString(const std::wstring& value) { 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!WriteInt(static_cast<int>(value.size()))) 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return WriteBytes(value.data(), 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>(value.size() * sizeof(wchar_t))); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Pickle::WriteString16(const string16& value) { 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!WriteInt(static_cast<int>(value.size()))) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return WriteBytes(value.data(), 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>(value.size()) * sizeof(char16)); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Pickle::WriteData(const char* data, int length) { 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return length >= 0 && WriteInt(length) && WriteBytes(data, length); 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Pickle::WriteBytes(const void* data, int data_len) { 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(kCapacityReadOnly, capacity_) << "oops: pickle is readonly"; 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* dest = BeginWrite(data_len); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!dest) 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(dest, data, data_len); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EndWrite(dest, data_len); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)char* Pickle::BeginWriteData(int length) { 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(variable_buffer_offset_, 0U) << 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "There can only be one variable buffer in a Pickle"; 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (length < 0 || !WriteInt(length)) 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *data_ptr = BeginWrite(length); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!data_ptr) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) variable_buffer_offset_ = 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data_ptr - reinterpret_cast<char*>(header_) - sizeof(int); 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // EndWrite doesn't necessarily have to be called after the write operation, 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // so we call it here to pad out what the caller will eventually write. 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EndWrite(data_ptr, length); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return data_ptr; 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Pickle::TrimWriteData(int new_length) { 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(variable_buffer_offset_, 0U); 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Fetch the the variable buffer size 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* cur_length = reinterpret_cast<int*>( 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<char*>(header_) + variable_buffer_offset_); 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (new_length < 0 || new_length > *cur_length) { 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Invalid length in TrimWriteData."; 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the payload size and variable buffer size 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header_->payload_size -= (*cur_length - new_length); 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *cur_length = new_length; 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)char* Pickle::BeginWrite(size_t length) { 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // write at a uint32-aligned offset from the beginning of the header 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t offset = AlignInt(header_->payload_size, sizeof(uint32)); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t new_size = offset + length; 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t needed_size = header_size_ + new_size; 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (needed_size > capacity_ && !Resize(std::max(capacity_ * 2, needed_size))) 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef ARCH_CPU_64_BITS 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LE(length, kuint32max); 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header_->payload_size = static_cast<uint32>(new_size); 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return payload() + offset; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Pickle::EndWrite(char* dest, int length) { 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Zero-pad to keep tools like valgrind from complaining about uninitialized 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // memory. 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (length % sizeof(uint32)) 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(dest + length, 0, sizeof(uint32) - (length % sizeof(uint32))); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Pickle::Resize(size_t new_capacity) { 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_capacity = AlignInt(new_capacity, kPayloadUnit); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_NE(capacity_, kCapacityReadOnly); 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* p = realloc(header_, new_capacity); 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!p) 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header_ = reinterpret_cast<Header*>(p); 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) capacity_ = new_capacity; 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* Pickle::FindNext(size_t header_size, 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* start, 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* end) { 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(header_size, AlignInt(header_size, sizeof(uint32))); 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LE(header_size, static_cast<size_t>(kPayloadUnit)); 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (static_cast<size_t>(end - start) < sizeof(Header)) 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Header* hdr = reinterpret_cast<const Header*>(start); 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* payload_base = start + header_size; 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* payload_end = payload_base + hdr->payload_size; 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (payload_end < payload_base) 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (payload_end > end) ? NULL : payload_end; 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 358