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 26 namespace courgette { 27 28 class SourceStream; 29 class SinkStream; 30 31 // Maximum number of streams in a stream set. 32 static 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. 36 class 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. 118 class 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. 166 class 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. 204 class 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