IMDb SQLite class: make queries cancellable, using the SQLite3 progress handler
[cinaest] / src / imdb / gzip-input-stream.vala
1 /* This file is part of Cinaest.
2  *
3  * Copyright (C) 2009 Philipp Zabel
4  *
5  * Cinaest is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * Cinaest is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with Cinaest. If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 using GLib;
20 using ZLib;
21
22 class GzipInputStream : FilterInputStream {
23         // 256KB buffer size
24         const int CHUNK = 256*1024;
25
26         InflateStream strm;
27         public uchar[] buf_in;
28
29         public GzipInputStream (GLib.InputStream _base_stream) {
30                 Object (base_stream: _base_stream);
31                 strm = InflateStream.full (15 | 32);
32         }
33
34         construct {
35                 buf_in = new uchar[CHUNK];
36         }
37
38         public async override ssize_t read_async (void *buffer, size_t count, int io_priority, Cancellable? cancellable) throws Error {
39                 int ret = Status.OK;
40                 ssize_t n;
41
42                 if (strm.avail_in == 0) {
43                         n = yield base_stream.read_async (buf_in, CHUNK, io_priority, cancellable);
44                         strm.avail_in = (uint) n;
45                         if (strm.avail_in == 0)
46                                 return -1;
47                         strm.next_in = buf_in;
48                 }
49
50                 strm.avail_out = (int) count;
51                 strm.next_out = buffer;
52
53                 ret = strm.inflate (Flush.NO_FLUSH);
54                 assert (ret != Status.STREAM_ERROR);
55                 if (ret == Status.NEED_DICT)
56                         ret = Status.DATA_ERROR;
57                 switch (ret) {
58                 case Status.DATA_ERROR:
59                 case Status.MEM_ERROR:
60                         throw new IOError.FAILED("Error in gzip stream");
61                 }
62
63                 return (ssize_t) count - strm.avail_out;
64         }
65
66         public override ssize_t read_fn (void *buffer, size_t count, Cancellable? cancellable) throws Error {
67                 int ret = Status.OK;
68
69                 if (strm.avail_in == 0) {
70                         strm.avail_in = (int) base_stream.read (buf_in, CHUNK, cancellable);
71                         if (strm.avail_in == 0)
72                                 return -1;
73                         strm.next_in = buf_in;
74                 }
75
76                 strm.avail_out = (int) count;
77                 strm.next_out = buffer;
78
79                 ret = strm.inflate (Flush.NO_FLUSH);
80                 assert (ret != Status.STREAM_ERROR);
81                 if (ret == Status.NEED_DICT)
82                         ret = Status.DATA_ERROR;
83                 switch (ret) {
84                 case Status.DATA_ERROR:
85                 case Status.MEM_ERROR:
86                         return -1;
87                 }
88
89                 return (ssize_t) count - strm.avail_out;
90         }
91
92         public ulong total_in () {
93                 return strm.total_in;
94         }
95 }