Add base to the repository.



git-svn-id: svn://svn.chromium.org/chrome/trunk/src@8 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/base/pickle.h b/base/pickle.h
new file mode 100644
index 0000000..5e97ff5
--- /dev/null
+++ b/base/pickle.h
@@ -0,0 +1,259 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef BASE_PICKLE_H__
+#define BASE_PICKLE_H__
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "testing/gtest/include/gtest/gtest_prod.h"
+
+// This class provides facilities for basic binary value packing and unpacking.
+//
+// The Pickle class supports appending primitive values (ints, strings, etc.)
+// to a pickle instance.  The Pickle instance grows its internal memory buffer
+// dynamically to hold the sequence of primitive values.   The internal memory
+// buffer is exposed as the "data" of the Pickle.  This "data" can be passed
+// to a Pickle object to initialize it for reading.
+//
+// When reading from a Pickle object, it is important for the consumer to know
+// what value types to read and in what order to read them as the Pickle does
+// not keep track of the type of data written to it.
+//
+// The Pickle's data has a header which contains the size of the Pickle's
+// payload.  It can optionally support additional space in the header.  That
+// space is controlled by the header_size parameter passed to the Pickle
+// constructor.
+//
+class Pickle {
+ public:
+  ~Pickle();
+
+  // Initialize a Pickle object using the default header size.
+  Pickle();
+
+  // Initialize a Pickle object with the specified header size in bytes, which
+  // must be greater-than-or-equal-to sizeof(Pickle::Header).  The header size
+  // will be rounded up to ensure that the header size is 32bit-aligned.
+  explicit Pickle(int header_size);
+
+  // Initializes a Pickle from a const block of data.  The data is not copied;
+  // instead the data is merely referenced by this Pickle.  Only const methods
+  // should be used on the Pickle when initialized this way.  The header
+  // padding size is deduced from the data length.
+  Pickle(const char* data, int data_len);
+
+  // Initializes a Pickle as a deep copy of another Pickle.
+  Pickle(const Pickle& other);
+
+  // Performs a deep copy.
+  Pickle& operator=(const Pickle& other);
+
+  // Returns the size of the Pickle's data.
+  int size() const { return static_cast<int>(header_size_ +
+                                             header_->payload_size); }
+
+  // Returns the data for this Pickle.
+  const void* data() const { return header_; }
+
+  // Methods for reading the payload of the Pickle.  To read from the start of
+  // the Pickle, initialize *iter to NULL.  If successful, these methods return
+  // true.  Otherwise, false is returned to indicate that the result could not
+  // be extracted.
+  bool ReadBool(void** iter, bool* result) const;
+  bool ReadInt(void** iter, int* result) const;
+  bool ReadSize(void** iter, size_t* result) const;
+  bool ReadInt64(void** iter, int64* result) const;
+  bool ReadIntPtr(void** iter, intptr_t* result) const;
+  bool ReadString(void** iter, std::string* result) const;
+  bool ReadWString(void** iter, std::wstring* result) const;
+  bool ReadData(void** iter, const char** data, int* length) const;
+  bool ReadBytes(void** iter, const char** data, int length) const;
+
+  // Safer version of ReadInt() checks for the result not being negative.
+  // Use it for reading the object sizes.
+  bool Pickle::ReadLength(void** iter, int* result) const;
+
+  // Methods for adding to the payload of the Pickle.  These values are
+  // appended to the end of the Pickle's payload.  When reading values from a
+  // Pickle, it is important to read them in the order in which they were added
+  // to the Pickle.
+  bool WriteBool(bool value) {
+    return WriteInt(value ? 1 : 0);
+  }
+  bool WriteInt(int value) {
+    return WriteBytes(&value, sizeof(value));
+  }
+  bool WriteSize(size_t value) {
+    return WriteBytes(&value, sizeof(value));
+  }
+  bool WriteInt64(int64 value) {
+    return WriteBytes(&value, sizeof(value));
+  }
+  bool WriteIntPtr(intptr_t value) {
+    return WriteBytes(&value, sizeof(value));
+  }
+  bool WriteString(const std::string& value);
+  bool WriteWString(const std::wstring& value);
+  bool WriteData(const char* data, int length);
+  bool WriteBytes(const void* data, int data_len);
+
+  // Same as WriteData, but allows the caller to write directly into the
+  // Pickle. This saves a copy in cases where the data is not already
+  // available in a buffer. The caller should take care to not write more
+  // than the length it declares it will. Use ReadData to get the data.
+  // Returns NULL on failure.
+  //
+  // The returned pointer will only be valid until the next write operation
+  // on this Pickle.
+  char* BeginWriteData(int length);
+
+  // For Pickles which contain variable length buffers (e.g. those created
+  // with BeginWriteData), the Pickle can
+  // be 'trimmed' if the amount of data required is less than originally
+  // requested.  For example, you may have created a buffer with 10K of data,
+  // but decided to only fill 10 bytes of that data.  Use this function
+  // to trim the buffer so that we don't send 9990 bytes of unused data.
+  // You cannot increase the size of the variable buffer; only shrink it.
+  // This function assumes that the length of the variable buffer has
+  // not been changed.
+  void TrimWriteData(int length);
+
+  // payload follows after allocation of Header (header size is customizable)
+  struct Header {
+    size_t payload_size;  // specifies the size of the payload
+  };
+
+  // Returns the header, cast to a user-specified type T.  The type T must be a
+  // subclass of Header and its size must correspond to the header_size passed
+  // to the Pickle constructor.
+  template <class T>
+  T* headerT() {
+    DCHECK(sizeof(T) == header_size_);
+    return static_cast<T*>(header_);
+  }
+  template <class T>
+  const T* headerT() const {
+    DCHECK(sizeof(T) == header_size_);
+    return static_cast<const T*>(header_);
+  }
+
+  // Returns true if the given iterator could point to data with the given
+  // length. If there is no room for the given data before the end of the
+  // payload, returns false.
+  bool IteratorHasRoomFor(const void* iter, int len) const {
+    if ((len < 0) || (iter < header_) || iter > end_of_payload())
+      return false;
+    const char* end_of_region = reinterpret_cast<const char*>(iter) + len;
+    // Watch out for overflow in pointer calculation, which wraps.
+    return (iter <= end_of_region) && (end_of_region <= end_of_payload());
+  }
+
+ protected:
+  size_t payload_size() const { return header_->payload_size; }
+
+  char* payload() {
+    return reinterpret_cast<char*>(header_) + header_size_;
+  }
+  const char* payload() const {
+    return reinterpret_cast<const char*>(header_) + header_size_;
+  }
+
+  // Returns the address of the byte immediately following the currently valid
+  // header + payload.
+  char* end_of_payload() {
+    return payload() + payload_size();
+  }
+  const char* end_of_payload() const {
+    return payload() + payload_size();
+  }
+
+  size_t capacity() const {
+    return capacity_;
+  }
+
+  // Resizes the buffer for use when writing the specified amount of data. The
+  // location that the data should be written at is returned, or NULL if there
+  // was an error. Call EndWrite with the returned offset and the given length
+  // to pad out for the next write.
+  char* BeginWrite(size_t length);
+
+  // Completes the write operation by padding the data with NULL bytes until it
+  // is padded. Should be paired with BeginWrite, but it does not necessarily
+  // have to be called after the data is written.
+  void EndWrite(char* dest, int length);
+
+  // Resize the capacity, note that the input value should include the size of
+  // the header: new_capacity = sizeof(Header) + desired_payload_capacity.
+  // A realloc() failure will cause a Resize failure... and caller should check
+  // the return result for true (i.e., successful resizing).
+  bool Resize(size_t new_capacity);
+
+  // Aligns 'i' by rounding it up to the next multiple of 'alignment'
+  static inline size_t AlignInt(size_t i, int alignment) {
+    return i + (alignment - (i % alignment)) % alignment;
+  }
+
+  // Moves the iterator by the given number of bytes, making sure it is aligned.
+  // Pointer (iterator) is NOT aligned, but the change in the pointer
+  // is guaranteed to be a multiple of sizeof(uint32).
+  static inline void UpdateIter(void** iter, int bytes) {
+    *iter = static_cast<char*>(*iter) + AlignInt(bytes, sizeof(uint32));
+  }
+
+  // Find the end of the pickled data that starts at range_start.  Returns NULL
+  // if the entire Pickle is not found in the given data range.
+  static const char* FindNext(size_t header_size,
+                              const char* range_start,
+                              const char* range_end);
+
+  // The allocation granularity of the payload.
+  static const int kPayloadUnit;
+
+ private:
+  // A buffer of variable length; used internally
+  struct VariableLengthBuffer {
+    int length;
+    char data;   // This is variable length.
+  };
+
+  Header* header_;
+  size_t header_size_;  // Supports extra data between header and payload.
+  // Allocation size of payload (or -1 if allocation is const).
+  size_t capacity_;
+  size_t variable_buffer_offset_;  // IF non-zero, then offset to a buffer.
+
+  FRIEND_TEST(PickleTest, Resize);
+  FRIEND_TEST(PickleTest, FindNext);
+  FRIEND_TEST(PickleTest, IteratorHasRoom);
+};
+
+#endif  // BASE_PICKLE_H__