obligatory forgotten android fixup
[pcsx_rearmed.git] / deps / libchdr / deps / zstd-1.5.6 / zlibWrapper / gzwrite.c
1 /* gzwrite.c contains minimal changes required to be compiled with zlibWrapper:
2  * - gz_statep was converted to union to work with -Wstrict-aliasing=1      */
3
4  /* gzwrite.c -- zlib functions for writing gzip files
5  * Copyright (C) 2004-2017 Mark Adler
6  * For conditions of distribution and use, see https://www.zlib.net/zlib_license.html
7  */
8
9 #include <assert.h>
10
11 #include "gzguts.h"
12
13 /* Local functions */
14 local int gz_init _Z_OF((gz_statep));
15 local int gz_comp _Z_OF((gz_statep, int));
16 local int gz_zero _Z_OF((gz_statep, z_off64_t));
17 local z_size_t gz_write _Z_OF((gz_statep, voidpc, z_size_t));
18
19 /* Initialize state for writing a gzip file.  Mark initialization by setting
20    state.state->size to non-zero.  Return -1 on a memory allocation failure, or 0 on
21    success. */
22 local int gz_init(gz_statep state) {
23     int ret;
24     z_streamp strm = &(state.state->strm);
25
26     /* allocate input buffer (double size for gzprintf) */
27     state.state->in = (unsigned char*)malloc(state.state->want << 1);
28     if (state.state->in == NULL) {
29         gz_error(state, Z_MEM_ERROR, "out of memory");
30         return -1;
31     }
32
33     /* only need output buffer and deflate state if compressing */
34     if (!state.state->direct) {
35         /* allocate output buffer */
36         state.state->out = (unsigned char*)malloc(state.state->want);
37         if (state.state->out == NULL) {
38             free(state.state->in);
39             gz_error(state, Z_MEM_ERROR, "out of memory");
40             return -1;
41         }
42
43         /* allocate deflate memory, set up for gzip compression */
44         strm->zalloc = Z_NULL;
45         strm->zfree = Z_NULL;
46         strm->opaque = Z_NULL;
47         ret = deflateInit2(strm, state.state->level, Z_DEFLATED,
48                            MAX_WBITS + 16, DEF_MEM_LEVEL, state.state->strategy);
49         if (ret != Z_OK) {
50             free(state.state->out);
51             free(state.state->in);
52             gz_error(state, Z_MEM_ERROR, "out of memory");
53             return -1;
54         }
55         strm->next_in = NULL;
56     }
57
58     /* mark state as initialized */
59     state.state->size = state.state->want;
60
61     /* initialize write buffer if compressing */
62     if (!state.state->direct) {
63         strm->avail_out = state.state->size;
64         strm->next_out = state.state->out;
65         state.state->x.next = strm->next_out;
66     }
67     return 0;
68 }
69
70 /* Compress whatever is at avail_in and next_in and write to the output file.
71    Return -1 if there is an error writing to the output file or if gz_init()
72    fails to allocate memory, otherwise 0.  flush is assumed to be a valid
73    deflate() flush value.  If flush is Z_FINISH, then the deflate() state is
74    reset to start a new gzip stream.  If gz->direct is true, then simply write
75    to the output file without compressing, and ignore flush. */
76 local int gz_comp(gz_statep state, int flush) {
77     int ret, writ;
78     unsigned have, put, max = ((unsigned)-1 >> 2) + 1;
79     z_streamp strm = &(state.state->strm);
80
81     /* allocate memory if this is the first time through */
82     if (state.state->size == 0 && gz_init(state) == -1)
83         return -1;
84
85     /* write directly if requested */
86     if (state.state->direct) {
87         while (strm->avail_in) {
88             put = strm->avail_in > max ? max : strm->avail_in;
89             writ = (int)write(state.state->fd, strm->next_in, put);
90             if (writ < 0) {
91                 gz_error(state, Z_ERRNO, zstrerror());
92                 return -1;
93             }
94             strm->avail_in -= (unsigned)writ;
95             strm->next_in += writ;
96         }
97         return 0;
98     }
99
100     /* run deflate() on provided input until it produces no more output */
101     ret = Z_OK;
102     do {
103         /* write out current buffer contents if full, or if flushing, but if
104            doing Z_FINISH then don't write until we get to Z_STREAM_END */
105         if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
106             (flush != Z_FINISH || ret == Z_STREAM_END))) {
107             while (strm->next_out > state.state->x.next) {
108                 put = strm->next_out - state.state->x.next > (int)max ? max :
109                       (unsigned)(strm->next_out - state.state->x.next);
110                 writ = (int)write(state.state->fd, state.state->x.next, put);
111                 if (writ < 0) {
112                     gz_error(state, Z_ERRNO, zstrerror());
113                     return -1;
114                 }
115                 state.state->x.next += writ;
116             }
117             if (strm->avail_out == 0) {
118                 strm->avail_out = state.state->size;
119                 strm->next_out = state.state->out;
120                 state.state->x.next = state.state->out;
121             }
122         }
123
124         /* compress */
125         have = strm->avail_out;
126         ret = deflate(strm, flush);
127         if (ret == Z_STREAM_ERROR) {
128             gz_error(state, Z_STREAM_ERROR,
129                       "internal error: deflate stream corrupt");
130             return -1;
131         }
132         have -= strm->avail_out;
133     } while (have);
134
135     /* if that completed a deflate stream, allow another to start */
136     if (flush == Z_FINISH)
137         deflateReset(strm);
138
139     /* all done, no errors */
140     return 0;
141 }
142
143 /* Compress len zeros to output.  Return -1 on a write error or memory
144    allocation failure by gz_comp(), or 0 on success. */
145 local int gz_zero(gz_statep state, z_off64_t len) {
146     int first;
147     unsigned n;
148     z_streamp strm = &(state.state->strm);
149
150     /* consume whatever's left in the input buffer */
151     if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
152         return -1;
153
154     /* compress len zeros (len guaranteed > 0) */
155     first = 1;
156     while (len) {
157         n = GT_OFF(state.state->size) || (z_off64_t)state.state->size > len ?
158             (unsigned)len : state.state->size;
159         if (first) {
160             memset(state.state->in, 0, n);
161             first = 0;
162         }
163         strm->avail_in = n;
164         strm->next_in = state.state->in;
165         state.state->x.pos += n;
166         if (gz_comp(state, Z_NO_FLUSH) == -1)
167             return -1;
168         len -= n;
169     }
170     return 0;
171 }
172
173 /* Write len bytes from buf to file.  Return the number of bytes written.  If
174    the returned value is less than len, then there was an error. */
175 local z_size_t gz_write(gz_statep state, voidpc buf, z_size_t len) {
176     z_size_t put = len;
177
178     /* if len is zero, avoid unnecessary operations */
179     if (len == 0)
180         return 0;
181
182     /* allocate memory if this is the first time through */
183     if (state.state->size == 0 && gz_init(state) == -1)
184         return 0;
185
186     /* check for seek request */
187     if (state.state->seek) {
188         state.state->seek = 0;
189         if (gz_zero(state, state.state->skip) == -1)
190             return 0;
191     }
192
193     /* for small len, copy to input buffer, otherwise compress directly */
194     if (len < state.state->size) {
195         /* copy to input buffer, compress when full */
196         do {
197             z_size_t have, copy;
198
199             if (state.state->strm.avail_in == 0)
200                 state.state->strm.next_in = state.state->in;
201             have = (unsigned)((state.state->strm.next_in + state.state->strm.avail_in) -
202                               state.state->in);
203             copy = state.state->size - have;
204             if (copy > len)
205                 copy = len;
206             memcpy(state.state->in + have, buf, copy);
207             state.state->strm.avail_in += copy;
208             state.state->x.pos += copy;
209             buf = (const char *)buf + copy;
210             len -= copy;
211             if (len && gz_comp(state, Z_NO_FLUSH) == -1)
212                 return 0;
213         } while (len);
214     }
215     else {
216         /* consume whatever's left in the input buffer */
217         if (state.state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
218             return 0;
219
220         /* directly compress user buffer to file */
221         state.state->strm.next_in = (z_const Bytef *)buf;
222         do {
223             z_size_t n = (unsigned)-1;
224             if (n > len)
225                 n = len;
226             state.state->strm.avail_in = (z_uInt)n;
227             state.state->x.pos += n;
228             if (gz_comp(state, Z_NO_FLUSH) == -1)
229                 return 0;
230             len -= n;
231         } while (len);
232     }
233
234     /* input was all buffered or compressed */
235     return put;
236 }
237
238 /* -- see zlib.h -- */
239 int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len) {
240     gz_statep state;
241
242     /* get internal structure */
243     if (file == NULL)
244         return 0;
245     state.file = file;
246
247     /* check that we're writing and that there's no error */
248     if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)
249         return 0;
250
251     /* since an int is returned, make sure len fits in one, otherwise return
252        with an error (this avoids a flaw in the interface) */
253     if ((int)len < 0) {
254         gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
255         return 0;
256     }
257
258     /* write len bytes from buf (the return value will fit in an int) */
259     return (int)gz_write(state, buf, len);
260 }
261
262 /* -- see zlib.h -- */
263 z_size_t ZEXPORT gzfwrite(voidpc buf, z_size_t size, z_size_t nitems,
264                           gzFile file) {
265     z_size_t len;
266     gz_statep state;
267
268     /* get internal structure */
269     assert(size != 0);
270     if (file == NULL)
271         return 0;
272     state.file = file;
273
274     /* check that we're writing and that there's no error */
275     if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)
276         return 0;
277
278     /* compute bytes to read -- error on overflow */
279     len = nitems * size;
280     if (size && (len / size != nitems)) {
281         gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
282         return 0;
283     }
284
285     /* write len bytes to buf, return the number of full items written */
286     return len ? gz_write(state, buf, len) / size : 0;
287 }
288
289 /* -- see zlib.h -- */
290 int ZEXPORT gzputc(gzFile file, int c) {
291     unsigned have;
292     unsigned char buf[1];
293     gz_statep state;
294     z_streamp strm;
295
296     /* get internal structure */
297     if (file == NULL)
298         return -1;
299     state.file = file;
300     strm = &(state.state->strm);
301
302     /* check that we're writing and that there's no error */
303     if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)
304         return -1;
305
306     /* check for seek request */
307     if (state.state->seek) {
308         state.state->seek = 0;
309         if (gz_zero(state, state.state->skip) == -1)
310             return -1;
311     }
312
313     /* try writing to input buffer for speed (state.state->size == 0 if buffer not
314        initialized) */
315     if (state.state->size) {
316         if (strm->avail_in == 0)
317             strm->next_in = state.state->in;
318         have = (unsigned)((strm->next_in + strm->avail_in) - state.state->in);
319         if (have < state.state->size) {
320             state.state->in[have] = (unsigned char)c;
321             strm->avail_in++;
322             state.state->x.pos++;
323             return c & 0xff;
324         }
325     }
326
327     /* no room in buffer or not initialized, use gz_write() */
328     buf[0] = (unsigned char)c;
329     if (gz_write(state, buf, 1) != 1)
330         return -1;
331     return c & 0xff;
332 }
333
334 /* -- see zlib.h -- */
335 int ZEXPORT gzputs(gzFile file, const char *str) {
336     int ret;
337     z_size_t len;
338     gz_statep state;
339
340     /* get internal structure */
341     if (file == NULL)
342         return -1;
343     state.file = file;
344
345     /* check that we're writing and that there's no error */
346     if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)
347         return -1;
348
349     /* write string */
350     len = strlen(str);
351     ret = (int)gz_write(state, str, len);
352     return ret == 0 && len != 0 ? -1 : ret;
353 }
354
355 #if defined(STDC) || defined(Z_HAVE_STDARG_H)
356 #include <stdarg.h>
357
358 /* -- see zlib.h -- */
359 int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) {
360     int len;
361     unsigned left;
362     char *next;
363     gz_statep state;
364     z_streamp strm;
365
366     /* get internal structure */
367     if (file == NULL)
368         return Z_STREAM_ERROR;
369     state.file = file;
370     strm = &(state.state->strm);
371
372     /* check that we're writing and that there's no error */
373     if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)
374         return Z_STREAM_ERROR;
375
376     /* make sure we have some buffer space */
377     if (state.state->size == 0 && gz_init(state) == -1)
378         return state.state->err;
379
380     /* check for seek request */
381     if (state.state->seek) {
382         state.state->seek = 0;
383         if (gz_zero(state, state.state->skip) == -1)
384             return state.state->err;
385     }
386
387     /* do the printf() into the input buffer, put length in len -- the input
388        buffer is double-sized just for this function, so there is guaranteed to
389        be state.state->size bytes available after the current contents */
390     if (strm->avail_in == 0)
391         strm->next_in = state.state->in;
392     next = (char *)(state.state->in + (strm->next_in - state.state->in) + strm->avail_in);
393     next[state.state->size - 1] = 0;
394 #ifdef NO_vsnprintf
395 #  ifdef HAS_vsprintf_void
396     (void)vsprintf(next, format, va);
397     for (len = 0; len < state.state->size; len++)
398         if (next[len] == 0) break;
399 #  else
400     len = vsprintf(next, format, va);
401 #  endif
402 #else
403 #  ifdef HAS_vsnprintf_void
404     (void)vsnprintf(next, state.state->size, format, va);
405     len = strlen(next);
406 #  else
407     len = vsnprintf(next, state.state->size, format, va);
408 #  endif
409 #endif
410
411     /* check that printf() results fit in buffer */
412     if (len == 0 || (unsigned)len >= state.state->size || next[state.state->size - 1] != 0)
413         return 0;
414
415     /* update buffer and position, compress first half if past that */
416     strm->avail_in += (unsigned)len;
417     state.state->x.pos += len;
418     if (strm->avail_in >= state.state->size) {
419         left = strm->avail_in - state.state->size;
420         strm->avail_in = state.state->size;
421         if (gz_comp(state, Z_NO_FLUSH) == -1)
422             return state.state->err;
423         memcpy(state.state->in, state.state->in + state.state->size, left);
424         strm->next_in = state.state->in;
425         strm->avail_in = left;
426     }
427     return len;
428 }
429
430 int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) {
431     va_list va;
432     int ret;
433
434     va_start(va, format);
435     ret = gzvprintf(file, format, va);
436     va_end(va);
437     return ret;
438 }
439
440 #else /* !STDC && !Z_HAVE_STDARG_H */
441
442 /* -- see zlib.h -- */
443 int ZEXPORTVA gzprintf(gzFile file, const char *format, int a1, int a2, int a3,
444                        int a4, int a5, int a6, int a7, int a8, int a9, int a10,
445                        int a11, int a12, int a13, int a14, int a15, int a16,
446                        int a17, int a18, int a19, int a20) {
447     unsigned len, left;
448     char *next;
449     gz_statep state;
450     z_streamp strm;
451
452     /* get internal structure */
453     if (file == NULL)
454         return Z_STREAM_ERROR;
455     state = (gz_statep)file;
456     strm = &(state.state->strm);
457
458     /* check that can really pass pointer in ints */
459     if (sizeof(int) != sizeof(void *))
460         return Z_STREAM_ERROR;
461
462     /* check that we're writing and that there's no error */
463     if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)
464         return Z_STREAM_ERROR;
465
466     /* make sure we have some buffer space */
467     if (state.state->size == 0 && gz_init(state) == -1)
468         return state.state->error;
469
470     /* check for seek request */
471     if (state.state->seek) {
472         state.state->seek = 0;
473         if (gz_zero(state, state.state->skip) == -1)
474             return state.state->error;
475     }
476
477     /* do the printf() into the input buffer, put length in len -- the input
478        buffer is double-sized just for this function, so there is guaranteed to
479        be state.state->size bytes available after the current contents */
480     if (strm->avail_in == 0)
481         strm->next_in = state.state->in;
482     next = (char *)(strm->next_in + strm->avail_in);
483     next[state.state->size - 1] = 0;
484 #ifdef NO_snprintf
485 #  ifdef HAS_sprintf_void
486     sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12,
487             a13, a14, a15, a16, a17, a18, a19, a20);
488     for (len = 0; len < size; len++)
489         if (next[len] == 0)
490             break;
491 #  else
492     len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11,
493                   a12, a13, a14, a15, a16, a17, a18, a19, a20);
494 #  endif
495 #else
496 #  ifdef HAS_snprintf_void
497     snprintf(next, state.state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9,
498              a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
499     len = strlen(next);
500 #  else
501     len = snprintf(next, state.state->size, format, a1, a2, a3, a4, a5, a6, a7, a8,
502                    a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
503 #  endif
504 #endif
505
506     /* check that printf() results fit in buffer */
507     if (len == 0 || len >= state.state->size || next[state.state->size - 1] != 0)
508         return 0;
509
510     /* update buffer and position, compress first half if past that */
511     strm->avail_in += len;
512     state.state->x.pos += len;
513     if (strm->avail_in >= state.state->size) {
514         left = strm->avail_in - state.state->size;
515         strm->avail_in = state.state->size;
516         if (gz_comp(state, Z_NO_FLUSH) == -1)
517             return state.state->err;
518         memcpy(state.state->in, state.state->in + state.state->size, left);
519         strm->next_in = state.state->in;
520         strm->avail_in = left;
521     }
522     return (int)len;
523 }
524
525 #endif
526
527 /* -- see zlib.h -- */
528 int ZEXPORT gzflush(gzFile file, int flush) {
529     gz_statep state;
530
531     /* get internal structure */
532     if (file == NULL)
533         return Z_STREAM_ERROR;
534     state.file = file;
535
536     /* check that we're writing and that there's no error */
537     if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)
538         return Z_STREAM_ERROR;
539
540     /* check flush parameter */
541     if (flush < 0 || flush > Z_FINISH)
542         return Z_STREAM_ERROR;
543
544     /* check for seek request */
545     if (state.state->seek) {
546         state.state->seek = 0;
547         if (gz_zero(state, state.state->skip) == -1)
548             return state.state->err;
549     }
550
551     /* compress remaining data with requested flush */
552     (void)gz_comp(state, flush);
553     return state.state->err;
554 }
555
556 /* -- see zlib.h -- */
557 int ZEXPORT gzsetparams(gzFile file, int level, int strategy) {
558     gz_statep state;
559     z_streamp strm;
560
561     /* get internal structure */
562     if (file == NULL)
563         return Z_STREAM_ERROR;
564     state.file = file;
565     strm = &(state.state->strm);
566
567     /* check that we're writing and that there's no error */
568     if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)
569         return Z_STREAM_ERROR;
570
571     /* if no change is requested, then do nothing */
572     if (level == state.state->level && strategy == state.state->strategy)
573         return Z_OK;
574
575     /* check for seek request */
576     if (state.state->seek) {
577         state.state->seek = 0;
578         if (gz_zero(state, state.state->skip) == -1)
579             return state.state->err;
580     }
581
582     /* change compression parameters for subsequent input */
583     if (state.state->size) {
584         /* flush previous input with previous parameters before changing */
585         if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1)
586             return state.state->err;
587         deflateParams(strm, level, strategy);
588     }
589     state.state->level = level;
590     state.state->strategy = strategy;
591     return Z_OK;
592 }
593
594 /* -- see zlib.h -- */
595 int ZEXPORT gzclose_w(gzFile file) {
596     int ret = Z_OK;
597     gz_statep state;
598
599     /* get internal structure */
600     if (file == NULL)
601         return Z_STREAM_ERROR;
602     state.file = file;
603
604     /* check that we're writing */
605     if (state.state->mode != GZ_WRITE)
606         return Z_STREAM_ERROR;
607
608     /* check for seek request */
609     if (state.state->seek) {
610         state.state->seek = 0;
611         if (gz_zero(state, state.state->skip) == -1)
612             ret = state.state->err;
613     }
614
615     /* flush, free memory, and close file */
616     if (gz_comp(state, Z_FINISH) == -1)
617         ret = state.state->err;
618     if (state.state->size) {
619         if (!state.state->direct) {
620             (void)deflateEnd(&(state.state->strm));
621             free(state.state->out);
622         }
623         free(state.state->in);
624     }
625     gz_error(state, Z_OK, NULL);
626     free(state.state->path);
627     if (close(state.state->fd) == -1)
628         ret = Z_ERRNO;
629     free(state.state);
630     return ret;
631 }