summaryrefslogtreecommitdiff
path: root/src/deflate.cpp
diff options
context:
space:
mode:
authorMike Buland <eichlan@xagasoft.com>2011-10-23 07:43:50 +0000
committerMike Buland <eichlan@xagasoft.com>2011-10-23 07:43:50 +0000
commitda1e0ef0772b078bd295301bd675afdee00d40e9 (patch)
tree7d1703bbb5c2d76e6e6300e51f0ed1e09704af4f /src/deflate.cpp
parent208b983734d7431699f4bd3534e08321e42ada86 (diff)
downloadlibbu++-da1e0ef0772b078bd295301bd675afdee00d40e9.tar.gz
libbu++-da1e0ef0772b078bd295301bd675afdee00d40e9.tar.bz2
libbu++-da1e0ef0772b078bd295301bd675afdee00d40e9.tar.xz
libbu++-da1e0ef0772b078bd295301bd675afdee00d40e9.zip
Switched ito* to synchro*, except the server, I'm thinking of takeing the core
in a different direction anyway. Added the Deflate class, it uses zlib, and can do raw (headerless) deflate streams, zlib format, or gzip format. It's easy to use and quite versitile.
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