diff options
Diffstat (limited to 'src/others/mimesh/libg3d-0.0.8/src/stream_gsf.c')
-rw-r--r-- | src/others/mimesh/libg3d-0.0.8/src/stream_gsf.c | 355 |
1 files changed, 355 insertions, 0 deletions
diff --git a/src/others/mimesh/libg3d-0.0.8/src/stream_gsf.c b/src/others/mimesh/libg3d-0.0.8/src/stream_gsf.c new file mode 100644 index 0000000..d059a62 --- /dev/null +++ b/src/others/mimesh/libg3d-0.0.8/src/stream_gsf.c | |||
@@ -0,0 +1,355 @@ | |||
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 | |||
23 | #include <string.h> | ||
24 | |||
25 | #include <gsf/gsf-input.h> | ||
26 | #include <gsf/gsf-infile.h> | ||
27 | #include <gsf/gsf-input-stdio.h> | ||
28 | #include <gsf/gsf-input-memory.h> | ||
29 | #include <gsf/gsf-input-gzip.h> | ||
30 | #include <gsf/gsf-infile-msole.h> | ||
31 | #include <gsf/gsf-infile-zip.h> | ||
32 | |||
33 | #include <g3d/stream.h> | ||
34 | |||
35 | #include "stream_gsf_class.h" | ||
36 | |||
37 | typedef struct { | ||
38 | GsfInput *input_container; | ||
39 | GsfInfile *infile_msole; | ||
40 | GsfInfile *infile_zip; | ||
41 | GsfInput *input_subfile; | ||
42 | gchar *uri; | ||
43 | } G3DStreamGsf; | ||
44 | |||
45 | static gsize g3d_stream_gsf_read(gpointer ptr, gsize size, gpointer data) | ||
46 | { | ||
47 | G3DStreamGsf *sg = (G3DStreamGsf *)data; | ||
48 | gsize n; | ||
49 | |||
50 | n = MIN(size, gsf_input_remaining(sg->input_subfile)); | ||
51 | gsf_input_read(sg->input_subfile, n, (guint8 *)ptr); | ||
52 | return n; | ||
53 | } | ||
54 | |||
55 | static gint g3d_stream_gsf_seek(gpointer data, goffset offset, | ||
56 | GSeekType whence) | ||
57 | { | ||
58 | G3DStreamGsf *sg = (G3DStreamGsf *)data; | ||
59 | return gsf_input_seek(sg->input_subfile, offset, whence); | ||
60 | } | ||
61 | |||
62 | static goffset g3d_stream_gsf_tell(gpointer data) | ||
63 | { | ||
64 | G3DStreamGsf *sg = (G3DStreamGsf *)data; | ||
65 | return gsf_input_tell(sg->input_subfile); | ||
66 | } | ||
67 | |||
68 | static goffset g3d_stream_gsf_size(gpointer data) | ||
69 | { | ||
70 | G3DStreamGsf *sg = (G3DStreamGsf *)data; | ||
71 | return gsf_input_size(sg->input_subfile); | ||
72 | } | ||
73 | |||
74 | static gboolean g3d_stream_gsf_eof(gpointer data) | ||
75 | { | ||
76 | G3DStreamGsf *sg = (G3DStreamGsf *)data; | ||
77 | if(gsf_input_remaining(sg->input_subfile) <= 0) | ||
78 | return TRUE; | ||
79 | return gsf_input_eof(sg->input_subfile); | ||
80 | } | ||
81 | |||
82 | static gint g3d_stream_gsf_close(gpointer data) | ||
83 | { | ||
84 | G3DStreamGsf *sg = (G3DStreamGsf *)data; | ||
85 | g_object_unref(sg->input_subfile); | ||
86 | if(sg->infile_msole) | ||
87 | g_object_unref(sg->infile_msole); | ||
88 | if(sg->infile_zip) | ||
89 | g_object_unref(sg->infile_zip); | ||
90 | if(sg->uri) | ||
91 | g_free(sg->uri); | ||
92 | g_object_unref(sg->input_container); | ||
93 | g_free(sg); | ||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | /****************************************************************************/ | ||
98 | |||
99 | static GsfInput *stream_gsf_chdir(GsfInput *input, gchar *dirname) | ||
100 | { | ||
101 | GsfInput *parent = input, *newinput = NULL; | ||
102 | gchar **dirs, **dir; | ||
103 | |||
104 | dirs = g_strsplit(dirname, "/", 0); | ||
105 | for(dir = dirs; *dir != NULL; dir ++) { | ||
106 | newinput = gsf_infile_child_by_name(GSF_INFILE(parent), | ||
107 | *dir); | ||
108 | if((newinput == NULL) || (!GSF_IS_INFILE(newinput))) { | ||
109 | g_strfreev(dirs); | ||
110 | return NULL; | ||
111 | } | ||
112 | parent = newinput; | ||
113 | } | ||
114 | g_strfreev(dirs); | ||
115 | return newinput; | ||
116 | } | ||
117 | |||
118 | /*****************************************************************************/ | ||
119 | |||
120 | EAPI | ||
121 | G3DStream *g3d_stream_open_gzip_from_stream(G3DStream *stream) | ||
122 | { | ||
123 | G3DStreamGsf *sg; | ||
124 | GsfInput *source; | ||
125 | GError *error = NULL; | ||
126 | guint32 flags = 0; | ||
127 | |||
128 | source = g3d_gsf_input_stream_new(stream); | ||
129 | if(source == NULL) | ||
130 | return NULL; | ||
131 | |||
132 | sg = g_new0(G3DStreamGsf, 1); | ||
133 | sg->input_container = source; | ||
134 | |||
135 | sg->input_subfile = gsf_input_gzip_new(source, &error); | ||
136 | if(error) { | ||
137 | g_warning("failed to read gzipped data from %s: %s", stream->uri, | ||
138 | error->message); | ||
139 | g_object_unref(sg->input_container); | ||
140 | g_error_free(error); | ||
141 | g_free(sg); | ||
142 | } | ||
143 | |||
144 | sg->uri = g_strdup_printf("%s#gzip@0x%08x", stream->uri, | ||
145 | (guint32)g3d_stream_tell(stream)); | ||
146 | |||
147 | flags |= (1 << G3D_STREAM_READABLE); | ||
148 | flags |= (1 << G3D_STREAM_SEEKABLE); | ||
149 | |||
150 | return g3d_stream_new_custom(flags, sg->uri, | ||
151 | g3d_stream_gsf_read, NULL, | ||
152 | g3d_stream_gsf_seek, g3d_stream_gsf_tell, | ||
153 | g3d_stream_gsf_size, g3d_stream_gsf_eof, | ||
154 | g3d_stream_gsf_close, sg, NULL); | ||
155 | } | ||
156 | |||
157 | |||
158 | /*****************************************************************************/ | ||
159 | /* Zip stuff */ | ||
160 | |||
161 | static G3DStream *g3d_stream_open_zip_from_input(GsfInput *input, | ||
162 | const gchar *subfile) { | ||
163 | G3DStreamGsf *sg; | ||
164 | GError *error = NULL; | ||
165 | guint32 flags = 0; | ||
166 | GsfInput *input_dir; | ||
167 | gchar *basename, *dirname; | ||
168 | G3DStream *zip_stream = g3d_gsf_input_stream_get_stream(input); | ||
169 | |||
170 | sg = g_new0(G3DStreamGsf, 1); | ||
171 | sg->input_container = input; | ||
172 | |||
173 | sg->infile_zip = gsf_infile_zip_new(sg->input_container, &error); | ||
174 | if(error != NULL) { | ||
175 | g_warning("error reading ZIP data from '%s': %s", | ||
176 | gsf_input_name(input), error->message); | ||
177 | g_object_unref(sg->input_container); | ||
178 | g_error_free(error); | ||
179 | g_free(sg); | ||
180 | return NULL; | ||
181 | } | ||
182 | |||
183 | if(strchr(subfile, '/')) { | ||
184 | basename = g_path_get_basename(subfile); | ||
185 | dirname = g_path_get_dirname(subfile); | ||
186 | input_dir = stream_gsf_chdir(GSF_INPUT(sg->infile_zip), dirname); | ||
187 | sg->input_subfile = gsf_infile_child_by_name(GSF_INFILE(input_dir), | ||
188 | basename); | ||
189 | g_free(basename); | ||
190 | g_free(dirname); | ||
191 | } else { | ||
192 | sg->input_subfile = gsf_infile_child_by_name(sg->infile_zip, subfile); | ||
193 | } | ||
194 | |||
195 | if(!GSF_IS_INPUT(sg->input_subfile)) { | ||
196 | g_warning("error: %s is not an input file", subfile); | ||
197 | g_object_unref(sg->infile_zip); | ||
198 | g_object_unref(sg->input_container); | ||
199 | g_free(sg); | ||
200 | return NULL; | ||
201 | } | ||
202 | |||
203 | flags |= (1 << G3D_STREAM_READABLE); | ||
204 | flags |= (1 << G3D_STREAM_SEEKABLE); | ||
205 | |||
206 | sg->uri = g_strdup_printf("zip://%s|%s", gsf_input_name(input), subfile); | ||
207 | |||
208 | if (NULL != zip_stream->zip_container) | ||
209 | zip_stream = zip_stream->zip_container; | ||
210 | |||
211 | return g3d_stream_new_custom(flags, sg->uri, | ||
212 | g3d_stream_gsf_read, NULL, | ||
213 | g3d_stream_gsf_seek, g3d_stream_gsf_tell, | ||
214 | g3d_stream_gsf_size, g3d_stream_gsf_eof, | ||
215 | g3d_stream_gsf_close, sg, zip_stream); | ||
216 | } | ||
217 | |||
218 | EAPI | ||
219 | G3DStream *g3d_stream_open_zip(const gchar *filename, const gchar *subfile) | ||
220 | { | ||
221 | GsfInput *input; | ||
222 | GError *error = NULL; | ||
223 | |||
224 | /* FIXME: This wont work if the "file" is a buffer. */ | ||
225 | input = gsf_input_stdio_new(filename, &error); | ||
226 | if(error != NULL) { | ||
227 | g_warning("error opening container file '%s': %s", filename, | ||
228 | error->message); | ||
229 | g_error_free(error); | ||
230 | return NULL; | ||
231 | } | ||
232 | |||
233 | return g3d_stream_open_zip_from_input(input, subfile); | ||
234 | } | ||
235 | |||
236 | EAPI | ||
237 | G3DStream *g3d_stream_open_zip_from_stream(G3DStream *stream, | ||
238 | const gchar *subfile) | ||
239 | { | ||
240 | GsfInput *input; | ||
241 | |||
242 | input = g3d_gsf_input_stream_new(stream); | ||
243 | if(!input) | ||
244 | return NULL; | ||
245 | |||
246 | return g3d_stream_open_zip_from_input(input, subfile); | ||
247 | } | ||
248 | |||
249 | /*****************************************************************************/ | ||
250 | /* Structured File stuff */ | ||
251 | |||
252 | static G3DStream *g3d_stream_open_structured_file_from_input(GsfInput *input, | ||
253 | const gchar *subfile) | ||
254 | { | ||
255 | G3DStreamGsf *sg; | ||
256 | GsfInput *input_gzipped, *input_tmp; | ||
257 | GError *error = NULL; | ||
258 | guint32 flags = 0; | ||
259 | |||
260 | sg = g_new0(G3DStreamGsf, 1); | ||
261 | sg->input_container = input; | ||
262 | |||
263 | sg->infile_msole = gsf_infile_msole_new(sg->input_container, &error); | ||
264 | if(error != NULL) { | ||
265 | g_warning("error reading OLE data from '%s': %s", | ||
266 | gsf_input_name(input), error->message); | ||
267 | g_object_unref(sg->input_container); | ||
268 | g_error_free(error); | ||
269 | g_free(sg); | ||
270 | return NULL; | ||
271 | } | ||
272 | #if DEBUG > 2 | ||
273 | g_debug("GSF: new MSOLE infile"); | ||
274 | #endif | ||
275 | sg->input_subfile = gsf_infile_child_by_name(sg->infile_msole, subfile); | ||
276 | if(error != NULL) { | ||
277 | g_warning("error opening contained file '%s' in '%s': %s", | ||
278 | subfile, gsf_input_name(input), error->message); | ||
279 | g_object_unref(sg->infile_msole); | ||
280 | g_object_unref(sg->input_container); | ||
281 | g_error_free(error); | ||
282 | g_free(sg); | ||
283 | return NULL; | ||
284 | } | ||
285 | if(!GSF_IS_INPUT(sg->input_subfile)) { | ||
286 | g_object_unref(sg->infile_msole); | ||
287 | g_object_unref(sg->input_container); | ||
288 | g_free(sg); | ||
289 | return NULL; | ||
290 | } | ||
291 | |||
292 | /* try to open subfile as gzipped */ | ||
293 | input_gzipped = gsf_input_gzip_new(sg->input_subfile, &error); | ||
294 | if(error != NULL) { | ||
295 | /* failed to open gzip data */ | ||
296 | g_error_free(error); | ||
297 | } else { | ||
298 | /* succeeded to open gzip data */ | ||
299 | input_tmp = sg->input_subfile; | ||
300 | sg->input_subfile = input_gzipped; | ||
301 | g_object_unref(input_tmp); | ||
302 | } | ||
303 | |||
304 | #if DEBUG > 2 | ||
305 | g_debug("GSF: got subfile '%s'", subfile); | ||
306 | #endif | ||
307 | flags |= (1 << G3D_STREAM_READABLE); | ||
308 | flags |= (1 << G3D_STREAM_SEEKABLE); | ||
309 | |||
310 | sg->uri = g_strdup_printf("wsf://%s/%s", gsf_input_name(input), subfile); | ||
311 | return g3d_stream_new_custom(flags, sg->uri, | ||
312 | g3d_stream_gsf_read, NULL, | ||
313 | g3d_stream_gsf_seek, g3d_stream_gsf_tell, | ||
314 | g3d_stream_gsf_size, g3d_stream_gsf_eof, | ||
315 | g3d_stream_gsf_close, sg, NULL); | ||
316 | } | ||
317 | |||
318 | EAPI | ||
319 | G3DStream *g3d_stream_open_structured_file(const gchar *filename, | ||
320 | const gchar *subfile) | ||
321 | { | ||
322 | GsfInput *container; | ||
323 | GError *error = NULL; | ||
324 | |||
325 | #if DEBUG > 2 | ||
326 | g_debug("GSF: Hello, World!"); | ||
327 | #endif | ||
328 | |||
329 | container = gsf_input_stdio_new(filename, &error); | ||
330 | if(error != NULL) { | ||
331 | g_warning("error opening structured file '%s': %s", filename, | ||
332 | error->message); | ||
333 | g_error_free(error); | ||
334 | return NULL; | ||
335 | } | ||
336 | #if DEBUG > 2 | ||
337 | g_debug("GSF: opened file '%s'", filename); | ||
338 | #endif | ||
339 | |||
340 | return g3d_stream_open_structured_file_from_input(container, subfile); | ||
341 | } | ||
342 | |||
343 | EAPI | ||
344 | G3DStream *g3d_stream_open_structured_file_from_stream(G3DStream *stream, | ||
345 | const gchar *subfile) | ||
346 | { | ||
347 | GsfInput *input; | ||
348 | |||
349 | input = g3d_gsf_input_stream_new(stream); | ||
350 | if(!input) | ||
351 | return NULL; | ||
352 | |||
353 | return g3d_stream_open_structured_file_from_input(input, subfile); | ||
354 | } | ||
355 | |||