You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
290 lines
11 KiB
290 lines
11 KiB
// 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_CONTAINERS_H_
|
|
#define LIBBRILLO_BRILLO_STREAMS_MEMORY_CONTAINERS_H_
|
|
|
|
#include <string>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include <brillo/brillo_export.h>
|
|
#include <brillo/errors/error.h>
|
|
#include <brillo/streams/stream.h>
|
|
|
|
namespace brillo {
|
|
namespace data_container {
|
|
|
|
// MemoryStream class relies on helper classes defined below to support data
|
|
// storage in various types of containers.
|
|
// A particular implementation of container type (e.g. based on raw memory
|
|
// buffers, std::vector, std::string or others) need to implement the container
|
|
// interface provided by data_container::DataContainerInterface.
|
|
// Low-level functionality such as reading data from and writing data to the
|
|
// container, getting and changing the buffer size, and so on, must be provided.
|
|
// Not all methods must be provided. For example, for read-only containers, only
|
|
// read operations can be provided.
|
|
class BRILLO_EXPORT DataContainerInterface {
|
|
public:
|
|
DataContainerInterface() = default;
|
|
virtual ~DataContainerInterface() = default;
|
|
|
|
// Read the data from the container into |buffer|. Up to |size_to_read| bytes
|
|
// must be read at a time. The container can return fewer bytes. The actual
|
|
// size of data read is provided in |size_read|.
|
|
// If the read operation fails, the function must return false and provide
|
|
// additional information about the error in |error| object.
|
|
virtual bool Read(void* buffer,
|
|
size_t size_to_read,
|
|
size_t offset,
|
|
size_t* size_read,
|
|
ErrorPtr* error) = 0;
|
|
|
|
// Writes |size_to_write| bytes of data from |buffer| into the container.
|
|
// The container may accept fewer bytes of data. The actual size of data
|
|
// written is provided in |size_written|.
|
|
// If the read operation fails, the function must return false and provide
|
|
// additional information about the error in |error| object.
|
|
virtual bool Write(const void* buffer,
|
|
size_t size_to_write,
|
|
size_t offset,
|
|
size_t* size_written,
|
|
ErrorPtr* error) = 0;
|
|
// Resizes the container to the new size specified in |new_size|.
|
|
virtual bool Resize(size_t new_size, ErrorPtr* error) = 0;
|
|
// Returns the current size of the container.
|
|
virtual size_t GetSize() const = 0;
|
|
// Returns true if the container is read-only.
|
|
virtual bool IsReadOnly() const = 0;
|
|
|
|
private:
|
|
DISALLOW_COPY_AND_ASSIGN(DataContainerInterface);
|
|
};
|
|
|
|
// ContiguousBufferBase is a helper base class for memory containers that
|
|
// employ contiguous memory for all of their data. This class provides the
|
|
// default implementation for Read() and Write() functions and requires the
|
|
// implementations to provide GetBuffer() and/or ReadOnlyBuffer() functions.
|
|
class BRILLO_EXPORT ContiguousBufferBase : public DataContainerInterface {
|
|
public:
|
|
ContiguousBufferBase() = default;
|
|
// Implementation of DataContainerInterface::Read().
|
|
bool Read(void* buffer,
|
|
size_t size_to_read,
|
|
size_t offset,
|
|
size_t* size_read,
|
|
ErrorPtr* error) override;
|
|
// Implementation of DataContainerInterface::Write().
|
|
bool Write(const void* buffer,
|
|
size_t size_to_write,
|
|
size_t offset,
|
|
size_t* size_written,
|
|
ErrorPtr* error) override;
|
|
|
|
// Overload to provide the pointer to the read-only data for the container at
|
|
// the specified |offset|. In case of an error, this function must return
|
|
// nullptr and provide error details in |error| object if provided.
|
|
virtual const void* GetReadOnlyBuffer(size_t offset,
|
|
ErrorPtr* error) const = 0;
|
|
// Overload to provide the pointer to the read/write data for the container at
|
|
// the specified |offset|. In case of an error, this function must return
|
|
// nullptr and provide error details in |error| object if provided.
|
|
virtual void* GetBuffer(size_t offset, ErrorPtr* error) = 0;
|
|
|
|
protected:
|
|
// Wrapper around memcpy which can be mocked out in tests.
|
|
virtual void CopyMemoryBlock(void* dest, const void* src, size_t size) const;
|
|
|
|
private:
|
|
DISALLOW_COPY_AND_ASSIGN(ContiguousBufferBase);
|
|
};
|
|
|
|
// ContiguousReadOnlyBufferBase is a specialization of ContiguousBufferBase for
|
|
// read-only containers.
|
|
class BRILLO_EXPORT ContiguousReadOnlyBufferBase : public ContiguousBufferBase {
|
|
public:
|
|
ContiguousReadOnlyBufferBase() = default;
|
|
// Fails with an error "operation_not_supported" (Stream is read-only) error.
|
|
bool Write(const void* buffer,
|
|
size_t size_to_write,
|
|
size_t offset,
|
|
size_t* size_written,
|
|
ErrorPtr* error) override;
|
|
// Fails with an error "operation_not_supported" (Stream is read-only) error.
|
|
bool Resize(size_t new_size, ErrorPtr* error) override;
|
|
// Fails with an error "operation_not_supported" (Stream is read-only) error.
|
|
bool IsReadOnly() const override { return true; }
|
|
// Fails with an error "operation_not_supported" (Stream is read-only) error.
|
|
void* GetBuffer(size_t offset, ErrorPtr* error) override;
|
|
|
|
private:
|
|
DISALLOW_COPY_AND_ASSIGN(ContiguousReadOnlyBufferBase);
|
|
};
|
|
|
|
// ReadOnlyBuffer implements a read-only container based on raw memory block.
|
|
class BRILLO_EXPORT ReadOnlyBuffer : public ContiguousReadOnlyBufferBase {
|
|
public:
|
|
// Constructs the container based at the pointer to memory |buffer| and its
|
|
// |size|. The pointer to the memory must be valid throughout life-time of
|
|
// the stream using this container.
|
|
ReadOnlyBuffer(const void* buffer, size_t size)
|
|
: buffer_(buffer), size_(size) {}
|
|
|
|
// Returns the pointer to data at |offset|.
|
|
const void* GetReadOnlyBuffer(size_t offset,
|
|
ErrorPtr* /* error */) const override {
|
|
return reinterpret_cast<const uint8_t*>(buffer_) + offset;
|
|
}
|
|
// Returns the size of the container.
|
|
size_t GetSize() const override { return size_; }
|
|
|
|
private:
|
|
// Raw memory pointer to the data block and its size.
|
|
const void* buffer_;
|
|
size_t size_;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(ReadOnlyBuffer);
|
|
};
|
|
|
|
// VectorPtr<T> is a read/write container based on a vector<T> pointer.
|
|
// This is a template class to allow usage of both vector<char> and
|
|
// vector<uint8_t> without duplicating the implementation.
|
|
template<typename T>
|
|
class VectorPtr : public ContiguousBufferBase {
|
|
public:
|
|
static_assert(sizeof(T) == 1, "Only char/byte is supported");
|
|
explicit VectorPtr(std::vector<T>* vector) : vector_ptr_(vector) {}
|
|
|
|
bool Resize(size_t new_size, ErrorPtr* /* error */) override {
|
|
vector_ptr_->resize(new_size);
|
|
return true;
|
|
}
|
|
size_t GetSize() const override { return vector_ptr_->size(); }
|
|
bool IsReadOnly() const override { return false; }
|
|
const void* GetReadOnlyBuffer(size_t offset,
|
|
ErrorPtr* /* error */) const override {
|
|
return reinterpret_cast<const uint8_t*>(vector_ptr_->data()) + offset;
|
|
}
|
|
void* GetBuffer(size_t offset, ErrorPtr* /* error */) override {
|
|
return reinterpret_cast<uint8_t*>(vector_ptr_->data()) + offset;
|
|
}
|
|
|
|
protected:
|
|
std::vector<T>* vector_ptr_;
|
|
|
|
private:
|
|
DISALLOW_COPY_AND_ASSIGN(VectorPtr);
|
|
};
|
|
|
|
// ReadOnlyVectorRef<T> is a read-only container based on a vector<T> reference.
|
|
// This is a template class to allow usage of both vector<char> and
|
|
// vector<uint8_t> without duplicating the implementation.
|
|
template<typename T>
|
|
class ReadOnlyVectorRef : public ContiguousReadOnlyBufferBase {
|
|
public:
|
|
static_assert(sizeof(T) == 1, "Only char/byte is supported");
|
|
explicit ReadOnlyVectorRef(const std::vector<T>& vector)
|
|
: vector_ref_(vector) {}
|
|
|
|
const void* GetReadOnlyBuffer(size_t offset,
|
|
ErrorPtr* /* error */) const override {
|
|
return reinterpret_cast<const uint8_t*>(vector_ref_.data()) + offset;
|
|
}
|
|
size_t GetSize() const override { return vector_ref_.size(); }
|
|
|
|
protected:
|
|
const std::vector<T>& vector_ref_;
|
|
|
|
private:
|
|
DISALLOW_COPY_AND_ASSIGN(ReadOnlyVectorRef);
|
|
};
|
|
|
|
// ReadOnlyVectorCopy<T> is a read-only container based on a copy of vector<T>.
|
|
// This container actually owns the data stored in the vector.
|
|
// This is a template class to allow usage of both vector<char> and
|
|
// vector<uint8_t> without duplicating the implementation.
|
|
template<typename T>
|
|
class ReadOnlyVectorCopy : public ContiguousReadOnlyBufferBase {
|
|
public:
|
|
static_assert(sizeof(T) == 1, "Only char/byte is supported");
|
|
explicit ReadOnlyVectorCopy(std::vector<T> vector)
|
|
: vector_copy_(std::move(vector)) {}
|
|
|
|
ReadOnlyVectorCopy(const T* buffer, size_t size)
|
|
: vector_copy_(buffer, buffer + size) {}
|
|
|
|
const void* GetReadOnlyBuffer(size_t offset,
|
|
ErrorPtr* /* error */) const override {
|
|
return reinterpret_cast<const uint8_t*>(vector_copy_.data()) + offset;
|
|
}
|
|
size_t GetSize() const override { return vector_copy_.size(); }
|
|
|
|
protected:
|
|
std::vector<T> vector_copy_;
|
|
|
|
private:
|
|
DISALLOW_COPY_AND_ASSIGN(ReadOnlyVectorCopy);
|
|
};
|
|
|
|
// ByteBuffer is a read/write container that manages the data and underlying
|
|
// storage.
|
|
class BRILLO_EXPORT ByteBuffer : public VectorPtr<uint8_t> {
|
|
public:
|
|
explicit ByteBuffer(size_t reserve_size);
|
|
~ByteBuffer() override;
|
|
|
|
private:
|
|
DISALLOW_COPY_AND_ASSIGN(ByteBuffer);
|
|
};
|
|
|
|
// StringPtr is a read/write container based on external std::string storage.
|
|
class BRILLO_EXPORT StringPtr : public ContiguousBufferBase {
|
|
public:
|
|
explicit StringPtr(std::string* string);
|
|
|
|
bool Resize(size_t new_size, ErrorPtr* error) override;
|
|
size_t GetSize() const override { return string_ptr_->size(); }
|
|
bool IsReadOnly() const override { return false; }
|
|
const void* GetReadOnlyBuffer(size_t offset, ErrorPtr* error) const override;
|
|
void* GetBuffer(size_t offset, ErrorPtr* error) override;
|
|
|
|
protected:
|
|
std::string* string_ptr_;
|
|
|
|
private:
|
|
DISALLOW_COPY_AND_ASSIGN(StringPtr);
|
|
};
|
|
|
|
// ReadOnlyStringRef is a read-only container based on external std::string.
|
|
class BRILLO_EXPORT ReadOnlyStringRef : public ContiguousReadOnlyBufferBase {
|
|
public:
|
|
explicit ReadOnlyStringRef(const std::string& string);
|
|
const void* GetReadOnlyBuffer(size_t offset, ErrorPtr* error) const override;
|
|
size_t GetSize() const override { return string_ref_.size(); }
|
|
|
|
protected:
|
|
const std::string& string_ref_;
|
|
|
|
private:
|
|
DISALLOW_COPY_AND_ASSIGN(ReadOnlyStringRef);
|
|
};
|
|
|
|
// ReadOnlyStringCopy is a read-only container based on a copy of a std::string.
|
|
// This container actually owns the data stored in the string.
|
|
class BRILLO_EXPORT ReadOnlyStringCopy : public ReadOnlyStringRef {
|
|
public:
|
|
explicit ReadOnlyStringCopy(std::string string);
|
|
|
|
protected:
|
|
std::string string_copy_;
|
|
|
|
private:
|
|
DISALLOW_COPY_AND_ASSIGN(ReadOnlyStringCopy);
|
|
};
|
|
|
|
} // namespace data_container
|
|
} // namespace brillo
|
|
|
|
#endif // LIBBRILLO_BRILLO_STREAMS_MEMORY_CONTAINERS_H_
|