~ubuntu-branches/debian/lenny/libgsf/lenny

« back to all changes in this revision

Viewing changes to gsf/gsf-input.c

  • Committer: Bazaar Package Importer
  • Author(s): J.H.M. Dassen (Ray)
  • Date: 2006-11-06 22:45:03 UTC
  • mfrom: (1.2.1 upstream) (2.1.1 dapper)
  • Revision ID: james.westby@ubuntu.com-20061106224503-g6pmv1m82zy8jya9
Tags: 1.14.3-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 *
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
19
19
 * USA
20
20
 */
21
21
 
25
25
#include <gsf/gsf-impl-utils.h>
26
26
#include <string.h>
27
27
 
28
 
#ifdef HAVE_BZIP
 
28
#ifdef HAVE_BZ2
29
29
#include <gsf/gsf-input-bzip.h>
30
30
#endif
31
31
 
32
32
#define GET_CLASS(instance) G_TYPE_INSTANCE_GET_CLASS (instance, GSF_INPUT_TYPE, GsfInputClass)
33
33
 
 
34
static GObjectClass *parent_class;
 
35
 
34
36
enum {
35
37
        PROP_0,
36
38
        PROP_NAME,
88
90
static void
89
91
gsf_input_finalize (GObject *obj)
90
92
{
91
 
        GObjectClass *parent_class;
 
93
        GsfInput *input = GSF_INPUT (obj);
92
94
 
93
 
        GsfInput *input = GSF_INPUT (obj);
94
 
        if (input->name != NULL) {
95
 
                g_free (input->name);
96
 
                input->name = NULL;
97
 
        }
 
95
        g_free (input->name);
 
96
        input->name = NULL;
98
97
        if (input->container != NULL) {
99
98
                g_object_unref (G_OBJECT (input->container));
100
99
                input->container = NULL;
101
100
        }
102
 
 
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);
106
102
}
107
103
 
108
104
static void
119
115
static void
120
116
gsf_input_class_init (GObjectClass *gobject_class)
121
117
{
 
118
        parent_class = g_type_class_peek_parent (gobject_class);
 
119
 
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;
125
123
 
126
124
        g_object_class_install_property (gobject_class,
127
125
                                         PROP_NAME,
128
 
                                         g_param_spec_pointer ("name", "Name",
129
 
                                                               "The Input's Name",
130
 
                                                               G_PARAM_READABLE));
 
126
                                         g_param_spec_string ("name", "Name",
 
127
                                                              "The Input's Name",
 
128
                                                              NULL,
 
129
                                                              GSF_PARAM_STATIC |
 
130
                                                              G_PARAM_READABLE));
131
131
        g_object_class_install_property (gobject_class,
132
132
                                         PROP_SIZE,
133
 
                                         g_param_spec_pointer ("size", "Size",
134
 
                                                               "The Input's Size",
135
 
                                                               G_PARAM_READABLE));
 
133
                                         g_param_spec_int64 ("size", "Size",
 
134
                                                             "The Input's Size",
 
135
                                                             0, G_MAXINT64, 0,
 
136
                                                             GSF_PARAM_STATIC |
 
137
                                                             G_PARAM_READABLE));
136
138
        g_object_class_install_property (gobject_class,
137
139
                                         PROP_EOF,
138
 
                                         g_param_spec_pointer ("eof", "OEF",
 
140
                                         g_param_spec_boolean ("eof", "OEF",
139
141
                                                               "End Of File",
 
142
                                                               FALSE,
 
143
                                                               GSF_PARAM_STATIC |
140
144
                                                               G_PARAM_READABLE));
141
145
        g_object_class_install_property (gobject_class,
142
146
                                         PROP_REMAINING,
143
 
                                         g_param_spec_pointer ("remaining", "Remaining",
144
 
                                                               "Amount of Data Remaining",
145
 
                                                               G_PARAM_READABLE));
 
147
                                         g_param_spec_int64 ("remaining", "Remaining",
 
148
                                                             "Amount of Data Remaining",
 
149
                                                             0, G_MAXINT64, 0,
 
150
                                                             GSF_PARAM_STATIC |
 
151
                                                             G_PARAM_READABLE));
146
152
        g_object_class_install_property (gobject_class,
147
153
                                         PROP_POS,
148
 
                                         g_param_spec_pointer ("position", "Position",
149
 
                                                               "The Output's Current Position",
150
 
                                                               G_PARAM_READABLE));
 
154
                                         g_param_spec_int64 ("position", "Position",
 
155
                                                             "The Output's Current Position",
 
156
                                                             0, G_MAXINT64, 0,
 
157
                                                             GSF_PARAM_STATIC |
 
158
                                                             G_PARAM_READABLE));
151
159
}
152
160
 
153
161
GSF_CLASS_ABSTRACT (GsfInput, gsf_input,
156
164
 
157
165
/**
158
166
 * gsf_input_name :
159
 
 * @input : 
160
 
 *
161
 
 * Returns @input's name in utf8 form, DO NOT FREE THIS STRING
 
167
 * @input: the input stream
 
168
 *
 
169
 * The name of the input stream.
 
170
 *
 
171
 * Returns: @input's name in utf8 form, or NULL if it has no name.
162
172
 **/
163
173
char const *
164
174
gsf_input_name (GsfInput *input)
169
179
 
170
180
/**
171
181
 * gsf_input_container :
172
 
 * @input : 
 
182
 * @input: the input stream
173
183
 *
174
184
 * Returns, but does not add a reference to @input's container.
175
185
 * Potentially NULL
183
193
 
184
194
/**
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
188
198
 *
189
199
 * Duplicates input @src leaving the new one at the same offset.
190
200
 *
191
 
 * Returns : the duplicate, or NULL on error
 
201
 * Returns: the duplicate, or NULL on error
192
202
 **/
193
203
GsfInput *
194
204
gsf_input_dup (GsfInput *input, GError **err)
199
209
 
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) {
 
213
                        if (err != NULL)
 
214
                                *err = g_error_new (gsf_input_error_id (), 0,
 
215
                                                    "Duplicate size mismatch");
 
216
                        g_object_unref (dst);
 
217
                        return NULL;
 
218
                }
 
219
                if (gsf_input_seek (dst, input->cur_offset, G_SEEK_SET)) {
 
220
                        if (err != NULL)
 
221
                                *err = g_error_new (gsf_input_error_id (), 0,
 
222
                                                    "Seek failed");
 
223
                        g_object_unref (dst);
 
224
                        return NULL;
 
225
                }
 
226
 
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);
209
232
        }
210
233
        return dst;
211
234
}
212
235
 
213
236
/**
 
237
 * gsf_input_open_sibling :
 
238
 * @input: The input
 
239
 *
 
240
 * UNIMPLEMENTED BY ANY BACKEND
 
241
 *      and it is probably unnecessary.   gsf_input_get_container provides
 
242
 *      enough power to do what is necessary.
 
243
 *
 
244
 * Attempts to open a 'sibling' of @input.  The caller is responsible for
 
245
 * managing the resulting object.
 
246
 *
 
247
 * Returns:  A related #GsfInput or NULL on failure.
 
248
 **/
 
249
GsfInput *
 
250
gsf_input_sibling (GsfInput const *input, char const *name, GError **err)
 
251
{
 
252
        g_return_val_if_fail (GET_CLASS (input)->OpenSibling, NULL);
 
253
 
 
254
        return GET_CLASS (input)->OpenSibling (input, name, err);
 
255
}
 
256
 
 
257
/**
214
258
 * gsf_input_size :
215
 
 * @input : The input
 
259
 * @input: The input
216
260
 *
217
261
 * Looks up and caches the number of bytes in the input
218
262
 *
219
 
 * Returns :  the size or -1 on error
 
263
 * Returns:  the size or -1 on error
220
264
 **/
221
265
gsf_off_t
222
266
gsf_input_size (GsfInput *input)
227
271
 
228
272
/**
229
273
 * gsf_input_eof :
230
 
 * @input : the input
 
274
 * @input: the input
231
275
 *
232
276
 * Are we at the end of the file ?
233
277
 *
234
 
 * Returns : TRUE if the input is at the eof.
 
278
 * Returns: TRUE if the input is at the eof.
235
279
 **/
236
280
gboolean
237
281
gsf_input_eof (GsfInput *input)
243
287
 
244
288
/**
245
289
 * gsf_input_read :
246
 
 * @input :
247
 
 * @num_bytes :
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
249
293
 *
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.
253
297
 *
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
255
299
 *      requested.
256
300
 **/
257
301
guint8 const *
269
313
 
270
314
        input->cur_offset += num_bytes;
271
315
        return res;
272
 
 
273
316
}
274
317
 
275
318
/**
276
319
 * gsf_input_remaining :
277
 
 * @input :
 
320
 * @input: the input stream
278
321
 *
279
 
 * Returns the number of bytes left in the file.
 
322
 * Returns: the number of bytes left in the file.
280
323
 **/
281
324
gsf_off_t
282
325
gsf_input_remaining (GsfInput *input)
288
331
 
289
332
/**
290
333
 * gsf_input_tell :
291
 
 * @input :
 
334
 * @input: the input stream
292
335
 *
293
 
 * Returns the current offset in the file.
 
336
 * Returns: the current offset in the file.
294
337
 **/
295
338
gsf_off_t
296
339
gsf_input_tell (GsfInput *input)
302
345
 
303
346
/**
304
347
 * gsf_input_seek :
305
 
 * @input :
306
 
 * @offset :
307
 
 * @whence :
308
 
 *
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.
 
352
 *
 
353
 * Move the current location in the input stream.
 
354
 *
 
355
 * Returns: TRUE on error.
310
356
 **/
311
357
gboolean
312
358
gsf_input_seek (GsfInput *input, gsf_off_t offset, GSeekType whence)
334
380
 
335
381
        if (GET_CLASS (input)->Seek (input, offset, whence))
336
382
                return TRUE;
 
383
 
337
384
        input->cur_offset = pos;
338
385
        return FALSE;
339
386
}
340
387
 
341
388
/**
342
389
 * gsf_input_set_name :
343
 
 * @input :
344
 
 * @name :
 
390
 * @input: the input stream
 
391
 * @name: the new name of the stream, or NULL.
345
392
 *
346
393
 * protected.
347
394
 *
348
 
 * Returns : TRUE if the assignment was ok.
 
395
 * Returns: TRUE if the assignment was ok.
349
396
 **/
350
397
gboolean
351
398
gsf_input_set_name (GsfInput *input, char const *name)
355
402
        g_return_val_if_fail (input != NULL, FALSE);
356
403
 
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;
361
407
        return TRUE;
362
408
}
363
409
 
364
410
/**
 
411
 * gsf_input_set_name_from_filename :
 
412
 * @input: the input stream
 
413
 * @filename: the (fs-sys encoded) filename
 
414
 *
 
415
 * protected.
 
416
 *
 
417
 * Returns: TRUE if the assignment was ok.
 
418
 **/
 
419
gboolean
 
420
gsf_input_set_name_from_filename (GsfInput *input, char const *filename)
 
421
{
 
422
        g_return_val_if_fail (input != NULL, FALSE);
 
423
 
 
424
        g_free (input->name);
 
425
        input->name = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
 
426
        return TRUE;
 
427
}
 
428
 
 
429
 
 
430
/**
365
431
 * gsf_input_set_container :
366
 
 * @input :
367
 
 * @container :
 
432
 * @input: the input stream
 
433
 * @container:
368
434
 *
369
 
 * Returns : TRUE if the assignment was ok.
 
435
 * Returns: TRUE if the assignment was ok.
370
436
 */
371
437
gboolean
372
438
gsf_input_set_container (GsfInput *input, GsfInfile *container)
383
449
 
384
450
/**
385
451
 * gsf_input_set_size :
386
 
 * @input :
387
 
 * @size :
 
452
 * @input: the input stream
 
453
 * @size: the size of the stream
388
454
 *
389
 
 * Returns : TRUE if the assignment was ok.
 
455
 * Returns: TRUE if the assignment was ok.
390
456
 */
391
457
gboolean
392
458
gsf_input_set_size (GsfInput *input, gsf_off_t size)
393
459
{
394
460
        g_return_val_if_fail (input != NULL, FALSE);
 
461
        g_return_val_if_fail (size >= 0, FALSE);
395
462
 
396
463
        input->size = size;
397
464
        return TRUE;
398
465
}
399
466
 
400
467
/**
401
 
 * gsf_input_seek_emulate: Emulate forward seeks by reading.
402
 
 * @input :
403
 
 * @pos :
404
 
 *
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
 
471
 *
 
472
 * Emulate forward seeks by reading.
 
473
 *
 
474
 * Returns: TRUE if the emulation failed.
406
475
 */
407
476
gboolean
408
477
gsf_input_seek_emulate (GsfInput *input, gsf_off_t pos)
421
490
/****************************************************************************/
422
491
 
423
492
/**
424
 
 * gsf_input_error :
 
493
 * gsf_input_error_id :
425
494
 *
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.
427
496
 */
428
497
GQuark 
429
 
gsf_input_error (void)
 
498
gsf_input_error_id (void)
430
499
{
431
500
        static GQuark quark;
432
501
        if (!quark)
433
 
                quark = g_quark_from_static_string ("gsf_input_error");
 
502
                quark = g_quark_from_static_string ("gsf_input_error_id");
434
503
        return quark;
435
504
}
436
505
 
 
506
/**
 
507
 * gsf_input_error :
 
508
 *
 
509
 * Deprecated as of GSF 1.12.0; use gsf_input_error_id() instead.
 
510
 *
 
511
 * Returns: A utility quark to flag a GError as being an input problem.
 
512
 */
 
513
GQuark 
 
514
gsf_input_error (void)
 
515
{
 
516
        return gsf_input_error_id ();
 
517
}
 
518
 
437
519
/****************************************************************************/
438
520
 
439
521
#define GSF_READ_BUFSIZE (1024 * 4)
440
522
 
441
523
/**
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
445
527
 *
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.
450
532
 *
451
 
 * Returns : TRUE on Success
 
533
 * Returns: TRUE on Success
452
534
 **/
453
535
gboolean
454
536
gsf_input_copy (GsfInput *input, GsfOutput *output)
490
572
        gsf_off_t cur_offset = src->cur_offset;
491
573
        const guint8 *data;
492
574
 
493
 
        if (gsf_input_seek (src, (gsf_off_t) 0, G_SEEK_SET))
 
575
        if (gsf_input_seek (src, 0, G_SEEK_SET))
494
576
                goto error;
495
577
 
496
578
        /* Read header up front, so we avoid extra seeks in tests.  */
503
585
                const unsigned char gzip_sig[2] = { 0x1f, 0x8b };
504
586
 
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);
507
589
                        if (res) {
508
590
                                g_object_unref (G_OBJECT (src));
509
 
                                return gsf_input_uncompress (GSF_INPUT (res));
 
591
                                return gsf_input_uncompress (res);
510
592
                        } 
511
593
                }
512
594
        }
513
595
 
514
 
#ifdef HAVE_BZIP
 
596
#ifdef HAVE_BZ2
515
597
        /* Let's try bzip.  */
516
598
        {
517
 
                const guint8 * bzip_sig = "BZh";
 
599
                guint8 const *bzip_sig = "BZh";
518
600
 
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);
521
603
                        if (res) {
522
604
                                g_object_unref (G_OBJECT (src));
523
 
                                return gsf_input_uncompress (GSF_INPUT (res));
 
605
                                return gsf_input_uncompress (res);
524
606
                        }
525
607
                }
526
608
        }
541
623
#include <gsf-gnome/gsf-input-gnomevfs.h>
542
624
#endif
543
625
 
544
 
GsfInput*
 
626
GsfInput *
545
627
gsf_input_new_for_uri (char const * uri, GError ** err)
546
628
{
547
629
        GsfInput * input = NULL;
554
636
 
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);
558
640
        } else {
559
641
#if HAVE_GNOME
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);
562
644
#else           
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);
566
648
                } 
567
649
                /* else: unknown or unhandled protocol - bail */
568
650
#endif