1 // Copyright 2015 The Chromium OS Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef LIBBRILLO_BRILLO_STREAMS_MEMORY_STREAM_H_ 6 #define LIBBRILLO_BRILLO_STREAMS_MEMORY_STREAM_H_ 7 8 #include <memory> 9 #include <string> 10 #include <utility> 11 #include <vector> 12 13 #include <base/macros.h> 14 #include <base/memory/weak_ptr.h> 15 #include <brillo/brillo_export.h> 16 #include <brillo/streams/memory_containers.h> 17 #include <brillo/streams/stream.h> 18 19 namespace brillo { 20 21 // MemoryStream is a brillo::Stream implementation for memory buffer. A number 22 // of memory containers are supported, such as raw memory pointers, data stored 23 // in std::vector and std::string. 24 // MemoryStream offers support for constant read-only memory buffers as well as 25 // for writable buffers that can grow when needed. 26 // A memory stream is created by using the OpenNNN and CreateNNN factory methods 27 // to construct a read-only and writable streams respectively. 28 // The following factory methods overloads are provided: 29 // - OpenRef - overloads for constructing the stream on a constant read-only 30 // memory buffer that is not owned by the stream. The buffer 31 // pointer/reference must remain valid throughout the lifetime 32 // of the constructed stream object. The benefit of this is that 33 // no data copying is performed and the underlying container can 34 // be manipulated outside of the stream. 35 // - OpenCopyOf - overloads to construct a stream that copies the data from the 36 // memory buffer and maintains the copied data until the stream 37 // is closed or destroyed. This makes it possible to construct 38 // a read-only streams on transient data or for cases where 39 // it is not possible or necessary to maintain the lifetime of 40 // the underlying memory buffer. 41 // - Create - creates a new internal memory buffer that can be written to 42 // or read from using the stream I/O interface. 43 // - CreateRef - constructs a read/write stream on a reference of data 44 // container such as std::vector or std::string which must 45 // remain valid throughout the lifetime of the memory stream. 46 // The data already stored in the container is maintained, 47 // however the stream pointer is set to the beginning of the 48 // data when the stream is created. 49 // - CreateRefForAppend - similar to CreateRef except that it automatically 50 // positions the stream seek pointer at the end of the data, 51 // which makes it possible to append more data to the existing 52 // container. 53 class BRILLO_EXPORT MemoryStream : public Stream { 54 public: 55 // == Construction ========================================================== 56 57 // Constructs a read-only stream on a generic memory buffer. The data 58 // pointed to by |buffer| will be copied and owned by the stream object. 59 static StreamPtr OpenCopyOf(const void* buffer, size_t size, ErrorPtr* error); 60 static StreamPtr OpenCopyOf(std::string buffer, ErrorPtr* error); 61 static StreamPtr OpenCopyOf(const char* buffer, ErrorPtr* error); 62 // Only vectors of char and uint8_t are supported. 63 template<typename T> OpenCopyOf(std::vector<T> buffer,ErrorPtr * error)64 inline static StreamPtr OpenCopyOf(std::vector<T> buffer, ErrorPtr* error) { 65 std::unique_ptr<data_container::ReadOnlyVectorCopy<T>> container{ 66 new data_container::ReadOnlyVectorCopy<T>{std::move(buffer)}}; 67 return CreateEx(std::move(container), 0, error); 68 } 69 70 // Constructs a read-only stream on a generic memory buffer which is owned 71 // by the caller. 72 // ***WARNING***: The |buffer| pointer must be valid for as long as the stream 73 // object is alive. The stream does not do any additional lifetime management 74 // for the data pointed to by |buffer| and destroying that buffer before 75 // the stream is closed will lead to unexpected behavior. 76 static StreamPtr OpenRef(const void* buffer, size_t size, ErrorPtr* error); 77 static StreamPtr OpenRef(const std::string& buffer, ErrorPtr* error); 78 static StreamPtr OpenRef(const char* buffer, ErrorPtr* error); 79 // Only vectors of char and uint8_t are supported. 80 template<typename T> OpenRef(const std::vector<T> & buffer,ErrorPtr * error)81 inline static StreamPtr OpenRef(const std::vector<T>& buffer, 82 ErrorPtr* error) { 83 std::unique_ptr<data_container::ReadOnlyVectorRef<T>> container{ 84 new data_container::ReadOnlyVectorRef<T>{buffer}}; 85 return CreateEx(std::move(container), 0, error); 86 } 87 88 ///------------------------------------------------------------------------ 89 // Creates new stream for reading/writing. This method creates an internal 90 // memory buffer and maintains it until the stream is closed. |reserve_size| 91 // parameter is a hint of the buffer size to pre-allocate. This does not 92 // affect the memory buffer reported size. The buffer can grow past that 93 // amount if needed. 94 static StreamPtr Create(size_t reserve_size, ErrorPtr* error); 95 Create(ErrorPtr * error)96 inline static StreamPtr Create(ErrorPtr* error) { return Create(0, error); } 97 98 // Creates new stream for reading/writing stored in a string. The string 99 // |buffer| must remain valid during the lifetime of the stream. 100 // The stream pointer will be at the beginning of the string and the string's 101 // content is preserved. 102 static StreamPtr CreateRef(std::string* buffer, ErrorPtr* error); 103 104 // Creates new stream for reading/writing stored in a vector. The vector 105 // |buffer| must remain valid during the lifetime of the stream. 106 // The stream pointer will be at the beginning of the data and the vector's 107 // content is preserved. 108 // Only vectors of char and uint8_t are supported. 109 template<typename T> CreateRef(std::vector<T> * buffer,ErrorPtr * error)110 static StreamPtr CreateRef(std::vector<T>* buffer, ErrorPtr* error) { 111 std::unique_ptr<data_container::VectorPtr<T>> container{ 112 new data_container::VectorPtr<T>{buffer}}; 113 return CreateEx(std::move(container), 0, error); 114 } 115 116 // Creates new stream for reading/writing stored in a string. The string 117 // |buffer| must remain valid during the lifetime of the stream. 118 // The stream pointer will be at the end of the string and the string's 119 // content is preserved. 120 static StreamPtr CreateRefForAppend(std::string* buffer, ErrorPtr* error); 121 122 // Creates new stream for reading/writing stored in a vector. The vector 123 // |buffer| must remain valid during the lifetime of the stream. 124 // The stream pointer will be at the end of the data and the vector's 125 // content is preserved. 126 // Only vectors of char and uint8_t are supported. 127 template<typename T> CreateRefForAppend(std::vector<T> * buffer,ErrorPtr * error)128 static StreamPtr CreateRefForAppend(std::vector<T>* buffer, ErrorPtr* error) { 129 std::unique_ptr<data_container::VectorPtr<T>> container{ 130 new data_container::VectorPtr<T>{buffer}}; 131 return CreateEx(std::move(container), buffer->size() * sizeof(T), error); 132 } 133 134 ///------------------------------------------------------------------------ 135 // Generic stream creation on a data container. Takes an arbitrary |container| 136 // and constructs a stream using it. The container determines the traits of 137 // the stream (e.g. whether it is read-only, what operations are supported 138 // and so on). |stream_position| is the current stream pointer position at 139 // creation time. 140 static StreamPtr CreateEx( 141 std::unique_ptr<data_container::DataContainerInterface> container, 142 size_t stream_position, 143 ErrorPtr* error); 144 145 // == Stream capabilities =================================================== 146 bool IsOpen() const override; 147 bool CanRead() const override; 148 bool CanWrite() const override; 149 bool CanSeek() const override; 150 bool CanGetSize() const override; 151 152 // == Stream size operations ================================================ 153 uint64_t GetSize() const override; 154 bool SetSizeBlocking(uint64_t size, ErrorPtr* error) override; 155 uint64_t GetRemainingSize() const override; 156 157 // == Seek operations ======================================================= 158 uint64_t GetPosition() const override; 159 bool Seek(int64_t offset, 160 Whence whence, 161 uint64_t* new_position, 162 ErrorPtr* error) override; 163 164 // == Read operations ======================================================= 165 bool ReadNonBlocking(void* buffer, 166 size_t size_to_read, 167 size_t* size_read, 168 bool* end_of_stream, 169 ErrorPtr* error) override; 170 171 // == Write operations ====================================================== 172 bool WriteNonBlocking(const void* buffer, 173 size_t size_to_write, 174 size_t* size_written, 175 ErrorPtr* error) override; 176 177 // == Finalizing/closing streams =========================================== 178 bool FlushBlocking(ErrorPtr* error) override; 179 bool CloseBlocking(ErrorPtr* error) override; 180 181 // == Data availability monitoring ========================================== 182 bool WaitForData(AccessMode mode, 183 const base::Callback<void(AccessMode)>& callback, 184 ErrorPtr* error) override; 185 186 bool WaitForDataBlocking(AccessMode in_mode, 187 base::TimeDelta timeout, 188 AccessMode* out_mode, 189 ErrorPtr* error) override; 190 191 private: 192 friend class MemoryStreamTest; 193 194 // Private constructor used by MemoryStream::OpenNNNN() and 195 // MemoryStream::CreateNNNN() factory methods. 196 MemoryStream( 197 std::unique_ptr<data_container::DataContainerInterface> container, 198 size_t stream_position); 199 200 // Checks if the stream has a valid container. 201 bool CheckContainer(ErrorPtr* error) const; 202 203 // Data container the stream is using to write and/or read data. 204 std::unique_ptr<data_container::DataContainerInterface> container_; 205 206 // The current stream pointer position. 207 size_t stream_position_{0}; 208 209 DISALLOW_COPY_AND_ASSIGN(MemoryStream); 210 }; 211 212 } // namespace brillo 213 214 #endif // LIBBRILLO_BRILLO_STREAMS_MEMORY_STREAM_H_ 215