aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/others/mimesh/libg3d-0.0.8/src/stream_zlib.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/others/mimesh/libg3d-0.0.8/src/stream_zlib.c')
-rw-r--r--src/others/mimesh/libg3d-0.0.8/src/stream_zlib.c192
1 files changed, 192 insertions, 0 deletions
diff --git a/src/others/mimesh/libg3d-0.0.8/src/stream_zlib.c b/src/others/mimesh/libg3d-0.0.8/src/stream_zlib.c
new file mode 100644
index 0000000..bfae2f5
--- /dev/null
+++ b/src/others/mimesh/libg3d-0.0.8/src/stream_zlib.c
@@ -0,0 +1,192 @@
1/* $Id:$ */
2
3/*
4 libg3d - 3D object loading library
5
6 Copyright (C) 2005-2009 Markus Dahms <mad@automagically.de>
7
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 2.1 of the License, or (at your option) any later version.
12
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public
19 License along with this library; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21*/
22#include <string.h>
23
24#include <g3d/types.h>
25#include <g3d/stream.h>
26
27#include <zlib.h>
28
29typedef struct {
30 G3DStream *stream;
31 gchar *uri;
32 z_streamp zstream;
33 gsize cmp_size; /* compressed size */
34 gsize cmp_read; /* compressed bytes read */
35 goffset offset; /* offset (decompressed) */
36 guint8 *inbuf;
37 guint8 *inbufp;
38 guint8 *buffer;
39 guint8 *bufp;
40 gsize bufpages;
41 gsize bufavail;
42 gboolean eof;
43} G3DStreamZlib;
44
45#define G3D_Z_CHUNK_SIZE (128 * 1024)
46
47static gsize zlib_refill_buffer(G3DStreamZlib *sz)
48{
49 gint ret;
50
51 /* FIXME: don't read beyond inflate stream */
52 sz->zstream->avail_in = g3d_stream_read(sz->stream, sz->inbuf,
53 MIN(G3D_Z_CHUNK_SIZE, (sz->cmp_size - sz->cmp_read)));
54 sz->cmp_read += sz->zstream->avail_in;
55 sz->zstream->next_in = sz->inbuf;
56#if DEBUG > 0
57 g_debug("ZLIB: %d bytes in input buffer", sz->zstream->avail_in);
58#endif
59
60 /* clean up previous refill */
61 if(sz->buffer)
62 g_free(sz->buffer);
63 sz->buffer = NULL;
64 sz->bufp = NULL;
65 sz->bufpages = 0;
66
67 /* decompress */
68 do {
69 /* add an output page */
70 sz->buffer = g_realloc(sz->buffer, (sz->bufpages + 1) *
71 G3D_Z_CHUNK_SIZE * sizeof(guint8));
72 sz->bufp = sz->buffer + G3D_Z_CHUNK_SIZE * sz->bufpages;
73 sz->bufpages ++;
74
75 sz->zstream->avail_out = G3D_Z_CHUNK_SIZE;
76 sz->zstream->next_out = sz->bufp;
77 ret = inflate(sz->zstream, Z_NO_FLUSH);
78 switch(ret) {
79 case Z_STREAM_ERROR:
80 g_warning("stream error");
81 return 0;
82 case Z_DATA_ERROR:
83 case Z_MEM_ERROR:
84 g_warning("zlib error: %d", ret);
85 return 0;
86 }
87 sz->bufavail += (G3D_Z_CHUNK_SIZE - sz->zstream->avail_out);
88#if DEBUG > 0
89 g_debug("ZLIB: %d bytes in output buffer", sz->bufavail);
90#endif
91 } while(sz->zstream->avail_out == 0);
92
93 sz->bufp = sz->buffer;
94 return sz->bufavail;
95}
96
97static gsize g3d_stream_zlib_read(gpointer ptr, gsize size, gpointer data)
98{
99 G3DStreamZlib *sz = data;
100 gsize n = size, nc, br = 0;
101 guint8 *bufp = ptr;
102
103#if DEBUG > 3
104 g_debug("ZLIB: reading %d bytes...", n);
105#endif
106
107 while(n > 0) {
108 if(sz->bufavail == 0)
109 zlib_refill_buffer(sz);
110
111 if(sz->bufavail == 0) {
112 sz->eof = TRUE;
113 return 0;
114 }
115
116 nc = MIN(n, sz->bufavail);
117 memcpy(bufp, sz->bufp, nc);
118 sz->bufp += nc;
119 bufp += nc;
120 sz->bufavail -= nc;
121 n -= nc;
122 br += nc;
123 sz->offset += nc;
124#if DEBUG > 3
125 g_debug("ZLIB: copied %d bytes [%02x]", nc, ((guint8 *)ptr)[0]);
126#endif
127 }
128
129 return br;
130}
131
132static goffset g3d_stream_zlib_tell(gpointer data)
133{
134 G3DStreamZlib *sz = data;
135 return sz->offset;
136}
137
138static gboolean g3d_stream_zlib_eof(gpointer data)
139{
140 G3DStreamZlib *sz = data;
141 return sz->eof;
142}
143
144static gint g3d_stream_zlib_close(gpointer data)
145{
146 G3DStreamZlib *sz = data;
147
148 if(sz->inbuf)
149 g_free(sz->inbuf);
150 if(sz->buffer)
151 g_free(sz->buffer);
152
153 inflateEnd(sz->zstream);
154 g_free(sz->zstream);
155 g_free(sz->uri);
156 g_free(sz);
157 return 0;
158}
159
160/*****************************************************************************/
161
162EAPI
163G3DStream *g3d_stream_zlib_inflate_stream(G3DStream *stream, gsize cmp_size)
164{
165 G3DStreamZlib *sz;
166 guint32 flags = 0;
167 gint ret;
168
169 sz = g_new0(G3DStreamZlib, 1);
170 sz->stream = stream;
171 sz->cmp_size = cmp_size;
172 sz->zstream = g_new0(z_stream, 1);
173 ret = inflateInit(sz->zstream);
174 if(ret != Z_OK) {
175 g_warning("stream_zlib: failed to init");
176 g_free(sz->zstream);
177 g_free(sz);
178 }
179
180 sz->inbuf = g_new0(guint8, G3D_Z_CHUNK_SIZE);
181
182 flags |= (1 << G3D_STREAM_READABLE);
183 sz->uri = g_strdup_printf("%s:gzipped@0x%08x", stream->uri,
184 (guint32)g3d_stream_tell(stream));
185
186 return g3d_stream_new_custom(flags, sz->uri,
187 g3d_stream_zlib_read, NULL /* readline */,
188 NULL /* seek */, g3d_stream_zlib_tell,
189 NULL /* size */, g3d_stream_zlib_eof,
190 g3d_stream_zlib_close, sz, NULL);
191}
192