Home | History | Annotate | Download | only in courgette
      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