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