ecere/gui/Window: Prevent uninitialized values if base Window methods not overridden...
[sdk] / deps / zlib-1.2.8 / gzread.c
1 /* gzread.c -- zlib functions for reading gzip files
2  * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler
3  * For conditions of distribution and use, see copyright notice in zlib.h
4  */
5
6 #include <unistd.h>
7
8 #include "gzguts.h"
9
10 /* Local functions */
11 local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *));
12 local int gz_avail OF((gz_statep));
13 local int gz_look OF((gz_statep));
14 local int gz_decomp OF((gz_statep));
15 local int gz_fetch OF((gz_statep));
16 local int gz_skip OF((gz_statep, z_off64_t));
17
18 /* Use read() to load a buffer -- return -1 on error, otherwise 0.  Read from
19    state->fd, and update state->eof, state->err, and state->msg as appropriate.
20    This function needs to loop on read(), since read() is not guaranteed to
21    read the number of bytes requested, depending on the type of descriptor. */
22 local int gz_load(state, buf, len, have)
23     gz_statep state;
24     unsigned char *buf;
25     unsigned len;
26     unsigned *have;
27 {
28     int ret;
29
30     *have = 0;
31     do {
32         ret = read(state->fd, buf + *have, len - *have);
33         if (ret <= 0)
34             break;
35         *have += ret;
36     } while (*have < len);
37     if (ret < 0) {
38         gz_error(state, Z_ERRNO, zstrerror());
39         return -1;
40     }
41     if (ret == 0)
42         state->eof = 1;
43     return 0;
44 }
45
46 /* Load up input buffer and set eof flag if last data loaded -- return -1 on
47    error, 0 otherwise.  Note that the eof flag is set when the end of the input
48    file is reached, even though there may be unused data in the buffer.  Once
49    that data has been used, no more attempts will be made to read the file.
50    If strm->avail_in != 0, then the current data is moved to the beginning of
51    the input buffer, and then the remainder of the buffer is loaded with the
52    available data from the input file. */
53 local int gz_avail(state)
54     gz_statep state;
55 {
56     unsigned got;
57     z_streamp strm = &(state->strm);
58
59     if (state->err != Z_OK && state->err != Z_BUF_ERROR)
60         return -1;
61     if (state->eof == 0) {
62         if (strm->avail_in) {       /* copy what's there to the start */
63             unsigned char *p = state->in;
64             unsigned const char *q = strm->next_in;
65             unsigned n = strm->avail_in;
66             do {
67                 *p++ = *q++;
68             } while (--n);
69         }
70         if (gz_load(state, state->in + strm->avail_in,
71                     state->size - strm->avail_in, &got) == -1)
72             return -1;
73         strm->avail_in += got;
74         strm->next_in = state->in;
75     }
76     return 0;
77 }
78
79 /* Look for gzip header, set up for inflate or copy.  state->x.have must be 0.
80    If this is the first time in, allocate required memory.  state->how will be
81    left unchanged if there is no more input data available, will be set to COPY
82    if there is no gzip header and direct copying will be performed, or it will
83    be set to GZIP for decompression.  If direct copying, then leftover input
84    data from the input buffer will be copied to the output buffer.  In that
85    case, all further file reads will be directly to either the output buffer or
86    a user buffer.  If decompressing, the inflate state will be initialized.
87    gz_look() will return 0 on success or -1 on failure. */
88 local int gz_look(state)
89     gz_statep state;
90 {
91     z_streamp strm = &(state->strm);
92
93     /* allocate read buffers and inflate memory */
94     if (state->size == 0) {
95         /* allocate buffers */
96         state->in = (unsigned char *)malloc(state->want);
97         state->out = (unsigned char *)malloc(state->want << 1);
98         if (state->in == NULL || state->out == NULL) {
99             if (state->out != NULL)
100                 free(state->out);
101             if (state->in != NULL)
102                 free(state->in);
103             gz_error(state, Z_MEM_ERROR, "out of memory");
104             return -1;
105         }
106         state->size = state->want;
107
108         /* allocate inflate memory */
109         state->strm.zalloc = Z_NULL;
110         state->strm.zfree = Z_NULL;
111         state->strm.opaque = Z_NULL;
112         state->strm.avail_in = 0;
113         state->strm.next_in = Z_NULL;
114         if (inflateInit2(&(state->strm), 15 + 16) != Z_OK) {    /* gunzip */
115             free(state->out);
116             free(state->in);
117             state->size = 0;
118             gz_error(state, Z_MEM_ERROR, "out of memory");
119             return -1;
120         }
121     }
122
123     /* get at least the magic bytes in the input buffer */
124     if (strm->avail_in < 2) {
125         if (gz_avail(state) == -1)
126             return -1;
127         if (strm->avail_in == 0)
128             return 0;
129     }
130
131     /* look for gzip magic bytes -- if there, do gzip decoding (note: there is
132        a logical dilemma here when considering the case of a partially written
133        gzip file, to wit, if a single 31 byte is written, then we cannot tell
134        whether this is a single-byte file, or just a partially written gzip
135        file -- for here we assume that if a gzip file is being written, then
136        the header will be written in a single operation, so that reading a
137        single byte is sufficient indication that it is not a gzip file) */
138     if (strm->avail_in > 1 &&
139             strm->next_in[0] == 31 && strm->next_in[1] == 139) {
140         inflateReset(strm);
141         state->how = GZIP;
142         state->direct = 0;
143         return 0;
144     }
145
146     /* no gzip header -- if we were decoding gzip before, then this is trailing
147        garbage.  Ignore the trailing garbage and finish. */
148     if (state->direct == 0) {
149         strm->avail_in = 0;
150         state->eof = 1;
151         state->x.have = 0;
152         return 0;
153     }
154
155     /* doing raw i/o, copy any leftover input to output -- this assumes that
156        the output buffer is larger than the input buffer, which also assures
157        space for gzungetc() */
158     state->x.next = state->out;
159     if (strm->avail_in) {
160         memcpy(state->x.next, strm->next_in, strm->avail_in);
161         state->x.have = strm->avail_in;
162         strm->avail_in = 0;
163     }
164     state->how = COPY;
165     state->direct = 1;
166     return 0;
167 }
168
169 /* Decompress from input to the provided next_out and avail_out in the state.
170    On return, state->x.have and state->x.next point to the just decompressed
171    data.  If the gzip stream completes, state->how is reset to LOOK to look for
172    the next gzip stream or raw data, once state->x.have is depleted.  Returns 0
173    on success, -1 on failure. */
174 local int gz_decomp(state)
175     gz_statep state;
176 {
177     int ret = Z_OK;
178     unsigned had;
179     z_streamp strm = &(state->strm);
180
181     /* fill output buffer up to end of deflate stream */
182     had = strm->avail_out;
183     do {
184         /* get more input for inflate() */
185         if (strm->avail_in == 0 && gz_avail(state) == -1)
186             return -1;
187         if (strm->avail_in == 0) {
188             gz_error(state, Z_BUF_ERROR, "unexpected end of file");
189             break;
190         }
191
192         /* decompress and handle errors */
193         ret = inflate(strm, Z_NO_FLUSH);
194         if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) {
195             gz_error(state, Z_STREAM_ERROR,
196                      "internal error: inflate stream corrupt");
197             return -1;
198         }
199         if (ret == Z_MEM_ERROR) {
200             gz_error(state, Z_MEM_ERROR, "out of memory");
201             return -1;
202         }
203         if (ret == Z_DATA_ERROR) {              /* deflate stream invalid */
204             gz_error(state, Z_DATA_ERROR,
205                      strm->msg == NULL ? "compressed data error" : strm->msg);
206             return -1;
207         }
208     } while (strm->avail_out && ret != Z_STREAM_END);
209
210     /* update available output */
211     state->x.have = had - strm->avail_out;
212     state->x.next = strm->next_out - state->x.have;
213
214     /* if the gzip stream completed successfully, look for another */
215     if (ret == Z_STREAM_END)
216         state->how = LOOK;
217
218     /* good decompression */
219     return 0;
220 }
221
222 /* Fetch data and put it in the output buffer.  Assumes state->x.have is 0.
223    Data is either copied from the input file or decompressed from the input
224    file depending on state->how.  If state->how is LOOK, then a gzip header is
225    looked for to determine whether to copy or decompress.  Returns -1 on error,
226    otherwise 0.  gz_fetch() will leave state->how as COPY or GZIP unless the
227    end of the input file has been reached and all data has been processed.  */
228 local int gz_fetch(state)
229     gz_statep state;
230 {
231     z_streamp strm = &(state->strm);
232
233     do {
234         switch(state->how) {
235         case LOOK:      /* -> LOOK, COPY (only if never GZIP), or GZIP */
236             if (gz_look(state) == -1)
237                 return -1;
238             if (state->how == LOOK)
239                 return 0;
240             break;
241         case COPY:      /* -> COPY */
242             if (gz_load(state, state->out, state->size << 1, &(state->x.have))
243                     == -1)
244                 return -1;
245             state->x.next = state->out;
246             return 0;
247         case GZIP:      /* -> GZIP or LOOK (if end of gzip stream) */
248             strm->avail_out = state->size << 1;
249             strm->next_out = state->out;
250             if (gz_decomp(state) == -1)
251                 return -1;
252         }
253     } while (state->x.have == 0 && (!state->eof || strm->avail_in));
254     return 0;
255 }
256
257 /* Skip len uncompressed bytes of output.  Return -1 on error, 0 on success. */
258 local int gz_skip(state, len)
259     gz_statep state;
260     z_off64_t len;
261 {
262     unsigned n;
263
264     /* skip over len bytes or reach end-of-file, whichever comes first */
265     while (len)
266         /* skip over whatever is in output buffer */
267         if (state->x.have) {
268             n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ?
269                 (unsigned)len : state->x.have;
270             state->x.have -= n;
271             state->x.next += n;
272             state->x.pos += n;
273             len -= n;
274         }
275
276         /* output buffer empty -- return if we're at the end of the input */
277         else if (state->eof && state->strm.avail_in == 0)
278             break;
279
280         /* need more data to skip -- load up output buffer */
281         else {
282             /* get more output, looking for header if required */
283             if (gz_fetch(state) == -1)
284                 return -1;
285         }
286     return 0;
287 }
288
289 /* -- see zlib.h -- */
290 int ZEXPORT gzread(file, buf, len)
291     gzFile file;
292     voidp buf;
293     unsigned len;
294 {
295     unsigned got, n;
296     gz_statep state;
297     z_streamp strm;
298
299     /* get internal structure */
300     if (file == NULL)
301         return -1;
302     state = (gz_statep)file;
303     strm = &(state->strm);
304
305     /* check that we're reading and that there's no (serious) error */
306     if (state->mode != GZ_READ ||
307             (state->err != Z_OK && state->err != Z_BUF_ERROR))
308         return -1;
309
310     /* since an int is returned, make sure len fits in one, otherwise return
311        with an error (this avoids the flaw in the interface) */
312     if ((int)len < 0) {
313         gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
314         return -1;
315     }
316
317     /* if len is zero, avoid unnecessary operations */
318     if (len == 0)
319         return 0;
320
321     /* process a skip request */
322     if (state->seek) {
323         state->seek = 0;
324         if (gz_skip(state, state->skip) == -1)
325             return -1;
326     }
327
328     /* get len bytes to buf, or less than len if at the end */
329     got = 0;
330     do {
331         /* first just try copying data from the output buffer */
332         if (state->x.have) {
333             n = state->x.have > len ? len : state->x.have;
334             memcpy(buf, state->x.next, n);
335             state->x.next += n;
336             state->x.have -= n;
337         }
338
339         /* output buffer empty -- return if we're at the end of the input */
340         else if (state->eof && strm->avail_in == 0) {
341             state->past = 1;        /* tried to read past end */
342             break;
343         }
344
345         /* need output data -- for small len or new stream load up our output
346            buffer */
347         else if (state->how == LOOK || len < (state->size << 1)) {
348             /* get more output, looking for header if required */
349             if (gz_fetch(state) == -1)
350                 return -1;
351             continue;       /* no progress yet -- go back to copy above */
352             /* the copy above assures that we will leave with space in the
353                output buffer, allowing at least one gzungetc() to succeed */
354         }
355
356         /* large len -- read directly into user buffer */
357         else if (state->how == COPY) {      /* read directly */
358             if (gz_load(state, (unsigned char *)buf, len, &n) == -1)
359                 return -1;
360         }
361
362         /* large len -- decompress directly into user buffer */
363         else {  /* state->how == GZIP */
364             strm->avail_out = len;
365             strm->next_out = (unsigned char *)buf;
366             if (gz_decomp(state) == -1)
367                 return -1;
368             n = state->x.have;
369             state->x.have = 0;
370         }
371
372         /* update progress */
373         len -= n;
374         buf = (char *)buf + n;
375         got += n;
376         state->x.pos += n;
377     } while (len);
378
379     /* return number of bytes read into user buffer (will fit in int) */
380     return (int)got;
381 }
382
383 /* -- see zlib.h -- */
384 #ifdef Z_PREFIX_SET
385 #  undef z_gzgetc
386 #else
387 #  undef gzgetc
388 #endif
389 int ZEXPORT gzgetc(file)
390     gzFile file;
391 {
392     int ret;
393     unsigned char buf[1];
394     gz_statep state;
395
396     /* get internal structure */
397     if (file == NULL)
398         return -1;
399     state = (gz_statep)file;
400
401     /* check that we're reading and that there's no (serious) error */
402     if (state->mode != GZ_READ ||
403         (state->err != Z_OK && state->err != Z_BUF_ERROR))
404         return -1;
405
406     /* try output buffer (no need to check for skip request) */
407     if (state->x.have) {
408         state->x.have--;
409         state->x.pos++;
410         return *(state->x.next)++;
411     }
412
413     /* nothing there -- try gzread() */
414     ret = gzread(file, buf, 1);
415     return ret < 1 ? -1 : buf[0];
416 }
417
418 int ZEXPORT gzgetc_(file)
419 gzFile file;
420 {
421     return gzgetc(file);
422 }
423
424 /* -- see zlib.h -- */
425 int ZEXPORT gzungetc(c, file)
426     int c;
427     gzFile file;
428 {
429     gz_statep state;
430
431     /* get internal structure */
432     if (file == NULL)
433         return -1;
434     state = (gz_statep)file;
435
436     /* check that we're reading and that there's no (serious) error */
437     if (state->mode != GZ_READ ||
438         (state->err != Z_OK && state->err != Z_BUF_ERROR))
439         return -1;
440
441     /* process a skip request */
442     if (state->seek) {
443         state->seek = 0;
444         if (gz_skip(state, state->skip) == -1)
445             return -1;
446     }
447
448     /* can't push EOF */
449     if (c < 0)
450         return -1;
451
452     /* if output buffer empty, put byte at end (allows more pushing) */
453     if (state->x.have == 0) {
454         state->x.have = 1;
455         state->x.next = state->out + (state->size << 1) - 1;
456         state->x.next[0] = c;
457         state->x.pos--;
458         state->past = 0;
459         return c;
460     }
461
462     /* if no room, give up (must have already done a gzungetc()) */
463     if (state->x.have == (state->size << 1)) {
464         gz_error(state, Z_DATA_ERROR, "out of room to push characters");
465         return -1;
466     }
467
468     /* slide output data if needed and insert byte before existing data */
469     if (state->x.next == state->out) {
470         unsigned char *src = state->out + state->x.have;
471         unsigned char *dest = state->out + (state->size << 1);
472         while (src > state->out)
473             *--dest = *--src;
474         state->x.next = dest;
475     }
476     state->x.have++;
477     state->x.next--;
478     state->x.next[0] = c;
479     state->x.pos--;
480     state->past = 0;
481     return c;
482 }
483
484 /* -- see zlib.h -- */
485 char * ZEXPORT gzgets(file, buf, len)
486     gzFile file;
487     char *buf;
488     int len;
489 {
490     unsigned left, n;
491     char *str;
492     unsigned char *eol;
493     gz_statep state;
494
495     /* check parameters and get internal structure */
496     if (file == NULL || buf == NULL || len < 1)
497         return NULL;
498     state = (gz_statep)file;
499
500     /* check that we're reading and that there's no (serious) error */
501     if (state->mode != GZ_READ ||
502         (state->err != Z_OK && state->err != Z_BUF_ERROR))
503         return NULL;
504
505     /* process a skip request */
506     if (state->seek) {
507         state->seek = 0;
508         if (gz_skip(state, state->skip) == -1)
509             return NULL;
510     }
511
512     /* copy output bytes up to new line or len - 1, whichever comes first --
513        append a terminating zero to the string (we don't check for a zero in
514        the contents, let the user worry about that) */
515     str = buf;
516     left = (unsigned)len - 1;
517     if (left) do {
518         /* assure that something is in the output buffer */
519         if (state->x.have == 0 && gz_fetch(state) == -1)
520             return NULL;                /* error */
521         if (state->x.have == 0) {       /* end of file */
522             state->past = 1;            /* read past end */
523             break;                      /* return what we have */
524         }
525
526         /* look for end-of-line in current output buffer */
527         n = state->x.have > left ? left : state->x.have;
528         eol = (unsigned char *)memchr(state->x.next, '\n', n);
529         if (eol != NULL)
530             n = (unsigned)(eol - state->x.next) + 1;
531
532         /* copy through end-of-line, or remainder if not found */
533         memcpy(buf, state->x.next, n);
534         state->x.have -= n;
535         state->x.next += n;
536         state->x.pos += n;
537         left -= n;
538         buf += n;
539     } while (left && eol == NULL);
540
541     /* return terminated string, or if nothing, end of file */
542     if (buf == str)
543         return NULL;
544     buf[0] = 0;
545     return str;
546 }
547
548 /* -- see zlib.h -- */
549 int ZEXPORT gzdirect(file)
550     gzFile file;
551 {
552     gz_statep state;
553
554     /* get internal structure */
555     if (file == NULL)
556         return 0;
557     state = (gz_statep)file;
558
559     /* if the state is not known, but we can find out, then do so (this is
560        mainly for right after a gzopen() or gzdopen()) */
561     if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0)
562         (void)gz_look(state);
563
564     /* return 1 if transparent, 0 if processing a gzip stream */
565     return state->direct;
566 }
567
568 /* -- see zlib.h -- */
569 int ZEXPORT gzclose_r(file)
570     gzFile file;
571 {
572     int ret, err;
573     gz_statep state;
574
575     /* get internal structure */
576     if (file == NULL)
577         return Z_STREAM_ERROR;
578     state = (gz_statep)file;
579
580     /* check that we're reading */
581     if (state->mode != GZ_READ)
582         return Z_STREAM_ERROR;
583
584     /* free memory and close file */
585     if (state->size) {
586         inflateEnd(&(state->strm));
587         free(state->out);
588         free(state->in);
589     }
590     err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK;
591     gz_error(state, Z_OK, NULL);
592     free(state->path);
593     ret = close(state->fd);
594     free(state);
595     return ret ? Z_ERRNO : err;
596 }