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(base::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,
    142                 bool* result) const WARN_UNUSED_RESULT {
    143     return iter->ReadBool(result);
    144   }
    145   bool ReadInt(PickleIterator* iter,
    146                int* result) const WARN_UNUSED_RESULT {
    147     return iter->ReadInt(result);
    148   }
    149   bool ReadLong(PickleIterator* iter,
    150                 long* result) const WARN_UNUSED_RESULT {
    151     return iter->ReadLong(result);
    152   }
    153   bool ReadUInt16(PickleIterator* iter,
    154                   uint16* result) const WARN_UNUSED_RESULT {
    155     return iter->ReadUInt16(result);
    156   }
    157   bool ReadUInt32(PickleIterator* iter,
    158                   uint32* result) const WARN_UNUSED_RESULT {
    159     return iter->ReadUInt32(result);
    160   }
    161   bool ReadInt64(PickleIterator* iter,
    162                  int64* result) const WARN_UNUSED_RESULT {
    163     return iter->ReadInt64(result);
    164   }
    165   bool ReadUInt64(PickleIterator* iter,
    166                   uint64* result) const WARN_UNUSED_RESULT {
    167     return iter->ReadUInt64(result);
    168   }
    169   bool ReadFloat(PickleIterator* iter,
    170                  float* result) const WARN_UNUSED_RESULT {
    171     return iter->ReadFloat(result);
    172   }
    173   bool ReadString(PickleIterator* iter,
    174                   std::string* result) const WARN_UNUSED_RESULT {
    175     return iter->ReadString(result);
    176   }
    177   bool ReadWString(PickleIterator* iter,
    178                    std::wstring* result) const WARN_UNUSED_RESULT {
    179     return iter->ReadWString(result);
    180   }
    181   bool ReadString16(PickleIterator* iter,
    182                     base::string16* result) const WARN_UNUSED_RESULT {
    183     return iter->ReadString16(result);
    184   }
    185   // A pointer to the data will be placed in *data, and the length will be
    186   // placed in *length. This buffer will be into the message's buffer so will
    187   // be scoped to the lifetime of the message (or until the message data is
    188   // mutated).
    189   bool ReadData(PickleIterator* iter,
    190                 const char** data,
    191                 int* length) const WARN_UNUSED_RESULT {
    192     return iter->ReadData(data, length);
    193   }
    194   // A pointer to the data will be placed in *data. The caller specifies the
    195   // number of bytes to read, and ReadBytes will validate this length. The
    196   // returned buffer will be into the message's buffer so will be scoped to the
    197   // lifetime of the message (or until the message data is mutated).
    198   bool ReadBytes(PickleIterator* iter,
    199                  const char** data,
    200                  int length) const WARN_UNUSED_RESULT {
    201     return iter->ReadBytes(data, length);
    202   }
    203 
    204   // Safer version of ReadInt() checks for the result not being negative.
    205   // Use it for reading the object sizes.
    206   bool ReadLength(PickleIterator* iter,
    207                   int* result) const  WARN_UNUSED_RESULT {
    208     return iter->ReadLength(result);
    209   }
    210 
    211   // Methods for adding to the payload of the Pickle.  These values are
    212   // appended to the end of the Pickle's payload.  When reading values from a
    213   // Pickle, it is important to read them in the order in which they were added
    214   // to the Pickle.
    215   bool WriteBool(bool value) {
    216     return WriteInt(value ? 1 : 0);
    217   }
    218   bool WriteInt(int value) {
    219     return WritePOD(value);
    220   }
    221   // WARNING: DO NOT USE THIS METHOD IF PICKLES ARE PERSISTED IN ANY WAY.
    222   // It will write whatever a "long" is on this architecture. On 32-bit
    223   // platforms, it is 32 bits. On 64-bit platforms, it is 64 bits. If persisted
    224   // pickles are still around after upgrading to 64-bit, or if they are copied
    225   // between dissimilar systems, YOUR PICKLES WILL HAVE GONE BAD.
    226   bool WriteLongUsingDangerousNonPortableLessPersistableForm(long value) {
    227     return WritePOD(value);
    228   }
    229   bool WriteUInt16(uint16 value) {
    230     return WritePOD(value);
    231   }
    232   bool WriteUInt32(uint32 value) {
    233     return WritePOD(value);
    234   }
    235   bool WriteInt64(int64 value) {
    236     return WritePOD(value);
    237   }
    238   bool WriteUInt64(uint64 value) {
    239     return WritePOD(value);
    240   }
    241   bool WriteFloat(float value) {
    242     return WritePOD(value);
    243   }
    244   bool WriteString(const std::string& value);
    245   bool WriteWString(const std::wstring& value);
    246   bool WriteString16(const base::string16& value);
    247   // "Data" is a blob with a length. When you read it out you will be given the
    248   // length. See also WriteBytes.
    249   bool WriteData(const char* data, int length);
    250   // "Bytes" is a blob with no length. The caller must specify the length both
    251   // when reading and writing. It is normally used to serialize PoD types of a
    252   // known size. See also WriteData.
    253   bool WriteBytes(const void* data, int length);
    254 
    255   // Reserves space for upcoming writes when multiple writes will be made and
    256   // their sizes are computed in advance. It can be significantly faster to call
    257   // Reserve() before calling WriteFoo() multiple times.
    258   void Reserve(size_t additional_capacity);
    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_after_header() const {
    299     return capacity_after_header_;
    300   }
    301 
    302   // Resize the capacity, note that the input value should not include the size
    303   // of the header.
    304   void Resize(size_t new_capacity);
    305 
    306   // Aligns 'i' by rounding it up to the next multiple of 'alignment'
    307   static size_t AlignInt(size_t i, int alignment) {
    308     return i + (alignment - (i % alignment)) % alignment;
    309   }
    310 
    311   // Find the end of the pickled data that starts at range_start.  Returns NULL
    312   // if the entire Pickle is not found in the given data range.
    313   static const char* FindNext(size_t header_size,
    314                               const char* range_start,
    315                               const char* range_end);
    316 
    317   // The allocation granularity of the payload.
    318   static const int kPayloadUnit;
    319 
    320  private:
    321   friend class PickleIterator;
    322 
    323   Header* header_;
    324   size_t header_size_;  // Supports extra data between header and payload.
    325   // Allocation size of payload (or -1 if allocation is const). Note: this
    326   // doesn't count the header.
    327   size_t capacity_after_header_;
    328   // The offset at which we will write the next field. Note: this doesn't count
    329   // the header.
    330   size_t write_offset_;
    331 
    332   // Just like WriteBytes, but with a compile-time size, for performance.
    333   template<size_t length> void WriteBytesStatic(const void* data);
    334 
    335   // Writes a POD by copying its bytes.
    336   template <typename T> bool WritePOD(const T& data) {
    337     WriteBytesStatic<sizeof(data)>(&data);
    338     return true;
    339   }
    340   inline void WriteBytesCommon(const void* data, size_t length);
    341 
    342   FRIEND_TEST_ALL_PREFIXES(PickleTest, Resize);
    343   FRIEND_TEST_ALL_PREFIXES(PickleTest, FindNext);
    344   FRIEND_TEST_ALL_PREFIXES(PickleTest, FindNextWithIncompleteHeader);
    345   FRIEND_TEST_ALL_PREFIXES(PickleTest, FindNextOverflow);
    346 };
    347 
    348 #endif  // BASE_PICKLE_H__
    349