summaryrefslogtreecommitdiff
path: root/src/deflate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/deflate.cpp')
-rw-r--r--src/deflate.cpp242
1 files changed, 242 insertions, 0 deletions
diff --git a/src/deflate.cpp b/src/deflate.cpp
new file mode 100644
index 0000000..aec2a18
--- /dev/null
+++ b/src/deflate.cpp
@@ -0,0 +1,242 @@
1/*
2 * Copyright (C) 2007-2011 Xagasoft, All rights reserved.
3 *
4 * This file is part of the libbu++ library and is released under the
5 * terms of the license contained in the file LICENSE.
6 */
7
8#include "bu/deflate.h"
9#include "bu/trace.h"
10
11using namespace Bu;
12
13Bu::Deflate::Deflate( Bu::Stream &rNext, int nCompression, Format eFmt ) :
14 Bu::Filter( rNext ),
15 nCompression( nCompression ),
16 sTotalOut( 0 ),
17 eFmt( eFmt ),
18 bEos( false )
19{
20 TRACE( nCompression );
21 start();
22}
23
24Bu::Deflate::~Deflate()
25{
26 TRACE();
27 stop();
28}
29
30void Bu::Deflate::start()
31{
32 TRACE();
33 zState.zalloc = NULL;
34 zState.zfree = NULL;
35 zState.opaque = NULL;
36 zState.state = NULL;
37
38 nBufSize = 64*1024;
39 pBuf = new char[nBufSize];
40}
41
42Bu::size Bu::Deflate::stop()
43{
44 TRACE();
45 if( zState.state )
46 {
47 if( bReading )
48 {
49 inflateEnd( &zState );
50 delete[] pBuf;
51 pBuf = NULL;
52 return 0;
53 }
54 else
55 {
56 for(;;)
57 {
58 zState.next_in = NULL;
59 zState.avail_in = 0;
60 zState.avail_out = nBufSize;
61 zState.next_out = (Bytef *)pBuf;
62 int res = deflate( &zState, Z_FINISH );
63 if( zState.avail_out < nBufSize )
64 {
65 sTotalOut += rNext.write( pBuf, nBufSize-zState.avail_out );
66 }
67 if( res == Z_STREAM_END )
68 break;
69 }
70 deflateEnd( &zState );
71 delete[] pBuf;
72 pBuf = NULL;
73 return sTotalOut;
74 }
75 }
76 return 0;
77}
78
79void Bu::Deflate::zError( int code )
80{
81 TRACE( code );
82 switch( code )
83 {
84 case Z_OK:
85 case Z_STREAM_END:
86 case Z_NEED_DICT:
87 return;
88
89 case Z_ERRNO:
90 throw ExceptionBase("Deflate: Errno - %s", zState.msg );
91
92 case Z_STREAM_ERROR:
93 throw ExceptionBase("Deflate: Stream Error - %s", zState.msg );
94
95 case Z_DATA_ERROR:
96 throw ExceptionBase("Deflate: Data Error - %s", zState.msg );
97
98 case Z_MEM_ERROR:
99 throw ExceptionBase("Deflate: Mem Error - %s", zState.msg );
100
101 case Z_BUF_ERROR:
102 throw ExceptionBase("Deflate: Buf Error - %s", zState.msg );
103
104 case Z_VERSION_ERROR:
105 throw ExceptionBase("Deflate: Version Error - %s", zState.msg );
106
107 default:
108 throw ExceptionBase("Deflate: Unknown error encountered - %s.", zState.msg );
109
110 }
111}
112
113Bu::size Bu::Deflate::read( void *pData, Bu::size nBytes )
114{
115 TRACE( pData, nBytes );
116 if( !zState.state )
117 {
118 bReading = true;
119 if( eFmt&AutoDetect )
120 inflateInit2( &zState, 32+15 ); // Auto-detect, large window
121 else if( eFmt == Raw )
122 inflateInit2( &zState, -15 ); // Raw
123 else if( eFmt == Zlib )
124 inflateInit2( &zState, 15 ); // Zlib
125 else if( eFmt == Gzip )
126 inflateInit2( &zState, 16+15 ); // GZip
127 else
128 throw Bu::ExceptionBase("Format mode for deflate read.");
129 zState.next_in = (Bytef *)pBuf;
130 zState.avail_in = 0;
131 }
132 if( bReading == false )
133 throw ExceptionBase("This deflate filter is in writing mode, you can't read.");
134
135 int nRead = 0;
136 int nReadTotal = zState.total_out;
137 zState.next_out = (Bytef *)pData;
138 zState.avail_out = nBytes;
139 for(;;)
140 {
141 int ret = inflate( &zState, Z_NO_FLUSH );
142 printf("inflate returned %d; avail in=%d, out=%d\n", ret,
143 zState.avail_in, zState.avail_out );
144
145 nReadTotal += nRead-zState.avail_out;
146
147 if( ret == Z_STREAM_END )
148 {
149 bEos = true;
150 if( zState.avail_in > 0 )
151 {
152 if( rNext.isSeekable() )
153 {
154 rNext.seek( -zState.avail_in );
155 }
156 }
157 return nBytes-zState.avail_out;
158 }
159 if( ret != Z_BUF_ERROR )
160 zError( ret );
161
162 if( zState.avail_out )
163 {
164 if( zState.avail_in == 0 )
165 {
166 nRead = rNext.read( pBuf, nBufSize );
167 if( nRead == 0 && rNext.isEos() )
168 {
169 throw Bu::ExceptionBase("Premature end of underlying "
170 "stream found reading deflate stream.");
171 }
172 zState.next_in = (Bytef *)pBuf;
173 zState.avail_in = nRead;
174 }
175 }
176 else
177 {
178 return nBytes-zState.avail_out;
179 }
180 }
181 return 0;
182}
183
184Bu::size Bu::Deflate::write( const void *pData, Bu::size nBytes )
185{
186 TRACE( pData, nBytes );
187 if( !zState.state )
188 {
189 bReading = false;
190 int iFmt = eFmt&Gzip;
191 if( iFmt == Raw )
192 deflateInit2( &zState, nCompression, Z_DEFLATED, -15, 9,
193 Z_DEFAULT_STRATEGY );
194 else if( iFmt == Zlib )
195 deflateInit2( &zState, nCompression, Z_DEFLATED, 15, 9,
196 Z_DEFAULT_STRATEGY );
197 else if( iFmt == Gzip )
198 deflateInit2( &zState, nCompression, Z_DEFLATED, 16+15, 9,
199 Z_DEFAULT_STRATEGY );
200 else
201 throw Bu::ExceptionBase("Invalid format for deflate.");
202 }
203 if( bReading == true )
204 throw ExceptionBase("This deflate filter is in reading mode, you can't write.");
205
206 zState.next_in = (Bytef *)pData;
207 zState.avail_in = nBytes;
208 for(;;)
209 {
210 zState.avail_out = nBufSize;
211 zState.next_out = (Bytef *)pBuf;
212
213 zError( deflate( &zState, Z_NO_FLUSH ) );
214
215 if( zState.avail_out < nBufSize )
216 {
217 sTotalOut += rNext.write( pBuf, nBufSize-zState.avail_out );
218 }
219 if( zState.avail_in == 0 )
220 break;
221 }
222
223 return nBytes;
224}
225
226bool Bu::Deflate::isOpen()
227{
228 TRACE();
229 return (zState.state != NULL);
230}
231
232bool Bu::Deflate::isEos()
233{
234 TRACE();
235 return bEos;
236}
237
238Bu::size Bu::Deflate::getCompressedSize()
239{
240 return sTotalOut;
241}
242