Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef BASE_PICKLE_H__
      6 #define BASE_PICKLE_H__
      7 
      8 #include <string>
      9 
     10 #include "base/base_export.h"
     11 #include "base/basictypes.h"
     12 #include "base/compiler_specific.h"
     13 #include "base/gtest_prod_util.h"
     14 #include "base/logging.h"
     15 #include "base/strings/string16.h"
     16 
     17 class Pickle;
     18 
     19 // PickleIterator reads data from a Pickle. The Pickle object must remain valid
     20 // while the PickleIterator object is in use.
     21 class BASE_EXPORT PickleIterator {
     22  public:
     23   PickleIterator() : read_ptr_(NULL), read_end_ptr_(NULL) {}
     24   explicit PickleIterator(const Pickle& pickle);
     25 
     26   // Methods for reading the payload of the Pickle. To read from the start of
     27   // the Pickle, create a PickleIterator from a Pickle. If successful, these
     28   // methods return true. Otherwise, false is returned to indicate that the
     29   // result could not be extracted.
     30   bool ReadBool(bool* result) WARN_UNUSED_RESULT;
     31   bool ReadInt(int* result) WARN_UNUSED_RESULT;
     32   bool ReadLong(long* result) WARN_UNUSED_RESULT;
     33   bool ReadUInt16(uint16* result) WARN_UNUSED_RESULT;
     34   bool ReadUInt32(uint32* result) WARN_UNUSED_RESULT;
     35   bool ReadInt64(int64* result) WARN_UNUSED_RESULT;
     36   bool ReadUInt64(uint64* result) WARN_UNUSED_RESULT;
     37   bool ReadFloat(float* result) WARN_UNUSED_RESULT;
     38   bool ReadString(std::string* result) WARN_UNUSED_RESULT;
     39   bool ReadWString(std::wstring* result) WARN_UNUSED_RESULT;
     40   bool ReadString16(string16* result) WARN_UNUSED_RESULT;
     41   bool ReadData(const char** data, int* length) WARN_UNUSED_RESULT;
     42   bool ReadBytes(const char** data, int length) WARN_UNUSED_RESULT;
     43 
     44   // Safer version of ReadInt() checks for the result not being negative.
     45   // Use it for reading the object sizes.
     46   bool ReadLength(int* result) WARN_UNUSED_RESULT {
     47     return ReadInt(result) && *result >= 0;
     48   }
     49 
     50   // Skips bytes in the read buffer and returns true if there are at least
     51   // num_bytes available. Otherwise, does nothing and returns false.
     52   bool SkipBytes(int num_bytes) WARN_UNUSED_RESULT {
     53     return !!GetReadPointerAndAdvance(num_bytes);
     54   }
     55 
     56  private:
     57   // Aligns 'i' by rounding it up to the next multiple of 'alignment'
     58   static size_t AlignInt(size_t i, int alignment) {
     59     return i + (alignment - (i % alignment)) % alignment;
     60   }
     61 
     62   // Read Type from Pickle.
     63   template <typename Type>
     64   inline bool ReadBuiltinType(Type* result);
     65 
     66   // Get read pointer for Type and advance read pointer.
     67   template<typename Type>
     68   inline const char* GetReadPointerAndAdvance();
     69 
     70   // Get read pointer for |num_bytes| and advance read pointer. This method
     71   // checks num_bytes for negativity and wrapping.
     72   const char* GetReadPointerAndAdvance(int num_bytes);
     73 
     74   // Get read pointer for (num_elements * size_element) bytes and advance read
     75   // pointer. This method checks for int overflow, negativity and wrapping.
     76   inline const char* GetReadPointerAndAdvance(int num_elements,
     77                                               size_t size_element);
     78 
     79   // Pointers to the Pickle data.
     80   const char* read_ptr_;
     81   const char* read_end_ptr_;
     82 
     83   FRIEND_TEST_ALL_PREFIXES(PickleTest, GetReadPointerAndAdvance);
     84 };
     85 
     86 // This class provides facilities for basic binary value packing and unpacking.
     87 //
     88 // The Pickle class supports appending primitive values (ints, strings, etc.)
     89 // to a pickle instance.  The Pickle instance grows its internal memory buffer
     90 // dynamically to hold the sequence of primitive values.   The internal memory
     91 // buffer is exposed as the "data" of the Pickle.  This "data" can be passed
     92 // to a Pickle object to initialize it for reading.
     93 //
     94 // When reading from a Pickle object, it is important for the consumer to know
     95 // what value types to read and in what order to read them as the Pickle does
     96 // not keep track of the type of data written to it.
     97 //
     98 // The Pickle's data has a header which contains the size of the Pickle's
     99 // payload.  It can optionally support additional space in the header.  That
    100 // space is controlled by the header_size parameter passed to the Pickle
    101 // constructor.
    102 //
    103 class BASE_EXPORT Pickle {
    104  public:
    105   // Initialize a Pickle object using the default header size.
    106   Pickle();
    107 
    108   // Initialize a Pickle object with the specified header size in bytes, which
    109   // must be greater-than-or-equal-to sizeof(Pickle::Header).  The header size
    110   // will be rounded up to ensure that the header size is 32bit-aligned.
    111   explicit Pickle(int header_size);
    112 
    113   // Initializes a Pickle from a const block of data.  The data is not copied;
    114   // instead the data is merely referenced by this Pickle.  Only const methods
    115   // should be used on the Pickle when initialized this way.  The header
    116   // padding size is deduced from the data length.
    117   Pickle(const char* data, int data_len);
    118 
    119   // Initializes a Pickle as a deep copy of another Pickle.
    120   Pickle(const Pickle& other);
    121 
    122   // Note: There are no virtual methods in this class.  This destructor is
    123   // virtual as an element of defensive coding.  Other classes have derived from
    124   // this class, and there is a *chance* that they will cast into this base
    125   // class before destruction.  At least one such class does have a virtual
    126   // destructor, suggesting at least some need to call more derived destructors.
    127   virtual ~Pickle();
    128 
    129   // Performs a deep copy.
    130   Pickle& operator=(const Pickle& other);
    131 
    132   // Returns the size of the Pickle's data.
    133   size_t size() const { return header_size_ + header_->payload_size; }
    134 
    135   // Returns the data for this Pickle.
    136   const void* data() const { return header_; }
    137 
    138   // For compatibility, these older style read methods pass through to the
    139   // PickleIterator methods.
    140   // TODO(jbates) Remove these methods.
    141   bool ReadBool(PickleIterator* iter, bool* result) const {
    142     return iter->ReadBool(result);
    143   }
    144   bool ReadInt(PickleIterator* iter, int* result) const {
    145     return iter->ReadInt(result);
    146   }
    147   bool ReadLong(PickleIterator* iter, long* result) const {
    148     return iter->ReadLong(result);
    149   }
    150   bool ReadUInt16(PickleIterator* iter, uint16* result) const {
    151     return iter->ReadUInt16(result);
    152   }
    153   bool ReadUInt32(PickleIterator* iter, uint32* result) const {
    154     return iter->ReadUInt32(result);
    155   }
    156   bool ReadInt64(PickleIterator* iter, int64* result) const {
    157     return iter->ReadInt64(result);
    158   }
    159   bool ReadUInt64(PickleIterator* iter, uint64* result) const {
    160     return iter->ReadUInt64(result);
    161   }
    162   bool ReadFloat(PickleIterator* iter, float* result) const {
    163     return iter->ReadFloat(result);
    164   }
    165   bool ReadString(PickleIterator* iter, std::string* result) const {
    166     return iter->ReadString(result);
    167   }
    168   bool ReadWString(PickleIterator* iter, std::wstring* result) const {
    169     return iter->ReadWString(result);
    170   }
    171   bool ReadString16(PickleIterator* iter, string16* result) const {
    172     return iter->ReadString16(result);
    173   }
    174   // A pointer to the data will be placed in *data, and the length will be
    175   // placed in *length. This buffer will be into the message's buffer so will
    176   // be scoped to the lifetime of the message (or until the message data is
    177   // mutated).
    178   bool ReadData(PickleIterator* iter, const char** data, int* length) const {
    179     return iter->ReadData(data, length);
    180   }
    181   // A pointer to the data will be placed in *data. The caller specifies the
    182   // number of bytes to read, and ReadBytes will validate this length. The
    183   // returned buffer will be into the message's buffer so will be scoped to the
    184   // lifetime of the message (or until the message data is mutated).
    185   bool ReadBytes(PickleIterator* iter, const char** data, int length) const {
    186     return iter->ReadBytes(data, length);
    187   }
    188 
    189   // Safer version of ReadInt() checks for the result not being negative.
    190   // Use it for reading the object sizes.
    191   bool ReadLength(PickleIterator* iter, int* result) const {
    192     return iter->ReadLength(result);
    193   }
    194 
    195   // Methods for adding to the payload of the Pickle.  These values are
    196   // appended to the end of the Pickle's payload.  When reading values from a
    197   // Pickle, it is important to read them in the order in which they were added
    198   // to the Pickle.
    199   bool WriteBool(bool value) {
    200     return WriteInt(value ? 1 : 0);
    201   }
    202   bool WriteInt(int value) {
    203     return WriteBytes(&value, sizeof(value));
    204   }
    205   // WARNING: DO NOT USE THIS METHOD IF PICKLES ARE PERSISTED IN ANY WAY.
    206   // It will write whatever a "long" is on this architecture. On 32-bit
    207   // platforms, it is 32 bits. On 64-bit platforms, it is 64 bits. If persisted
    208   // pickles are still around after upgrading to 64-bit, or if they are copied
    209   // between dissimilar systems, YOUR PICKLES WILL HAVE GONE BAD.
    210   bool WriteLongUsingDangerousNonPortableLessPersistableForm(long value) {
    211     return WriteBytes(&value, sizeof(value));
    212   }
    213   bool WriteUInt16(uint16 value) {
    214     return WriteBytes(&value, sizeof(value));
    215   }
    216   bool WriteUInt32(uint32 value) {
    217     return WriteBytes(&value, sizeof(value));
    218   }
    219   bool WriteInt64(int64 value) {
    220     return WriteBytes(&value, sizeof(value));
    221   }
    222   bool WriteUInt64(uint64 value) {
    223     return WriteBytes(&value, sizeof(value));
    224   }
    225   bool WriteFloat(float value) {
    226     return WriteBytes(&value, sizeof(value));
    227   }
    228   bool WriteString(const std::string& value);
    229   bool WriteWString(const std::wstring& value);
    230   bool WriteString16(const string16& value);
    231   // "Data" is a blob with a length. When you read it out you will be given the
    232   // length. See also WriteBytes.
    233   bool WriteData(const char* data, int length);
    234   // "Bytes" is a blob with no length. The caller must specify the lenght both
    235   // when reading and writing. It is normally used to serialize PoD types of a
    236   // known size. See also WriteData.
    237   bool WriteBytes(const void* data, int data_len);
    238 
    239   // Same as WriteData, but allows the caller to write directly into the
    240   // Pickle. This saves a copy in cases where the data is not already
    241   // available in a buffer. The caller should take care to not write more
    242   // than the length it declares it will. Use ReadData to get the data.
    243   // Returns NULL on failure.
    244   //
    245   // The returned pointer will only be valid until the next write operation
    246   // on this Pickle.
    247   char* BeginWriteData(int length);
    248 
    249   // For Pickles which contain variable length buffers (e.g. those created
    250   // with BeginWriteData), the Pickle can
    251   // be 'trimmed' if the amount of data required is less than originally
    252   // requested.  For example, you may have created a buffer with 10K of data,
    253   // but decided to only fill 10 bytes of that data.  Use this function
    254   // to trim the buffer so that we don't send 9990 bytes of unused data.
    255   // You cannot increase the size of the variable buffer; only shrink it.
    256   // This function assumes that the length of the variable buffer has
    257   // not been changed.
    258   void TrimWriteData(int length);
    259 
    260   // Payload follows after allocation of Header (header size is customizable).
    261   struct Header {
    262     uint32 payload_size;  // Specifies the size of the payload.
    263   };
    264 
    265   // Returns the header, cast to a user-specified type T.  The type T must be a
    266   // subclass of Header and its size must correspond to the header_size passed
    267   // to the Pickle constructor.
    268   template <class T>
    269   T* headerT() {
    270     DCHECK_EQ(header_size_, sizeof(T));
    271     return static_cast<T*>(header_);
    272   }
    273   template <class T>
    274   const T* headerT() const {
    275     DCHECK_EQ(header_size_, sizeof(T));
    276     return static_cast<const T*>(header_);
    277   }
    278 
    279   // The payload is the pickle data immediately following the header.
    280   size_t payload_size() const { return header_->payload_size; }
    281 
    282   const char* payload() const {
    283     return reinterpret_cast<const char*>(header_) + header_size_;
    284   }
    285 
    286   // Returns the address of the byte immediately following the currently valid
    287   // header + payload.
    288   const char* end_of_payload() const {
    289     // This object may be invalid.
    290     return header_ ? payload() + payload_size() : NULL;
    291   }
    292 
    293  protected:
    294   char* mutable_payload() {
    295     return reinterpret_cast<char*>(header_) + header_size_;
    296   }
    297 
    298   size_t capacity() const {
    299     return capacity_;
    300   }
    301 
    302   // Resizes the buffer for use when writing the specified amount of data. The
    303   // location that the data should be written at is returned, or NULL if there
    304   // was an error. Call EndWrite with the returned offset and the given length
    305   // to pad out for the next write.
    306   char* BeginWrite(size_t length);
    307 
    308   // Completes the write operation by padding the data with NULL bytes until it
    309   // is padded. Should be paired with BeginWrite, but it does not necessarily
    310   // have to be called after the data is written.
    311   void EndWrite(char* dest, int length);
    312 
    313   // Resize the capacity, note that the input value should include the size of
    314   // the header: new_capacity = sizeof(Header) + desired_payload_capacity.
    315   // A realloc() failure will cause a Resize failure... and caller should check
    316   // the return result for true (i.e., successful resizing).
    317   bool Resize(size_t new_capacity);
    318 
    319   // Aligns 'i' by rounding it up to the next multiple of 'alignment'
    320   static size_t AlignInt(size_t i, int alignment) {
    321     return i + (alignment - (i % alignment)) % alignment;
    322   }
    323 
    324   // Find the end of the pickled data that starts at range_start.  Returns NULL
    325   // if the entire Pickle is not found in the given data range.
    326   static const char* FindNext(size_t header_size,
    327                               const char* range_start,
    328                               const char* range_end);
    329 
    330   // The allocation granularity of the payload.
    331   static const int kPayloadUnit;
    332 
    333  private:
    334   friend class PickleIterator;
    335 
    336   Header* header_;
    337   size_t header_size_;  // Supports extra data between header and payload.
    338   // Allocation size of payload (or -1 if allocation is const).
    339   size_t capacity_;
    340   size_t variable_buffer_offset_;  // IF non-zero, then offset to a buffer.
    341 
    342   FRIEND_TEST_ALL_PREFIXES(PickleTest, Resize);
    343   FRIEND_TEST_ALL_PREFIXES(PickleTest, FindNext);
    344   FRIEND_TEST_ALL_PREFIXES(PickleTest, FindNextWithIncompleteHeader);
    345 };
    346 
    347 #endif  // BASE_PICKLE_H__
    348