1 /*
2 * IO layer : zlib streambuf
3 *
4 * Authors:
5 * Johan Ceuppens <jceuppen at easynet dot be>
6 *
7 * Copyright (C) 2004 Johan Ceuppens
8 *
9 * Released under GNU LGPL, read the file 'COPYING.LIB' for more information
10 */
12 #include "streams-zlib.h"
14 namespace Inkscape {
16 /**
17 * ZlibBuffer
18 */
20 ZlibBuffer::ZlibBuffer(URIHandle& urih)
21 : _urihandle(&urih), _putsize(BUFSIZE_STREAM), _getsize(BUFSIZE_STREAM)
22 {
23 init_inflation();
24 }
26 int ZlibBuffer::allocate_buffers()
27 {
28 if (!eback()) {
29 char *buf = new char[_getsize + _putsize];
30 setg(buf, buf , buf);
31 buf += _getsize;
32 setp(buf, buf + _putsize);
33 return 1;
34 }
35 return 0;
36 }
38 int ZlibBuffer::reallocate_buffers(int new_getsize, int new_putsize)
39 {
40 char *new_buffer = new char[new_getsize + new_putsize];
42 std::memcpy(new_buffer, eback(), _getsize);
43 std::memcpy(new_buffer, eback() + _getsize, _putsize);
45 setg(new_buffer, new_buffer + (gptr() - eback()),
46 new_buffer + new_getsize);
47 new_buffer += new_getsize;
48 setp(new_buffer, new_buffer + new_putsize);
50 _getsize = new_getsize;
51 _putsize = new_putsize;
53 return 1;
54 }
56 int ZlibBuffer::underflow()
57 {
58 if (eback() == 0 && allocate_buffers() == 0)
59 return EOF;
61 if (consume_and_inflate() == EOF)
62 return EOF;
64 return *(unsigned char *)gptr();
65 }
67 int ZlibBuffer::overflow(int c)
68 {
69 if (c == EOF)
70 return flush_output();
72 if (pbase() == 0 && allocate_buffers() == 0)
73 return EOF;
75 if (pptr() >= epptr() &&
76 flush_output() == EOF)
77 return EOF;
79 putchar(c);
81 if (pptr() >= epptr() &&
82 flush_output() == EOF)
83 return EOF;
85 return c;
86 }
88 int ZlibBuffer::consume(guint8 *buf, int nbytes)
89 {
90 return do_consume(buf, nbytes);
91 }
93 int ZlibBuffer::do_consume(guint8 *buf, int nbytes)
94 {
95 nbytes = _urihandle->read(buf, nbytes);
97 if (nbytes == EOF)
98 return EOF;
99 else if (nbytes == 0)
100 return EOF;
102 return nbytes;
103 }
105 int ZlibBuffer::do_consume_and_inflate(int nbytes)
106 {
107 guint8 buf[nbytes];
108 if (consume(buf, nbytes) == EOF)
109 return EOF;
111 GByteArray *gba = inflate(buf, nbytes);
112 copy_to_get(gba->data, gba->len);
114 g_byte_array_free(gba, TRUE);
115 return 1;
116 }
118 int ZlibBuffer::consume_and_inflate()
119 {
120 return do_consume_and_inflate(BUFSIZE_STREAM);
121 }
123 int ZlibBuffer::flush_output()
124 {
125 if (pptr() <= pbase())
126 return 0;
127 int len = pptr() - pbase();
128 int nbytes = _urihandle->write(pbase(), len);
129 setp(pbase(), pbase() + BUFSIZE_STREAM);
130 if (len == nbytes)
131 return 0;
132 else
133 return EOF;
134 }
136 void ZlibBuffer::init_inflation() throw(ZlibBufferException)
137 {
138 memset(&_zs, 0, sizeof(z_stream));
140 _zs.zalloc = Z_NULL;
141 _zs.zfree = Z_NULL;
142 _zs.opaque = Z_NULL;
144 if(inflateInit2(&_zs, -15) != Z_OK) {
145 throw ZlibBufferException();
146 }
148 }
150 void ZlibBuffer::reset_inflation() throw(ZlibBufferException)
151 {
152 if (inflateReset(&_zs) != Z_OK)
153 throw ZlibBufferException();
154 }
156 GByteArray *ZlibBuffer::inflate(guint8 *in_buffer, int nbytes)
157 {
158 return do_inflate(in_buffer, nbytes);
159 }
161 GByteArray *ZlibBuffer::do_inflate(guint8 *data, int nbytes)
162 {
163 GByteArray *gba = g_byte_array_new();
164 guint8 out_buffer[BUFSIZE_STREAM];
166 _zs.avail_in = 0;
167 guint32 crc = crc32(0, Z_NULL, 0);
169 if (!_zs.avail_in) {
170 _zs.avail_in = nbytes;
171 _zs.next_in = (Bytef *)data;
172 crc = crc32(crc, (Bytef *)data, _zs.avail_in);
173 }
174 do {
175 _zs.next_out = out_buffer;
176 _zs.avail_out = BUFSIZE_STREAM;
178 int ret = ::inflate(&_zs, Z_NO_FLUSH);
179 if (BUFSIZE_STREAM != _zs.avail_out) {
180 unsigned int tmp_len = BUFSIZE_STREAM - _zs.avail_out;
181 g_byte_array_append(gba, out_buffer, tmp_len);
182 }
184 if (ret == Z_STREAM_END) {
185 break;
186 }
187 if (ret != Z_OK) {
188 std::fprintf(stderr, "decompression error %d\n", ret);
189 break;
190 }
191 } while (_zs.avail_in);
193 return gba;
194 }
196 int ZlibBuffer::copy_to_get(guint8 *data, int nbytes)
197 {
198 return do_copy_to_get(data, nbytes);
199 }
201 int ZlibBuffer::do_copy_to_get(guint8 *data, int nbytes)
202 {
203 if (nbytes + gptr() - eback() > _getsize)
204 reallocate_buffers(nbytes + gptr() - eback() + BUFSIZE_STREAM,
205 _putsize);
207 std::memcpy(gptr(), data, nbytes);
208 setg(eback(), gptr(), gptr() + nbytes);
209 return 1;
210 }
212 } // namespace Inkscape
214 /*
215 Local Variables:
216 mode:c++
217 c-file-style:"stroustrup"
218 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
219 indent-tabs-mode:nil
220 fill-column:99
221 End:
222 */
223 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :