1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * soup-coding-gzip.c: "gzip" coding
5 * Copyright (C) 2005 Novell, Inc.
6 * Copyright (C) 2008 Red Hat, Inc.
13 #include "soup-coding-gzip.h"
20 } SoupCodingGzipPrivate;
21 #define SOUP_CODING_GZIP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_CODING_GZIP, SoupCodingGzipPrivate))
23 G_DEFINE_TYPE (SoupCodingGzip, soup_coding_gzip, SOUP_TYPE_CODING)
25 static void constructed (GObject *object);
26 static void finalize (GObject *object);
27 static SoupCodingStatus apply_into (SoupCoding *coding,
28 gconstpointer input, gsize input_length,
30 gpointer output, gsize output_length,
32 gboolean done, GError **error);
35 soup_coding_gzip_init (SoupCodingGzip *gzip)
37 SoupCodingGzipPrivate *priv = SOUP_CODING_GZIP_GET_PRIVATE (gzip);
39 priv->stream.zalloc = Z_NULL;
40 priv->stream.zfree = Z_NULL;
41 priv->stream.opaque = Z_NULL;
45 soup_coding_gzip_class_init (SoupCodingGzipClass *gzip_class)
47 GObjectClass *object_class = G_OBJECT_CLASS (gzip_class);
48 SoupCodingClass *coding_class = SOUP_CODING_CLASS (gzip_class);
50 g_type_class_add_private (gzip_class, sizeof (SoupCodingGzipPrivate));
52 coding_class->name = "gzip";
54 object_class->constructed = constructed;
55 object_class->finalize = finalize;
57 coding_class->apply_into = apply_into;
61 constructed (GObject *object)
63 SoupCodingGzipPrivate *priv = SOUP_CODING_GZIP_GET_PRIVATE (object);
65 /* All of these values are the defaults according to the zlib
66 * documentation. "16" is a magic number that means gzip
69 if (SOUP_CODING (object)->direction == SOUP_CODING_ENCODE) {
70 deflateInit2 (&priv->stream, Z_DEFAULT_COMPRESSION,
71 Z_DEFLATED, MAX_WBITS | 16, 8,
74 inflateInit2 (&priv->stream, MAX_WBITS | 16);
78 finalize (GObject *object)
80 SoupCodingGzipPrivate *priv = SOUP_CODING_GZIP_GET_PRIVATE (object);
82 if (SOUP_CODING (object)->direction == SOUP_CODING_ENCODE)
83 deflateEnd (&priv->stream);
85 inflateEnd (&priv->stream);
87 G_OBJECT_CLASS (soup_coding_gzip_parent_class)->finalize (object);
90 static SoupCodingStatus
91 apply_into (SoupCoding *coding,
92 gconstpointer input, gsize input_length, gsize *input_used,
93 gpointer output, gsize output_length, gsize *output_used,
94 gboolean done, GError **error)
96 SoupCodingGzipPrivate *priv = SOUP_CODING_GZIP_GET_PRIVATE (coding);
99 priv->stream.avail_in = input_length;
100 priv->stream.next_in = (gpointer)input;
101 priv->stream.total_in = 0;
103 priv->stream.avail_out = output_length;
104 priv->stream.next_out = output;
105 priv->stream.total_out = 0;
107 if (coding->direction == SOUP_CODING_ENCODE)
108 ret = deflate (&priv->stream, done ? Z_FINISH : Z_NO_FLUSH);
110 ret = inflate (&priv->stream, Z_SYNC_FLUSH);
112 *input_used = priv->stream.total_in;
113 *output_used = priv->stream.total_out;
119 g_set_error_literal (error, SOUP_CODING_ERROR,
120 SOUP_CODING_ERROR_DATA_ERROR,
121 priv->stream.msg ? priv->stream.msg : "Bad data");
122 return SOUP_CODING_STATUS_ERROR;
126 g_set_error_literal (error, SOUP_CODING_ERROR,
127 SOUP_CODING_ERROR_INTERNAL_ERROR,
128 priv->stream.msg ? priv->stream.msg : "Internal error");
129 return SOUP_CODING_STATUS_ERROR;
132 /* Discard any trailing junk, for compatibility with
133 * other browsers. FIXME: this really belongs in
134 * soup-message-io, but it's not possible to do there
135 * with the current API.
137 *input_used = input_length;
138 return SOUP_CODING_STATUS_COMPLETE;
142 if (*output_used == output_length &&
143 *input_used < input_length)
144 return SOUP_CODING_STATUS_NEED_SPACE;
146 return SOUP_CODING_STATUS_OK;