1// Copyright (c) 2011 The Chromium 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// Streams classes.
6//
7// These memory-resident streams are used for serializing data into a sequential
8// region of memory.
9// Streams are divided into SourceStreams for reading and SinkStreams for
10// writing.  Streams are aggregated into Sets which allows several streams to be
11// used at once.  Example: we can write A1, B1, A2, B2 but achieve the memory
12// layout A1 A2 B1 B2 by writing 'A's to one stream and 'B's to another.
13#ifndef COURGETTE_STREAMS_H_
14#define COURGETTE_STREAMS_H_
15
16#include <stdio.h>  // for FILE*
17#include <string>
18
19#include "base/basictypes.h"
20#include "base/compiler_specific.h"
21
22#include "courgette/memory_allocator.h"
23#include "courgette/region.h"
24
25
26namespace courgette {
27
28class SourceStream;
29class SinkStream;
30
31// Maximum number of streams in a stream set.
32static const unsigned int kMaxStreams = 10;
33
34// A SourceStream allows a region of memory to be scanned by a sequence of Read
35// operations.  The stream does not own the memory.
36class SourceStream {
37 public:
38  SourceStream() : start_(NULL), end_(NULL), current_(NULL) {}
39
40  // Initializes the SourceStream to yield the bytes at |pointer|.  The caller
41  // still owns the memory at |pointer| and should free the memory only after
42  // the last use of the stream.
43  void Init(const void* pointer, size_t length) {
44    start_ = static_cast<const uint8*>(pointer);
45    end_ = start_ + length;
46    current_ = start_;
47  }
48
49  // Initializes the SourceStream to yield the bytes in |region|.  The caller
50  // still owns the memory at |region| and should free the memory only after
51  // the last use of the stream.
52  void Init(const Region& region) { Init(region.start(), region.length()); }
53
54  // Initializes the SourceStream to yield the bytes in |string|.  The caller
55  // still owns the memory at |string| and should free the memory only after
56  // the last use of the stream.
57  void Init(const std::string& string) { Init(string.c_str(), string.size()); }
58
59  // Initializes the SourceStream to yield the bytes written to |sink|. |sink|
60  // still owns the memory, so needs to outlive |this|.  |sink| should not be
61  // written to after |this| is initialized.
62  void Init(const SinkStream& sink);
63
64  // Returns number of bytes remaining to be read from stream.
65  size_t Remaining() const { return end_ - current_; }
66
67  // Returns initial length of stream before any data consumed by reading.
68  size_t OriginalLength() const { return end_ - start_; }
69
70  const uint8* Buffer() const { return current_; }
71  bool Empty() const { return current_ == end_; }
72
73  // Copies bytes from stream to memory at |destination|.  Returns 'false' if
74  // insufficient data to satisfy request.
75  bool Read(void* destination, size_t byte_count);
76
77  // Reads a varint formatted unsigned integer from stream.  Returns 'false' if
78  // the read failed due to insufficient data or malformed Varint32.
79  bool ReadVarint32(uint32* output_value);
80
81  // Reads a varint formatted signed integer from stream.  Returns 'false' if
82  // the read failed due to insufficient data or malformed Varint32.
83  bool ReadVarint32Signed(int32* output_value);
84
85  // Initializes |substream| to yield |length| bytes from |this| stream,
86  // starting at |offset| bytes from the current position.  Returns 'false' if
87  // there are insufficient bytes in |this| stream.
88  bool ShareSubstream(size_t offset, size_t length, SourceStream* substream);
89
90  // Initializes |substream| to yield |length| bytes from |this| stream,
91  // starting at the current position.  Returns 'false' if there are
92  // insufficient bytes in |this| stream.
93  bool ShareSubstream(size_t length, SourceStream* substream) {
94    return ShareSubstream(0, length, substream);
95  }
96
97  // Reads |length| bytes from |this| stream.  Initializes |substream| to yield
98  // the bytes.  Returns 'false' if there are insufficient bytes in |this|
99  // stream.
100  bool ReadSubstream(size_t length, SourceStream* substream);
101
102  // Skips over bytes.  Returns 'false' if insufficient data to satisfy request.
103  bool Skip(size_t byte_count);
104
105 private:
106  const uint8* start_;     // Points to start of buffer.
107  const uint8* end_;       // Points to first location after buffer.
108  const uint8* current_;   // Points into buffer at current read location.
109
110  DISALLOW_COPY_AND_ASSIGN(SourceStream);
111};
112
113// A SinkStream accumulates writes into a buffer that it owns.  The stream is
114// initially in an 'accumulating' state where writes are permitted.  Accessing
115// the buffer moves the stream into a 'locked' state where no more writes are
116// permitted.  The stream may also be in a 'retired' state where the buffer
117// contents are no longer available.
118class SinkStream {
119 public:
120  SinkStream() {}
121  ~SinkStream() {}
122
123  // Appends |byte_count| bytes from |data| to the stream.
124  CheckBool Write(const void* data, size_t byte_count) WARN_UNUSED_RESULT;
125
126  // Appends the 'varint32' encoding of |value| to the stream.
127  CheckBool WriteVarint32(uint32 value) WARN_UNUSED_RESULT;
128
129  // Appends the 'varint32' encoding of |value| to the stream.
130  CheckBool WriteVarint32Signed(int32 value) WARN_UNUSED_RESULT;
131
132  // Appends the 'varint32' encoding of |value| to the stream.
133  // On platforms where sizeof(size_t) != sizeof(int32), do a safety check.
134  CheckBool WriteSizeVarint32(size_t value) WARN_UNUSED_RESULT;
135
136  // Contents of |other| are appended to |this| stream.  The |other| stream
137  // becomes retired.
138  CheckBool Append(SinkStream* other) WARN_UNUSED_RESULT;
139
140  // Returns the number of bytes in this SinkStream
141  size_t Length() const { return buffer_.size(); }
142
143  // Returns a pointer to contiguously allocated Length() bytes in the stream.
144  // Writing to the stream invalidates the pointer.  The SinkStream continues to
145  // own the memory.
146  const uint8* Buffer() const {
147    return reinterpret_cast<const uint8*>(buffer_.data());
148  }
149
150  // Hints that the stream will grow by an additional |length| bytes.
151  // Caller must be prepared to handle memory allocation problems.
152  CheckBool Reserve(size_t length) WARN_UNUSED_RESULT {
153    return buffer_.reserve(length + buffer_.size());
154  }
155
156  // Finished with this stream and any storage it has.
157  void Retire();
158
159 private:
160  NoThrowBuffer<char> buffer_;
161
162  DISALLOW_COPY_AND_ASSIGN(SinkStream);
163};
164
165// A SourceStreamSet is a set of SourceStreams.
166class SourceStreamSet {
167 public:
168  SourceStreamSet();
169  ~SourceStreamSet();
170
171  // Initializes the SourceStreamSet with the stream data in memory at |source|.
172  // The caller continues to own the memory and should not modify or free the
173  // memory until the SourceStreamSet destructor has been called.
174  //
175  // The layout of the streams are as written by SinkStreamSet::CopyTo.
176  // Init returns 'false' if the layout is inconsistent with |byte_count|.
177  bool Init(const void* source, size_t byte_count);
178
179  // Initializes |this| from |source|.  The caller continues to own the memory
180  // because it continues to be owned by |source|.
181  bool Init(SourceStream* source);
182
183  // Returns a pointer to one of the sub-streams.
184  SourceStream* stream(size_t id) { return id < count_ ? &streams_[id] : NULL; }
185
186  // Initialize |set| from |this|.
187  bool ReadSet(SourceStreamSet* set);
188
189  // Returns 'true' if all streams are completely consumed.
190  bool Empty() const;
191
192 private:
193  size_t count_;
194  SourceStream streams_[kMaxStreams];
195
196  DISALLOW_COPY_AND_ASSIGN(SourceStreamSet);
197};
198
199// A SinkStreamSet is a set of SinkStreams.  Data is collected by writing to the
200// component streams.  When data collection is complete, it is destructively
201// transferred, either by flattening into one stream (CopyTo), or transfering
202// data pairwise into another SinkStreamSet by calling that SinkStreamSet's
203// WriteSet method.
204class SinkStreamSet {
205 public:
206  SinkStreamSet();
207  ~SinkStreamSet();
208
209  // Initializes the SinkStreamSet to have |stream_index_limit| streams.  Must
210  // be <= kMaxStreams.  If Init is not called the default is has kMaxStream.
211  void Init(size_t stream_index_limit);
212
213  // Returns a pointer to a substream.
214  SinkStream* stream(size_t id) { return id < count_ ? &streams_[id] : NULL; }
215
216  // CopyTo serializes the streams in this SinkStreamSet into a single target
217  // stream.  The serialized format may be re-read by initializing a
218  // SourceStreamSet with a buffer containing the data.
219  CheckBool CopyTo(SinkStream* combined_stream) WARN_UNUSED_RESULT;
220
221  // Writes the streams of |set| into the corresponding streams of |this|.
222  // Stream zero first has some metadata written to it.  |set| becomes retired.
223  // Partner to SourceStreamSet::ReadSet.
224  CheckBool WriteSet(SinkStreamSet* set) WARN_UNUSED_RESULT;
225
226 private:
227  CheckBool CopyHeaderTo(SinkStream* stream) WARN_UNUSED_RESULT;
228
229  size_t count_;
230  SinkStream streams_[kMaxStreams];
231
232  DISALLOW_COPY_AND_ASSIGN(SinkStreamSet);
233};
234
235}  // namespace
236#endif  // COURGETTE_STREAMS_H_
237