| // 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 LIBCHROMEOS_BRILLO_STREAMS_MEMORY_STREAM_H_ |
| #define LIBCHROMEOS_BRILLO_STREAMS_MEMORY_STREAM_H_ |
| |
| #include <string> |
| #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 // LIBCHROMEOS_BRILLO_STREAMS_MEMORY_STREAM_H_ |