16
16
* You should have received a copy of the GNU Lesser General Public License
17
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
25
25
#include <gsf/gsf-impl-utils.h>
26
26
#include <string.h>
29
29
#include <gsf/gsf-input-bzip.h>
32
32
#define GET_CLASS(instance) G_TYPE_INSTANCE_GET_CLASS (instance, GSF_INPUT_TYPE, GsfInputClass)
34
static GObjectClass *parent_class;
89
91
gsf_input_finalize (GObject *obj)
91
GObjectClass *parent_class;
93
GsfInput *input = GSF_INPUT (obj);
93
GsfInput *input = GSF_INPUT (obj);
94
if (input->name != NULL) {
98
97
if (input->container != NULL) {
99
98
g_object_unref (G_OBJECT (input->container));
100
99
input->container = NULL;
103
parent_class = g_type_class_peek (G_TYPE_OBJECT);
104
if (parent_class && parent_class->finalize)
105
parent_class->finalize (obj);
101
parent_class->finalize (obj);
120
116
gsf_input_class_init (GObjectClass *gobject_class)
118
parent_class = g_type_class_peek_parent (gobject_class);
122
120
gobject_class->finalize = gsf_input_finalize;
123
121
/* gobject_class->set_property = gsf_input_set_property; */
124
122
gobject_class->get_property = gsf_input_get_property;
126
124
g_object_class_install_property (gobject_class,
128
g_param_spec_pointer ("name", "Name",
126
g_param_spec_string ("name", "Name",
131
131
g_object_class_install_property (gobject_class,
133
g_param_spec_pointer ("size", "Size",
133
g_param_spec_int64 ("size", "Size",
136
138
g_object_class_install_property (gobject_class,
138
g_param_spec_pointer ("eof", "OEF",
140
g_param_spec_boolean ("eof", "OEF",
140
144
G_PARAM_READABLE));
141
145
g_object_class_install_property (gobject_class,
143
g_param_spec_pointer ("remaining", "Remaining",
144
"Amount of Data Remaining",
147
g_param_spec_int64 ("remaining", "Remaining",
148
"Amount of Data Remaining",
146
152
g_object_class_install_property (gobject_class,
148
g_param_spec_pointer ("position", "Position",
149
"The Output's Current Position",
154
g_param_spec_int64 ("position", "Position",
155
"The Output's Current Position",
153
161
GSF_CLASS_ABSTRACT (GsfInput, gsf_input,
158
166
* gsf_input_name :
161
* Returns @input's name in utf8 form, DO NOT FREE THIS STRING
167
* @input: the input stream
169
* The name of the input stream.
171
* Returns: @input's name in utf8 form, or NULL if it has no name.
164
174
gsf_input_name (GsfInput *input)
185
195
* gsf_input_dup :
186
* @input : The input to duplicate
187
* @err : optionally NULL
196
* @input: The input to duplicate
197
* @err: optionally NULL
189
199
* Duplicates input @src leaving the new one at the same offset.
191
* Returns : the duplicate, or NULL on error
201
* Returns: the duplicate, or NULL on error
194
204
gsf_input_dup (GsfInput *input, GError **err)
200
210
dst = GET_CLASS (input)->Dup (input, err);
201
211
if (dst != NULL) {
202
dst->size = input->size;
212
if (dst->size != input->size) {
214
*err = g_error_new (gsf_input_error_id (), 0,
215
"Duplicate size mismatch");
216
g_object_unref (dst);
219
if (gsf_input_seek (dst, input->cur_offset, G_SEEK_SET)) {
221
*err = g_error_new (gsf_input_error_id (), 0,
223
g_object_unref (dst);
203
227
if (input->name != NULL)
204
228
gsf_input_set_name (dst, input->name);
205
229
dst->container = input->container;
206
230
if (dst->container != NULL)
207
231
g_object_ref (G_OBJECT (dst->container));
208
gsf_input_seek (dst, (gsf_off_t)input->cur_offset, G_SEEK_SET);
237
* gsf_input_open_sibling :
240
* UNIMPLEMENTED BY ANY BACKEND
241
* and it is probably unnecessary. gsf_input_get_container provides
242
* enough power to do what is necessary.
244
* Attempts to open a 'sibling' of @input. The caller is responsible for
245
* managing the resulting object.
247
* Returns: A related #GsfInput or NULL on failure.
250
gsf_input_sibling (GsfInput const *input, char const *name, GError **err)
252
g_return_val_if_fail (GET_CLASS (input)->OpenSibling, NULL);
254
return GET_CLASS (input)->OpenSibling (input, name, err);
214
258
* gsf_input_size :
217
261
* Looks up and caches the number of bytes in the input
219
* Returns : the size or -1 on error
263
* Returns: the size or -1 on error
222
266
gsf_input_size (GsfInput *input)
245
289
* gsf_input_read :
248
* @optional_buffer : If supplied copy the data into it
290
* @input: the input stream
291
* @num_bytes: number of bytes to read
292
* @optional_buffer: NULL, or pointer to destination memory area
250
* Read at at least @num_bytes. Does not change the current position if there
294
* Read at least @num_bytes. Does not change the current position if there
251
295
* is an error. Will only read if the entire amount can be read. Invalidates
252
296
* the buffer associated with previous calls to gsf_input_read.
254
* Returns : pointer to the buffer or NULL if there is an error or 0 bytes are
298
* Returns: pointer to the buffer or NULL if there is an error or 0 bytes are
270
314
input->cur_offset += num_bytes;
276
319
* gsf_input_remaining :
320
* @input: the input stream
279
* Returns the number of bytes left in the file.
322
* Returns: the number of bytes left in the file.
282
325
gsf_input_remaining (GsfInput *input)
304
347
* gsf_input_seek :
309
* Returns TRUE on error.
348
* @input: the input stream
349
* @offset: target offset
350
* @whence: determines whether the offset is relative to the beginning or
351
* the end of the stream, or to the current location.
353
* Move the current location in the input stream.
355
* Returns: TRUE on error.
312
358
gsf_input_seek (GsfInput *input, gsf_off_t offset, GSeekType whence)
335
381
if (GET_CLASS (input)->Seek (input, offset, whence))
337
384
input->cur_offset = pos;
342
389
* gsf_input_set_name :
390
* @input: the input stream
391
* @name: the new name of the stream, or NULL.
348
* Returns : TRUE if the assignment was ok.
395
* Returns: TRUE if the assignment was ok.
351
398
gsf_input_set_name (GsfInput *input, char const *name)
355
402
g_return_val_if_fail (input != NULL, FALSE);
357
404
buf = g_strdup (name);
358
if (input->name != NULL)
359
g_free (input->name);
405
g_free (input->name);
360
406
input->name = buf;
411
* gsf_input_set_name_from_filename :
412
* @input: the input stream
413
* @filename: the (fs-sys encoded) filename
417
* Returns: TRUE if the assignment was ok.
420
gsf_input_set_name_from_filename (GsfInput *input, char const *filename)
422
g_return_val_if_fail (input != NULL, FALSE);
424
g_free (input->name);
425
input->name = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
365
431
* gsf_input_set_container :
432
* @input: the input stream
369
* Returns : TRUE if the assignment was ok.
435
* Returns: TRUE if the assignment was ok.
372
438
gsf_input_set_container (GsfInput *input, GsfInfile *container)
385
451
* gsf_input_set_size :
452
* @input: the input stream
453
* @size: the size of the stream
389
* Returns : TRUE if the assignment was ok.
455
* Returns: TRUE if the assignment was ok.
392
458
gsf_input_set_size (GsfInput *input, gsf_off_t size)
394
460
g_return_val_if_fail (input != NULL, FALSE);
461
g_return_val_if_fail (size >= 0, FALSE);
396
463
input->size = size;
401
* gsf_input_seek_emulate: Emulate forward seeks by reading.
405
* Returns : TRUE if the emulation worked.
468
* gsf_input_seek_emulate :
469
* @input: stream to emulate seek for
470
* @pos: absolute position to seek to
472
* Emulate forward seeks by reading.
474
* Returns: TRUE if the emulation failed.
408
477
gsf_input_seek_emulate (GsfInput *input, gsf_off_t pos)
421
490
/****************************************************************************/
493
* gsf_input_error_id :
426
* Returns : A utility quark to flag a GError as being an input problem.
495
* Returns: A utility quark to flag a GError as being an input problem.
429
gsf_input_error (void)
498
gsf_input_error_id (void)
431
500
static GQuark quark;
433
quark = g_quark_from_static_string ("gsf_input_error");
502
quark = g_quark_from_static_string ("gsf_input_error_id");
509
* Deprecated as of GSF 1.12.0; use gsf_input_error_id() instead.
511
* Returns: A utility quark to flag a GError as being an input problem.
514
gsf_input_error (void)
516
return gsf_input_error_id ();
437
519
/****************************************************************************/
439
521
#define GSF_READ_BUFSIZE (1024 * 4)
442
524
* gsf_input_copy :
443
* @input : a non-null #GsfInput
444
* @output : a non-null #GsfOutput
525
* @input: a non-null #GsfInput
526
* @output: a non-null #GsfOutput
446
528
* Copy the contents from @input to @output from their respective
447
529
* current positions. So if you want to be sure to copy *everything*,
448
530
* make sure to call gsf_input_seek (input, 0, G_SEEK_SET) and
449
531
* gsf_output_seek (output, 0, G_SEEK_SET) first, if applicable.
451
* Returns : TRUE on Success
533
* Returns: TRUE on Success
454
536
gsf_input_copy (GsfInput *input, GsfOutput *output)
490
572
gsf_off_t cur_offset = src->cur_offset;
491
573
const guint8 *data;
493
if (gsf_input_seek (src, (gsf_off_t) 0, G_SEEK_SET))
575
if (gsf_input_seek (src, 0, G_SEEK_SET))
496
578
/* Read header up front, so we avoid extra seeks in tests. */
503
585
const unsigned char gzip_sig[2] = { 0x1f, 0x8b };
505
587
if (memcmp (gzip_sig, data, sizeof (gzip_sig)) == 0) {
506
GsfInputGZip *res = gsf_input_gzip_new (src, NULL);
588
GsfInput *res = gsf_input_gzip_new (src, NULL);
508
590
g_object_unref (G_OBJECT (src));
509
return gsf_input_uncompress (GSF_INPUT (res));
591
return gsf_input_uncompress (res);
515
597
/* Let's try bzip. */
517
const guint8 * bzip_sig = "BZh";
599
guint8 const *bzip_sig = "BZh";
519
if (memcmp (gzip_sig, data, strlen (bzip_sig)) == 0) {
520
GsfInputMemory *res = gsf_input_memory_new_from_bzip (src, NULL);
601
if (memcmp (bzip_sig, data, strlen (bzip_sig)) == 0) {
602
GsfInput *res = gsf_input_memory_new_from_bzip (src, NULL);
522
604
g_object_unref (G_OBJECT (src));
523
return gsf_input_uncompress (GSF_INPUT (res));
605
return gsf_input_uncompress (res);
555
637
if (len > 3 && !strstr (uri, ":/")) {
556
638
/* assume plain file */
557
input = GSF_INPUT (gsf_input_stdio_new (uri, err));
639
input = gsf_input_stdio_new (uri, err);
560
642
/* have gnome, let GnomeVFS deal with this */
561
input = GSF_INPUT (gsf_input_gnomevfs_new (uri, err));
643
input = gsf_input_gnomevfs_new (uri, err);
563
645
if (len > 7 && !strncmp (uri, "file:/", 6)) {
564
646
/* dumb attempt to translate this into a local path */
565
input = GSF_INPUT (gsf_input_stdio_new (uri+7, err));
647
input = gsf_input_stdio_new (uri+7, err);
567
649
/* else: unknown or unhandled protocol - bail */