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