streams.h 9.2 KB

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