1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipc/chromium/src/base/pickle.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,287 @@ 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 +#ifndef BASE_PICKLE_H__ 1.9 +#define BASE_PICKLE_H__ 1.10 + 1.11 +#include <string> 1.12 + 1.13 +#include "base/basictypes.h" 1.14 +#include "base/logging.h" 1.15 +#include "base/string16.h" 1.16 + 1.17 +// This class provides facilities for basic binary value packing and unpacking. 1.18 +// 1.19 +// The Pickle class supports appending primitive values (ints, strings, etc.) 1.20 +// to a pickle instance. The Pickle instance grows its internal memory buffer 1.21 +// dynamically to hold the sequence of primitive values. The internal memory 1.22 +// buffer is exposed as the "data" of the Pickle. This "data" can be passed 1.23 +// to a Pickle object to initialize it for reading. 1.24 +// 1.25 +// When reading from a Pickle object, it is important for the consumer to know 1.26 +// what value types to read and in what order to read them as the Pickle does 1.27 +// not keep track of the type of data written to it. 1.28 +// 1.29 +// The Pickle's data has a header which contains the size of the Pickle's 1.30 +// payload. It can optionally support additional space in the header. That 1.31 +// space is controlled by the header_size parameter passed to the Pickle 1.32 +// constructor. 1.33 +// 1.34 +class Pickle { 1.35 + public: 1.36 + ~Pickle(); 1.37 + 1.38 + // Initialize a Pickle object using the default header size. 1.39 + Pickle(); 1.40 + 1.41 + // Initialize a Pickle object with the specified header size in bytes, which 1.42 + // must be greater-than-or-equal-to sizeof(Pickle::Header). The header size 1.43 + // will be rounded up to ensure that the header size is 32bit-aligned. 1.44 + explicit Pickle(int header_size); 1.45 + 1.46 + // Initializes a Pickle from a const block of data. The data is not copied; 1.47 + // instead the data is merely referenced by this Pickle. Only const methods 1.48 + // should be used on the Pickle when initialized this way. The header 1.49 + // padding size is deduced from the data length. 1.50 + Pickle(const char* data, int data_len); 1.51 + 1.52 + // Initializes a Pickle as a deep copy of another Pickle. 1.53 + Pickle(const Pickle& other); 1.54 + 1.55 + // Performs a deep copy. 1.56 + Pickle& operator=(const Pickle& other); 1.57 + 1.58 + // Returns the size of the Pickle's data. 1.59 + int size() const { return static_cast<int>(header_size_ + 1.60 + header_->payload_size); } 1.61 + 1.62 + // Returns the data for this Pickle. 1.63 + const void* data() const { return header_; } 1.64 + 1.65 + // Methods for reading the payload of the Pickle. To read from the start of 1.66 + // the Pickle, initialize *iter to NULL. If successful, these methods return 1.67 + // true. Otherwise, false is returned to indicate that the result could not 1.68 + // be extracted. 1.69 + bool ReadBool(void** iter, bool* result) const; 1.70 + bool ReadInt16(void** iter, int16_t* result) const; 1.71 + bool ReadUInt16(void** iter, uint16_t* result) const; 1.72 + bool ReadShort(void** iter, short* result) const; 1.73 + bool ReadInt(void** iter, int* result) const; 1.74 + bool ReadLong(void** iter, long* result) const; 1.75 + bool ReadULong(void** iter, unsigned long* result) const; 1.76 + bool ReadSize(void** iter, size_t* result) const; 1.77 + bool ReadInt32(void** iter, int32_t* result) const; 1.78 + bool ReadUInt32(void** iter, uint32_t* result) const; 1.79 + bool ReadInt64(void** iter, int64_t* result) const; 1.80 + bool ReadUInt64(void** iter, uint64_t* result) const; 1.81 + bool ReadDouble(void** iter, double* result) const; 1.82 + bool ReadIntPtr(void** iter, intptr_t* result) const; 1.83 + bool ReadUnsignedChar(void** iter, unsigned char* result) const; 1.84 + bool ReadString(void** iter, std::string* result) const; 1.85 + bool ReadWString(void** iter, std::wstring* result) const; 1.86 + bool ReadString16(void** iter, string16* result) const; 1.87 + bool ReadData(void** iter, const char** data, int* length) const; 1.88 + bool ReadBytes(void** iter, const char** data, int length, 1.89 + uint32_t alignment = sizeof(memberAlignmentType)) const; 1.90 + 1.91 + // Safer version of ReadInt() checks for the result not being negative. 1.92 + // Use it for reading the object sizes. 1.93 + bool ReadLength(void** iter, int* result) const; 1.94 + 1.95 + // Methods for adding to the payload of the Pickle. These values are 1.96 + // appended to the end of the Pickle's payload. When reading values from a 1.97 + // Pickle, it is important to read them in the order in which they were added 1.98 + // to the Pickle. 1.99 + bool WriteBool(bool value) { 1.100 + return WriteInt(value ? 1 : 0); 1.101 + } 1.102 + bool WriteInt16(int16_t value) { 1.103 + return WriteBytes(&value, sizeof(value)); 1.104 + } 1.105 + bool WriteUInt16(uint16_t value) { 1.106 + return WriteBytes(&value, sizeof(value)); 1.107 + } 1.108 + bool WriteInt(int value) { 1.109 + return WriteBytes(&value, sizeof(value)); 1.110 + } 1.111 + bool WriteLong(long value) { 1.112 + // Always written as a 64-bit value since the size for this type can 1.113 + // differ between architectures. 1.114 + return WriteInt64(int64_t(value)); 1.115 + } 1.116 + bool WriteULong(unsigned long value) { 1.117 + // Always written as a 64-bit value since the size for this type can 1.118 + // differ between architectures. 1.119 + return WriteUInt64(uint64_t(value)); 1.120 + } 1.121 + bool WriteSize(size_t value) { 1.122 + // Always written as a 64-bit value since the size for this type can 1.123 + // differ between architectures. 1.124 + return WriteUInt64(uint64_t(value)); 1.125 + } 1.126 + bool WriteInt32(int32_t value) { 1.127 + return WriteBytes(&value, sizeof(value)); 1.128 + } 1.129 + bool WriteUInt32(uint32_t value) { 1.130 + return WriteBytes(&value, sizeof(value)); 1.131 + } 1.132 + bool WriteInt64(int64_t value) { 1.133 + return WriteBytes(&value, sizeof(value)); 1.134 + } 1.135 + bool WriteUInt64(uint64_t value) { 1.136 + return WriteBytes(&value, sizeof(value)); 1.137 + } 1.138 + bool WriteDouble(double value) { 1.139 + return WriteBytes(&value, sizeof(value)); 1.140 + } 1.141 + bool WriteIntPtr(intptr_t value) { 1.142 + // Always written as a 64-bit value since the size for this type can 1.143 + // differ between architectures. 1.144 + return WriteInt64(int64_t(value)); 1.145 + } 1.146 + bool WriteUnsignedChar(unsigned char value) { 1.147 + return WriteBytes(&value, sizeof(value)); 1.148 + } 1.149 + bool WriteString(const std::string& value); 1.150 + bool WriteWString(const std::wstring& value); 1.151 + bool WriteString16(const string16& value); 1.152 + bool WriteData(const char* data, int length); 1.153 + bool WriteBytes(const void* data, int data_len, 1.154 + uint32_t alignment = sizeof(memberAlignmentType)); 1.155 + 1.156 + // Same as WriteData, but allows the caller to write directly into the 1.157 + // Pickle. This saves a copy in cases where the data is not already 1.158 + // available in a buffer. The caller should take care to not write more 1.159 + // than the length it declares it will. Use ReadData to get the data. 1.160 + // Returns NULL on failure. 1.161 + // 1.162 + // The returned pointer will only be valid until the next write operation 1.163 + // on this Pickle. 1.164 + char* BeginWriteData(int length); 1.165 + 1.166 + // For Pickles which contain variable length buffers (e.g. those created 1.167 + // with BeginWriteData), the Pickle can 1.168 + // be 'trimmed' if the amount of data required is less than originally 1.169 + // requested. For example, you may have created a buffer with 10K of data, 1.170 + // but decided to only fill 10 bytes of that data. Use this function 1.171 + // to trim the buffer so that we don't send 9990 bytes of unused data. 1.172 + // You cannot increase the size of the variable buffer; only shrink it. 1.173 + // This function assumes that the length of the variable buffer has 1.174 + // not been changed. 1.175 + void TrimWriteData(int length); 1.176 + 1.177 + void EndRead(void* iter) const { 1.178 + DCHECK(iter == end_of_payload()); 1.179 + } 1.180 + 1.181 + // Payload follows after allocation of Header (header size is customizable). 1.182 + struct Header { 1.183 + uint32_t payload_size; // Specifies the size of the payload. 1.184 + }; 1.185 + 1.186 + // Returns the header, cast to a user-specified type T. The type T must be a 1.187 + // subclass of Header and its size must correspond to the header_size passed 1.188 + // to the Pickle constructor. 1.189 + template <class T> 1.190 + T* headerT() { 1.191 + DCHECK(sizeof(T) == header_size_); 1.192 + return static_cast<T*>(header_); 1.193 + } 1.194 + template <class T> 1.195 + const T* headerT() const { 1.196 + DCHECK(sizeof(T) == header_size_); 1.197 + return static_cast<const T*>(header_); 1.198 + } 1.199 + 1.200 + // Returns true if the given iterator could point to data with the given 1.201 + // length. If there is no room for the given data before the end of the 1.202 + // payload, returns false. 1.203 + bool IteratorHasRoomFor(const void* iter, int len) const { 1.204 + if ((len < 0) || (iter < header_) || iter > end_of_payload()) 1.205 + return false; 1.206 + const char* end_of_region = reinterpret_cast<const char*>(iter) + len; 1.207 + // Watch out for overflow in pointer calculation, which wraps. 1.208 + return (iter <= end_of_region) && (end_of_region <= end_of_payload()); 1.209 + } 1.210 + 1.211 + typedef uint32_t memberAlignmentType; 1.212 + 1.213 + protected: 1.214 + uint32_t payload_size() const { return header_->payload_size; } 1.215 + 1.216 + char* payload() { 1.217 + return reinterpret_cast<char*>(header_) + header_size_; 1.218 + } 1.219 + const char* payload() const { 1.220 + return reinterpret_cast<const char*>(header_) + header_size_; 1.221 + } 1.222 + 1.223 + // Returns the address of the byte immediately following the currently valid 1.224 + // header + payload. 1.225 + char* end_of_payload() { 1.226 + return payload() + payload_size(); 1.227 + } 1.228 + const char* end_of_payload() const { 1.229 + return payload() + payload_size(); 1.230 + } 1.231 + 1.232 + uint32_t capacity() const { 1.233 + return capacity_; 1.234 + } 1.235 + 1.236 + // Resizes the buffer for use when writing the specified amount of data. The 1.237 + // location that the data should be written at is returned, or NULL if there 1.238 + // was an error. Call EndWrite with the returned offset and the given length 1.239 + // to pad out for the next write. 1.240 + char* BeginWrite(uint32_t length, uint32_t alignment); 1.241 + 1.242 + // Completes the write operation by padding the data with NULL bytes until it 1.243 + // is padded. Should be paired with BeginWrite, but it does not necessarily 1.244 + // have to be called after the data is written. 1.245 + void EndWrite(char* dest, int length); 1.246 + 1.247 + // Resize the capacity, note that the input value should include the size of 1.248 + // the header: new_capacity = sizeof(Header) + desired_payload_capacity. 1.249 + // A realloc() failure will cause a Resize failure... and caller should check 1.250 + // the return result for true (i.e., successful resizing). 1.251 + bool Resize(uint32_t new_capacity); 1.252 + 1.253 + // Round 'bytes' up to the next multiple of 'alignment'. 'alignment' must be 1.254 + // a power of 2. 1.255 + template<uint32_t alignment> struct ConstantAligner { 1.256 + static uint32_t align(int bytes) { 1.257 + static_assert((alignment & (alignment - 1)) == 0, 1.258 + "alignment must be a power of two"); 1.259 + return (bytes + (alignment - 1)) & ~static_cast<uint32_t>(alignment - 1); 1.260 + } 1.261 + }; 1.262 + 1.263 + static uint32_t AlignInt(int bytes) { 1.264 + return ConstantAligner<sizeof(memberAlignmentType)>::align(bytes); 1.265 + } 1.266 + 1.267 + // Moves the iterator by the given number of bytes, making sure it is aligned. 1.268 + // Pointer (iterator) is NOT aligned, but the change in the pointer 1.269 + // is guaranteed to be a multiple of sizeof(memberAlignmentType). 1.270 + static void UpdateIter(void** iter, int bytes) { 1.271 + *iter = static_cast<char*>(*iter) + AlignInt(bytes); 1.272 + } 1.273 + 1.274 + // Find the end of the pickled data that starts at range_start. Returns NULL 1.275 + // if the entire Pickle is not found in the given data range. 1.276 + static const char* FindNext(uint32_t header_size, 1.277 + const char* range_start, 1.278 + const char* range_end); 1.279 + 1.280 + // The allocation granularity of the payload. 1.281 + static const int kPayloadUnit; 1.282 + 1.283 + private: 1.284 + Header* header_; 1.285 + uint32_t header_size_; 1.286 + uint32_t capacity_; 1.287 + uint32_t variable_buffer_offset_; 1.288 +}; 1.289 + 1.290 +#endif // BASE_PICKLE_H__