fix codetest failure - ASSERT_ARGS does not have a ; after and
[parrot.git] / src / dynpmc / gziphandle.pmc
blobf1a113efa0a99df5c042a38fd9e2d7e8546385a0
1 /*
2 Copyright (C) 2010, Parrot Foundation.
3 $Id$
5 =head1 NAME
7 src/dynpmc/gziphandle.pmc - GzipHandle PMC
9 =head1 DESCRIPTION
11 The GzipHandle PMC performs I/O operations on a source or destination file.
13 This PMC wraps the zlib.
15 =head2 Vtable Functions
17 =over 4
19 =cut
23 #include <zlib.h>
24 #include "parrot/extend.h"
26 /* HEADERIZER HFILE: none */
27 /* HEADERIZER BEGIN: static */
28 /* HEADERIZER END: static */
30 pmclass GzipHandle extends Handle dynpmc auto_attrs {
31     ATTR void *file;
35 =item C<void init()>
37 Initializes a newly created FileHandle object.
39 =cut
42     VTABLE void init() {
43         PARROT_GZIPHANDLE(SELF)->file = NULL;
44     }
48 =item C<INTVAL get_bool()>
50 Returns whether the GzipHandle has reached the end of the file.
52 =cut
55     VTABLE INTVAL get_bool() {
56         gzFile file;
57         GET_ATTR_file(INTERP, SELF, file);
58         return !gzeof(file);
59     }
63 =back
65 =head2 Stream-Oriented Methods
67 =over 4
69 =item C<METHOD open(STRING *filename, STRING *mode :optional)>
71 Opens the file at the given filename (including path) with the given mode. The
72 invocant is modified and becomes an open filehandle.
74 =cut
77     METHOD open(STRING *filename, STRING *mode :optional,
78                                INTVAL has_mode :opt_flag) {
79         char * const path  = Parrot_str_to_cstring(INTERP, filename);
80         gzFile file;
82         if (has_mode) {
83             char * const mod = Parrot_str_to_cstring(INTERP, mode);
84             file      = gzopen(path, mod);
85             Parrot_str_free_cstring(mod);
86         }
87         else
88             file = gzopen(path, "rb");
90         Parrot_str_free_cstring(path);
92         if (!file)
93             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_ILL_INHERIT,
94                 "gzopen fails");
96         SET_ATTR_file(INTERP, SELF, file);
97         RETURN(PMC SELF);
98     }
102 =item C<METHOD close()>
104 Close the gziphandle.
106 =cut
109     METHOD close() {
110         INTVAL status;
111         gzFile file;
112         GET_ATTR_file(INTERP, SELF, file);
113         status = gzclose(file);
114         RETURN(INTVAL status);
115     }
119 =item C<METHOD eof()>
121 Returns true if the filehandle is at end-of-file, returns false otherwise.
123 =cut
126     METHOD eof() {
127         INTVAL status;
128         gzFile file;
129         GET_ATTR_file(INTERP, SELF, file);
130         status = gzeof(file);
131         RETURN(INTVAL status);
132     }
136 =item C<METHOD flush()>
138 Flushes the gziphandle.
140 =cut
143     METHOD flush() {
144         INTVAL status;
145         gzFile file;
146         GET_ATTR_file(INTERP, SELF, file);
147         status = gzflush(file, Z_SYNC_FLUSH);
148         RETURN(INTVAL status);
149     }
153 =item C<METHOD print([INTVAL|FLOATVAL|STRING *|PMC*] value)>
155 Print the passed in integer, number, string, or PMC to the gziphandle.
156 (Integers, numbers, and strings are auto-boxed as PMCs.)
158 =cut
161     METHOD print(PMC *value) {
162         gzFile file;
163         STRING * const str = VTABLE_get_string(INTERP, value);
164         char   * const buf = Parrot_str_to_cstring(INTERP, str);
165         const UINTVAL  len =  Parrot_str_byte_length(INTERP, str);
167         GET_ATTR_file(INTERP, SELF, file);
168         (void)gzwrite(file, buf, len);
169         Parrot_str_free_cstring(buf);
170     }
175 =item C<METHOD puts(STRING *value)>
177 Print the string to the gziphandle.
179 =cut
182     METHOD puts(STRING *value) {
183         INTVAL status;
184         gzFile file;
185         char * const  buf = Parrot_str_to_cstring(INTERP, value);
186         const UINTVAL len =  Parrot_str_byte_length(INTERP, value);
188         GET_ATTR_file(INTERP, SELF, file);
189         status =  gzwrite(file, buf, len);
190         Parrot_str_free_cstring(buf);
191         RETURN(INTVAL status);
192     }
196 =item C<METHOD read(INTVAL bytes)>
198 Read the given number of bytes from the gziphandle and return them in a string.
200 =cut
203     METHOD read(INTVAL length) {
204         int result;
205         gzFile file;
206         STRING *str = STRINGNULL;
207         char * const buf = mem_allocate_n_zeroed_typed(length, char);
208         GET_ATTR_file(INTERP, SELF, file);
209         result = gzread(file, buf, length);
210         if (result > 0) {
211             str = Parrot_str_new(INTERP, buf, result);
212         }
213         mem_sys_free(buf);
214         RETURN(STRING *str);
215     }
219 =back
221 =head2 Basic Methods
223 =over 4
225 =item C<METHOD version()>
227 Returns a string with the zlib version.
229 =back
231 =cut
235     METHOD version() {
236         STRING *version = Parrot_str_new_constant(INTERP, zlibVersion());
237         RETURN(STRING *version);
238     }
240     METHOD compress(STRING *str) {
241         int rc;
242         char *buf;
243         STRING *dst = STRINGNULL;
244         UINTVAL srcLen, dstLen;
245         char * const src = Parrot_str_to_cstring(INTERP, str);
247         if (!src)
248             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_ILL_INHERIT,
249                 "failed to allocate");
251         srcLen = Parrot_str_byte_length(INTERP, str);
252         dstLen = 12 + srcLen + srcLen / 1000;
253         buf    = mem_allocate_n_zeroed_typed(dstLen, char);
255         if (!buf) {
256             Parrot_str_free_cstring(src);
257             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_ILL_INHERIT,
258                 "failed to allocate");
259         }
261         rc = compress((Bytef *)buf, &dstLen, (const Bytef *)src, srcLen);
262         Parrot_str_free_cstring(src);
264         switch (rc) {
265           case Z_OK:
266             dst = Parrot_str_new(INTERP, buf, dstLen);
267             mem_sys_free(buf);
268             break;
270           case Z_MEM_ERROR:
271             mem_sys_free(buf);
272             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_ILL_INHERIT,
273                 "not enough memory");
274             break;
276           case Z_BUF_ERROR:
277             mem_sys_free(buf);
278             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_ILL_INHERIT,
279                 "output buffer error");
280             break;
282           default:
283             /* these are the only three documented return values */
284             break;
285         }
287         RETURN(STRING *dst);
288     }
290     METHOD uncompress(STRING *str) {
291         int rc;
292         char *buf;
293         STRING *dst = STRINGNULL;
294         UINTVAL srcLen, dstLen;
295         char * const src = Parrot_str_to_cstring(INTERP, str);
297         if (!src)
298             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_ILL_INHERIT,
299                 "failed to allocate");
301         srcLen = Parrot_str_byte_length(INTERP, str);
302         dstLen = 2 * srcLen;
303     REDO:
304         buf = mem_allocate_n_zeroed_typed(dstLen, char);
306         if (!buf) {
307             Parrot_str_free_cstring(src);
308             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_ILL_INHERIT,
309                 "failed to allocate");
310         }
312         rc = uncompress((Bytef *)buf, &dstLen, (const Bytef *)src, srcLen);
314         switch (rc) {
315           case Z_OK:
316             Parrot_str_free_cstring(src);
317             dst = Parrot_str_new(INTERP, buf, dstLen);
318             mem_sys_free(buf);
319             break;
321           case Z_MEM_ERROR:
322             Parrot_str_free_cstring(src);
323             mem_sys_free(buf);
324             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_ILL_INHERIT,
325                 "not enough memory");
326             break;
328           case Z_BUF_ERROR:
329             mem_sys_free(buf);
330             dstLen *= 2;
331             goto REDO;
333           case Z_DATA_ERROR:
334             Parrot_str_free_cstring(src);
335             mem_sys_free(buf);
336             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_ILL_INHERIT,
337                 "input data corrupted");
338             break;
340           default:
341             /* these are the only four documented return values */
342             break;
343         }
345         RETURN(STRING *dst);
346     }
348     METHOD crc32(INTVAL crc, STRING *str) {
349         UINTVAL srcLen;
350         char * const src = Parrot_str_to_cstring(INTERP, str);
352         if (!src)
353             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_ILL_INHERIT,
354                 "failed to allocate");
356         srcLen  = Parrot_str_byte_length(INTERP, str);
358         crc = crc32(crc, (const Bytef *)src, srcLen);
359         RETURN(INTVAL crc);
360     }
364  * Local variables:
365  *   c-file-style: "parrot"
366  * End:
367  * vim: expandtab shiftwidth=4:
368  */