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_CONTAINERS_H_ 6 #define LIBBRILLO_BRILLO_STREAMS_MEMORY_CONTAINERS_H_ 7 8 #include <string> 9 #include <utility> 10 #include <vector> 11 12 #include <brillo/brillo_export.h> 13 #include <brillo/errors/error.h> 14 #include <brillo/streams/stream.h> 15 16 namespace brillo { 17 namespace data_container { 18 19 // MemoryStream class relies on helper classes defined below to support data 20 // storage in various types of containers. 21 // A particular implementation of container type (e.g. based on raw memory 22 // buffers, std::vector, std::string or others) need to implement the container 23 // interface provided by data_container::DataContainerInterface. 24 // Low-level functionality such as reading data from and writing data to the 25 // container, getting and changing the buffer size, and so on, must be provided. 26 // Not all methods must be provided. For example, for read-only containers, only 27 // read operations can be provided. 28 class BRILLO_EXPORT DataContainerInterface { 29 public: 30 DataContainerInterface() = default; 31 virtual ~DataContainerInterface() = default; 32 33 // Read the data from the container into |buffer|. Up to |size_to_read| bytes 34 // must be read at a time. The container can return fewer bytes. The actual 35 // size of data read is provided in |size_read|. 36 // If the read operation fails, the function must return false and provide 37 // additional information about the error in |error| object. 38 virtual bool Read(void* buffer, 39 size_t size_to_read, 40 size_t offset, 41 size_t* size_read, 42 ErrorPtr* error) = 0; 43 44 // Writes |size_to_write| bytes of data from |buffer| into the container. 45 // The container may accept fewer bytes of data. The actual size of data 46 // written is provided in |size_written|. 47 // If the read operation fails, the function must return false and provide 48 // additional information about the error in |error| object. 49 virtual bool Write(const void* buffer, 50 size_t size_to_write, 51 size_t offset, 52 size_t* size_written, 53 ErrorPtr* error) = 0; 54 // Resizes the container to the new size specified in |new_size|. 55 virtual bool Resize(size_t new_size, ErrorPtr* error) = 0; 56 // Returns the current size of the container. 57 virtual size_t GetSize() const = 0; 58 // Returns true if the container is read-only. 59 virtual bool IsReadOnly() const = 0; 60 61 private: 62 DISALLOW_COPY_AND_ASSIGN(DataContainerInterface); 63 }; 64 65 // ContiguousBufferBase is a helper base class for memory containers that 66 // employ contiguous memory for all of their data. This class provides the 67 // default implementation for Read() and Write() functions and requires the 68 // implementations to provide GetBuffer() and/or ReadOnlyBuffer() functions. 69 class BRILLO_EXPORT ContiguousBufferBase : public DataContainerInterface { 70 public: 71 ContiguousBufferBase() = default; 72 // Implementation of DataContainerInterface::Read(). 73 bool Read(void* buffer, 74 size_t size_to_read, 75 size_t offset, 76 size_t* size_read, 77 ErrorPtr* error) override; 78 // Implementation of DataContainerInterface::Write(). 79 bool Write(const void* buffer, 80 size_t size_to_write, 81 size_t offset, 82 size_t* size_written, 83 ErrorPtr* error) override; 84 85 // Overload to provide the pointer to the read-only data for the container at 86 // the specified |offset|. In case of an error, this function must return 87 // nullptr and provide error details in |error| object if provided. 88 virtual const void* GetReadOnlyBuffer(size_t offset, 89 ErrorPtr* error) const = 0; 90 // Overload to provide the pointer to the read/write data for the container at 91 // the specified |offset|. In case of an error, this function must return 92 // nullptr and provide error details in |error| object if provided. 93 virtual void* GetBuffer(size_t offset, ErrorPtr* error) = 0; 94 95 protected: 96 // Wrapper around memcpy which can be mocked out in tests. 97 virtual void CopyMemoryBlock(void* dest, const void* src, size_t size) const; 98 99 private: 100 DISALLOW_COPY_AND_ASSIGN(ContiguousBufferBase); 101 }; 102 103 // ContiguousReadOnlyBufferBase is a specialization of ContiguousBufferBase for 104 // read-only containers. 105 class BRILLO_EXPORT ContiguousReadOnlyBufferBase : public ContiguousBufferBase { 106 public: 107 ContiguousReadOnlyBufferBase() = default; 108 // Fails with an error "operation_not_supported" (Stream is read-only) error. 109 bool Write(const void* buffer, 110 size_t size_to_write, 111 size_t offset, 112 size_t* size_written, 113 ErrorPtr* error) override; 114 // Fails with an error "operation_not_supported" (Stream is read-only) error. 115 bool Resize(size_t new_size, ErrorPtr* error) override; 116 // Fails with an error "operation_not_supported" (Stream is read-only) error. IsReadOnly()117 bool IsReadOnly() const override { return true; } 118 // Fails with an error "operation_not_supported" (Stream is read-only) error. 119 void* GetBuffer(size_t offset, ErrorPtr* error) override; 120 121 private: 122 DISALLOW_COPY_AND_ASSIGN(ContiguousReadOnlyBufferBase); 123 }; 124 125 // ReadOnlyBuffer implements a read-only container based on raw memory block. 126 class BRILLO_EXPORT ReadOnlyBuffer : public ContiguousReadOnlyBufferBase { 127 public: 128 // Constructs the container based at the pointer to memory |buffer| and its 129 // |size|. The pointer to the memory must be valid throughout life-time of 130 // the stream using this container. ReadOnlyBuffer(const void * buffer,size_t size)131 ReadOnlyBuffer(const void* buffer, size_t size) 132 : buffer_(buffer), size_(size) {} 133 134 // Returns the pointer to data at |offset|. GetReadOnlyBuffer(size_t offset,ErrorPtr *)135 const void* GetReadOnlyBuffer(size_t offset, 136 ErrorPtr* /* error */) const override { 137 return reinterpret_cast<const uint8_t*>(buffer_) + offset; 138 } 139 // Returns the size of the container. GetSize()140 size_t GetSize() const override { return size_; } 141 142 private: 143 // Raw memory pointer to the data block and its size. 144 const void* buffer_; 145 size_t size_; 146 147 DISALLOW_COPY_AND_ASSIGN(ReadOnlyBuffer); 148 }; 149 150 // VectorPtr<T> is a read/write container based on a vector<T> pointer. 151 // This is a template class to allow usage of both vector<char> and 152 // vector<uint8_t> without duplicating the implementation. 153 template<typename T> 154 class VectorPtr : public ContiguousBufferBase { 155 public: 156 static_assert(sizeof(T) == 1, "Only char/byte is supported"); VectorPtr(std::vector<T> * vector)157 explicit VectorPtr(std::vector<T>* vector) : vector_ptr_(vector) {} 158 Resize(size_t new_size,ErrorPtr *)159 bool Resize(size_t new_size, ErrorPtr* /* error */) override { 160 vector_ptr_->resize(new_size); 161 return true; 162 } GetSize()163 size_t GetSize() const override { return vector_ptr_->size(); } IsReadOnly()164 bool IsReadOnly() const override { return false; } GetReadOnlyBuffer(size_t offset,ErrorPtr *)165 const void* GetReadOnlyBuffer(size_t offset, 166 ErrorPtr* /* error */) const override { 167 return reinterpret_cast<const uint8_t*>(vector_ptr_->data()) + offset; 168 } GetBuffer(size_t offset,ErrorPtr *)169 void* GetBuffer(size_t offset, ErrorPtr* /* error */) override { 170 return reinterpret_cast<uint8_t*>(vector_ptr_->data()) + offset; 171 } 172 173 protected: 174 std::vector<T>* vector_ptr_; 175 176 private: 177 DISALLOW_COPY_AND_ASSIGN(VectorPtr); 178 }; 179 180 // ReadOnlyVectorRef<T> is a read-only container based on a vector<T> reference. 181 // This is a template class to allow usage of both vector<char> and 182 // vector<uint8_t> without duplicating the implementation. 183 template<typename T> 184 class ReadOnlyVectorRef : public ContiguousReadOnlyBufferBase { 185 public: 186 static_assert(sizeof(T) == 1, "Only char/byte is supported"); ReadOnlyVectorRef(const std::vector<T> & vector)187 explicit ReadOnlyVectorRef(const std::vector<T>& vector) 188 : vector_ref_(vector) {} 189 GetReadOnlyBuffer(size_t offset,ErrorPtr *)190 const void* GetReadOnlyBuffer(size_t offset, 191 ErrorPtr* /* error */) const override { 192 return reinterpret_cast<const uint8_t*>(vector_ref_.data()) + offset; 193 } GetSize()194 size_t GetSize() const override { return vector_ref_.size(); } 195 196 protected: 197 const std::vector<T>& vector_ref_; 198 199 private: 200 DISALLOW_COPY_AND_ASSIGN(ReadOnlyVectorRef); 201 }; 202 203 // ReadOnlyVectorCopy<T> is a read-only container based on a copy of vector<T>. 204 // This container actually owns the data stored in the vector. 205 // This is a template class to allow usage of both vector<char> and 206 // vector<uint8_t> without duplicating the implementation. 207 template<typename T> 208 class ReadOnlyVectorCopy : public ContiguousReadOnlyBufferBase { 209 public: 210 static_assert(sizeof(T) == 1, "Only char/byte is supported"); ReadOnlyVectorCopy(std::vector<T> vector)211 explicit ReadOnlyVectorCopy(std::vector<T> vector) 212 : vector_copy_(std::move(vector)) {} 213 ReadOnlyVectorCopy(const T * buffer,size_t size)214 ReadOnlyVectorCopy(const T* buffer, size_t size) 215 : vector_copy_(buffer, buffer + size) {} 216 GetReadOnlyBuffer(size_t offset,ErrorPtr *)217 const void* GetReadOnlyBuffer(size_t offset, 218 ErrorPtr* /* error */) const override { 219 return reinterpret_cast<const uint8_t*>(vector_copy_.data()) + offset; 220 } GetSize()221 size_t GetSize() const override { return vector_copy_.size(); } 222 223 protected: 224 std::vector<T> vector_copy_; 225 226 private: 227 DISALLOW_COPY_AND_ASSIGN(ReadOnlyVectorCopy); 228 }; 229 230 // ByteBuffer is a read/write container that manages the data and underlying 231 // storage. 232 class BRILLO_EXPORT ByteBuffer : public VectorPtr<uint8_t> { 233 public: 234 explicit ByteBuffer(size_t reserve_size); 235 ~ByteBuffer() override; 236 237 private: 238 DISALLOW_COPY_AND_ASSIGN(ByteBuffer); 239 }; 240 241 // StringPtr is a read/write container based on external std::string storage. 242 class BRILLO_EXPORT StringPtr : public ContiguousBufferBase { 243 public: 244 explicit StringPtr(std::string* string); 245 246 bool Resize(size_t new_size, ErrorPtr* error) override; GetSize()247 size_t GetSize() const override { return string_ptr_->size(); } IsReadOnly()248 bool IsReadOnly() const override { return false; } 249 const void* GetReadOnlyBuffer(size_t offset, ErrorPtr* error) const override; 250 void* GetBuffer(size_t offset, ErrorPtr* error) override; 251 252 protected: 253 std::string* string_ptr_; 254 255 private: 256 DISALLOW_COPY_AND_ASSIGN(StringPtr); 257 }; 258 259 // ReadOnlyStringRef is a read-only container based on external std::string. 260 class BRILLO_EXPORT ReadOnlyStringRef : public ContiguousReadOnlyBufferBase { 261 public: 262 explicit ReadOnlyStringRef(const std::string& string); 263 const void* GetReadOnlyBuffer(size_t offset, ErrorPtr* error) const override; GetSize()264 size_t GetSize() const override { return string_ref_.size(); } 265 266 protected: 267 const std::string& string_ref_; 268 269 private: 270 DISALLOW_COPY_AND_ASSIGN(ReadOnlyStringRef); 271 }; 272 273 // ReadOnlyStringCopy is a read-only container based on a copy of a std::string. 274 // This container actually owns the data stored in the string. 275 class BRILLO_EXPORT ReadOnlyStringCopy : public ReadOnlyStringRef { 276 public: 277 explicit ReadOnlyStringCopy(std::string string); 278 279 protected: 280 std::string string_copy_; 281 282 private: 283 DISALLOW_COPY_AND_ASSIGN(ReadOnlyStringCopy); 284 }; 285 286 } // namespace data_container 287 } // namespace brillo 288 289 #endif // LIBBRILLO_BRILLO_STREAMS_MEMORY_CONTAINERS_H_ 290