Line data Source code
1 : /* Copyright (C) 2021 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 0 : 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 :
54 0 : u8* Buffer() const
55 : {
56 0 : return m_buffer;
57 : }
58 :
59 0 : size_t Size() const
60 : {
61 0 : 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 : std::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 0 : 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 :
94 0 : size_t OutSize() const
95 : {
96 0 : return m_outProduced;
97 : }
98 :
99 0 : u32 Checksum() const
100 : {
101 0 : 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:
119 0 : StreamFeeder(Stream& stream)
120 0 : : stream(stream)
121 : {
122 0 : }
123 :
124 0 : Status operator()(const u8* data, size_t size) const
125 : {
126 0 : return stream.Feed(data, size);
127 : }
128 :
129 : private:
130 : Stream& stream;
131 : };
132 :
133 : #endif // #ifndef INCLUDED_STREAM
|