/* Copyright (c) 2010 Wildfire Games * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* * output buffer and 'stream' layered on top of a compression codec */ #ifndef INCLUDED_STREAM #define INCLUDED_STREAM #include "lib/file/archive/codec.h" // note: this is similar in function to std::vector, but we don't need // iterators etc. and would prefer to avoid initializing each byte. class OutputBufferManager { public: OutputBufferManager(); void Reset(); void SetBuffer(u8* buffer, size_t size); /** * allocate a new output buffer. * * @param size [bytes] to allocate. * * notes: * - if a buffer had previously been allocated and is large enough, * it is reused (this reduces the number of allocations). * - this class manages the lifetime of the buffer. **/ void AllocateBuffer(size_t size); u8* Buffer() const { return m_buffer; } size_t Size() const { return m_size; } private: bool IsAllowableBuffer(u8* buffer, size_t size); u8* m_buffer; size_t m_size; shared_ptr m_mem; // size of m_mem. allows reusing previously allocated buffers // (user-specified buffers can't be reused because we have no control // over their lifetime) size_t m_capacity; }; class Stream { public: Stream(const PICodec& codec); void SetOutputBuffer(u8* out, size_t outSize); void AllocateOutputBuffer(size_t outSizeMax); /** * 'feed' the codec with a data block. **/ Status Feed(const u8* in, size_t inSize); Status Finish(); size_t OutSize() const { return m_outProduced; } u32 Checksum() const { return m_checksum; } private: PICodec m_codec; OutputBufferManager m_outputBufferManager; size_t m_inConsumed; size_t m_outProduced; u32 m_checksum; }; // avoids the need for std::bind (not supported on all compilers) and boost::bind (can't be // used at work) struct StreamFeeder { NONCOPYABLE(StreamFeeder); public: StreamFeeder(Stream& stream) : stream(stream) { } Status operator()(const u8* data, size_t size) const { return stream.Feed(data, size); } private: Stream& stream; }; #endif // #ifndef INCLUDED_STREAM