1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * gsf-output-bzip.c: wrapper to compress to bzipped output
5 * Copyright (C) 2003-2006 Dom Lachowicz (cinamod@hotmail.com)
6 * 2002-2006 Jon K Hellan (hellan@acm.org)
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of version 2.1 of the GNU Lesser General Public
10 * License as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
23 #include <gsf-config.h>
25 #include <gsf/gsf-output-bzip.h>
26 #include <gsf/gsf-output-impl.h>
27 #include <gsf/gsf-impl-utils.h>
28 #include <gsf/gsf-utils.h>
31 /* For getting FILE. Don't ask. */
34 #define BZ_BUFSIZE 1024
37 static GObjectClass *parent_class;
39 struct _GsfOutputBzip {
43 GsfOutput *sink; /* compressed data */
51 GsfOutputClass output_class;
55 gsf_output_bzip_finalize (GObject *obj)
58 GsfOutputBzip *bzip = (GsfOutputBzip *)obj;
60 if (bzip->sink != NULL) {
61 g_object_unref (G_OBJECT (bzip->sink));
66 parent_class->finalize (obj);
71 init_bzip (GsfOutputBzip *bzip, GError **err)
75 ret = BZ2_bzCompressInit (&bzip->stream, 6, 0, 0);
79 *err = g_error_new (gsf_output_error_id (), 0,
80 "Unable to initialize BZ2 library");
84 bzip->buf_size = BZ_BUFSIZE;
85 bzip->buf = g_new (guint8, bzip->buf_size);
87 bzip->stream.next_out = bzip->buf;
88 bzip->stream.avail_out = bzip->buf_size;
94 bzip_output_block (GsfOutputBzip *bzip)
96 size_t num_bytes = bzip->buf_size - bzip->stream.avail_out;
98 if (!gsf_output_write (bzip->sink, num_bytes, bzip->buf))
101 bzip->stream.next_out = bzip->buf;
102 bzip->stream.avail_out = bzip->buf_size;
108 bzip_flush (GsfOutputBzip *bzip)
113 zret = BZ2_bzCompress (&bzip->stream, BZ_FINISH);
114 if (zret == BZ_FINISH_OK) {
115 /* In this case BZ_FINISH_OK means more buffer space
117 if (!bzip_output_block (bzip))
120 } while (zret == BZ_FINISH_OK);
121 if (zret != BZ_STREAM_END) {
122 g_warning ("Unexpected error code %d from bzlib during compression.",
126 if (!bzip_output_block (bzip))
134 gsf_output_bzip_write (GsfOutput *output,
135 size_t num_bytes, guint8 const *data)
138 GsfOutputBzip *bzip = GSF_OUTPUT_BZIP (output);
140 g_return_val_if_fail (data, FALSE);
142 bzip->stream.next_in = (unsigned char *) data;
143 bzip->stream.avail_in = num_bytes;
145 while (bzip->stream.avail_in > 0) {
148 if (bzip->stream.avail_out == 0) {
149 if (!bzip_output_block (bzip))
153 zret = BZ2_bzCompress (&bzip->stream, BZ_RUN);
154 if (zret != BZ_RUN_OK) {
155 g_warning ("Unexpected error code %d from bzlib during compression.",
161 if (bzip->stream.avail_out == 0) {
162 if (!bzip_output_block (bzip))
176 gsf_output_bzip_seek (G_GNUC_UNUSED GsfOutput *output,
177 G_GNUC_UNUSED gsf_off_t offset,
178 G_GNUC_UNUSED GSeekType whence)
184 gsf_output_bzip_close (GsfOutput *output)
187 GsfOutputBzip *bzip = GSF_OUTPUT_BZIP (output);
190 rt = bzip_flush (bzip);
191 BZ2_bzCompressEnd (&bzip->stream);
201 gsf_output_bzip_init (GObject *obj)
204 GsfOutputBzip *bzip = GSF_OUTPUT_BZIP (obj);
207 bzip->stream.bzalloc = NULL;
208 bzip->stream.bzfree = NULL;
209 bzip->stream.opaque = NULL;
210 bzip->stream.next_in = NULL;
211 bzip->stream.next_out = NULL;
212 bzip->stream.avail_in = bzip->stream.avail_out = 0;
221 gsf_output_bzip_class_init (GObjectClass *gobject_class)
223 GsfOutputClass *output_class = GSF_OUTPUT_CLASS (gobject_class);
225 gobject_class->finalize = gsf_output_bzip_finalize;
226 output_class->Write = gsf_output_bzip_write;
227 output_class->Seek = gsf_output_bzip_seek;
228 output_class->Close = gsf_output_bzip_close;
230 parent_class = g_type_class_peek_parent (gobject_class);
233 GSF_CLASS (GsfOutputBzip, gsf_output_bzip,
234 gsf_output_bzip_class_init, gsf_output_bzip_init,
238 * gsf_output_bzip_new :
239 * @sink : The underlying data source.
240 * @err : optionally %NULL.
242 * Adds a reference to @sink.
244 * Returns: a new file or %NULL.
247 gsf_output_bzip_new (GsfOutput *sink, GError **err)
252 g_return_val_if_fail (GSF_IS_OUTPUT (sink), NULL);
254 bzip = g_object_new (GSF_OUTPUT_BZIP_TYPE, NULL);
255 if (G_UNLIKELY (NULL == bzip)) return NULL;
257 g_object_ref (G_OBJECT (sink));
260 if (!init_bzip (bzip, err)) {
261 g_object_unref (G_OBJECT (bzip));
265 return GSF_OUTPUT (bzip);
269 *err = g_error_new (gsf_output_error_id (), 0,
270 "BZ2 support not enabled");