Code

include libpng with pkg-config check for include path (fixes #1519300)
[inkscape.git] / src / streams-zlib.cpp
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 <vector>
13 #include "streams-zlib.h"
15 namespace Inkscape {
17 /**
18  * ZlibBuffer
19  */
21 ZlibBuffer::ZlibBuffer(URIHandle& urih)
22   : _urihandle(&urih), _putsize(BUFSIZE_STREAM), _getsize(BUFSIZE_STREAM)
23 {
24     init_inflation();
25 }
27 int ZlibBuffer::allocate_buffers()
28 {
29     if (!eback()) {
30         char *buf = new char[_getsize + _putsize];
31         setg(buf, buf , buf);
32         buf += _getsize;
33         setp(buf, buf + _putsize);
34         return 1;
35     }
36     return 0;
37 }
39 int ZlibBuffer::reallocate_buffers(int new_getsize, int new_putsize)
40 {
41     char *new_buffer = new char[new_getsize + new_putsize];
43     std::memcpy(new_buffer, eback(), _getsize);
44     std::memcpy(new_buffer, eback() + _getsize, _putsize);
46     setg(new_buffer, new_buffer + (gptr() - eback()),
47          new_buffer + new_getsize);
48     new_buffer += new_getsize;
49     setp(new_buffer, new_buffer + new_putsize);
51     _getsize = new_getsize;
52     _putsize = new_putsize;
54     return 1;
55 }
57 int ZlibBuffer::underflow()
58 {
59     if (eback() == 0 && allocate_buffers() == 0)
60         return EOF;
62     if (consume_and_inflate() == EOF)
63         return EOF;
65     return *(unsigned char *)gptr();
66 }
68 int ZlibBuffer::overflow(int c)
69 {
70     if (c == EOF)
71         return flush_output();
73     if (pbase() == 0 && allocate_buffers() == 0)
74         return EOF;
76     if (pptr() >= epptr() &&
77         flush_output() == EOF)
78         return EOF;
80     putchar(c);
82     if (pptr() >= epptr() &&
83         flush_output() == EOF)
84         return EOF;
86     return c;
87 }
89 int ZlibBuffer::consume(guint8 *buf, int nbytes)
90 {
91     return do_consume(buf, nbytes);
92 }
94 int ZlibBuffer::do_consume(guint8 *buf, int nbytes)
95 {
96     nbytes = _urihandle->read(buf, nbytes);
98     if (nbytes == EOF)
99         return EOF;
100     else if (nbytes == 0)
101         return EOF;
103     return nbytes;
106 int ZlibBuffer::do_consume_and_inflate(int nbytes)
108     std::vector<guint8> buf(nbytes);
110     int ret=consume(&buf[0], nbytes);
111     
112     if ( ret != EOF ) {
113         ret = 1;
114         GByteArray *gba = inflate(&buf[0], nbytes);
115         copy_to_get(gba->data, gba->len);
116         g_byte_array_free(gba, TRUE);
117     }
119     return ret;
122 int ZlibBuffer::consume_and_inflate()
124     return do_consume_and_inflate(BUFSIZE_STREAM);
127 int ZlibBuffer::flush_output()
129     if (pptr() <= pbase())
130         return 0;
131     int len = pptr() - pbase();
132     int nbytes = _urihandle->write(pbase(), len);
133     setp(pbase(), pbase() + BUFSIZE_STREAM);
134     if (len == nbytes)
135         return 0;
136     else
137         return EOF;
140 void ZlibBuffer::init_inflation() throw(ZlibBufferException)
142     memset(&_zs, 0, sizeof(z_stream));
144     _zs.zalloc = Z_NULL;
145     _zs.zfree = Z_NULL;
146     _zs.opaque = Z_NULL;
148     if(inflateInit2(&_zs, -15) != Z_OK) {
149         throw ZlibBufferException();
150     }
154 void ZlibBuffer::reset_inflation() throw(ZlibBufferException)
156     if (inflateReset(&_zs) != Z_OK)
157         throw ZlibBufferException();
160 GByteArray *ZlibBuffer::inflate(guint8 *in_buffer, int nbytes)
162     return do_inflate(in_buffer, nbytes);
165 GByteArray *ZlibBuffer::do_inflate(guint8 *data, int nbytes)
167     GByteArray *gba = g_byte_array_new();
168     guint8 out_buffer[BUFSIZE_STREAM];
170     _zs.avail_in = 0;
171     guint32 crc = crc32(0, Z_NULL, 0);
173     if (!_zs.avail_in) {
174         _zs.avail_in = nbytes;
175         _zs.next_in = (Bytef *)data;
176         crc = crc32(crc, (Bytef *)data, _zs.avail_in);
177     }
178     do {
179         _zs.next_out = out_buffer;
180         _zs.avail_out = BUFSIZE_STREAM;
182         int ret = ::inflate(&_zs, Z_NO_FLUSH);
183         if (BUFSIZE_STREAM != _zs.avail_out) {
184             unsigned int tmp_len = BUFSIZE_STREAM - _zs.avail_out;
185             g_byte_array_append(gba, out_buffer, tmp_len);
186         }
187         
188         if (ret == Z_STREAM_END) {
189             break;
190         }
191         if (ret != Z_OK) {
192             std::fprintf(stderr, "decompression error %d\n", ret);
193             break;
194         }
195     } while (_zs.avail_in);
197     return gba;
200 int ZlibBuffer::copy_to_get(guint8 *data, int nbytes)
202     return do_copy_to_get(data, nbytes);
205 int ZlibBuffer::do_copy_to_get(guint8 *data, int nbytes)
207     if (nbytes + gptr() - eback() > _getsize)
208         reallocate_buffers(nbytes + gptr() - eback() + BUFSIZE_STREAM,
209                            _putsize);
211     std::memcpy(gptr(), data, nbytes);
212     setg(eback(), gptr(), gptr() + nbytes);
213     return 1;
216 } // namespace Inkscape
218 /*
219   Local Variables:
220   mode:c++
221   c-file-style:"stroustrup"
222   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
223   indent-tabs-mode:nil
224   fill-column:99
225   End:
226 */
227 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :