Home | History | Annotate | Download | only in streams
      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