215 lines
9.9 KiB
C++
215 lines
9.9 KiB
C++
// Copyright 2015 The Chromium OS 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 LIBBRILLO_BRILLO_STREAMS_MEMORY_STREAM_H_
|
|
#define LIBBRILLO_BRILLO_STREAMS_MEMORY_STREAM_H_
|
|
|
|
#include <memory>
|
|
#include <string>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include <base/macros.h>
|
|
#include <base/memory/weak_ptr.h>
|
|
#include <brillo/brillo_export.h>
|
|
#include <brillo/streams/memory_containers.h>
|
|
#include <brillo/streams/stream.h>
|
|
|
|
namespace brillo {
|
|
|
|
// MemoryStream is a brillo::Stream implementation for memory buffer. A number
|
|
// of memory containers are supported, such as raw memory pointers, data stored
|
|
// in std::vector and std::string.
|
|
// MemoryStream offers support for constant read-only memory buffers as well as
|
|
// for writable buffers that can grow when needed.
|
|
// A memory stream is created by using the OpenNNN and CreateNNN factory methods
|
|
// to construct a read-only and writable streams respectively.
|
|
// The following factory methods overloads are provided:
|
|
// - OpenRef - overloads for constructing the stream on a constant read-only
|
|
// memory buffer that is not owned by the stream. The buffer
|
|
// pointer/reference must remain valid throughout the lifetime
|
|
// of the constructed stream object. The benefit of this is that
|
|
// no data copying is performed and the underlying container can
|
|
// be manipulated outside of the stream.
|
|
// - OpenCopyOf - overloads to construct a stream that copies the data from the
|
|
// memory buffer and maintains the copied data until the stream
|
|
// is closed or destroyed. This makes it possible to construct
|
|
// a read-only streams on transient data or for cases where
|
|
// it is not possible or necessary to maintain the lifetime of
|
|
// the underlying memory buffer.
|
|
// - Create - creates a new internal memory buffer that can be written to
|
|
// or read from using the stream I/O interface.
|
|
// - CreateRef - constructs a read/write stream on a reference of data
|
|
// container such as std::vector or std::string which must
|
|
// remain valid throughout the lifetime of the memory stream.
|
|
// The data already stored in the container is maintained,
|
|
// however the stream pointer is set to the beginning of the
|
|
// data when the stream is created.
|
|
// - CreateRefForAppend - similar to CreateRef except that it automatically
|
|
// positions the stream seek pointer at the end of the data,
|
|
// which makes it possible to append more data to the existing
|
|
// container.
|
|
class BRILLO_EXPORT MemoryStream : public Stream {
|
|
public:
|
|
// == Construction ==========================================================
|
|
|
|
// Constructs a read-only stream on a generic memory buffer. The data
|
|
// pointed to by |buffer| will be copied and owned by the stream object.
|
|
static StreamPtr OpenCopyOf(const void* buffer, size_t size, ErrorPtr* error);
|
|
static StreamPtr OpenCopyOf(std::string buffer, ErrorPtr* error);
|
|
static StreamPtr OpenCopyOf(const char* buffer, ErrorPtr* error);
|
|
// Only vectors of char and uint8_t are supported.
|
|
template<typename T>
|
|
inline static StreamPtr OpenCopyOf(std::vector<T> buffer, ErrorPtr* error) {
|
|
std::unique_ptr<data_container::ReadOnlyVectorCopy<T>> container{
|
|
new data_container::ReadOnlyVectorCopy<T>{std::move(buffer)}};
|
|
return CreateEx(std::move(container), 0, error);
|
|
}
|
|
|
|
// Constructs a read-only stream on a generic memory buffer which is owned
|
|
// by the caller.
|
|
// ***WARNING***: The |buffer| pointer must be valid for as long as the stream
|
|
// object is alive. The stream does not do any additional lifetime management
|
|
// for the data pointed to by |buffer| and destroying that buffer before
|
|
// the stream is closed will lead to unexpected behavior.
|
|
static StreamPtr OpenRef(const void* buffer, size_t size, ErrorPtr* error);
|
|
static StreamPtr OpenRef(const std::string& buffer, ErrorPtr* error);
|
|
static StreamPtr OpenRef(const char* buffer, ErrorPtr* error);
|
|
// Only vectors of char and uint8_t are supported.
|
|
template<typename T>
|
|
inline static StreamPtr OpenRef(const std::vector<T>& buffer,
|
|
ErrorPtr* error) {
|
|
std::unique_ptr<data_container::ReadOnlyVectorRef<T>> container{
|
|
new data_container::ReadOnlyVectorRef<T>{buffer}};
|
|
return CreateEx(std::move(container), 0, error);
|
|
}
|
|
|
|
///------------------------------------------------------------------------
|
|
// Creates new stream for reading/writing. This method creates an internal
|
|
// memory buffer and maintains it until the stream is closed. |reserve_size|
|
|
// parameter is a hint of the buffer size to pre-allocate. This does not
|
|
// affect the memory buffer reported size. The buffer can grow past that
|
|
// amount if needed.
|
|
static StreamPtr Create(size_t reserve_size, ErrorPtr* error);
|
|
|
|
inline static StreamPtr Create(ErrorPtr* error) { return Create(0, error); }
|
|
|
|
// Creates new stream for reading/writing stored in a string. The string
|
|
// |buffer| must remain valid during the lifetime of the stream.
|
|
// The stream pointer will be at the beginning of the string and the string's
|
|
// content is preserved.
|
|
static StreamPtr CreateRef(std::string* buffer, ErrorPtr* error);
|
|
|
|
// Creates new stream for reading/writing stored in a vector. The vector
|
|
// |buffer| must remain valid during the lifetime of the stream.
|
|
// The stream pointer will be at the beginning of the data and the vector's
|
|
// content is preserved.
|
|
// Only vectors of char and uint8_t are supported.
|
|
template<typename T>
|
|
static StreamPtr CreateRef(std::vector<T>* buffer, ErrorPtr* error) {
|
|
std::unique_ptr<data_container::VectorPtr<T>> container{
|
|
new data_container::VectorPtr<T>{buffer}};
|
|
return CreateEx(std::move(container), 0, error);
|
|
}
|
|
|
|
// Creates new stream for reading/writing stored in a string. The string
|
|
// |buffer| must remain valid during the lifetime of the stream.
|
|
// The stream pointer will be at the end of the string and the string's
|
|
// content is preserved.
|
|
static StreamPtr CreateRefForAppend(std::string* buffer, ErrorPtr* error);
|
|
|
|
// Creates new stream for reading/writing stored in a vector. The vector
|
|
// |buffer| must remain valid during the lifetime of the stream.
|
|
// The stream pointer will be at the end of the data and the vector's
|
|
// content is preserved.
|
|
// Only vectors of char and uint8_t are supported.
|
|
template<typename T>
|
|
static StreamPtr CreateRefForAppend(std::vector<T>* buffer, ErrorPtr* error) {
|
|
std::unique_ptr<data_container::VectorPtr<T>> container{
|
|
new data_container::VectorPtr<T>{buffer}};
|
|
return CreateEx(std::move(container), buffer->size() * sizeof(T), error);
|
|
}
|
|
|
|
///------------------------------------------------------------------------
|
|
// Generic stream creation on a data container. Takes an arbitrary |container|
|
|
// and constructs a stream using it. The container determines the traits of
|
|
// the stream (e.g. whether it is read-only, what operations are supported
|
|
// and so on). |stream_position| is the current stream pointer position at
|
|
// creation time.
|
|
static StreamPtr CreateEx(
|
|
std::unique_ptr<data_container::DataContainerInterface> container,
|
|
size_t stream_position,
|
|
ErrorPtr* error);
|
|
|
|
// == Stream capabilities ===================================================
|
|
bool IsOpen() const override;
|
|
bool CanRead() const override;
|
|
bool CanWrite() const override;
|
|
bool CanSeek() const override;
|
|
bool CanGetSize() const override;
|
|
|
|
// == Stream size operations ================================================
|
|
uint64_t GetSize() const override;
|
|
bool SetSizeBlocking(uint64_t size, ErrorPtr* error) override;
|
|
uint64_t GetRemainingSize() const override;
|
|
|
|
// == Seek operations =======================================================
|
|
uint64_t GetPosition() const override;
|
|
bool Seek(int64_t offset,
|
|
Whence whence,
|
|
uint64_t* new_position,
|
|
ErrorPtr* error) override;
|
|
|
|
// == Read operations =======================================================
|
|
bool ReadNonBlocking(void* buffer,
|
|
size_t size_to_read,
|
|
size_t* size_read,
|
|
bool* end_of_stream,
|
|
ErrorPtr* error) override;
|
|
|
|
// == Write operations ======================================================
|
|
bool WriteNonBlocking(const void* buffer,
|
|
size_t size_to_write,
|
|
size_t* size_written,
|
|
ErrorPtr* error) override;
|
|
|
|
// == Finalizing/closing streams ===========================================
|
|
bool FlushBlocking(ErrorPtr* error) override;
|
|
bool CloseBlocking(ErrorPtr* error) override;
|
|
|
|
// == Data availability monitoring ==========================================
|
|
bool WaitForData(AccessMode mode,
|
|
const base::Callback<void(AccessMode)>& callback,
|
|
ErrorPtr* error) override;
|
|
|
|
bool WaitForDataBlocking(AccessMode in_mode,
|
|
base::TimeDelta timeout,
|
|
AccessMode* out_mode,
|
|
ErrorPtr* error) override;
|
|
|
|
private:
|
|
friend class MemoryStreamTest;
|
|
|
|
// Private constructor used by MemoryStream::OpenNNNN() and
|
|
// MemoryStream::CreateNNNN() factory methods.
|
|
MemoryStream(
|
|
std::unique_ptr<data_container::DataContainerInterface> container,
|
|
size_t stream_position);
|
|
|
|
// Checks if the stream has a valid container.
|
|
bool CheckContainer(ErrorPtr* error) const;
|
|
|
|
// Data container the stream is using to write and/or read data.
|
|
std::unique_ptr<data_container::DataContainerInterface> container_;
|
|
|
|
// The current stream pointer position.
|
|
size_t stream_position_{0};
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(MemoryStream);
|
|
};
|
|
|
|
} // namespace brillo
|
|
|
|
#endif // LIBBRILLO_BRILLO_STREAMS_MEMORY_STREAM_H_
|