// Copyright 2013 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 MOJO_PUBLIC_CPP_BINDINGS_LIB_BUFFER_H_
#define MOJO_PUBLIC_CPP_BINDINGS_LIB_BUFFER_H_
#include <stddef.h>
#include <stdint.h>
#include <vector>
#include "base/component_export.h"
#include "base/macros.h"
#include "mojo/public/cpp/system/handle.h"
#include "mojo/public/cpp/system/message.h"
namespace mojo {
namespace internal {
// Buffer provides an interface to allocate memory blocks which are 8-byte
// aligned. It doesn't own the underlying memory. Users must ensure that the
// memory stays valid while using the allocated blocks from Buffer.
//
// A Buffer may be moved around. A moved-from Buffer is reset and may no longer
// be used to Allocate memory unless re-Initialized.
class COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) Buffer {
public:
// Constructs an invalid Buffer. May not call Allocate().
Buffer();
// Constructs a Buffer which can Allocate() blocks from a buffer of fixed size
// |size| at |data|. Allocations start at |cursor|, so if |cursor| == |size|
// then no allocations are allowed.
//
// |data| is not owned.
Buffer(void* data, size_t size, size_t cursor);
// Like above, but gives the Buffer an underlying message object which can
// have its payload extended to acquire more storage capacity on Allocate().
//
// |data| and |size| must correspond to |message|'s data buffer at the time of
// construction.
//
// |payload_size| is the length of the payload as known by |message|, and it
// must be less than or equal to |size|.
//
// |message| is NOT owned and must outlive this Buffer.
Buffer(MessageHandle message,
size_t message_payload_size,
void* data,
size_t size);
Buffer(Buffer&& other);
~Buffer();
Buffer& operator=(Buffer&& other);
void* data() const { return data_; }
size_t size() const { return size_; }
size_t cursor() const { return cursor_; }
bool is_valid() const {
return data_ != nullptr || (size_ == 0 && !message_.is_valid());
}
// Allocates |num_bytes| from the buffer and returns an index to the start of
// the allocated block. The resulting index is 8-byte aligned and can be
// resolved to an address using Get<T>() below.
size_t Allocate(size_t num_bytes);
// Returns a typed address within the Buffer corresponding to |index|. Note
// that this address is NOT stable across calls to |Allocate()| and thus must
// not be cached accordingly.
template <typename T>
T* Get(size_t index) {
DCHECK_LT(index, cursor_);
return reinterpret_cast<T*>(static_cast<uint8_t*>(data_) + index);
}
// A template helper combining Allocate() and Get<T>() above to allocate and
// return a block of size |sizeof(T)|.
template <typename T>
T* AllocateAndGet() {
return Get<T>(Allocate(sizeof(T)));
}
// A helper which combines Allocate() and Get<void>() for a specified number
// of bytes.
void* AllocateAndGet(size_t num_bytes) {
return Get<void>(Allocate(num_bytes));
}
// Serializes |handles| into the buffer object. Only valid to call when this
// Buffer is backed by a message object.
void AttachHandles(std::vector<ScopedHandle>* handles);
// Seals this Buffer so it can no longer be used for allocation, and ensures
// the backing message object has a complete accounting of the size of the
// meaningful payload bytes.
void Seal();
// Resets the buffer to an invalid state. Can no longer be used to Allocate().
void Reset();
private:
MessageHandle message_;
// The payload size from the message's internal perspective. This differs from
// |size_| as Mojo may intentionally over-allocate space to account for future
// growth. It differs from |cursor_| because we don't push payload size
// updates to the message object as frequently as we update |cursor_|, for
// performance.
size_t message_payload_size_ = 0;
// The storage location and capacity currently backing |message_|. Owned by
// the message object internally, not by this Buffer.
void* data_ = nullptr;
size_t size_ = 0;
// The current write offset into |data_| if this Buffer is being used for
// message creation.
size_t cursor_ = 0;
DISALLOW_COPY_AND_ASSIGN(Buffer);
};
} // namespace internal
} // namespace mojo
#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_BUFFER_H_