summaryrefslogtreecommitdiff
path: root/brillo/streams/memory_stream.h
blob: b9f5e4bcced70914e98c9a30ec4b3026c5c192ec (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
// Copyright 2015 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef LIBCHROMEOS_BRILLO_STREAMS_MEMORY_STREAM_H_
#define LIBCHROMEOS_BRILLO_STREAMS_MEMORY_STREAM_H_

#include <string>
#include <vector>

#include <base/macros.h>
#include <base/memory/weak_ptr.h>
#include <brillo/brillo_export.h>
#include <brillo/streams/memory_containers.h>
#include <brillo/streams/stream.h>

namespace brillo {

// MemoryStream is a brillo::Stream implementation for memory buffer. A number
// of memory containers are supported, such as raw memory pointers, data stored
// in std::vector and std::string.
// MemoryStream offers support for constant read-only memory buffers as well as
// for writable buffers that can grow when needed.
// A memory stream is created by using the OpenNNN and CreateNNN factory methods
// to construct a read-only and writable streams respectively.
// The following factory methods overloads are provided:
//  - OpenRef    - overloads for constructing the stream on a constant read-only
//                 memory buffer that is not owned by the stream. The buffer
//                 pointer/reference must remain valid throughout the lifetime
//                 of the constructed stream object. The benefit of this is that
//                 no data copying is performed and the underlying container can
//                 be manipulated outside of the stream.
//  - OpenCopyOf - overloads to construct a stream that copies the data from the
//                 memory buffer and maintains the copied data until the stream
//                 is closed or destroyed. This makes it possible to construct
//                 a read-only streams on transient data or for cases where
//                 it is not possible or necessary to maintain the lifetime of
//                 the underlying memory buffer.
//  - Create     - creates a new internal memory buffer that can be written to
//                 or read from using the stream I/O interface.
//  - CreateRef  - constructs a read/write stream on a reference of data
//                 container such as std::vector or std::string which must
//                 remain valid throughout the lifetime of the memory stream.
//                 The data already stored in the container is maintained,
//                 however the stream pointer is set to the beginning of the
//                 data when the stream is created.
//  - CreateRefForAppend - similar to CreateRef except that it automatically
//                 positions the stream seek pointer at the end of the data,
//                 which makes it possible to append more data to the existing
//                 container.
class BRILLO_EXPORT MemoryStream : public Stream {
 public:
  // == Construction ==========================================================

  // Constructs a read-only stream on a generic memory buffer. The data
  // pointed to by |buffer| will be copied and owned by the stream object.
  static StreamPtr OpenCopyOf(const void* buffer, size_t size, ErrorPtr* error);
  static StreamPtr OpenCopyOf(std::string buffer, ErrorPtr* error);
  static StreamPtr OpenCopyOf(const char* buffer, ErrorPtr* error);
  // Only vectors of char and uint8_t are supported.
  template<typename T>
  inline static StreamPtr OpenCopyOf(std::vector<T> buffer, ErrorPtr* error) {
    std::unique_ptr<data_container::ReadOnlyVectorCopy<T>> container{
        new data_container::ReadOnlyVectorCopy<T>{std::move(buffer)}};
    return CreateEx(std::move(container), 0, error);
  }

  // Constructs a read-only stream on a generic memory buffer which is owned
  // by the caller.
  // ***WARNING***: The |buffer| pointer must be valid for as long as the stream
  // object is alive. The stream does not do any additional lifetime management
  // for the data pointed to by |buffer| and destroying that buffer before
  // the stream is closed will lead to unexpected behavior.
  static StreamPtr OpenRef(const void* buffer, size_t size, ErrorPtr* error);
  static StreamPtr OpenRef(const std::string& buffer, ErrorPtr* error);
  static StreamPtr OpenRef(const char* buffer, ErrorPtr* error);
  // Only vectors of char and uint8_t are supported.
  template<typename T>
  inline static StreamPtr OpenRef(const std::vector<T>& buffer,
                                  ErrorPtr* error) {
    std::unique_ptr<data_container::ReadOnlyVectorRef<T>> container{
        new data_container::ReadOnlyVectorRef<T>{buffer}};
    return CreateEx(std::move(container), 0, error);
  }

  ///------------------------------------------------------------------------
  // Creates new stream for reading/writing. This method creates an internal
  // memory buffer and maintains it until the stream is closed. |reserve_size|
  // parameter is a hint of the buffer size to pre-allocate. This does not
  // affect the memory buffer reported size. The buffer can grow past that
  // amount if needed.
  static StreamPtr Create(size_t reserve_size, ErrorPtr* error);

  inline static StreamPtr Create(ErrorPtr* error) { return Create(0, error); }

  // Creates new stream for reading/writing stored in a string. The string
  // |buffer| must remain valid during the lifetime of the stream.
  // The stream pointer will be at the beginning of the string and the string's
  // content is preserved.
  static StreamPtr CreateRef(std::string* buffer, ErrorPtr* error);

  // Creates new stream for reading/writing stored in a vector. The vector
  // |buffer| must remain valid during the lifetime of the stream.
  // The stream pointer will be at the beginning of the data and the vector's
  // content is preserved.
  // Only vectors of char and uint8_t are supported.
  template<typename T>
  static StreamPtr CreateRef(std::vector<T>* buffer, ErrorPtr* error) {
    std::unique_ptr<data_container::VectorPtr<T>> container{
        new data_container::VectorPtr<T>{buffer}};
    return CreateEx(std::move(container), 0, error);
  }

  // Creates new stream for reading/writing stored in a string. The string
  // |buffer| must remain valid during the lifetime of the stream.
  // The stream pointer will be at the end of the string and the string's
  // content is preserved.
  static StreamPtr CreateRefForAppend(std::string* buffer, ErrorPtr* error);

  // Creates new stream for reading/writing stored in a vector. The vector
  // |buffer| must remain valid during the lifetime of the stream.
  // The stream pointer will be at the end of the data and the vector's
  // content is preserved.
  // Only vectors of char and uint8_t are supported.
  template<typename T>
  static StreamPtr CreateRefForAppend(std::vector<T>* buffer, ErrorPtr* error) {
    std::unique_ptr<data_container::VectorPtr<T>> container{
        new data_container::VectorPtr<T>{buffer}};
    return CreateEx(std::move(container), buffer->size() * sizeof(T), error);
  }

  ///------------------------------------------------------------------------
  // Generic stream creation on a data container. Takes an arbitrary |container|
  // and constructs a stream using it. The container determines the traits of
  // the stream (e.g. whether it is read-only, what operations are supported
  // and so on). |stream_position| is the current stream pointer position at
  // creation time.
  static StreamPtr CreateEx(
      std::unique_ptr<data_container::DataContainerInterface> container,
      size_t stream_position,
      ErrorPtr* error);

  // == Stream capabilities ===================================================
  bool IsOpen() const override;
  bool CanRead() const override;
  bool CanWrite() const override;
  bool CanSeek() const override;
  bool CanGetSize() const override;

  // == Stream size operations ================================================
  uint64_t GetSize() const override;
  bool SetSizeBlocking(uint64_t size, ErrorPtr* error) override;
  uint64_t GetRemainingSize() const override;

  // == Seek operations =======================================================
  uint64_t GetPosition() const override;
  bool Seek(int64_t offset,
            Whence whence,
            uint64_t* new_position,
            ErrorPtr* error) override;

  // == Read operations =======================================================
  bool ReadNonBlocking(void* buffer,
                       size_t size_to_read,
                       size_t* size_read,
                       bool* end_of_stream,
                       ErrorPtr* error) override;

  // == Write operations ======================================================
  bool WriteNonBlocking(const void* buffer,
                        size_t size_to_write,
                        size_t* size_written,
                        ErrorPtr* error) override;

  // == Finalizing/closing streams  ===========================================
  bool FlushBlocking(ErrorPtr* error) override;
  bool CloseBlocking(ErrorPtr* error) override;

  // == Data availability monitoring ==========================================
  bool WaitForData(AccessMode mode,
                   const base::Callback<void(AccessMode)>& callback,
                   ErrorPtr* error) override;

  bool WaitForDataBlocking(AccessMode in_mode,
                           base::TimeDelta timeout,
                           AccessMode* out_mode,
                           ErrorPtr* error) override;

 private:
  friend class MemoryStreamTest;

  // Private constructor used by MemoryStream::OpenNNNN() and
  // MemoryStream::CreateNNNN() factory methods.
  MemoryStream(
      std::unique_ptr<data_container::DataContainerInterface> container,
      size_t stream_position);

  // Checks if the stream has a valid container.
  bool CheckContainer(ErrorPtr* error) const;

  // Data container the stream is using to write and/or read data.
  std::unique_ptr<data_container::DataContainerInterface> container_;

  // The current stream pointer position.
  size_t stream_position_{0};

  DISALLOW_COPY_AND_ASSIGN(MemoryStream);
};

}  // namespace brillo

#endif  // LIBCHROMEOS_BRILLO_STREAMS_MEMORY_STREAM_H_