summaryrefslogtreecommitdiffstats
path: root/ipc/chromium/src/base/pickle.h
diff options
context:
space:
mode:
Diffstat (limited to 'ipc/chromium/src/base/pickle.h')
-rw-r--r--ipc/chromium/src/base/pickle.h284
1 files changed, 284 insertions, 0 deletions
diff --git a/ipc/chromium/src/base/pickle.h b/ipc/chromium/src/base/pickle.h
new file mode 100644
index 0000000000..5f64880848
--- /dev/null
+++ b/ipc/chromium/src/base/pickle.h
@@ -0,0 +1,284 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_PICKLE_H__
+#define BASE_PICKLE_H__
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "base/string16.h"
+
+#include "mozilla/Attributes.h"
+#include "mozilla/BufferList.h"
+#include "mozilla/mozalloc.h"
+#include "mozilla/TimeStamp.h"
+#if !defined(FUZZING) && (!defined(RELEASE_OR_BETA) || defined(DEBUG))
+# define MOZ_PICKLE_SENTINEL_CHECKING
+#endif
+class Pickle;
+class PickleIterator {
+ public:
+ explicit PickleIterator(const Pickle& pickle);
+
+ private:
+ friend class Pickle;
+
+ mozilla::BufferList<InfallibleAllocPolicy>::IterImpl iter_;
+
+ template <typename T>
+ void CopyInto(T* dest);
+};
+
+// 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();
+
+ Pickle() = delete;
+
+ // 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(uint32_t header_size, size_t segment_capacity = 0);
+
+ Pickle(uint32_t header_size, const char* data, uint32_t length);
+
+ Pickle(const Pickle& other) = delete;
+
+ Pickle(Pickle&& other);
+
+ // Performs a deep copy.
+ Pickle& operator=(const Pickle& other) = delete;
+
+ Pickle& operator=(Pickle&& other);
+
+ void CopyFrom(const Pickle& other);
+
+ // Returns the size of the Pickle's data.
+ uint32_t size() const { return header_size_ + header_->payload_size; }
+
+ typedef mozilla::BufferList<InfallibleAllocPolicy> BufferList;
+
+ const BufferList& Buffers() const { return buffers_; }
+
+ uint32_t CurrentSize() const { return buffers_.Size(); }
+
+ // 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.
+ [[nodiscard]] bool ReadBool(PickleIterator* iter, bool* result) const;
+ [[nodiscard]] bool ReadInt16(PickleIterator* iter, int16_t* result) const;
+ [[nodiscard]] bool ReadUInt16(PickleIterator* iter, uint16_t* result) const;
+ [[nodiscard]] bool ReadShort(PickleIterator* iter, short* result) const;
+ [[nodiscard]] bool ReadInt(PickleIterator* iter, int* result) const;
+ [[nodiscard]] bool ReadLong(PickleIterator* iter, long* result) const;
+ [[nodiscard]] bool ReadULong(PickleIterator* iter,
+ unsigned long* result) const;
+ [[nodiscard]] bool ReadInt32(PickleIterator* iter, int32_t* result) const;
+ [[nodiscard]] bool ReadUInt32(PickleIterator* iter, uint32_t* result) const;
+ [[nodiscard]] bool ReadInt64(PickleIterator* iter, int64_t* result) const;
+ [[nodiscard]] bool ReadUInt64(PickleIterator* iter, uint64_t* result) const;
+ [[nodiscard]] bool ReadDouble(PickleIterator* iter, double* result) const;
+ [[nodiscard]] bool ReadIntPtr(PickleIterator* iter, intptr_t* result) const;
+ [[nodiscard]] bool ReadUnsignedChar(PickleIterator* iter,
+ unsigned char* result) const;
+ [[nodiscard]] bool ReadString(PickleIterator* iter,
+ std::string* result) const;
+ [[nodiscard]] bool ReadWString(PickleIterator* iter,
+ std::wstring* result) const;
+ [[nodiscard]] bool ReadBytesInto(PickleIterator* iter, void* data,
+ uint32_t length) const;
+
+ // Safer version of ReadInt() checks for the result not being negative.
+ // Use it for reading the object sizes.
+ [[nodiscard]] bool ReadLength(PickleIterator* iter, int* result) const;
+
+ [[nodiscard]] bool IgnoreBytes(PickleIterator* iter, uint32_t length) const;
+
+ [[nodiscard]] bool ReadSentinel(PickleIterator* iter, uint32_t sentinel) const
+#ifdef MOZ_PICKLE_SENTINEL_CHECKING
+ ;
+#else
+ {
+ return true;
+ }
+#endif
+
+ template <class T>
+ [[nodiscard]] bool ReadScalar(PickleIterator* iter, T* result) const {
+ DCHECK(iter);
+
+ if (!IteratorHasRoomFor(*iter, sizeof(*result)))
+ return ReadBytesInto(iter, result, sizeof(*result));
+
+ iter->CopyInto(result);
+
+ UpdateIter(iter, sizeof(*result));
+ return true;
+ }
+
+ bool IgnoreSentinel(PickleIterator* iter) const
+#ifdef MOZ_PICKLE_SENTINEL_CHECKING
+ ;
+#else
+ {
+ return true;
+ }
+#endif
+
+ // NOTE: The message type optional parameter should _only_ be called from
+ // generated IPDL code, as it is used to trigger the IPC_READ_LATENCY_MS
+ // telemetry probe.
+ void EndRead(PickleIterator& iter, uint32_t ipcMessageType = 0) const;
+
+ // Returns true if the given iterator has at least |len| bytes remaining it,
+ // across all segments. If there is not that much data available, returns
+ // false. Generally used when reading a (len, data) pair from the message,
+ // before allocating |len| bytes of space, to ensure that reading |len| bytes
+ // will succeed.
+ bool HasBytesAvailable(const PickleIterator* iter, uint32_t len) const;
+
+ // Truncate the message at the current point, discarding any data after this
+ // point in the message.
+ void Truncate(PickleIterator* iter);
+
+ // 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);
+ bool WriteInt16(int16_t value);
+ bool WriteUInt16(uint16_t value);
+ bool WriteInt(int value);
+ bool WriteLong(long value);
+ bool WriteULong(unsigned long value);
+ bool WriteInt32(int32_t value);
+ bool WriteUInt32(uint32_t value);
+ bool WriteInt64(int64_t value);
+ bool WriteUInt64(uint64_t value);
+ bool WriteDouble(double value);
+ bool WriteIntPtr(intptr_t value);
+ bool WriteUnsignedChar(unsigned char value);
+ bool WriteString(const std::string& value);
+ bool WriteWString(const std::wstring& value);
+ bool WriteData(const char* data, uint32_t length);
+ bool WriteBytes(const void* data, uint32_t data_len);
+ // Takes ownership of data
+ bool WriteBytesZeroCopy(void* data, uint32_t data_len, uint32_t capacity);
+
+ bool WriteSentinel(uint32_t sentinel)
+#ifdef MOZ_PICKLE_SENTINEL_CHECKING
+ ;
+#else
+ {
+ return true;
+ }
+#endif
+
+ int32_t* GetInt32PtrForTest(uint32_t offset);
+
+ void InputBytes(const char* data, uint32_t length);
+
+ // Payload follows after allocation of Header (header size is customizable).
+ struct Header {
+ uint32_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_);
+ }
+
+ typedef uint32_t memberAlignmentType;
+
+ protected:
+ uint32_t payload_size() const { return header_->payload_size; }
+
+ // Resizes the buffer for use when writing the specified amount of data. Call
+ // EndWrite with the given length to pad out for the next write.
+ void BeginWrite(uint32_t length);
+
+ // Completes the write operation by padding the data with poison bytes. Should
+ // be paired with BeginWrite, but it does not necessarily have to be called
+ // after the data is written.
+ void EndWrite(uint32_t length);
+
+ // Round 'bytes' up to the next multiple of 'alignment'. 'alignment' must be
+ // a power of 2.
+ template <uint32_t alignment>
+ struct ConstantAligner {
+ static uint32_t align(int bytes) {
+ static_assert((alignment & (alignment - 1)) == 0,
+ "alignment must be a power of two");
+ return (bytes + (alignment - 1)) & ~static_cast<uint32_t>(alignment - 1);
+ }
+ };
+
+ static uint32_t AlignInt(int bytes) {
+ return ConstantAligner<sizeof(memberAlignmentType)>::align(bytes);
+ }
+
+ static uint32_t AlignCapacity(int bytes) {
+ return ConstantAligner<kSegmentAlignment>::align(bytes);
+ }
+
+ // 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 PickleIterator& iter, uint32_t len) const;
+
+ // 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(memberAlignmentType).
+ void UpdateIter(PickleIterator* iter, uint32_t bytes) const;
+
+ // Figure out how big the message starting at range_start is. Returns 0 if
+ // there's no enough data to determine (i.e., if [range_start, range_end) does
+ // not contain enough of the message header to know the size).
+ static uint32_t MessageSize(uint32_t header_size, const char* range_start,
+ const char* range_end);
+
+ // Segments capacities are aligned to 8 bytes to ensure that all reads/writes
+ // at 8-byte aligned offsets will be on 8-byte aligned pointers.
+ static const uint32_t kSegmentAlignment = 8;
+
+ private:
+ friend class PickleIterator;
+
+ BufferList buffers_;
+ Header* header_;
+ uint32_t header_size_;
+};
+
+#endif // BASE_PICKLE_H__