"Initial commit to Gerrit"
[profile/ivi/libgsf.git] / gsf / gsf-input-bzip.c
1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * gsf-input-iochannel.c: wrapper for glib's GIOChannel
4  *
5  * Copyright (C) 2003-2006 Dom Lachowicz (cinamod@hotmail.com)
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of version 2.1 of the GNU Lesser General Public
9  * License as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
19  * USA
20  */
21
22 #include <gsf-config.h>
23 #include <gsf-input-bzip.h>
24 #include <gsf-input-memory.h>
25 #include <gsf-output-memory.h>
26 #include <gsf-input-impl.h>
27 #include <string.h>
28
29 #ifdef HAVE_BZ2
30 /* For getting FILE.  Don't ask.  */
31 #include <stdio.h>
32 #include <bzlib.h>
33 #define BZ_BUFSIZ 1024
34 #endif
35
36 /**
37  * gsf_input_memory_new_from_bzip :
38  * @source : a #GsfInput
39  * @err    : a #GError
40  *
41  * Returns: a new #GsfInputMemory or %NULL.
42  */
43 GsfInput * 
44 gsf_input_memory_new_from_bzip (GsfInput *source, GError **err)
45 {
46 #ifndef HAVE_BZ2
47         (void)source;
48         if (err)
49                 *err = g_error_new (gsf_input_error_id (), 0,
50                                     "BZ2 support not enabled");
51         return NULL;
52 #else
53         bz_stream  bzstm;
54         GsfInput  *mem       = NULL;
55         GsfOutput *sink      = NULL;
56         guint8     out_buf [BZ_BUFSIZ];
57         int        bzerr     = BZ_OK;
58
59         g_return_val_if_fail (source != NULL, NULL);
60
61         memset (&bzstm, 0, sizeof (bzstm));
62         if (BZ_OK != BZ2_bzDecompressInit (&bzstm, 0, 0)) {
63                 if (err)
64                         *err = g_error_new (gsf_input_error_id (), 0,
65                                             "BZ2 decompress init failed");
66                 return NULL;
67         }
68
69         sink = gsf_output_memory_new ();
70
71         for (;;) {
72                 bzstm.next_out  = (char *)out_buf;
73                 bzstm.avail_out = (unsigned int)sizeof (out_buf);
74
75                 if (bzstm.avail_in == 0) {
76                         bzstm.avail_in = (unsigned int)MIN (gsf_input_remaining (source), BZ_BUFSIZ);
77                         bzstm.next_in  = (char *)gsf_input_read (source, bzstm.avail_in, NULL);
78                 }
79                 
80                 bzerr = BZ2_bzDecompress (&bzstm);
81                 if (bzerr != BZ_OK && bzerr != BZ_STREAM_END) {
82                         if (err)
83                                 *err = g_error_new (gsf_input_error_id (), 0,
84                                                     "BZ2 decompress failed");
85                         BZ2_bzDecompressEnd (&bzstm);
86                         gsf_output_close (sink);
87                         g_object_unref (G_OBJECT (sink));
88                         return NULL;
89                 }
90                 
91                 gsf_output_write (sink, BZ_BUFSIZ - bzstm.avail_out, out_buf);
92                 if (bzerr == BZ_STREAM_END)
93                         break;
94         }
95
96         gsf_output_close (sink);
97         
98         if (BZ_OK != BZ2_bzDecompressEnd (&bzstm)) {
99                 if (err)
100                         *err = g_error_new (gsf_input_error_id (), 0,
101                                             "BZ2 decompress end failed");
102                 g_object_unref (G_OBJECT (sink));
103                 return NULL;
104         }
105
106         mem = gsf_input_memory_new_clone (
107                 gsf_output_memory_get_bytes (GSF_OUTPUT_MEMORY (sink)), 
108                 gsf_output_size (sink));
109
110         if (mem != NULL)
111                 gsf_input_set_name (mem, gsf_input_name (source));
112
113         g_object_unref (G_OBJECT (sink));
114         return mem;
115 #endif
116 }