diff options
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.c | 192 |
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 | |||
29 | typedef 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 | |||
47 | static 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 | |||
97 | static 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 | |||
132 | static goffset g3d_stream_zlib_tell(gpointer data) | ||
133 | { | ||
134 | G3DStreamZlib *sz = data; | ||
135 | return sz->offset; | ||
136 | } | ||
137 | |||
138 | static gboolean g3d_stream_zlib_eof(gpointer data) | ||
139 | { | ||
140 | G3DStreamZlib *sz = data; | ||
141 | return sz->eof; | ||
142 | } | ||
143 | |||
144 | static 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 | |||
162 | EAPI | ||
163 | G3DStream *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 | |||