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() : payload_(NULL), read_index_(0), end_index_(0) {}
     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. It is not possible to read from iterator
     30   // after that.
     31   bool ReadBool(bool* result) WARN_UNUSED_RESULT;
     32   bool ReadInt(int* result) WARN_UNUSED_RESULT;
     33   bool ReadLong(long* result) WARN_UNUSED_RESULT;
     34   bool ReadUInt16(uint16* result) WARN_UNUSED_RESULT;
     35   bool ReadUInt32(uint32* result) WARN_UNUSED_RESULT;
     36   bool ReadInt64(int64* result) WARN_UNUSED_RESULT;
     37   bool ReadUInt64(uint64* result) WARN_UNUSED_RESULT;
     38   bool ReadFloat(float* result) WARN_UNUSED_RESULT;
     39   bool ReadDouble(double* result) WARN_UNUSED_RESULT;
     40   bool ReadString(std::string* result) WARN_UNUSED_RESULT;
     41   bool ReadWString(std::wstring* result) WARN_UNUSED_RESULT;
     42   bool ReadString16(base::string16* result) WARN_UNUSED_RESULT;
     43   bool ReadData(const char** data, int* length) WARN_UNUSED_RESULT;
     44   bool ReadBytes(const char** data, int length) WARN_UNUSED_RESULT;
     45 
     46   // Safer version of ReadInt() checks for the result not being negative.
     47   // Use it for reading the object sizes.
     48   bool ReadLength(int* result) WARN_UNUSED_RESULT {
     49     return ReadInt(result) && *result >= 0;
     50   }
     51 
     52   // Skips bytes in the read buffer and returns true if there are at least
     53   // num_bytes available. Otherwise, does nothing and returns false.
     54   bool SkipBytes(int num_bytes) WARN_UNUSED_RESULT {
     55     return !!GetReadPointerAndAdvance(num_bytes);
     56   }
     57 
     58  private:
     59   // Aligns 'i' by rounding it up to the next multiple of 'alignment'
     60   static size_t AlignInt(size_t i, int alignment) {
     61     return i + (alignment - (i % alignment)) % alignment;
     62   }
     63 
     64   // Read Type from Pickle.
     65   template <typename Type>
     66   bool ReadBuiltinType(Type* result);
     67 
     68   // Advance read_index_ but do not allow it to exceed end_index_.
     69   // Keeps read_index_ aligned.
     70   void Advance(size_t size);
     71 
     72   // Get read pointer for Type and advance read pointer.
     73   template<typename Type>
     74   const char* GetReadPointerAndAdvance();
     75 
     76   // Get read pointer for |num_bytes| and advance read pointer. This method
     77   // checks num_bytes for negativity and wrapping.
     78   const char* GetReadPointerAndAdvance(int num_bytes);
     79 
     80   // Get read pointer for (num_elements * size_element) bytes and advance read
     81   // pointer. This method checks for int overflow, negativity and wrapping.
     82   const char* GetReadPointerAndAdvance(int num_elements,
     83                                        size_t size_element);
     84 
     85   const char* payload_;  // Start of our pickle's payload.
     86   size_t read_index_;  // Offset of the next readable byte in payload.
     87   size_t end_index_;  // Payload size.
     88 
     89   FRIEND_TEST_ALL_PREFIXES(PickleTest, GetReadPointerAndAdvance);
     90 };
     91 
     92 // This class provides facilities for basic binary value packing and unpacking.
     93 //
     94 // The Pickle class supports appending primitive values (ints, strings, etc.)
     95 // to a pickle instance.  The Pickle instance grows its internal memory buffer
     96 // dynamically to hold the sequence of primitive values.   The internal memory
     97 // buffer is exposed as the "data" of the Pickle.  This "data" can be passed
     98 // to a Pickle object to initialize it for reading.
     99 //
    100 // When reading from a Pickle object, it is important for the consumer to know
    101 // what value types to read and in what order to read them as the Pickle does
    102 // not keep track of the type of data written to it.
    103 //
    104 // The Pickle's data has a header which contains the size of the Pickle's
    105 // payload.  It can optionally support additional space in the header.  That
    106 // space is controlled by the header_size parameter passed to the Pickle
    107 // constructor.
    108 //
    109 class BASE_EXPORT Pickle {
    110  public:
    111   // Initialize a Pickle object using the default header size.
    112   Pickle();
    113 
    114   // Initialize a Pickle object with the specified header size in bytes, which
    115   // must be greater-than-or-equal-to sizeof(Pickle::Header).  The header size
    116   // will be rounded up to ensure that the header size is 32bit-aligned.
    117   explicit Pickle(int header_size);
    118 
    119   // Initializes a Pickle from a const block of data.  The data is not copied;
    120   // instead the data is merely referenced by this Pickle.  Only const methods
    121   // should be used on the Pickle when initialized this way.  The header
    122   // padding size is deduced from the data length.
    123   Pickle(const char* data, int data_len);
    124 
    125   // Initializes a Pickle as a deep copy of another Pickle.
    126   Pickle(const Pickle& other);
    127 
    128   // Note: There are no virtual methods in this class.  This destructor is
    129   // virtual as an element of defensive coding.  Other classes have derived from
    130   // this class, and there is a *chance* that they will cast into this base
    131   // class before destruction.  At least one such class does have a virtual
    132   // destructor, suggesting at least some need to call more derived destructors.
    133   virtual ~Pickle();
    134 
    135   // Performs a deep copy.
    136   Pickle& operator=(const Pickle& other);
    137 
    138   // Returns the size of the Pickle's data.
    139   size_t size() const { return header_size_ + header_->payload_size; }
    140 
    141   // Returns the data for this Pickle.
    142   const void* data() const { return header_; }
    143 
    144   // For compatibility, these older style read methods pass through to the
    145   // PickleIterator methods.
    146   // TODO(jbates) Remove these methods.
    147   bool ReadBool(PickleIterator* iter,
    148                 bool* result) const WARN_UNUSED_RESULT {
    149     return iter->ReadBool(result);
    150   }
    151   bool ReadInt(PickleIterator* iter,
    152                int* result) const WARN_UNUSED_RESULT {
    153     return iter->ReadInt(result);
    154   }
    155   bool ReadLong(PickleIterator* iter,
    156                 long* result) const WARN_UNUSED_RESULT {
    157     return iter->ReadLong(result);
    158   }
    159   bool ReadUInt16(PickleIterator* iter,
    160                   uint16* result) const WARN_UNUSED_RESULT {
    161     return iter->ReadUInt16(result);
    162   }
    163   bool ReadUInt32(PickleIterator* iter,
    164                   uint32* result) const WARN_UNUSED_RESULT {
    165     return iter->ReadUInt32(result);
    166   }
    167   bool ReadInt64(PickleIterator* iter,
    168                  int64* result) const WARN_UNUSED_RESULT {
    169     return iter->ReadInt64(result);
    170   }
    171   bool ReadUInt64(PickleIterator* iter,
    172                   uint64* result) const WARN_UNUSED_RESULT {
    173     return iter->ReadUInt64(result);
    174   }
    175   bool ReadFloat(PickleIterator* iter,
    176                  float* result) const WARN_UNUSED_RESULT {
    177     return iter->ReadFloat(result);
    178   }
    179   bool ReadDouble(PickleIterator* iter,
    180                   double* result) const WARN_UNUSED_RESULT {
    181     return iter->ReadDouble(result);
    182   }
    183   bool ReadString(PickleIterator* iter,
    184                   std::string* result) const WARN_UNUSED_RESULT {
    185     return iter->ReadString(result);
    186   }
    187   bool ReadWString(PickleIterator* iter,
    188                    std::wstring* result) const WARN_UNUSED_RESULT {
    189     return iter->ReadWString(result);
    190   }
    191   bool ReadString16(PickleIterator* iter,
    192                     base::string16* result) const WARN_UNUSED_RESULT {
    193     return iter->ReadString16(result);
    194   }
    195   // A pointer to the data will be placed in *data, and the length will be
    196   // placed in *length. This buffer will be into the message's buffer so will
    197   // be scoped to the lifetime of the message (or until the message data is
    198   // mutated).
    199   bool ReadData(PickleIterator* iter,
    200                 const char** data,
    201                 int* length) const WARN_UNUSED_RESULT {
    202     return iter->ReadData(data, length);
    203   }
    204   // A pointer to the data will be placed in *data. The caller specifies the
    205   // number of bytes to read, and ReadBytes will validate this length. The
    206   // returned buffer will be into the message's buffer so will be scoped to the
    207   // lifetime of the message (or until the message data is mutated).
    208   bool ReadBytes(PickleIterator* iter,
    209                  const char** data,
    210                  int length) const WARN_UNUSED_RESULT {
    211     return iter->ReadBytes(data, length);
    212   }
    213 
    214   // Safer version of ReadInt() checks for the result not being negative.
    215   // Use it for reading the object sizes.
    216   bool ReadLength(PickleIterator* iter,
    217                   int* result) const  WARN_UNUSED_RESULT {
    218     return iter->ReadLength(result);
    219   }
    220 
    221   // Methods for adding to the payload of the Pickle.  These values are
    222   // appended to the end of the Pickle's payload.  When reading values from a
    223   // Pickle, it is important to read them in the order in which they were added
    224   // to the Pickle.
    225   bool WriteBool(bool value) {
    226     return WriteInt(value ? 1 : 0);
    227   }
    228   bool WriteInt(int value) {
    229     return WritePOD(value);
    230   }
    231   // WARNING: DO NOT USE THIS METHOD IF PICKLES ARE PERSISTED IN ANY WAY.
    232   // It will write whatever a "long" is on this architecture. On 32-bit
    233   // platforms, it is 32 bits. On 64-bit platforms, it is 64 bits. If persisted
    234   // pickles are still around after upgrading to 64-bit, or if they are copied
    235   // between dissimilar systems, YOUR PICKLES WILL HAVE GONE BAD.
    236   bool WriteLongUsingDangerousNonPortableLessPersistableForm(long value) {
    237     return WritePOD(value);
    238   }
    239   bool WriteUInt16(uint16 value) {
    240     return WritePOD(value);
    241   }
    242   bool WriteUInt32(uint32 value) {
    243     return WritePOD(value);
    244   }
    245   bool WriteInt64(int64 value) {
    246     return WritePOD(value);
    247   }
    248   bool WriteUInt64(uint64 value) {
    249     return WritePOD(value);
    250   }
    251   bool WriteFloat(float value) {
    252     return WritePOD(value);
    253   }
    254   bool WriteDouble(double value) {
    255     return WritePOD(value);
    256   }
    257   bool WriteString(const std::string& value);
    258   bool WriteWString(const std::wstring& value);
    259   bool WriteString16(const base::string16& value);
    260   // "Data" is a blob with a length. When you read it out you will be given the
    261   // length. See also WriteBytes.
    262   bool WriteData(const char* data, int length);
    263   // "Bytes" is a blob with no length. The caller must specify the length both
    264   // when reading and writing. It is normally used to serialize PoD types of a
    265   // known size. See also WriteData.
    266   bool WriteBytes(const void* data, int length);
    267 
    268   // Reserves space for upcoming writes when multiple writes will be made and
    269   // their sizes are computed in advance. It can be significantly faster to call
    270   // Reserve() before calling WriteFoo() multiple times.
    271   void Reserve(size_t additional_capacity);
    272 
    273   // Payload follows after allocation of Header (header size is customizable).
    274   struct Header {
    275     uint32 payload_size;  // Specifies the size of the payload.
    276   };
    277 
    278   // Returns the header, cast to a user-specified type T.  The type T must be a
    279   // subclass of Header and its size must correspond to the header_size passed
    280   // to the Pickle constructor.
    281   template <class T>
    282   T* headerT() {
    283     DCHECK_EQ(header_size_, sizeof(T));
    284     return static_cast<T*>(header_);
    285   }
    286   template <class T>
    287   const T* headerT() const {
    288     DCHECK_EQ(header_size_, sizeof(T));
    289     return static_cast<const T*>(header_);
    290   }
    291 
    292   // The payload is the pickle data immediately following the header.
    293   size_t payload_size() const {
    294     return header_ ? header_->payload_size : 0;
    295   }
    296 
    297   const char* payload() const {
    298     return reinterpret_cast<const char*>(header_) + header_size_;
    299   }
    300 
    301   // Returns the address of the byte immediately following the currently valid
    302   // header + payload.
    303   const char* end_of_payload() const {
    304     // This object may be invalid.
    305     return header_ ? payload() + payload_size() : NULL;
    306   }
    307 
    308  protected:
    309   char* mutable_payload() {
    310     return reinterpret_cast<char*>(header_) + header_size_;
    311   }
    312 
    313   size_t capacity_after_header() const {
    314     return capacity_after_header_;
    315   }
    316 
    317   // Resize the capacity, note that the input value should not include the size
    318   // of the header.
    319   void Resize(size_t new_capacity);
    320 
    321   // Aligns 'i' by rounding it up to the next multiple of 'alignment'
    322   static size_t AlignInt(size_t i, int alignment) {
    323     return i + (alignment - (i % alignment)) % alignment;
    324   }
    325 
    326   // Find the end of the pickled data that starts at range_start.  Returns NULL
    327   // if the entire Pickle is not found in the given data range.
    328   static const char* FindNext(size_t header_size,
    329                               const char* range_start,
    330                               const char* range_end);
    331 
    332   // The allocation granularity of the payload.
    333   static const int kPayloadUnit;
    334 
    335  private:
    336   friend class PickleIterator;
    337 
    338   Header* header_;
    339   size_t header_size_;  // Supports extra data between header and payload.
    340   // Allocation size of payload (or -1 if allocation is const). Note: this
    341   // doesn't count the header.
    342   size_t capacity_after_header_;
    343   // The offset at which we will write the next field. Note: this doesn't count
    344   // the header.
    345   size_t write_offset_;
    346 
    347   // Just like WriteBytes, but with a compile-time size, for performance.
    348   template<size_t length> void BASE_EXPORT WriteBytesStatic(const void* data);
    349 
    350   // Writes a POD by copying its bytes.
    351   template <typename T> bool WritePOD(const T& data) {
    352     WriteBytesStatic<sizeof(data)>(&data);
    353     return true;
    354   }
    355   inline void WriteBytesCommon(const void* data, size_t length);
    356 
    357   FRIEND_TEST_ALL_PREFIXES(PickleTest, Resize);
    358   FRIEND_TEST_ALL_PREFIXES(PickleTest, FindNext);
    359   FRIEND_TEST_ALL_PREFIXES(PickleTest, FindNextWithIncompleteHeader);
    360   FRIEND_TEST_ALL_PREFIXES(PickleTest, FindNextOverflow);
    361 };
    362 
    363 #endif  // BASE_PICKLE_H__
    364