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