1 // Copyright 2017 The Chromium OS 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 #ifndef SRC_PUFFIN_STREAM_H_ 6 #define SRC_PUFFIN_STREAM_H_ 7 8 #include <list> 9 #include <memory> 10 #include <string> 11 #include <utility> 12 #include <vector> 13 14 #include "puffin/src/include/puffin/common.h" 15 #include "puffin/src/include/puffin/huffer.h" 16 #include "puffin/src/include/puffin/puffer.h" 17 #include "puffin/src/include/puffin/stream.h" 18 19 namespace puffin { 20 21 // A class for puffing a deflate stream and huffing into a deflate stream. The 22 // puff stream is "imaginary", which means it doesn't really exists; It is build 23 // and used on demand. This class uses a given deflate stream, and puffs the 24 // deflate buffers in the stream as needed or vice versa. An object of this 25 // class can be used for reading and writing puff data but should not be used 26 // for both reading and writing using the same instance. In theory we can 27 // separate this class into two classes, namely |PuffStream| and |HuffStream|, 28 // but they are sharing a lot of codes which might be inconvenient and 29 // unnecessary to do so. In this implementation, there is no protection against 30 // reading and writing at the same time. 31 class PuffinStream : public StreamInterface { 32 public: 33 ~PuffinStream() override = default; 34 35 // Creates a |PuffinStream| for reading puff buffers from a deflate stream. 36 // |stream| IN The deflate stream. 37 // |puffer| IN The |Puffer| used for puffing the stream. 38 // |puff_size| IN The size of the puff stream (assuming |stream| has been 39 // completely puffed. 40 // |deflates| IN The location of deflates in |stream|. 41 // |puffs| IN The location of puffs into the final puff stream. 42 // |max_cache_size| IN The amount of memory to use for caching puff buffers. 43 // If the mount is smaller than the maximum puff buffer 44 // size in |puffs|, then its value will be set to zero 45 // and no puff will be cached. 46 static UniqueStreamPtr CreateForPuff(UniqueStreamPtr stream, 47 std::shared_ptr<Puffer> puffer, 48 uint64_t puff_size, 49 const std::vector<BitExtent>& deflates, 50 const std::vector<ByteExtent>& puffs, 51 size_t max_cache_size = 0); 52 53 // Creates a |PuffinStream| for writing puff buffers into a deflate stream. 54 // |stream| IN The deflate stream. 55 // |huffer| IN The |Huffer| used for huffing into the |stream|. 56 // |puff_size| IN The size of the puff stream (assuming |stream| has been 57 // completely puffed. 58 // |deflates| IN The location of deflates in |stream|. 59 // |puffs| IN The location of puffs into the input puff stream. 60 static UniqueStreamPtr CreateForHuff(UniqueStreamPtr stream, 61 std::shared_ptr<Huffer> huffer, 62 uint64_t puff_size, 63 const std::vector<BitExtent>& deflates, 64 const std::vector<ByteExtent>& puffs); 65 66 bool GetSize(uint64_t* size) const override; 67 68 // Returns the current offset in the imaginary puff stream. 69 bool GetOffset(uint64_t* offset) const override; 70 71 // Sets the current offset in the imaginary puff stream. 72 bool Seek(uint64_t offset) override; 73 74 // Reads from the deflate stream |stream_| and writes the puff stream into 75 // |buffer|. 76 bool Read(void* buffer, size_t length) override; 77 78 // Reads the puff stream from |buffer|, huffs it and writes it into the 79 // deflate stream |stream_|. The current assumption for write is that data is 80 // wrote from beginning to end with no retraction or random change of offset. 81 // This function, writes non-puff data directly to |stream_| and caches the 82 // puff data into |puff_buffer_|. When |puff_buffer_| is full, it huffs it 83 // into |deflate_buffer_| and writes it to |stream_|. 84 bool Write(const void* buffer, size_t length) override; 85 86 bool Close() override; 87 88 protected: 89 // The non-public internal Ctor. 90 PuffinStream(UniqueStreamPtr stream, 91 std::shared_ptr<Puffer> puffer, 92 std::shared_ptr<Huffer> huffer, 93 uint64_t puff_size, 94 const std::vector<BitExtent>& deflates, 95 const std::vector<ByteExtent>& puffs, 96 size_t max_cache_size); 97 98 private: 99 // See |extra_byte_|. 100 bool SetExtraByte(); 101 102 // Returns the cache for the |puff_id|th puff. If it does not find it, either 103 // returns the least accessed cached (if cache is full) or creates a new empty 104 // buffer. It returns false if it cannot find the |puff_id|th puff cache. 105 bool GetPuffCache(int puff_id, 106 uint64_t puff_size, 107 std::shared_ptr<Buffer>* buffer); 108 109 UniqueStreamPtr stream_; 110 111 std::shared_ptr<Puffer> puffer_; 112 std::shared_ptr<Huffer> huffer_; 113 114 // The size of the imaginary puff stream. 115 uint64_t puff_stream_size_; 116 117 std::vector<BitExtent> deflates_; 118 // The current deflate is being processed. 119 std::vector<BitExtent>::iterator cur_deflate_; 120 121 std::vector<ByteExtent> puffs_; 122 // The current puff is being processed. 123 std::vector<ByteExtent>::iterator cur_puff_; 124 125 std::vector<uint64_t> upper_bounds_; 126 127 // The current offset in the imaginary puff stream is |puff_pos_| + 128 // |skip_bytes_| 129 uint64_t puff_pos_; 130 uint64_t skip_bytes_; 131 132 // The current bit offset in |stream_|. 133 uint64_t deflate_bit_pos_; 134 135 // This value caches the first or last byte of a deflate stream. This is 136 // needed when two deflate stream end on the same byte (with greater than zero 137 // bit offset difference) or a deflate starts from middle of the byte. We need 138 // to cache the value in here before we have the rest of the puff buffer to 139 // make the deflate. 140 uint8_t last_byte_; 141 142 // We have to figure out if we need to cache an extra puff byte for the last 143 // byte of the deflate. This is only needed if the last bit of the current 144 // deflate is not in the same byte as the first bit of the next deflate. The 145 // value is either 0 or 1. If 1. 146 size_t extra_byte_; 147 148 // True if the stream is only for puffing. False if for huffing. 149 bool is_for_puff_; 150 151 // True if the |Close()| is called. 152 bool closed_; 153 154 std::unique_ptr<Buffer> deflate_buffer_; 155 std::shared_ptr<Buffer> puff_buffer_; 156 157 // The list of puff buffer caches. 158 std::list<std::pair<int, std::shared_ptr<Buffer>>> caches_; 159 // The maximum memory (in bytes) kept for caching puff buffers by an object of 160 // this class. 161 size_t max_cache_size_; 162 // The current amount of memory (in bytes) used for caching puff buffers. 163 uint64_t cur_cache_size_; 164 165 DISALLOW_COPY_AND_ASSIGN(PuffinStream); 166 }; 167 168 } // namespace puffin 169 170 #endif // SRC_PUFFIN_STREAM_H_ 171