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_STREAM_H_
      6 #define LIBBRILLO_BRILLO_STREAMS_MEMORY_STREAM_H_
      7 
      8 #include <string>
      9 #include <vector>
     10 
     11 #include <base/macros.h>
     12 #include <base/memory/weak_ptr.h>
     13 #include <brillo/brillo_export.h>
     14 #include <brillo/streams/memory_containers.h>
     15 #include <brillo/streams/stream.h>
     16 
     17 namespace brillo {
     18 
     19 // MemoryStream is a brillo::Stream implementation for memory buffer. A number
     20 // of memory containers are supported, such as raw memory pointers, data stored
     21 // in std::vector and std::string.
     22 // MemoryStream offers support for constant read-only memory buffers as well as
     23 // for writable buffers that can grow when needed.
     24 // A memory stream is created by using the OpenNNN and CreateNNN factory methods
     25 // to construct a read-only and writable streams respectively.
     26 // The following factory methods overloads are provided:
     27 //  - OpenRef    - overloads for constructing the stream on a constant read-only
     28 //                 memory buffer that is not owned by the stream. The buffer
     29 //                 pointer/reference must remain valid throughout the lifetime
     30 //                 of the constructed stream object. The benefit of this is that
     31 //                 no data copying is performed and the underlying container can
     32 //                 be manipulated outside of the stream.
     33 //  - OpenCopyOf - overloads to construct a stream that copies the data from the
     34 //                 memory buffer and maintains the copied data until the stream
     35 //                 is closed or destroyed. This makes it possible to construct
     36 //                 a read-only streams on transient data or for cases where
     37 //                 it is not possible or necessary to maintain the lifetime of
     38 //                 the underlying memory buffer.
     39 //  - Create     - creates a new internal memory buffer that can be written to
     40 //                 or read from using the stream I/O interface.
     41 //  - CreateRef  - constructs a read/write stream on a reference of data
     42 //                 container such as std::vector or std::string which must
     43 //                 remain valid throughout the lifetime of the memory stream.
     44 //                 The data already stored in the container is maintained,
     45 //                 however the stream pointer is set to the beginning of the
     46 //                 data when the stream is created.
     47 //  - CreateRefForAppend - similar to CreateRef except that it automatically
     48 //                 positions the stream seek pointer at the end of the data,
     49 //                 which makes it possible to append more data to the existing
     50 //                 container.
     51 class BRILLO_EXPORT MemoryStream : public Stream {
     52  public:
     53   // == Construction ==========================================================
     54 
     55   // Constructs a read-only stream on a generic memory buffer. The data
     56   // pointed to by |buffer| will be copied and owned by the stream object.
     57   static StreamPtr OpenCopyOf(const void* buffer, size_t size, ErrorPtr* error);
     58   static StreamPtr OpenCopyOf(std::string buffer, ErrorPtr* error);
     59   static StreamPtr OpenCopyOf(const char* buffer, ErrorPtr* error);
     60   // Only vectors of char and uint8_t are supported.
     61   template<typename T>
     62   inline static StreamPtr OpenCopyOf(std::vector<T> buffer, ErrorPtr* error) {
     63     std::unique_ptr<data_container::ReadOnlyVectorCopy<T>> container{
     64         new data_container::ReadOnlyVectorCopy<T>{std::move(buffer)}};
     65     return CreateEx(std::move(container), 0, error);
     66   }
     67 
     68   // Constructs a read-only stream on a generic memory buffer which is owned
     69   // by the caller.
     70   // ***WARNING***: The |buffer| pointer must be valid for as long as the stream
     71   // object is alive. The stream does not do any additional lifetime management
     72   // for the data pointed to by |buffer| and destroying that buffer before
     73   // the stream is closed will lead to unexpected behavior.
     74   static StreamPtr OpenRef(const void* buffer, size_t size, ErrorPtr* error);
     75   static StreamPtr OpenRef(const std::string& buffer, ErrorPtr* error);
     76   static StreamPtr OpenRef(const char* buffer, ErrorPtr* error);
     77   // Only vectors of char and uint8_t are supported.
     78   template<typename T>
     79   inline static StreamPtr OpenRef(const std::vector<T>& buffer,
     80                                   ErrorPtr* error) {
     81     std::unique_ptr<data_container::ReadOnlyVectorRef<T>> container{
     82         new data_container::ReadOnlyVectorRef<T>{buffer}};
     83     return CreateEx(std::move(container), 0, error);
     84   }
     85 
     86   ///------------------------------------------------------------------------
     87   // Creates new stream for reading/writing. This method creates an internal
     88   // memory buffer and maintains it until the stream is closed. |reserve_size|
     89   // parameter is a hint of the buffer size to pre-allocate. This does not
     90   // affect the memory buffer reported size. The buffer can grow past that
     91   // amount if needed.
     92   static StreamPtr Create(size_t reserve_size, ErrorPtr* error);
     93 
     94   inline static StreamPtr Create(ErrorPtr* error) { return Create(0, error); }
     95 
     96   // Creates new stream for reading/writing stored in a string. The string
     97   // |buffer| must remain valid during the lifetime of the stream.
     98   // The stream pointer will be at the beginning of the string and the string's
     99   // content is preserved.
    100   static StreamPtr CreateRef(std::string* buffer, ErrorPtr* error);
    101 
    102   // Creates new stream for reading/writing stored in a vector. The vector
    103   // |buffer| must remain valid during the lifetime of the stream.
    104   // The stream pointer will be at the beginning of the data and the vector's
    105   // content is preserved.
    106   // Only vectors of char and uint8_t are supported.
    107   template<typename T>
    108   static StreamPtr CreateRef(std::vector<T>* buffer, ErrorPtr* error) {
    109     std::unique_ptr<data_container::VectorPtr<T>> container{
    110         new data_container::VectorPtr<T>{buffer}};
    111     return CreateEx(std::move(container), 0, error);
    112   }
    113 
    114   // Creates new stream for reading/writing stored in a string. The string
    115   // |buffer| must remain valid during the lifetime of the stream.
    116   // The stream pointer will be at the end of the string and the string's
    117   // content is preserved.
    118   static StreamPtr CreateRefForAppend(std::string* buffer, ErrorPtr* error);
    119 
    120   // Creates new stream for reading/writing stored in a vector. The vector
    121   // |buffer| must remain valid during the lifetime of the stream.
    122   // The stream pointer will be at the end of the data and the vector's
    123   // content is preserved.
    124   // Only vectors of char and uint8_t are supported.
    125   template<typename T>
    126   static StreamPtr CreateRefForAppend(std::vector<T>* buffer, ErrorPtr* error) {
    127     std::unique_ptr<data_container::VectorPtr<T>> container{
    128         new data_container::VectorPtr<T>{buffer}};
    129     return CreateEx(std::move(container), buffer->size() * sizeof(T), error);
    130   }
    131 
    132   ///------------------------------------------------------------------------
    133   // Generic stream creation on a data container. Takes an arbitrary |container|
    134   // and constructs a stream using it. The container determines the traits of
    135   // the stream (e.g. whether it is read-only, what operations are supported
    136   // and so on). |stream_position| is the current stream pointer position at
    137   // creation time.
    138   static StreamPtr CreateEx(
    139       std::unique_ptr<data_container::DataContainerInterface> container,
    140       size_t stream_position,
    141       ErrorPtr* error);
    142 
    143   // == Stream capabilities ===================================================
    144   bool IsOpen() const override;
    145   bool CanRead() const override;
    146   bool CanWrite() const override;
    147   bool CanSeek() const override;
    148   bool CanGetSize() const override;
    149 
    150   // == Stream size operations ================================================
    151   uint64_t GetSize() const override;
    152   bool SetSizeBlocking(uint64_t size, ErrorPtr* error) override;
    153   uint64_t GetRemainingSize() const override;
    154 
    155   // == Seek operations =======================================================
    156   uint64_t GetPosition() const override;
    157   bool Seek(int64_t offset,
    158             Whence whence,
    159             uint64_t* new_position,
    160             ErrorPtr* error) override;
    161 
    162   // == Read operations =======================================================
    163   bool ReadNonBlocking(void* buffer,
    164                        size_t size_to_read,
    165                        size_t* size_read,
    166                        bool* end_of_stream,
    167                        ErrorPtr* error) override;
    168 
    169   // == Write operations ======================================================
    170   bool WriteNonBlocking(const void* buffer,
    171                         size_t size_to_write,
    172                         size_t* size_written,
    173                         ErrorPtr* error) override;
    174 
    175   // == Finalizing/closing streams  ===========================================
    176   bool FlushBlocking(ErrorPtr* error) override;
    177   bool CloseBlocking(ErrorPtr* error) override;
    178 
    179   // == Data availability monitoring ==========================================
    180   bool WaitForData(AccessMode mode,
    181                    const base::Callback<void(AccessMode)>& callback,
    182                    ErrorPtr* error) override;
    183 
    184   bool WaitForDataBlocking(AccessMode in_mode,
    185                            base::TimeDelta timeout,
    186                            AccessMode* out_mode,
    187                            ErrorPtr* error) override;
    188 
    189  private:
    190   friend class MemoryStreamTest;
    191 
    192   // Private constructor used by MemoryStream::OpenNNNN() and
    193   // MemoryStream::CreateNNNN() factory methods.
    194   MemoryStream(
    195       std::unique_ptr<data_container::DataContainerInterface> container,
    196       size_t stream_position);
    197 
    198   // Checks if the stream has a valid container.
    199   bool CheckContainer(ErrorPtr* error) const;
    200 
    201   // Data container the stream is using to write and/or read data.
    202   std::unique_ptr<data_container::DataContainerInterface> container_;
    203 
    204   // The current stream pointer position.
    205   size_t stream_position_{0};
    206 
    207   DISALLOW_COPY_AND_ASSIGN(MemoryStream);
    208 };
    209 
    210 }  // namespace brillo
    211 
    212 #endif  // LIBBRILLO_BRILLO_STREAMS_MEMORY_STREAM_H_
    213