• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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