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
17class Pickle;
18
19// PickleIterator reads data from a Pickle. The Pickle object must remain valid
20// while the PickleIterator object is in use.
21class 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//
103class 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