Add GIO gzip input stream class
authorPhilipp Zabel <philipp.zabel@gmail.com>
Thu, 15 Oct 2009 08:27:14 +0000 (10:27 +0200)
committerPhilipp Zabel <philipp.zabel@gmail.com>
Fri, 30 Oct 2009 22:30:17 +0000 (23:30 +0100)
To be used to decompress the downloaded IMDb plaintext database files.

src/imdb/gzip-input-stream.vala [new file with mode: 0644]

diff --git a/src/imdb/gzip-input-stream.vala b/src/imdb/gzip-input-stream.vala
new file mode 100644 (file)
index 0000000..6445fb8
--- /dev/null
@@ -0,0 +1,95 @@
+/* This file is part of Cinaest.
+ *
+ * Copyright (C) 2009 Philipp Zabel
+ *
+ * Cinaest is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Cinaest is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Cinaest. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+using GLib;
+using ZLib;
+
+class GzipInputStream : FilterInputStream {
+       // 256KB buffer size
+       const int CHUNK = 256*1024;
+
+       InflateStream strm;
+       public uchar[] buf_in;
+
+       public GzipInputStream (GLib.InputStream _base_stream) {
+               base_stream = _base_stream;
+               strm = InflateStream.full (15 | 32);
+       }
+
+       construct {
+               buf_in = new uchar[CHUNK];
+       }
+
+       public async override ssize_t read_async (void *buffer, size_t count, int io_priority, Cancellable? cancellable) throws Error {
+               int ret = Status.OK;
+               ssize_t n;
+
+               if (strm.avail_in == 0) {
+                       n = yield base_stream.read_async (buf_in, CHUNK, io_priority, cancellable);
+                       strm.avail_in = (uint) n;
+                       if (strm.avail_in == 0)
+                               return -1;
+                       strm.next_in = buf_in;
+               }
+
+               strm.avail_out = (int) count;
+               strm.next_out = buffer;
+
+               ret = strm.inflate (Flush.NONE);
+               assert (ret != Status.STREAM_ERROR);
+               if (ret == Status.NEED_DICT)
+                       ret = Status.DATA_ERROR;
+               switch (ret) {
+               case Status.DATA_ERROR:
+               case Status.MEM_ERROR:
+                       throw new IOError.FAILED("Error in gzip stream");
+               }
+
+               return (ssize_t) count - strm.avail_out;
+       }
+
+       public override ssize_t read_fn (void *buffer, size_t count, Cancellable? cancellable) throws Error {
+               int ret = Status.OK;
+
+               if (strm.avail_in == 0) {
+                       strm.avail_in = (int) base_stream.read (buf_in, CHUNK, cancellable);
+                       if (strm.avail_in == 0)
+                               return -1;
+                       strm.next_in = buf_in;
+               }
+
+               strm.avail_out = (int) count;
+               strm.next_out = buffer;
+
+               ret = strm.inflate (Flush.NONE);
+               assert (ret != Status.STREAM_ERROR);
+               if (ret == Status.NEED_DICT)
+                       ret = Status.DATA_ERROR;
+               switch (ret) {
+               case Status.DATA_ERROR:
+               case Status.MEM_ERROR:
+                       return -1;
+               }
+
+               return (ssize_t) count - strm.avail_out;
+       }
+
+       public ulong total_in () {
+               return strm.total_in;
+       }
+}