ipc/chromium/src/base/pickle.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
michael@0 2 // Use of this source code is governed by a BSD-style license that can be
michael@0 3 // found in the LICENSE file.
michael@0 4
michael@0 5 #ifndef BASE_PICKLE_H__
michael@0 6 #define BASE_PICKLE_H__
michael@0 7
michael@0 8 #include <string>
michael@0 9
michael@0 10 #include "base/basictypes.h"
michael@0 11 #include "base/logging.h"
michael@0 12 #include "base/string16.h"
michael@0 13
michael@0 14 // This class provides facilities for basic binary value packing and unpacking.
michael@0 15 //
michael@0 16 // The Pickle class supports appending primitive values (ints, strings, etc.)
michael@0 17 // to a pickle instance. The Pickle instance grows its internal memory buffer
michael@0 18 // dynamically to hold the sequence of primitive values. The internal memory
michael@0 19 // buffer is exposed as the "data" of the Pickle. This "data" can be passed
michael@0 20 // to a Pickle object to initialize it for reading.
michael@0 21 //
michael@0 22 // When reading from a Pickle object, it is important for the consumer to know
michael@0 23 // what value types to read and in what order to read them as the Pickle does
michael@0 24 // not keep track of the type of data written to it.
michael@0 25 //
michael@0 26 // The Pickle's data has a header which contains the size of the Pickle's
michael@0 27 // payload. It can optionally support additional space in the header. That
michael@0 28 // space is controlled by the header_size parameter passed to the Pickle
michael@0 29 // constructor.
michael@0 30 //
michael@0 31 class Pickle {
michael@0 32 public:
michael@0 33 ~Pickle();
michael@0 34
michael@0 35 // Initialize a Pickle object using the default header size.
michael@0 36 Pickle();
michael@0 37
michael@0 38 // Initialize a Pickle object with the specified header size in bytes, which
michael@0 39 // must be greater-than-or-equal-to sizeof(Pickle::Header). The header size
michael@0 40 // will be rounded up to ensure that the header size is 32bit-aligned.
michael@0 41 explicit Pickle(int header_size);
michael@0 42
michael@0 43 // Initializes a Pickle from a const block of data. The data is not copied;
michael@0 44 // instead the data is merely referenced by this Pickle. Only const methods
michael@0 45 // should be used on the Pickle when initialized this way. The header
michael@0 46 // padding size is deduced from the data length.
michael@0 47 Pickle(const char* data, int data_len);
michael@0 48
michael@0 49 // Initializes a Pickle as a deep copy of another Pickle.
michael@0 50 Pickle(const Pickle& other);
michael@0 51
michael@0 52 // Performs a deep copy.
michael@0 53 Pickle& operator=(const Pickle& other);
michael@0 54
michael@0 55 // Returns the size of the Pickle's data.
michael@0 56 int size() const { return static_cast<int>(header_size_ +
michael@0 57 header_->payload_size); }
michael@0 58
michael@0 59 // Returns the data for this Pickle.
michael@0 60 const void* data() const { return header_; }
michael@0 61
michael@0 62 // Methods for reading the payload of the Pickle. To read from the start of
michael@0 63 // the Pickle, initialize *iter to NULL. If successful, these methods return
michael@0 64 // true. Otherwise, false is returned to indicate that the result could not
michael@0 65 // be extracted.
michael@0 66 bool ReadBool(void** iter, bool* result) const;
michael@0 67 bool ReadInt16(void** iter, int16_t* result) const;
michael@0 68 bool ReadUInt16(void** iter, uint16_t* result) const;
michael@0 69 bool ReadShort(void** iter, short* result) const;
michael@0 70 bool ReadInt(void** iter, int* result) const;
michael@0 71 bool ReadLong(void** iter, long* result) const;
michael@0 72 bool ReadULong(void** iter, unsigned long* result) const;
michael@0 73 bool ReadSize(void** iter, size_t* result) const;
michael@0 74 bool ReadInt32(void** iter, int32_t* result) const;
michael@0 75 bool ReadUInt32(void** iter, uint32_t* result) const;
michael@0 76 bool ReadInt64(void** iter, int64_t* result) const;
michael@0 77 bool ReadUInt64(void** iter, uint64_t* result) const;
michael@0 78 bool ReadDouble(void** iter, double* result) const;
michael@0 79 bool ReadIntPtr(void** iter, intptr_t* result) const;
michael@0 80 bool ReadUnsignedChar(void** iter, unsigned char* result) const;
michael@0 81 bool ReadString(void** iter, std::string* result) const;
michael@0 82 bool ReadWString(void** iter, std::wstring* result) const;
michael@0 83 bool ReadString16(void** iter, string16* result) const;
michael@0 84 bool ReadData(void** iter, const char** data, int* length) const;
michael@0 85 bool ReadBytes(void** iter, const char** data, int length,
michael@0 86 uint32_t alignment = sizeof(memberAlignmentType)) const;
michael@0 87
michael@0 88 // Safer version of ReadInt() checks for the result not being negative.
michael@0 89 // Use it for reading the object sizes.
michael@0 90 bool ReadLength(void** iter, int* result) const;
michael@0 91
michael@0 92 // Methods for adding to the payload of the Pickle. These values are
michael@0 93 // appended to the end of the Pickle's payload. When reading values from a
michael@0 94 // Pickle, it is important to read them in the order in which they were added
michael@0 95 // to the Pickle.
michael@0 96 bool WriteBool(bool value) {
michael@0 97 return WriteInt(value ? 1 : 0);
michael@0 98 }
michael@0 99 bool WriteInt16(int16_t value) {
michael@0 100 return WriteBytes(&value, sizeof(value));
michael@0 101 }
michael@0 102 bool WriteUInt16(uint16_t value) {
michael@0 103 return WriteBytes(&value, sizeof(value));
michael@0 104 }
michael@0 105 bool WriteInt(int value) {
michael@0 106 return WriteBytes(&value, sizeof(value));
michael@0 107 }
michael@0 108 bool WriteLong(long value) {
michael@0 109 // Always written as a 64-bit value since the size for this type can
michael@0 110 // differ between architectures.
michael@0 111 return WriteInt64(int64_t(value));
michael@0 112 }
michael@0 113 bool WriteULong(unsigned long value) {
michael@0 114 // Always written as a 64-bit value since the size for this type can
michael@0 115 // differ between architectures.
michael@0 116 return WriteUInt64(uint64_t(value));
michael@0 117 }
michael@0 118 bool WriteSize(size_t value) {
michael@0 119 // Always written as a 64-bit value since the size for this type can
michael@0 120 // differ between architectures.
michael@0 121 return WriteUInt64(uint64_t(value));
michael@0 122 }
michael@0 123 bool WriteInt32(int32_t value) {
michael@0 124 return WriteBytes(&value, sizeof(value));
michael@0 125 }
michael@0 126 bool WriteUInt32(uint32_t value) {
michael@0 127 return WriteBytes(&value, sizeof(value));
michael@0 128 }
michael@0 129 bool WriteInt64(int64_t value) {
michael@0 130 return WriteBytes(&value, sizeof(value));
michael@0 131 }
michael@0 132 bool WriteUInt64(uint64_t value) {
michael@0 133 return WriteBytes(&value, sizeof(value));
michael@0 134 }
michael@0 135 bool WriteDouble(double value) {
michael@0 136 return WriteBytes(&value, sizeof(value));
michael@0 137 }
michael@0 138 bool WriteIntPtr(intptr_t value) {
michael@0 139 // Always written as a 64-bit value since the size for this type can
michael@0 140 // differ between architectures.
michael@0 141 return WriteInt64(int64_t(value));
michael@0 142 }
michael@0 143 bool WriteUnsignedChar(unsigned char value) {
michael@0 144 return WriteBytes(&value, sizeof(value));
michael@0 145 }
michael@0 146 bool WriteString(const std::string& value);
michael@0 147 bool WriteWString(const std::wstring& value);
michael@0 148 bool WriteString16(const string16& value);
michael@0 149 bool WriteData(const char* data, int length);
michael@0 150 bool WriteBytes(const void* data, int data_len,
michael@0 151 uint32_t alignment = sizeof(memberAlignmentType));
michael@0 152
michael@0 153 // Same as WriteData, but allows the caller to write directly into the
michael@0 154 // Pickle. This saves a copy in cases where the data is not already
michael@0 155 // available in a buffer. The caller should take care to not write more
michael@0 156 // than the length it declares it will. Use ReadData to get the data.
michael@0 157 // Returns NULL on failure.
michael@0 158 //
michael@0 159 // The returned pointer will only be valid until the next write operation
michael@0 160 // on this Pickle.
michael@0 161 char* BeginWriteData(int length);
michael@0 162
michael@0 163 // For Pickles which contain variable length buffers (e.g. those created
michael@0 164 // with BeginWriteData), the Pickle can
michael@0 165 // be 'trimmed' if the amount of data required is less than originally
michael@0 166 // requested. For example, you may have created a buffer with 10K of data,
michael@0 167 // but decided to only fill 10 bytes of that data. Use this function
michael@0 168 // to trim the buffer so that we don't send 9990 bytes of unused data.
michael@0 169 // You cannot increase the size of the variable buffer; only shrink it.
michael@0 170 // This function assumes that the length of the variable buffer has
michael@0 171 // not been changed.
michael@0 172 void TrimWriteData(int length);
michael@0 173
michael@0 174 void EndRead(void* iter) const {
michael@0 175 DCHECK(iter == end_of_payload());
michael@0 176 }
michael@0 177
michael@0 178 // Payload follows after allocation of Header (header size is customizable).
michael@0 179 struct Header {
michael@0 180 uint32_t payload_size; // Specifies the size of the payload.
michael@0 181 };
michael@0 182
michael@0 183 // Returns the header, cast to a user-specified type T. The type T must be a
michael@0 184 // subclass of Header and its size must correspond to the header_size passed
michael@0 185 // to the Pickle constructor.
michael@0 186 template <class T>
michael@0 187 T* headerT() {
michael@0 188 DCHECK(sizeof(T) == header_size_);
michael@0 189 return static_cast<T*>(header_);
michael@0 190 }
michael@0 191 template <class T>
michael@0 192 const T* headerT() const {
michael@0 193 DCHECK(sizeof(T) == header_size_);
michael@0 194 return static_cast<const T*>(header_);
michael@0 195 }
michael@0 196
michael@0 197 // Returns true if the given iterator could point to data with the given
michael@0 198 // length. If there is no room for the given data before the end of the
michael@0 199 // payload, returns false.
michael@0 200 bool IteratorHasRoomFor(const void* iter, int len) const {
michael@0 201 if ((len < 0) || (iter < header_) || iter > end_of_payload())
michael@0 202 return false;
michael@0 203 const char* end_of_region = reinterpret_cast<const char*>(iter) + len;
michael@0 204 // Watch out for overflow in pointer calculation, which wraps.
michael@0 205 return (iter <= end_of_region) && (end_of_region <= end_of_payload());
michael@0 206 }
michael@0 207
michael@0 208 typedef uint32_t memberAlignmentType;
michael@0 209
michael@0 210 protected:
michael@0 211 uint32_t payload_size() const { return header_->payload_size; }
michael@0 212
michael@0 213 char* payload() {
michael@0 214 return reinterpret_cast<char*>(header_) + header_size_;
michael@0 215 }
michael@0 216 const char* payload() const {
michael@0 217 return reinterpret_cast<const char*>(header_) + header_size_;
michael@0 218 }
michael@0 219
michael@0 220 // Returns the address of the byte immediately following the currently valid
michael@0 221 // header + payload.
michael@0 222 char* end_of_payload() {
michael@0 223 return payload() + payload_size();
michael@0 224 }
michael@0 225 const char* end_of_payload() const {
michael@0 226 return payload() + payload_size();
michael@0 227 }
michael@0 228
michael@0 229 uint32_t capacity() const {
michael@0 230 return capacity_;
michael@0 231 }
michael@0 232
michael@0 233 // Resizes the buffer for use when writing the specified amount of data. The
michael@0 234 // location that the data should be written at is returned, or NULL if there
michael@0 235 // was an error. Call EndWrite with the returned offset and the given length
michael@0 236 // to pad out for the next write.
michael@0 237 char* BeginWrite(uint32_t length, uint32_t alignment);
michael@0 238
michael@0 239 // Completes the write operation by padding the data with NULL bytes until it
michael@0 240 // is padded. Should be paired with BeginWrite, but it does not necessarily
michael@0 241 // have to be called after the data is written.
michael@0 242 void EndWrite(char* dest, int length);
michael@0 243
michael@0 244 // Resize the capacity, note that the input value should include the size of
michael@0 245 // the header: new_capacity = sizeof(Header) + desired_payload_capacity.
michael@0 246 // A realloc() failure will cause a Resize failure... and caller should check
michael@0 247 // the return result for true (i.e., successful resizing).
michael@0 248 bool Resize(uint32_t new_capacity);
michael@0 249
michael@0 250 // Round 'bytes' up to the next multiple of 'alignment'. 'alignment' must be
michael@0 251 // a power of 2.
michael@0 252 template<uint32_t alignment> struct ConstantAligner {
michael@0 253 static uint32_t align(int bytes) {
michael@0 254 static_assert((alignment & (alignment - 1)) == 0,
michael@0 255 "alignment must be a power of two");
michael@0 256 return (bytes + (alignment - 1)) & ~static_cast<uint32_t>(alignment - 1);
michael@0 257 }
michael@0 258 };
michael@0 259
michael@0 260 static uint32_t AlignInt(int bytes) {
michael@0 261 return ConstantAligner<sizeof(memberAlignmentType)>::align(bytes);
michael@0 262 }
michael@0 263
michael@0 264 // Moves the iterator by the given number of bytes, making sure it is aligned.
michael@0 265 // Pointer (iterator) is NOT aligned, but the change in the pointer
michael@0 266 // is guaranteed to be a multiple of sizeof(memberAlignmentType).
michael@0 267 static void UpdateIter(void** iter, int bytes) {
michael@0 268 *iter = static_cast<char*>(*iter) + AlignInt(bytes);
michael@0 269 }
michael@0 270
michael@0 271 // Find the end of the pickled data that starts at range_start. Returns NULL
michael@0 272 // if the entire Pickle is not found in the given data range.
michael@0 273 static const char* FindNext(uint32_t header_size,
michael@0 274 const char* range_start,
michael@0 275 const char* range_end);
michael@0 276
michael@0 277 // The allocation granularity of the payload.
michael@0 278 static const int kPayloadUnit;
michael@0 279
michael@0 280 private:
michael@0 281 Header* header_;
michael@0 282 uint32_t header_size_;
michael@0 283 uint32_t capacity_;
michael@0 284 uint32_t variable_buffer_offset_;
michael@0 285 };
michael@0 286
michael@0 287 #endif // BASE_PICKLE_H__

mercurial