1 /* Copyright (C) 2010 Wildfire Games. 2 * 3 * Permission is hereby granted, free of charge, to any person obtaining 4 * a copy of this software and associated documentation files (the 5 * "Software"), to deal in the Software without restriction, including 6 * without limitation the rights to use, copy, modify, merge, publish, 7 * distribute, sublicense, and/or sell copies of the Software, and to 8 * permit persons to whom the Software is furnished to do so, subject to 9 * the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included 12 * in all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 18 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 19 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 20 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 */ 22 23 /* 24 * output buffer and 'stream' layered on top of a compression codec 25 */ 26 27 #ifndef INCLUDED_STREAM 28 #define INCLUDED_STREAM 29 30 #include "lib/file/archive/codec.h" 31 32 // note: this is similar in function to std::vector, but we don't need 33 // iterators etc. and would prefer to avoid initializing each byte. 34 class OutputBufferManager 35 { 36 public: 37 OutputBufferManager(); 38 39 void Reset(); 40 void SetBuffer(u8* buffer, size_t size); 41 42 /** 43 * allocate a new output buffer. 44 * 45 * @param size [bytes] to allocate. 46 * 47 * notes: 48 * - if a buffer had previously been allocated and is large enough, 49 * it is reused (this reduces the number of allocations). 50 * - this class manages the lifetime of the buffer. 51 **/ 52 void AllocateBuffer(size_t size); 53 Buffer()54 u8* Buffer() const 55 { 56 return m_buffer; 57 } 58 Size()59 size_t Size() const 60 { 61 return m_size; 62 } 63 64 private: 65 bool IsAllowableBuffer(u8* buffer, size_t size); 66 67 u8* m_buffer; 68 size_t m_size; 69 70 shared_ptr<u8> m_mem; 71 // size of m_mem. allows reusing previously allocated buffers 72 // (user-specified buffers can't be reused because we have no control 73 // over their lifetime) 74 size_t m_capacity; 75 }; 76 77 78 class Stream 79 { 80 public: 81 Stream(const PICodec& codec); 82 83 void SetOutputBuffer(u8* out, size_t outSize); 84 85 void AllocateOutputBuffer(size_t outSizeMax); 86 87 /** 88 * 'feed' the codec with a data block. 89 **/ 90 Status Feed(const u8* in, size_t inSize); 91 92 Status Finish(); 93 OutSize()94 size_t OutSize() const 95 { 96 return m_outProduced; 97 } 98 Checksum()99 u32 Checksum() const 100 { 101 return m_checksum; 102 } 103 104 private: 105 PICodec m_codec; 106 OutputBufferManager m_outputBufferManager; 107 108 size_t m_inConsumed; 109 size_t m_outProduced; 110 u32 m_checksum; 111 }; 112 113 // avoids the need for std::bind (not supported on all compilers) and boost::bind (can't be 114 // used at work) 115 struct StreamFeeder 116 { 117 NONCOPYABLE(StreamFeeder); 118 public: StreamFeederStreamFeeder119 StreamFeeder(Stream& stream) 120 : stream(stream) 121 { 122 } 123 operatorStreamFeeder124 Status operator()(const u8* data, size_t size) const 125 { 126 return stream.Feed(data, size); 127 } 128 129 private: 130 Stream& stream; 131 }; 132 133 #endif // #ifndef INCLUDED_STREAM 134