ipc/chromium/src/base/pickle.h

changeset 0
6474c204b198
     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__

mercurial