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() : 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//
109class 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