• 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 <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.
IsReadOnly()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.
ReadOnlyBuffer(const void * buffer,size_t size)130   ReadOnlyBuffer(const void* buffer, size_t size)
131       : buffer_(buffer), size_(size) {}
132 
133   // Returns the pointer to data at |offset|.
GetReadOnlyBuffer(size_t offset,ErrorPtr *)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.
GetSize()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");
VectorPtr(std::vector<T> * vector)156   explicit VectorPtr(std::vector<T>* vector) : vector_ptr_(vector) {}
157 
Resize(size_t new_size,ErrorPtr *)158   bool Resize(size_t new_size, ErrorPtr* /* error */) override {
159     vector_ptr_->resize(new_size);
160     return true;
161   }
GetSize()162   size_t GetSize() const override { return vector_ptr_->size(); }
IsReadOnly()163   bool IsReadOnly() const override { return false; }
GetReadOnlyBuffer(size_t offset,ErrorPtr *)164   const void* GetReadOnlyBuffer(size_t offset,
165                                 ErrorPtr* /* error */) const override {
166     return reinterpret_cast<const uint8_t*>(vector_ptr_->data()) + offset;
167   }
GetBuffer(size_t offset,ErrorPtr *)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");
ReadOnlyVectorRef(const std::vector<T> & vector)186   explicit ReadOnlyVectorRef(const std::vector<T>& vector)
187       : vector_ref_(vector) {}
188 
GetReadOnlyBuffer(size_t offset,ErrorPtr *)189   const void* GetReadOnlyBuffer(size_t offset,
190                                 ErrorPtr* /* error */) const override {
191     return reinterpret_cast<const uint8_t*>(vector_ref_.data()) + offset;
192   }
GetSize()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");
ReadOnlyVectorCopy(std::vector<T> vector)210   explicit ReadOnlyVectorCopy(std::vector<T> vector)
211       : vector_copy_(std::move(vector)) {}
212 
ReadOnlyVectorCopy(const T * buffer,size_t size)213   ReadOnlyVectorCopy(const T* buffer, size_t size)
214       : vector_copy_(buffer, buffer + size) {}
215 
GetReadOnlyBuffer(size_t offset,ErrorPtr *)216   const void* GetReadOnlyBuffer(size_t offset,
217                                 ErrorPtr* /* error */) const override {
218     return reinterpret_cast<const uint8_t*>(vector_copy_.data()) + offset;
219   }
GetSize()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;
GetSize()246   size_t GetSize() const override { return string_ptr_->size(); }
IsReadOnly()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;
GetSize()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