1 /*
2 Copyright (c) 2014 - 2019, Syoyo Fujita and many contributors.
3 All rights reserved.
4 
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7     * Redistributions of source code must retain the above copyright
8       notice, this list of conditions and the following disclaimer.
9     * Redistributions in binary form must reproduce the above copyright
10       notice, this list of conditions and the following disclaimer in the
11       documentation and/or other materials provided with the distribution.
12     * Neither the name of the Syoyo Fujita nor the
13       names of its contributors may be used to endorse or promote products
14       derived from this software without specific prior written permission.
15 
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
20 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 
28 // TinyEXR contains some OpenEXR code, which is licensed under ------------
29 
30 ///////////////////////////////////////////////////////////////////////////
31 //
32 // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
33 // Digital Ltd. LLC
34 //
35 // All rights reserved.
36 //
37 // Redistribution and use in source and binary forms, with or without
38 // modification, are permitted provided that the following conditions are
39 // met:
40 // *       Redistributions of source code must retain the above copyright
41 // notice, this list of conditions and the following disclaimer.
42 // *       Redistributions in binary form must reproduce the above
43 // copyright notice, this list of conditions and the following disclaimer
44 // in the documentation and/or other materials provided with the
45 // distribution.
46 // *       Neither the name of Industrial Light & Magic nor the names of
47 // its contributors may be used to endorse or promote products derived
48 // from this software without specific prior written permission.
49 //
50 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
51 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
52 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
53 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
54 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
56 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
57 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
58 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
59 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
60 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61 //
62 ///////////////////////////////////////////////////////////////////////////
63 
64 // End of OpenEXR license -------------------------------------------------
65 
66 #ifndef TINYEXR_H_
67 #define TINYEXR_H_
68 
69 //
70 //
71 //   Do this:
72 //    #define TINYEXR_IMPLEMENTATION
73 //   before you include this file in *one* C or C++ file to create the
74 //   implementation.
75 //
76 //   // i.e. it should look like this:
77 //   #include ...
78 //   #include ...
79 //   #include ...
80 //   #define TINYEXR_IMPLEMENTATION
81 //   #include "tinyexr.h"
82 //
83 //
84 
85 #include <stddef.h>  // for size_t
86 #include <stdint.h>  // guess stdint.h is available(C99)
87 
88 #ifdef __cplusplus
89 extern "C" {
90 #endif
91 
92 // Use embedded miniz or not to decode ZIP format pixel. Linking with zlib
93 // required if this flas is 0.
94 #ifndef TINYEXR_USE_MINIZ
95 #define TINYEXR_USE_MINIZ (1)
96 #endif
97 
98 // Disable PIZ comporession when applying cpplint.
99 #ifndef TINYEXR_USE_PIZ
100 #define TINYEXR_USE_PIZ (1)
101 #endif
102 
103 #ifndef TINYEXR_USE_ZFP
104 #define TINYEXR_USE_ZFP (0)  // TinyEXR extension.
105 // http://computation.llnl.gov/projects/floating-point-compression
106 #endif
107 
108 #ifndef TINYEXR_USE_THREAD
109 #define TINYEXR_USE_THREAD (0)  // No threaded loading.
110 // http://computation.llnl.gov/projects/floating-point-compression
111 #endif
112 
113 #ifndef TINYEXR_USE_OPENMP
114 #ifdef _OPENMP
115 #define TINYEXR_USE_OPENMP (1)
116 #else
117 #define TINYEXR_USE_OPENMP (0)
118 #endif
119 #endif
120 
121 #define TINYEXR_SUCCESS (0)
122 #define TINYEXR_ERROR_INVALID_MAGIC_NUMBER (-1)
123 #define TINYEXR_ERROR_INVALID_EXR_VERSION (-2)
124 #define TINYEXR_ERROR_INVALID_ARGUMENT (-3)
125 #define TINYEXR_ERROR_INVALID_DATA (-4)
126 #define TINYEXR_ERROR_INVALID_FILE (-5)
127 #define TINYEXR_ERROR_INVALID_PARAMETER (-6)
128 #define TINYEXR_ERROR_CANT_OPEN_FILE (-7)
129 #define TINYEXR_ERROR_UNSUPPORTED_FORMAT (-8)
130 #define TINYEXR_ERROR_INVALID_HEADER (-9)
131 #define TINYEXR_ERROR_UNSUPPORTED_FEATURE (-10)
132 #define TINYEXR_ERROR_CANT_WRITE_FILE (-11)
133 #define TINYEXR_ERROR_SERIALZATION_FAILED (-12)
134 #define TINYEXR_ERROR_LAYER_NOT_FOUND (-13)
135 
136 // @note { OpenEXR file format: http://www.openexr.com/openexrfilelayout.pdf }
137 
138 // pixel type: possible values are: UINT = 0 HALF = 1 FLOAT = 2
139 #define TINYEXR_PIXELTYPE_UINT (0)
140 #define TINYEXR_PIXELTYPE_HALF (1)
141 #define TINYEXR_PIXELTYPE_FLOAT (2)
142 
143 #define TINYEXR_MAX_HEADER_ATTRIBUTES (1024)
144 #define TINYEXR_MAX_CUSTOM_ATTRIBUTES (128)
145 
146 #define TINYEXR_COMPRESSIONTYPE_NONE (0)
147 #define TINYEXR_COMPRESSIONTYPE_RLE (1)
148 #define TINYEXR_COMPRESSIONTYPE_ZIPS (2)
149 #define TINYEXR_COMPRESSIONTYPE_ZIP (3)
150 #define TINYEXR_COMPRESSIONTYPE_PIZ (4)
151 #define TINYEXR_COMPRESSIONTYPE_ZFP (128)  // TinyEXR extension
152 
153 #define TINYEXR_ZFP_COMPRESSIONTYPE_RATE (0)
154 #define TINYEXR_ZFP_COMPRESSIONTYPE_PRECISION (1)
155 #define TINYEXR_ZFP_COMPRESSIONTYPE_ACCURACY (2)
156 
157 #define TINYEXR_TILE_ONE_LEVEL (0)
158 #define TINYEXR_TILE_MIPMAP_LEVELS (1)
159 #define TINYEXR_TILE_RIPMAP_LEVELS (2)
160 
161 #define TINYEXR_TILE_ROUND_DOWN (0)
162 #define TINYEXR_TILE_ROUND_UP (1)
163 
164 typedef struct _EXRVersion {
165   int version;    // this must be 2
166   int tiled;      // tile format image
167   int long_name;  // long name attribute
168   int non_image;  // deep image(EXR 2.0)
169   int multipart;  // multi-part(EXR 2.0)
170 } EXRVersion;
171 
172 typedef struct _EXRAttribute {
173   char name[256];  // name and type are up to 255 chars long.
174   char type[256];
175   unsigned char *value;  // uint8_t*
176   int size;
177   int pad0;
178 } EXRAttribute;
179 
180 typedef struct _EXRChannelInfo {
181   char name[256];  // less than 255 bytes long
182   int pixel_type;
183   int x_sampling;
184   int y_sampling;
185   unsigned char p_linear;
186   unsigned char pad[3];
187 } EXRChannelInfo;
188 
189 typedef struct _EXRTile {
190   int offset_x;
191   int offset_y;
192   int level_x;
193   int level_y;
194 
195   int width;   // actual width in a tile.
196   int height;  // actual height int a tile.
197 
198   unsigned char **images;  // image[channels][pixels]
199 } EXRTile;
200 
201 typedef struct _EXRHeader {
202   float pixel_aspect_ratio;
203   int line_order;
204   int data_window[4];
205   int display_window[4];
206   float screen_window_center[2];
207   float screen_window_width;
208 
209   int chunk_count;
210 
211   // Properties for tiled format(`tiledesc`).
212   int tiled;
213   int tile_size_x;
214   int tile_size_y;
215   int tile_level_mode;
216   int tile_rounding_mode;
217 
218   int long_name;
219   int non_image;
220   int multipart;
221   unsigned int header_len;
222 
223   // Custom attributes(exludes required attributes(e.g. `channels`,
224   // `compression`, etc)
225   int num_custom_attributes;
226   EXRAttribute *custom_attributes;  // array of EXRAttribute. size =
227                                     // `num_custom_attributes`.
228 
229   EXRChannelInfo *channels;  // [num_channels]
230 
231   int *pixel_types;  // Loaded pixel type(TINYEXR_PIXELTYPE_*) of `images` for
232   // each channel. This is overwritten with `requested_pixel_types` when
233   // loading.
234   int num_channels;
235 
236   int compression_type;        // compression type(TINYEXR_COMPRESSIONTYPE_*)
237   int *requested_pixel_types;  // Filled initially by
238                                // ParseEXRHeaderFrom(Meomory|File), then users
239                                // can edit it(only valid for HALF pixel type
240                                // channel)
241 
242 } EXRHeader;
243 
244 typedef struct _EXRMultiPartHeader {
245   int num_headers;
246   EXRHeader *headers;
247 
248 } EXRMultiPartHeader;
249 
250 typedef struct _EXRImage {
251   EXRTile *tiles;  // Tiled pixel data. The application must reconstruct image
252                    // from tiles manually. NULL if scanline format.
253   unsigned char **images;  // image[channels][pixels]. NULL if tiled format.
254 
255   int width;
256   int height;
257   int num_channels;
258 
259   // Properties for tile format.
260   int num_tiles;
261 
262 } EXRImage;
263 
264 typedef struct _EXRMultiPartImage {
265   int num_images;
266   EXRImage *images;
267 
268 } EXRMultiPartImage;
269 
270 typedef struct _DeepImage {
271   const char **channel_names;
272   float ***image;      // image[channels][scanlines][samples]
273   int **offset_table;  // offset_table[scanline][offsets]
274   int num_channels;
275   int width;
276   int height;
277   int pad0;
278 } DeepImage;
279 
280 // @deprecated { For backward compatibility. Not recommended to use. }
281 // Loads single-frame OpenEXR image. Assume EXR image contains A(single channel
282 // alpha) or RGB(A) channels.
283 // Application must free image data as returned by `out_rgba`
284 // Result image format is: float x RGBA x width x hight
285 // Returns negative value and may set error string in `err` when there's an
286 // error
287 extern int LoadEXR(float **out_rgba, int *width, int *height,
288                    const char *filename, const char **err);
289 
290 // Loads single-frame OpenEXR image by specifing layer name. Assume EXR image contains A(single channel
291 // alpha) or RGB(A) channels.
292 // Application must free image data as returned by `out_rgba`
293 // Result image format is: float x RGBA x width x hight
294 // Returns negative value and may set error string in `err` when there's an
295 // error
296 // When the specified layer name is not found in the EXR file, the function will return `TINYEXR_ERROR_LAYER_NOT_FOUND`.
297 extern int LoadEXRWithLayer(float **out_rgba, int *width, int *height,
298                    const char *filename, const char *layer_name, const char **err);
299 
300 //
301 // Get layer infos from EXR file.
302 //
303 // @param[out] layer_names List of layer names. Application must free memory after using this.
304 // @param[out] num_layers The number of layers
305 // @param[out] err Error string(wll be filled when the function returns error code). Free it using FreeEXRErrorMessage after using this value.
306 //
307 // @return TINYEXR_SUCCEES upon success.
308 //
309 extern int EXRLayers(const char *filename, const char **layer_names[], int *num_layers, const char **err);
310 
311 // @deprecated { to be removed. }
312 // Simple wrapper API for ParseEXRHeaderFromFile.
313 // checking given file is a EXR file(by just look up header)
314 // @return TINYEXR_SUCCEES for EXR image, TINYEXR_ERROR_INVALID_HEADER for
315 // others
316 extern int IsEXR(const char *filename);
317 
318 // @deprecated { to be removed. }
319 // Saves single-frame OpenEXR image. Assume EXR image contains RGB(A) channels.
320 // components must be 1(Grayscale), 3(RGB) or 4(RGBA).
321 // Input image format is: `float x width x height`, or `float x RGB(A) x width x
322 // hight`
323 // Save image as fp16(HALF) format when `save_as_fp16` is positive non-zero
324 // value.
325 // Save image as fp32(FLOAT) format when `save_as_fp16` is 0.
326 // Use ZIP compression by default.
327 // Returns negative value and may set error string in `err` when there's an
328 // error
329 extern int SaveEXR(const float *data, const int width, const int height,
330                    const int components, const int save_as_fp16,
331                    const char *filename, const char **err);
332 
333 // Initialize EXRHeader struct
334 extern void InitEXRHeader(EXRHeader *exr_header);
335 
336 // Initialize EXRImage struct
337 extern void InitEXRImage(EXRImage *exr_image);
338 
339 // Free's internal data of EXRHeader struct
340 extern int FreeEXRHeader(EXRHeader *exr_header);
341 
342 // Free's internal data of EXRImage struct
343 extern int FreeEXRImage(EXRImage *exr_image);
344 
345 // Free's error message
346 extern void FreeEXRErrorMessage(const char *msg);
347 
348 // Parse EXR version header of a file.
349 extern int ParseEXRVersionFromFile(EXRVersion *version, const char *filename);
350 
351 // Parse EXR version header from memory-mapped EXR data.
352 extern int ParseEXRVersionFromMemory(EXRVersion *version,
353                                      const unsigned char *memory, size_t size);
354 
355 // Parse single-part OpenEXR header from a file and initialize `EXRHeader`.
356 // When there was an error message, Application must free `err` with
357 // FreeEXRErrorMessage()
358 extern int ParseEXRHeaderFromFile(EXRHeader *header, const EXRVersion *version,
359                                   const char *filename, const char **err);
360 
361 // Parse single-part OpenEXR header from a memory and initialize `EXRHeader`.
362 // When there was an error message, Application must free `err` with
363 // FreeEXRErrorMessage()
364 extern int ParseEXRHeaderFromMemory(EXRHeader *header,
365                                     const EXRVersion *version,
366                                     const unsigned char *memory, size_t size,
367                                     const char **err);
368 
369 // Parse multi-part OpenEXR headers from a file and initialize `EXRHeader*`
370 // array.
371 // When there was an error message, Application must free `err` with
372 // FreeEXRErrorMessage()
373 extern int ParseEXRMultipartHeaderFromFile(EXRHeader ***headers,
374                                            int *num_headers,
375                                            const EXRVersion *version,
376                                            const char *filename,
377                                            const char **err);
378 
379 // Parse multi-part OpenEXR headers from a memory and initialize `EXRHeader*`
380 // array
381 // When there was an error message, Application must free `err` with
382 // FreeEXRErrorMessage()
383 extern int ParseEXRMultipartHeaderFromMemory(EXRHeader ***headers,
384                                              int *num_headers,
385                                              const EXRVersion *version,
386                                              const unsigned char *memory,
387                                              size_t size, const char **err);
388 
389 // Loads single-part OpenEXR image from a file.
390 // Application must setup `ParseEXRHeaderFromFile` before calling this function.
391 // Application can free EXRImage using `FreeEXRImage`
392 // Returns negative value and may set error string in `err` when there's an
393 // error
394 // When there was an error message, Application must free `err` with
395 // FreeEXRErrorMessage()
396 extern int LoadEXRImageFromFile(EXRImage *image, const EXRHeader *header,
397                                 const char *filename, const char **err);
398 
399 // Loads single-part OpenEXR image from a memory.
400 // Application must setup `EXRHeader` with
401 // `ParseEXRHeaderFromMemory` before calling this function.
402 // Application can free EXRImage using `FreeEXRImage`
403 // Returns negative value and may set error string in `err` when there's an
404 // error
405 // When there was an error message, Application must free `err` with
406 // FreeEXRErrorMessage()
407 extern int LoadEXRImageFromMemory(EXRImage *image, const EXRHeader *header,
408                                   const unsigned char *memory,
409                                   const size_t size, const char **err);
410 
411 // Loads multi-part OpenEXR image from a file.
412 // Application must setup `ParseEXRMultipartHeaderFromFile` before calling this
413 // function.
414 // Application can free EXRImage using `FreeEXRImage`
415 // Returns negative value and may set error string in `err` when there's an
416 // error
417 // When there was an error message, Application must free `err` with
418 // FreeEXRErrorMessage()
419 extern int LoadEXRMultipartImageFromFile(EXRImage *images,
420                                          const EXRHeader **headers,
421                                          unsigned int num_parts,
422                                          const char *filename,
423                                          const char **err);
424 
425 // Loads multi-part OpenEXR image from a memory.
426 // Application must setup `EXRHeader*` array with
427 // `ParseEXRMultipartHeaderFromMemory` before calling this function.
428 // Application can free EXRImage using `FreeEXRImage`
429 // Returns negative value and may set error string in `err` when there's an
430 // error
431 // When there was an error message, Application must free `err` with
432 // FreeEXRErrorMessage()
433 extern int LoadEXRMultipartImageFromMemory(EXRImage *images,
434                                            const EXRHeader **headers,
435                                            unsigned int num_parts,
436                                            const unsigned char *memory,
437                                            const size_t size, const char **err);
438 
439 // Saves multi-channel, single-frame OpenEXR image to a file.
440 // Returns negative value and may set error string in `err` when there's an
441 // error
442 // When there was an error message, Application must free `err` with
443 // FreeEXRErrorMessage()
444 extern int SaveEXRImageToFile(const EXRImage *image,
445                               const EXRHeader *exr_header, const char *filename,
446                               const char **err);
447 
448 // Saves multi-channel, single-frame OpenEXR image to a memory.
449 // Image is compressed using EXRImage.compression value.
450 // Return the number of bytes if success.
451 // Return zero and will set error string in `err` when there's an
452 // error.
453 // When there was an error message, Application must free `err` with
454 // FreeEXRErrorMessage()
455 extern size_t SaveEXRImageToMemory(const EXRImage *image,
456                                    const EXRHeader *exr_header,
457                                    unsigned char **memory, const char **err);
458 
459 // Loads single-frame OpenEXR deep image.
460 // Application must free memory of variables in DeepImage(image, offset_table)
461 // Returns negative value and may set error string in `err` when there's an
462 // error
463 // When there was an error message, Application must free `err` with
464 // FreeEXRErrorMessage()
465 extern int LoadDeepEXR(DeepImage *out_image, const char *filename,
466                        const char **err);
467 
468 // NOT YET IMPLEMENTED:
469 // Saves single-frame OpenEXR deep image.
470 // Returns negative value and may set error string in `err` when there's an
471 // error
472 // extern int SaveDeepEXR(const DeepImage *in_image, const char *filename,
473 //                       const char **err);
474 
475 // NOT YET IMPLEMENTED:
476 // Loads multi-part OpenEXR deep image.
477 // Application must free memory of variables in DeepImage(image, offset_table)
478 // extern int LoadMultiPartDeepEXR(DeepImage **out_image, int num_parts, const
479 // char *filename,
480 //                       const char **err);
481 
482 // For emscripten.
483 // Loads single-frame OpenEXR image from memory. Assume EXR image contains
484 // RGB(A) channels.
485 // Returns negative value and may set error string in `err` when there's an
486 // error
487 // When there was an error message, Application must free `err` with
488 // FreeEXRErrorMessage()
489 extern int LoadEXRFromMemory(float **out_rgba, int *width, int *height,
490                              const unsigned char *memory, size_t size,
491                              const char **err);
492 
493 #ifdef __cplusplus
494 }
495 #endif
496 
497 #endif  // TINYEXR_H_
498 
499 #ifdef TINYEXR_IMPLEMENTATION
500 #ifndef TINYEXR_IMPLEMENTATION_DEIFNED
501 #define TINYEXR_IMPLEMENTATION_DEIFNED
502 
503 #include <algorithm>
504 #include <cstdio>
505 #include <cstdlib>
506 #include <cstring>
507 #include <sstream>
508 
509 // #include <iostream> // debug
510 
511 #include <limits>
512 #include <string>
513 #include <vector>
514 
515 #if __cplusplus > 199711L
516 // C++11
517 #include <cstdint>
518 
519 #if TINYEXR_USE_THREAD
520 #include <atomic>
521 #include <thread>
522 #endif
523 
524 #endif  // __cplusplus > 199711L
525 
526 #if TINYEXR_USE_OPENMP
527 #include <omp.h>
528 #endif
529 
530 #if TINYEXR_USE_MINIZ
531 #else
532 //  Issue #46. Please include your own zlib-compatible API header before
533 //  including `tinyexr.h`
534 //#include "zlib.h"
535 #endif
536 
537 #if TINYEXR_USE_ZFP
538 #include "zfp.h"
539 #endif
540 
541 namespace tinyexr {
542 
543 #if __cplusplus > 199711L
544 // C++11
545 typedef uint64_t tinyexr_uint64;
546 typedef int64_t tinyexr_int64;
547 #else
548 // Although `long long` is not a standard type pre C++11, assume it is defined
549 // as a compiler's extension.
550 #ifdef __clang__
551 #pragma clang diagnostic push
552 #pragma clang diagnostic ignored "-Wc++11-long-long"
553 #endif
554 typedef unsigned long long tinyexr_uint64;
555 typedef long long tinyexr_int64;
556 #ifdef __clang__
557 #pragma clang diagnostic pop
558 #endif
559 #endif
560 
561 #if TINYEXR_USE_MINIZ
562 
563 namespace miniz {
564 
565 #ifdef __clang__
566 #pragma clang diagnostic push
567 #pragma clang diagnostic ignored "-Wc++11-long-long"
568 #pragma clang diagnostic ignored "-Wold-style-cast"
569 #pragma clang diagnostic ignored "-Wpadded"
570 #pragma clang diagnostic ignored "-Wsign-conversion"
571 #pragma clang diagnostic ignored "-Wc++11-extensions"
572 #pragma clang diagnostic ignored "-Wconversion"
573 #pragma clang diagnostic ignored "-Wunused-function"
574 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
575 #pragma clang diagnostic ignored "-Wundef"
576 
577 #if __has_warning("-Wcomma")
578 #pragma clang diagnostic ignored "-Wcomma"
579 #endif
580 
581 #if __has_warning("-Wmacro-redefined")
582 #pragma clang diagnostic ignored "-Wmacro-redefined"
583 #endif
584 
585 #if __has_warning("-Wcast-qual")
586 #pragma clang diagnostic ignored "-Wcast-qual"
587 #endif
588 
589 #if __has_warning("-Wzero-as-null-pointer-constant")
590 #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
591 #endif
592 
593 #if __has_warning("-Wtautological-constant-compare")
594 #pragma clang diagnostic ignored "-Wtautological-constant-compare"
595 #endif
596 
597 #if __has_warning("-Wextra-semi-stmt")
598 #pragma clang diagnostic ignored "-Wextra-semi-stmt"
599 #endif
600 
601 #endif
602 
603 /* miniz.c v1.15 - public domain deflate/inflate, zlib-subset, ZIP
604    reading/writing/appending, PNG writing
605    See "unlicense" statement at the end of this file.
606    Rich Geldreich <richgel99@gmail.com>, last updated Oct. 13, 2013
607    Implements RFC 1950: http://www.ietf.org/rfc/rfc1950.txt and RFC 1951:
608    http://www.ietf.org/rfc/rfc1951.txt
609 
610    Most API's defined in miniz.c are optional. For example, to disable the
611    archive related functions just define
612    MINIZ_NO_ARCHIVE_APIS, or to get rid of all stdio usage define MINIZ_NO_STDIO
613    (see the list below for more macros).
614 
615    * Change History
616      10/13/13 v1.15 r4 - Interim bugfix release while I work on the next major
617    release with Zip64 support (almost there!):
618        - Critical fix for the MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY bug
619    (thanks kahmyong.moon@hp.com) which could cause locate files to not find
620    files. This bug
621         would only have occured in earlier versions if you explicitly used this
622    flag, OR if you used mz_zip_extract_archive_file_to_heap() or
623    mz_zip_add_mem_to_archive_file_in_place()
624         (which used this flag). If you can't switch to v1.15 but want to fix
625    this bug, just remove the uses of this flag from both helper funcs (and of
626    course don't use the flag).
627        - Bugfix in mz_zip_reader_extract_to_mem_no_alloc() from kymoon when
628    pUser_read_buf is not NULL and compressed size is > uncompressed size
629        - Fixing mz_zip_reader_extract_*() funcs so they don't try to extract
630    compressed data from directory entries, to account for weird zipfiles which
631    contain zero-size compressed data on dir entries.
632          Hopefully this fix won't cause any issues on weird zip archives,
633    because it assumes the low 16-bits of zip external attributes are DOS
634    attributes (which I believe they always are in practice).
635        - Fixing mz_zip_reader_is_file_a_directory() so it doesn't check the
636    internal attributes, just the filename and external attributes
637        - mz_zip_reader_init_file() - missing MZ_FCLOSE() call if the seek failed
638        - Added cmake support for Linux builds which builds all the examples,
639    tested with clang v3.3 and gcc v4.6.
640        - Clang fix for tdefl_write_image_to_png_file_in_memory() from toffaletti
641        - Merged MZ_FORCEINLINE fix from hdeanclark
642        - Fix <time.h> include before config #ifdef, thanks emil.brink
643        - Added tdefl_write_image_to_png_file_in_memory_ex(): supports Y flipping
644    (super useful for OpenGL apps), and explicit control over the compression
645    level (so you can
646         set it to 1 for real-time compression).
647        - Merged in some compiler fixes from paulharris's github repro.
648        - Retested this build under Windows (VS 2010, including static analysis),
649    tcc  0.9.26, gcc v4.6 and clang v3.3.
650        - Added example6.c, which dumps an image of the mandelbrot set to a PNG
651    file.
652        - Modified example2 to help test the
653    MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY flag more.
654        - In r3: Bugfix to mz_zip_writer_add_file() found during merge: Fix
655    possible src file fclose() leak if alignment bytes+local header file write
656    faiiled
657                  - In r4: Minor bugfix to mz_zip_writer_add_from_zip_reader():
658    Was pushing the wrong central dir header offset, appears harmless in this
659    release, but it became a problem in the zip64 branch
660      5/20/12 v1.14 - MinGW32/64 GCC 4.6.1 compiler fixes: added MZ_FORCEINLINE,
661    #include <time.h> (thanks fermtect).
662      5/19/12 v1.13 - From jason@cornsyrup.org and kelwert@mtu.edu - Fix
663    mz_crc32() so it doesn't compute the wrong CRC-32's when mz_ulong is 64-bit.
664        - Temporarily/locally slammed in "typedef unsigned long mz_ulong" and
665    re-ran a randomized regression test on ~500k files.
666        - Eliminated a bunch of warnings when compiling with GCC 32-bit/64.
667        - Ran all examples, miniz.c, and tinfl.c through MSVC 2008's /analyze
668    (static analysis) option and fixed all warnings (except for the silly
669         "Use of the comma-operator in a tested expression.." analysis warning,
670    which I purposely use to work around a MSVC compiler warning).
671        - Created 32-bit and 64-bit Codeblocks projects/workspace. Built and
672    tested Linux executables. The codeblocks workspace is compatible with
673    Linux+Win32/x64.
674        - Added miniz_tester solution/project, which is a useful little app
675    derived from LZHAM's tester app that I use as part of the regression test.
676        - Ran miniz.c and tinfl.c through another series of regression testing on
677    ~500,000 files and archives.
678        - Modified example5.c so it purposely disables a bunch of high-level
679    functionality (MINIZ_NO_STDIO, etc.). (Thanks to corysama for the
680    MINIZ_NO_STDIO bug report.)
681        - Fix ftell() usage in examples so they exit with an error on files which
682    are too large (a limitation of the examples, not miniz itself).
683      4/12/12 v1.12 - More comments, added low-level example5.c, fixed a couple
684    minor level_and_flags issues in the archive API's.
685       level_and_flags can now be set to MZ_DEFAULT_COMPRESSION. Thanks to Bruce
686    Dawson <bruced@valvesoftware.com> for the feedback/bug report.
687      5/28/11 v1.11 - Added statement from unlicense.org
688      5/27/11 v1.10 - Substantial compressor optimizations:
689       - Level 1 is now ~4x faster than before. The L1 compressor's throughput
690    now varies between 70-110MB/sec. on a
691       - Core i7 (actual throughput varies depending on the type of data, and x64
692    vs. x86).
693       - Improved baseline L2-L9 compression perf. Also, greatly improved
694    compression perf. issues on some file types.
695       - Refactored the compression code for better readability and
696    maintainability.
697       - Added level 10 compression level (L10 has slightly better ratio than
698    level 9, but could have a potentially large
699        drop in throughput on some files).
700      5/15/11 v1.09 - Initial stable release.
701 
702    * Low-level Deflate/Inflate implementation notes:
703 
704      Compression: Use the "tdefl" API's. The compressor supports raw, static,
705    and dynamic blocks, lazy or
706      greedy parsing, match length filtering, RLE-only, and Huffman-only streams.
707    It performs and compresses
708      approximately as well as zlib.
709 
710      Decompression: Use the "tinfl" API's. The entire decompressor is
711    implemented as a single function
712      coroutine: see tinfl_decompress(). It supports decompression into a 32KB
713    (or larger power of 2) wrapping buffer, or into a memory
714      block large enough to hold the entire file.
715 
716      The low-level tdefl/tinfl API's do not make any use of dynamic memory
717    allocation.
718 
719    * zlib-style API notes:
720 
721      miniz.c implements a fairly large subset of zlib. There's enough
722    functionality present for it to be a drop-in
723      zlib replacement in many apps:
724         The z_stream struct, optional memory allocation callbacks
725         deflateInit/deflateInit2/deflate/deflateReset/deflateEnd/deflateBound
726         inflateInit/inflateInit2/inflate/inflateEnd
727         compress, compress2, compressBound, uncompress
728         CRC-32, Adler-32 - Using modern, minimal code size, CPU cache friendly
729    routines.
730         Supports raw deflate streams or standard zlib streams with adler-32
731    checking.
732 
733      Limitations:
734       The callback API's are not implemented yet. No support for gzip headers or
735    zlib static dictionaries.
736       I've tried to closely emulate zlib's various flavors of stream flushing
737    and return status codes, but
738       there are no guarantees that miniz.c pulls this off perfectly.
739 
740    * PNG writing: See the tdefl_write_image_to_png_file_in_memory() function,
741    originally written by
742      Alex Evans. Supports 1-4 bytes/pixel images.
743 
744    * ZIP archive API notes:
745 
746      The ZIP archive API's where designed with simplicity and efficiency in
747    mind, with just enough abstraction to
748      get the job done with minimal fuss. There are simple API's to retrieve file
749    information, read files from
750      existing archives, create new archives, append new files to existing
751    archives, or clone archive data from
752      one archive to another. It supports archives located in memory or the heap,
753    on disk (using stdio.h),
754      or you can specify custom file read/write callbacks.
755 
756      - Archive reading: Just call this function to read a single file from a
757    disk archive:
758 
759       void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const
760    char *pArchive_name,
761         size_t *pSize, mz_uint zip_flags);
762 
763      For more complex cases, use the "mz_zip_reader" functions. Upon opening an
764    archive, the entire central
765      directory is located and read as-is into memory, and subsequent file access
766    only occurs when reading individual files.
767 
768      - Archives file scanning: The simple way is to use this function to scan a
769    loaded archive for a specific file:
770 
771      int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName,
772    const char *pComment, mz_uint flags);
773 
774      The locate operation can optionally check file comments too, which (as one
775    example) can be used to identify
776      multiple versions of the same file in an archive. This function uses a
777    simple linear search through the central
778      directory, so it's not very fast.
779 
780      Alternately, you can iterate through all the files in an archive (using
781    mz_zip_reader_get_num_files()) and
782      retrieve detailed info on each file by calling mz_zip_reader_file_stat().
783 
784      - Archive creation: Use the "mz_zip_writer" functions. The ZIP writer
785    immediately writes compressed file data
786      to disk and builds an exact image of the central directory in memory. The
787    central directory image is written
788      all at once at the end of the archive file when the archive is finalized.
789 
790      The archive writer can optionally align each file's local header and file
791    data to any power of 2 alignment,
792      which can be useful when the archive will be read from optical media. Also,
793    the writer supports placing
794      arbitrary data blobs at the very beginning of ZIP archives. Archives
795    written using either feature are still
796      readable by any ZIP tool.
797 
798      - Archive appending: The simple way to add a single file to an archive is
799    to call this function:
800 
801       mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename,
802    const char *pArchive_name,
803         const void *pBuf, size_t buf_size, const void *pComment, mz_uint16
804    comment_size, mz_uint level_and_flags);
805 
806      The archive will be created if it doesn't already exist, otherwise it'll be
807    appended to.
808      Note the appending is done in-place and is not an atomic operation, so if
809    something goes wrong
810      during the operation it's possible the archive could be left without a
811    central directory (although the local
812      file headers and file data will be fine, so the archive will be
813    recoverable).
814 
815      For more complex archive modification scenarios:
816      1. The safest way is to use a mz_zip_reader to read the existing archive,
817    cloning only those bits you want to
818      preserve into a new archive using using the
819    mz_zip_writer_add_from_zip_reader() function (which compiles the
820      compressed file data as-is). When you're done, delete the old archive and
821    rename the newly written archive, and
822      you're done. This is safe but requires a bunch of temporary disk space or
823    heap memory.
824 
825      2. Or, you can convert an mz_zip_reader in-place to an mz_zip_writer using
826    mz_zip_writer_init_from_reader(),
827      append new files as needed, then finalize the archive which will write an
828    updated central directory to the
829      original archive. (This is basically what
830    mz_zip_add_mem_to_archive_file_in_place() does.) There's a
831      possibility that the archive's central directory could be lost with this
832    method if anything goes wrong, though.
833 
834      - ZIP archive support limitations:
835      No zip64 or spanning support. Extraction functions can only handle
836    unencrypted, stored or deflated files.
837      Requires streams capable of seeking.
838 
839    * This is a header file library, like stb_image.c. To get only a header file,
840    either cut and paste the
841      below header, or create miniz.h, #define MINIZ_HEADER_FILE_ONLY, and then
842    include miniz.c from it.
843 
844    * Important: For best perf. be sure to customize the below macros for your
845    target platform:
846      #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1
847      #define MINIZ_LITTLE_ENDIAN 1
848      #define MINIZ_HAS_64BIT_REGISTERS 1
849 
850    * On platforms using glibc, Be sure to "#define _LARGEFILE64_SOURCE 1" before
851    including miniz.c to ensure miniz
852      uses the 64-bit variants: fopen64(), stat64(), etc. Otherwise you won't be
853    able to process large files
854      (i.e. 32-bit stat() fails for me on files > 0x7FFFFFFF bytes).
855 */
856 
857 #ifndef MINIZ_HEADER_INCLUDED
858 #define MINIZ_HEADER_INCLUDED
859 
860 //#include <stdlib.h>
861 
862 // Defines to completely disable specific portions of miniz.c:
863 // If all macros here are defined the only functionality remaining will be
864 // CRC-32, adler-32, tinfl, and tdefl.
865 
866 // Define MINIZ_NO_STDIO to disable all usage and any functions which rely on
867 // stdio for file I/O.
868 //#define MINIZ_NO_STDIO
869 
870 // If MINIZ_NO_TIME is specified then the ZIP archive functions will not be able
871 // to get the current time, or
872 // get/set file times, and the C run-time funcs that get/set times won't be
873 // called.
874 // The current downside is the times written to your archives will be from 1979.
875 #define MINIZ_NO_TIME
876 
877 // Define MINIZ_NO_ARCHIVE_APIS to disable all ZIP archive API's.
878 #define MINIZ_NO_ARCHIVE_APIS
879 
880 // Define MINIZ_NO_ARCHIVE_APIS to disable all writing related ZIP archive
881 // API's.
882 //#define MINIZ_NO_ARCHIVE_WRITING_APIS
883 
884 // Define MINIZ_NO_ZLIB_APIS to remove all ZLIB-style compression/decompression
885 // API's.
886 //#define MINIZ_NO_ZLIB_APIS
887 
888 // Define MINIZ_NO_ZLIB_COMPATIBLE_NAME to disable zlib names, to prevent
889 // conflicts against stock zlib.
890 //#define MINIZ_NO_ZLIB_COMPATIBLE_NAMES
891 
892 // Define MINIZ_NO_MALLOC to disable all calls to malloc, free, and realloc.
893 // Note if MINIZ_NO_MALLOC is defined then the user must always provide custom
894 // user alloc/free/realloc
895 // callbacks to the zlib and archive API's, and a few stand-alone helper API's
896 // which don't provide custom user
897 // functions (such as tdefl_compress_mem_to_heap() and
898 // tinfl_decompress_mem_to_heap()) won't work.
899 //#define MINIZ_NO_MALLOC
900 
901 #if defined(__TINYC__) && (defined(__linux) || defined(__linux__))
902 // TODO: Work around "error: include file 'sys\utime.h' when compiling with tcc
903 // on Linux
904 #define MINIZ_NO_TIME
905 #endif
906 
907 #if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_ARCHIVE_APIS)
908 //#include <time.h>
909 #endif
910 
911 #if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || \
912     defined(__i386) || defined(__i486__) || defined(__i486) ||  \
913     defined(i386) || defined(__ia64__) || defined(__x86_64__)
914 // MINIZ_X86_OR_X64_CPU is only used to help set the below macros.
915 #define MINIZ_X86_OR_X64_CPU 1
916 #endif
917 
918 #if defined(__sparcv9)
919 // Big endian
920 #else
921 #if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || MINIZ_X86_OR_X64_CPU
922 // Set MINIZ_LITTLE_ENDIAN to 1 if the processor is little endian.
923 #define MINIZ_LITTLE_ENDIAN 1
924 #endif
925 #endif
926 
927 #if MINIZ_X86_OR_X64_CPU
928 // Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 on CPU's that permit efficient
929 // integer loads and stores from unaligned addresses.
930 //#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1
931 #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES \
932   0  // disable to suppress compiler warnings
933 #endif
934 
935 #if defined(_M_X64) || defined(_WIN64) || defined(__MINGW64__) || \
936     defined(_LP64) || defined(__LP64__) || defined(__ia64__) ||   \
937     defined(__x86_64__)
938 // Set MINIZ_HAS_64BIT_REGISTERS to 1 if operations on 64-bit integers are
939 // reasonably fast (and don't involve compiler generated calls to helper
940 // functions).
941 #define MINIZ_HAS_64BIT_REGISTERS 1
942 #endif
943 
944 #ifdef __cplusplus
945 extern "C" {
946 #endif
947 
948 // ------------------- zlib-style API Definitions.
949 
950 // For more compatibility with zlib, miniz.c uses unsigned long for some
951 // parameters/struct members. Beware: mz_ulong can be either 32 or 64-bits!
952 typedef unsigned long mz_ulong;
953 
954 // mz_free() internally uses the MZ_FREE() macro (which by default calls free()
955 // unless you've modified the MZ_MALLOC macro) to release a block allocated from
956 // the heap.
957 void mz_free(void *p);
958 
959 #define MZ_ADLER32_INIT (1)
960 // mz_adler32() returns the initial adler-32 value to use when called with
961 // ptr==NULL.
962 mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len);
963 
964 #define MZ_CRC32_INIT (0)
965 // mz_crc32() returns the initial CRC-32 value to use when called with
966 // ptr==NULL.
967 mz_ulong mz_crc32(mz_ulong crc, const unsigned char *ptr, size_t buf_len);
968 
969 // Compression strategies.
970 enum {
971   MZ_DEFAULT_STRATEGY = 0,
972   MZ_FILTERED = 1,
973   MZ_HUFFMAN_ONLY = 2,
974   MZ_RLE = 3,
975   MZ_FIXED = 4
976 };
977 
978 // Method
979 #define MZ_DEFLATED 8
980 
981 #ifndef MINIZ_NO_ZLIB_APIS
982 
983 // Heap allocation callbacks.
984 // Note that mz_alloc_func parameter types purpsosely differ from zlib's:
985 // items/size is size_t, not unsigned long.
986 typedef void *(*mz_alloc_func)(void *opaque, size_t items, size_t size);
987 typedef void (*mz_free_func)(void *opaque, void *address);
988 typedef void *(*mz_realloc_func)(void *opaque, void *address, size_t items,
989                                  size_t size);
990 
991 #define MZ_VERSION "9.1.15"
992 #define MZ_VERNUM 0x91F0
993 #define MZ_VER_MAJOR 9
994 #define MZ_VER_MINOR 1
995 #define MZ_VER_REVISION 15
996 #define MZ_VER_SUBREVISION 0
997 
998 // Flush values. For typical usage you only need MZ_NO_FLUSH and MZ_FINISH. The
999 // other values are for advanced use (refer to the zlib docs).
1000 enum {
1001   MZ_NO_FLUSH = 0,
1002   MZ_PARTIAL_FLUSH = 1,
1003   MZ_SYNC_FLUSH = 2,
1004   MZ_FULL_FLUSH = 3,
1005   MZ_FINISH = 4,
1006   MZ_BLOCK = 5
1007 };
1008 
1009 // Return status codes. MZ_PARAM_ERROR is non-standard.
1010 enum {
1011   MZ_OK = 0,
1012   MZ_STREAM_END = 1,
1013   MZ_NEED_DICT = 2,
1014   MZ_ERRNO = -1,
1015   MZ_STREAM_ERROR = -2,
1016   MZ_DATA_ERROR = -3,
1017   MZ_MEM_ERROR = -4,
1018   MZ_BUF_ERROR = -5,
1019   MZ_VERSION_ERROR = -6,
1020   MZ_PARAM_ERROR = -10000
1021 };
1022 
1023 // Compression levels: 0-9 are the standard zlib-style levels, 10 is best
1024 // possible compression (not zlib compatible, and may be very slow),
1025 // MZ_DEFAULT_COMPRESSION=MZ_DEFAULT_LEVEL.
1026 enum {
1027   MZ_NO_COMPRESSION = 0,
1028   MZ_BEST_SPEED = 1,
1029   MZ_BEST_COMPRESSION = 9,
1030   MZ_UBER_COMPRESSION = 10,
1031   MZ_DEFAULT_LEVEL = 6,
1032   MZ_DEFAULT_COMPRESSION = -1
1033 };
1034 
1035 // Window bits
1036 #define MZ_DEFAULT_WINDOW_BITS 15
1037 
1038 struct mz_internal_state;
1039 
1040 // Compression/decompression stream struct.
1041 typedef struct mz_stream_s {
1042   const unsigned char *next_in;  // pointer to next byte to read
1043   unsigned int avail_in;         // number of bytes available at next_in
1044   mz_ulong total_in;             // total number of bytes consumed so far
1045 
1046   unsigned char *next_out;  // pointer to next byte to write
1047   unsigned int avail_out;   // number of bytes that can be written to next_out
1048   mz_ulong total_out;       // total number of bytes produced so far
1049 
1050   char *msg;                        // error msg (unused)
1051   struct mz_internal_state *state;  // internal state, allocated by zalloc/zfree
1052 
1053   mz_alloc_func
1054       zalloc;          // optional heap allocation function (defaults to malloc)
1055   mz_free_func zfree;  // optional heap free function (defaults to free)
1056   void *opaque;        // heap alloc function user pointer
1057 
1058   int data_type;      // data_type (unused)
1059   mz_ulong adler;     // adler32 of the source or uncompressed data
1060   mz_ulong reserved;  // not used
1061 } mz_stream;
1062 
1063 typedef mz_stream *mz_streamp;
1064 
1065 // Returns the version string of miniz.c.
1066 const char *mz_version(void);
1067 
1068 // mz_deflateInit() initializes a compressor with default options:
1069 // Parameters:
1070 //  pStream must point to an initialized mz_stream struct.
1071 //  level must be between [MZ_NO_COMPRESSION, MZ_BEST_COMPRESSION].
1072 //  level 1 enables a specially optimized compression function that's been
1073 //  optimized purely for performance, not ratio.
1074 //  (This special func. is currently only enabled when
1075 //  MINIZ_USE_UNALIGNED_LOADS_AND_STORES and MINIZ_LITTLE_ENDIAN are defined.)
1076 // Return values:
1077 //  MZ_OK on success.
1078 //  MZ_STREAM_ERROR if the stream is bogus.
1079 //  MZ_PARAM_ERROR if the input parameters are bogus.
1080 //  MZ_MEM_ERROR on out of memory.
1081 int mz_deflateInit(mz_streamp pStream, int level);
1082 
1083 // mz_deflateInit2() is like mz_deflate(), except with more control:
1084 // Additional parameters:
1085 //   method must be MZ_DEFLATED
1086 //   window_bits must be MZ_DEFAULT_WINDOW_BITS (to wrap the deflate stream with
1087 //   zlib header/adler-32 footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate/no
1088 //   header or footer)
1089 //   mem_level must be between [1, 9] (it's checked but ignored by miniz.c)
1090 int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits,
1091                     int mem_level, int strategy);
1092 
1093 // Quickly resets a compressor without having to reallocate anything. Same as
1094 // calling mz_deflateEnd() followed by mz_deflateInit()/mz_deflateInit2().
1095 int mz_deflateReset(mz_streamp pStream);
1096 
1097 // mz_deflate() compresses the input to output, consuming as much of the input
1098 // and producing as much output as possible.
1099 // Parameters:
1100 //   pStream is the stream to read from and write to. You must initialize/update
1101 //   the next_in, avail_in, next_out, and avail_out members.
1102 //   flush may be MZ_NO_FLUSH, MZ_PARTIAL_FLUSH/MZ_SYNC_FLUSH, MZ_FULL_FLUSH, or
1103 //   MZ_FINISH.
1104 // Return values:
1105 //   MZ_OK on success (when flushing, or if more input is needed but not
1106 //   available, and/or there's more output to be written but the output buffer
1107 //   is full).
1108 //   MZ_STREAM_END if all input has been consumed and all output bytes have been
1109 //   written. Don't call mz_deflate() on the stream anymore.
1110 //   MZ_STREAM_ERROR if the stream is bogus.
1111 //   MZ_PARAM_ERROR if one of the parameters is invalid.
1112 //   MZ_BUF_ERROR if no forward progress is possible because the input and/or
1113 //   output buffers are empty. (Fill up the input buffer or free up some output
1114 //   space and try again.)
1115 int mz_deflate(mz_streamp pStream, int flush);
1116 
1117 // mz_deflateEnd() deinitializes a compressor:
1118 // Return values:
1119 //  MZ_OK on success.
1120 //  MZ_STREAM_ERROR if the stream is bogus.
1121 int mz_deflateEnd(mz_streamp pStream);
1122 
1123 // mz_deflateBound() returns a (very) conservative upper bound on the amount of
1124 // data that could be generated by deflate(), assuming flush is set to only
1125 // MZ_NO_FLUSH or MZ_FINISH.
1126 mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len);
1127 
1128 // Single-call compression functions mz_compress() and mz_compress2():
1129 // Returns MZ_OK on success, or one of the error codes from mz_deflate() on
1130 // failure.
1131 int mz_compress(unsigned char *pDest, mz_ulong *pDest_len,
1132                 const unsigned char *pSource, mz_ulong source_len);
1133 int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len,
1134                  const unsigned char *pSource, mz_ulong source_len, int level);
1135 
1136 // mz_compressBound() returns a (very) conservative upper bound on the amount of
1137 // data that could be generated by calling mz_compress().
1138 mz_ulong mz_compressBound(mz_ulong source_len);
1139 
1140 // Initializes a decompressor.
1141 int mz_inflateInit(mz_streamp pStream);
1142 
1143 // mz_inflateInit2() is like mz_inflateInit() with an additional option that
1144 // controls the window size and whether or not the stream has been wrapped with
1145 // a zlib header/footer:
1146 // window_bits must be MZ_DEFAULT_WINDOW_BITS (to parse zlib header/footer) or
1147 // -MZ_DEFAULT_WINDOW_BITS (raw deflate).
1148 int mz_inflateInit2(mz_streamp pStream, int window_bits);
1149 
1150 // Decompresses the input stream to the output, consuming only as much of the
1151 // input as needed, and writing as much to the output as possible.
1152 // Parameters:
1153 //   pStream is the stream to read from and write to. You must initialize/update
1154 //   the next_in, avail_in, next_out, and avail_out members.
1155 //   flush may be MZ_NO_FLUSH, MZ_SYNC_FLUSH, or MZ_FINISH.
1156 //   On the first call, if flush is MZ_FINISH it's assumed the input and output
1157 //   buffers are both sized large enough to decompress the entire stream in a
1158 //   single call (this is slightly faster).
1159 //   MZ_FINISH implies that there are no more source bytes available beside
1160 //   what's already in the input buffer, and that the output buffer is large
1161 //   enough to hold the rest of the decompressed data.
1162 // Return values:
1163 //   MZ_OK on success. Either more input is needed but not available, and/or
1164 //   there's more output to be written but the output buffer is full.
1165 //   MZ_STREAM_END if all needed input has been consumed and all output bytes
1166 //   have been written. For zlib streams, the adler-32 of the decompressed data
1167 //   has also been verified.
1168 //   MZ_STREAM_ERROR if the stream is bogus.
1169 //   MZ_DATA_ERROR if the deflate stream is invalid.
1170 //   MZ_PARAM_ERROR if one of the parameters is invalid.
1171 //   MZ_BUF_ERROR if no forward progress is possible because the input buffer is
1172 //   empty but the inflater needs more input to continue, or if the output
1173 //   buffer is not large enough. Call mz_inflate() again
1174 //   with more input data, or with more room in the output buffer (except when
1175 //   using single call decompression, described above).
1176 int mz_inflate(mz_streamp pStream, int flush);
1177 
1178 // Deinitializes a decompressor.
1179 int mz_inflateEnd(mz_streamp pStream);
1180 
1181 // Single-call decompression.
1182 // Returns MZ_OK on success, or one of the error codes from mz_inflate() on
1183 // failure.
1184 int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len,
1185                   const unsigned char *pSource, mz_ulong source_len);
1186 
1187 // Returns a string description of the specified error code, or NULL if the
1188 // error code is invalid.
1189 const char *mz_error(int err);
1190 
1191 // Redefine zlib-compatible names to miniz equivalents, so miniz.c can be used
1192 // as a drop-in replacement for the subset of zlib that miniz.c supports.
1193 // Define MINIZ_NO_ZLIB_COMPATIBLE_NAMES to disable zlib-compatibility if you
1194 // use zlib in the same project.
1195 #ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES
1196 typedef unsigned char Byte;
1197 typedef unsigned int uInt;
1198 typedef mz_ulong uLong;
1199 typedef Byte Bytef;
1200 typedef uInt uIntf;
1201 typedef char charf;
1202 typedef int intf;
1203 typedef void *voidpf;
1204 typedef uLong uLongf;
1205 typedef void *voidp;
1206 typedef void *const voidpc;
1207 #define Z_NULL 0
1208 #define Z_NO_FLUSH MZ_NO_FLUSH
1209 #define Z_PARTIAL_FLUSH MZ_PARTIAL_FLUSH
1210 #define Z_SYNC_FLUSH MZ_SYNC_FLUSH
1211 #define Z_FULL_FLUSH MZ_FULL_FLUSH
1212 #define Z_FINISH MZ_FINISH
1213 #define Z_BLOCK MZ_BLOCK
1214 #define Z_OK MZ_OK
1215 #define Z_STREAM_END MZ_STREAM_END
1216 #define Z_NEED_DICT MZ_NEED_DICT
1217 #define Z_ERRNO MZ_ERRNO
1218 #define Z_STREAM_ERROR MZ_STREAM_ERROR
1219 #define Z_DATA_ERROR MZ_DATA_ERROR
1220 #define Z_MEM_ERROR MZ_MEM_ERROR
1221 #define Z_BUF_ERROR MZ_BUF_ERROR
1222 #define Z_VERSION_ERROR MZ_VERSION_ERROR
1223 #define Z_PARAM_ERROR MZ_PARAM_ERROR
1224 #define Z_NO_COMPRESSION MZ_NO_COMPRESSION
1225 #define Z_BEST_SPEED MZ_BEST_SPEED
1226 #define Z_BEST_COMPRESSION MZ_BEST_COMPRESSION
1227 #define Z_DEFAULT_COMPRESSION MZ_DEFAULT_COMPRESSION
1228 #define Z_DEFAULT_STRATEGY MZ_DEFAULT_STRATEGY
1229 #define Z_FILTERED MZ_FILTERED
1230 #define Z_HUFFMAN_ONLY MZ_HUFFMAN_ONLY
1231 #define Z_RLE MZ_RLE
1232 #define Z_FIXED MZ_FIXED
1233 #define Z_DEFLATED MZ_DEFLATED
1234 #define Z_DEFAULT_WINDOW_BITS MZ_DEFAULT_WINDOW_BITS
1235 #define alloc_func mz_alloc_func
1236 #define free_func mz_free_func
1237 #define internal_state mz_internal_state
1238 #define z_stream mz_stream
1239 #define deflateInit mz_deflateInit
1240 #define deflateInit2 mz_deflateInit2
1241 #define deflateReset mz_deflateReset
1242 #define deflate mz_deflate
1243 #define deflateEnd mz_deflateEnd
1244 #define deflateBound mz_deflateBound
1245 #define compress mz_compress
1246 #define compress2 mz_compress2
1247 #define compressBound mz_compressBound
1248 #define inflateInit mz_inflateInit
1249 #define inflateInit2 mz_inflateInit2
1250 #define inflate mz_inflate
1251 #define inflateEnd mz_inflateEnd
1252 #define uncompress mz_uncompress
1253 #define crc32 mz_crc32
1254 #define adler32 mz_adler32
1255 #define MAX_WBITS 15
1256 #define MAX_MEM_LEVEL 9
1257 #define zError mz_error
1258 #define ZLIB_VERSION MZ_VERSION
1259 #define ZLIB_VERNUM MZ_VERNUM
1260 #define ZLIB_VER_MAJOR MZ_VER_MAJOR
1261 #define ZLIB_VER_MINOR MZ_VER_MINOR
1262 #define ZLIB_VER_REVISION MZ_VER_REVISION
1263 #define ZLIB_VER_SUBREVISION MZ_VER_SUBREVISION
1264 #define zlibVersion mz_version
1265 #define zlib_version mz_version()
1266 #endif  // #ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES
1267 
1268 #endif  // MINIZ_NO_ZLIB_APIS
1269 
1270 // ------------------- Types and macros
1271 
1272 typedef unsigned char mz_uint8;
1273 typedef signed short mz_int16;
1274 typedef unsigned short mz_uint16;
1275 typedef unsigned int mz_uint32;
1276 typedef unsigned int mz_uint;
1277 typedef long long mz_int64;
1278 typedef unsigned long long mz_uint64;
1279 typedef int mz_bool;
1280 
1281 #define MZ_FALSE (0)
1282 #define MZ_TRUE (1)
1283 
1284 // An attempt to work around MSVC's spammy "warning C4127: conditional
1285 // expression is constant" message.
1286 #ifdef _MSC_VER
1287 #define MZ_MACRO_END while (0, 0)
1288 #else
1289 #define MZ_MACRO_END while (0)
1290 #endif
1291 
1292 // ------------------- ZIP archive reading/writing
1293 
1294 #ifndef MINIZ_NO_ARCHIVE_APIS
1295 
1296 enum {
1297   MZ_ZIP_MAX_IO_BUF_SIZE = 64 * 1024,
1298   MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE = 260,
1299   MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE = 256
1300 };
1301 
1302 typedef struct {
1303   mz_uint32 m_file_index;
1304   mz_uint32 m_central_dir_ofs;
1305   mz_uint16 m_version_made_by;
1306   mz_uint16 m_version_needed;
1307   mz_uint16 m_bit_flag;
1308   mz_uint16 m_method;
1309 #ifndef MINIZ_NO_TIME
1310   time_t m_time;
1311 #endif
1312   mz_uint32 m_crc32;
1313   mz_uint64 m_comp_size;
1314   mz_uint64 m_uncomp_size;
1315   mz_uint16 m_internal_attr;
1316   mz_uint32 m_external_attr;
1317   mz_uint64 m_local_header_ofs;
1318   mz_uint32 m_comment_size;
1319   char m_filename[MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE];
1320   char m_comment[MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE];
1321 } mz_zip_archive_file_stat;
1322 
1323 typedef size_t (*mz_file_read_func)(void *pOpaque, mz_uint64 file_ofs,
1324                                     void *pBuf, size_t n);
1325 typedef size_t (*mz_file_write_func)(void *pOpaque, mz_uint64 file_ofs,
1326                                      const void *pBuf, size_t n);
1327 
1328 struct mz_zip_internal_state_tag;
1329 typedef struct mz_zip_internal_state_tag mz_zip_internal_state;
1330 
1331 typedef enum {
1332   MZ_ZIP_MODE_INVALID = 0,
1333   MZ_ZIP_MODE_READING = 1,
1334   MZ_ZIP_MODE_WRITING = 2,
1335   MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED = 3
1336 } mz_zip_mode;
1337 
1338 typedef struct mz_zip_archive_tag {
1339   mz_uint64 m_archive_size;
1340   mz_uint64 m_central_directory_file_ofs;
1341   mz_uint m_total_files;
1342   mz_zip_mode m_zip_mode;
1343 
1344   mz_uint m_file_offset_alignment;
1345 
1346   mz_alloc_func m_pAlloc;
1347   mz_free_func m_pFree;
1348   mz_realloc_func m_pRealloc;
1349   void *m_pAlloc_opaque;
1350 
1351   mz_file_read_func m_pRead;
1352   mz_file_write_func m_pWrite;
1353   void *m_pIO_opaque;
1354 
1355   mz_zip_internal_state *m_pState;
1356 
1357 } mz_zip_archive;
1358 
1359 typedef enum {
1360   MZ_ZIP_FLAG_CASE_SENSITIVE = 0x0100,
1361   MZ_ZIP_FLAG_IGNORE_PATH = 0x0200,
1362   MZ_ZIP_FLAG_COMPRESSED_DATA = 0x0400,
1363   MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY = 0x0800
1364 } mz_zip_flags;
1365 
1366 // ZIP archive reading
1367 
1368 // Inits a ZIP archive reader.
1369 // These functions read and validate the archive's central directory.
1370 mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size,
1371                            mz_uint32 flags);
1372 mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem,
1373                                size_t size, mz_uint32 flags);
1374 
1375 #ifndef MINIZ_NO_STDIO
1376 mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename,
1377                                 mz_uint32 flags);
1378 #endif
1379 
1380 // Returns the total number of files in the archive.
1381 mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip);
1382 
1383 // Returns detailed information about an archive file entry.
1384 mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index,
1385                                 mz_zip_archive_file_stat *pStat);
1386 
1387 // Determines if an archive file entry is a directory entry.
1388 mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip,
1389                                           mz_uint file_index);
1390 mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip,
1391                                         mz_uint file_index);
1392 
1393 // Retrieves the filename of an archive file entry.
1394 // Returns the number of bytes written to pFilename, or if filename_buf_size is
1395 // 0 this function returns the number of bytes needed to fully store the
1396 // filename.
1397 mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index,
1398                                    char *pFilename, mz_uint filename_buf_size);
1399 
1400 // Attempts to locates a file in the archive's central directory.
1401 // Valid flags: MZ_ZIP_FLAG_CASE_SENSITIVE, MZ_ZIP_FLAG_IGNORE_PATH
1402 // Returns -1 if the file cannot be found.
1403 int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName,
1404                               const char *pComment, mz_uint flags);
1405 
1406 // Extracts a archive file to a memory buffer using no memory allocation.
1407 mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip,
1408                                               mz_uint file_index, void *pBuf,
1409                                               size_t buf_size, mz_uint flags,
1410                                               void *pUser_read_buf,
1411                                               size_t user_read_buf_size);
1412 mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(
1413     mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size,
1414     mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size);
1415 
1416 // Extracts a archive file to a memory buffer.
1417 mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index,
1418                                      void *pBuf, size_t buf_size,
1419                                      mz_uint flags);
1420 mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip,
1421                                           const char *pFilename, void *pBuf,
1422                                           size_t buf_size, mz_uint flags);
1423 
1424 // Extracts a archive file to a dynamically allocated heap buffer.
1425 void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index,
1426                                     size_t *pSize, mz_uint flags);
1427 void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip,
1428                                          const char *pFilename, size_t *pSize,
1429                                          mz_uint flags);
1430 
1431 // Extracts a archive file using a callback function to output the file's data.
1432 mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip,
1433                                           mz_uint file_index,
1434                                           mz_file_write_func pCallback,
1435                                           void *pOpaque, mz_uint flags);
1436 mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip,
1437                                                const char *pFilename,
1438                                                mz_file_write_func pCallback,
1439                                                void *pOpaque, mz_uint flags);
1440 
1441 #ifndef MINIZ_NO_STDIO
1442 // Extracts a archive file to a disk file and sets its last accessed and
1443 // modified times.
1444 // This function only extracts files, not archive directory records.
1445 mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index,
1446                                       const char *pDst_filename, mz_uint flags);
1447 mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip,
1448                                            const char *pArchive_filename,
1449                                            const char *pDst_filename,
1450                                            mz_uint flags);
1451 #endif
1452 
1453 // Ends archive reading, freeing all allocations, and closing the input archive
1454 // file if mz_zip_reader_init_file() was used.
1455 mz_bool mz_zip_reader_end(mz_zip_archive *pZip);
1456 
1457 // ZIP archive writing
1458 
1459 #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
1460 
1461 // Inits a ZIP archive writer.
1462 mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size);
1463 mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip,
1464                                 size_t size_to_reserve_at_beginning,
1465                                 size_t initial_allocation_size);
1466 
1467 #ifndef MINIZ_NO_STDIO
1468 mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename,
1469                                 mz_uint64 size_to_reserve_at_beginning);
1470 #endif
1471 
1472 // Converts a ZIP archive reader object into a writer object, to allow efficient
1473 // in-place file appends to occur on an existing archive.
1474 // For archives opened using mz_zip_reader_init_file, pFilename must be the
1475 // archive's filename so it can be reopened for writing. If the file can't be
1476 // reopened, mz_zip_reader_end() will be called.
1477 // For archives opened using mz_zip_reader_init_mem, the memory block must be
1478 // growable using the realloc callback (which defaults to realloc unless you've
1479 // overridden it).
1480 // Finally, for archives opened using mz_zip_reader_init, the mz_zip_archive's
1481 // user provided m_pWrite function cannot be NULL.
1482 // Note: In-place archive modification is not recommended unless you know what
1483 // you're doing, because if execution stops or something goes wrong before
1484 // the archive is finalized the file's central directory will be hosed.
1485 mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip,
1486                                        const char *pFilename);
1487 
1488 // Adds the contents of a memory buffer to an archive. These functions record
1489 // the current local time into the archive.
1490 // To add a directory entry, call this method with an archive name ending in a
1491 // forwardslash with empty buffer.
1492 // level_and_flags - compression level (0-10, see MZ_BEST_SPEED,
1493 // MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or
1494 // just set to MZ_DEFAULT_COMPRESSION.
1495 mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name,
1496                               const void *pBuf, size_t buf_size,
1497                               mz_uint level_and_flags);
1498 mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip,
1499                                  const char *pArchive_name, const void *pBuf,
1500                                  size_t buf_size, const void *pComment,
1501                                  mz_uint16 comment_size,
1502                                  mz_uint level_and_flags, mz_uint64 uncomp_size,
1503                                  mz_uint32 uncomp_crc32);
1504 
1505 #ifndef MINIZ_NO_STDIO
1506 // Adds the contents of a disk file to an archive. This function also records
1507 // the disk file's modified time into the archive.
1508 // level_and_flags - compression level (0-10, see MZ_BEST_SPEED,
1509 // MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or
1510 // just set to MZ_DEFAULT_COMPRESSION.
1511 mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name,
1512                                const char *pSrc_filename, const void *pComment,
1513                                mz_uint16 comment_size, mz_uint level_and_flags);
1514 #endif
1515 
1516 // Adds a file to an archive by fully cloning the data from another archive.
1517 // This function fully clones the source file's compressed data (no
1518 // recompression), along with its full filename, extra data, and comment fields.
1519 mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip,
1520                                           mz_zip_archive *pSource_zip,
1521                                           mz_uint file_index);
1522 
1523 // Finalizes the archive by writing the central directory records followed by
1524 // the end of central directory record.
1525 // After an archive is finalized, the only valid call on the mz_zip_archive
1526 // struct is mz_zip_writer_end().
1527 // An archive must be manually finalized by calling this function for it to be
1528 // valid.
1529 mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip);
1530 mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **pBuf,
1531                                             size_t *pSize);
1532 
1533 // Ends archive writing, freeing all allocations, and closing the output file if
1534 // mz_zip_writer_init_file() was used.
1535 // Note for the archive to be valid, it must have been finalized before ending.
1536 mz_bool mz_zip_writer_end(mz_zip_archive *pZip);
1537 
1538 // Misc. high-level helper functions:
1539 
1540 // mz_zip_add_mem_to_archive_file_in_place() efficiently (but not atomically)
1541 // appends a memory blob to a ZIP archive.
1542 // level_and_flags - compression level (0-10, see MZ_BEST_SPEED,
1543 // MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or
1544 // just set to MZ_DEFAULT_COMPRESSION.
1545 mz_bool mz_zip_add_mem_to_archive_file_in_place(
1546     const char *pZip_filename, const char *pArchive_name, const void *pBuf,
1547     size_t buf_size, const void *pComment, mz_uint16 comment_size,
1548     mz_uint level_and_flags);
1549 
1550 // Reads a single file from an archive into a heap block.
1551 // Returns NULL on failure.
1552 void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename,
1553                                           const char *pArchive_name,
1554                                           size_t *pSize, mz_uint zip_flags);
1555 
1556 #endif  // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
1557 
1558 #endif  // #ifndef MINIZ_NO_ARCHIVE_APIS
1559 
1560 // ------------------- Low-level Decompression API Definitions
1561 
1562 // Decompression flags used by tinfl_decompress().
1563 // TINFL_FLAG_PARSE_ZLIB_HEADER: If set, the input has a valid zlib header and
1564 // ends with an adler32 checksum (it's a valid zlib stream). Otherwise, the
1565 // input is a raw deflate stream.
1566 // TINFL_FLAG_HAS_MORE_INPUT: If set, there are more input bytes available
1567 // beyond the end of the supplied input buffer. If clear, the input buffer
1568 // contains all remaining input.
1569 // TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF: If set, the output buffer is large
1570 // enough to hold the entire decompressed stream. If clear, the output buffer is
1571 // at least the size of the dictionary (typically 32KB).
1572 // TINFL_FLAG_COMPUTE_ADLER32: Force adler-32 checksum computation of the
1573 // decompressed bytes.
1574 enum {
1575   TINFL_FLAG_PARSE_ZLIB_HEADER = 1,
1576   TINFL_FLAG_HAS_MORE_INPUT = 2,
1577   TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF = 4,
1578   TINFL_FLAG_COMPUTE_ADLER32 = 8
1579 };
1580 
1581 // High level decompression functions:
1582 // tinfl_decompress_mem_to_heap() decompresses a block in memory to a heap block
1583 // allocated via malloc().
1584 // On entry:
1585 //  pSrc_buf, src_buf_len: Pointer and size of the Deflate or zlib source data
1586 //  to decompress.
1587 // On return:
1588 //  Function returns a pointer to the decompressed data, or NULL on failure.
1589 //  *pOut_len will be set to the decompressed data's size, which could be larger
1590 //  than src_buf_len on uncompressible data.
1591 //  The caller must call mz_free() on the returned block when it's no longer
1592 //  needed.
1593 void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len,
1594                                    size_t *pOut_len, int flags);
1595 
1596 // tinfl_decompress_mem_to_mem() decompresses a block in memory to another block
1597 // in memory.
1598 // Returns TINFL_DECOMPRESS_MEM_TO_MEM_FAILED on failure, or the number of bytes
1599 // written on success.
1600 #define TINFL_DECOMPRESS_MEM_TO_MEM_FAILED ((size_t)(-1))
1601 size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len,
1602                                    const void *pSrc_buf, size_t src_buf_len,
1603                                    int flags);
1604 
1605 // tinfl_decompress_mem_to_callback() decompresses a block in memory to an
1606 // internal 32KB buffer, and a user provided callback function will be called to
1607 // flush the buffer.
1608 // Returns 1 on success or 0 on failure.
1609 typedef int (*tinfl_put_buf_func_ptr)(const void *pBuf, int len, void *pUser);
1610 int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size,
1611                                      tinfl_put_buf_func_ptr pPut_buf_func,
1612                                      void *pPut_buf_user, int flags);
1613 
1614 struct tinfl_decompressor_tag;
1615 typedef struct tinfl_decompressor_tag tinfl_decompressor;
1616 
1617 // Max size of LZ dictionary.
1618 #define TINFL_LZ_DICT_SIZE 32768
1619 
1620 // Return status.
1621 typedef enum {
1622   TINFL_STATUS_BAD_PARAM = -3,
1623   TINFL_STATUS_ADLER32_MISMATCH = -2,
1624   TINFL_STATUS_FAILED = -1,
1625   TINFL_STATUS_DONE = 0,
1626   TINFL_STATUS_NEEDS_MORE_INPUT = 1,
1627   TINFL_STATUS_HAS_MORE_OUTPUT = 2
1628 } tinfl_status;
1629 
1630 // Initializes the decompressor to its initial state.
1631 #define tinfl_init(r) \
1632   do {                \
1633     (r)->m_state = 0; \
1634   }                   \
1635   MZ_MACRO_END
1636 #define tinfl_get_adler32(r) (r)->m_check_adler32
1637 
1638 // Main low-level decompressor coroutine function. This is the only function
1639 // actually needed for decompression. All the other functions are just
1640 // high-level helpers for improved usability.
1641 // This is a universal API, i.e. it can be used as a building block to build any
1642 // desired higher level decompression API. In the limit case, it can be called
1643 // once per every byte input or output.
1644 tinfl_status tinfl_decompress(tinfl_decompressor *r,
1645                               const mz_uint8 *pIn_buf_next,
1646                               size_t *pIn_buf_size, mz_uint8 *pOut_buf_start,
1647                               mz_uint8 *pOut_buf_next, size_t *pOut_buf_size,
1648                               const mz_uint32 decomp_flags);
1649 
1650 // Internal/private bits follow.
1651 enum {
1652   TINFL_MAX_HUFF_TABLES = 3,
1653   TINFL_MAX_HUFF_SYMBOLS_0 = 288,
1654   TINFL_MAX_HUFF_SYMBOLS_1 = 32,
1655   TINFL_MAX_HUFF_SYMBOLS_2 = 19,
1656   TINFL_FAST_LOOKUP_BITS = 10,
1657   TINFL_FAST_LOOKUP_SIZE = 1 << TINFL_FAST_LOOKUP_BITS
1658 };
1659 
1660 typedef struct {
1661   mz_uint8 m_code_size[TINFL_MAX_HUFF_SYMBOLS_0];
1662   mz_int16 m_look_up[TINFL_FAST_LOOKUP_SIZE],
1663       m_tree[TINFL_MAX_HUFF_SYMBOLS_0 * 2];
1664 } tinfl_huff_table;
1665 
1666 #if MINIZ_HAS_64BIT_REGISTERS
1667 #define TINFL_USE_64BIT_BITBUF 1
1668 #endif
1669 
1670 #if TINFL_USE_64BIT_BITBUF
1671 typedef mz_uint64 tinfl_bit_buf_t;
1672 #define TINFL_BITBUF_SIZE (64)
1673 #else
1674 typedef mz_uint32 tinfl_bit_buf_t;
1675 #define TINFL_BITBUF_SIZE (32)
1676 #endif
1677 
1678 struct tinfl_decompressor_tag {
1679   mz_uint32 m_state, m_num_bits, m_zhdr0, m_zhdr1, m_z_adler32, m_final, m_type,
1680       m_check_adler32, m_dist, m_counter, m_num_extra,
1681       m_table_sizes[TINFL_MAX_HUFF_TABLES];
1682   tinfl_bit_buf_t m_bit_buf;
1683   size_t m_dist_from_out_buf_start;
1684   tinfl_huff_table m_tables[TINFL_MAX_HUFF_TABLES];
1685   mz_uint8 m_raw_header[4],
1686       m_len_codes[TINFL_MAX_HUFF_SYMBOLS_0 + TINFL_MAX_HUFF_SYMBOLS_1 + 137];
1687 };
1688 
1689 // ------------------- Low-level Compression API Definitions
1690 
1691 // Set TDEFL_LESS_MEMORY to 1 to use less memory (compression will be slightly
1692 // slower, and raw/dynamic blocks will be output more frequently).
1693 #define TDEFL_LESS_MEMORY 0
1694 
1695 // tdefl_init() compression flags logically OR'd together (low 12 bits contain
1696 // the max. number of probes per dictionary search):
1697 // TDEFL_DEFAULT_MAX_PROBES: The compressor defaults to 128 dictionary probes
1698 // per dictionary search. 0=Huffman only, 1=Huffman+LZ (fastest/crap
1699 // compression), 4095=Huffman+LZ (slowest/best compression).
1700 enum {
1701   TDEFL_HUFFMAN_ONLY = 0,
1702   TDEFL_DEFAULT_MAX_PROBES = 128,
1703   TDEFL_MAX_PROBES_MASK = 0xFFF
1704 };
1705 
1706 // TDEFL_WRITE_ZLIB_HEADER: If set, the compressor outputs a zlib header before
1707 // the deflate data, and the Adler-32 of the source data at the end. Otherwise,
1708 // you'll get raw deflate data.
1709 // TDEFL_COMPUTE_ADLER32: Always compute the adler-32 of the input data (even
1710 // when not writing zlib headers).
1711 // TDEFL_GREEDY_PARSING_FLAG: Set to use faster greedy parsing, instead of more
1712 // efficient lazy parsing.
1713 // TDEFL_NONDETERMINISTIC_PARSING_FLAG: Enable to decrease the compressor's
1714 // initialization time to the minimum, but the output may vary from run to run
1715 // given the same input (depending on the contents of memory).
1716 // TDEFL_RLE_MATCHES: Only look for RLE matches (matches with a distance of 1)
1717 // TDEFL_FILTER_MATCHES: Discards matches <= 5 chars if enabled.
1718 // TDEFL_FORCE_ALL_STATIC_BLOCKS: Disable usage of optimized Huffman tables.
1719 // TDEFL_FORCE_ALL_RAW_BLOCKS: Only use raw (uncompressed) deflate blocks.
1720 // The low 12 bits are reserved to control the max # of hash probes per
1721 // dictionary lookup (see TDEFL_MAX_PROBES_MASK).
1722 enum {
1723   TDEFL_WRITE_ZLIB_HEADER = 0x01000,
1724   TDEFL_COMPUTE_ADLER32 = 0x02000,
1725   TDEFL_GREEDY_PARSING_FLAG = 0x04000,
1726   TDEFL_NONDETERMINISTIC_PARSING_FLAG = 0x08000,
1727   TDEFL_RLE_MATCHES = 0x10000,
1728   TDEFL_FILTER_MATCHES = 0x20000,
1729   TDEFL_FORCE_ALL_STATIC_BLOCKS = 0x40000,
1730   TDEFL_FORCE_ALL_RAW_BLOCKS = 0x80000
1731 };
1732 
1733 // High level compression functions:
1734 // tdefl_compress_mem_to_heap() compresses a block in memory to a heap block
1735 // allocated via malloc().
1736 // On entry:
1737 //  pSrc_buf, src_buf_len: Pointer and size of source block to compress.
1738 //  flags: The max match finder probes (default is 128) logically OR'd against
1739 //  the above flags. Higher probes are slower but improve compression.
1740 // On return:
1741 //  Function returns a pointer to the compressed data, or NULL on failure.
1742 //  *pOut_len will be set to the compressed data's size, which could be larger
1743 //  than src_buf_len on uncompressible data.
1744 //  The caller must free() the returned block when it's no longer needed.
1745 void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len,
1746                                  size_t *pOut_len, int flags);
1747 
1748 // tdefl_compress_mem_to_mem() compresses a block in memory to another block in
1749 // memory.
1750 // Returns 0 on failure.
1751 size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len,
1752                                  const void *pSrc_buf, size_t src_buf_len,
1753                                  int flags);
1754 
1755 // Compresses an image to a compressed PNG file in memory.
1756 // On entry:
1757 //  pImage, w, h, and num_chans describe the image to compress. num_chans may be
1758 //  1, 2, 3, or 4.
1759 //  The image pitch in bytes per scanline will be w*num_chans. The leftmost
1760 //  pixel on the top scanline is stored first in memory.
1761 //  level may range from [0,10], use MZ_NO_COMPRESSION, MZ_BEST_SPEED,
1762 //  MZ_BEST_COMPRESSION, etc. or a decent default is MZ_DEFAULT_LEVEL
1763 //  If flip is true, the image will be flipped on the Y axis (useful for OpenGL
1764 //  apps).
1765 // On return:
1766 //  Function returns a pointer to the compressed data, or NULL on failure.
1767 //  *pLen_out will be set to the size of the PNG image file.
1768 //  The caller must mz_free() the returned heap block (which will typically be
1769 //  larger than *pLen_out) when it's no longer needed.
1770 void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w,
1771                                                  int h, int num_chans,
1772                                                  size_t *pLen_out,
1773                                                  mz_uint level, mz_bool flip);
1774 void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h,
1775                                               int num_chans, size_t *pLen_out);
1776 
1777 // Output stream interface. The compressor uses this interface to write
1778 // compressed data. It'll typically be called TDEFL_OUT_BUF_SIZE at a time.
1779 typedef mz_bool (*tdefl_put_buf_func_ptr)(const void *pBuf, int len,
1780                                           void *pUser);
1781 
1782 // tdefl_compress_mem_to_output() compresses a block to an output stream. The
1783 // above helpers use this function internally.
1784 mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len,
1785                                      tdefl_put_buf_func_ptr pPut_buf_func,
1786                                      void *pPut_buf_user, int flags);
1787 
1788 enum {
1789   TDEFL_MAX_HUFF_TABLES = 3,
1790   TDEFL_MAX_HUFF_SYMBOLS_0 = 288,
1791   TDEFL_MAX_HUFF_SYMBOLS_1 = 32,
1792   TDEFL_MAX_HUFF_SYMBOLS_2 = 19,
1793   TDEFL_LZ_DICT_SIZE = 32768,
1794   TDEFL_LZ_DICT_SIZE_MASK = TDEFL_LZ_DICT_SIZE - 1,
1795   TDEFL_MIN_MATCH_LEN = 3,
1796   TDEFL_MAX_MATCH_LEN = 258
1797 };
1798 
1799 // TDEFL_OUT_BUF_SIZE MUST be large enough to hold a single entire compressed
1800 // output block (using static/fixed Huffman codes).
1801 #if TDEFL_LESS_MEMORY
1802 enum {
1803   TDEFL_LZ_CODE_BUF_SIZE = 24 * 1024,
1804   TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13) / 10,
1805   TDEFL_MAX_HUFF_SYMBOLS = 288,
1806   TDEFL_LZ_HASH_BITS = 12,
1807   TDEFL_LEVEL1_HASH_SIZE_MASK = 4095,
1808   TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3,
1809   TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS
1810 };
1811 #else
1812 enum {
1813   TDEFL_LZ_CODE_BUF_SIZE = 64 * 1024,
1814   TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13) / 10,
1815   TDEFL_MAX_HUFF_SYMBOLS = 288,
1816   TDEFL_LZ_HASH_BITS = 15,
1817   TDEFL_LEVEL1_HASH_SIZE_MASK = 4095,
1818   TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3,
1819   TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS
1820 };
1821 #endif
1822 
1823 // The low-level tdefl functions below may be used directly if the above helper
1824 // functions aren't flexible enough. The low-level functions don't make any heap
1825 // allocations, unlike the above helper functions.
1826 typedef enum {
1827   TDEFL_STATUS_BAD_PARAM = -2,
1828   TDEFL_STATUS_PUT_BUF_FAILED = -1,
1829   TDEFL_STATUS_OKAY = 0,
1830   TDEFL_STATUS_DONE = 1
1831 } tdefl_status;
1832 
1833 // Must map to MZ_NO_FLUSH, MZ_SYNC_FLUSH, etc. enums
1834 typedef enum {
1835   TDEFL_NO_FLUSH = 0,
1836   TDEFL_SYNC_FLUSH = 2,
1837   TDEFL_FULL_FLUSH = 3,
1838   TDEFL_FINISH = 4
1839 } tdefl_flush;
1840 
1841 // tdefl's compression state structure.
1842 typedef struct {
1843   tdefl_put_buf_func_ptr m_pPut_buf_func;
1844   void *m_pPut_buf_user;
1845   mz_uint m_flags, m_max_probes[2];
1846   int m_greedy_parsing;
1847   mz_uint m_adler32, m_lookahead_pos, m_lookahead_size, m_dict_size;
1848   mz_uint8 *m_pLZ_code_buf, *m_pLZ_flags, *m_pOutput_buf, *m_pOutput_buf_end;
1849   mz_uint m_num_flags_left, m_total_lz_bytes, m_lz_code_buf_dict_pos, m_bits_in,
1850       m_bit_buffer;
1851   mz_uint m_saved_match_dist, m_saved_match_len, m_saved_lit,
1852       m_output_flush_ofs, m_output_flush_remaining, m_finished, m_block_index,
1853       m_wants_to_finish;
1854   tdefl_status m_prev_return_status;
1855   const void *m_pIn_buf;
1856   void *m_pOut_buf;
1857   size_t *m_pIn_buf_size, *m_pOut_buf_size;
1858   tdefl_flush m_flush;
1859   const mz_uint8 *m_pSrc;
1860   size_t m_src_buf_left, m_out_buf_ofs;
1861   mz_uint8 m_dict[TDEFL_LZ_DICT_SIZE + TDEFL_MAX_MATCH_LEN - 1];
1862   mz_uint16 m_huff_count[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
1863   mz_uint16 m_huff_codes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
1864   mz_uint8 m_huff_code_sizes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
1865   mz_uint8 m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE];
1866   mz_uint16 m_next[TDEFL_LZ_DICT_SIZE];
1867   mz_uint16 m_hash[TDEFL_LZ_HASH_SIZE];
1868   mz_uint8 m_output_buf[TDEFL_OUT_BUF_SIZE];
1869 } tdefl_compressor;
1870 
1871 // Initializes the compressor.
1872 // There is no corresponding deinit() function because the tdefl API's do not
1873 // dynamically allocate memory.
1874 // pBut_buf_func: If NULL, output data will be supplied to the specified
1875 // callback. In this case, the user should call the tdefl_compress_buffer() API
1876 // for compression.
1877 // If pBut_buf_func is NULL the user should always call the tdefl_compress()
1878 // API.
1879 // flags: See the above enums (TDEFL_HUFFMAN_ONLY, TDEFL_WRITE_ZLIB_HEADER,
1880 // etc.)
1881 tdefl_status tdefl_init(tdefl_compressor *d,
1882                         tdefl_put_buf_func_ptr pPut_buf_func,
1883                         void *pPut_buf_user, int flags);
1884 
1885 // Compresses a block of data, consuming as much of the specified input buffer
1886 // as possible, and writing as much compressed data to the specified output
1887 // buffer as possible.
1888 tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf,
1889                             size_t *pIn_buf_size, void *pOut_buf,
1890                             size_t *pOut_buf_size, tdefl_flush flush);
1891 
1892 // tdefl_compress_buffer() is only usable when the tdefl_init() is called with a
1893 // non-NULL tdefl_put_buf_func_ptr.
1894 // tdefl_compress_buffer() always consumes the entire input buffer.
1895 tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf,
1896                                    size_t in_buf_size, tdefl_flush flush);
1897 
1898 tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d);
1899 mz_uint32 tdefl_get_adler32(tdefl_compressor *d);
1900 
1901 // Can't use tdefl_create_comp_flags_from_zip_params if MINIZ_NO_ZLIB_APIS isn't
1902 // defined, because it uses some of its macros.
1903 #ifndef MINIZ_NO_ZLIB_APIS
1904 // Create tdefl_compress() flags given zlib-style compression parameters.
1905 // level may range from [0,10] (where 10 is absolute max compression, but may be
1906 // much slower on some files)
1907 // window_bits may be -15 (raw deflate) or 15 (zlib)
1908 // strategy may be either MZ_DEFAULT_STRATEGY, MZ_FILTERED, MZ_HUFFMAN_ONLY,
1909 // MZ_RLE, or MZ_FIXED
1910 mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits,
1911                                                 int strategy);
1912 #endif  // #ifndef MINIZ_NO_ZLIB_APIS
1913 
1914 #ifdef __cplusplus
1915 }
1916 #endif
1917 
1918 #endif  // MINIZ_HEADER_INCLUDED
1919 
1920 // ------------------- End of Header: Implementation follows. (If you only want
1921 // the header, define MINIZ_HEADER_FILE_ONLY.)
1922 
1923 #ifndef MINIZ_HEADER_FILE_ONLY
1924 
1925 typedef unsigned char mz_validate_uint16[sizeof(mz_uint16) == 2 ? 1 : -1];
1926 typedef unsigned char mz_validate_uint32[sizeof(mz_uint32) == 4 ? 1 : -1];
1927 typedef unsigned char mz_validate_uint64[sizeof(mz_uint64) == 8 ? 1 : -1];
1928 
1929 #define MZ_ASSERT(x) TEXR_ASSERT(x)
1930 
1931 #ifdef MINIZ_NO_MALLOC
1932 #define MZ_MALLOC(x) NULL
1933 #define MZ_FREE(x) (void)x, ((void)0)
1934 #define MZ_REALLOC(p, x) NULL
1935 #else
1936 #define MZ_MALLOC(x) malloc(x)
1937 #define MZ_FREE(x) free(x)
1938 #define MZ_REALLOC(p, x) realloc(p, x)
1939 #endif
1940 
1941 #define MZ_MAX(a, b) (((a) > (b)) ? (a) : (b))
1942 #define MZ_MIN(a, b) (((a) < (b)) ? (a) : (b))
1943 #define MZ_CLEAR_OBJ(obj) memset(&(obj), 0, sizeof(obj))
1944 
1945 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
1946 #define MZ_READ_LE16(p) *((const mz_uint16 *)(p))
1947 #define MZ_READ_LE32(p) *((const mz_uint32 *)(p))
1948 #else
1949 #define MZ_READ_LE16(p)                      \
1950   ((mz_uint32)(((const mz_uint8 *)(p))[0]) | \
1951    ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U))
1952 #define MZ_READ_LE32(p)                               \
1953   ((mz_uint32)(((const mz_uint8 *)(p))[0]) |          \
1954    ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U) |  \
1955    ((mz_uint32)(((const mz_uint8 *)(p))[2]) << 16U) | \
1956    ((mz_uint32)(((const mz_uint8 *)(p))[3]) << 24U))
1957 #endif
1958 
1959 #ifdef _MSC_VER
1960 #define MZ_FORCEINLINE __forceinline
1961 #elif defined(__GNUC__)
1962 #define MZ_FORCEINLINE inline __attribute__((__always_inline__))
1963 #else
1964 #define MZ_FORCEINLINE inline
1965 #endif
1966 
1967 #ifdef __cplusplus
1968 extern "C" {
1969 #endif
1970 
1971 // ------------------- zlib-style API's
1972 
mz_adler32(mz_ulong adler,const unsigned char * ptr,size_t buf_len)1973 mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len) {
1974   mz_uint32 i, s1 = (mz_uint32)(adler & 0xffff), s2 = (mz_uint32)(adler >> 16);
1975   size_t block_len = buf_len % 5552;
1976   if (!ptr) return MZ_ADLER32_INIT;
1977   while (buf_len) {
1978     for (i = 0; i + 7 < block_len; i += 8, ptr += 8) {
1979       s1 += ptr[0], s2 += s1;
1980       s1 += ptr[1], s2 += s1;
1981       s1 += ptr[2], s2 += s1;
1982       s1 += ptr[3], s2 += s1;
1983       s1 += ptr[4], s2 += s1;
1984       s1 += ptr[5], s2 += s1;
1985       s1 += ptr[6], s2 += s1;
1986       s1 += ptr[7], s2 += s1;
1987     }
1988     for (; i < block_len; ++i) s1 += *ptr++, s2 += s1;
1989     s1 %= 65521U, s2 %= 65521U;
1990     buf_len -= block_len;
1991     block_len = 5552;
1992   }
1993   return (s2 << 16) + s1;
1994 }
1995 
1996 // Karl Malbrain's compact CRC-32. See "A compact CCITT crc16 and crc32 C
1997 // implementation that balances processor cache usage against speed":
1998 // http://www.geocities.com/malbrain/
mz_crc32(mz_ulong crc,const mz_uint8 * ptr,size_t buf_len)1999 mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len) {
2000   static const mz_uint32 s_crc32[16] = {
2001       0,          0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4,
2002       0x4db26158, 0x5005713c, 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
2003       0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c};
2004   mz_uint32 crcu32 = (mz_uint32)crc;
2005   if (!ptr) return MZ_CRC32_INIT;
2006   crcu32 = ~crcu32;
2007   while (buf_len--) {
2008     mz_uint8 b = *ptr++;
2009     crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)];
2010     crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)];
2011   }
2012   return ~crcu32;
2013 }
2014 
mz_free(void * p)2015 void mz_free(void *p) { MZ_FREE(p); }
2016 
2017 #ifndef MINIZ_NO_ZLIB_APIS
2018 
def_alloc_func(void * opaque,size_t items,size_t size)2019 static void *def_alloc_func(void *opaque, size_t items, size_t size) {
2020   (void)opaque, (void)items, (void)size;
2021   return MZ_MALLOC(items * size);
2022 }
def_free_func(void * opaque,void * address)2023 static void def_free_func(void *opaque, void *address) {
2024   (void)opaque, (void)address;
2025   MZ_FREE(address);
2026 }
2027 // static void *def_realloc_func(void *opaque, void *address, size_t items,
2028 //                              size_t size) {
2029 //  (void)opaque, (void)address, (void)items, (void)size;
2030 //  return MZ_REALLOC(address, items * size);
2031 //}
2032 
mz_version(void)2033 const char *mz_version(void) { return MZ_VERSION; }
2034 
mz_deflateInit(mz_streamp pStream,int level)2035 int mz_deflateInit(mz_streamp pStream, int level) {
2036   return mz_deflateInit2(pStream, level, MZ_DEFLATED, MZ_DEFAULT_WINDOW_BITS, 9,
2037                          MZ_DEFAULT_STRATEGY);
2038 }
2039 
mz_deflateInit2(mz_streamp pStream,int level,int method,int window_bits,int mem_level,int strategy)2040 int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits,
2041                     int mem_level, int strategy) {
2042   tdefl_compressor *pComp;
2043   mz_uint comp_flags =
2044       TDEFL_COMPUTE_ADLER32 |
2045       tdefl_create_comp_flags_from_zip_params(level, window_bits, strategy);
2046 
2047   if (!pStream) return MZ_STREAM_ERROR;
2048   if ((method != MZ_DEFLATED) || ((mem_level < 1) || (mem_level > 9)) ||
2049       ((window_bits != MZ_DEFAULT_WINDOW_BITS) &&
2050        (-window_bits != MZ_DEFAULT_WINDOW_BITS)))
2051     return MZ_PARAM_ERROR;
2052 
2053   pStream->data_type = 0;
2054   pStream->adler = MZ_ADLER32_INIT;
2055   pStream->msg = NULL;
2056   pStream->reserved = 0;
2057   pStream->total_in = 0;
2058   pStream->total_out = 0;
2059   if (!pStream->zalloc) pStream->zalloc = def_alloc_func;
2060   if (!pStream->zfree) pStream->zfree = def_free_func;
2061 
2062   pComp = (tdefl_compressor *)pStream->zalloc(pStream->opaque, 1,
2063                                               sizeof(tdefl_compressor));
2064   if (!pComp) return MZ_MEM_ERROR;
2065 
2066   pStream->state = (struct mz_internal_state *)pComp;
2067 
2068   if (tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY) {
2069     mz_deflateEnd(pStream);
2070     return MZ_PARAM_ERROR;
2071   }
2072 
2073   return MZ_OK;
2074 }
2075 
mz_deflateReset(mz_streamp pStream)2076 int mz_deflateReset(mz_streamp pStream) {
2077   if ((!pStream) || (!pStream->state) || (!pStream->zalloc) ||
2078       (!pStream->zfree))
2079     return MZ_STREAM_ERROR;
2080   pStream->total_in = pStream->total_out = 0;
2081   tdefl_init((tdefl_compressor *)pStream->state, NULL, NULL,
2082              ((tdefl_compressor *)pStream->state)->m_flags);
2083   return MZ_OK;
2084 }
2085 
mz_deflate(mz_streamp pStream,int flush)2086 int mz_deflate(mz_streamp pStream, int flush) {
2087   size_t in_bytes, out_bytes;
2088   mz_ulong orig_total_in, orig_total_out;
2089   int mz_status = MZ_OK;
2090 
2091   if ((!pStream) || (!pStream->state) || (flush < 0) || (flush > MZ_FINISH) ||
2092       (!pStream->next_out))
2093     return MZ_STREAM_ERROR;
2094   if (!pStream->avail_out) return MZ_BUF_ERROR;
2095 
2096   if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH;
2097 
2098   if (((tdefl_compressor *)pStream->state)->m_prev_return_status ==
2099       TDEFL_STATUS_DONE)
2100     return (flush == MZ_FINISH) ? MZ_STREAM_END : MZ_BUF_ERROR;
2101 
2102   orig_total_in = pStream->total_in;
2103   orig_total_out = pStream->total_out;
2104   for (;;) {
2105     tdefl_status defl_status;
2106     in_bytes = pStream->avail_in;
2107     out_bytes = pStream->avail_out;
2108 
2109     defl_status = tdefl_compress((tdefl_compressor *)pStream->state,
2110                                  pStream->next_in, &in_bytes, pStream->next_out,
2111                                  &out_bytes, (tdefl_flush)flush);
2112     pStream->next_in += (mz_uint)in_bytes;
2113     pStream->avail_in -= (mz_uint)in_bytes;
2114     pStream->total_in += (mz_uint)in_bytes;
2115     pStream->adler = tdefl_get_adler32((tdefl_compressor *)pStream->state);
2116 
2117     pStream->next_out += (mz_uint)out_bytes;
2118     pStream->avail_out -= (mz_uint)out_bytes;
2119     pStream->total_out += (mz_uint)out_bytes;
2120 
2121     if (defl_status < 0) {
2122       mz_status = MZ_STREAM_ERROR;
2123       break;
2124     } else if (defl_status == TDEFL_STATUS_DONE) {
2125       mz_status = MZ_STREAM_END;
2126       break;
2127     } else if (!pStream->avail_out)
2128       break;
2129     else if ((!pStream->avail_in) && (flush != MZ_FINISH)) {
2130       if ((flush) || (pStream->total_in != orig_total_in) ||
2131           (pStream->total_out != orig_total_out))
2132         break;
2133       return MZ_BUF_ERROR;  // Can't make forward progress without some input.
2134     }
2135   }
2136   return mz_status;
2137 }
2138 
mz_deflateEnd(mz_streamp pStream)2139 int mz_deflateEnd(mz_streamp pStream) {
2140   if (!pStream) return MZ_STREAM_ERROR;
2141   if (pStream->state) {
2142     pStream->zfree(pStream->opaque, pStream->state);
2143     pStream->state = NULL;
2144   }
2145   return MZ_OK;
2146 }
2147 
mz_deflateBound(mz_streamp pStream,mz_ulong source_len)2148 mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len) {
2149   (void)pStream;
2150   // This is really over conservative. (And lame, but it's actually pretty
2151   // tricky to compute a true upper bound given the way tdefl's blocking works.)
2152   return MZ_MAX(128 + (source_len * 110) / 100,
2153                 128 + source_len + ((source_len / (31 * 1024)) + 1) * 5);
2154 }
2155 
mz_compress2(unsigned char * pDest,mz_ulong * pDest_len,const unsigned char * pSource,mz_ulong source_len,int level)2156 int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len,
2157                  const unsigned char *pSource, mz_ulong source_len, int level) {
2158   int status;
2159   mz_stream stream;
2160   memset(&stream, 0, sizeof(stream));
2161 
2162   // In case mz_ulong is 64-bits (argh I hate longs).
2163   if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR;
2164 
2165   stream.next_in = pSource;
2166   stream.avail_in = (mz_uint32)source_len;
2167   stream.next_out = pDest;
2168   stream.avail_out = (mz_uint32)*pDest_len;
2169 
2170   status = mz_deflateInit(&stream, level);
2171   if (status != MZ_OK) return status;
2172 
2173   status = mz_deflate(&stream, MZ_FINISH);
2174   if (status != MZ_STREAM_END) {
2175     mz_deflateEnd(&stream);
2176     return (status == MZ_OK) ? MZ_BUF_ERROR : status;
2177   }
2178 
2179   *pDest_len = stream.total_out;
2180   return mz_deflateEnd(&stream);
2181 }
2182 
mz_compress(unsigned char * pDest,mz_ulong * pDest_len,const unsigned char * pSource,mz_ulong source_len)2183 int mz_compress(unsigned char *pDest, mz_ulong *pDest_len,
2184                 const unsigned char *pSource, mz_ulong source_len) {
2185   return mz_compress2(pDest, pDest_len, pSource, source_len,
2186                       MZ_DEFAULT_COMPRESSION);
2187 }
2188 
mz_compressBound(mz_ulong source_len)2189 mz_ulong mz_compressBound(mz_ulong source_len) {
2190   return mz_deflateBound(NULL, source_len);
2191 }
2192 
2193 typedef struct {
2194   tinfl_decompressor m_decomp;
2195   mz_uint m_dict_ofs, m_dict_avail, m_first_call, m_has_flushed;
2196   int m_window_bits;
2197   mz_uint8 m_dict[TINFL_LZ_DICT_SIZE];
2198   tinfl_status m_last_status;
2199 } inflate_state;
2200 
mz_inflateInit2(mz_streamp pStream,int window_bits)2201 int mz_inflateInit2(mz_streamp pStream, int window_bits) {
2202   inflate_state *pDecomp;
2203   if (!pStream) return MZ_STREAM_ERROR;
2204   if ((window_bits != MZ_DEFAULT_WINDOW_BITS) &&
2205       (-window_bits != MZ_DEFAULT_WINDOW_BITS))
2206     return MZ_PARAM_ERROR;
2207 
2208   pStream->data_type = 0;
2209   pStream->adler = 0;
2210   pStream->msg = NULL;
2211   pStream->total_in = 0;
2212   pStream->total_out = 0;
2213   pStream->reserved = 0;
2214   if (!pStream->zalloc) pStream->zalloc = def_alloc_func;
2215   if (!pStream->zfree) pStream->zfree = def_free_func;
2216 
2217   pDecomp = (inflate_state *)pStream->zalloc(pStream->opaque, 1,
2218                                              sizeof(inflate_state));
2219   if (!pDecomp) return MZ_MEM_ERROR;
2220 
2221   pStream->state = (struct mz_internal_state *)pDecomp;
2222 
2223   tinfl_init(&pDecomp->m_decomp);
2224   pDecomp->m_dict_ofs = 0;
2225   pDecomp->m_dict_avail = 0;
2226   pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT;
2227   pDecomp->m_first_call = 1;
2228   pDecomp->m_has_flushed = 0;
2229   pDecomp->m_window_bits = window_bits;
2230 
2231   return MZ_OK;
2232 }
2233 
mz_inflateInit(mz_streamp pStream)2234 int mz_inflateInit(mz_streamp pStream) {
2235   return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS);
2236 }
2237 
mz_inflate(mz_streamp pStream,int flush)2238 int mz_inflate(mz_streamp pStream, int flush) {
2239   inflate_state *pState;
2240   mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32;
2241   size_t in_bytes, out_bytes, orig_avail_in;
2242   tinfl_status status;
2243 
2244   if ((!pStream) || (!pStream->state)) return MZ_STREAM_ERROR;
2245   if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH;
2246   if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH))
2247     return MZ_STREAM_ERROR;
2248 
2249   pState = (inflate_state *)pStream->state;
2250   if (pState->m_window_bits > 0) decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER;
2251   orig_avail_in = pStream->avail_in;
2252 
2253   first_call = pState->m_first_call;
2254   pState->m_first_call = 0;
2255   if (pState->m_last_status < 0) return MZ_DATA_ERROR;
2256 
2257   if (pState->m_has_flushed && (flush != MZ_FINISH)) return MZ_STREAM_ERROR;
2258   pState->m_has_flushed |= (flush == MZ_FINISH);
2259 
2260   if ((flush == MZ_FINISH) && (first_call)) {
2261     // MZ_FINISH on the first call implies that the input and output buffers are
2262     // large enough to hold the entire compressed/decompressed file.
2263     decomp_flags |= TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF;
2264     in_bytes = pStream->avail_in;
2265     out_bytes = pStream->avail_out;
2266     status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes,
2267                               pStream->next_out, pStream->next_out, &out_bytes,
2268                               decomp_flags);
2269     pState->m_last_status = status;
2270     pStream->next_in += (mz_uint)in_bytes;
2271     pStream->avail_in -= (mz_uint)in_bytes;
2272     pStream->total_in += (mz_uint)in_bytes;
2273     pStream->adler = tinfl_get_adler32(&pState->m_decomp);
2274     pStream->next_out += (mz_uint)out_bytes;
2275     pStream->avail_out -= (mz_uint)out_bytes;
2276     pStream->total_out += (mz_uint)out_bytes;
2277 
2278     if (status < 0)
2279       return MZ_DATA_ERROR;
2280     else if (status != TINFL_STATUS_DONE) {
2281       pState->m_last_status = TINFL_STATUS_FAILED;
2282       return MZ_BUF_ERROR;
2283     }
2284     return MZ_STREAM_END;
2285   }
2286   // flush != MZ_FINISH then we must assume there's more input.
2287   if (flush != MZ_FINISH) decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT;
2288 
2289   if (pState->m_dict_avail) {
2290     n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
2291     memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
2292     pStream->next_out += n;
2293     pStream->avail_out -= n;
2294     pStream->total_out += n;
2295     pState->m_dict_avail -= n;
2296     pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
2297     return ((pState->m_last_status == TINFL_STATUS_DONE) &&
2298             (!pState->m_dict_avail))
2299                ? MZ_STREAM_END
2300                : MZ_OK;
2301   }
2302 
2303   for (;;) {
2304     in_bytes = pStream->avail_in;
2305     out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs;
2306 
2307     status = tinfl_decompress(
2308         &pState->m_decomp, pStream->next_in, &in_bytes, pState->m_dict,
2309         pState->m_dict + pState->m_dict_ofs, &out_bytes, decomp_flags);
2310     pState->m_last_status = status;
2311 
2312     pStream->next_in += (mz_uint)in_bytes;
2313     pStream->avail_in -= (mz_uint)in_bytes;
2314     pStream->total_in += (mz_uint)in_bytes;
2315     pStream->adler = tinfl_get_adler32(&pState->m_decomp);
2316 
2317     pState->m_dict_avail = (mz_uint)out_bytes;
2318 
2319     n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
2320     memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
2321     pStream->next_out += n;
2322     pStream->avail_out -= n;
2323     pStream->total_out += n;
2324     pState->m_dict_avail -= n;
2325     pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
2326 
2327     if (status < 0)
2328       return MZ_DATA_ERROR;  // Stream is corrupted (there could be some
2329     // uncompressed data left in the output dictionary -
2330     // oh well).
2331     else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in))
2332       return MZ_BUF_ERROR;  // Signal caller that we can't make forward progress
2333                             // without supplying more input or by setting flush
2334                             // to MZ_FINISH.
2335     else if (flush == MZ_FINISH) {
2336       // The output buffer MUST be large to hold the remaining uncompressed data
2337       // when flush==MZ_FINISH.
2338       if (status == TINFL_STATUS_DONE)
2339         return pState->m_dict_avail ? MZ_BUF_ERROR : MZ_STREAM_END;
2340       // status here must be TINFL_STATUS_HAS_MORE_OUTPUT, which means there's
2341       // at least 1 more byte on the way. If there's no more room left in the
2342       // output buffer then something is wrong.
2343       else if (!pStream->avail_out)
2344         return MZ_BUF_ERROR;
2345     } else if ((status == TINFL_STATUS_DONE) || (!pStream->avail_in) ||
2346                (!pStream->avail_out) || (pState->m_dict_avail))
2347       break;
2348   }
2349 
2350   return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail))
2351              ? MZ_STREAM_END
2352              : MZ_OK;
2353 }
2354 
mz_inflateEnd(mz_streamp pStream)2355 int mz_inflateEnd(mz_streamp pStream) {
2356   if (!pStream) return MZ_STREAM_ERROR;
2357   if (pStream->state) {
2358     pStream->zfree(pStream->opaque, pStream->state);
2359     pStream->state = NULL;
2360   }
2361   return MZ_OK;
2362 }
2363 
mz_uncompress(unsigned char * pDest,mz_ulong * pDest_len,const unsigned char * pSource,mz_ulong source_len)2364 int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len,
2365                   const unsigned char *pSource, mz_ulong source_len) {
2366   mz_stream stream;
2367   int status;
2368   memset(&stream, 0, sizeof(stream));
2369 
2370   // In case mz_ulong is 64-bits (argh I hate longs).
2371   if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR;
2372 
2373   stream.next_in = pSource;
2374   stream.avail_in = (mz_uint32)source_len;
2375   stream.next_out = pDest;
2376   stream.avail_out = (mz_uint32)*pDest_len;
2377 
2378   status = mz_inflateInit(&stream);
2379   if (status != MZ_OK) return status;
2380 
2381   status = mz_inflate(&stream, MZ_FINISH);
2382   if (status != MZ_STREAM_END) {
2383     mz_inflateEnd(&stream);
2384     return ((status == MZ_BUF_ERROR) && (!stream.avail_in)) ? MZ_DATA_ERROR
2385                                                             : status;
2386   }
2387   *pDest_len = stream.total_out;
2388 
2389   return mz_inflateEnd(&stream);
2390 }
2391 
mz_error(int err)2392 const char *mz_error(int err) {
2393   static struct {
2394     int m_err;
2395     const char *m_pDesc;
2396   } s_error_descs[] = {{MZ_OK, ""},
2397                        {MZ_STREAM_END, "stream end"},
2398                        {MZ_NEED_DICT, "need dictionary"},
2399                        {MZ_ERRNO, "file error"},
2400                        {MZ_STREAM_ERROR, "stream error"},
2401                        {MZ_DATA_ERROR, "data error"},
2402                        {MZ_MEM_ERROR, "out of memory"},
2403                        {MZ_BUF_ERROR, "buf error"},
2404                        {MZ_VERSION_ERROR, "version error"},
2405                        {MZ_PARAM_ERROR, "parameter error"}};
2406   mz_uint i;
2407   for (i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i)
2408     if (s_error_descs[i].m_err == err) return s_error_descs[i].m_pDesc;
2409   return NULL;
2410 }
2411 
2412 #endif  // MINIZ_NO_ZLIB_APIS
2413 
2414 // ------------------- Low-level Decompression (completely independent from all
2415 // compression API's)
2416 
2417 #define TINFL_MEMCPY(d, s, l) memcpy(d, s, l)
2418 #define TINFL_MEMSET(p, c, l) memset(p, c, l)
2419 
2420 #define TINFL_CR_BEGIN  \
2421   switch (r->m_state) { \
2422     case 0:
2423 #define TINFL_CR_RETURN(state_index, result) \
2424   do {                                       \
2425     status = result;                         \
2426     r->m_state = state_index;                \
2427     goto common_exit;                        \
2428     case state_index:;                       \
2429   }                                          \
2430   MZ_MACRO_END
2431 #define TINFL_CR_RETURN_FOREVER(state_index, result) \
2432   do {                                               \
2433     for (;;) {                                       \
2434       TINFL_CR_RETURN(state_index, result);          \
2435     }                                                \
2436   }                                                  \
2437   MZ_MACRO_END
2438 #define TINFL_CR_FINISH }
2439 
2440 // TODO: If the caller has indicated that there's no more input, and we attempt
2441 // to read beyond the input buf, then something is wrong with the input because
2442 // the inflator never
2443 // reads ahead more than it needs to. Currently TINFL_GET_BYTE() pads the end of
2444 // the stream with 0's in this scenario.
2445 #define TINFL_GET_BYTE(state_index, c)                                 \
2446   do {                                                                 \
2447     if (pIn_buf_cur >= pIn_buf_end) {                                  \
2448       for (;;) {                                                       \
2449         if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) {                \
2450           TINFL_CR_RETURN(state_index, TINFL_STATUS_NEEDS_MORE_INPUT); \
2451           if (pIn_buf_cur < pIn_buf_end) {                             \
2452             c = *pIn_buf_cur++;                                        \
2453             break;                                                     \
2454           }                                                            \
2455         } else {                                                       \
2456           c = 0;                                                       \
2457           break;                                                       \
2458         }                                                              \
2459       }                                                                \
2460     } else                                                             \
2461       c = *pIn_buf_cur++;                                              \
2462   }                                                                    \
2463   MZ_MACRO_END
2464 
2465 #define TINFL_NEED_BITS(state_index, n)            \
2466   do {                                             \
2467     mz_uint c;                                     \
2468     TINFL_GET_BYTE(state_index, c);                \
2469     bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); \
2470     num_bits += 8;                                 \
2471   } while (num_bits < (mz_uint)(n))
2472 #define TINFL_SKIP_BITS(state_index, n) \
2473   do {                                  \
2474     if (num_bits < (mz_uint)(n)) {      \
2475       TINFL_NEED_BITS(state_index, n);  \
2476     }                                   \
2477     bit_buf >>= (n);                    \
2478     num_bits -= (n);                    \
2479   }                                     \
2480   MZ_MACRO_END
2481 #define TINFL_GET_BITS(state_index, b, n) \
2482   do {                                    \
2483     if (num_bits < (mz_uint)(n)) {        \
2484       TINFL_NEED_BITS(state_index, n);    \
2485     }                                     \
2486     b = bit_buf & ((1 << (n)) - 1);       \
2487     bit_buf >>= (n);                      \
2488     num_bits -= (n);                      \
2489   }                                       \
2490   MZ_MACRO_END
2491 
2492 // TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes
2493 // remaining in the input buffer falls below 2.
2494 // It reads just enough bytes from the input stream that are needed to decode
2495 // the next Huffman code (and absolutely no more). It works by trying to fully
2496 // decode a
2497 // Huffman code by using whatever bits are currently present in the bit buffer.
2498 // If this fails, it reads another byte, and tries again until it succeeds or
2499 // until the
2500 // bit buffer contains >=15 bits (deflate's max. Huffman code size).
2501 #define TINFL_HUFF_BITBUF_FILL(state_index, pHuff)                     \
2502   do {                                                                 \
2503     temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]; \
2504     if (temp >= 0) {                                                   \
2505       code_len = temp >> 9;                                            \
2506       if ((code_len) && (num_bits >= code_len)) break;                 \
2507     } else if (num_bits > TINFL_FAST_LOOKUP_BITS) {                    \
2508       code_len = TINFL_FAST_LOOKUP_BITS;                               \
2509       do {                                                             \
2510         temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \
2511       } while ((temp < 0) && (num_bits >= (code_len + 1)));            \
2512       if (temp >= 0) break;                                            \
2513     }                                                                  \
2514     TINFL_GET_BYTE(state_index, c);                                    \
2515     bit_buf |= (((tinfl_bit_buf_t)c) << num_bits);                     \
2516     num_bits += 8;                                                     \
2517   } while (num_bits < 15);
2518 
2519 // TINFL_HUFF_DECODE() decodes the next Huffman coded symbol. It's more complex
2520 // than you would initially expect because the zlib API expects the decompressor
2521 // to never read
2522 // beyond the final byte of the deflate stream. (In other words, when this macro
2523 // wants to read another byte from the input, it REALLY needs another byte in
2524 // order to fully
2525 // decode the next Huffman code.) Handling this properly is particularly
2526 // important on raw deflate (non-zlib) streams, which aren't followed by a byte
2527 // aligned adler-32.
2528 // The slow path is only executed at the very end of the input buffer.
2529 #define TINFL_HUFF_DECODE(state_index, sym, pHuff)                             \
2530   do {                                                                         \
2531     int temp;                                                                  \
2532     mz_uint code_len, c;                                                       \
2533     if (num_bits < 15) {                                                       \
2534       if ((pIn_buf_end - pIn_buf_cur) < 2) {                                   \
2535         TINFL_HUFF_BITBUF_FILL(state_index, pHuff);                            \
2536       } else {                                                                 \
2537         bit_buf |= (((tinfl_bit_buf_t)pIn_buf_cur[0]) << num_bits) |           \
2538                    (((tinfl_bit_buf_t)pIn_buf_cur[1]) << (num_bits + 8));      \
2539         pIn_buf_cur += 2;                                                      \
2540         num_bits += 16;                                                        \
2541       }                                                                        \
2542     }                                                                          \
2543     if ((temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= \
2544         0)                                                                     \
2545       code_len = temp >> 9, temp &= 511;                                       \
2546     else {                                                                     \
2547       code_len = TINFL_FAST_LOOKUP_BITS;                                       \
2548       do {                                                                     \
2549         temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)];         \
2550       } while (temp < 0);                                                      \
2551     }                                                                          \
2552     sym = temp;                                                                \
2553     bit_buf >>= code_len;                                                      \
2554     num_bits -= code_len;                                                      \
2555   }                                                                            \
2556   MZ_MACRO_END
2557 
tinfl_decompress(tinfl_decompressor * r,const mz_uint8 * pIn_buf_next,size_t * pIn_buf_size,mz_uint8 * pOut_buf_start,mz_uint8 * pOut_buf_next,size_t * pOut_buf_size,const mz_uint32 decomp_flags)2558 tinfl_status tinfl_decompress(tinfl_decompressor *r,
2559                               const mz_uint8 *pIn_buf_next,
2560                               size_t *pIn_buf_size, mz_uint8 *pOut_buf_start,
2561                               mz_uint8 *pOut_buf_next, size_t *pOut_buf_size,
2562                               const mz_uint32 decomp_flags) {
2563   static const int s_length_base[31] = {
2564       3,  4,  5,  6,  7,  8,  9,  10,  11,  13,  15,  17,  19,  23, 27, 31,
2565       35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0,  0};
2566   static const int s_length_extra[31] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
2567                                          1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4,
2568                                          4, 4, 5, 5, 5, 5, 0, 0, 0};
2569   static const int s_dist_base[32] = {
2570       1,    2,    3,    4,    5,    7,     9,     13,    17,  25,   33,
2571       49,   65,   97,   129,  193,  257,   385,   513,   769, 1025, 1537,
2572       2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 0,   0};
2573   static const int s_dist_extra[32] = {0, 0, 0,  0,  1,  1,  2,  2,  3,  3,
2574                                        4, 4, 5,  5,  6,  6,  7,  7,  8,  8,
2575                                        9, 9, 10, 10, 11, 11, 12, 12, 13, 13};
2576   static const mz_uint8 s_length_dezigzag[19] = {
2577       16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
2578   static const int s_min_table_sizes[3] = {257, 1, 4};
2579 
2580   tinfl_status status = TINFL_STATUS_FAILED;
2581   mz_uint32 num_bits, dist, counter, num_extra;
2582   tinfl_bit_buf_t bit_buf;
2583   const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end =
2584                                                   pIn_buf_next + *pIn_buf_size;
2585   mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end =
2586                                               pOut_buf_next + *pOut_buf_size;
2587   size_t out_buf_size_mask =
2588              (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)
2589                  ? (size_t)-1
2590                  : ((pOut_buf_next - pOut_buf_start) + *pOut_buf_size) - 1,
2591          dist_from_out_buf_start;
2592 
2593   // Ensure the output buffer's size is a power of 2, unless the output buffer
2594   // is large enough to hold the entire output file (in which case it doesn't
2595   // matter).
2596   if (((out_buf_size_mask + 1) & out_buf_size_mask) ||
2597       (pOut_buf_next < pOut_buf_start)) {
2598     *pIn_buf_size = *pOut_buf_size = 0;
2599     return TINFL_STATUS_BAD_PARAM;
2600   }
2601 
2602   num_bits = r->m_num_bits;
2603   bit_buf = r->m_bit_buf;
2604   dist = r->m_dist;
2605   counter = r->m_counter;
2606   num_extra = r->m_num_extra;
2607   dist_from_out_buf_start = r->m_dist_from_out_buf_start;
2608   TINFL_CR_BEGIN
2609 
2610   bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0;
2611   r->m_z_adler32 = r->m_check_adler32 = 1;
2612   if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) {
2613     TINFL_GET_BYTE(1, r->m_zhdr0);
2614     TINFL_GET_BYTE(2, r->m_zhdr1);
2615     counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) ||
2616                (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8));
2617     if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))
2618       counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) ||
2619                   ((out_buf_size_mask + 1) <
2620                    (size_t)(1ULL << (8U + (r->m_zhdr0 >> 4)))));
2621     if (counter) {
2622       TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED);
2623     }
2624   }
2625 
2626   do {
2627     TINFL_GET_BITS(3, r->m_final, 3);
2628     r->m_type = r->m_final >> 1;
2629     if (r->m_type == 0) {
2630       TINFL_SKIP_BITS(5, num_bits & 7);
2631       for (counter = 0; counter < 4; ++counter) {
2632         if (num_bits)
2633           TINFL_GET_BITS(6, r->m_raw_header[counter], 8);
2634         else
2635           TINFL_GET_BYTE(7, r->m_raw_header[counter]);
2636       }
2637       if ((counter = (r->m_raw_header[0] | (r->m_raw_header[1] << 8))) !=
2638           (mz_uint)(0xFFFF ^
2639                     (r->m_raw_header[2] | (r->m_raw_header[3] << 8)))) {
2640         TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED);
2641       }
2642       while ((counter) && (num_bits)) {
2643         TINFL_GET_BITS(51, dist, 8);
2644         while (pOut_buf_cur >= pOut_buf_end) {
2645           TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT);
2646         }
2647         *pOut_buf_cur++ = (mz_uint8)dist;
2648         counter--;
2649       }
2650       while (counter) {
2651         size_t n;
2652         while (pOut_buf_cur >= pOut_buf_end) {
2653           TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT);
2654         }
2655         while (pIn_buf_cur >= pIn_buf_end) {
2656           if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) {
2657             TINFL_CR_RETURN(38, TINFL_STATUS_NEEDS_MORE_INPUT);
2658           } else {
2659             TINFL_CR_RETURN_FOREVER(40, TINFL_STATUS_FAILED);
2660           }
2661         }
2662         n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur),
2663                           (size_t)(pIn_buf_end - pIn_buf_cur)),
2664                    counter);
2665         TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n);
2666         pIn_buf_cur += n;
2667         pOut_buf_cur += n;
2668         counter -= (mz_uint)n;
2669       }
2670     } else if (r->m_type == 3) {
2671       TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED);
2672     } else {
2673       if (r->m_type == 1) {
2674         mz_uint8 *p = r->m_tables[0].m_code_size;
2675         mz_uint i;
2676         r->m_table_sizes[0] = 288;
2677         r->m_table_sizes[1] = 32;
2678         TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32);
2679         for (i = 0; i <= 143; ++i) *p++ = 8;
2680         for (; i <= 255; ++i) *p++ = 9;
2681         for (; i <= 279; ++i) *p++ = 7;
2682         for (; i <= 287; ++i) *p++ = 8;
2683       } else {
2684         for (counter = 0; counter < 3; counter++) {
2685           TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]);
2686           r->m_table_sizes[counter] += s_min_table_sizes[counter];
2687         }
2688         MZ_CLEAR_OBJ(r->m_tables[2].m_code_size);
2689         for (counter = 0; counter < r->m_table_sizes[2]; counter++) {
2690           mz_uint s;
2691           TINFL_GET_BITS(14, s, 3);
2692           r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s;
2693         }
2694         r->m_table_sizes[2] = 19;
2695       }
2696       for (; (int)r->m_type >= 0; r->m_type--) {
2697         int tree_next, tree_cur;
2698         tinfl_huff_table *pTable;
2699         mz_uint i, j, used_syms, total, sym_index, next_code[17],
2700             total_syms[16];
2701         pTable = &r->m_tables[r->m_type];
2702         MZ_CLEAR_OBJ(total_syms);
2703         MZ_CLEAR_OBJ(pTable->m_look_up);
2704         MZ_CLEAR_OBJ(pTable->m_tree);
2705         for (i = 0; i < r->m_table_sizes[r->m_type]; ++i)
2706           total_syms[pTable->m_code_size[i]]++;
2707         used_syms = 0, total = 0;
2708         next_code[0] = next_code[1] = 0;
2709         for (i = 1; i <= 15; ++i) {
2710           used_syms += total_syms[i];
2711           next_code[i + 1] = (total = ((total + total_syms[i]) << 1));
2712         }
2713         if ((65536 != total) && (used_syms > 1)) {
2714           TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED);
2715         }
2716         for (tree_next = -1, sym_index = 0;
2717              sym_index < r->m_table_sizes[r->m_type]; ++sym_index) {
2718           mz_uint rev_code = 0, l, cur_code,
2719                   code_size = pTable->m_code_size[sym_index];
2720           if (!code_size) continue;
2721           cur_code = next_code[code_size]++;
2722           for (l = code_size; l > 0; l--, cur_code >>= 1)
2723             rev_code = (rev_code << 1) | (cur_code & 1);
2724           if (code_size <= TINFL_FAST_LOOKUP_BITS) {
2725             mz_int16 k = (mz_int16)((code_size << 9) | sym_index);
2726             while (rev_code < TINFL_FAST_LOOKUP_SIZE) {
2727               pTable->m_look_up[rev_code] = k;
2728               rev_code += (1 << code_size);
2729             }
2730             continue;
2731           }
2732           if (0 ==
2733               (tree_cur = pTable->m_look_up[rev_code &
2734                                             (TINFL_FAST_LOOKUP_SIZE - 1)])) {
2735             pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] =
2736                 (mz_int16)tree_next;
2737             tree_cur = tree_next;
2738             tree_next -= 2;
2739           }
2740           rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1);
2741           for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--) {
2742             tree_cur -= ((rev_code >>= 1) & 1);
2743             if (!pTable->m_tree[-tree_cur - 1]) {
2744               pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next;
2745               tree_cur = tree_next;
2746               tree_next -= 2;
2747             } else
2748               tree_cur = pTable->m_tree[-tree_cur - 1];
2749           }
2750           tree_cur -= ((rev_code >>= 1) & 1);
2751           pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index;
2752         }
2753         if (r->m_type == 2) {
2754           for (counter = 0;
2755                counter < (r->m_table_sizes[0] + r->m_table_sizes[1]);) {
2756             mz_uint s;
2757             TINFL_HUFF_DECODE(16, dist, &r->m_tables[2]);
2758             if (dist < 16) {
2759               r->m_len_codes[counter++] = (mz_uint8)dist;
2760               continue;
2761             }
2762             if ((dist == 16) && (!counter)) {
2763               TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED);
2764             }
2765             num_extra = "\02\03\07"[dist - 16];
2766             TINFL_GET_BITS(18, s, num_extra);
2767             s += "\03\03\013"[dist - 16];
2768             TINFL_MEMSET(r->m_len_codes + counter,
2769                          (dist == 16) ? r->m_len_codes[counter - 1] : 0, s);
2770             counter += s;
2771           }
2772           if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter) {
2773             TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED);
2774           }
2775           TINFL_MEMCPY(r->m_tables[0].m_code_size, r->m_len_codes,
2776                        r->m_table_sizes[0]);
2777           TINFL_MEMCPY(r->m_tables[1].m_code_size,
2778                        r->m_len_codes + r->m_table_sizes[0],
2779                        r->m_table_sizes[1]);
2780         }
2781       }
2782       for (;;) {
2783         mz_uint8 *pSrc;
2784         for (;;) {
2785           if (((pIn_buf_end - pIn_buf_cur) < 4) ||
2786               ((pOut_buf_end - pOut_buf_cur) < 2)) {
2787             TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]);
2788             if (counter >= 256) break;
2789             while (pOut_buf_cur >= pOut_buf_end) {
2790               TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT);
2791             }
2792             *pOut_buf_cur++ = (mz_uint8)counter;
2793           } else {
2794             int sym2;
2795             mz_uint code_len;
2796 #if TINFL_USE_64BIT_BITBUF
2797             if (num_bits < 30) {
2798               bit_buf |=
2799                   (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits);
2800               pIn_buf_cur += 4;
2801               num_bits += 32;
2802             }
2803 #else
2804             if (num_bits < 15) {
2805               bit_buf |=
2806                   (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits);
2807               pIn_buf_cur += 2;
2808               num_bits += 16;
2809             }
2810 #endif
2811             if ((sym2 =
2812                      r->m_tables[0]
2813                          .m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >=
2814                 0)
2815               code_len = sym2 >> 9;
2816             else {
2817               code_len = TINFL_FAST_LOOKUP_BITS;
2818               do {
2819                 sym2 = r->m_tables[0]
2820                            .m_tree[~sym2 + ((bit_buf >> code_len++) & 1)];
2821               } while (sym2 < 0);
2822             }
2823             counter = sym2;
2824             bit_buf >>= code_len;
2825             num_bits -= code_len;
2826             if (counter & 256) break;
2827 
2828 #if !TINFL_USE_64BIT_BITBUF
2829             if (num_bits < 15) {
2830               bit_buf |=
2831                   (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits);
2832               pIn_buf_cur += 2;
2833               num_bits += 16;
2834             }
2835 #endif
2836             if ((sym2 =
2837                      r->m_tables[0]
2838                          .m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >=
2839                 0)
2840               code_len = sym2 >> 9;
2841             else {
2842               code_len = TINFL_FAST_LOOKUP_BITS;
2843               do {
2844                 sym2 = r->m_tables[0]
2845                            .m_tree[~sym2 + ((bit_buf >> code_len++) & 1)];
2846               } while (sym2 < 0);
2847             }
2848             bit_buf >>= code_len;
2849             num_bits -= code_len;
2850 
2851             pOut_buf_cur[0] = (mz_uint8)counter;
2852             if (sym2 & 256) {
2853               pOut_buf_cur++;
2854               counter = sym2;
2855               break;
2856             }
2857             pOut_buf_cur[1] = (mz_uint8)sym2;
2858             pOut_buf_cur += 2;
2859           }
2860         }
2861         if ((counter &= 511) == 256) break;
2862 
2863         num_extra = s_length_extra[counter - 257];
2864         counter = s_length_base[counter - 257];
2865         if (num_extra) {
2866           mz_uint extra_bits;
2867           TINFL_GET_BITS(25, extra_bits, num_extra);
2868           counter += extra_bits;
2869         }
2870 
2871         TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]);
2872         num_extra = s_dist_extra[dist];
2873         dist = s_dist_base[dist];
2874         if (num_extra) {
2875           mz_uint extra_bits;
2876           TINFL_GET_BITS(27, extra_bits, num_extra);
2877           dist += extra_bits;
2878         }
2879 
2880         dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start;
2881         if ((dist > dist_from_out_buf_start) &&
2882             (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) {
2883           TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED);
2884         }
2885 
2886         pSrc = pOut_buf_start +
2887                ((dist_from_out_buf_start - dist) & out_buf_size_mask);
2888 
2889         if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end) {
2890           while (counter--) {
2891             while (pOut_buf_cur >= pOut_buf_end) {
2892               TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT);
2893             }
2894             *pOut_buf_cur++ =
2895                 pOut_buf_start[(dist_from_out_buf_start++ - dist) &
2896                                out_buf_size_mask];
2897           }
2898           continue;
2899         }
2900 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
2901         else if ((counter >= 9) && (counter <= dist)) {
2902           const mz_uint8 *pSrc_end = pSrc + (counter & ~7);
2903           do {
2904             ((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0];
2905             ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1];
2906             pOut_buf_cur += 8;
2907           } while ((pSrc += 8) < pSrc_end);
2908           if ((counter &= 7) < 3) {
2909             if (counter) {
2910               pOut_buf_cur[0] = pSrc[0];
2911               if (counter > 1) pOut_buf_cur[1] = pSrc[1];
2912               pOut_buf_cur += counter;
2913             }
2914             continue;
2915           }
2916         }
2917 #endif
2918         do {
2919           pOut_buf_cur[0] = pSrc[0];
2920           pOut_buf_cur[1] = pSrc[1];
2921           pOut_buf_cur[2] = pSrc[2];
2922           pOut_buf_cur += 3;
2923           pSrc += 3;
2924         } while ((int)(counter -= 3) > 2);
2925         if ((int)counter > 0) {
2926           pOut_buf_cur[0] = pSrc[0];
2927           if ((int)counter > 1) pOut_buf_cur[1] = pSrc[1];
2928           pOut_buf_cur += counter;
2929         }
2930       }
2931     }
2932   } while (!(r->m_final & 1));
2933   if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) {
2934     TINFL_SKIP_BITS(32, num_bits & 7);
2935     for (counter = 0; counter < 4; ++counter) {
2936       mz_uint s;
2937       if (num_bits)
2938         TINFL_GET_BITS(41, s, 8);
2939       else
2940         TINFL_GET_BYTE(42, s);
2941       r->m_z_adler32 = (r->m_z_adler32 << 8) | s;
2942     }
2943   }
2944   TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE);
2945   TINFL_CR_FINISH
2946 
2947 common_exit:
2948   r->m_num_bits = num_bits;
2949   r->m_bit_buf = bit_buf;
2950   r->m_dist = dist;
2951   r->m_counter = counter;
2952   r->m_num_extra = num_extra;
2953   r->m_dist_from_out_buf_start = dist_from_out_buf_start;
2954   *pIn_buf_size = pIn_buf_cur - pIn_buf_next;
2955   *pOut_buf_size = pOut_buf_cur - pOut_buf_next;
2956   if ((decomp_flags &
2957        (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) &&
2958       (status >= 0)) {
2959     const mz_uint8 *ptr = pOut_buf_next;
2960     size_t buf_len = *pOut_buf_size;
2961     mz_uint32 i, s1 = r->m_check_adler32 & 0xffff,
2962                  s2 = r->m_check_adler32 >> 16;
2963     size_t block_len = buf_len % 5552;
2964     while (buf_len) {
2965       for (i = 0; i + 7 < block_len; i += 8, ptr += 8) {
2966         s1 += ptr[0], s2 += s1;
2967         s1 += ptr[1], s2 += s1;
2968         s1 += ptr[2], s2 += s1;
2969         s1 += ptr[3], s2 += s1;
2970         s1 += ptr[4], s2 += s1;
2971         s1 += ptr[5], s2 += s1;
2972         s1 += ptr[6], s2 += s1;
2973         s1 += ptr[7], s2 += s1;
2974       }
2975       for (; i < block_len; ++i) s1 += *ptr++, s2 += s1;
2976       s1 %= 65521U, s2 %= 65521U;
2977       buf_len -= block_len;
2978       block_len = 5552;
2979     }
2980     r->m_check_adler32 = (s2 << 16) + s1;
2981     if ((status == TINFL_STATUS_DONE) &&
2982         (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) &&
2983         (r->m_check_adler32 != r->m_z_adler32))
2984       status = TINFL_STATUS_ADLER32_MISMATCH;
2985   }
2986   return status;
2987 }
2988 
2989 // Higher level helper functions.
tinfl_decompress_mem_to_heap(const void * pSrc_buf,size_t src_buf_len,size_t * pOut_len,int flags)2990 void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len,
2991                                    size_t *pOut_len, int flags) {
2992   tinfl_decompressor decomp;
2993   void *pBuf = NULL, *pNew_buf;
2994   size_t src_buf_ofs = 0, out_buf_capacity = 0;
2995   *pOut_len = 0;
2996   tinfl_init(&decomp);
2997   for (;;) {
2998     size_t src_buf_size = src_buf_len - src_buf_ofs,
2999            dst_buf_size = out_buf_capacity - *pOut_len, new_out_buf_capacity;
3000     tinfl_status status = tinfl_decompress(
3001         &decomp, (const mz_uint8 *)pSrc_buf + src_buf_ofs, &src_buf_size,
3002         (mz_uint8 *)pBuf, pBuf ? (mz_uint8 *)pBuf + *pOut_len : NULL,
3003         &dst_buf_size,
3004         (flags & ~TINFL_FLAG_HAS_MORE_INPUT) |
3005             TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
3006     if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT)) {
3007       MZ_FREE(pBuf);
3008       *pOut_len = 0;
3009       return NULL;
3010     }
3011     src_buf_ofs += src_buf_size;
3012     *pOut_len += dst_buf_size;
3013     if (status == TINFL_STATUS_DONE) break;
3014     new_out_buf_capacity = out_buf_capacity * 2;
3015     if (new_out_buf_capacity < 128) new_out_buf_capacity = 128;
3016     pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity);
3017     if (!pNew_buf) {
3018       MZ_FREE(pBuf);
3019       *pOut_len = 0;
3020       return NULL;
3021     }
3022     pBuf = pNew_buf;
3023     out_buf_capacity = new_out_buf_capacity;
3024   }
3025   return pBuf;
3026 }
3027 
tinfl_decompress_mem_to_mem(void * pOut_buf,size_t out_buf_len,const void * pSrc_buf,size_t src_buf_len,int flags)3028 size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len,
3029                                    const void *pSrc_buf, size_t src_buf_len,
3030                                    int flags) {
3031   tinfl_decompressor decomp;
3032   tinfl_status status;
3033   tinfl_init(&decomp);
3034   status =
3035       tinfl_decompress(&decomp, (const mz_uint8 *)pSrc_buf, &src_buf_len,
3036                        (mz_uint8 *)pOut_buf, (mz_uint8 *)pOut_buf, &out_buf_len,
3037                        (flags & ~TINFL_FLAG_HAS_MORE_INPUT) |
3038                            TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
3039   return (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED
3040                                        : out_buf_len;
3041 }
3042 
tinfl_decompress_mem_to_callback(const void * pIn_buf,size_t * pIn_buf_size,tinfl_put_buf_func_ptr pPut_buf_func,void * pPut_buf_user,int flags)3043 int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size,
3044                                      tinfl_put_buf_func_ptr pPut_buf_func,
3045                                      void *pPut_buf_user, int flags) {
3046   int result = 0;
3047   tinfl_decompressor decomp;
3048   mz_uint8 *pDict = (mz_uint8 *)MZ_MALLOC(TINFL_LZ_DICT_SIZE);
3049   size_t in_buf_ofs = 0, dict_ofs = 0;
3050   if (!pDict) return TINFL_STATUS_FAILED;
3051   tinfl_init(&decomp);
3052   for (;;) {
3053     size_t in_buf_size = *pIn_buf_size - in_buf_ofs,
3054            dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs;
3055     tinfl_status status =
3056         tinfl_decompress(&decomp, (const mz_uint8 *)pIn_buf + in_buf_ofs,
3057                          &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size,
3058                          (flags & ~(TINFL_FLAG_HAS_MORE_INPUT |
3059                                     TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)));
3060     in_buf_ofs += in_buf_size;
3061     if ((dst_buf_size) &&
3062         (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user)))
3063       break;
3064     if (status != TINFL_STATUS_HAS_MORE_OUTPUT) {
3065       result = (status == TINFL_STATUS_DONE);
3066       break;
3067     }
3068     dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1);
3069   }
3070   MZ_FREE(pDict);
3071   *pIn_buf_size = in_buf_ofs;
3072   return result;
3073 }
3074 
3075 // ------------------- Low-level Compression (independent from all decompression
3076 // API's)
3077 
3078 // Purposely making these tables static for faster init and thread safety.
3079 static const mz_uint16 s_tdefl_len_sym[256] = {
3080     257, 258, 259, 260, 261, 262, 263, 264, 265, 265, 266, 266, 267, 267, 268,
3081     268, 269, 269, 269, 269, 270, 270, 270, 270, 271, 271, 271, 271, 272, 272,
3082     272, 272, 273, 273, 273, 273, 273, 273, 273, 273, 274, 274, 274, 274, 274,
3083     274, 274, 274, 275, 275, 275, 275, 275, 275, 275, 275, 276, 276, 276, 276,
3084     276, 276, 276, 276, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
3085     277, 277, 277, 277, 277, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278,
3086     278, 278, 278, 278, 278, 278, 279, 279, 279, 279, 279, 279, 279, 279, 279,
3087     279, 279, 279, 279, 279, 279, 279, 280, 280, 280, 280, 280, 280, 280, 280,
3088     280, 280, 280, 280, 280, 280, 280, 280, 281, 281, 281, 281, 281, 281, 281,
3089     281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
3090     281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 282, 282, 282, 282, 282,
3091     282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282,
3092     282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 283, 283, 283,
3093     283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283,
3094     283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 284,
3095     284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
3096     284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
3097     285};
3098 
3099 static const mz_uint8 s_tdefl_len_extra[256] = {
3100     0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2,
3101     2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3102     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
3103     4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
3104     4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
3105     4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
3106     5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
3107     5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
3108     5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
3109     5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
3110     5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0};
3111 
3112 static const mz_uint8 s_tdefl_small_dist_sym[512] = {
3113     0,  1,  2,  3,  4,  4,  5,  5,  6,  6,  6,  6,  7,  7,  7,  7,  8,  8,  8,
3114     8,  8,  8,  8,  8,  9,  9,  9,  9,  9,  9,  9,  9,  10, 10, 10, 10, 10, 10,
3115     10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11,
3116     11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
3117     12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
3118     12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
3119     13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14,
3120     14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
3121     14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
3122     14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
3123     14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
3124     15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
3125     15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
3126     15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
3127     16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
3128     16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
3129     16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
3130     16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
3131     16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
3132     16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
3133     16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
3134     17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
3135     17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
3136     17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
3137     17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
3138     17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
3139     17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17};
3140 
3141 static const mz_uint8 s_tdefl_small_dist_extra[512] = {
3142     0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3143     3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
3144     4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
3145     5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
3146     5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
3147     5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
3148     6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
3149     6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
3150     6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
3151     6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
3152     6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
3153     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
3154     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
3155     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
3156     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
3157     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
3158     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
3159     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
3160     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
3161     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
3162     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7};
3163 
3164 static const mz_uint8 s_tdefl_large_dist_sym[128] = {
3165     0,  0,  18, 19, 20, 20, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, 24, 24, 24,
3166     24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26,
3167     26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27,
3168     27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
3169     28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
3170     28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
3171     29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29};
3172 
3173 static const mz_uint8 s_tdefl_large_dist_extra[128] = {
3174     0,  0,  8,  8,  9,  9,  9,  9,  10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11,
3175     11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12,
3176     12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
3177     12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
3178     13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
3179     13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
3180     13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13};
3181 
3182 // Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted
3183 // values.
3184 typedef struct {
3185   mz_uint16 m_key, m_sym_index;
3186 } tdefl_sym_freq;
tdefl_radix_sort_syms(mz_uint num_syms,tdefl_sym_freq * pSyms0,tdefl_sym_freq * pSyms1)3187 static tdefl_sym_freq *tdefl_radix_sort_syms(mz_uint num_syms,
3188                                              tdefl_sym_freq *pSyms0,
3189                                              tdefl_sym_freq *pSyms1) {
3190   mz_uint32 total_passes = 2, pass_shift, pass, i, hist[256 * 2];
3191   tdefl_sym_freq *pCur_syms = pSyms0, *pNew_syms = pSyms1;
3192   MZ_CLEAR_OBJ(hist);
3193   for (i = 0; i < num_syms; i++) {
3194     mz_uint freq = pSyms0[i].m_key;
3195     hist[freq & 0xFF]++;
3196     hist[256 + ((freq >> 8) & 0xFF)]++;
3197   }
3198   while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256]))
3199     total_passes--;
3200   for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8) {
3201     const mz_uint32 *pHist = &hist[pass << 8];
3202     mz_uint offsets[256], cur_ofs = 0;
3203     for (i = 0; i < 256; i++) {
3204       offsets[i] = cur_ofs;
3205       cur_ofs += pHist[i];
3206     }
3207     for (i = 0; i < num_syms; i++)
3208       pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] =
3209           pCur_syms[i];
3210     {
3211       tdefl_sym_freq *t = pCur_syms;
3212       pCur_syms = pNew_syms;
3213       pNew_syms = t;
3214     }
3215   }
3216   return pCur_syms;
3217 }
3218 
3219 // tdefl_calculate_minimum_redundancy() originally written by: Alistair Moffat,
3220 // alistair@cs.mu.oz.au, Jyrki Katajainen, jyrki@diku.dk, November 1996.
tdefl_calculate_minimum_redundancy(tdefl_sym_freq * A,int n)3221 static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq *A, int n) {
3222   int root, leaf, next, avbl, used, dpth;
3223   if (n == 0)
3224     return;
3225   else if (n == 1) {
3226     A[0].m_key = 1;
3227     return;
3228   }
3229   A[0].m_key += A[1].m_key;
3230   root = 0;
3231   leaf = 2;
3232   for (next = 1; next < n - 1; next++) {
3233     if (leaf >= n || A[root].m_key < A[leaf].m_key) {
3234       A[next].m_key = A[root].m_key;
3235       A[root++].m_key = (mz_uint16)next;
3236     } else
3237       A[next].m_key = A[leaf++].m_key;
3238     if (leaf >= n || (root < next && A[root].m_key < A[leaf].m_key)) {
3239       A[next].m_key = (mz_uint16)(A[next].m_key + A[root].m_key);
3240       A[root++].m_key = (mz_uint16)next;
3241     } else
3242       A[next].m_key = (mz_uint16)(A[next].m_key + A[leaf++].m_key);
3243   }
3244   A[n - 2].m_key = 0;
3245   for (next = n - 3; next >= 0; next--)
3246     A[next].m_key = A[A[next].m_key].m_key + 1;
3247   avbl = 1;
3248   used = dpth = 0;
3249   root = n - 2;
3250   next = n - 1;
3251   while (avbl > 0) {
3252     while (root >= 0 && (int)A[root].m_key == dpth) {
3253       used++;
3254       root--;
3255     }
3256     while (avbl > used) {
3257       A[next--].m_key = (mz_uint16)(dpth);
3258       avbl--;
3259     }
3260     avbl = 2 * used;
3261     dpth++;
3262     used = 0;
3263   }
3264 }
3265 
3266 // Limits canonical Huffman code table's max code size.
3267 enum { TDEFL_MAX_SUPPORTED_HUFF_CODESIZE = 32 };
tdefl_huffman_enforce_max_code_size(int * pNum_codes,int code_list_len,int max_code_size)3268 static void tdefl_huffman_enforce_max_code_size(int *pNum_codes,
3269                                                 int code_list_len,
3270                                                 int max_code_size) {
3271   int i;
3272   mz_uint32 total = 0;
3273   if (code_list_len <= 1) return;
3274   for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++)
3275     pNum_codes[max_code_size] += pNum_codes[i];
3276   for (i = max_code_size; i > 0; i--)
3277     total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i));
3278   while (total != (1UL << max_code_size)) {
3279     pNum_codes[max_code_size]--;
3280     for (i = max_code_size - 1; i > 0; i--)
3281       if (pNum_codes[i]) {
3282         pNum_codes[i]--;
3283         pNum_codes[i + 1] += 2;
3284         break;
3285       }
3286     total--;
3287   }
3288 }
3289 
tdefl_optimize_huffman_table(tdefl_compressor * d,int table_num,int table_len,int code_size_limit,int static_table)3290 static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num,
3291                                          int table_len, int code_size_limit,
3292                                          int static_table) {
3293   int i, j, l, num_codes[1 + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE];
3294   mz_uint next_code[TDEFL_MAX_SUPPORTED_HUFF_CODESIZE + 1];
3295   MZ_CLEAR_OBJ(num_codes);
3296   if (static_table) {
3297     for (i = 0; i < table_len; i++)
3298       num_codes[d->m_huff_code_sizes[table_num][i]]++;
3299   } else {
3300     tdefl_sym_freq syms0[TDEFL_MAX_HUFF_SYMBOLS], syms1[TDEFL_MAX_HUFF_SYMBOLS],
3301         *pSyms;
3302     int num_used_syms = 0;
3303     const mz_uint16 *pSym_count = &d->m_huff_count[table_num][0];
3304     for (i = 0; i < table_len; i++)
3305       if (pSym_count[i]) {
3306         syms0[num_used_syms].m_key = (mz_uint16)pSym_count[i];
3307         syms0[num_used_syms++].m_sym_index = (mz_uint16)i;
3308       }
3309 
3310     pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1);
3311     tdefl_calculate_minimum_redundancy(pSyms, num_used_syms);
3312 
3313     for (i = 0; i < num_used_syms; i++) num_codes[pSyms[i].m_key]++;
3314 
3315     tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms,
3316                                         code_size_limit);
3317 
3318     MZ_CLEAR_OBJ(d->m_huff_code_sizes[table_num]);
3319     MZ_CLEAR_OBJ(d->m_huff_codes[table_num]);
3320     for (i = 1, j = num_used_syms; i <= code_size_limit; i++)
3321       for (l = num_codes[i]; l > 0; l--)
3322         d->m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = (mz_uint8)(i);
3323   }
3324 
3325   next_code[1] = 0;
3326   for (j = 0, i = 2; i <= code_size_limit; i++)
3327     next_code[i] = j = ((j + num_codes[i - 1]) << 1);
3328 
3329   for (i = 0; i < table_len; i++) {
3330     mz_uint rev_code = 0, code, code_size;
3331     if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0) continue;
3332     code = next_code[code_size]++;
3333     for (l = code_size; l > 0; l--, code >>= 1)
3334       rev_code = (rev_code << 1) | (code & 1);
3335     d->m_huff_codes[table_num][i] = (mz_uint16)rev_code;
3336   }
3337 }
3338 
3339 #define TDEFL_PUT_BITS(b, l)                               \
3340   do {                                                     \
3341     mz_uint bits = b;                                      \
3342     mz_uint len = l;                                       \
3343     MZ_ASSERT(bits <= ((1U << len) - 1U));                 \
3344     d->m_bit_buffer |= (bits << d->m_bits_in);             \
3345     d->m_bits_in += len;                                   \
3346     while (d->m_bits_in >= 8) {                            \
3347       if (d->m_pOutput_buf < d->m_pOutput_buf_end)         \
3348         *d->m_pOutput_buf++ = (mz_uint8)(d->m_bit_buffer); \
3349       d->m_bit_buffer >>= 8;                               \
3350       d->m_bits_in -= 8;                                   \
3351     }                                                      \
3352   }                                                        \
3353   MZ_MACRO_END
3354 
3355 #define TDEFL_RLE_PREV_CODE_SIZE()                                        \
3356   {                                                                       \
3357     if (rle_repeat_count) {                                               \
3358       if (rle_repeat_count < 3) {                                         \
3359         d->m_huff_count[2][prev_code_size] = (mz_uint16)(                 \
3360             d->m_huff_count[2][prev_code_size] + rle_repeat_count);       \
3361         while (rle_repeat_count--)                                        \
3362           packed_code_sizes[num_packed_code_sizes++] = prev_code_size;    \
3363       } else {                                                            \
3364         d->m_huff_count[2][16] = (mz_uint16)(d->m_huff_count[2][16] + 1); \
3365         packed_code_sizes[num_packed_code_sizes++] = 16;                  \
3366         packed_code_sizes[num_packed_code_sizes++] =                      \
3367             (mz_uint8)(rle_repeat_count - 3);                             \
3368       }                                                                   \
3369       rle_repeat_count = 0;                                               \
3370     }                                                                     \
3371   }
3372 
3373 #define TDEFL_RLE_ZERO_CODE_SIZE()                                            \
3374   {                                                                           \
3375     if (rle_z_count) {                                                        \
3376       if (rle_z_count < 3) {                                                  \
3377         d->m_huff_count[2][0] =                                               \
3378             (mz_uint16)(d->m_huff_count[2][0] + rle_z_count);                 \
3379         while (rle_z_count--) packed_code_sizes[num_packed_code_sizes++] = 0; \
3380       } else if (rle_z_count <= 10) {                                         \
3381         d->m_huff_count[2][17] = (mz_uint16)(d->m_huff_count[2][17] + 1);     \
3382         packed_code_sizes[num_packed_code_sizes++] = 17;                      \
3383         packed_code_sizes[num_packed_code_sizes++] =                          \
3384             (mz_uint8)(rle_z_count - 3);                                      \
3385       } else {                                                                \
3386         d->m_huff_count[2][18] = (mz_uint16)(d->m_huff_count[2][18] + 1);     \
3387         packed_code_sizes[num_packed_code_sizes++] = 18;                      \
3388         packed_code_sizes[num_packed_code_sizes++] =                          \
3389             (mz_uint8)(rle_z_count - 11);                                     \
3390       }                                                                       \
3391       rle_z_count = 0;                                                        \
3392     }                                                                         \
3393   }
3394 
3395 static mz_uint8 s_tdefl_packed_code_size_syms_swizzle[] = {
3396     16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
3397 
tdefl_start_dynamic_block(tdefl_compressor * d)3398 static void tdefl_start_dynamic_block(tdefl_compressor *d) {
3399   int num_lit_codes, num_dist_codes, num_bit_lengths;
3400   mz_uint i, total_code_sizes_to_pack, num_packed_code_sizes, rle_z_count,
3401       rle_repeat_count, packed_code_sizes_index;
3402   mz_uint8
3403       code_sizes_to_pack[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1],
3404       packed_code_sizes[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1],
3405       prev_code_size = 0xFF;
3406 
3407   d->m_huff_count[0][256] = 1;
3408 
3409   tdefl_optimize_huffman_table(d, 0, TDEFL_MAX_HUFF_SYMBOLS_0, 15, MZ_FALSE);
3410   tdefl_optimize_huffman_table(d, 1, TDEFL_MAX_HUFF_SYMBOLS_1, 15, MZ_FALSE);
3411 
3412   for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--)
3413     if (d->m_huff_code_sizes[0][num_lit_codes - 1]) break;
3414   for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--)
3415     if (d->m_huff_code_sizes[1][num_dist_codes - 1]) break;
3416 
3417   memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0], num_lit_codes);
3418   memcpy(code_sizes_to_pack + num_lit_codes, &d->m_huff_code_sizes[1][0],
3419          num_dist_codes);
3420   total_code_sizes_to_pack = num_lit_codes + num_dist_codes;
3421   num_packed_code_sizes = 0;
3422   rle_z_count = 0;
3423   rle_repeat_count = 0;
3424 
3425   memset(&d->m_huff_count[2][0], 0,
3426          sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2);
3427   for (i = 0; i < total_code_sizes_to_pack; i++) {
3428     mz_uint8 code_size = code_sizes_to_pack[i];
3429     if (!code_size) {
3430       TDEFL_RLE_PREV_CODE_SIZE();
3431       if (++rle_z_count == 138) {
3432         TDEFL_RLE_ZERO_CODE_SIZE();
3433       }
3434     } else {
3435       TDEFL_RLE_ZERO_CODE_SIZE();
3436       if (code_size != prev_code_size) {
3437         TDEFL_RLE_PREV_CODE_SIZE();
3438         d->m_huff_count[2][code_size] =
3439             (mz_uint16)(d->m_huff_count[2][code_size] + 1);
3440         packed_code_sizes[num_packed_code_sizes++] = code_size;
3441       } else if (++rle_repeat_count == 6) {
3442         TDEFL_RLE_PREV_CODE_SIZE();
3443       }
3444     }
3445     prev_code_size = code_size;
3446   }
3447   if (rle_repeat_count) {
3448     TDEFL_RLE_PREV_CODE_SIZE();
3449   } else {
3450     TDEFL_RLE_ZERO_CODE_SIZE();
3451   }
3452 
3453   tdefl_optimize_huffman_table(d, 2, TDEFL_MAX_HUFF_SYMBOLS_2, 7, MZ_FALSE);
3454 
3455   TDEFL_PUT_BITS(2, 2);
3456 
3457   TDEFL_PUT_BITS(num_lit_codes - 257, 5);
3458   TDEFL_PUT_BITS(num_dist_codes - 1, 5);
3459 
3460   for (num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--)
3461     if (d->m_huff_code_sizes
3462             [2][s_tdefl_packed_code_size_syms_swizzle[num_bit_lengths]])
3463       break;
3464   num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1));
3465   TDEFL_PUT_BITS(num_bit_lengths - 4, 4);
3466   for (i = 0; (int)i < num_bit_lengths; i++)
3467     TDEFL_PUT_BITS(
3468         d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[i]], 3);
3469 
3470   for (packed_code_sizes_index = 0;
3471        packed_code_sizes_index < num_packed_code_sizes;) {
3472     mz_uint code = packed_code_sizes[packed_code_sizes_index++];
3473     MZ_ASSERT(code < TDEFL_MAX_HUFF_SYMBOLS_2);
3474     TDEFL_PUT_BITS(d->m_huff_codes[2][code], d->m_huff_code_sizes[2][code]);
3475     if (code >= 16)
3476       TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++],
3477                      "\02\03\07"[code - 16]);
3478   }
3479 }
3480 
tdefl_start_static_block(tdefl_compressor * d)3481 static void tdefl_start_static_block(tdefl_compressor *d) {
3482   mz_uint i;
3483   mz_uint8 *p = &d->m_huff_code_sizes[0][0];
3484 
3485   for (i = 0; i <= 143; ++i) *p++ = 8;
3486   for (; i <= 255; ++i) *p++ = 9;
3487   for (; i <= 279; ++i) *p++ = 7;
3488   for (; i <= 287; ++i) *p++ = 8;
3489 
3490   memset(d->m_huff_code_sizes[1], 5, 32);
3491 
3492   tdefl_optimize_huffman_table(d, 0, 288, 15, MZ_TRUE);
3493   tdefl_optimize_huffman_table(d, 1, 32, 15, MZ_TRUE);
3494 
3495   TDEFL_PUT_BITS(1, 2);
3496 }
3497 
3498 static const mz_uint mz_bitmasks[17] = {
3499     0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF,
3500     0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF};
3501 
3502 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && \
3503     MINIZ_HAS_64BIT_REGISTERS
tdefl_compress_lz_codes(tdefl_compressor * d)3504 static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) {
3505   mz_uint flags;
3506   mz_uint8 *pLZ_codes;
3507   mz_uint8 *pOutput_buf = d->m_pOutput_buf;
3508   mz_uint8 *pLZ_code_buf_end = d->m_pLZ_code_buf;
3509   mz_uint64 bit_buffer = d->m_bit_buffer;
3510   mz_uint bits_in = d->m_bits_in;
3511 
3512 #define TDEFL_PUT_BITS_FAST(b, l)                \
3513   {                                              \
3514     bit_buffer |= (((mz_uint64)(b)) << bits_in); \
3515     bits_in += (l);                              \
3516   }
3517 
3518   flags = 1;
3519   for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < pLZ_code_buf_end;
3520        flags >>= 1) {
3521     if (flags == 1) flags = *pLZ_codes++ | 0x100;
3522 
3523     if (flags & 1) {
3524       mz_uint s0, s1, n0, n1, sym, num_extra_bits;
3525       mz_uint match_len = pLZ_codes[0],
3526               match_dist = *(const mz_uint16 *)(pLZ_codes + 1);
3527       pLZ_codes += 3;
3528 
3529       MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
3530       TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][s_tdefl_len_sym[match_len]],
3531                           d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
3532       TDEFL_PUT_BITS_FAST(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]],
3533                           s_tdefl_len_extra[match_len]);
3534 
3535       // This sequence coaxes MSVC into using cmov's vs. jmp's.
3536       s0 = s_tdefl_small_dist_sym[match_dist & 511];
3537       n0 = s_tdefl_small_dist_extra[match_dist & 511];
3538       s1 = s_tdefl_large_dist_sym[match_dist >> 8];
3539       n1 = s_tdefl_large_dist_extra[match_dist >> 8];
3540       sym = (match_dist < 512) ? s0 : s1;
3541       num_extra_bits = (match_dist < 512) ? n0 : n1;
3542 
3543       MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
3544       TDEFL_PUT_BITS_FAST(d->m_huff_codes[1][sym],
3545                           d->m_huff_code_sizes[1][sym]);
3546       TDEFL_PUT_BITS_FAST(match_dist & mz_bitmasks[num_extra_bits],
3547                           num_extra_bits);
3548     } else {
3549       mz_uint lit = *pLZ_codes++;
3550       MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
3551       TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit],
3552                           d->m_huff_code_sizes[0][lit]);
3553 
3554       if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) {
3555         flags >>= 1;
3556         lit = *pLZ_codes++;
3557         MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
3558         TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit],
3559                             d->m_huff_code_sizes[0][lit]);
3560 
3561         if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) {
3562           flags >>= 1;
3563           lit = *pLZ_codes++;
3564           MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
3565           TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit],
3566                               d->m_huff_code_sizes[0][lit]);
3567         }
3568       }
3569     }
3570 
3571     if (pOutput_buf >= d->m_pOutput_buf_end) return MZ_FALSE;
3572 
3573     *(mz_uint64 *)pOutput_buf = bit_buffer;
3574     pOutput_buf += (bits_in >> 3);
3575     bit_buffer >>= (bits_in & ~7);
3576     bits_in &= 7;
3577   }
3578 
3579 #undef TDEFL_PUT_BITS_FAST
3580 
3581   d->m_pOutput_buf = pOutput_buf;
3582   d->m_bits_in = 0;
3583   d->m_bit_buffer = 0;
3584 
3585   while (bits_in) {
3586     mz_uint32 n = MZ_MIN(bits_in, 16);
3587     TDEFL_PUT_BITS((mz_uint)bit_buffer & mz_bitmasks[n], n);
3588     bit_buffer >>= n;
3589     bits_in -= n;
3590   }
3591 
3592   TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
3593 
3594   return (d->m_pOutput_buf < d->m_pOutput_buf_end);
3595 }
3596 #else
tdefl_compress_lz_codes(tdefl_compressor * d)3597 static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) {
3598   mz_uint flags;
3599   mz_uint8 *pLZ_codes;
3600 
3601   flags = 1;
3602   for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < d->m_pLZ_code_buf;
3603        flags >>= 1) {
3604     if (flags == 1) flags = *pLZ_codes++ | 0x100;
3605     if (flags & 1) {
3606       mz_uint sym, num_extra_bits;
3607       mz_uint match_len = pLZ_codes[0],
3608               match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8));
3609       pLZ_codes += 3;
3610 
3611       MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
3612       TDEFL_PUT_BITS(d->m_huff_codes[0][s_tdefl_len_sym[match_len]],
3613                      d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
3614       TDEFL_PUT_BITS(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]],
3615                      s_tdefl_len_extra[match_len]);
3616 
3617       if (match_dist < 512) {
3618         sym = s_tdefl_small_dist_sym[match_dist];
3619         num_extra_bits = s_tdefl_small_dist_extra[match_dist];
3620       } else {
3621         sym = s_tdefl_large_dist_sym[match_dist >> 8];
3622         num_extra_bits = s_tdefl_large_dist_extra[match_dist >> 8];
3623       }
3624       MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
3625       TDEFL_PUT_BITS(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
3626       TDEFL_PUT_BITS(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
3627     } else {
3628       mz_uint lit = *pLZ_codes++;
3629       MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
3630       TDEFL_PUT_BITS(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
3631     }
3632   }
3633 
3634   TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
3635 
3636   return (d->m_pOutput_buf < d->m_pOutput_buf_end);
3637 }
3638 #endif  // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN &&
3639         // MINIZ_HAS_64BIT_REGISTERS
3640 
tdefl_compress_block(tdefl_compressor * d,mz_bool static_block)3641 static mz_bool tdefl_compress_block(tdefl_compressor *d, mz_bool static_block) {
3642   if (static_block)
3643     tdefl_start_static_block(d);
3644   else
3645     tdefl_start_dynamic_block(d);
3646   return tdefl_compress_lz_codes(d);
3647 }
3648 
tdefl_flush_block(tdefl_compressor * d,int flush)3649 static int tdefl_flush_block(tdefl_compressor *d, int flush) {
3650   mz_uint saved_bit_buf, saved_bits_in;
3651   mz_uint8 *pSaved_output_buf;
3652   mz_bool comp_block_succeeded = MZ_FALSE;
3653   int n, use_raw_block =
3654              ((d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS) != 0) &&
3655              (d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size;
3656   mz_uint8 *pOutput_buf_start =
3657       ((d->m_pPut_buf_func == NULL) &&
3658        ((*d->m_pOut_buf_size - d->m_out_buf_ofs) >= TDEFL_OUT_BUF_SIZE))
3659           ? ((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs)
3660           : d->m_output_buf;
3661 
3662   d->m_pOutput_buf = pOutput_buf_start;
3663   d->m_pOutput_buf_end = d->m_pOutput_buf + TDEFL_OUT_BUF_SIZE - 16;
3664 
3665   MZ_ASSERT(!d->m_output_flush_remaining);
3666   d->m_output_flush_ofs = 0;
3667   d->m_output_flush_remaining = 0;
3668 
3669   *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> d->m_num_flags_left);
3670   d->m_pLZ_code_buf -= (d->m_num_flags_left == 8);
3671 
3672   if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index)) {
3673     TDEFL_PUT_BITS(0x78, 8);
3674     TDEFL_PUT_BITS(0x01, 8);
3675   }
3676 
3677   TDEFL_PUT_BITS(flush == TDEFL_FINISH, 1);
3678 
3679   pSaved_output_buf = d->m_pOutput_buf;
3680   saved_bit_buf = d->m_bit_buffer;
3681   saved_bits_in = d->m_bits_in;
3682 
3683   if (!use_raw_block)
3684     comp_block_succeeded =
3685         tdefl_compress_block(d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) ||
3686                                     (d->m_total_lz_bytes < 48));
3687 
3688   // If the block gets expanded, forget the current contents of the output
3689   // buffer and send a raw block instead.
3690   if (((use_raw_block) ||
3691        ((d->m_total_lz_bytes) && ((d->m_pOutput_buf - pSaved_output_buf + 1U) >=
3692                                   d->m_total_lz_bytes))) &&
3693       ((d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size)) {
3694     mz_uint i;
3695     d->m_pOutput_buf = pSaved_output_buf;
3696     d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
3697     TDEFL_PUT_BITS(0, 2);
3698     if (d->m_bits_in) {
3699       TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
3700     }
3701     for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF) {
3702       TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16);
3703     }
3704     for (i = 0; i < d->m_total_lz_bytes; ++i) {
3705       TDEFL_PUT_BITS(
3706           d->m_dict[(d->m_lz_code_buf_dict_pos + i) & TDEFL_LZ_DICT_SIZE_MASK],
3707           8);
3708     }
3709   }
3710   // Check for the extremely unlikely (if not impossible) case of the compressed
3711   // block not fitting into the output buffer when using dynamic codes.
3712   else if (!comp_block_succeeded) {
3713     d->m_pOutput_buf = pSaved_output_buf;
3714     d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
3715     tdefl_compress_block(d, MZ_TRUE);
3716   }
3717 
3718   if (flush) {
3719     if (flush == TDEFL_FINISH) {
3720       if (d->m_bits_in) {
3721         TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
3722       }
3723       if (d->m_flags & TDEFL_WRITE_ZLIB_HEADER) {
3724         mz_uint i, a = d->m_adler32;
3725         for (i = 0; i < 4; i++) {
3726           TDEFL_PUT_BITS((a >> 24) & 0xFF, 8);
3727           a <<= 8;
3728         }
3729       }
3730     } else {
3731       mz_uint i, z = 0;
3732       TDEFL_PUT_BITS(0, 3);
3733       if (d->m_bits_in) {
3734         TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
3735       }
3736       for (i = 2; i; --i, z ^= 0xFFFF) {
3737         TDEFL_PUT_BITS(z & 0xFFFF, 16);
3738       }
3739     }
3740   }
3741 
3742   MZ_ASSERT(d->m_pOutput_buf < d->m_pOutput_buf_end);
3743 
3744   memset(&d->m_huff_count[0][0], 0,
3745          sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
3746   memset(&d->m_huff_count[1][0], 0,
3747          sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
3748 
3749   d->m_pLZ_code_buf = d->m_lz_code_buf + 1;
3750   d->m_pLZ_flags = d->m_lz_code_buf;
3751   d->m_num_flags_left = 8;
3752   d->m_lz_code_buf_dict_pos += d->m_total_lz_bytes;
3753   d->m_total_lz_bytes = 0;
3754   d->m_block_index++;
3755 
3756   if ((n = (int)(d->m_pOutput_buf - pOutput_buf_start)) != 0) {
3757     if (d->m_pPut_buf_func) {
3758       *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
3759       if (!(*d->m_pPut_buf_func)(d->m_output_buf, n, d->m_pPut_buf_user))
3760         return (d->m_prev_return_status = TDEFL_STATUS_PUT_BUF_FAILED);
3761     } else if (pOutput_buf_start == d->m_output_buf) {
3762       int bytes_to_copy = (int)MZ_MIN(
3763           (size_t)n, (size_t)(*d->m_pOut_buf_size - d->m_out_buf_ofs));
3764       memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf,
3765              bytes_to_copy);
3766       d->m_out_buf_ofs += bytes_to_copy;
3767       if ((n -= bytes_to_copy) != 0) {
3768         d->m_output_flush_ofs = bytes_to_copy;
3769         d->m_output_flush_remaining = n;
3770       }
3771     } else {
3772       d->m_out_buf_ofs += n;
3773     }
3774   }
3775 
3776   return d->m_output_flush_remaining;
3777 }
3778 
3779 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
3780 #define TDEFL_READ_UNALIGNED_WORD(p) *(const mz_uint16 *)(p)
tdefl_find_match(tdefl_compressor * d,mz_uint lookahead_pos,mz_uint max_dist,mz_uint max_match_len,mz_uint * pMatch_dist,mz_uint * pMatch_len)3781 static MZ_FORCEINLINE void tdefl_find_match(
3782     tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist,
3783     mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len) {
3784   mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK,
3785                 match_len = *pMatch_len, probe_pos = pos, next_probe_pos,
3786                 probe_len;
3787   mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
3788   const mz_uint16 *s = (const mz_uint16 *)(d->m_dict + pos), *p, *q;
3789   mz_uint16 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]),
3790             s01 = TDEFL_READ_UNALIGNED_WORD(s);
3791   MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN);
3792   if (max_match_len <= match_len) return;
3793   for (;;) {
3794     for (;;) {
3795       if (--num_probes_left == 0) return;
3796 #define TDEFL_PROBE                                                            \
3797   next_probe_pos = d->m_next[probe_pos];                                       \
3798   if ((!next_probe_pos) ||                                                     \
3799       ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist))       \
3800     return;                                                                    \
3801   probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK;                        \
3802   if (TDEFL_READ_UNALIGNED_WORD(&d->m_dict[probe_pos + match_len - 1]) == c01) \
3803     break;
3804       TDEFL_PROBE;
3805       TDEFL_PROBE;
3806       TDEFL_PROBE;
3807     }
3808     if (!dist) break;
3809     q = (const mz_uint16 *)(d->m_dict + probe_pos);
3810     if (TDEFL_READ_UNALIGNED_WORD(q) != s01) continue;
3811     p = s;
3812     probe_len = 32;
3813     do {
3814     } while (
3815         (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) &&
3816         (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) &&
3817         (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) &&
3818         (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) &&
3819         (--probe_len > 0));
3820     if (!probe_len) {
3821       *pMatch_dist = dist;
3822       *pMatch_len = MZ_MIN(max_match_len, TDEFL_MAX_MATCH_LEN);
3823       break;
3824     } else if ((probe_len = ((mz_uint)(p - s) * 2) +
3825                             (mz_uint)(*(const mz_uint8 *)p ==
3826                                       *(const mz_uint8 *)q)) > match_len) {
3827       *pMatch_dist = dist;
3828       if ((*pMatch_len = match_len = MZ_MIN(max_match_len, probe_len)) ==
3829           max_match_len)
3830         break;
3831       c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]);
3832     }
3833   }
3834 }
3835 #else
tdefl_find_match(tdefl_compressor * d,mz_uint lookahead_pos,mz_uint max_dist,mz_uint max_match_len,mz_uint * pMatch_dist,mz_uint * pMatch_len)3836 static MZ_FORCEINLINE void tdefl_find_match(
3837     tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist,
3838     mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len) {
3839   mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK,
3840                 match_len = *pMatch_len, probe_pos = pos, next_probe_pos,
3841                 probe_len;
3842   mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
3843   const mz_uint8 *s = d->m_dict + pos, *p, *q;
3844   mz_uint8 c0 = d->m_dict[pos + match_len], c1 = d->m_dict[pos + match_len - 1];
3845   MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN);
3846   if (max_match_len <= match_len) return;
3847   for (;;) {
3848     for (;;) {
3849       if (--num_probes_left == 0) return;
3850 #define TDEFL_PROBE                                                      \
3851   next_probe_pos = d->m_next[probe_pos];                                 \
3852   if ((!next_probe_pos) ||                                               \
3853       ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) \
3854     return;                                                              \
3855   probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK;                  \
3856   if ((d->m_dict[probe_pos + match_len] == c0) &&                        \
3857       (d->m_dict[probe_pos + match_len - 1] == c1))                      \
3858     break;
3859       TDEFL_PROBE;
3860       TDEFL_PROBE;
3861       TDEFL_PROBE;
3862     }
3863     if (!dist) break;
3864     p = s;
3865     q = d->m_dict + probe_pos;
3866     for (probe_len = 0; probe_len < max_match_len; probe_len++)
3867       if (*p++ != *q++) break;
3868     if (probe_len > match_len) {
3869       *pMatch_dist = dist;
3870       if ((*pMatch_len = match_len = probe_len) == max_match_len) return;
3871       c0 = d->m_dict[pos + match_len];
3872       c1 = d->m_dict[pos + match_len - 1];
3873     }
3874   }
3875 }
3876 #endif  // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
3877 
3878 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
tdefl_compress_fast(tdefl_compressor * d)3879 static mz_bool tdefl_compress_fast(tdefl_compressor *d) {
3880   // Faster, minimally featured LZRW1-style match+parse loop with better
3881   // register utilization. Intended for applications where raw throughput is
3882   // valued more highly than ratio.
3883   mz_uint lookahead_pos = d->m_lookahead_pos,
3884           lookahead_size = d->m_lookahead_size, dict_size = d->m_dict_size,
3885           total_lz_bytes = d->m_total_lz_bytes,
3886           num_flags_left = d->m_num_flags_left;
3887   mz_uint8 *pLZ_code_buf = d->m_pLZ_code_buf, *pLZ_flags = d->m_pLZ_flags;
3888   mz_uint cur_pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
3889 
3890   while ((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size))) {
3891     const mz_uint TDEFL_COMP_FAST_LOOKAHEAD_SIZE = 4096;
3892     mz_uint dst_pos =
3893         (lookahead_pos + lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;
3894     mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(
3895         d->m_src_buf_left, TDEFL_COMP_FAST_LOOKAHEAD_SIZE - lookahead_size);
3896     d->m_src_buf_left -= num_bytes_to_process;
3897     lookahead_size += num_bytes_to_process;
3898 
3899     while (num_bytes_to_process) {
3900       mz_uint32 n = MZ_MIN(TDEFL_LZ_DICT_SIZE - dst_pos, num_bytes_to_process);
3901       memcpy(d->m_dict + dst_pos, d->m_pSrc, n);
3902       if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
3903         memcpy(d->m_dict + TDEFL_LZ_DICT_SIZE + dst_pos, d->m_pSrc,
3904                MZ_MIN(n, (TDEFL_MAX_MATCH_LEN - 1) - dst_pos));
3905       d->m_pSrc += n;
3906       dst_pos = (dst_pos + n) & TDEFL_LZ_DICT_SIZE_MASK;
3907       num_bytes_to_process -= n;
3908     }
3909 
3910     dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - lookahead_size, dict_size);
3911     if ((!d->m_flush) && (lookahead_size < TDEFL_COMP_FAST_LOOKAHEAD_SIZE))
3912       break;
3913 
3914     while (lookahead_size >= 4) {
3915       mz_uint cur_match_dist, cur_match_len = 1;
3916       mz_uint8 *pCur_dict = d->m_dict + cur_pos;
3917       mz_uint first_trigram = (*(const mz_uint32 *)pCur_dict) & 0xFFFFFF;
3918       mz_uint hash =
3919           (first_trigram ^ (first_trigram >> (24 - (TDEFL_LZ_HASH_BITS - 8)))) &
3920           TDEFL_LEVEL1_HASH_SIZE_MASK;
3921       mz_uint probe_pos = d->m_hash[hash];
3922       d->m_hash[hash] = (mz_uint16)lookahead_pos;
3923 
3924       if (((cur_match_dist = (mz_uint16)(lookahead_pos - probe_pos)) <=
3925            dict_size) &&
3926           ((*(const mz_uint32 *)(d->m_dict +
3927                                  (probe_pos &= TDEFL_LZ_DICT_SIZE_MASK)) &
3928             0xFFFFFF) == first_trigram)) {
3929         const mz_uint16 *p = (const mz_uint16 *)pCur_dict;
3930         const mz_uint16 *q = (const mz_uint16 *)(d->m_dict + probe_pos);
3931         mz_uint32 probe_len = 32;
3932         do {
3933         } while ((TDEFL_READ_UNALIGNED_WORD(++p) ==
3934                   TDEFL_READ_UNALIGNED_WORD(++q)) &&
3935                  (TDEFL_READ_UNALIGNED_WORD(++p) ==
3936                   TDEFL_READ_UNALIGNED_WORD(++q)) &&
3937                  (TDEFL_READ_UNALIGNED_WORD(++p) ==
3938                   TDEFL_READ_UNALIGNED_WORD(++q)) &&
3939                  (TDEFL_READ_UNALIGNED_WORD(++p) ==
3940                   TDEFL_READ_UNALIGNED_WORD(++q)) &&
3941                  (--probe_len > 0));
3942         cur_match_len = ((mz_uint)(p - (const mz_uint16 *)pCur_dict) * 2) +
3943                         (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q);
3944         if (!probe_len)
3945           cur_match_len = cur_match_dist ? TDEFL_MAX_MATCH_LEN : 0;
3946 
3947         if ((cur_match_len < TDEFL_MIN_MATCH_LEN) ||
3948             ((cur_match_len == TDEFL_MIN_MATCH_LEN) &&
3949              (cur_match_dist >= 8U * 1024U))) {
3950           cur_match_len = 1;
3951           *pLZ_code_buf++ = (mz_uint8)first_trigram;
3952           *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
3953           d->m_huff_count[0][(mz_uint8)first_trigram]++;
3954         } else {
3955           mz_uint32 s0, s1;
3956           cur_match_len = MZ_MIN(cur_match_len, lookahead_size);
3957 
3958           MZ_ASSERT((cur_match_len >= TDEFL_MIN_MATCH_LEN) &&
3959                     (cur_match_dist >= 1) &&
3960                     (cur_match_dist <= TDEFL_LZ_DICT_SIZE));
3961 
3962           cur_match_dist--;
3963 
3964           pLZ_code_buf[0] = (mz_uint8)(cur_match_len - TDEFL_MIN_MATCH_LEN);
3965           *(mz_uint16 *)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist;
3966           pLZ_code_buf += 3;
3967           *pLZ_flags = (mz_uint8)((*pLZ_flags >> 1) | 0x80);
3968 
3969           s0 = s_tdefl_small_dist_sym[cur_match_dist & 511];
3970           s1 = s_tdefl_large_dist_sym[cur_match_dist >> 8];
3971           d->m_huff_count[1][(cur_match_dist < 512) ? s0 : s1]++;
3972 
3973           d->m_huff_count[0][s_tdefl_len_sym[cur_match_len -
3974                                              TDEFL_MIN_MATCH_LEN]]++;
3975         }
3976       } else {
3977         *pLZ_code_buf++ = (mz_uint8)first_trigram;
3978         *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
3979         d->m_huff_count[0][(mz_uint8)first_trigram]++;
3980       }
3981 
3982       if (--num_flags_left == 0) {
3983         num_flags_left = 8;
3984         pLZ_flags = pLZ_code_buf++;
3985       }
3986 
3987       total_lz_bytes += cur_match_len;
3988       lookahead_pos += cur_match_len;
3989       dict_size = MZ_MIN(dict_size + cur_match_len, TDEFL_LZ_DICT_SIZE);
3990       cur_pos = (cur_pos + cur_match_len) & TDEFL_LZ_DICT_SIZE_MASK;
3991       MZ_ASSERT(lookahead_size >= cur_match_len);
3992       lookahead_size -= cur_match_len;
3993 
3994       if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) {
3995         int n;
3996         d->m_lookahead_pos = lookahead_pos;
3997         d->m_lookahead_size = lookahead_size;
3998         d->m_dict_size = dict_size;
3999         d->m_total_lz_bytes = total_lz_bytes;
4000         d->m_pLZ_code_buf = pLZ_code_buf;
4001         d->m_pLZ_flags = pLZ_flags;
4002         d->m_num_flags_left = num_flags_left;
4003         if ((n = tdefl_flush_block(d, 0)) != 0)
4004           return (n < 0) ? MZ_FALSE : MZ_TRUE;
4005         total_lz_bytes = d->m_total_lz_bytes;
4006         pLZ_code_buf = d->m_pLZ_code_buf;
4007         pLZ_flags = d->m_pLZ_flags;
4008         num_flags_left = d->m_num_flags_left;
4009       }
4010     }
4011 
4012     while (lookahead_size) {
4013       mz_uint8 lit = d->m_dict[cur_pos];
4014 
4015       total_lz_bytes++;
4016       *pLZ_code_buf++ = lit;
4017       *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
4018       if (--num_flags_left == 0) {
4019         num_flags_left = 8;
4020         pLZ_flags = pLZ_code_buf++;
4021       }
4022 
4023       d->m_huff_count[0][lit]++;
4024 
4025       lookahead_pos++;
4026       dict_size = MZ_MIN(dict_size + 1, TDEFL_LZ_DICT_SIZE);
4027       cur_pos = (cur_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK;
4028       lookahead_size--;
4029 
4030       if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) {
4031         int n;
4032         d->m_lookahead_pos = lookahead_pos;
4033         d->m_lookahead_size = lookahead_size;
4034         d->m_dict_size = dict_size;
4035         d->m_total_lz_bytes = total_lz_bytes;
4036         d->m_pLZ_code_buf = pLZ_code_buf;
4037         d->m_pLZ_flags = pLZ_flags;
4038         d->m_num_flags_left = num_flags_left;
4039         if ((n = tdefl_flush_block(d, 0)) != 0)
4040           return (n < 0) ? MZ_FALSE : MZ_TRUE;
4041         total_lz_bytes = d->m_total_lz_bytes;
4042         pLZ_code_buf = d->m_pLZ_code_buf;
4043         pLZ_flags = d->m_pLZ_flags;
4044         num_flags_left = d->m_num_flags_left;
4045       }
4046     }
4047   }
4048 
4049   d->m_lookahead_pos = lookahead_pos;
4050   d->m_lookahead_size = lookahead_size;
4051   d->m_dict_size = dict_size;
4052   d->m_total_lz_bytes = total_lz_bytes;
4053   d->m_pLZ_code_buf = pLZ_code_buf;
4054   d->m_pLZ_flags = pLZ_flags;
4055   d->m_num_flags_left = num_flags_left;
4056   return MZ_TRUE;
4057 }
4058 #endif  // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
4059 
tdefl_record_literal(tdefl_compressor * d,mz_uint8 lit)4060 static MZ_FORCEINLINE void tdefl_record_literal(tdefl_compressor *d,
4061                                                 mz_uint8 lit) {
4062   d->m_total_lz_bytes++;
4063   *d->m_pLZ_code_buf++ = lit;
4064   *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> 1);
4065   if (--d->m_num_flags_left == 0) {
4066     d->m_num_flags_left = 8;
4067     d->m_pLZ_flags = d->m_pLZ_code_buf++;
4068   }
4069   d->m_huff_count[0][lit]++;
4070 }
4071 
tdefl_record_match(tdefl_compressor * d,mz_uint match_len,mz_uint match_dist)4072 static MZ_FORCEINLINE void tdefl_record_match(tdefl_compressor *d,
4073                                               mz_uint match_len,
4074                                               mz_uint match_dist) {
4075   mz_uint32 s0, s1;
4076 
4077   MZ_ASSERT((match_len >= TDEFL_MIN_MATCH_LEN) && (match_dist >= 1) &&
4078             (match_dist <= TDEFL_LZ_DICT_SIZE));
4079 
4080   d->m_total_lz_bytes += match_len;
4081 
4082   d->m_pLZ_code_buf[0] = (mz_uint8)(match_len - TDEFL_MIN_MATCH_LEN);
4083 
4084   match_dist -= 1;
4085   d->m_pLZ_code_buf[1] = (mz_uint8)(match_dist & 0xFF);
4086   d->m_pLZ_code_buf[2] = (mz_uint8)(match_dist >> 8);
4087   d->m_pLZ_code_buf += 3;
4088 
4089   *d->m_pLZ_flags = (mz_uint8)((*d->m_pLZ_flags >> 1) | 0x80);
4090   if (--d->m_num_flags_left == 0) {
4091     d->m_num_flags_left = 8;
4092     d->m_pLZ_flags = d->m_pLZ_code_buf++;
4093   }
4094 
4095   s0 = s_tdefl_small_dist_sym[match_dist & 511];
4096   s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127];
4097   d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++;
4098 
4099   if (match_len >= TDEFL_MIN_MATCH_LEN)
4100     d->m_huff_count[0][s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++;
4101 }
4102 
tdefl_compress_normal(tdefl_compressor * d)4103 static mz_bool tdefl_compress_normal(tdefl_compressor *d) {
4104   const mz_uint8 *pSrc = d->m_pSrc;
4105   size_t src_buf_left = d->m_src_buf_left;
4106   tdefl_flush flush = d->m_flush;
4107 
4108   while ((src_buf_left) || ((flush) && (d->m_lookahead_size))) {
4109     mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos;
4110     // Update dictionary and hash chains. Keeps the lookahead size equal to
4111     // TDEFL_MAX_MATCH_LEN.
4112     if ((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1)) {
4113       mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) &
4114                         TDEFL_LZ_DICT_SIZE_MASK,
4115               ins_pos = d->m_lookahead_pos + d->m_lookahead_size - 2;
4116       mz_uint hash = (d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK]
4117                       << TDEFL_LZ_HASH_SHIFT) ^
4118                      d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK];
4119       mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(
4120           src_buf_left, TDEFL_MAX_MATCH_LEN - d->m_lookahead_size);
4121       const mz_uint8 *pSrc_end = pSrc + num_bytes_to_process;
4122       src_buf_left -= num_bytes_to_process;
4123       d->m_lookahead_size += num_bytes_to_process;
4124       while (pSrc != pSrc_end) {
4125         mz_uint8 c = *pSrc++;
4126         d->m_dict[dst_pos] = c;
4127         if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
4128           d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
4129         hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1);
4130         d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash];
4131         d->m_hash[hash] = (mz_uint16)(ins_pos);
4132         dst_pos = (dst_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK;
4133         ins_pos++;
4134       }
4135     } else {
4136       while ((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) {
4137         mz_uint8 c = *pSrc++;
4138         mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) &
4139                           TDEFL_LZ_DICT_SIZE_MASK;
4140         src_buf_left--;
4141         d->m_dict[dst_pos] = c;
4142         if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
4143           d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
4144         if ((++d->m_lookahead_size + d->m_dict_size) >= TDEFL_MIN_MATCH_LEN) {
4145           mz_uint ins_pos = d->m_lookahead_pos + (d->m_lookahead_size - 1) - 2;
4146           mz_uint hash = ((d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK]
4147                            << (TDEFL_LZ_HASH_SHIFT * 2)) ^
4148                           (d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK]
4149                            << TDEFL_LZ_HASH_SHIFT) ^
4150                           c) &
4151                          (TDEFL_LZ_HASH_SIZE - 1);
4152           d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash];
4153           d->m_hash[hash] = (mz_uint16)(ins_pos);
4154         }
4155       }
4156     }
4157     d->m_dict_size =
4158         MZ_MIN(TDEFL_LZ_DICT_SIZE - d->m_lookahead_size, d->m_dict_size);
4159     if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) break;
4160 
4161     // Simple lazy/greedy parsing state machine.
4162     len_to_move = 1;
4163     cur_match_dist = 0;
4164     cur_match_len =
4165         d->m_saved_match_len ? d->m_saved_match_len : (TDEFL_MIN_MATCH_LEN - 1);
4166     cur_pos = d->m_lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
4167     if (d->m_flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS)) {
4168       if ((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))) {
4169         mz_uint8 c = d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK];
4170         cur_match_len = 0;
4171         while (cur_match_len < d->m_lookahead_size) {
4172           if (d->m_dict[cur_pos + cur_match_len] != c) break;
4173           cur_match_len++;
4174         }
4175         if (cur_match_len < TDEFL_MIN_MATCH_LEN)
4176           cur_match_len = 0;
4177         else
4178           cur_match_dist = 1;
4179       }
4180     } else {
4181       tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size,
4182                        d->m_lookahead_size, &cur_match_dist, &cur_match_len);
4183     }
4184     if (((cur_match_len == TDEFL_MIN_MATCH_LEN) &&
4185          (cur_match_dist >= 8U * 1024U)) ||
4186         (cur_pos == cur_match_dist) ||
4187         ((d->m_flags & TDEFL_FILTER_MATCHES) && (cur_match_len <= 5))) {
4188       cur_match_dist = cur_match_len = 0;
4189     }
4190     if (d->m_saved_match_len) {
4191       if (cur_match_len > d->m_saved_match_len) {
4192         tdefl_record_literal(d, (mz_uint8)d->m_saved_lit);
4193         if (cur_match_len >= 128) {
4194           tdefl_record_match(d, cur_match_len, cur_match_dist);
4195           d->m_saved_match_len = 0;
4196           len_to_move = cur_match_len;
4197         } else {
4198           d->m_saved_lit = d->m_dict[cur_pos];
4199           d->m_saved_match_dist = cur_match_dist;
4200           d->m_saved_match_len = cur_match_len;
4201         }
4202       } else {
4203         tdefl_record_match(d, d->m_saved_match_len, d->m_saved_match_dist);
4204         len_to_move = d->m_saved_match_len - 1;
4205         d->m_saved_match_len = 0;
4206       }
4207     } else if (!cur_match_dist)
4208       tdefl_record_literal(d,
4209                            d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]);
4210     else if ((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) ||
4211              (cur_match_len >= 128)) {
4212       tdefl_record_match(d, cur_match_len, cur_match_dist);
4213       len_to_move = cur_match_len;
4214     } else {
4215       d->m_saved_lit = d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)];
4216       d->m_saved_match_dist = cur_match_dist;
4217       d->m_saved_match_len = cur_match_len;
4218     }
4219     // Move the lookahead forward by len_to_move bytes.
4220     d->m_lookahead_pos += len_to_move;
4221     MZ_ASSERT(d->m_lookahead_size >= len_to_move);
4222     d->m_lookahead_size -= len_to_move;
4223     d->m_dict_size =
4224         MZ_MIN(d->m_dict_size + len_to_move, (mz_uint)TDEFL_LZ_DICT_SIZE);
4225     // Check if it's time to flush the current LZ codes to the internal output
4226     // buffer.
4227     if ((d->m_pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) ||
4228         ((d->m_total_lz_bytes > 31 * 1024) &&
4229          (((((mz_uint)(d->m_pLZ_code_buf - d->m_lz_code_buf) * 115) >> 7) >=
4230            d->m_total_lz_bytes) ||
4231           (d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS)))) {
4232       int n;
4233       d->m_pSrc = pSrc;
4234       d->m_src_buf_left = src_buf_left;
4235       if ((n = tdefl_flush_block(d, 0)) != 0)
4236         return (n < 0) ? MZ_FALSE : MZ_TRUE;
4237     }
4238   }
4239 
4240   d->m_pSrc = pSrc;
4241   d->m_src_buf_left = src_buf_left;
4242   return MZ_TRUE;
4243 }
4244 
tdefl_flush_output_buffer(tdefl_compressor * d)4245 static tdefl_status tdefl_flush_output_buffer(tdefl_compressor *d) {
4246   if (d->m_pIn_buf_size) {
4247     *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
4248   }
4249 
4250   if (d->m_pOut_buf_size) {
4251     size_t n = MZ_MIN(*d->m_pOut_buf_size - d->m_out_buf_ofs,
4252                       d->m_output_flush_remaining);
4253     memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs,
4254            d->m_output_buf + d->m_output_flush_ofs, n);
4255     d->m_output_flush_ofs += (mz_uint)n;
4256     d->m_output_flush_remaining -= (mz_uint)n;
4257     d->m_out_buf_ofs += n;
4258 
4259     *d->m_pOut_buf_size = d->m_out_buf_ofs;
4260   }
4261 
4262   return (d->m_finished && !d->m_output_flush_remaining) ? TDEFL_STATUS_DONE
4263                                                          : TDEFL_STATUS_OKAY;
4264 }
4265 
tdefl_compress(tdefl_compressor * d,const void * pIn_buf,size_t * pIn_buf_size,void * pOut_buf,size_t * pOut_buf_size,tdefl_flush flush)4266 tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf,
4267                             size_t *pIn_buf_size, void *pOut_buf,
4268                             size_t *pOut_buf_size, tdefl_flush flush) {
4269   if (!d) {
4270     if (pIn_buf_size) *pIn_buf_size = 0;
4271     if (pOut_buf_size) *pOut_buf_size = 0;
4272     return TDEFL_STATUS_BAD_PARAM;
4273   }
4274 
4275   d->m_pIn_buf = pIn_buf;
4276   d->m_pIn_buf_size = pIn_buf_size;
4277   d->m_pOut_buf = pOut_buf;
4278   d->m_pOut_buf_size = pOut_buf_size;
4279   d->m_pSrc = (const mz_uint8 *)(pIn_buf);
4280   d->m_src_buf_left = pIn_buf_size ? *pIn_buf_size : 0;
4281   d->m_out_buf_ofs = 0;
4282   d->m_flush = flush;
4283 
4284   if (((d->m_pPut_buf_func != NULL) ==
4285        ((pOut_buf != NULL) || (pOut_buf_size != NULL))) ||
4286       (d->m_prev_return_status != TDEFL_STATUS_OKAY) ||
4287       (d->m_wants_to_finish && (flush != TDEFL_FINISH)) ||
4288       (pIn_buf_size && *pIn_buf_size && !pIn_buf) ||
4289       (pOut_buf_size && *pOut_buf_size && !pOut_buf)) {
4290     if (pIn_buf_size) *pIn_buf_size = 0;
4291     if (pOut_buf_size) *pOut_buf_size = 0;
4292     return (d->m_prev_return_status = TDEFL_STATUS_BAD_PARAM);
4293   }
4294   d->m_wants_to_finish |= (flush == TDEFL_FINISH);
4295 
4296   if ((d->m_output_flush_remaining) || (d->m_finished))
4297     return (d->m_prev_return_status = tdefl_flush_output_buffer(d));
4298 
4299 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
4300   if (((d->m_flags & TDEFL_MAX_PROBES_MASK) == 1) &&
4301       ((d->m_flags & TDEFL_GREEDY_PARSING_FLAG) != 0) &&
4302       ((d->m_flags & (TDEFL_FILTER_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS |
4303                       TDEFL_RLE_MATCHES)) == 0)) {
4304     if (!tdefl_compress_fast(d)) return d->m_prev_return_status;
4305   } else
4306 #endif  // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
4307   {
4308     if (!tdefl_compress_normal(d)) return d->m_prev_return_status;
4309   }
4310 
4311   if ((d->m_flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32)) &&
4312       (pIn_buf))
4313     d->m_adler32 =
4314         (mz_uint32)mz_adler32(d->m_adler32, (const mz_uint8 *)pIn_buf,
4315                               d->m_pSrc - (const mz_uint8 *)pIn_buf);
4316 
4317   if ((flush) && (!d->m_lookahead_size) && (!d->m_src_buf_left) &&
4318       (!d->m_output_flush_remaining)) {
4319     if (tdefl_flush_block(d, flush) < 0) return d->m_prev_return_status;
4320     d->m_finished = (flush == TDEFL_FINISH);
4321     if (flush == TDEFL_FULL_FLUSH) {
4322       MZ_CLEAR_OBJ(d->m_hash);
4323       MZ_CLEAR_OBJ(d->m_next);
4324       d->m_dict_size = 0;
4325     }
4326   }
4327 
4328   return (d->m_prev_return_status = tdefl_flush_output_buffer(d));
4329 }
4330 
tdefl_compress_buffer(tdefl_compressor * d,const void * pIn_buf,size_t in_buf_size,tdefl_flush flush)4331 tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf,
4332                                    size_t in_buf_size, tdefl_flush flush) {
4333   MZ_ASSERT(d->m_pPut_buf_func);
4334   return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush);
4335 }
4336 
tdefl_init(tdefl_compressor * d,tdefl_put_buf_func_ptr pPut_buf_func,void * pPut_buf_user,int flags)4337 tdefl_status tdefl_init(tdefl_compressor *d,
4338                         tdefl_put_buf_func_ptr pPut_buf_func,
4339                         void *pPut_buf_user, int flags) {
4340   d->m_pPut_buf_func = pPut_buf_func;
4341   d->m_pPut_buf_user = pPut_buf_user;
4342   d->m_flags = (mz_uint)(flags);
4343   d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3;
4344   d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0;
4345   d->m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3;
4346   if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG)) MZ_CLEAR_OBJ(d->m_hash);
4347   d->m_lookahead_pos = d->m_lookahead_size = d->m_dict_size =
4348       d->m_total_lz_bytes = d->m_lz_code_buf_dict_pos = d->m_bits_in = 0;
4349   d->m_output_flush_ofs = d->m_output_flush_remaining = d->m_finished =
4350       d->m_block_index = d->m_bit_buffer = d->m_wants_to_finish = 0;
4351   d->m_pLZ_code_buf = d->m_lz_code_buf + 1;
4352   d->m_pLZ_flags = d->m_lz_code_buf;
4353   d->m_num_flags_left = 8;
4354   d->m_pOutput_buf = d->m_output_buf;
4355   d->m_pOutput_buf_end = d->m_output_buf;
4356   d->m_prev_return_status = TDEFL_STATUS_OKAY;
4357   d->m_saved_match_dist = d->m_saved_match_len = d->m_saved_lit = 0;
4358   d->m_adler32 = 1;
4359   d->m_pIn_buf = NULL;
4360   d->m_pOut_buf = NULL;
4361   d->m_pIn_buf_size = NULL;
4362   d->m_pOut_buf_size = NULL;
4363   d->m_flush = TDEFL_NO_FLUSH;
4364   d->m_pSrc = NULL;
4365   d->m_src_buf_left = 0;
4366   d->m_out_buf_ofs = 0;
4367   memset(&d->m_huff_count[0][0], 0,
4368          sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
4369   memset(&d->m_huff_count[1][0], 0,
4370          sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
4371   return TDEFL_STATUS_OKAY;
4372 }
4373 
tdefl_get_prev_return_status(tdefl_compressor * d)4374 tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d) {
4375   return d->m_prev_return_status;
4376 }
4377 
tdefl_get_adler32(tdefl_compressor * d)4378 mz_uint32 tdefl_get_adler32(tdefl_compressor *d) { return d->m_adler32; }
4379 
tdefl_compress_mem_to_output(const void * pBuf,size_t buf_len,tdefl_put_buf_func_ptr pPut_buf_func,void * pPut_buf_user,int flags)4380 mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len,
4381                                      tdefl_put_buf_func_ptr pPut_buf_func,
4382                                      void *pPut_buf_user, int flags) {
4383   tdefl_compressor *pComp;
4384   mz_bool succeeded;
4385   if (((buf_len) && (!pBuf)) || (!pPut_buf_func)) return MZ_FALSE;
4386   pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor));
4387   if (!pComp) return MZ_FALSE;
4388   succeeded = (tdefl_init(pComp, pPut_buf_func, pPut_buf_user, flags) ==
4389                TDEFL_STATUS_OKAY);
4390   succeeded =
4391       succeeded && (tdefl_compress_buffer(pComp, pBuf, buf_len, TDEFL_FINISH) ==
4392                     TDEFL_STATUS_DONE);
4393   MZ_FREE(pComp);
4394   return succeeded;
4395 }
4396 
4397 typedef struct {
4398   size_t m_size, m_capacity;
4399   mz_uint8 *m_pBuf;
4400   mz_bool m_expandable;
4401 } tdefl_output_buffer;
4402 
tdefl_output_buffer_putter(const void * pBuf,int len,void * pUser)4403 static mz_bool tdefl_output_buffer_putter(const void *pBuf, int len,
4404                                           void *pUser) {
4405   tdefl_output_buffer *p = (tdefl_output_buffer *)pUser;
4406   size_t new_size = p->m_size + len;
4407   if (new_size > p->m_capacity) {
4408     size_t new_capacity = p->m_capacity;
4409     mz_uint8 *pNew_buf;
4410     if (!p->m_expandable) return MZ_FALSE;
4411     do {
4412       new_capacity = MZ_MAX(128U, new_capacity << 1U);
4413     } while (new_size > new_capacity);
4414     pNew_buf = (mz_uint8 *)MZ_REALLOC(p->m_pBuf, new_capacity);
4415     if (!pNew_buf) return MZ_FALSE;
4416     p->m_pBuf = pNew_buf;
4417     p->m_capacity = new_capacity;
4418   }
4419   memcpy((mz_uint8 *)p->m_pBuf + p->m_size, pBuf, len);
4420   p->m_size = new_size;
4421   return MZ_TRUE;
4422 }
4423 
tdefl_compress_mem_to_heap(const void * pSrc_buf,size_t src_buf_len,size_t * pOut_len,int flags)4424 void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len,
4425                                  size_t *pOut_len, int flags) {
4426   tdefl_output_buffer out_buf;
4427   MZ_CLEAR_OBJ(out_buf);
4428   if (!pOut_len)
4429     return MZ_FALSE;
4430   else
4431     *pOut_len = 0;
4432   out_buf.m_expandable = MZ_TRUE;
4433   if (!tdefl_compress_mem_to_output(
4434           pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags))
4435     return NULL;
4436   *pOut_len = out_buf.m_size;
4437   return out_buf.m_pBuf;
4438 }
4439 
tdefl_compress_mem_to_mem(void * pOut_buf,size_t out_buf_len,const void * pSrc_buf,size_t src_buf_len,int flags)4440 size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len,
4441                                  const void *pSrc_buf, size_t src_buf_len,
4442                                  int flags) {
4443   tdefl_output_buffer out_buf;
4444   MZ_CLEAR_OBJ(out_buf);
4445   if (!pOut_buf) return 0;
4446   out_buf.m_pBuf = (mz_uint8 *)pOut_buf;
4447   out_buf.m_capacity = out_buf_len;
4448   if (!tdefl_compress_mem_to_output(
4449           pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags))
4450     return 0;
4451   return out_buf.m_size;
4452 }
4453 
4454 #ifndef MINIZ_NO_ZLIB_APIS
4455 static const mz_uint s_tdefl_num_probes[11] = {0,   1,   6,   32,  16,  32,
4456                                                128, 256, 512, 768, 1500};
4457 
4458 // level may actually range from [0,10] (10 is a "hidden" max level, where we
4459 // want a bit more compression and it's fine if throughput to fall off a cliff
4460 // on some files).
tdefl_create_comp_flags_from_zip_params(int level,int window_bits,int strategy)4461 mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits,
4462                                                 int strategy) {
4463   mz_uint comp_flags =
4464       s_tdefl_num_probes[(level >= 0) ? MZ_MIN(10, level) : MZ_DEFAULT_LEVEL] |
4465       ((level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0);
4466   if (window_bits > 0) comp_flags |= TDEFL_WRITE_ZLIB_HEADER;
4467 
4468   if (!level)
4469     comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS;
4470   else if (strategy == MZ_FILTERED)
4471     comp_flags |= TDEFL_FILTER_MATCHES;
4472   else if (strategy == MZ_HUFFMAN_ONLY)
4473     comp_flags &= ~TDEFL_MAX_PROBES_MASK;
4474   else if (strategy == MZ_FIXED)
4475     comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS;
4476   else if (strategy == MZ_RLE)
4477     comp_flags |= TDEFL_RLE_MATCHES;
4478 
4479   return comp_flags;
4480 }
4481 #endif  // MINIZ_NO_ZLIB_APIS
4482 
4483 #ifdef _MSC_VER
4484 #pragma warning(push)
4485 #pragma warning(disable : 4204)  // nonstandard extension used : non-constant
4486                                  // aggregate initializer (also supported by GNU
4487                                  // C and C99, so no big deal)
4488 #pragma warning(disable : 4244)  // 'initializing': conversion from '__int64' to
4489                                  // 'int', possible loss of data
4490 #pragma warning(disable : 4267)  // 'argument': conversion from '__int64' to
4491                                  // 'int', possible loss of data
4492 #pragma warning(disable : 4996)  // 'strdup': The POSIX name for this item is
4493                                  // deprecated. Instead, use the ISO C and C++
4494                                  // conformant name: _strdup.
4495 #endif
4496 
4497 // Simple PNG writer function by Alex Evans, 2011. Released into the public
4498 // domain: https://gist.github.com/908299, more context at
4499 // http://altdevblogaday.org/2011/04/06/a-smaller-jpg-encoder/.
4500 // This is actually a modification of Alex's original code so PNG files
4501 // generated by this function pass pngcheck.
tdefl_write_image_to_png_file_in_memory_ex(const void * pImage,int w,int h,int num_chans,size_t * pLen_out,mz_uint level,mz_bool flip)4502 void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w,
4503                                                  int h, int num_chans,
4504                                                  size_t *pLen_out,
4505                                                  mz_uint level, mz_bool flip) {
4506   // Using a local copy of this array here in case MINIZ_NO_ZLIB_APIS was
4507   // defined.
4508   static const mz_uint s_tdefl_png_num_probes[11] = {
4509       0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500};
4510   tdefl_compressor *pComp =
4511       (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor));
4512   tdefl_output_buffer out_buf;
4513   int i, bpl = w * num_chans, y, z;
4514   mz_uint32 c;
4515   *pLen_out = 0;
4516   if (!pComp) return NULL;
4517   MZ_CLEAR_OBJ(out_buf);
4518   out_buf.m_expandable = MZ_TRUE;
4519   out_buf.m_capacity = 57 + MZ_MAX(64, (1 + bpl) * h);
4520   if (NULL == (out_buf.m_pBuf = (mz_uint8 *)MZ_MALLOC(out_buf.m_capacity))) {
4521     MZ_FREE(pComp);
4522     return NULL;
4523   }
4524   // write dummy header
4525   for (z = 41; z; --z) tdefl_output_buffer_putter(&z, 1, &out_buf);
4526   // compress image data
4527   tdefl_init(
4528       pComp, tdefl_output_buffer_putter, &out_buf,
4529       s_tdefl_png_num_probes[MZ_MIN(10, level)] | TDEFL_WRITE_ZLIB_HEADER);
4530   for (y = 0; y < h; ++y) {
4531     tdefl_compress_buffer(pComp, &z, 1, TDEFL_NO_FLUSH);
4532     tdefl_compress_buffer(pComp,
4533                           (mz_uint8 *)pImage + (flip ? (h - 1 - y) : y) * bpl,
4534                           bpl, TDEFL_NO_FLUSH);
4535   }
4536   if (tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) !=
4537       TDEFL_STATUS_DONE) {
4538     MZ_FREE(pComp);
4539     MZ_FREE(out_buf.m_pBuf);
4540     return NULL;
4541   }
4542   // write real header
4543   *pLen_out = out_buf.m_size - 41;
4544   {
4545     static const mz_uint8 chans[] = {0x00, 0x00, 0x04, 0x02, 0x06};
4546     mz_uint8 pnghdr[41] = {0x89,
4547                            0x50,
4548                            0x4e,
4549                            0x47,
4550                            0x0d,
4551                            0x0a,
4552                            0x1a,
4553                            0x0a,
4554                            0x00,
4555                            0x00,
4556                            0x00,
4557                            0x0d,
4558                            0x49,
4559                            0x48,
4560                            0x44,
4561                            0x52,
4562                            0,
4563                            0,
4564                            (mz_uint8)(w >> 8),
4565                            (mz_uint8)w,
4566                            0,
4567                            0,
4568                            (mz_uint8)(h >> 8),
4569                            (mz_uint8)h,
4570                            8,
4571                            chans[num_chans],
4572                            0,
4573                            0,
4574                            0,
4575                            0,
4576                            0,
4577                            0,
4578                            0,
4579                            (mz_uint8)(*pLen_out >> 24),
4580                            (mz_uint8)(*pLen_out >> 16),
4581                            (mz_uint8)(*pLen_out >> 8),
4582                            (mz_uint8)*pLen_out,
4583                            0x49,
4584                            0x44,
4585                            0x41,
4586                            0x54};
4587     c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, pnghdr + 12, 17);
4588     for (i = 0; i < 4; ++i, c <<= 8)
4589       ((mz_uint8 *)(pnghdr + 29))[i] = (mz_uint8)(c >> 24);
4590     memcpy(out_buf.m_pBuf, pnghdr, 41);
4591   }
4592   // write footer (IDAT CRC-32, followed by IEND chunk)
4593   if (!tdefl_output_buffer_putter(
4594           "\0\0\0\0\0\0\0\0\x49\x45\x4e\x44\xae\x42\x60\x82", 16, &out_buf)) {
4595     *pLen_out = 0;
4596     MZ_FREE(pComp);
4597     MZ_FREE(out_buf.m_pBuf);
4598     return NULL;
4599   }
4600   c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, out_buf.m_pBuf + 41 - 4,
4601                           *pLen_out + 4);
4602   for (i = 0; i < 4; ++i, c <<= 8)
4603     (out_buf.m_pBuf + out_buf.m_size - 16)[i] = (mz_uint8)(c >> 24);
4604   // compute final size of file, grab compressed data buffer and return
4605   *pLen_out += 57;
4606   MZ_FREE(pComp);
4607   return out_buf.m_pBuf;
4608 }
tdefl_write_image_to_png_file_in_memory(const void * pImage,int w,int h,int num_chans,size_t * pLen_out)4609 void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h,
4610                                               int num_chans, size_t *pLen_out) {
4611   // Level 6 corresponds to TDEFL_DEFAULT_MAX_PROBES or MZ_DEFAULT_LEVEL (but we
4612   // can't depend on MZ_DEFAULT_LEVEL being available in case the zlib API's
4613   // where #defined out)
4614   return tdefl_write_image_to_png_file_in_memory_ex(pImage, w, h, num_chans,
4615                                                     pLen_out, 6, MZ_FALSE);
4616 }
4617 
4618 // ------------------- .ZIP archive reading
4619 
4620 #ifndef MINIZ_NO_ARCHIVE_APIS
4621 #error "No arvhive APIs"
4622 
4623 #ifdef MINIZ_NO_STDIO
4624 #define MZ_FILE void *
4625 #else
4626 #include <stdio.h>
4627 #include <sys/stat.h>
4628 
4629 #if defined(_MSC_VER) || defined(__MINGW64__)
mz_fopen(const char * pFilename,const char * pMode)4630 static FILE *mz_fopen(const char *pFilename, const char *pMode) {
4631   FILE *pFile = NULL;
4632   fopen_s(&pFile, pFilename, pMode);
4633   return pFile;
4634 }
mz_freopen(const char * pPath,const char * pMode,FILE * pStream)4635 static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream) {
4636   FILE *pFile = NULL;
4637   if (freopen_s(&pFile, pPath, pMode, pStream)) return NULL;
4638   return pFile;
4639 }
4640 #ifndef MINIZ_NO_TIME
4641 #include <sys/utime.h>
4642 #endif
4643 #define MZ_FILE FILE
4644 #define MZ_FOPEN mz_fopen
4645 #define MZ_FCLOSE fclose
4646 #define MZ_FREAD fread
4647 #define MZ_FWRITE fwrite
4648 #define MZ_FTELL64 _ftelli64
4649 #define MZ_FSEEK64 _fseeki64
4650 #define MZ_FILE_STAT_STRUCT _stat
4651 #define MZ_FILE_STAT _stat
4652 #define MZ_FFLUSH fflush
4653 #define MZ_FREOPEN mz_freopen
4654 #define MZ_DELETE_FILE remove
4655 #elif defined(__MINGW32__)
4656 #ifndef MINIZ_NO_TIME
4657 #include <sys/utime.h>
4658 #endif
4659 #define MZ_FILE FILE
4660 #define MZ_FOPEN(f, m) fopen(f, m)
4661 #define MZ_FCLOSE fclose
4662 #define MZ_FREAD fread
4663 #define MZ_FWRITE fwrite
4664 #define MZ_FTELL64 ftello64
4665 #define MZ_FSEEK64 fseeko64
4666 #define MZ_FILE_STAT_STRUCT _stat
4667 #define MZ_FILE_STAT _stat
4668 #define MZ_FFLUSH fflush
4669 #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
4670 #define MZ_DELETE_FILE remove
4671 #elif defined(__TINYC__)
4672 #ifndef MINIZ_NO_TIME
4673 #include <sys/utime.h>
4674 #endif
4675 #define MZ_FILE FILE
4676 #define MZ_FOPEN(f, m) fopen(f, m)
4677 #define MZ_FCLOSE fclose
4678 #define MZ_FREAD fread
4679 #define MZ_FWRITE fwrite
4680 #define MZ_FTELL64 ftell
4681 #define MZ_FSEEK64 fseek
4682 #define MZ_FILE_STAT_STRUCT stat
4683 #define MZ_FILE_STAT stat
4684 #define MZ_FFLUSH fflush
4685 #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
4686 #define MZ_DELETE_FILE remove
4687 #elif defined(__GNUC__) && defined(_LARGEFILE64_SOURCE) && _LARGEFILE64_SOURCE
4688 #ifndef MINIZ_NO_TIME
4689 #include <utime.h>
4690 #endif
4691 #define MZ_FILE FILE
4692 #define MZ_FOPEN(f, m) fopen64(f, m)
4693 #define MZ_FCLOSE fclose
4694 #define MZ_FREAD fread
4695 #define MZ_FWRITE fwrite
4696 #define MZ_FTELL64 ftello64
4697 #define MZ_FSEEK64 fseeko64
4698 #define MZ_FILE_STAT_STRUCT stat64
4699 #define MZ_FILE_STAT stat64
4700 #define MZ_FFLUSH fflush
4701 #define MZ_FREOPEN(p, m, s) freopen64(p, m, s)
4702 #define MZ_DELETE_FILE remove
4703 #else
4704 #ifndef MINIZ_NO_TIME
4705 #include <utime.h>
4706 #endif
4707 #define MZ_FILE FILE
4708 #define MZ_FOPEN(f, m) fopen(f, m)
4709 #define MZ_FCLOSE fclose
4710 #define MZ_FREAD fread
4711 #define MZ_FWRITE fwrite
4712 #define MZ_FTELL64 ftello
4713 #define MZ_FSEEK64 fseeko
4714 #define MZ_FILE_STAT_STRUCT stat
4715 #define MZ_FILE_STAT stat
4716 #define MZ_FFLUSH fflush
4717 #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
4718 #define MZ_DELETE_FILE remove
4719 #endif  // #ifdef _MSC_VER
4720 #endif  // #ifdef MINIZ_NO_STDIO
4721 
4722 #define MZ_TOLOWER(c) ((((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c))
4723 
4724 // Various ZIP archive enums. To completely avoid cross platform compiler
4725 // alignment and platform endian issues, miniz.c doesn't use structs for any of
4726 // this stuff.
4727 enum {
4728   // ZIP archive identifiers and record sizes
4729   MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06054b50,
4730   MZ_ZIP_CENTRAL_DIR_HEADER_SIG = 0x02014b50,
4731   MZ_ZIP_LOCAL_DIR_HEADER_SIG = 0x04034b50,
4732   MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30,
4733   MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46,
4734   MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22,
4735   // Central directory header record offsets
4736   MZ_ZIP_CDH_SIG_OFS = 0,
4737   MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4,
4738   MZ_ZIP_CDH_VERSION_NEEDED_OFS = 6,
4739   MZ_ZIP_CDH_BIT_FLAG_OFS = 8,
4740   MZ_ZIP_CDH_METHOD_OFS = 10,
4741   MZ_ZIP_CDH_FILE_TIME_OFS = 12,
4742   MZ_ZIP_CDH_FILE_DATE_OFS = 14,
4743   MZ_ZIP_CDH_CRC32_OFS = 16,
4744   MZ_ZIP_CDH_COMPRESSED_SIZE_OFS = 20,
4745   MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS = 24,
4746   MZ_ZIP_CDH_FILENAME_LEN_OFS = 28,
4747   MZ_ZIP_CDH_EXTRA_LEN_OFS = 30,
4748   MZ_ZIP_CDH_COMMENT_LEN_OFS = 32,
4749   MZ_ZIP_CDH_DISK_START_OFS = 34,
4750   MZ_ZIP_CDH_INTERNAL_ATTR_OFS = 36,
4751   MZ_ZIP_CDH_EXTERNAL_ATTR_OFS = 38,
4752   MZ_ZIP_CDH_LOCAL_HEADER_OFS = 42,
4753   // Local directory header offsets
4754   MZ_ZIP_LDH_SIG_OFS = 0,
4755   MZ_ZIP_LDH_VERSION_NEEDED_OFS = 4,
4756   MZ_ZIP_LDH_BIT_FLAG_OFS = 6,
4757   MZ_ZIP_LDH_METHOD_OFS = 8,
4758   MZ_ZIP_LDH_FILE_TIME_OFS = 10,
4759   MZ_ZIP_LDH_FILE_DATE_OFS = 12,
4760   MZ_ZIP_LDH_CRC32_OFS = 14,
4761   MZ_ZIP_LDH_COMPRESSED_SIZE_OFS = 18,
4762   MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS = 22,
4763   MZ_ZIP_LDH_FILENAME_LEN_OFS = 26,
4764   MZ_ZIP_LDH_EXTRA_LEN_OFS = 28,
4765   // End of central directory offsets
4766   MZ_ZIP_ECDH_SIG_OFS = 0,
4767   MZ_ZIP_ECDH_NUM_THIS_DISK_OFS = 4,
4768   MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS = 6,
4769   MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 8,
4770   MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS = 10,
4771   MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12,
4772   MZ_ZIP_ECDH_CDIR_OFS_OFS = 16,
4773   MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20,
4774 };
4775 
4776 typedef struct {
4777   void *m_p;
4778   size_t m_size, m_capacity;
4779   mz_uint m_element_size;
4780 } mz_zip_array;
4781 
4782 struct mz_zip_internal_state_tag {
4783   mz_zip_array m_central_dir;
4784   mz_zip_array m_central_dir_offsets;
4785   mz_zip_array m_sorted_central_dir_offsets;
4786   MZ_FILE *m_pFile;
4787   void *m_pMem;
4788   size_t m_mem_size;
4789   size_t m_mem_capacity;
4790 };
4791 
4792 #define MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(array_ptr, element_size) \
4793   (array_ptr)->m_element_size = element_size
4794 #define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) \
4795   ((element_type *)((array_ptr)->m_p))[index]
4796 
mz_zip_array_clear(mz_zip_archive * pZip,mz_zip_array * pArray)4797 static MZ_FORCEINLINE void mz_zip_array_clear(mz_zip_archive *pZip,
4798                                               mz_zip_array *pArray) {
4799   pZip->m_pFree(pZip->m_pAlloc_opaque, pArray->m_p);
4800   memset(pArray, 0, sizeof(mz_zip_array));
4801 }
4802 
mz_zip_array_ensure_capacity(mz_zip_archive * pZip,mz_zip_array * pArray,size_t min_new_capacity,mz_uint growing)4803 static mz_bool mz_zip_array_ensure_capacity(mz_zip_archive *pZip,
4804                                             mz_zip_array *pArray,
4805                                             size_t min_new_capacity,
4806                                             mz_uint growing) {
4807   void *pNew_p;
4808   size_t new_capacity = min_new_capacity;
4809   MZ_ASSERT(pArray->m_element_size);
4810   if (pArray->m_capacity >= min_new_capacity) return MZ_TRUE;
4811   if (growing) {
4812     new_capacity = MZ_MAX(1, pArray->m_capacity);
4813     while (new_capacity < min_new_capacity) new_capacity *= 2;
4814   }
4815   if (NULL == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p,
4816                                          pArray->m_element_size, new_capacity)))
4817     return MZ_FALSE;
4818   pArray->m_p = pNew_p;
4819   pArray->m_capacity = new_capacity;
4820   return MZ_TRUE;
4821 }
4822 
mz_zip_array_reserve(mz_zip_archive * pZip,mz_zip_array * pArray,size_t new_capacity,mz_uint growing)4823 static MZ_FORCEINLINE mz_bool mz_zip_array_reserve(mz_zip_archive *pZip,
4824                                                    mz_zip_array *pArray,
4825                                                    size_t new_capacity,
4826                                                    mz_uint growing) {
4827   if (new_capacity > pArray->m_capacity) {
4828     if (!mz_zip_array_ensure_capacity(pZip, pArray, new_capacity, growing))
4829       return MZ_FALSE;
4830   }
4831   return MZ_TRUE;
4832 }
4833 
mz_zip_array_resize(mz_zip_archive * pZip,mz_zip_array * pArray,size_t new_size,mz_uint growing)4834 static MZ_FORCEINLINE mz_bool mz_zip_array_resize(mz_zip_archive *pZip,
4835                                                   mz_zip_array *pArray,
4836                                                   size_t new_size,
4837                                                   mz_uint growing) {
4838   if (new_size > pArray->m_capacity) {
4839     if (!mz_zip_array_ensure_capacity(pZip, pArray, new_size, growing))
4840       return MZ_FALSE;
4841   }
4842   pArray->m_size = new_size;
4843   return MZ_TRUE;
4844 }
4845 
mz_zip_array_ensure_room(mz_zip_archive * pZip,mz_zip_array * pArray,size_t n)4846 static MZ_FORCEINLINE mz_bool mz_zip_array_ensure_room(mz_zip_archive *pZip,
4847                                                        mz_zip_array *pArray,
4848                                                        size_t n) {
4849   return mz_zip_array_reserve(pZip, pArray, pArray->m_size + n, MZ_TRUE);
4850 }
4851 
mz_zip_array_push_back(mz_zip_archive * pZip,mz_zip_array * pArray,const void * pElements,size_t n)4852 static MZ_FORCEINLINE mz_bool mz_zip_array_push_back(mz_zip_archive *pZip,
4853                                                      mz_zip_array *pArray,
4854                                                      const void *pElements,
4855                                                      size_t n) {
4856   size_t orig_size = pArray->m_size;
4857   if (!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE))
4858     return MZ_FALSE;
4859   memcpy((mz_uint8 *)pArray->m_p + orig_size * pArray->m_element_size,
4860          pElements, n * pArray->m_element_size);
4861   return MZ_TRUE;
4862 }
4863 
4864 #ifndef MINIZ_NO_TIME
mz_zip_dos_to_time_t(int dos_time,int dos_date)4865 static time_t mz_zip_dos_to_time_t(int dos_time, int dos_date) {
4866   struct tm tm;
4867   memset(&tm, 0, sizeof(tm));
4868   tm.tm_isdst = -1;
4869   tm.tm_year = ((dos_date >> 9) & 127) + 1980 - 1900;
4870   tm.tm_mon = ((dos_date >> 5) & 15) - 1;
4871   tm.tm_mday = dos_date & 31;
4872   tm.tm_hour = (dos_time >> 11) & 31;
4873   tm.tm_min = (dos_time >> 5) & 63;
4874   tm.tm_sec = (dos_time << 1) & 62;
4875   return mktime(&tm);
4876 }
4877 
mz_zip_time_to_dos_time(time_t time,mz_uint16 * pDOS_time,mz_uint16 * pDOS_date)4878 static void mz_zip_time_to_dos_time(time_t time, mz_uint16 *pDOS_time,
4879                                     mz_uint16 *pDOS_date) {
4880 #ifdef _MSC_VER
4881   struct tm tm_struct;
4882   struct tm *tm = &tm_struct;
4883   errno_t err = localtime_s(tm, &time);
4884   if (err) {
4885     *pDOS_date = 0;
4886     *pDOS_time = 0;
4887     return;
4888   }
4889 #else
4890   struct tm *tm = localtime(&time);
4891 #endif
4892   *pDOS_time = (mz_uint16)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) +
4893                            ((tm->tm_sec) >> 1));
4894   *pDOS_date = (mz_uint16)(((tm->tm_year + 1900 - 1980) << 9) +
4895                            ((tm->tm_mon + 1) << 5) + tm->tm_mday);
4896 }
4897 #endif
4898 
4899 #ifndef MINIZ_NO_STDIO
mz_zip_get_file_modified_time(const char * pFilename,mz_uint16 * pDOS_time,mz_uint16 * pDOS_date)4900 static mz_bool mz_zip_get_file_modified_time(const char *pFilename,
4901                                              mz_uint16 *pDOS_time,
4902                                              mz_uint16 *pDOS_date) {
4903 #ifdef MINIZ_NO_TIME
4904   (void)pFilename;
4905   *pDOS_date = *pDOS_time = 0;
4906 #else
4907   struct MZ_FILE_STAT_STRUCT file_stat;
4908   // On Linux with x86 glibc, this call will fail on large files (>= 0x80000000
4909   // bytes) unless you compiled with _LARGEFILE64_SOURCE. Argh.
4910   if (MZ_FILE_STAT(pFilename, &file_stat) != 0) return MZ_FALSE;
4911   mz_zip_time_to_dos_time(file_stat.st_mtime, pDOS_time, pDOS_date);
4912 #endif  // #ifdef MINIZ_NO_TIME
4913   return MZ_TRUE;
4914 }
4915 
4916 #ifndef MINIZ_NO_TIME
mz_zip_set_file_times(const char * pFilename,time_t access_time,time_t modified_time)4917 static mz_bool mz_zip_set_file_times(const char *pFilename, time_t access_time,
4918                                      time_t modified_time) {
4919   struct utimbuf t;
4920   t.actime = access_time;
4921   t.modtime = modified_time;
4922   return !utime(pFilename, &t);
4923 }
4924 #endif  // #ifndef MINIZ_NO_TIME
4925 #endif  // #ifndef MINIZ_NO_STDIO
4926 
mz_zip_reader_init_internal(mz_zip_archive * pZip,mz_uint32 flags)4927 static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip,
4928                                            mz_uint32 flags) {
4929   (void)flags;
4930   if ((!pZip) || (pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
4931     return MZ_FALSE;
4932 
4933   if (!pZip->m_pAlloc) pZip->m_pAlloc = def_alloc_func;
4934   if (!pZip->m_pFree) pZip->m_pFree = def_free_func;
4935   if (!pZip->m_pRealloc) pZip->m_pRealloc = def_realloc_func;
4936 
4937   pZip->m_zip_mode = MZ_ZIP_MODE_READING;
4938   pZip->m_archive_size = 0;
4939   pZip->m_central_directory_file_ofs = 0;
4940   pZip->m_total_files = 0;
4941 
4942   if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(
4943                    pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
4944     return MZ_FALSE;
4945   memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
4946   MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir,
4947                                 sizeof(mz_uint8));
4948   MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets,
4949                                 sizeof(mz_uint32));
4950   MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets,
4951                                 sizeof(mz_uint32));
4952   return MZ_TRUE;
4953 }
4954 
4955 static MZ_FORCEINLINE mz_bool
mz_zip_reader_filename_less(const mz_zip_array * pCentral_dir_array,const mz_zip_array * pCentral_dir_offsets,mz_uint l_index,mz_uint r_index)4956 mz_zip_reader_filename_less(const mz_zip_array *pCentral_dir_array,
4957                             const mz_zip_array *pCentral_dir_offsets,
4958                             mz_uint l_index, mz_uint r_index) {
4959   const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(
4960                      pCentral_dir_array, mz_uint8,
4961                      MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32,
4962                                           l_index)),
4963                  *pE;
4964   const mz_uint8 *pR = &MZ_ZIP_ARRAY_ELEMENT(
4965       pCentral_dir_array, mz_uint8,
4966       MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, r_index));
4967   mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS),
4968           r_len = MZ_READ_LE16(pR + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4969   mz_uint8 l = 0, r = 0;
4970   pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
4971   pR += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
4972   pE = pL + MZ_MIN(l_len, r_len);
4973   while (pL < pE) {
4974     if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR))) break;
4975     pL++;
4976     pR++;
4977   }
4978   return (pL == pE) ? (l_len < r_len) : (l < r);
4979 }
4980 
4981 #define MZ_SWAP_UINT32(a, b) \
4982   do {                       \
4983     mz_uint32 t = a;         \
4984     a = b;                   \
4985     b = t;                   \
4986   }                          \
4987   MZ_MACRO_END
4988 
4989 // Heap sort of lowercased filenames, used to help accelerate plain central
4990 // directory searches by mz_zip_reader_locate_file(). (Could also use qsort(),
4991 // but it could allocate memory.)
mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive * pZip)4992 static void mz_zip_reader_sort_central_dir_offsets_by_filename(
4993     mz_zip_archive *pZip) {
4994   mz_zip_internal_state *pState = pZip->m_pState;
4995   const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
4996   const mz_zip_array *pCentral_dir = &pState->m_central_dir;
4997   mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(
4998       &pState->m_sorted_central_dir_offsets, mz_uint32, 0);
4999   const int size = pZip->m_total_files;
5000   int start = (size - 2) >> 1, end;
5001   while (start >= 0) {
5002     int child, root = start;
5003     for (;;) {
5004       if ((child = (root << 1) + 1) >= size) break;
5005       child +=
5006           (((child + 1) < size) &&
5007            (mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets,
5008                                         pIndices[child], pIndices[child + 1])));
5009       if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets,
5010                                        pIndices[root], pIndices[child]))
5011         break;
5012       MZ_SWAP_UINT32(pIndices[root], pIndices[child]);
5013       root = child;
5014     }
5015     start--;
5016   }
5017 
5018   end = size - 1;
5019   while (end > 0) {
5020     int child, root = 0;
5021     MZ_SWAP_UINT32(pIndices[end], pIndices[0]);
5022     for (;;) {
5023       if ((child = (root << 1) + 1) >= end) break;
5024       child +=
5025           (((child + 1) < end) &&
5026            mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets,
5027                                        pIndices[child], pIndices[child + 1]));
5028       if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets,
5029                                        pIndices[root], pIndices[child]))
5030         break;
5031       MZ_SWAP_UINT32(pIndices[root], pIndices[child]);
5032       root = child;
5033     }
5034     end--;
5035   }
5036 }
5037 
mz_zip_reader_read_central_dir(mz_zip_archive * pZip,mz_uint32 flags)5038 static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip,
5039                                               mz_uint32 flags) {
5040   mz_uint cdir_size, num_this_disk, cdir_disk_index;
5041   mz_uint64 cdir_ofs;
5042   mz_int64 cur_file_ofs;
5043   const mz_uint8 *p;
5044   mz_uint32 buf_u32[4096 / sizeof(mz_uint32)];
5045   mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
5046   mz_bool sort_central_dir =
5047       ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0);
5048   // Basic sanity checks - reject files which are too small, and check the first
5049   // 4 bytes of the file to make sure a local header is there.
5050   if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
5051     return MZ_FALSE;
5052   // Find the end of central directory record by scanning the file from the end
5053   // towards the beginning.
5054   cur_file_ofs =
5055       MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0);
5056   for (;;) {
5057     int i,
5058         n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs);
5059     if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n)
5060       return MZ_FALSE;
5061     for (i = n - 4; i >= 0; --i)
5062       if (MZ_READ_LE32(pBuf + i) == MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) break;
5063     if (i >= 0) {
5064       cur_file_ofs += i;
5065       break;
5066     }
5067     if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >=
5068                             (0xFFFF + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)))
5069       return MZ_FALSE;
5070     cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0);
5071   }
5072   // Read and verify the end of central directory record.
5073   if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf,
5074                     MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) !=
5075       MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
5076     return MZ_FALSE;
5077   if ((MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) !=
5078        MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) ||
5079       ((pZip->m_total_files =
5080             MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS)) !=
5081        MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS)))
5082     return MZ_FALSE;
5083 
5084   num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS);
5085   cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS);
5086   if (((num_this_disk | cdir_disk_index) != 0) &&
5087       ((num_this_disk != 1) || (cdir_disk_index != 1)))
5088     return MZ_FALSE;
5089 
5090   if ((cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS)) <
5091       pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)
5092     return MZ_FALSE;
5093 
5094   cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS);
5095   if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size) return MZ_FALSE;
5096 
5097   pZip->m_central_directory_file_ofs = cdir_ofs;
5098 
5099   if (pZip->m_total_files) {
5100     mz_uint i, n;
5101 
5102     // Read the entire central directory into a heap block, and allocate another
5103     // heap block to hold the unsorted central dir file record offsets, and
5104     // another to hold the sorted indices.
5105     if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size,
5106                               MZ_FALSE)) ||
5107         (!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets,
5108                               pZip->m_total_files, MZ_FALSE)))
5109       return MZ_FALSE;
5110 
5111     if (sort_central_dir) {
5112       if (!mz_zip_array_resize(pZip,
5113                                &pZip->m_pState->m_sorted_central_dir_offsets,
5114                                pZip->m_total_files, MZ_FALSE))
5115         return MZ_FALSE;
5116     }
5117 
5118     if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs,
5119                       pZip->m_pState->m_central_dir.m_p,
5120                       cdir_size) != cdir_size)
5121       return MZ_FALSE;
5122 
5123     // Now create an index into the central directory file records, do some
5124     // basic sanity checking on each record, and check for zip64 entries (which
5125     // are not yet supported).
5126     p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p;
5127     for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i) {
5128       mz_uint total_header_size, comp_size, decomp_size, disk_index;
5129       if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) ||
5130           (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG))
5131         return MZ_FALSE;
5132       MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32,
5133                            i) =
5134           (mz_uint32)(p - (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p);
5135       if (sort_central_dir)
5136         MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets,
5137                              mz_uint32, i) = i;
5138       comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
5139       decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
5140       if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) &&
5141            (decomp_size != comp_size)) ||
5142           (decomp_size && !comp_size) || (decomp_size == 0xFFFFFFFF) ||
5143           (comp_size == 0xFFFFFFFF))
5144         return MZ_FALSE;
5145       disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS);
5146       if ((disk_index != num_this_disk) && (disk_index != 1)) return MZ_FALSE;
5147       if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) +
5148            MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size)
5149         return MZ_FALSE;
5150       if ((total_header_size = MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
5151                                MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) +
5152                                MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS) +
5153                                MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS)) >
5154           n)
5155         return MZ_FALSE;
5156       n -= total_header_size;
5157       p += total_header_size;
5158     }
5159   }
5160 
5161   if (sort_central_dir)
5162     mz_zip_reader_sort_central_dir_offsets_by_filename(pZip);
5163 
5164   return MZ_TRUE;
5165 }
5166 
mz_zip_reader_init(mz_zip_archive * pZip,mz_uint64 size,mz_uint32 flags)5167 mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size,
5168                            mz_uint32 flags) {
5169   if ((!pZip) || (!pZip->m_pRead)) return MZ_FALSE;
5170   if (!mz_zip_reader_init_internal(pZip, flags)) return MZ_FALSE;
5171   pZip->m_archive_size = size;
5172   if (!mz_zip_reader_read_central_dir(pZip, flags)) {
5173     mz_zip_reader_end(pZip);
5174     return MZ_FALSE;
5175   }
5176   return MZ_TRUE;
5177 }
5178 
mz_zip_mem_read_func(void * pOpaque,mz_uint64 file_ofs,void * pBuf,size_t n)5179 static size_t mz_zip_mem_read_func(void *pOpaque, mz_uint64 file_ofs,
5180                                    void *pBuf, size_t n) {
5181   mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
5182   size_t s = (file_ofs >= pZip->m_archive_size)
5183                  ? 0
5184                  : (size_t)MZ_MIN(pZip->m_archive_size - file_ofs, n);
5185   memcpy(pBuf, (const mz_uint8 *)pZip->m_pState->m_pMem + file_ofs, s);
5186   return s;
5187 }
5188 
mz_zip_reader_init_mem(mz_zip_archive * pZip,const void * pMem,size_t size,mz_uint32 flags)5189 mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem,
5190                                size_t size, mz_uint32 flags) {
5191   if (!mz_zip_reader_init_internal(pZip, flags)) return MZ_FALSE;
5192   pZip->m_archive_size = size;
5193   pZip->m_pRead = mz_zip_mem_read_func;
5194   pZip->m_pIO_opaque = pZip;
5195 #ifdef __cplusplus
5196   pZip->m_pState->m_pMem = const_cast<void *>(pMem);
5197 #else
5198   pZip->m_pState->m_pMem = (void *)pMem;
5199 #endif
5200   pZip->m_pState->m_mem_size = size;
5201   if (!mz_zip_reader_read_central_dir(pZip, flags)) {
5202     mz_zip_reader_end(pZip);
5203     return MZ_FALSE;
5204   }
5205   return MZ_TRUE;
5206 }
5207 
5208 #ifndef MINIZ_NO_STDIO
mz_zip_file_read_func(void * pOpaque,mz_uint64 file_ofs,void * pBuf,size_t n)5209 static size_t mz_zip_file_read_func(void *pOpaque, mz_uint64 file_ofs,
5210                                     void *pBuf, size_t n) {
5211   mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
5212   mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
5213   if (((mz_int64)file_ofs < 0) ||
5214       (((cur_ofs != (mz_int64)file_ofs)) &&
5215        (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET))))
5216     return 0;
5217   return MZ_FREAD(pBuf, 1, n, pZip->m_pState->m_pFile);
5218 }
5219 
mz_zip_reader_init_file(mz_zip_archive * pZip,const char * pFilename,mz_uint32 flags)5220 mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename,
5221                                 mz_uint32 flags) {
5222   mz_uint64 file_size;
5223   MZ_FILE *pFile = MZ_FOPEN(pFilename, "rb");
5224   if (!pFile) return MZ_FALSE;
5225   if (MZ_FSEEK64(pFile, 0, SEEK_END)) {
5226     MZ_FCLOSE(pFile);
5227     return MZ_FALSE;
5228   }
5229   file_size = MZ_FTELL64(pFile);
5230   if (!mz_zip_reader_init_internal(pZip, flags)) {
5231     MZ_FCLOSE(pFile);
5232     return MZ_FALSE;
5233   }
5234   pZip->m_pRead = mz_zip_file_read_func;
5235   pZip->m_pIO_opaque = pZip;
5236   pZip->m_pState->m_pFile = pFile;
5237   pZip->m_archive_size = file_size;
5238   if (!mz_zip_reader_read_central_dir(pZip, flags)) {
5239     mz_zip_reader_end(pZip);
5240     return MZ_FALSE;
5241   }
5242   return MZ_TRUE;
5243 }
5244 #endif  // #ifndef MINIZ_NO_STDIO
5245 
mz_zip_reader_get_num_files(mz_zip_archive * pZip)5246 mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip) {
5247   return pZip ? pZip->m_total_files : 0;
5248 }
5249 
mz_zip_reader_get_cdh(mz_zip_archive * pZip,mz_uint file_index)5250 static MZ_FORCEINLINE const mz_uint8 *mz_zip_reader_get_cdh(
5251     mz_zip_archive *pZip, mz_uint file_index) {
5252   if ((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files) ||
5253       (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
5254     return NULL;
5255   return &MZ_ZIP_ARRAY_ELEMENT(
5256       &pZip->m_pState->m_central_dir, mz_uint8,
5257       MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32,
5258                            file_index));
5259 }
5260 
mz_zip_reader_is_file_encrypted(mz_zip_archive * pZip,mz_uint file_index)5261 mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip,
5262                                         mz_uint file_index) {
5263   mz_uint m_bit_flag;
5264   const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
5265   if (!p) return MZ_FALSE;
5266   m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
5267   return (m_bit_flag & 1);
5268 }
5269 
mz_zip_reader_is_file_a_directory(mz_zip_archive * pZip,mz_uint file_index)5270 mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip,
5271                                           mz_uint file_index) {
5272   mz_uint filename_len, external_attr;
5273   const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
5274   if (!p) return MZ_FALSE;
5275 
5276   // First see if the filename ends with a '/' character.
5277   filename_len = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
5278   if (filename_len) {
5279     if (*(p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_len - 1) == '/')
5280       return MZ_TRUE;
5281   }
5282 
5283   // Bugfix: This code was also checking if the internal attribute was non-zero,
5284   // which wasn't correct.
5285   // Most/all zip writers (hopefully) set DOS file/directory attributes in the
5286   // low 16-bits, so check for the DOS directory flag and ignore the source OS
5287   // ID in the created by field.
5288   // FIXME: Remove this check? Is it necessary - we already check the filename.
5289   external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
5290   if ((external_attr & 0x10) != 0) return MZ_TRUE;
5291 
5292   return MZ_FALSE;
5293 }
5294 
mz_zip_reader_file_stat(mz_zip_archive * pZip,mz_uint file_index,mz_zip_archive_file_stat * pStat)5295 mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index,
5296                                 mz_zip_archive_file_stat *pStat) {
5297   mz_uint n;
5298   const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
5299   if ((!p) || (!pStat)) return MZ_FALSE;
5300 
5301   // Unpack the central directory record.
5302   pStat->m_file_index = file_index;
5303   pStat->m_central_dir_ofs = MZ_ZIP_ARRAY_ELEMENT(
5304       &pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index);
5305   pStat->m_version_made_by = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS);
5306   pStat->m_version_needed = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_NEEDED_OFS);
5307   pStat->m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
5308   pStat->m_method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS);
5309 #ifndef MINIZ_NO_TIME
5310   pStat->m_time =
5311       mz_zip_dos_to_time_t(MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_TIME_OFS),
5312                            MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_DATE_OFS));
5313 #endif
5314   pStat->m_crc32 = MZ_READ_LE32(p + MZ_ZIP_CDH_CRC32_OFS);
5315   pStat->m_comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
5316   pStat->m_uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
5317   pStat->m_internal_attr = MZ_READ_LE16(p + MZ_ZIP_CDH_INTERNAL_ATTR_OFS);
5318   pStat->m_external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
5319   pStat->m_local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
5320 
5321   // Copy as much of the filename and comment as possible.
5322   n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
5323   n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE - 1);
5324   memcpy(pStat->m_filename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
5325   pStat->m_filename[n] = '\0';
5326 
5327   n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS);
5328   n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1);
5329   pStat->m_comment_size = n;
5330   memcpy(pStat->m_comment,
5331          p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
5332              MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) +
5333              MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS),
5334          n);
5335   pStat->m_comment[n] = '\0';
5336 
5337   return MZ_TRUE;
5338 }
5339 
mz_zip_reader_get_filename(mz_zip_archive * pZip,mz_uint file_index,char * pFilename,mz_uint filename_buf_size)5340 mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index,
5341                                    char *pFilename, mz_uint filename_buf_size) {
5342   mz_uint n;
5343   const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
5344   if (!p) {
5345     if (filename_buf_size) pFilename[0] = '\0';
5346     return 0;
5347   }
5348   n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
5349   if (filename_buf_size) {
5350     n = MZ_MIN(n, filename_buf_size - 1);
5351     memcpy(pFilename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
5352     pFilename[n] = '\0';
5353   }
5354   return n + 1;
5355 }
5356 
mz_zip_reader_string_equal(const char * pA,const char * pB,mz_uint len,mz_uint flags)5357 static MZ_FORCEINLINE mz_bool mz_zip_reader_string_equal(const char *pA,
5358                                                          const char *pB,
5359                                                          mz_uint len,
5360                                                          mz_uint flags) {
5361   mz_uint i;
5362   if (flags & MZ_ZIP_FLAG_CASE_SENSITIVE) return 0 == memcmp(pA, pB, len);
5363   for (i = 0; i < len; ++i)
5364     if (MZ_TOLOWER(pA[i]) != MZ_TOLOWER(pB[i])) return MZ_FALSE;
5365   return MZ_TRUE;
5366 }
5367 
mz_zip_reader_filename_compare(const mz_zip_array * pCentral_dir_array,const mz_zip_array * pCentral_dir_offsets,mz_uint l_index,const char * pR,mz_uint r_len)5368 static MZ_FORCEINLINE int mz_zip_reader_filename_compare(
5369     const mz_zip_array *pCentral_dir_array,
5370     const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, const char *pR,
5371     mz_uint r_len) {
5372   const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(
5373                      pCentral_dir_array, mz_uint8,
5374                      MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32,
5375                                           l_index)),
5376                  *pE;
5377   mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS);
5378   mz_uint8 l = 0, r = 0;
5379   pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
5380   pE = pL + MZ_MIN(l_len, r_len);
5381   while (pL < pE) {
5382     if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR))) break;
5383     pL++;
5384     pR++;
5385   }
5386   return (pL == pE) ? (int)(l_len - r_len) : (l - r);
5387 }
5388 
mz_zip_reader_locate_file_binary_search(mz_zip_archive * pZip,const char * pFilename)5389 static int mz_zip_reader_locate_file_binary_search(mz_zip_archive *pZip,
5390                                                    const char *pFilename) {
5391   mz_zip_internal_state *pState = pZip->m_pState;
5392   const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
5393   const mz_zip_array *pCentral_dir = &pState->m_central_dir;
5394   mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(
5395       &pState->m_sorted_central_dir_offsets, mz_uint32, 0);
5396   const int size = pZip->m_total_files;
5397   const mz_uint filename_len = (mz_uint)strlen(pFilename);
5398   int l = 0, h = size - 1;
5399   while (l <= h) {
5400     int m = (l + h) >> 1, file_index = pIndices[m],
5401         comp =
5402             mz_zip_reader_filename_compare(pCentral_dir, pCentral_dir_offsets,
5403                                            file_index, pFilename, filename_len);
5404     if (!comp)
5405       return file_index;
5406     else if (comp < 0)
5407       l = m + 1;
5408     else
5409       h = m - 1;
5410   }
5411   return -1;
5412 }
5413 
mz_zip_reader_locate_file(mz_zip_archive * pZip,const char * pName,const char * pComment,mz_uint flags)5414 int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName,
5415                               const char *pComment, mz_uint flags) {
5416   mz_uint file_index;
5417   size_t name_len, comment_len;
5418   if ((!pZip) || (!pZip->m_pState) || (!pName) ||
5419       (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
5420     return -1;
5421   if (((flags & (MZ_ZIP_FLAG_IGNORE_PATH | MZ_ZIP_FLAG_CASE_SENSITIVE)) == 0) &&
5422       (!pComment) && (pZip->m_pState->m_sorted_central_dir_offsets.m_size))
5423     return mz_zip_reader_locate_file_binary_search(pZip, pName);
5424   name_len = strlen(pName);
5425   if (name_len > 0xFFFF) return -1;
5426   comment_len = pComment ? strlen(pComment) : 0;
5427   if (comment_len > 0xFFFF) return -1;
5428   for (file_index = 0; file_index < pZip->m_total_files; file_index++) {
5429     const mz_uint8 *pHeader = &MZ_ZIP_ARRAY_ELEMENT(
5430         &pZip->m_pState->m_central_dir, mz_uint8,
5431         MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32,
5432                              file_index));
5433     mz_uint filename_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS);
5434     const char *pFilename =
5435         (const char *)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
5436     if (filename_len < name_len) continue;
5437     if (comment_len) {
5438       mz_uint file_extra_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_EXTRA_LEN_OFS),
5439               file_comment_len =
5440                   MZ_READ_LE16(pHeader + MZ_ZIP_CDH_COMMENT_LEN_OFS);
5441       const char *pFile_comment = pFilename + filename_len + file_extra_len;
5442       if ((file_comment_len != comment_len) ||
5443           (!mz_zip_reader_string_equal(pComment, pFile_comment,
5444                                        file_comment_len, flags)))
5445         continue;
5446     }
5447     if ((flags & MZ_ZIP_FLAG_IGNORE_PATH) && (filename_len)) {
5448       int ofs = filename_len - 1;
5449       do {
5450         if ((pFilename[ofs] == '/') || (pFilename[ofs] == '\\') ||
5451             (pFilename[ofs] == ':'))
5452           break;
5453       } while (--ofs >= 0);
5454       ofs++;
5455       pFilename += ofs;
5456       filename_len -= ofs;
5457     }
5458     if ((filename_len == name_len) &&
5459         (mz_zip_reader_string_equal(pName, pFilename, filename_len, flags)))
5460       return file_index;
5461   }
5462   return -1;
5463 }
5464 
mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive * pZip,mz_uint file_index,void * pBuf,size_t buf_size,mz_uint flags,void * pUser_read_buf,size_t user_read_buf_size)5465 mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip,
5466                                               mz_uint file_index, void *pBuf,
5467                                               size_t buf_size, mz_uint flags,
5468                                               void *pUser_read_buf,
5469                                               size_t user_read_buf_size) {
5470   int status = TINFL_STATUS_DONE;
5471   mz_uint64 needed_size, cur_file_ofs, comp_remaining,
5472       out_buf_ofs = 0, read_buf_size, read_buf_ofs = 0, read_buf_avail;
5473   mz_zip_archive_file_stat file_stat;
5474   void *pRead_buf;
5475   mz_uint32
5476       local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) /
5477                        sizeof(mz_uint32)];
5478   mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
5479   tinfl_decompressor inflator;
5480 
5481   if ((buf_size) && (!pBuf)) return MZ_FALSE;
5482 
5483   if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) return MZ_FALSE;
5484 
5485   // Empty file, or a directory (but not always a directory - I've seen odd zips
5486   // with directories that have compressed data which inflates to 0 bytes)
5487   if (!file_stat.m_comp_size) return MZ_TRUE;
5488 
5489   // Entry is a subdirectory (I've seen old zips with dir entries which have
5490   // compressed deflate data which inflates to 0 bytes, but these entries claim
5491   // to uncompress to 512 bytes in the headers).
5492   // I'm torn how to handle this case - should it fail instead?
5493   if (mz_zip_reader_is_file_a_directory(pZip, file_index)) return MZ_TRUE;
5494 
5495   // Encryption and patch files are not supported.
5496   if (file_stat.m_bit_flag & (1 | 32)) return MZ_FALSE;
5497 
5498   // This function only supports stored and deflate.
5499   if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) &&
5500       (file_stat.m_method != MZ_DEFLATED))
5501     return MZ_FALSE;
5502 
5503   // Ensure supplied output buffer is large enough.
5504   needed_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size
5505                                                       : file_stat.m_uncomp_size;
5506   if (buf_size < needed_size) return MZ_FALSE;
5507 
5508   // Read and parse the local directory entry.
5509   cur_file_ofs = file_stat.m_local_header_ofs;
5510   if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header,
5511                     MZ_ZIP_LOCAL_DIR_HEADER_SIZE) !=
5512       MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
5513     return MZ_FALSE;
5514   if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
5515     return MZ_FALSE;
5516 
5517   cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE +
5518                   MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) +
5519                   MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
5520   if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
5521     return MZ_FALSE;
5522 
5523   if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) {
5524     // The file is stored or the caller has requested the compressed data.
5525     if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf,
5526                       (size_t)needed_size) != needed_size)
5527       return MZ_FALSE;
5528     return ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) != 0) ||
5529            (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf,
5530                      (size_t)file_stat.m_uncomp_size) == file_stat.m_crc32);
5531   }
5532 
5533   // Decompress the file either directly from memory or from a file input
5534   // buffer.
5535   tinfl_init(&inflator);
5536 
5537   if (pZip->m_pState->m_pMem) {
5538     // Read directly from the archive in memory.
5539     pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
5540     read_buf_size = read_buf_avail = file_stat.m_comp_size;
5541     comp_remaining = 0;
5542   } else if (pUser_read_buf) {
5543     // Use a user provided read buffer.
5544     if (!user_read_buf_size) return MZ_FALSE;
5545     pRead_buf = (mz_uint8 *)pUser_read_buf;
5546     read_buf_size = user_read_buf_size;
5547     read_buf_avail = 0;
5548     comp_remaining = file_stat.m_comp_size;
5549   } else {
5550     // Temporarily allocate a read buffer.
5551     read_buf_size =
5552         MZ_MIN(file_stat.m_comp_size, (mz_uint)MZ_ZIP_MAX_IO_BUF_SIZE);
5553 #ifdef _MSC_VER
5554     if (((0, sizeof(size_t) == sizeof(mz_uint32))) &&
5555         (read_buf_size > 0x7FFFFFFF))
5556 #else
5557     if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF))
5558 #endif
5559       return MZ_FALSE;
5560     if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1,
5561                                             (size_t)read_buf_size)))
5562       return MZ_FALSE;
5563     read_buf_avail = 0;
5564     comp_remaining = file_stat.m_comp_size;
5565   }
5566 
5567   do {
5568     size_t in_buf_size,
5569         out_buf_size = (size_t)(file_stat.m_uncomp_size - out_buf_ofs);
5570     if ((!read_buf_avail) && (!pZip->m_pState->m_pMem)) {
5571       read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
5572       if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf,
5573                         (size_t)read_buf_avail) != read_buf_avail) {
5574         status = TINFL_STATUS_FAILED;
5575         break;
5576       }
5577       cur_file_ofs += read_buf_avail;
5578       comp_remaining -= read_buf_avail;
5579       read_buf_ofs = 0;
5580     }
5581     in_buf_size = (size_t)read_buf_avail;
5582     status = tinfl_decompress(
5583         &inflator, (mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size,
5584         (mz_uint8 *)pBuf, (mz_uint8 *)pBuf + out_buf_ofs, &out_buf_size,
5585         TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF |
5586             (comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0));
5587     read_buf_avail -= in_buf_size;
5588     read_buf_ofs += in_buf_size;
5589     out_buf_ofs += out_buf_size;
5590   } while (status == TINFL_STATUS_NEEDS_MORE_INPUT);
5591 
5592   if (status == TINFL_STATUS_DONE) {
5593     // Make sure the entire file was decompressed, and check its CRC.
5594     if ((out_buf_ofs != file_stat.m_uncomp_size) ||
5595         (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf,
5596                   (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32))
5597       status = TINFL_STATUS_FAILED;
5598   }
5599 
5600   if ((!pZip->m_pState->m_pMem) && (!pUser_read_buf))
5601     pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
5602 
5603   return status == TINFL_STATUS_DONE;
5604 }
5605 
mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive * pZip,const char * pFilename,void * pBuf,size_t buf_size,mz_uint flags,void * pUser_read_buf,size_t user_read_buf_size)5606 mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(
5607     mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size,
5608     mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size) {
5609   int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags);
5610   if (file_index < 0) return MZ_FALSE;
5611   return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size,
5612                                                flags, pUser_read_buf,
5613                                                user_read_buf_size);
5614 }
5615 
mz_zip_reader_extract_to_mem(mz_zip_archive * pZip,mz_uint file_index,void * pBuf,size_t buf_size,mz_uint flags)5616 mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index,
5617                                      void *pBuf, size_t buf_size,
5618                                      mz_uint flags) {
5619   return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size,
5620                                                flags, NULL, 0);
5621 }
5622 
mz_zip_reader_extract_file_to_mem(mz_zip_archive * pZip,const char * pFilename,void * pBuf,size_t buf_size,mz_uint flags)5623 mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip,
5624                                           const char *pFilename, void *pBuf,
5625                                           size_t buf_size, mz_uint flags) {
5626   return mz_zip_reader_extract_file_to_mem_no_alloc(pZip, pFilename, pBuf,
5627                                                     buf_size, flags, NULL, 0);
5628 }
5629 
mz_zip_reader_extract_to_heap(mz_zip_archive * pZip,mz_uint file_index,size_t * pSize,mz_uint flags)5630 void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index,
5631                                     size_t *pSize, mz_uint flags) {
5632   mz_uint64 comp_size, uncomp_size, alloc_size;
5633   const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
5634   void *pBuf;
5635 
5636   if (pSize) *pSize = 0;
5637   if (!p) return NULL;
5638 
5639   comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
5640   uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
5641 
5642   alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? comp_size : uncomp_size;
5643 #ifdef _MSC_VER
5644   if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
5645 #else
5646   if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
5647 #endif
5648     return NULL;
5649   if (NULL ==
5650       (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size)))
5651     return NULL;
5652 
5653   if (!mz_zip_reader_extract_to_mem(pZip, file_index, pBuf, (size_t)alloc_size,
5654                                     flags)) {
5655     pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
5656     return NULL;
5657   }
5658 
5659   if (pSize) *pSize = (size_t)alloc_size;
5660   return pBuf;
5661 }
5662 
mz_zip_reader_extract_file_to_heap(mz_zip_archive * pZip,const char * pFilename,size_t * pSize,mz_uint flags)5663 void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip,
5664                                          const char *pFilename, size_t *pSize,
5665                                          mz_uint flags) {
5666   int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags);
5667   if (file_index < 0) {
5668     if (pSize) *pSize = 0;
5669     return MZ_FALSE;
5670   }
5671   return mz_zip_reader_extract_to_heap(pZip, file_index, pSize, flags);
5672 }
5673 
mz_zip_reader_extract_to_callback(mz_zip_archive * pZip,mz_uint file_index,mz_file_write_func pCallback,void * pOpaque,mz_uint flags)5674 mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip,
5675                                           mz_uint file_index,
5676                                           mz_file_write_func pCallback,
5677                                           void *pOpaque, mz_uint flags) {
5678   int status = TINFL_STATUS_DONE;
5679   mz_uint file_crc32 = MZ_CRC32_INIT;
5680   mz_uint64 read_buf_size, read_buf_ofs = 0, read_buf_avail, comp_remaining,
5681                            out_buf_ofs = 0, cur_file_ofs;
5682   mz_zip_archive_file_stat file_stat;
5683   void *pRead_buf = NULL;
5684   void *pWrite_buf = NULL;
5685   mz_uint32
5686       local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) /
5687                        sizeof(mz_uint32)];
5688   mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
5689 
5690   if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) return MZ_FALSE;
5691 
5692   // Empty file, or a directory (but not always a directory - I've seen odd zips
5693   // with directories that have compressed data which inflates to 0 bytes)
5694   if (!file_stat.m_comp_size) return MZ_TRUE;
5695 
5696   // Entry is a subdirectory (I've seen old zips with dir entries which have
5697   // compressed deflate data which inflates to 0 bytes, but these entries claim
5698   // to uncompress to 512 bytes in the headers).
5699   // I'm torn how to handle this case - should it fail instead?
5700   if (mz_zip_reader_is_file_a_directory(pZip, file_index)) return MZ_TRUE;
5701 
5702   // Encryption and patch files are not supported.
5703   if (file_stat.m_bit_flag & (1 | 32)) return MZ_FALSE;
5704 
5705   // This function only supports stored and deflate.
5706   if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) &&
5707       (file_stat.m_method != MZ_DEFLATED))
5708     return MZ_FALSE;
5709 
5710   // Read and parse the local directory entry.
5711   cur_file_ofs = file_stat.m_local_header_ofs;
5712   if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header,
5713                     MZ_ZIP_LOCAL_DIR_HEADER_SIZE) !=
5714       MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
5715     return MZ_FALSE;
5716   if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
5717     return MZ_FALSE;
5718 
5719   cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE +
5720                   MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) +
5721                   MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
5722   if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
5723     return MZ_FALSE;
5724 
5725   // Decompress the file either directly from memory or from a file input
5726   // buffer.
5727   if (pZip->m_pState->m_pMem) {
5728     pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
5729     read_buf_size = read_buf_avail = file_stat.m_comp_size;
5730     comp_remaining = 0;
5731   } else {
5732     read_buf_size =
5733         MZ_MIN(file_stat.m_comp_size, (mz_uint)MZ_ZIP_MAX_IO_BUF_SIZE);
5734     if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1,
5735                                             (size_t)read_buf_size)))
5736       return MZ_FALSE;
5737     read_buf_avail = 0;
5738     comp_remaining = file_stat.m_comp_size;
5739   }
5740 
5741   if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) {
5742     // The file is stored or the caller has requested the compressed data.
5743     if (pZip->m_pState->m_pMem) {
5744 #ifdef _MSC_VER
5745       if (((0, sizeof(size_t) == sizeof(mz_uint32))) &&
5746           (file_stat.m_comp_size > 0xFFFFFFFF))
5747 #else
5748       if (((sizeof(size_t) == sizeof(mz_uint32))) &&
5749           (file_stat.m_comp_size > 0xFFFFFFFF))
5750 #endif
5751         return MZ_FALSE;
5752       if (pCallback(pOpaque, out_buf_ofs, pRead_buf,
5753                     (size_t)file_stat.m_comp_size) != file_stat.m_comp_size)
5754         status = TINFL_STATUS_FAILED;
5755       else if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
5756         file_crc32 =
5757             (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf,
5758                                 (size_t)file_stat.m_comp_size);
5759       cur_file_ofs += file_stat.m_comp_size;
5760       out_buf_ofs += file_stat.m_comp_size;
5761       comp_remaining = 0;
5762     } else {
5763       while (comp_remaining) {
5764         read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
5765         if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf,
5766                           (size_t)read_buf_avail) != read_buf_avail) {
5767           status = TINFL_STATUS_FAILED;
5768           break;
5769         }
5770 
5771         if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
5772           file_crc32 = (mz_uint32)mz_crc32(
5773               file_crc32, (const mz_uint8 *)pRead_buf, (size_t)read_buf_avail);
5774 
5775         if (pCallback(pOpaque, out_buf_ofs, pRead_buf,
5776                       (size_t)read_buf_avail) != read_buf_avail) {
5777           status = TINFL_STATUS_FAILED;
5778           break;
5779         }
5780         cur_file_ofs += read_buf_avail;
5781         out_buf_ofs += read_buf_avail;
5782         comp_remaining -= read_buf_avail;
5783       }
5784     }
5785   } else {
5786     tinfl_decompressor inflator;
5787     tinfl_init(&inflator);
5788 
5789     if (NULL == (pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1,
5790                                              TINFL_LZ_DICT_SIZE)))
5791       status = TINFL_STATUS_FAILED;
5792     else {
5793       do {
5794         mz_uint8 *pWrite_buf_cur =
5795             (mz_uint8 *)pWrite_buf + (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
5796         size_t in_buf_size,
5797             out_buf_size =
5798                 TINFL_LZ_DICT_SIZE - (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
5799         if ((!read_buf_avail) && (!pZip->m_pState->m_pMem)) {
5800           read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
5801           if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf,
5802                             (size_t)read_buf_avail) != read_buf_avail) {
5803             status = TINFL_STATUS_FAILED;
5804             break;
5805           }
5806           cur_file_ofs += read_buf_avail;
5807           comp_remaining -= read_buf_avail;
5808           read_buf_ofs = 0;
5809         }
5810 
5811         in_buf_size = (size_t)read_buf_avail;
5812         status = tinfl_decompress(
5813             &inflator, (const mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size,
5814             (mz_uint8 *)pWrite_buf, pWrite_buf_cur, &out_buf_size,
5815             comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0);
5816         read_buf_avail -= in_buf_size;
5817         read_buf_ofs += in_buf_size;
5818 
5819         if (out_buf_size) {
5820           if (pCallback(pOpaque, out_buf_ofs, pWrite_buf_cur, out_buf_size) !=
5821               out_buf_size) {
5822             status = TINFL_STATUS_FAILED;
5823             break;
5824           }
5825           file_crc32 =
5826               (mz_uint32)mz_crc32(file_crc32, pWrite_buf_cur, out_buf_size);
5827           if ((out_buf_ofs += out_buf_size) > file_stat.m_uncomp_size) {
5828             status = TINFL_STATUS_FAILED;
5829             break;
5830           }
5831         }
5832       } while ((status == TINFL_STATUS_NEEDS_MORE_INPUT) ||
5833                (status == TINFL_STATUS_HAS_MORE_OUTPUT));
5834     }
5835   }
5836 
5837   if ((status == TINFL_STATUS_DONE) &&
5838       (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))) {
5839     // Make sure the entire file was decompressed, and check its CRC.
5840     if ((out_buf_ofs != file_stat.m_uncomp_size) ||
5841         (file_crc32 != file_stat.m_crc32))
5842       status = TINFL_STATUS_FAILED;
5843   }
5844 
5845   if (!pZip->m_pState->m_pMem) pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
5846   if (pWrite_buf) pZip->m_pFree(pZip->m_pAlloc_opaque, pWrite_buf);
5847 
5848   return status == TINFL_STATUS_DONE;
5849 }
5850 
mz_zip_reader_extract_file_to_callback(mz_zip_archive * pZip,const char * pFilename,mz_file_write_func pCallback,void * pOpaque,mz_uint flags)5851 mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip,
5852                                                const char *pFilename,
5853                                                mz_file_write_func pCallback,
5854                                                void *pOpaque, mz_uint flags) {
5855   int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags);
5856   if (file_index < 0) return MZ_FALSE;
5857   return mz_zip_reader_extract_to_callback(pZip, file_index, pCallback, pOpaque,
5858                                            flags);
5859 }
5860 
5861 #ifndef MINIZ_NO_STDIO
mz_zip_file_write_callback(void * pOpaque,mz_uint64 ofs,const void * pBuf,size_t n)5862 static size_t mz_zip_file_write_callback(void *pOpaque, mz_uint64 ofs,
5863                                          const void *pBuf, size_t n) {
5864   (void)ofs;
5865   return MZ_FWRITE(pBuf, 1, n, (MZ_FILE *)pOpaque);
5866 }
5867 
mz_zip_reader_extract_to_file(mz_zip_archive * pZip,mz_uint file_index,const char * pDst_filename,mz_uint flags)5868 mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index,
5869                                       const char *pDst_filename,
5870                                       mz_uint flags) {
5871   mz_bool status;
5872   mz_zip_archive_file_stat file_stat;
5873   MZ_FILE *pFile;
5874   if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) return MZ_FALSE;
5875   pFile = MZ_FOPEN(pDst_filename, "wb");
5876   if (!pFile) return MZ_FALSE;
5877   status = mz_zip_reader_extract_to_callback(
5878       pZip, file_index, mz_zip_file_write_callback, pFile, flags);
5879   if (MZ_FCLOSE(pFile) == EOF) return MZ_FALSE;
5880 #ifndef MINIZ_NO_TIME
5881   if (status)
5882     mz_zip_set_file_times(pDst_filename, file_stat.m_time, file_stat.m_time);
5883 #endif
5884   return status;
5885 }
5886 #endif  // #ifndef MINIZ_NO_STDIO
5887 
mz_zip_reader_end(mz_zip_archive * pZip)5888 mz_bool mz_zip_reader_end(mz_zip_archive *pZip) {
5889   if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) ||
5890       (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
5891     return MZ_FALSE;
5892 
5893   if (pZip->m_pState) {
5894     mz_zip_internal_state *pState = pZip->m_pState;
5895     pZip->m_pState = NULL;
5896     mz_zip_array_clear(pZip, &pState->m_central_dir);
5897     mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
5898     mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
5899 
5900 #ifndef MINIZ_NO_STDIO
5901     if (pState->m_pFile) {
5902       MZ_FCLOSE(pState->m_pFile);
5903       pState->m_pFile = NULL;
5904     }
5905 #endif  // #ifndef MINIZ_NO_STDIO
5906 
5907     pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
5908   }
5909   pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
5910 
5911   return MZ_TRUE;
5912 }
5913 
5914 #ifndef MINIZ_NO_STDIO
mz_zip_reader_extract_file_to_file(mz_zip_archive * pZip,const char * pArchive_filename,const char * pDst_filename,mz_uint flags)5915 mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip,
5916                                            const char *pArchive_filename,
5917                                            const char *pDst_filename,
5918                                            mz_uint flags) {
5919   int file_index =
5920       mz_zip_reader_locate_file(pZip, pArchive_filename, NULL, flags);
5921   if (file_index < 0) return MZ_FALSE;
5922   return mz_zip_reader_extract_to_file(pZip, file_index, pDst_filename, flags);
5923 }
5924 #endif
5925 
5926 // ------------------- .ZIP archive writing
5927 
5928 #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
5929 
mz_write_le16(mz_uint8 * p,mz_uint16 v)5930 static void mz_write_le16(mz_uint8 *p, mz_uint16 v) {
5931   p[0] = (mz_uint8)v;
5932   p[1] = (mz_uint8)(v >> 8);
5933 }
mz_write_le32(mz_uint8 * p,mz_uint32 v)5934 static void mz_write_le32(mz_uint8 *p, mz_uint32 v) {
5935   p[0] = (mz_uint8)v;
5936   p[1] = (mz_uint8)(v >> 8);
5937   p[2] = (mz_uint8)(v >> 16);
5938   p[3] = (mz_uint8)(v >> 24);
5939 }
5940 #define MZ_WRITE_LE16(p, v) mz_write_le16((mz_uint8 *)(p), (mz_uint16)(v))
5941 #define MZ_WRITE_LE32(p, v) mz_write_le32((mz_uint8 *)(p), (mz_uint32)(v))
5942 
mz_zip_writer_init(mz_zip_archive * pZip,mz_uint64 existing_size)5943 mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size) {
5944   if ((!pZip) || (pZip->m_pState) || (!pZip->m_pWrite) ||
5945       (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
5946     return MZ_FALSE;
5947 
5948   if (pZip->m_file_offset_alignment) {
5949     // Ensure user specified file offset alignment is a power of 2.
5950     if (pZip->m_file_offset_alignment & (pZip->m_file_offset_alignment - 1))
5951       return MZ_FALSE;
5952   }
5953 
5954   if (!pZip->m_pAlloc) pZip->m_pAlloc = def_alloc_func;
5955   if (!pZip->m_pFree) pZip->m_pFree = def_free_func;
5956   if (!pZip->m_pRealloc) pZip->m_pRealloc = def_realloc_func;
5957 
5958   pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
5959   pZip->m_archive_size = existing_size;
5960   pZip->m_central_directory_file_ofs = 0;
5961   pZip->m_total_files = 0;
5962 
5963   if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(
5964                    pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
5965     return MZ_FALSE;
5966   memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
5967   MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir,
5968                                 sizeof(mz_uint8));
5969   MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets,
5970                                 sizeof(mz_uint32));
5971   MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets,
5972                                 sizeof(mz_uint32));
5973   return MZ_TRUE;
5974 }
5975 
mz_zip_heap_write_func(void * pOpaque,mz_uint64 file_ofs,const void * pBuf,size_t n)5976 static size_t mz_zip_heap_write_func(void *pOpaque, mz_uint64 file_ofs,
5977                                      const void *pBuf, size_t n) {
5978   mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
5979   mz_zip_internal_state *pState = pZip->m_pState;
5980   mz_uint64 new_size = MZ_MAX(file_ofs + n, pState->m_mem_size);
5981 #ifdef _MSC_VER
5982   if ((!n) ||
5983       ((0, sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF)))
5984 #else
5985   if ((!n) ||
5986       ((sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF)))
5987 #endif
5988     return 0;
5989   if (new_size > pState->m_mem_capacity) {
5990     void *pNew_block;
5991     size_t new_capacity = MZ_MAX(64, pState->m_mem_capacity);
5992     while (new_capacity < new_size) new_capacity *= 2;
5993     if (NULL == (pNew_block = pZip->m_pRealloc(
5994                      pZip->m_pAlloc_opaque, pState->m_pMem, 1, new_capacity)))
5995       return 0;
5996     pState->m_pMem = pNew_block;
5997     pState->m_mem_capacity = new_capacity;
5998   }
5999   memcpy((mz_uint8 *)pState->m_pMem + file_ofs, pBuf, n);
6000   pState->m_mem_size = (size_t)new_size;
6001   return n;
6002 }
6003 
mz_zip_writer_init_heap(mz_zip_archive * pZip,size_t size_to_reserve_at_beginning,size_t initial_allocation_size)6004 mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip,
6005                                 size_t size_to_reserve_at_beginning,
6006                                 size_t initial_allocation_size) {
6007   pZip->m_pWrite = mz_zip_heap_write_func;
6008   pZip->m_pIO_opaque = pZip;
6009   if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning)) return MZ_FALSE;
6010   if (0 != (initial_allocation_size = MZ_MAX(initial_allocation_size,
6011                                              size_to_reserve_at_beginning))) {
6012     if (NULL == (pZip->m_pState->m_pMem = pZip->m_pAlloc(
6013                      pZip->m_pAlloc_opaque, 1, initial_allocation_size))) {
6014       mz_zip_writer_end(pZip);
6015       return MZ_FALSE;
6016     }
6017     pZip->m_pState->m_mem_capacity = initial_allocation_size;
6018   }
6019   return MZ_TRUE;
6020 }
6021 
6022 #ifndef MINIZ_NO_STDIO
mz_zip_file_write_func(void * pOpaque,mz_uint64 file_ofs,const void * pBuf,size_t n)6023 static size_t mz_zip_file_write_func(void *pOpaque, mz_uint64 file_ofs,
6024                                      const void *pBuf, size_t n) {
6025   mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
6026   mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
6027   if (((mz_int64)file_ofs < 0) ||
6028       (((cur_ofs != (mz_int64)file_ofs)) &&
6029        (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET))))
6030     return 0;
6031   return MZ_FWRITE(pBuf, 1, n, pZip->m_pState->m_pFile);
6032 }
6033 
mz_zip_writer_init_file(mz_zip_archive * pZip,const char * pFilename,mz_uint64 size_to_reserve_at_beginning)6034 mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename,
6035                                 mz_uint64 size_to_reserve_at_beginning) {
6036   MZ_FILE *pFile;
6037   pZip->m_pWrite = mz_zip_file_write_func;
6038   pZip->m_pIO_opaque = pZip;
6039   if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning)) return MZ_FALSE;
6040   if (NULL == (pFile = MZ_FOPEN(pFilename, "wb"))) {
6041     mz_zip_writer_end(pZip);
6042     return MZ_FALSE;
6043   }
6044   pZip->m_pState->m_pFile = pFile;
6045   if (size_to_reserve_at_beginning) {
6046     mz_uint64 cur_ofs = 0;
6047     char buf[4096];
6048     MZ_CLEAR_OBJ(buf);
6049     do {
6050       size_t n = (size_t)MZ_MIN(sizeof(buf), size_to_reserve_at_beginning);
6051       if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_ofs, buf, n) != n) {
6052         mz_zip_writer_end(pZip);
6053         return MZ_FALSE;
6054       }
6055       cur_ofs += n;
6056       size_to_reserve_at_beginning -= n;
6057     } while (size_to_reserve_at_beginning);
6058   }
6059   return MZ_TRUE;
6060 }
6061 #endif  // #ifndef MINIZ_NO_STDIO
6062 
mz_zip_writer_init_from_reader(mz_zip_archive * pZip,const char * pFilename)6063 mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip,
6064                                        const char *pFilename) {
6065   mz_zip_internal_state *pState;
6066   if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
6067     return MZ_FALSE;
6068   // No sense in trying to write to an archive that's already at the support max
6069   // size
6070   if ((pZip->m_total_files == 0xFFFF) ||
6071       ((pZip->m_archive_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
6072         MZ_ZIP_LOCAL_DIR_HEADER_SIZE) > 0xFFFFFFFF))
6073     return MZ_FALSE;
6074 
6075   pState = pZip->m_pState;
6076 
6077   if (pState->m_pFile) {
6078 #ifdef MINIZ_NO_STDIO
6079     pFilename;
6080     return MZ_FALSE;
6081 #else
6082     // Archive is being read from stdio - try to reopen as writable.
6083     if (pZip->m_pIO_opaque != pZip) return MZ_FALSE;
6084     if (!pFilename) return MZ_FALSE;
6085     pZip->m_pWrite = mz_zip_file_write_func;
6086     if (NULL ==
6087         (pState->m_pFile = MZ_FREOPEN(pFilename, "r+b", pState->m_pFile))) {
6088       // The mz_zip_archive is now in a bogus state because pState->m_pFile is
6089       // NULL, so just close it.
6090       mz_zip_reader_end(pZip);
6091       return MZ_FALSE;
6092     }
6093 #endif  // #ifdef MINIZ_NO_STDIO
6094   } else if (pState->m_pMem) {
6095     // Archive lives in a memory block. Assume it's from the heap that we can
6096     // resize using the realloc callback.
6097     if (pZip->m_pIO_opaque != pZip) return MZ_FALSE;
6098     pState->m_mem_capacity = pState->m_mem_size;
6099     pZip->m_pWrite = mz_zip_heap_write_func;
6100   }
6101   // Archive is being read via a user provided read function - make sure the
6102   // user has specified a write function too.
6103   else if (!pZip->m_pWrite)
6104     return MZ_FALSE;
6105 
6106   // Start writing new files at the archive's current central directory
6107   // location.
6108   pZip->m_archive_size = pZip->m_central_directory_file_ofs;
6109   pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
6110   pZip->m_central_directory_file_ofs = 0;
6111 
6112   return MZ_TRUE;
6113 }
6114 
mz_zip_writer_add_mem(mz_zip_archive * pZip,const char * pArchive_name,const void * pBuf,size_t buf_size,mz_uint level_and_flags)6115 mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name,
6116                               const void *pBuf, size_t buf_size,
6117                               mz_uint level_and_flags) {
6118   return mz_zip_writer_add_mem_ex(pZip, pArchive_name, pBuf, buf_size, NULL, 0,
6119                                   level_and_flags, 0, 0);
6120 }
6121 
6122 typedef struct {
6123   mz_zip_archive *m_pZip;
6124   mz_uint64 m_cur_archive_file_ofs;
6125   mz_uint64 m_comp_size;
6126 } mz_zip_writer_add_state;
6127 
mz_zip_writer_add_put_buf_callback(const void * pBuf,int len,void * pUser)6128 static mz_bool mz_zip_writer_add_put_buf_callback(const void *pBuf, int len,
6129                                                   void *pUser) {
6130   mz_zip_writer_add_state *pState = (mz_zip_writer_add_state *)pUser;
6131   if ((int)pState->m_pZip->m_pWrite(pState->m_pZip->m_pIO_opaque,
6132                                     pState->m_cur_archive_file_ofs, pBuf,
6133                                     len) != len)
6134     return MZ_FALSE;
6135   pState->m_cur_archive_file_ofs += len;
6136   pState->m_comp_size += len;
6137   return MZ_TRUE;
6138 }
6139 
mz_zip_writer_create_local_dir_header(mz_zip_archive * pZip,mz_uint8 * pDst,mz_uint16 filename_size,mz_uint16 extra_size,mz_uint64 uncomp_size,mz_uint64 comp_size,mz_uint32 uncomp_crc32,mz_uint16 method,mz_uint16 bit_flags,mz_uint16 dos_time,mz_uint16 dos_date)6140 static mz_bool mz_zip_writer_create_local_dir_header(
6141     mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size,
6142     mz_uint16 extra_size, mz_uint64 uncomp_size, mz_uint64 comp_size,
6143     mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags,
6144     mz_uint16 dos_time, mz_uint16 dos_date) {
6145   (void)pZip;
6146   memset(pDst, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE);
6147   MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_SIG_OFS, MZ_ZIP_LOCAL_DIR_HEADER_SIG);
6148   MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_VERSION_NEEDED_OFS, method ? 20 : 0);
6149   MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_BIT_FLAG_OFS, bit_flags);
6150   MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_METHOD_OFS, method);
6151   MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_TIME_OFS, dos_time);
6152   MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_DATE_OFS, dos_date);
6153   MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_CRC32_OFS, uncomp_crc32);
6154   MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS, comp_size);
6155   MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS, uncomp_size);
6156   MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILENAME_LEN_OFS, filename_size);
6157   MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_EXTRA_LEN_OFS, extra_size);
6158   return MZ_TRUE;
6159 }
6160 
mz_zip_writer_create_central_dir_header(mz_zip_archive * pZip,mz_uint8 * pDst,mz_uint16 filename_size,mz_uint16 extra_size,mz_uint16 comment_size,mz_uint64 uncomp_size,mz_uint64 comp_size,mz_uint32 uncomp_crc32,mz_uint16 method,mz_uint16 bit_flags,mz_uint16 dos_time,mz_uint16 dos_date,mz_uint64 local_header_ofs,mz_uint32 ext_attributes)6161 static mz_bool mz_zip_writer_create_central_dir_header(
6162     mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size,
6163     mz_uint16 extra_size, mz_uint16 comment_size, mz_uint64 uncomp_size,
6164     mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method,
6165     mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date,
6166     mz_uint64 local_header_ofs, mz_uint32 ext_attributes) {
6167   (void)pZip;
6168   memset(pDst, 0, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
6169   MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_SIG_OFS, MZ_ZIP_CENTRAL_DIR_HEADER_SIG);
6170   MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, method ? 20 : 0);
6171   MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_BIT_FLAG_OFS, bit_flags);
6172   MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_METHOD_OFS, method);
6173   MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_TIME_OFS, dos_time);
6174   MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_DATE_OFS, dos_date);
6175   MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_CRC32_OFS, uncomp_crc32);
6176   MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, comp_size);
6177   MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, uncomp_size);
6178   MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILENAME_LEN_OFS, filename_size);
6179   MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_EXTRA_LEN_OFS, extra_size);
6180   MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_COMMENT_LEN_OFS, comment_size);
6181   MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS, ext_attributes);
6182   MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_header_ofs);
6183   return MZ_TRUE;
6184 }
6185 
mz_zip_writer_add_to_central_dir(mz_zip_archive * pZip,const char * pFilename,mz_uint16 filename_size,const void * pExtra,mz_uint16 extra_size,const void * pComment,mz_uint16 comment_size,mz_uint64 uncomp_size,mz_uint64 comp_size,mz_uint32 uncomp_crc32,mz_uint16 method,mz_uint16 bit_flags,mz_uint16 dos_time,mz_uint16 dos_date,mz_uint64 local_header_ofs,mz_uint32 ext_attributes)6186 static mz_bool mz_zip_writer_add_to_central_dir(
6187     mz_zip_archive *pZip, const char *pFilename, mz_uint16 filename_size,
6188     const void *pExtra, mz_uint16 extra_size, const void *pComment,
6189     mz_uint16 comment_size, mz_uint64 uncomp_size, mz_uint64 comp_size,
6190     mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags,
6191     mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs,
6192     mz_uint32 ext_attributes) {
6193   mz_zip_internal_state *pState = pZip->m_pState;
6194   mz_uint32 central_dir_ofs = (mz_uint32)pState->m_central_dir.m_size;
6195   size_t orig_central_dir_size = pState->m_central_dir.m_size;
6196   mz_uint8 central_dir_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
6197 
6198   // No zip64 support yet
6199   if ((local_header_ofs > 0xFFFFFFFF) ||
6200       (((mz_uint64)pState->m_central_dir.m_size +
6201         MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + extra_size +
6202         comment_size) > 0xFFFFFFFF))
6203     return MZ_FALSE;
6204 
6205   if (!mz_zip_writer_create_central_dir_header(
6206           pZip, central_dir_header, filename_size, extra_size, comment_size,
6207           uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time,
6208           dos_date, local_header_ofs, ext_attributes))
6209     return MZ_FALSE;
6210 
6211   if ((!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_dir_header,
6212                                MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) ||
6213       (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pFilename,
6214                                filename_size)) ||
6215       (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pExtra,
6216                                extra_size)) ||
6217       (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pComment,
6218                                comment_size)) ||
6219       (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets,
6220                                &central_dir_ofs, 1))) {
6221     // Try to push the central directory array back into its original state.
6222     mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size,
6223                         MZ_FALSE);
6224     return MZ_FALSE;
6225   }
6226 
6227   return MZ_TRUE;
6228 }
6229 
mz_zip_writer_validate_archive_name(const char * pArchive_name)6230 static mz_bool mz_zip_writer_validate_archive_name(const char *pArchive_name) {
6231   // Basic ZIP archive filename validity checks: Valid filenames cannot start
6232   // with a forward slash, cannot contain a drive letter, and cannot use
6233   // DOS-style backward slashes.
6234   if (*pArchive_name == '/') return MZ_FALSE;
6235   while (*pArchive_name) {
6236     if ((*pArchive_name == '\\') || (*pArchive_name == ':')) return MZ_FALSE;
6237     pArchive_name++;
6238   }
6239   return MZ_TRUE;
6240 }
6241 
mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive * pZip)6242 static mz_uint mz_zip_writer_compute_padding_needed_for_file_alignment(
6243     mz_zip_archive *pZip) {
6244   mz_uint32 n;
6245   if (!pZip->m_file_offset_alignment) return 0;
6246   n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1));
6247   return (pZip->m_file_offset_alignment - n) &
6248          (pZip->m_file_offset_alignment - 1);
6249 }
6250 
mz_zip_writer_write_zeros(mz_zip_archive * pZip,mz_uint64 cur_file_ofs,mz_uint32 n)6251 static mz_bool mz_zip_writer_write_zeros(mz_zip_archive *pZip,
6252                                          mz_uint64 cur_file_ofs, mz_uint32 n) {
6253   char buf[4096];
6254   memset(buf, 0, MZ_MIN(sizeof(buf), n));
6255   while (n) {
6256     mz_uint32 s = MZ_MIN(sizeof(buf), n);
6257     if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_file_ofs, buf, s) != s)
6258       return MZ_FALSE;
6259     cur_file_ofs += s;
6260     n -= s;
6261   }
6262   return MZ_TRUE;
6263 }
6264 
mz_zip_writer_add_mem_ex(mz_zip_archive * pZip,const char * pArchive_name,const void * pBuf,size_t buf_size,const void * pComment,mz_uint16 comment_size,mz_uint level_and_flags,mz_uint64 uncomp_size,mz_uint32 uncomp_crc32)6265 mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip,
6266                                  const char *pArchive_name, const void *pBuf,
6267                                  size_t buf_size, const void *pComment,
6268                                  mz_uint16 comment_size,
6269                                  mz_uint level_and_flags, mz_uint64 uncomp_size,
6270                                  mz_uint32 uncomp_crc32) {
6271   mz_uint16 method = 0, dos_time = 0, dos_date = 0;
6272   mz_uint level, ext_attributes = 0, num_alignment_padding_bytes;
6273   mz_uint64 local_dir_header_ofs = pZip->m_archive_size,
6274             cur_archive_file_ofs = pZip->m_archive_size, comp_size = 0;
6275   size_t archive_name_size;
6276   mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
6277   tdefl_compressor *pComp = NULL;
6278   mz_bool store_data_uncompressed;
6279   mz_zip_internal_state *pState;
6280 
6281   if ((int)level_and_flags < 0) level_and_flags = MZ_DEFAULT_LEVEL;
6282   level = level_and_flags & 0xF;
6283   store_data_uncompressed =
6284       ((!level) || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA));
6285 
6286   if ((!pZip) || (!pZip->m_pState) ||
6287       (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || ((buf_size) && (!pBuf)) ||
6288       (!pArchive_name) || ((comment_size) && (!pComment)) ||
6289       (pZip->m_total_files == 0xFFFF) || (level > MZ_UBER_COMPRESSION))
6290     return MZ_FALSE;
6291 
6292   pState = pZip->m_pState;
6293 
6294   if ((!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (uncomp_size))
6295     return MZ_FALSE;
6296   // No zip64 support yet
6297   if ((buf_size > 0xFFFFFFFF) || (uncomp_size > 0xFFFFFFFF)) return MZ_FALSE;
6298   if (!mz_zip_writer_validate_archive_name(pArchive_name)) return MZ_FALSE;
6299 
6300 #ifndef MINIZ_NO_TIME
6301   {
6302     time_t cur_time;
6303     time(&cur_time);
6304     mz_zip_time_to_dos_time(cur_time, &dos_time, &dos_date);
6305   }
6306 #endif  // #ifndef MINIZ_NO_TIME
6307 
6308   archive_name_size = strlen(pArchive_name);
6309   if (archive_name_size > 0xFFFF) return MZ_FALSE;
6310 
6311   num_alignment_padding_bytes =
6312       mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
6313 
6314   // no zip64 support yet
6315   if ((pZip->m_total_files == 0xFFFF) ||
6316       ((pZip->m_archive_size + num_alignment_padding_bytes +
6317         MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
6318         comment_size + archive_name_size) > 0xFFFFFFFF))
6319     return MZ_FALSE;
6320 
6321   if ((archive_name_size) && (pArchive_name[archive_name_size - 1] == '/')) {
6322     // Set DOS Subdirectory attribute bit.
6323     ext_attributes |= 0x10;
6324     // Subdirectories cannot contain data.
6325     if ((buf_size) || (uncomp_size)) return MZ_FALSE;
6326   }
6327 
6328   // Try to do any allocations before writing to the archive, so if an
6329   // allocation fails the file remains unmodified. (A good idea if we're doing
6330   // an in-place modification.)
6331   if ((!mz_zip_array_ensure_room(
6332           pZip, &pState->m_central_dir,
6333           MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size)) ||
6334       (!mz_zip_array_ensure_room(pZip, &pState->m_central_dir_offsets, 1)))
6335     return MZ_FALSE;
6336 
6337   if ((!store_data_uncompressed) && (buf_size)) {
6338     if (NULL == (pComp = (tdefl_compressor *)pZip->m_pAlloc(
6339                      pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor))))
6340       return MZ_FALSE;
6341   }
6342 
6343   if (!mz_zip_writer_write_zeros(
6344           pZip, cur_archive_file_ofs,
6345           num_alignment_padding_bytes + sizeof(local_dir_header))) {
6346     pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6347     return MZ_FALSE;
6348   }
6349   local_dir_header_ofs += num_alignment_padding_bytes;
6350   if (pZip->m_file_offset_alignment) {
6351     MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) ==
6352               0);
6353   }
6354   cur_archive_file_ofs +=
6355       num_alignment_padding_bytes + sizeof(local_dir_header);
6356 
6357   MZ_CLEAR_OBJ(local_dir_header);
6358   if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name,
6359                      archive_name_size) != archive_name_size) {
6360     pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6361     return MZ_FALSE;
6362   }
6363   cur_archive_file_ofs += archive_name_size;
6364 
6365   if (!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) {
6366     uncomp_crc32 =
6367         (mz_uint32)mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, buf_size);
6368     uncomp_size = buf_size;
6369     if (uncomp_size <= 3) {
6370       level = 0;
6371       store_data_uncompressed = MZ_TRUE;
6372     }
6373   }
6374 
6375   if (store_data_uncompressed) {
6376     if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pBuf,
6377                        buf_size) != buf_size) {
6378       pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6379       return MZ_FALSE;
6380     }
6381 
6382     cur_archive_file_ofs += buf_size;
6383     comp_size = buf_size;
6384 
6385     if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA) method = MZ_DEFLATED;
6386   } else if (buf_size) {
6387     mz_zip_writer_add_state state;
6388 
6389     state.m_pZip = pZip;
6390     state.m_cur_archive_file_ofs = cur_archive_file_ofs;
6391     state.m_comp_size = 0;
6392 
6393     if ((tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state,
6394                     tdefl_create_comp_flags_from_zip_params(
6395                         level, -15, MZ_DEFAULT_STRATEGY)) !=
6396          TDEFL_STATUS_OKAY) ||
6397         (tdefl_compress_buffer(pComp, pBuf, buf_size, TDEFL_FINISH) !=
6398          TDEFL_STATUS_DONE)) {
6399       pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6400       return MZ_FALSE;
6401     }
6402 
6403     comp_size = state.m_comp_size;
6404     cur_archive_file_ofs = state.m_cur_archive_file_ofs;
6405 
6406     method = MZ_DEFLATED;
6407   }
6408 
6409   pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6410   pComp = NULL;
6411 
6412   // no zip64 support yet
6413   if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF))
6414     return MZ_FALSE;
6415 
6416   if (!mz_zip_writer_create_local_dir_header(
6417           pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size,
6418           comp_size, uncomp_crc32, method, 0, dos_time, dos_date))
6419     return MZ_FALSE;
6420 
6421   if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header,
6422                      sizeof(local_dir_header)) != sizeof(local_dir_header))
6423     return MZ_FALSE;
6424 
6425   if (!mz_zip_writer_add_to_central_dir(
6426           pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment,
6427           comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0,
6428           dos_time, dos_date, local_dir_header_ofs, ext_attributes))
6429     return MZ_FALSE;
6430 
6431   pZip->m_total_files++;
6432   pZip->m_archive_size = cur_archive_file_ofs;
6433 
6434   return MZ_TRUE;
6435 }
6436 
6437 #ifndef MINIZ_NO_STDIO
mz_zip_writer_add_file(mz_zip_archive * pZip,const char * pArchive_name,const char * pSrc_filename,const void * pComment,mz_uint16 comment_size,mz_uint level_and_flags)6438 mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name,
6439                                const char *pSrc_filename, const void *pComment,
6440                                mz_uint16 comment_size,
6441                                mz_uint level_and_flags) {
6442   mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes;
6443   mz_uint16 method = 0, dos_time = 0, dos_date = 0, ext_attributes = 0;
6444   mz_uint64 local_dir_header_ofs = pZip->m_archive_size,
6445             cur_archive_file_ofs = pZip->m_archive_size, uncomp_size = 0,
6446             comp_size = 0;
6447   size_t archive_name_size;
6448   mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
6449   MZ_FILE *pSrc_file = NULL;
6450 
6451   if ((int)level_and_flags < 0) level_and_flags = MZ_DEFAULT_LEVEL;
6452   level = level_and_flags & 0xF;
6453 
6454   if ((!pZip) || (!pZip->m_pState) ||
6455       (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pArchive_name) ||
6456       ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION))
6457     return MZ_FALSE;
6458   if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA) return MZ_FALSE;
6459   if (!mz_zip_writer_validate_archive_name(pArchive_name)) return MZ_FALSE;
6460 
6461   archive_name_size = strlen(pArchive_name);
6462   if (archive_name_size > 0xFFFF) return MZ_FALSE;
6463 
6464   num_alignment_padding_bytes =
6465       mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
6466 
6467   // no zip64 support yet
6468   if ((pZip->m_total_files == 0xFFFF) ||
6469       ((pZip->m_archive_size + num_alignment_padding_bytes +
6470         MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
6471         comment_size + archive_name_size) > 0xFFFFFFFF))
6472     return MZ_FALSE;
6473 
6474   if (!mz_zip_get_file_modified_time(pSrc_filename, &dos_time, &dos_date))
6475     return MZ_FALSE;
6476 
6477   pSrc_file = MZ_FOPEN(pSrc_filename, "rb");
6478   if (!pSrc_file) return MZ_FALSE;
6479   MZ_FSEEK64(pSrc_file, 0, SEEK_END);
6480   uncomp_size = MZ_FTELL64(pSrc_file);
6481   MZ_FSEEK64(pSrc_file, 0, SEEK_SET);
6482 
6483   if (uncomp_size > 0xFFFFFFFF) {
6484     // No zip64 support yet
6485     MZ_FCLOSE(pSrc_file);
6486     return MZ_FALSE;
6487   }
6488   if (uncomp_size <= 3) level = 0;
6489 
6490   if (!mz_zip_writer_write_zeros(
6491           pZip, cur_archive_file_ofs,
6492           num_alignment_padding_bytes + sizeof(local_dir_header))) {
6493     MZ_FCLOSE(pSrc_file);
6494     return MZ_FALSE;
6495   }
6496   local_dir_header_ofs += num_alignment_padding_bytes;
6497   if (pZip->m_file_offset_alignment) {
6498     MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) ==
6499               0);
6500   }
6501   cur_archive_file_ofs +=
6502       num_alignment_padding_bytes + sizeof(local_dir_header);
6503 
6504   MZ_CLEAR_OBJ(local_dir_header);
6505   if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name,
6506                      archive_name_size) != archive_name_size) {
6507     MZ_FCLOSE(pSrc_file);
6508     return MZ_FALSE;
6509   }
6510   cur_archive_file_ofs += archive_name_size;
6511 
6512   if (uncomp_size) {
6513     mz_uint64 uncomp_remaining = uncomp_size;
6514     void *pRead_buf =
6515         pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, MZ_ZIP_MAX_IO_BUF_SIZE);
6516     if (!pRead_buf) {
6517       MZ_FCLOSE(pSrc_file);
6518       return MZ_FALSE;
6519     }
6520 
6521     if (!level) {
6522       while (uncomp_remaining) {
6523         mz_uint n =
6524             (mz_uint)MZ_MIN((mz_uint)MZ_ZIP_MAX_IO_BUF_SIZE, uncomp_remaining);
6525         if ((MZ_FREAD(pRead_buf, 1, n, pSrc_file) != n) ||
6526             (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf,
6527                             n) != n)) {
6528           pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6529           MZ_FCLOSE(pSrc_file);
6530           return MZ_FALSE;
6531         }
6532         uncomp_crc32 =
6533             (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n);
6534         uncomp_remaining -= n;
6535         cur_archive_file_ofs += n;
6536       }
6537       comp_size = uncomp_size;
6538     } else {
6539       mz_bool result = MZ_FALSE;
6540       mz_zip_writer_add_state state;
6541       tdefl_compressor *pComp = (tdefl_compressor *)pZip->m_pAlloc(
6542           pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor));
6543       if (!pComp) {
6544         pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6545         MZ_FCLOSE(pSrc_file);
6546         return MZ_FALSE;
6547       }
6548 
6549       state.m_pZip = pZip;
6550       state.m_cur_archive_file_ofs = cur_archive_file_ofs;
6551       state.m_comp_size = 0;
6552 
6553       if (tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state,
6554                      tdefl_create_comp_flags_from_zip_params(
6555                          level, -15, MZ_DEFAULT_STRATEGY)) !=
6556           TDEFL_STATUS_OKAY) {
6557         pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6558         pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6559         MZ_FCLOSE(pSrc_file);
6560         return MZ_FALSE;
6561       }
6562 
6563       for (;;) {
6564         size_t in_buf_size = (mz_uint32)MZ_MIN(uncomp_remaining,
6565                                                (mz_uint)MZ_ZIP_MAX_IO_BUF_SIZE);
6566         tdefl_status status;
6567 
6568         if (MZ_FREAD(pRead_buf, 1, in_buf_size, pSrc_file) != in_buf_size)
6569           break;
6570 
6571         uncomp_crc32 = (mz_uint32)mz_crc32(
6572             uncomp_crc32, (const mz_uint8 *)pRead_buf, in_buf_size);
6573         uncomp_remaining -= in_buf_size;
6574 
6575         status = tdefl_compress_buffer(
6576             pComp, pRead_buf, in_buf_size,
6577             uncomp_remaining ? TDEFL_NO_FLUSH : TDEFL_FINISH);
6578         if (status == TDEFL_STATUS_DONE) {
6579           result = MZ_TRUE;
6580           break;
6581         } else if (status != TDEFL_STATUS_OKAY)
6582           break;
6583       }
6584 
6585       pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6586 
6587       if (!result) {
6588         pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6589         MZ_FCLOSE(pSrc_file);
6590         return MZ_FALSE;
6591       }
6592 
6593       comp_size = state.m_comp_size;
6594       cur_archive_file_ofs = state.m_cur_archive_file_ofs;
6595 
6596       method = MZ_DEFLATED;
6597     }
6598 
6599     pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6600   }
6601 
6602   MZ_FCLOSE(pSrc_file);
6603   pSrc_file = NULL;
6604 
6605   // no zip64 support yet
6606   if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF))
6607     return MZ_FALSE;
6608 
6609   if (!mz_zip_writer_create_local_dir_header(
6610           pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size,
6611           comp_size, uncomp_crc32, method, 0, dos_time, dos_date))
6612     return MZ_FALSE;
6613 
6614   if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header,
6615                      sizeof(local_dir_header)) != sizeof(local_dir_header))
6616     return MZ_FALSE;
6617 
6618   if (!mz_zip_writer_add_to_central_dir(
6619           pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment,
6620           comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0,
6621           dos_time, dos_date, local_dir_header_ofs, ext_attributes))
6622     return MZ_FALSE;
6623 
6624   pZip->m_total_files++;
6625   pZip->m_archive_size = cur_archive_file_ofs;
6626 
6627   return MZ_TRUE;
6628 }
6629 #endif  // #ifndef MINIZ_NO_STDIO
6630 
mz_zip_writer_add_from_zip_reader(mz_zip_archive * pZip,mz_zip_archive * pSource_zip,mz_uint file_index)6631 mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip,
6632                                           mz_zip_archive *pSource_zip,
6633                                           mz_uint file_index) {
6634   mz_uint n, bit_flags, num_alignment_padding_bytes;
6635   mz_uint64 comp_bytes_remaining, local_dir_header_ofs;
6636   mz_uint64 cur_src_file_ofs, cur_dst_file_ofs;
6637   mz_uint32
6638       local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) /
6639                        sizeof(mz_uint32)];
6640   mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
6641   mz_uint8 central_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
6642   size_t orig_central_dir_size;
6643   mz_zip_internal_state *pState;
6644   void *pBuf;
6645   const mz_uint8 *pSrc_central_header;
6646 
6647   if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING))
6648     return MZ_FALSE;
6649   if (NULL ==
6650       (pSrc_central_header = mz_zip_reader_get_cdh(pSource_zip, file_index)))
6651     return MZ_FALSE;
6652   pState = pZip->m_pState;
6653 
6654   num_alignment_padding_bytes =
6655       mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
6656 
6657   // no zip64 support yet
6658   if ((pZip->m_total_files == 0xFFFF) ||
6659       ((pZip->m_archive_size + num_alignment_padding_bytes +
6660         MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) >
6661        0xFFFFFFFF))
6662     return MZ_FALSE;
6663 
6664   cur_src_file_ofs =
6665       MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
6666   cur_dst_file_ofs = pZip->m_archive_size;
6667 
6668   if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs,
6669                            pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) !=
6670       MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
6671     return MZ_FALSE;
6672   if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
6673     return MZ_FALSE;
6674   cur_src_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
6675 
6676   if (!mz_zip_writer_write_zeros(pZip, cur_dst_file_ofs,
6677                                  num_alignment_padding_bytes))
6678     return MZ_FALSE;
6679   cur_dst_file_ofs += num_alignment_padding_bytes;
6680   local_dir_header_ofs = cur_dst_file_ofs;
6681   if (pZip->m_file_offset_alignment) {
6682     MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) ==
6683               0);
6684   }
6685 
6686   if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pLocal_header,
6687                      MZ_ZIP_LOCAL_DIR_HEADER_SIZE) !=
6688       MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
6689     return MZ_FALSE;
6690   cur_dst_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
6691 
6692   n = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) +
6693       MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
6694   comp_bytes_remaining =
6695       n + MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
6696 
6697   if (NULL == (pBuf = pZip->m_pAlloc(
6698                    pZip->m_pAlloc_opaque, 1,
6699                    (size_t)MZ_MAX(sizeof(mz_uint32) * 4,
6700                                   MZ_MIN((mz_uint)MZ_ZIP_MAX_IO_BUF_SIZE,
6701                                          comp_bytes_remaining)))))
6702     return MZ_FALSE;
6703 
6704   while (comp_bytes_remaining) {
6705     n = (mz_uint)MZ_MIN((mz_uint)MZ_ZIP_MAX_IO_BUF_SIZE, comp_bytes_remaining);
6706     if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf,
6707                              n) != n) {
6708       pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6709       return MZ_FALSE;
6710     }
6711     cur_src_file_ofs += n;
6712 
6713     if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n) {
6714       pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6715       return MZ_FALSE;
6716     }
6717     cur_dst_file_ofs += n;
6718 
6719     comp_bytes_remaining -= n;
6720   }
6721 
6722   bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS);
6723   if (bit_flags & 8) {
6724     // Copy data descriptor
6725     if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf,
6726                              sizeof(mz_uint32) * 4) != sizeof(mz_uint32) * 4) {
6727       pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6728       return MZ_FALSE;
6729     }
6730 
6731     n = sizeof(mz_uint32) * ((MZ_READ_LE32(pBuf) == 0x08074b50) ? 4 : 3);
6732     if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n) {
6733       pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6734       return MZ_FALSE;
6735     }
6736 
6737     cur_src_file_ofs += n;
6738     cur_dst_file_ofs += n;
6739   }
6740   pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6741 
6742   // no zip64 support yet
6743   if (cur_dst_file_ofs > 0xFFFFFFFF) return MZ_FALSE;
6744 
6745   orig_central_dir_size = pState->m_central_dir.m_size;
6746 
6747   memcpy(central_header, pSrc_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
6748   MZ_WRITE_LE32(central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS,
6749                 local_dir_header_ofs);
6750   if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_header,
6751                               MZ_ZIP_CENTRAL_DIR_HEADER_SIZE))
6752     return MZ_FALSE;
6753 
6754   n = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_FILENAME_LEN_OFS) +
6755       MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS) +
6756       MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_COMMENT_LEN_OFS);
6757   if (!mz_zip_array_push_back(
6758           pZip, &pState->m_central_dir,
6759           pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n)) {
6760     mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size,
6761                         MZ_FALSE);
6762     return MZ_FALSE;
6763   }
6764 
6765   if (pState->m_central_dir.m_size > 0xFFFFFFFF) return MZ_FALSE;
6766   n = (mz_uint32)orig_central_dir_size;
6767   if (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &n, 1)) {
6768     mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size,
6769                         MZ_FALSE);
6770     return MZ_FALSE;
6771   }
6772 
6773   pZip->m_total_files++;
6774   pZip->m_archive_size = cur_dst_file_ofs;
6775 
6776   return MZ_TRUE;
6777 }
6778 
mz_zip_writer_finalize_archive(mz_zip_archive * pZip)6779 mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip) {
6780   mz_zip_internal_state *pState;
6781   mz_uint64 central_dir_ofs, central_dir_size;
6782   mz_uint8 hdr[MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE];
6783 
6784   if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING))
6785     return MZ_FALSE;
6786 
6787   pState = pZip->m_pState;
6788 
6789   // no zip64 support yet
6790   if ((pZip->m_total_files > 0xFFFF) ||
6791       ((pZip->m_archive_size + pState->m_central_dir.m_size +
6792         MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF))
6793     return MZ_FALSE;
6794 
6795   central_dir_ofs = 0;
6796   central_dir_size = 0;
6797   if (pZip->m_total_files) {
6798     // Write central directory
6799     central_dir_ofs = pZip->m_archive_size;
6800     central_dir_size = pState->m_central_dir.m_size;
6801     pZip->m_central_directory_file_ofs = central_dir_ofs;
6802     if (pZip->m_pWrite(pZip->m_pIO_opaque, central_dir_ofs,
6803                        pState->m_central_dir.m_p,
6804                        (size_t)central_dir_size) != central_dir_size)
6805       return MZ_FALSE;
6806     pZip->m_archive_size += central_dir_size;
6807   }
6808 
6809   // Write end of central directory record
6810   MZ_CLEAR_OBJ(hdr);
6811   MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_SIG_OFS,
6812                 MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG);
6813   MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS,
6814                 pZip->m_total_files);
6815   MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS, pZip->m_total_files);
6816   MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_SIZE_OFS, central_dir_size);
6817   MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_OFS_OFS, central_dir_ofs);
6818 
6819   if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr,
6820                      sizeof(hdr)) != sizeof(hdr))
6821     return MZ_FALSE;
6822 #ifndef MINIZ_NO_STDIO
6823   if ((pState->m_pFile) && (MZ_FFLUSH(pState->m_pFile) == EOF)) return MZ_FALSE;
6824 #endif  // #ifndef MINIZ_NO_STDIO
6825 
6826   pZip->m_archive_size += sizeof(hdr);
6827 
6828   pZip->m_zip_mode = MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED;
6829   return MZ_TRUE;
6830 }
6831 
mz_zip_writer_finalize_heap_archive(mz_zip_archive * pZip,void ** pBuf,size_t * pSize)6832 mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **pBuf,
6833                                             size_t *pSize) {
6834   if ((!pZip) || (!pZip->m_pState) || (!pBuf) || (!pSize)) return MZ_FALSE;
6835   if (pZip->m_pWrite != mz_zip_heap_write_func) return MZ_FALSE;
6836   if (!mz_zip_writer_finalize_archive(pZip)) return MZ_FALSE;
6837 
6838   *pBuf = pZip->m_pState->m_pMem;
6839   *pSize = pZip->m_pState->m_mem_size;
6840   pZip->m_pState->m_pMem = NULL;
6841   pZip->m_pState->m_mem_size = pZip->m_pState->m_mem_capacity = 0;
6842   return MZ_TRUE;
6843 }
6844 
mz_zip_writer_end(mz_zip_archive * pZip)6845 mz_bool mz_zip_writer_end(mz_zip_archive *pZip) {
6846   mz_zip_internal_state *pState;
6847   mz_bool status = MZ_TRUE;
6848   if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) ||
6849       ((pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) &&
6850        (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED)))
6851     return MZ_FALSE;
6852 
6853   pState = pZip->m_pState;
6854   pZip->m_pState = NULL;
6855   mz_zip_array_clear(pZip, &pState->m_central_dir);
6856   mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
6857   mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
6858 
6859 #ifndef MINIZ_NO_STDIO
6860   if (pState->m_pFile) {
6861     MZ_FCLOSE(pState->m_pFile);
6862     pState->m_pFile = NULL;
6863   }
6864 #endif  // #ifndef MINIZ_NO_STDIO
6865 
6866   if ((pZip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem)) {
6867     pZip->m_pFree(pZip->m_pAlloc_opaque, pState->m_pMem);
6868     pState->m_pMem = NULL;
6869   }
6870 
6871   pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
6872   pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
6873   return status;
6874 }
6875 
6876 #ifndef MINIZ_NO_STDIO
mz_zip_add_mem_to_archive_file_in_place(const char * pZip_filename,const char * pArchive_name,const void * pBuf,size_t buf_size,const void * pComment,mz_uint16 comment_size,mz_uint level_and_flags)6877 mz_bool mz_zip_add_mem_to_archive_file_in_place(
6878     const char *pZip_filename, const char *pArchive_name, const void *pBuf,
6879     size_t buf_size, const void *pComment, mz_uint16 comment_size,
6880     mz_uint level_and_flags) {
6881   mz_bool status, created_new_archive = MZ_FALSE;
6882   mz_zip_archive zip_archive;
6883   struct MZ_FILE_STAT_STRUCT file_stat;
6884   MZ_CLEAR_OBJ(zip_archive);
6885   if ((int)level_and_flags < 0) level_and_flags = MZ_DEFAULT_LEVEL;
6886   if ((!pZip_filename) || (!pArchive_name) || ((buf_size) && (!pBuf)) ||
6887       ((comment_size) && (!pComment)) ||
6888       ((level_and_flags & 0xF) > MZ_UBER_COMPRESSION))
6889     return MZ_FALSE;
6890   if (!mz_zip_writer_validate_archive_name(pArchive_name)) return MZ_FALSE;
6891   if (MZ_FILE_STAT(pZip_filename, &file_stat) != 0) {
6892     // Create a new archive.
6893     if (!mz_zip_writer_init_file(&zip_archive, pZip_filename, 0))
6894       return MZ_FALSE;
6895     created_new_archive = MZ_TRUE;
6896   } else {
6897     // Append to an existing archive.
6898     if (!mz_zip_reader_init_file(
6899             &zip_archive, pZip_filename,
6900             level_and_flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY))
6901       return MZ_FALSE;
6902     if (!mz_zip_writer_init_from_reader(&zip_archive, pZip_filename)) {
6903       mz_zip_reader_end(&zip_archive);
6904       return MZ_FALSE;
6905     }
6906   }
6907   status =
6908       mz_zip_writer_add_mem_ex(&zip_archive, pArchive_name, pBuf, buf_size,
6909                                pComment, comment_size, level_and_flags, 0, 0);
6910   // Always finalize, even if adding failed for some reason, so we have a valid
6911   // central directory. (This may not always succeed, but we can try.)
6912   if (!mz_zip_writer_finalize_archive(&zip_archive)) status = MZ_FALSE;
6913   if (!mz_zip_writer_end(&zip_archive)) status = MZ_FALSE;
6914   if ((!status) && (created_new_archive)) {
6915     // It's a new archive and something went wrong, so just delete it.
6916     int ignoredStatus = MZ_DELETE_FILE(pZip_filename);
6917     (void)ignoredStatus;
6918   }
6919   return status;
6920 }
6921 
mz_zip_extract_archive_file_to_heap(const char * pZip_filename,const char * pArchive_name,size_t * pSize,mz_uint flags)6922 void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename,
6923                                           const char *pArchive_name,
6924                                           size_t *pSize, mz_uint flags) {
6925   int file_index;
6926   mz_zip_archive zip_archive;
6927   void *p = NULL;
6928 
6929   if (pSize) *pSize = 0;
6930 
6931   if ((!pZip_filename) || (!pArchive_name)) return NULL;
6932 
6933   MZ_CLEAR_OBJ(zip_archive);
6934   if (!mz_zip_reader_init_file(
6935           &zip_archive, pZip_filename,
6936           flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY))
6937     return NULL;
6938 
6939   if ((file_index = mz_zip_reader_locate_file(&zip_archive, pArchive_name, NULL,
6940                                               flags)) >= 0)
6941     p = mz_zip_reader_extract_to_heap(&zip_archive, file_index, pSize, flags);
6942 
6943   mz_zip_reader_end(&zip_archive);
6944   return p;
6945 }
6946 
6947 #endif  // #ifndef MINIZ_NO_STDIO
6948 
6949 #endif  // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
6950 
6951 #endif  // #ifndef MINIZ_NO_ARCHIVE_APIS
6952 
6953 #ifdef __cplusplus
6954 }
6955 #endif
6956 
6957 #ifdef _MSC_VER
6958 #pragma warning(pop)
6959 #endif
6960 
6961 #endif  // MINIZ_HEADER_FILE_ONLY
6962 
6963 /*
6964   This is free and unencumbered software released into the public domain.
6965 
6966   Anyone is free to copy, modify, publish, use, compile, sell, or
6967   distribute this software, either in source code form or as a compiled
6968   binary, for any purpose, commercial or non-commercial, and by any
6969   means.
6970 
6971   In jurisdictions that recognize copyright laws, the author or authors
6972   of this software dedicate any and all copyright interest in the
6973   software to the public domain. We make this dedication for the benefit
6974   of the public at large and to the detriment of our heirs and
6975   successors. We intend this dedication to be an overt act of
6976   relinquishment in perpetuity of all present and future rights to this
6977   software under copyright law.
6978 
6979   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
6980   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
6981   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
6982   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
6983   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
6984   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
6985   OTHER DEALINGS IN THE SOFTWARE.
6986 
6987   For more information, please refer to <http://unlicense.org/>
6988 */
6989 
6990 // ---------------------- end of miniz ----------------------------------------
6991 
6992 #ifdef __clang__
6993 #pragma clang diagnostic pop
6994 #endif
6995 
6996 }  // namespace miniz
6997 #else
6998 
6999 // Reuse MINIZ_LITTE_ENDIAN macro
7000 
7001 #if defined(__sparcv9)
7002 // Big endian
7003 #else
7004 #if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || MINIZ_X86_OR_X64_CPU
7005 // Set MINIZ_LITTLE_ENDIAN to 1 if the processor is little endian.
7006 #define MINIZ_LITTLE_ENDIAN 1
7007 #endif
7008 #endif
7009 
7010 #endif  // TINYEXR_USE_MINIZ
7011 
7012 // static bool IsBigEndian(void) {
7013 //  union {
7014 //    unsigned int i;
7015 //    char c[4];
7016 //  } bint = {0x01020304};
7017 //
7018 //  return bint.c[0] == 1;
7019 //}
7020 
SetErrorMessage(const std::string & msg,const char ** err)7021 static void SetErrorMessage(const std::string &msg, const char **err) {
7022   if (err) {
7023 #ifdef _WIN32
7024     (*err) = _strdup(msg.c_str());
7025 #else
7026     (*err) = strdup(msg.c_str());
7027 #endif
7028   }
7029 }
7030 
7031 static const int kEXRVersionSize = 8;
7032 
cpy2(unsigned short * dst_val,const unsigned short * src_val)7033 static void cpy2(unsigned short *dst_val, const unsigned short *src_val) {
7034   unsigned char *dst = reinterpret_cast<unsigned char *>(dst_val);
7035   const unsigned char *src = reinterpret_cast<const unsigned char *>(src_val);
7036 
7037   dst[0] = src[0];
7038   dst[1] = src[1];
7039 }
7040 
swap2(unsigned short * val)7041 static void swap2(unsigned short *val) {
7042 #ifdef MINIZ_LITTLE_ENDIAN
7043   (void)val;
7044 #else
7045   unsigned short tmp = *val;
7046   unsigned char *dst = reinterpret_cast<unsigned char *>(val);
7047   unsigned char *src = reinterpret_cast<unsigned char *>(&tmp);
7048 
7049   dst[0] = src[1];
7050   dst[1] = src[0];
7051 #endif
7052 }
7053 
7054 #ifdef __clang__
7055 #pragma clang diagnostic push
7056 #pragma clang diagnostic ignored "-Wunused-function"
7057 #endif
7058 
7059 #ifdef __GNUC__
7060 #pragma GCC diagnostic push
7061 #pragma GCC diagnostic ignored "-Wunused-function"
7062 #endif
cpy4(int * dst_val,const int * src_val)7063 static void cpy4(int *dst_val, const int *src_val) {
7064   unsigned char *dst = reinterpret_cast<unsigned char *>(dst_val);
7065   const unsigned char *src = reinterpret_cast<const unsigned char *>(src_val);
7066 
7067   dst[0] = src[0];
7068   dst[1] = src[1];
7069   dst[2] = src[2];
7070   dst[3] = src[3];
7071 }
7072 
cpy4(unsigned int * dst_val,const unsigned int * src_val)7073 static void cpy4(unsigned int *dst_val, const unsigned int *src_val) {
7074   unsigned char *dst = reinterpret_cast<unsigned char *>(dst_val);
7075   const unsigned char *src = reinterpret_cast<const unsigned char *>(src_val);
7076 
7077   dst[0] = src[0];
7078   dst[1] = src[1];
7079   dst[2] = src[2];
7080   dst[3] = src[3];
7081 }
7082 
cpy4(float * dst_val,const float * src_val)7083 static void cpy4(float *dst_val, const float *src_val) {
7084   unsigned char *dst = reinterpret_cast<unsigned char *>(dst_val);
7085   const unsigned char *src = reinterpret_cast<const unsigned char *>(src_val);
7086 
7087   dst[0] = src[0];
7088   dst[1] = src[1];
7089   dst[2] = src[2];
7090   dst[3] = src[3];
7091 }
7092 #ifdef __clang__
7093 #pragma clang diagnostic pop
7094 #endif
7095 
7096 #ifdef __GNUC__
7097 #pragma GCC diagnostic pop
7098 #endif
7099 
swap4(unsigned int * val)7100 static void swap4(unsigned int *val) {
7101 #ifdef MINIZ_LITTLE_ENDIAN
7102   (void)val;
7103 #else
7104   unsigned int tmp = *val;
7105   unsigned char *dst = reinterpret_cast<unsigned char *>(val);
7106   unsigned char *src = reinterpret_cast<unsigned char *>(&tmp);
7107 
7108   dst[0] = src[3];
7109   dst[1] = src[2];
7110   dst[2] = src[1];
7111   dst[3] = src[0];
7112 #endif
7113 }
7114 
7115 #if 0
7116 static void cpy8(tinyexr::tinyexr_uint64 *dst_val, const tinyexr::tinyexr_uint64 *src_val) {
7117   unsigned char *dst = reinterpret_cast<unsigned char *>(dst_val);
7118   const unsigned char *src = reinterpret_cast<const unsigned char *>(src_val);
7119 
7120   dst[0] = src[0];
7121   dst[1] = src[1];
7122   dst[2] = src[2];
7123   dst[3] = src[3];
7124   dst[4] = src[4];
7125   dst[5] = src[5];
7126   dst[6] = src[6];
7127   dst[7] = src[7];
7128 }
7129 #endif
7130 
swap8(tinyexr::tinyexr_uint64 * val)7131 static void swap8(tinyexr::tinyexr_uint64 *val) {
7132 #ifdef MINIZ_LITTLE_ENDIAN
7133   (void)val;
7134 #else
7135   tinyexr::tinyexr_uint64 tmp = (*val);
7136   unsigned char *dst = reinterpret_cast<unsigned char *>(val);
7137   unsigned char *src = reinterpret_cast<unsigned char *>(&tmp);
7138 
7139   dst[0] = src[7];
7140   dst[1] = src[6];
7141   dst[2] = src[5];
7142   dst[3] = src[4];
7143   dst[4] = src[3];
7144   dst[5] = src[2];
7145   dst[6] = src[1];
7146   dst[7] = src[0];
7147 #endif
7148 }
7149 
7150 // https://gist.github.com/rygorous/2156668
7151 // Reuse MINIZ_LITTLE_ENDIAN flag from miniz.
7152 union FP32 {
7153   unsigned int u;
7154   float f;
7155   struct {
7156 #if MINIZ_LITTLE_ENDIAN
7157     unsigned int Mantissa : 23;
7158     unsigned int Exponent : 8;
7159     unsigned int Sign : 1;
7160 #else
7161     unsigned int Sign : 1;
7162     unsigned int Exponent : 8;
7163     unsigned int Mantissa : 23;
7164 #endif
7165   } s;
7166 };
7167 
7168 #ifdef __clang__
7169 #pragma clang diagnostic push
7170 #pragma clang diagnostic ignored "-Wpadded"
7171 #endif
7172 
7173 union FP16 {
7174   unsigned short u;
7175   struct {
7176 #if MINIZ_LITTLE_ENDIAN
7177     unsigned int Mantissa : 10;
7178     unsigned int Exponent : 5;
7179     unsigned int Sign : 1;
7180 #else
7181     unsigned int Sign : 1;
7182     unsigned int Exponent : 5;
7183     unsigned int Mantissa : 10;
7184 #endif
7185   } s;
7186 };
7187 
7188 #ifdef __clang__
7189 #pragma clang diagnostic pop
7190 #endif
7191 
half_to_float(FP16 h)7192 static FP32 half_to_float(FP16 h) {
7193   static const FP32 magic = {113 << 23};
7194   static const unsigned int shifted_exp = 0x7c00
7195                                           << 13;  // exponent mask after shift
7196   FP32 o;
7197 
7198   o.u = (h.u & 0x7fffU) << 13U;           // exponent/mantissa bits
7199   unsigned int exp_ = shifted_exp & o.u;  // just the exponent
7200   o.u += (127 - 15) << 23;                // exponent adjust
7201 
7202   // handle exponent special cases
7203   if (exp_ == shifted_exp)    // Inf/NaN?
7204     o.u += (128 - 16) << 23;  // extra exp adjust
7205   else if (exp_ == 0)         // Zero/Denormal?
7206   {
7207     o.u += 1 << 23;  // extra exp adjust
7208     o.f -= magic.f;  // renormalize
7209   }
7210 
7211   o.u |= (h.u & 0x8000U) << 16U;  // sign bit
7212   return o;
7213 }
7214 
float_to_half_full(FP32 f)7215 static FP16 float_to_half_full(FP32 f) {
7216   FP16 o = {0};
7217 
7218   // Based on ISPC reference code (with minor modifications)
7219   if (f.s.Exponent == 0)  // Signed zero/denormal (which will underflow)
7220     o.s.Exponent = 0;
7221   else if (f.s.Exponent == 255)  // Inf or NaN (all exponent bits set)
7222   {
7223     o.s.Exponent = 31;
7224     o.s.Mantissa = f.s.Mantissa ? 0x200 : 0;  // NaN->qNaN and Inf->Inf
7225   } else                                      // Normalized number
7226   {
7227     // Exponent unbias the single, then bias the halfp
7228     int newexp = f.s.Exponent - 127 + 15;
7229     if (newexp >= 31)  // Overflow, return signed infinity
7230       o.s.Exponent = 31;
7231     else if (newexp <= 0)  // Underflow
7232     {
7233       if ((14 - newexp) <= 24)  // Mantissa might be non-zero
7234       {
7235         unsigned int mant = f.s.Mantissa | 0x800000;  // Hidden 1 bit
7236         o.s.Mantissa = mant >> (14 - newexp);
7237         if ((mant >> (13 - newexp)) & 1)  // Check for rounding
7238           o.u++;  // Round, might overflow into exp bit, but this is OK
7239       }
7240     } else {
7241       o.s.Exponent = static_cast<unsigned int>(newexp);
7242       o.s.Mantissa = f.s.Mantissa >> 13;
7243       if (f.s.Mantissa & 0x1000)  // Check for rounding
7244         o.u++;                    // Round, might overflow to inf, this is OK
7245     }
7246   }
7247 
7248   o.s.Sign = f.s.Sign;
7249   return o;
7250 }
7251 
7252 // NOTE: From OpenEXR code
7253 // #define IMF_INCREASING_Y  0
7254 // #define IMF_DECREASING_Y  1
7255 // #define IMF_RAMDOM_Y    2
7256 //
7257 // #define IMF_NO_COMPRESSION  0
7258 // #define IMF_RLE_COMPRESSION 1
7259 // #define IMF_ZIPS_COMPRESSION  2
7260 // #define IMF_ZIP_COMPRESSION 3
7261 // #define IMF_PIZ_COMPRESSION 4
7262 // #define IMF_PXR24_COMPRESSION 5
7263 // #define IMF_B44_COMPRESSION 6
7264 // #define IMF_B44A_COMPRESSION  7
7265 
7266 #ifdef __clang__
7267 #pragma clang diagnostic push
7268 
7269 #if __has_warning("-Wzero-as-null-pointer-constant")
7270 #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
7271 #endif
7272 
7273 #endif
7274 
ReadString(std::string * s,const char * ptr,size_t len)7275 static const char *ReadString(std::string *s, const char *ptr, size_t len) {
7276   // Read untile NULL(\0).
7277   const char *p = ptr;
7278   const char *q = ptr;
7279   while ((size_t(q - ptr) < len) && (*q) != 0) {
7280     q++;
7281   }
7282 
7283   if (size_t(q - ptr) >= len) {
7284     (*s) = std::string();
7285     return NULL;
7286   }
7287 
7288   (*s) = std::string(p, q);
7289 
7290   return q + 1;  // skip '\0'
7291 }
7292 
ReadAttribute(std::string * name,std::string * type,std::vector<unsigned char> * data,size_t * marker_size,const char * marker,size_t size)7293 static bool ReadAttribute(std::string *name, std::string *type,
7294                           std::vector<unsigned char> *data, size_t *marker_size,
7295                           const char *marker, size_t size) {
7296   size_t name_len = strnlen(marker, size);
7297   if (name_len == size) {
7298     // String does not have a terminating character.
7299     return false;
7300   }
7301   *name = std::string(marker, name_len);
7302 
7303   marker += name_len + 1;
7304   size -= name_len + 1;
7305 
7306   size_t type_len = strnlen(marker, size);
7307   if (type_len == size) {
7308     return false;
7309   }
7310   *type = std::string(marker, type_len);
7311 
7312   marker += type_len + 1;
7313   size -= type_len + 1;
7314 
7315   if (size < sizeof(uint32_t)) {
7316     return false;
7317   }
7318 
7319   uint32_t data_len;
7320   memcpy(&data_len, marker, sizeof(uint32_t));
7321   tinyexr::swap4(reinterpret_cast<unsigned int *>(&data_len));
7322 
7323   if (data_len == 0) {
7324     if ((*type).compare("string") == 0) {
7325       // Accept empty string attribute.
7326 
7327       marker += sizeof(uint32_t);
7328       size -= sizeof(uint32_t);
7329 
7330       *marker_size = name_len + 1 + type_len + 1 + sizeof(uint32_t);
7331 
7332       data->resize(1);
7333       (*data)[0] = '\0';
7334 
7335       return true;
7336     } else {
7337       return false;
7338     }
7339   }
7340 
7341   marker += sizeof(uint32_t);
7342   size -= sizeof(uint32_t);
7343 
7344   if (size < data_len) {
7345     return false;
7346   }
7347 
7348   data->resize(static_cast<size_t>(data_len));
7349   memcpy(&data->at(0), marker, static_cast<size_t>(data_len));
7350 
7351   *marker_size = name_len + 1 + type_len + 1 + sizeof(uint32_t) + data_len;
7352   return true;
7353 }
7354 
WriteAttributeToMemory(std::vector<unsigned char> * out,const char * name,const char * type,const unsigned char * data,int len)7355 static void WriteAttributeToMemory(std::vector<unsigned char> *out,
7356                                    const char *name, const char *type,
7357                                    const unsigned char *data, int len) {
7358   out->insert(out->end(), name, name + strlen(name) + 1);
7359   out->insert(out->end(), type, type + strlen(type) + 1);
7360 
7361   int outLen = len;
7362   tinyexr::swap4(reinterpret_cast<unsigned int *>(&outLen));
7363   out->insert(out->end(), reinterpret_cast<unsigned char *>(&outLen),
7364               reinterpret_cast<unsigned char *>(&outLen) + sizeof(int));
7365   out->insert(out->end(), data, data + len);
7366 }
7367 
7368 struct ChannelInfo {
7369   std::string name;  // less than 255 bytes long
7370   int pixel_type;
7371   int x_sampling;
7372   int y_sampling;
7373   unsigned char p_linear;
7374   unsigned char pad[3];
7375 };
7376 
7377 struct HeaderInfo {
7378   std::vector<tinyexr::ChannelInfo> channels;
7379   std::vector<EXRAttribute> attributes;
7380 
7381   int data_window[4];
7382   int line_order;
7383   int display_window[4];
7384   float screen_window_center[2];
7385   float screen_window_width;
7386   float pixel_aspect_ratio;
7387 
7388   int chunk_count;
7389 
7390   // Tiled format
7391   int tile_size_x;
7392   int tile_size_y;
7393   int tile_level_mode;
7394   int tile_rounding_mode;
7395 
7396   unsigned int header_len;
7397 
7398   int compression_type;
7399 
clearHeaderInfo7400   void clear() {
7401     channels.clear();
7402     attributes.clear();
7403 
7404     data_window[0] = 0;
7405     data_window[1] = 0;
7406     data_window[2] = 0;
7407     data_window[3] = 0;
7408     line_order = 0;
7409     display_window[0] = 0;
7410     display_window[1] = 0;
7411     display_window[2] = 0;
7412     display_window[3] = 0;
7413     screen_window_center[0] = 0.0f;
7414     screen_window_center[1] = 0.0f;
7415     screen_window_width = 0.0f;
7416     pixel_aspect_ratio = 0.0f;
7417 
7418     chunk_count = 0;
7419 
7420     // Tiled format
7421     tile_size_x = 0;
7422     tile_size_y = 0;
7423     tile_level_mode = 0;
7424     tile_rounding_mode = 0;
7425 
7426     header_len = 0;
7427     compression_type = 0;
7428   }
7429 };
7430 
ReadChannelInfo(std::vector<ChannelInfo> & channels,const std::vector<unsigned char> & data)7431 static bool ReadChannelInfo(std::vector<ChannelInfo> &channels,
7432                             const std::vector<unsigned char> &data) {
7433   const char *p = reinterpret_cast<const char *>(&data.at(0));
7434 
7435   for (;;) {
7436     if ((*p) == 0) {
7437       break;
7438     }
7439     ChannelInfo info;
7440 
7441     tinyexr_int64 data_len = static_cast<tinyexr_int64>(data.size()) -
7442                              (p - reinterpret_cast<const char *>(data.data()));
7443     if (data_len < 0) {
7444       return false;
7445     }
7446 
7447     p = ReadString(&info.name, p, size_t(data_len));
7448     if ((p == NULL) && (info.name.empty())) {
7449       // Buffer overrun. Issue #51.
7450       return false;
7451     }
7452 
7453     const unsigned char *data_end =
7454         reinterpret_cast<const unsigned char *>(p) + 16;
7455     if (data_end >= (data.data() + data.size())) {
7456       return false;
7457     }
7458 
7459     memcpy(&info.pixel_type, p, sizeof(int));
7460     p += 4;
7461     info.p_linear = static_cast<unsigned char>(p[0]);  // uchar
7462     p += 1 + 3;                                        // reserved: uchar[3]
7463     memcpy(&info.x_sampling, p, sizeof(int));          // int
7464     p += 4;
7465     memcpy(&info.y_sampling, p, sizeof(int));  // int
7466     p += 4;
7467 
7468     tinyexr::swap4(reinterpret_cast<unsigned int *>(&info.pixel_type));
7469     tinyexr::swap4(reinterpret_cast<unsigned int *>(&info.x_sampling));
7470     tinyexr::swap4(reinterpret_cast<unsigned int *>(&info.y_sampling));
7471 
7472     channels.push_back(info);
7473   }
7474 
7475   return true;
7476 }
7477 
WriteChannelInfo(std::vector<unsigned char> & data,const std::vector<ChannelInfo> & channels)7478 static void WriteChannelInfo(std::vector<unsigned char> &data,
7479                              const std::vector<ChannelInfo> &channels) {
7480   size_t sz = 0;
7481 
7482   // Calculate total size.
7483   for (size_t c = 0; c < channels.size(); c++) {
7484     sz += strlen(channels[c].name.c_str()) + 1;  // +1 for \0
7485     sz += 16;                                    // 4 * int
7486   }
7487   data.resize(sz + 1);
7488 
7489   unsigned char *p = &data.at(0);
7490 
7491   for (size_t c = 0; c < channels.size(); c++) {
7492     memcpy(p, channels[c].name.c_str(), strlen(channels[c].name.c_str()));
7493     p += strlen(channels[c].name.c_str());
7494     (*p) = '\0';
7495     p++;
7496 
7497     int pixel_type = channels[c].pixel_type;
7498     int x_sampling = channels[c].x_sampling;
7499     int y_sampling = channels[c].y_sampling;
7500     tinyexr::swap4(reinterpret_cast<unsigned int *>(&pixel_type));
7501     tinyexr::swap4(reinterpret_cast<unsigned int *>(&x_sampling));
7502     tinyexr::swap4(reinterpret_cast<unsigned int *>(&y_sampling));
7503 
7504     memcpy(p, &pixel_type, sizeof(int));
7505     p += sizeof(int);
7506 
7507     (*p) = channels[c].p_linear;
7508     p += 4;
7509 
7510     memcpy(p, &x_sampling, sizeof(int));
7511     p += sizeof(int);
7512 
7513     memcpy(p, &y_sampling, sizeof(int));
7514     p += sizeof(int);
7515   }
7516 
7517   (*p) = '\0';
7518 }
7519 
CompressZip(unsigned char * dst,tinyexr::tinyexr_uint64 & compressedSize,const unsigned char * src,unsigned long src_size)7520 static void CompressZip(unsigned char *dst,
7521                         tinyexr::tinyexr_uint64 &compressedSize,
7522                         const unsigned char *src, unsigned long src_size) {
7523   std::vector<unsigned char> tmpBuf(src_size);
7524 
7525   //
7526   // Apply EXR-specific? postprocess. Grabbed from OpenEXR's
7527   // ImfZipCompressor.cpp
7528   //
7529 
7530   //
7531   // Reorder the pixel data.
7532   //
7533 
7534   const char *srcPtr = reinterpret_cast<const char *>(src);
7535 
7536   {
7537     char *t1 = reinterpret_cast<char *>(&tmpBuf.at(0));
7538     char *t2 = reinterpret_cast<char *>(&tmpBuf.at(0)) + (src_size + 1) / 2;
7539     const char *stop = srcPtr + src_size;
7540 
7541     for (;;) {
7542       if (srcPtr < stop)
7543         *(t1++) = *(srcPtr++);
7544       else
7545         break;
7546 
7547       if (srcPtr < stop)
7548         *(t2++) = *(srcPtr++);
7549       else
7550         break;
7551     }
7552   }
7553 
7554   //
7555   // Predictor.
7556   //
7557 
7558   {
7559     unsigned char *t = &tmpBuf.at(0) + 1;
7560     unsigned char *stop = &tmpBuf.at(0) + src_size;
7561     int p = t[-1];
7562 
7563     while (t < stop) {
7564       int d = int(t[0]) - p + (128 + 256);
7565       p = t[0];
7566       t[0] = static_cast<unsigned char>(d);
7567       ++t;
7568     }
7569   }
7570 
7571 #if TINYEXR_USE_MINIZ
7572   //
7573   // Compress the data using miniz
7574   //
7575 
7576   miniz::mz_ulong outSize = miniz::mz_compressBound(src_size);
7577   int ret = miniz::mz_compress(
7578       dst, &outSize, static_cast<const unsigned char *>(&tmpBuf.at(0)),
7579       src_size);
7580   TEXR_ASSERT(ret == miniz::MZ_OK);
7581   (void)ret;
7582 
7583   compressedSize = outSize;
7584 #else
7585   uLong outSize = compressBound(static_cast<uLong>(src_size));
7586   int ret = compress(dst, &outSize, static_cast<const Bytef *>(&tmpBuf.at(0)),
7587                      src_size);
7588   TEXR_ASSERT(ret == Z_OK);
7589 
7590   compressedSize = outSize;
7591 #endif
7592 
7593   // Use uncompressed data when compressed data is larger than uncompressed.
7594   // (Issue 40)
7595   if (compressedSize >= src_size) {
7596     compressedSize = src_size;
7597     memcpy(dst, src, src_size);
7598   }
7599 }
7600 
DecompressZip(unsigned char * dst,unsigned long * uncompressed_size,const unsigned char * src,unsigned long src_size)7601 static bool DecompressZip(unsigned char *dst,
7602                           unsigned long *uncompressed_size /* inout */,
7603                           const unsigned char *src, unsigned long src_size) {
7604   if ((*uncompressed_size) == src_size) {
7605     // Data is not compressed(Issue 40).
7606     memcpy(dst, src, src_size);
7607     return true;
7608   }
7609   std::vector<unsigned char> tmpBuf(*uncompressed_size);
7610 
7611 #if TINYEXR_USE_MINIZ
7612   int ret =
7613       miniz::mz_uncompress(&tmpBuf.at(0), uncompressed_size, src, src_size);
7614   if (miniz::MZ_OK != ret) {
7615     return false;
7616   }
7617 #else
7618   int ret = uncompress(&tmpBuf.at(0), uncompressed_size, src, src_size);
7619   if (Z_OK != ret) {
7620     return false;
7621   }
7622 #endif
7623 
7624   //
7625   // Apply EXR-specific? postprocess. Grabbed from OpenEXR's
7626   // ImfZipCompressor.cpp
7627   //
7628 
7629   // Predictor.
7630   {
7631     unsigned char *t = &tmpBuf.at(0) + 1;
7632     unsigned char *stop = &tmpBuf.at(0) + (*uncompressed_size);
7633 
7634     while (t < stop) {
7635       int d = int(t[-1]) + int(t[0]) - 128;
7636       t[0] = static_cast<unsigned char>(d);
7637       ++t;
7638     }
7639   }
7640 
7641   // Reorder the pixel data.
7642   {
7643     const char *t1 = reinterpret_cast<const char *>(&tmpBuf.at(0));
7644     const char *t2 = reinterpret_cast<const char *>(&tmpBuf.at(0)) +
7645                      (*uncompressed_size + 1) / 2;
7646     char *s = reinterpret_cast<char *>(dst);
7647     char *stop = s + (*uncompressed_size);
7648 
7649     for (;;) {
7650       if (s < stop)
7651         *(s++) = *(t1++);
7652       else
7653         break;
7654 
7655       if (s < stop)
7656         *(s++) = *(t2++);
7657       else
7658         break;
7659     }
7660   }
7661 
7662   return true;
7663 }
7664 
7665 // RLE code from OpenEXR --------------------------------------
7666 
7667 #ifdef __clang__
7668 #pragma clang diagnostic push
7669 #pragma clang diagnostic ignored "-Wsign-conversion"
7670 #if __has_warning("-Wextra-semi-stmt")
7671 #pragma clang diagnostic ignored "-Wextra-semi-stmt"
7672 #endif
7673 #endif
7674 
7675 #ifdef _MSC_VER
7676 #pragma warning(push)
7677 #pragma warning(disable : 4204)  // nonstandard extension used : non-constant
7678                                  // aggregate initializer (also supported by GNU
7679                                  // C and C99, so no big deal)
7680 #pragma warning(disable : 4244)  // 'initializing': conversion from '__int64' to
7681                                  // 'int', possible loss of data
7682 #pragma warning(disable : 4267)  // 'argument': conversion from '__int64' to
7683                                  // 'int', possible loss of data
7684 #pragma warning(disable : 4996)  // 'strdup': The POSIX name for this item is
7685                                  // deprecated. Instead, use the ISO C and C++
7686                                  // conformant name: _strdup.
7687 #endif
7688 
7689 const int MIN_RUN_LENGTH = 3;
7690 const int MAX_RUN_LENGTH = 127;
7691 
7692 //
7693 // Compress an array of bytes, using run-length encoding,
7694 // and return the length of the compressed data.
7695 //
7696 
rleCompress(int inLength,const char in[],signed char out[])7697 static int rleCompress(int inLength, const char in[], signed char out[]) {
7698   const char *inEnd = in + inLength;
7699   const char *runStart = in;
7700   const char *runEnd = in + 1;
7701   signed char *outWrite = out;
7702 
7703   while (runStart < inEnd) {
7704     while (runEnd < inEnd && *runStart == *runEnd &&
7705            runEnd - runStart - 1 < MAX_RUN_LENGTH) {
7706       ++runEnd;
7707     }
7708 
7709     if (runEnd - runStart >= MIN_RUN_LENGTH) {
7710       //
7711       // Compressable run
7712       //
7713 
7714       *outWrite++ = static_cast<char>(runEnd - runStart) - 1;
7715       *outWrite++ = *(reinterpret_cast<const signed char *>(runStart));
7716       runStart = runEnd;
7717     } else {
7718       //
7719       // Uncompressable run
7720       //
7721 
7722       while (runEnd < inEnd &&
7723              ((runEnd + 1 >= inEnd || *runEnd != *(runEnd + 1)) ||
7724               (runEnd + 2 >= inEnd || *(runEnd + 1) != *(runEnd + 2))) &&
7725              runEnd - runStart < MAX_RUN_LENGTH) {
7726         ++runEnd;
7727       }
7728 
7729       *outWrite++ = static_cast<char>(runStart - runEnd);
7730 
7731       while (runStart < runEnd) {
7732         *outWrite++ = *(reinterpret_cast<const signed char *>(runStart++));
7733       }
7734     }
7735 
7736     ++runEnd;
7737   }
7738 
7739   return static_cast<int>(outWrite - out);
7740 }
7741 
7742 //
7743 // Uncompress an array of bytes compressed with rleCompress().
7744 // Returns the length of the oncompressed data, or 0 if the
7745 // length of the uncompressed data would be more than maxLength.
7746 //
7747 
rleUncompress(int inLength,int maxLength,const signed char in[],char out[])7748 static int rleUncompress(int inLength, int maxLength, const signed char in[],
7749                          char out[]) {
7750   char *outStart = out;
7751 
7752   while (inLength > 0) {
7753     if (*in < 0) {
7754       int count = -(static_cast<int>(*in++));
7755       inLength -= count + 1;
7756 
7757       // Fixes #116: Add bounds check to in buffer.
7758       if ((0 > (maxLength -= count)) || (inLength < 0)) return 0;
7759 
7760       memcpy(out, in, count);
7761       out += count;
7762       in += count;
7763     } else {
7764       int count = *in++;
7765       inLength -= 2;
7766 
7767       if (0 > (maxLength -= count + 1)) return 0;
7768 
7769       memset(out, *reinterpret_cast<const char *>(in), count + 1);
7770       out += count + 1;
7771 
7772       in++;
7773     }
7774   }
7775 
7776   return static_cast<int>(out - outStart);
7777 }
7778 
7779 #ifdef __clang__
7780 #pragma clang diagnostic pop
7781 #endif
7782 
7783 // End of RLE code from OpenEXR -----------------------------------
7784 
CompressRle(unsigned char * dst,tinyexr::tinyexr_uint64 & compressedSize,const unsigned char * src,unsigned long src_size)7785 static void CompressRle(unsigned char *dst,
7786                         tinyexr::tinyexr_uint64 &compressedSize,
7787                         const unsigned char *src, unsigned long src_size) {
7788   std::vector<unsigned char> tmpBuf(src_size);
7789 
7790   //
7791   // Apply EXR-specific? postprocess. Grabbed from OpenEXR's
7792   // ImfRleCompressor.cpp
7793   //
7794 
7795   //
7796   // Reorder the pixel data.
7797   //
7798 
7799   const char *srcPtr = reinterpret_cast<const char *>(src);
7800 
7801   {
7802     char *t1 = reinterpret_cast<char *>(&tmpBuf.at(0));
7803     char *t2 = reinterpret_cast<char *>(&tmpBuf.at(0)) + (src_size + 1) / 2;
7804     const char *stop = srcPtr + src_size;
7805 
7806     for (;;) {
7807       if (srcPtr < stop)
7808         *(t1++) = *(srcPtr++);
7809       else
7810         break;
7811 
7812       if (srcPtr < stop)
7813         *(t2++) = *(srcPtr++);
7814       else
7815         break;
7816     }
7817   }
7818 
7819   //
7820   // Predictor.
7821   //
7822 
7823   {
7824     unsigned char *t = &tmpBuf.at(0) + 1;
7825     unsigned char *stop = &tmpBuf.at(0) + src_size;
7826     int p = t[-1];
7827 
7828     while (t < stop) {
7829       int d = int(t[0]) - p + (128 + 256);
7830       p = t[0];
7831       t[0] = static_cast<unsigned char>(d);
7832       ++t;
7833     }
7834   }
7835 
7836   // outSize will be (srcSiz * 3) / 2 at max.
7837   int outSize = rleCompress(static_cast<int>(src_size),
7838                             reinterpret_cast<const char *>(&tmpBuf.at(0)),
7839                             reinterpret_cast<signed char *>(dst));
7840   TEXR_ASSERT(outSize > 0);
7841 
7842   compressedSize = static_cast<tinyexr::tinyexr_uint64>(outSize);
7843 
7844   // Use uncompressed data when compressed data is larger than uncompressed.
7845   // (Issue 40)
7846   if (compressedSize >= src_size) {
7847     compressedSize = src_size;
7848     memcpy(dst, src, src_size);
7849   }
7850 }
7851 
DecompressRle(unsigned char * dst,const unsigned long uncompressed_size,const unsigned char * src,unsigned long src_size)7852 static bool DecompressRle(unsigned char *dst,
7853                           const unsigned long uncompressed_size,
7854                           const unsigned char *src, unsigned long src_size) {
7855   if (uncompressed_size == src_size) {
7856     // Data is not compressed(Issue 40).
7857     memcpy(dst, src, src_size);
7858     return true;
7859   }
7860 
7861   // Workaround for issue #112.
7862   // TODO(syoyo): Add more robust out-of-bounds check in `rleUncompress`.
7863   if (src_size <= 2) {
7864     return false;
7865   }
7866 
7867   std::vector<unsigned char> tmpBuf(uncompressed_size);
7868 
7869   int ret = rleUncompress(static_cast<int>(src_size),
7870                           static_cast<int>(uncompressed_size),
7871                           reinterpret_cast<const signed char *>(src),
7872                           reinterpret_cast<char *>(&tmpBuf.at(0)));
7873   if (ret != static_cast<int>(uncompressed_size)) {
7874     return false;
7875   }
7876 
7877   //
7878   // Apply EXR-specific? postprocess. Grabbed from OpenEXR's
7879   // ImfRleCompressor.cpp
7880   //
7881 
7882   // Predictor.
7883   {
7884     unsigned char *t = &tmpBuf.at(0) + 1;
7885     unsigned char *stop = &tmpBuf.at(0) + uncompressed_size;
7886 
7887     while (t < stop) {
7888       int d = int(t[-1]) + int(t[0]) - 128;
7889       t[0] = static_cast<unsigned char>(d);
7890       ++t;
7891     }
7892   }
7893 
7894   // Reorder the pixel data.
7895   {
7896     const char *t1 = reinterpret_cast<const char *>(&tmpBuf.at(0));
7897     const char *t2 = reinterpret_cast<const char *>(&tmpBuf.at(0)) +
7898                      (uncompressed_size + 1) / 2;
7899     char *s = reinterpret_cast<char *>(dst);
7900     char *stop = s + uncompressed_size;
7901 
7902     for (;;) {
7903       if (s < stop)
7904         *(s++) = *(t1++);
7905       else
7906         break;
7907 
7908       if (s < stop)
7909         *(s++) = *(t2++);
7910       else
7911         break;
7912     }
7913   }
7914 
7915   return true;
7916 }
7917 
7918 #if TINYEXR_USE_PIZ
7919 
7920 #ifdef __clang__
7921 #pragma clang diagnostic push
7922 #pragma clang diagnostic ignored "-Wc++11-long-long"
7923 #pragma clang diagnostic ignored "-Wold-style-cast"
7924 #pragma clang diagnostic ignored "-Wpadded"
7925 #pragma clang diagnostic ignored "-Wsign-conversion"
7926 #pragma clang diagnostic ignored "-Wc++11-extensions"
7927 #pragma clang diagnostic ignored "-Wconversion"
7928 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
7929 
7930 #if __has_warning("-Wcast-qual")
7931 #pragma clang diagnostic ignored "-Wcast-qual"
7932 #endif
7933 
7934 #if __has_warning("-Wextra-semi-stmt")
7935 #pragma clang diagnostic ignored "-Wextra-semi-stmt"
7936 #endif
7937 
7938 #endif
7939 
7940 //
7941 // PIZ compress/uncompress, based on OpenEXR's ImfPizCompressor.cpp
7942 //
7943 // -----------------------------------------------------------------
7944 // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
7945 // Digital Ltd. LLC)
7946 // (3 clause BSD license)
7947 //
7948 
7949 struct PIZChannelData {
7950   unsigned short *start;
7951   unsigned short *end;
7952   int nx;
7953   int ny;
7954   int ys;
7955   int size;
7956 };
7957 
7958 //-----------------------------------------------------------------------------
7959 //
7960 //  16-bit Haar Wavelet encoding and decoding
7961 //
7962 //  The source code in this file is derived from the encoding
7963 //  and decoding routines written by Christian Rouet for his
7964 //  PIZ image file format.
7965 //
7966 //-----------------------------------------------------------------------------
7967 
7968 //
7969 // Wavelet basis functions without modulo arithmetic; they produce
7970 // the best compression ratios when the wavelet-transformed data are
7971 // Huffman-encoded, but the wavelet transform works only for 14-bit
7972 // data (untransformed data values must be less than (1 << 14)).
7973 //
7974 
wenc14(unsigned short a,unsigned short b,unsigned short & l,unsigned short & h)7975 inline void wenc14(unsigned short a, unsigned short b, unsigned short &l,
7976                    unsigned short &h) {
7977   short as = static_cast<short>(a);
7978   short bs = static_cast<short>(b);
7979 
7980   short ms = (as + bs) >> 1;
7981   short ds = as - bs;
7982 
7983   l = static_cast<unsigned short>(ms);
7984   h = static_cast<unsigned short>(ds);
7985 }
7986 
wdec14(unsigned short l,unsigned short h,unsigned short & a,unsigned short & b)7987 inline void wdec14(unsigned short l, unsigned short h, unsigned short &a,
7988                    unsigned short &b) {
7989   short ls = static_cast<short>(l);
7990   short hs = static_cast<short>(h);
7991 
7992   int hi = hs;
7993   int ai = ls + (hi & 1) + (hi >> 1);
7994 
7995   short as = static_cast<short>(ai);
7996   short bs = static_cast<short>(ai - hi);
7997 
7998   a = static_cast<unsigned short>(as);
7999   b = static_cast<unsigned short>(bs);
8000 }
8001 
8002 //
8003 // Wavelet basis functions with modulo arithmetic; they work with full
8004 // 16-bit data, but Huffman-encoding the wavelet-transformed data doesn't
8005 // compress the data quite as well.
8006 //
8007 
8008 const int NBITS = 16;
8009 const int A_OFFSET = 1 << (NBITS - 1);
8010 const int M_OFFSET = 1 << (NBITS - 1);
8011 const int MOD_MASK = (1 << NBITS) - 1;
8012 
wenc16(unsigned short a,unsigned short b,unsigned short & l,unsigned short & h)8013 inline void wenc16(unsigned short a, unsigned short b, unsigned short &l,
8014                    unsigned short &h) {
8015   int ao = (a + A_OFFSET) & MOD_MASK;
8016   int m = ((ao + b) >> 1);
8017   int d = ao - b;
8018 
8019   if (d < 0) m = (m + M_OFFSET) & MOD_MASK;
8020 
8021   d &= MOD_MASK;
8022 
8023   l = static_cast<unsigned short>(m);
8024   h = static_cast<unsigned short>(d);
8025 }
8026 
wdec16(unsigned short l,unsigned short h,unsigned short & a,unsigned short & b)8027 inline void wdec16(unsigned short l, unsigned short h, unsigned short &a,
8028                    unsigned short &b) {
8029   int m = l;
8030   int d = h;
8031   int bb = (m - (d >> 1)) & MOD_MASK;
8032   int aa = (d + bb - A_OFFSET) & MOD_MASK;
8033   b = static_cast<unsigned short>(bb);
8034   a = static_cast<unsigned short>(aa);
8035 }
8036 
8037 //
8038 // 2D Wavelet encoding:
8039 //
8040 
wav2Encode(unsigned short * in,int nx,int ox,int ny,int oy,unsigned short mx)8041 static void wav2Encode(
8042     unsigned short *in,  // io: values are transformed in place
8043     int nx,              // i : x size
8044     int ox,              // i : x offset
8045     int ny,              // i : y size
8046     int oy,              // i : y offset
8047     unsigned short mx)   // i : maximum in[x][y] value
8048 {
8049   bool w14 = (mx < (1 << 14));
8050   int n = (nx > ny) ? ny : nx;
8051   int p = 1;   // == 1 <<  level
8052   int p2 = 2;  // == 1 << (level+1)
8053 
8054   //
8055   // Hierachical loop on smaller dimension n
8056   //
8057 
8058   while (p2 <= n) {
8059     unsigned short *py = in;
8060     unsigned short *ey = in + oy * (ny - p2);
8061     int oy1 = oy * p;
8062     int oy2 = oy * p2;
8063     int ox1 = ox * p;
8064     int ox2 = ox * p2;
8065     unsigned short i00, i01, i10, i11;
8066 
8067     //
8068     // Y loop
8069     //
8070 
8071     for (; py <= ey; py += oy2) {
8072       unsigned short *px = py;
8073       unsigned short *ex = py + ox * (nx - p2);
8074 
8075       //
8076       // X loop
8077       //
8078 
8079       for (; px <= ex; px += ox2) {
8080         unsigned short *p01 = px + ox1;
8081         unsigned short *p10 = px + oy1;
8082         unsigned short *p11 = p10 + ox1;
8083 
8084         //
8085         // 2D wavelet encoding
8086         //
8087 
8088         if (w14) {
8089           wenc14(*px, *p01, i00, i01);
8090           wenc14(*p10, *p11, i10, i11);
8091           wenc14(i00, i10, *px, *p10);
8092           wenc14(i01, i11, *p01, *p11);
8093         } else {
8094           wenc16(*px, *p01, i00, i01);
8095           wenc16(*p10, *p11, i10, i11);
8096           wenc16(i00, i10, *px, *p10);
8097           wenc16(i01, i11, *p01, *p11);
8098         }
8099       }
8100 
8101       //
8102       // Encode (1D) odd column (still in Y loop)
8103       //
8104 
8105       if (nx & p) {
8106         unsigned short *p10 = px + oy1;
8107 
8108         if (w14)
8109           wenc14(*px, *p10, i00, *p10);
8110         else
8111           wenc16(*px, *p10, i00, *p10);
8112 
8113         *px = i00;
8114       }
8115     }
8116 
8117     //
8118     // Encode (1D) odd line (must loop in X)
8119     //
8120 
8121     if (ny & p) {
8122       unsigned short *px = py;
8123       unsigned short *ex = py + ox * (nx - p2);
8124 
8125       for (; px <= ex; px += ox2) {
8126         unsigned short *p01 = px + ox1;
8127 
8128         if (w14)
8129           wenc14(*px, *p01, i00, *p01);
8130         else
8131           wenc16(*px, *p01, i00, *p01);
8132 
8133         *px = i00;
8134       }
8135     }
8136 
8137     //
8138     // Next level
8139     //
8140 
8141     p = p2;
8142     p2 <<= 1;
8143   }
8144 }
8145 
8146 //
8147 // 2D Wavelet decoding:
8148 //
8149 
wav2Decode(unsigned short * in,int nx,int ox,int ny,int oy,unsigned short mx)8150 static void wav2Decode(
8151     unsigned short *in,  // io: values are transformed in place
8152     int nx,              // i : x size
8153     int ox,              // i : x offset
8154     int ny,              // i : y size
8155     int oy,              // i : y offset
8156     unsigned short mx)   // i : maximum in[x][y] value
8157 {
8158   bool w14 = (mx < (1 << 14));
8159   int n = (nx > ny) ? ny : nx;
8160   int p = 1;
8161   int p2;
8162 
8163   //
8164   // Search max level
8165   //
8166 
8167   while (p <= n) p <<= 1;
8168 
8169   p >>= 1;
8170   p2 = p;
8171   p >>= 1;
8172 
8173   //
8174   // Hierarchical loop on smaller dimension n
8175   //
8176 
8177   while (p >= 1) {
8178     unsigned short *py = in;
8179     unsigned short *ey = in + oy * (ny - p2);
8180     int oy1 = oy * p;
8181     int oy2 = oy * p2;
8182     int ox1 = ox * p;
8183     int ox2 = ox * p2;
8184     unsigned short i00, i01, i10, i11;
8185 
8186     //
8187     // Y loop
8188     //
8189 
8190     for (; py <= ey; py += oy2) {
8191       unsigned short *px = py;
8192       unsigned short *ex = py + ox * (nx - p2);
8193 
8194       //
8195       // X loop
8196       //
8197 
8198       for (; px <= ex; px += ox2) {
8199         unsigned short *p01 = px + ox1;
8200         unsigned short *p10 = px + oy1;
8201         unsigned short *p11 = p10 + ox1;
8202 
8203         //
8204         // 2D wavelet decoding
8205         //
8206 
8207         if (w14) {
8208           wdec14(*px, *p10, i00, i10);
8209           wdec14(*p01, *p11, i01, i11);
8210           wdec14(i00, i01, *px, *p01);
8211           wdec14(i10, i11, *p10, *p11);
8212         } else {
8213           wdec16(*px, *p10, i00, i10);
8214           wdec16(*p01, *p11, i01, i11);
8215           wdec16(i00, i01, *px, *p01);
8216           wdec16(i10, i11, *p10, *p11);
8217         }
8218       }
8219 
8220       //
8221       // Decode (1D) odd column (still in Y loop)
8222       //
8223 
8224       if (nx & p) {
8225         unsigned short *p10 = px + oy1;
8226 
8227         if (w14)
8228           wdec14(*px, *p10, i00, *p10);
8229         else
8230           wdec16(*px, *p10, i00, *p10);
8231 
8232         *px = i00;
8233       }
8234     }
8235 
8236     //
8237     // Decode (1D) odd line (must loop in X)
8238     //
8239 
8240     if (ny & p) {
8241       unsigned short *px = py;
8242       unsigned short *ex = py + ox * (nx - p2);
8243 
8244       for (; px <= ex; px += ox2) {
8245         unsigned short *p01 = px + ox1;
8246 
8247         if (w14)
8248           wdec14(*px, *p01, i00, *p01);
8249         else
8250           wdec16(*px, *p01, i00, *p01);
8251 
8252         *px = i00;
8253       }
8254     }
8255 
8256     //
8257     // Next level
8258     //
8259 
8260     p2 = p;
8261     p >>= 1;
8262   }
8263 }
8264 
8265 //-----------------------------------------------------------------------------
8266 //
8267 //  16-bit Huffman compression and decompression.
8268 //
8269 //  The source code in this file is derived from the 8-bit
8270 //  Huffman compression and decompression routines written
8271 //  by Christian Rouet for his PIZ image file format.
8272 //
8273 //-----------------------------------------------------------------------------
8274 
8275 // Adds some modification for tinyexr.
8276 
8277 const int HUF_ENCBITS = 16;  // literal (value) bit length
8278 const int HUF_DECBITS = 14;  // decoding bit size (>= 8)
8279 
8280 const int HUF_ENCSIZE = (1 << HUF_ENCBITS) + 1;  // encoding table size
8281 const int HUF_DECSIZE = 1 << HUF_DECBITS;        // decoding table size
8282 const int HUF_DECMASK = HUF_DECSIZE - 1;
8283 
8284 struct HufDec {  // short code    long code
8285   //-------------------------------
8286   int len : 8;   // code length    0
8287   int lit : 24;  // lit      p size
8288   int *p;        // 0      lits
8289 };
8290 
hufLength(long long code)8291 inline long long hufLength(long long code) { return code & 63; }
8292 
hufCode(long long code)8293 inline long long hufCode(long long code) { return code >> 6; }
8294 
outputBits(int nBits,long long bits,long long & c,int & lc,char * & out)8295 inline void outputBits(int nBits, long long bits, long long &c, int &lc,
8296                        char *&out) {
8297   c <<= nBits;
8298   lc += nBits;
8299 
8300   c |= bits;
8301 
8302   while (lc >= 8) *out++ = static_cast<char>((c >> (lc -= 8)));
8303 }
8304 
getBits(int nBits,long long & c,int & lc,const char * & in)8305 inline long long getBits(int nBits, long long &c, int &lc, const char *&in) {
8306   while (lc < nBits) {
8307     c = (c << 8) | *(reinterpret_cast<const unsigned char *>(in++));
8308     lc += 8;
8309   }
8310 
8311   lc -= nBits;
8312   return (c >> lc) & ((1 << nBits) - 1);
8313 }
8314 
8315 //
8316 // ENCODING TABLE BUILDING & (UN)PACKING
8317 //
8318 
8319 //
8320 // Build a "canonical" Huffman code table:
8321 //  - for each (uncompressed) symbol, hcode contains the length
8322 //    of the corresponding code (in the compressed data)
8323 //  - canonical codes are computed and stored in hcode
8324 //  - the rules for constructing canonical codes are as follows:
8325 //    * shorter codes (if filled with zeroes to the right)
8326 //      have a numerically higher value than longer codes
8327 //    * for codes with the same length, numerical values
8328 //      increase with numerical symbol values
8329 //  - because the canonical code table can be constructed from
8330 //    symbol lengths alone, the code table can be transmitted
8331 //    without sending the actual code values
8332 //  - see http://www.compressconsult.com/huffman/
8333 //
8334 
hufCanonicalCodeTable(long long hcode[HUF_ENCSIZE])8335 static void hufCanonicalCodeTable(long long hcode[HUF_ENCSIZE]) {
8336   long long n[59];
8337 
8338   //
8339   // For each i from 0 through 58, count the
8340   // number of different codes of length i, and
8341   // store the count in n[i].
8342   //
8343 
8344   for (int i = 0; i <= 58; ++i) n[i] = 0;
8345 
8346   for (int i = 0; i < HUF_ENCSIZE; ++i) n[hcode[i]] += 1;
8347 
8348   //
8349   // For each i from 58 through 1, compute the
8350   // numerically lowest code with length i, and
8351   // store that code in n[i].
8352   //
8353 
8354   long long c = 0;
8355 
8356   for (int i = 58; i > 0; --i) {
8357     long long nc = ((c + n[i]) >> 1);
8358     n[i] = c;
8359     c = nc;
8360   }
8361 
8362   //
8363   // hcode[i] contains the length, l, of the
8364   // code for symbol i.  Assign the next available
8365   // code of length l to the symbol and store both
8366   // l and the code in hcode[i].
8367   //
8368 
8369   for (int i = 0; i < HUF_ENCSIZE; ++i) {
8370     int l = static_cast<int>(hcode[i]);
8371 
8372     if (l > 0) hcode[i] = l | (n[l]++ << 6);
8373   }
8374 }
8375 
8376 //
8377 // Compute Huffman codes (based on frq input) and store them in frq:
8378 //  - code structure is : [63:lsb - 6:msb] | [5-0: bit length];
8379 //  - max code length is 58 bits;
8380 //  - codes outside the range [im-iM] have a null length (unused values);
8381 //  - original frequencies are destroyed;
8382 //  - encoding tables are used by hufEncode() and hufBuildDecTable();
8383 //
8384 
8385 struct FHeapCompare {
operatorFHeapCompare8386   bool operator()(long long *a, long long *b) { return *a > *b; }
8387 };
8388 
hufBuildEncTable(long long * frq,int * im,int * iM)8389 static void hufBuildEncTable(
8390     long long *frq,  // io: input frequencies [HUF_ENCSIZE], output table
8391     int *im,         //  o: min frq index
8392     int *iM)         //  o: max frq index
8393 {
8394   //
8395   // This function assumes that when it is called, array frq
8396   // indicates the frequency of all possible symbols in the data
8397   // that are to be Huffman-encoded.  (frq[i] contains the number
8398   // of occurrences of symbol i in the data.)
8399   //
8400   // The loop below does three things:
8401   //
8402   // 1) Finds the minimum and maximum indices that point
8403   //    to non-zero entries in frq:
8404   //
8405   //     frq[im] != 0, and frq[i] == 0 for all i < im
8406   //     frq[iM] != 0, and frq[i] == 0 for all i > iM
8407   //
8408   // 2) Fills array fHeap with pointers to all non-zero
8409   //    entries in frq.
8410   //
8411   // 3) Initializes array hlink such that hlink[i] == i
8412   //    for all array entries.
8413   //
8414 
8415   std::vector<int> hlink(HUF_ENCSIZE);
8416   std::vector<long long *> fHeap(HUF_ENCSIZE);
8417 
8418   *im = 0;
8419 
8420   while (!frq[*im]) (*im)++;
8421 
8422   int nf = 0;
8423 
8424   for (int i = *im; i < HUF_ENCSIZE; i++) {
8425     hlink[i] = i;
8426 
8427     if (frq[i]) {
8428       fHeap[nf] = &frq[i];
8429       nf++;
8430       *iM = i;
8431     }
8432   }
8433 
8434   //
8435   // Add a pseudo-symbol, with a frequency count of 1, to frq;
8436   // adjust the fHeap and hlink array accordingly.  Function
8437   // hufEncode() uses the pseudo-symbol for run-length encoding.
8438   //
8439 
8440   (*iM)++;
8441   frq[*iM] = 1;
8442   fHeap[nf] = &frq[*iM];
8443   nf++;
8444 
8445   //
8446   // Build an array, scode, such that scode[i] contains the number
8447   // of bits assigned to symbol i.  Conceptually this is done by
8448   // constructing a tree whose leaves are the symbols with non-zero
8449   // frequency:
8450   //
8451   //     Make a heap that contains all symbols with a non-zero frequency,
8452   //     with the least frequent symbol on top.
8453   //
8454   //     Repeat until only one symbol is left on the heap:
8455   //
8456   //         Take the two least frequent symbols off the top of the heap.
8457   //         Create a new node that has first two nodes as children, and
8458   //         whose frequency is the sum of the frequencies of the first
8459   //         two nodes.  Put the new node back into the heap.
8460   //
8461   // The last node left on the heap is the root of the tree.  For each
8462   // leaf node, the distance between the root and the leaf is the length
8463   // of the code for the corresponding symbol.
8464   //
8465   // The loop below doesn't actually build the tree; instead we compute
8466   // the distances of the leaves from the root on the fly.  When a new
8467   // node is added to the heap, then that node's descendants are linked
8468   // into a single linear list that starts at the new node, and the code
8469   // lengths of the descendants (that is, their distance from the root
8470   // of the tree) are incremented by one.
8471   //
8472 
8473   std::make_heap(&fHeap[0], &fHeap[nf], FHeapCompare());
8474 
8475   std::vector<long long> scode(HUF_ENCSIZE);
8476   memset(scode.data(), 0, sizeof(long long) * HUF_ENCSIZE);
8477 
8478   while (nf > 1) {
8479     //
8480     // Find the indices, mm and m, of the two smallest non-zero frq
8481     // values in fHeap, add the smallest frq to the second-smallest
8482     // frq, and remove the smallest frq value from fHeap.
8483     //
8484 
8485     int mm = fHeap[0] - frq;
8486     std::pop_heap(&fHeap[0], &fHeap[nf], FHeapCompare());
8487     --nf;
8488 
8489     int m = fHeap[0] - frq;
8490     std::pop_heap(&fHeap[0], &fHeap[nf], FHeapCompare());
8491 
8492     frq[m] += frq[mm];
8493     std::push_heap(&fHeap[0], &fHeap[nf], FHeapCompare());
8494 
8495     //
8496     // The entries in scode are linked into lists with the
8497     // entries in hlink serving as "next" pointers and with
8498     // the end of a list marked by hlink[j] == j.
8499     //
8500     // Traverse the lists that start at scode[m] and scode[mm].
8501     // For each element visited, increment the length of the
8502     // corresponding code by one bit. (If we visit scode[j]
8503     // during the traversal, then the code for symbol j becomes
8504     // one bit longer.)
8505     //
8506     // Merge the lists that start at scode[m] and scode[mm]
8507     // into a single list that starts at scode[m].
8508     //
8509 
8510     //
8511     // Add a bit to all codes in the first list.
8512     //
8513 
8514     for (int j = m;; j = hlink[j]) {
8515       scode[j]++;
8516 
8517       TEXR_ASSERT(scode[j] <= 58);
8518 
8519       if (hlink[j] == j) {
8520         //
8521         // Merge the two lists.
8522         //
8523 
8524         hlink[j] = mm;
8525         break;
8526       }
8527     }
8528 
8529     //
8530     // Add a bit to all codes in the second list
8531     //
8532 
8533     for (int j = mm;; j = hlink[j]) {
8534       scode[j]++;
8535 
8536       TEXR_ASSERT(scode[j] <= 58);
8537 
8538       if (hlink[j] == j) break;
8539     }
8540   }
8541 
8542   //
8543   // Build a canonical Huffman code table, replacing the code
8544   // lengths in scode with (code, code length) pairs.  Copy the
8545   // code table from scode into frq.
8546   //
8547 
8548   hufCanonicalCodeTable(scode.data());
8549   memcpy(frq, scode.data(), sizeof(long long) * HUF_ENCSIZE);
8550 }
8551 
8552 //
8553 // Pack an encoding table:
8554 //  - only code lengths, not actual codes, are stored
8555 //  - runs of zeroes are compressed as follows:
8556 //
8557 //    unpacked    packed
8558 //    --------------------------------
8559 //    1 zero    0  (6 bits)
8560 //    2 zeroes    59
8561 //    3 zeroes    60
8562 //    4 zeroes    61
8563 //    5 zeroes    62
8564 //    n zeroes (6 or more)  63 n-6  (6 + 8 bits)
8565 //
8566 
8567 const int SHORT_ZEROCODE_RUN = 59;
8568 const int LONG_ZEROCODE_RUN = 63;
8569 const int SHORTEST_LONG_RUN = 2 + LONG_ZEROCODE_RUN - SHORT_ZEROCODE_RUN;
8570 const int LONGEST_LONG_RUN = 255 + SHORTEST_LONG_RUN;
8571 
hufPackEncTable(const long long * hcode,int im,int iM,char ** pcode)8572 static void hufPackEncTable(
8573     const long long *hcode,  // i : encoding table [HUF_ENCSIZE]
8574     int im,                  // i : min hcode index
8575     int iM,                  // i : max hcode index
8576     char **pcode)            //  o: ptr to packed table (updated)
8577 {
8578   char *p = *pcode;
8579   long long c = 0;
8580   int lc = 0;
8581 
8582   for (; im <= iM; im++) {
8583     int l = hufLength(hcode[im]);
8584 
8585     if (l == 0) {
8586       int zerun = 1;
8587 
8588       while ((im < iM) && (zerun < LONGEST_LONG_RUN)) {
8589         if (hufLength(hcode[im + 1]) > 0) break;
8590         im++;
8591         zerun++;
8592       }
8593 
8594       if (zerun >= 2) {
8595         if (zerun >= SHORTEST_LONG_RUN) {
8596           outputBits(6, LONG_ZEROCODE_RUN, c, lc, p);
8597           outputBits(8, zerun - SHORTEST_LONG_RUN, c, lc, p);
8598         } else {
8599           outputBits(6, SHORT_ZEROCODE_RUN + zerun - 2, c, lc, p);
8600         }
8601         continue;
8602       }
8603     }
8604 
8605     outputBits(6, l, c, lc, p);
8606   }
8607 
8608   if (lc > 0) *p++ = (unsigned char)(c << (8 - lc));
8609 
8610   *pcode = p;
8611 }
8612 
8613 //
8614 // Unpack an encoding table packed by hufPackEncTable():
8615 //
8616 
hufUnpackEncTable(const char ** pcode,int ni,int im,int iM,long long * hcode)8617 static bool hufUnpackEncTable(
8618     const char **pcode,  // io: ptr to packed table (updated)
8619     int ni,              // i : input size (in bytes)
8620     int im,              // i : min hcode index
8621     int iM,              // i : max hcode index
8622     long long *hcode)    //  o: encoding table [HUF_ENCSIZE]
8623 {
8624   memset(hcode, 0, sizeof(long long) * HUF_ENCSIZE);
8625 
8626   const char *p = *pcode;
8627   long long c = 0;
8628   int lc = 0;
8629 
8630   for (; im <= iM; im++) {
8631     if (p - *pcode >= ni) {
8632       return false;
8633     }
8634 
8635     long long l = hcode[im] = getBits(6, c, lc, p);  // code length
8636 
8637     if (l == (long long)LONG_ZEROCODE_RUN) {
8638       if (p - *pcode > ni) {
8639         return false;
8640       }
8641 
8642       int zerun = getBits(8, c, lc, p) + SHORTEST_LONG_RUN;
8643 
8644       if (im + zerun > iM + 1) {
8645         return false;
8646       }
8647 
8648       while (zerun--) hcode[im++] = 0;
8649 
8650       im--;
8651     } else if (l >= (long long)SHORT_ZEROCODE_RUN) {
8652       int zerun = l - SHORT_ZEROCODE_RUN + 2;
8653 
8654       if (im + zerun > iM + 1) {
8655         return false;
8656       }
8657 
8658       while (zerun--) hcode[im++] = 0;
8659 
8660       im--;
8661     }
8662   }
8663 
8664   *pcode = const_cast<char *>(p);
8665 
8666   hufCanonicalCodeTable(hcode);
8667 
8668   return true;
8669 }
8670 
8671 //
8672 // DECODING TABLE BUILDING
8673 //
8674 
8675 //
8676 // Clear a newly allocated decoding table so that it contains only zeroes.
8677 //
8678 
hufClearDecTable(HufDec * hdecod)8679 static void hufClearDecTable(HufDec *hdecod)  // io: (allocated by caller)
8680 //     decoding table [HUF_DECSIZE]
8681 {
8682   for (int i = 0; i < HUF_DECSIZE; i++) {
8683     hdecod[i].len = 0;
8684     hdecod[i].lit = 0;
8685     hdecod[i].p = NULL;
8686   }
8687   // memset(hdecod, 0, sizeof(HufDec) * HUF_DECSIZE);
8688 }
8689 
8690 //
8691 // Build a decoding hash table based on the encoding table hcode:
8692 //  - short codes (<= HUF_DECBITS) are resolved with a single table access;
8693 //  - long code entry allocations are not optimized, because long codes are
8694 //    unfrequent;
8695 //  - decoding tables are used by hufDecode();
8696 //
8697 
hufBuildDecTable(const long long * hcode,int im,int iM,HufDec * hdecod)8698 static bool hufBuildDecTable(const long long *hcode,  // i : encoding table
8699                              int im,                  // i : min index in hcode
8700                              int iM,                  // i : max index in hcode
8701                              HufDec *hdecod)  //  o: (allocated by caller)
8702 //     decoding table [HUF_DECSIZE]
8703 {
8704   //
8705   // Init hashtable & loop on all codes.
8706   // Assumes that hufClearDecTable(hdecod) has already been called.
8707   //
8708 
8709   for (; im <= iM; im++) {
8710     long long c = hufCode(hcode[im]);
8711     int l = hufLength(hcode[im]);
8712 
8713     if (c >> l) {
8714       //
8715       // Error: c is supposed to be an l-bit code,
8716       // but c contains a value that is greater
8717       // than the largest l-bit number.
8718       //
8719 
8720       // invalidTableEntry();
8721       return false;
8722     }
8723 
8724     if (l > HUF_DECBITS) {
8725       //
8726       // Long code: add a secondary entry
8727       //
8728 
8729       HufDec *pl = hdecod + (c >> (l - HUF_DECBITS));
8730 
8731       if (pl->len) {
8732         //
8733         // Error: a short code has already
8734         // been stored in table entry *pl.
8735         //
8736 
8737         // invalidTableEntry();
8738         return false;
8739       }
8740 
8741       pl->lit++;
8742 
8743       if (pl->p) {
8744         int *p = pl->p;
8745         pl->p = new int[pl->lit];
8746 
8747         for (int i = 0; i < pl->lit - 1; ++i) pl->p[i] = p[i];
8748 
8749         delete[] p;
8750       } else {
8751         pl->p = new int[1];
8752       }
8753 
8754       pl->p[pl->lit - 1] = im;
8755     } else if (l) {
8756       //
8757       // Short code: init all primary entries
8758       //
8759 
8760       HufDec *pl = hdecod + (c << (HUF_DECBITS - l));
8761 
8762       for (long long i = 1ULL << (HUF_DECBITS - l); i > 0; i--, pl++) {
8763         if (pl->len || pl->p) {
8764           //
8765           // Error: a short code or a long code has
8766           // already been stored in table entry *pl.
8767           //
8768 
8769           // invalidTableEntry();
8770           return false;
8771         }
8772 
8773         pl->len = l;
8774         pl->lit = im;
8775       }
8776     }
8777   }
8778 
8779   return true;
8780 }
8781 
8782 //
8783 // Free the long code entries of a decoding table built by hufBuildDecTable()
8784 //
8785 
hufFreeDecTable(HufDec * hdecod)8786 static void hufFreeDecTable(HufDec *hdecod)  // io: Decoding table
8787 {
8788   for (int i = 0; i < HUF_DECSIZE; i++) {
8789     if (hdecod[i].p) {
8790       delete[] hdecod[i].p;
8791       hdecod[i].p = 0;
8792     }
8793   }
8794 }
8795 
8796 //
8797 // ENCODING
8798 //
8799 
outputCode(long long code,long long & c,int & lc,char * & out)8800 inline void outputCode(long long code, long long &c, int &lc, char *&out) {
8801   outputBits(hufLength(code), hufCode(code), c, lc, out);
8802 }
8803 
sendCode(long long sCode,int runCount,long long runCode,long long & c,int & lc,char * & out)8804 inline void sendCode(long long sCode, int runCount, long long runCode,
8805                      long long &c, int &lc, char *&out) {
8806   //
8807   // Output a run of runCount instances of the symbol sCount.
8808   // Output the symbols explicitly, or if that is shorter, output
8809   // the sCode symbol once followed by a runCode symbol and runCount
8810   // expressed as an 8-bit number.
8811   //
8812 
8813   if (hufLength(sCode) + hufLength(runCode) + 8 < hufLength(sCode) * runCount) {
8814     outputCode(sCode, c, lc, out);
8815     outputCode(runCode, c, lc, out);
8816     outputBits(8, runCount, c, lc, out);
8817   } else {
8818     while (runCount-- >= 0) outputCode(sCode, c, lc, out);
8819   }
8820 }
8821 
8822 //
8823 // Encode (compress) ni values based on the Huffman encoding table hcode:
8824 //
8825 
hufEncode(const long long * hcode,const unsigned short * in,const int ni,int rlc,char * out)8826 static int hufEncode            // return: output size (in bits)
8827     (const long long *hcode,    // i : encoding table
8828      const unsigned short *in,  // i : uncompressed input buffer
8829      const int ni,              // i : input buffer size (in bytes)
8830      int rlc,                   // i : rl code
8831      char *out)                 //  o: compressed output buffer
8832 {
8833   char *outStart = out;
8834   long long c = 0;  // bits not yet written to out
8835   int lc = 0;       // number of valid bits in c (LSB)
8836   int s = in[0];
8837   int cs = 0;
8838 
8839   //
8840   // Loop on input values
8841   //
8842 
8843   for (int i = 1; i < ni; i++) {
8844     //
8845     // Count same values or send code
8846     //
8847 
8848     if (s == in[i] && cs < 255) {
8849       cs++;
8850     } else {
8851       sendCode(hcode[s], cs, hcode[rlc], c, lc, out);
8852       cs = 0;
8853     }
8854 
8855     s = in[i];
8856   }
8857 
8858   //
8859   // Send remaining code
8860   //
8861 
8862   sendCode(hcode[s], cs, hcode[rlc], c, lc, out);
8863 
8864   if (lc) *out = (c << (8 - lc)) & 0xff;
8865 
8866   return (out - outStart) * 8 + lc;
8867 }
8868 
8869 //
8870 // DECODING
8871 //
8872 
8873 //
8874 // In order to force the compiler to inline them,
8875 // getChar() and getCode() are implemented as macros
8876 // instead of "inline" functions.
8877 //
8878 
8879 #define getChar(c, lc, in)                   \
8880   {                                          \
8881     c = (c << 8) | *(unsigned char *)(in++); \
8882     lc += 8;                                 \
8883   }
8884 
8885 #if 0
8886 #define getCode(po, rlc, c, lc, in, out, ob, oe) \
8887   {                                              \
8888     if (po == rlc) {                             \
8889       if (lc < 8) getChar(c, lc, in);            \
8890                                                  \
8891       lc -= 8;                                   \
8892                                                  \
8893       unsigned char cs = (c >> lc);              \
8894                                                  \
8895       if (out + cs > oe) return false;           \
8896                                                  \
8897       /* TinyEXR issue 78 */                     \
8898       unsigned short s = out[-1];                \
8899                                                  \
8900       while (cs-- > 0) *out++ = s;               \
8901     } else if (out < oe) {                       \
8902       *out++ = po;                               \
8903     } else {                                     \
8904       return false;                              \
8905     }                                            \
8906   }
8907 #else
getCode(int po,int rlc,long long & c,int & lc,const char * & in,const char * in_end,unsigned short * & out,const unsigned short * ob,const unsigned short * oe)8908 static bool getCode(int po, int rlc, long long &c, int &lc, const char *&in,
8909                     const char *in_end, unsigned short *&out,
8910                     const unsigned short *ob, const unsigned short *oe) {
8911   (void)ob;
8912   if (po == rlc) {
8913     if (lc < 8) {
8914       /* TinyEXR issue 78 */
8915       if ((in + 1) >= in_end) {
8916         return false;
8917       }
8918 
8919       getChar(c, lc, in);
8920     }
8921 
8922     lc -= 8;
8923 
8924     unsigned char cs = (c >> lc);
8925 
8926     if (out + cs > oe) return false;
8927 
8928     // Bounds check for safety
8929     // Issue 100.
8930     if ((out - 1) < ob) return false;
8931     unsigned short s = out[-1];
8932 
8933     while (cs-- > 0) *out++ = s;
8934   } else if (out < oe) {
8935     *out++ = po;
8936   } else {
8937     return false;
8938   }
8939   return true;
8940 }
8941 #endif
8942 
8943 //
8944 // Decode (uncompress) ni bits based on encoding & decoding tables:
8945 //
8946 
hufDecode(const long long * hcode,const HufDec * hdecod,const char * in,int ni,int rlc,int no,unsigned short * out)8947 static bool hufDecode(const long long *hcode,  // i : encoding table
8948                       const HufDec *hdecod,    // i : decoding table
8949                       const char *in,          // i : compressed input buffer
8950                       int ni,                  // i : input size (in bits)
8951                       int rlc,                 // i : run-length code
8952                       int no,  // i : expected output size (in bytes)
8953                       unsigned short *out)  //  o: uncompressed output buffer
8954 {
8955   long long c = 0;
8956   int lc = 0;
8957   unsigned short *outb = out;          // begin
8958   unsigned short *oe = out + no;       // end
8959   const char *ie = in + (ni + 7) / 8;  // input byte size
8960 
8961   //
8962   // Loop on input bytes
8963   //
8964 
8965   while (in < ie) {
8966     getChar(c, lc, in);
8967 
8968     //
8969     // Access decoding table
8970     //
8971 
8972     while (lc >= HUF_DECBITS) {
8973       const HufDec pl = hdecod[(c >> (lc - HUF_DECBITS)) & HUF_DECMASK];
8974 
8975       if (pl.len) {
8976         //
8977         // Get short code
8978         //
8979 
8980         lc -= pl.len;
8981         // std::cout << "lit = " << pl.lit << std::endl;
8982         // std::cout << "rlc = " << rlc << std::endl;
8983         // std::cout << "c = " << c << std::endl;
8984         // std::cout << "lc = " << lc << std::endl;
8985         // std::cout << "in = " << in << std::endl;
8986         // std::cout << "out = " << out << std::endl;
8987         // std::cout << "oe = " << oe << std::endl;
8988         if (!getCode(pl.lit, rlc, c, lc, in, ie, out, outb, oe)) {
8989           return false;
8990         }
8991       } else {
8992         if (!pl.p) {
8993           return false;
8994         }
8995         // invalidCode(); // wrong code
8996 
8997         //
8998         // Search long code
8999         //
9000 
9001         int j;
9002 
9003         for (j = 0; j < pl.lit; j++) {
9004           int l = hufLength(hcode[pl.p[j]]);
9005 
9006           while (lc < l && in < ie)  // get more bits
9007             getChar(c, lc, in);
9008 
9009           if (lc >= l) {
9010             if (hufCode(hcode[pl.p[j]]) ==
9011                 ((c >> (lc - l)) & (((long long)(1) << l) - 1))) {
9012               //
9013               // Found : get long code
9014               //
9015 
9016               lc -= l;
9017               if (!getCode(pl.p[j], rlc, c, lc, in, ie, out, outb, oe)) {
9018                 return false;
9019               }
9020               break;
9021             }
9022           }
9023         }
9024 
9025         if (j == pl.lit) {
9026           return false;
9027           // invalidCode(); // Not found
9028         }
9029       }
9030     }
9031   }
9032 
9033   //
9034   // Get remaining (short) codes
9035   //
9036 
9037   int i = (8 - ni) & 7;
9038   c >>= i;
9039   lc -= i;
9040 
9041   while (lc > 0) {
9042     const HufDec pl = hdecod[(c << (HUF_DECBITS - lc)) & HUF_DECMASK];
9043 
9044     if (pl.len) {
9045       lc -= pl.len;
9046       if (!getCode(pl.lit, rlc, c, lc, in, ie, out, outb, oe)) {
9047         return false;
9048       }
9049     } else {
9050       return false;
9051       // invalidCode(); // wrong (long) code
9052     }
9053   }
9054 
9055   if (out - outb != no) {
9056     return false;
9057   }
9058   // notEnoughData ();
9059 
9060   return true;
9061 }
9062 
countFrequencies(std::vector<long long> & freq,const unsigned short data[],int n)9063 static void countFrequencies(std::vector<long long> &freq,
9064                              const unsigned short data[/*n*/], int n) {
9065   for (int i = 0; i < HUF_ENCSIZE; ++i) freq[i] = 0;
9066 
9067   for (int i = 0; i < n; ++i) ++freq[data[i]];
9068 }
9069 
writeUInt(char buf[4],unsigned int i)9070 static void writeUInt(char buf[4], unsigned int i) {
9071   unsigned char *b = (unsigned char *)buf;
9072 
9073   b[0] = i;
9074   b[1] = i >> 8;
9075   b[2] = i >> 16;
9076   b[3] = i >> 24;
9077 }
9078 
readUInt(const char buf[4])9079 static unsigned int readUInt(const char buf[4]) {
9080   const unsigned char *b = (const unsigned char *)buf;
9081 
9082   return (b[0] & 0x000000ff) | ((b[1] << 8) & 0x0000ff00) |
9083          ((b[2] << 16) & 0x00ff0000) | ((b[3] << 24) & 0xff000000);
9084 }
9085 
9086 //
9087 // EXTERNAL INTERFACE
9088 //
9089 
hufCompress(const unsigned short raw[],int nRaw,char compressed[])9090 static int hufCompress(const unsigned short raw[], int nRaw,
9091                        char compressed[]) {
9092   if (nRaw == 0) return 0;
9093 
9094   std::vector<long long> freq(HUF_ENCSIZE);
9095 
9096   countFrequencies(freq, raw, nRaw);
9097 
9098   int im = 0;
9099   int iM = 0;
9100   hufBuildEncTable(freq.data(), &im, &iM);
9101 
9102   char *tableStart = compressed + 20;
9103   char *tableEnd = tableStart;
9104   hufPackEncTable(freq.data(), im, iM, &tableEnd);
9105   int tableLength = tableEnd - tableStart;
9106 
9107   char *dataStart = tableEnd;
9108   int nBits = hufEncode(freq.data(), raw, nRaw, iM, dataStart);
9109   int data_length = (nBits + 7) / 8;
9110 
9111   writeUInt(compressed, im);
9112   writeUInt(compressed + 4, iM);
9113   writeUInt(compressed + 8, tableLength);
9114   writeUInt(compressed + 12, nBits);
9115   writeUInt(compressed + 16, 0);  // room for future extensions
9116 
9117   return dataStart + data_length - compressed;
9118 }
9119 
hufUncompress(const char compressed[],int nCompressed,std::vector<unsigned short> * raw)9120 static bool hufUncompress(const char compressed[], int nCompressed,
9121                           std::vector<unsigned short> *raw) {
9122   if (nCompressed == 0) {
9123     if (raw->size() != 0) return false;
9124 
9125     return false;
9126   }
9127 
9128   int im = readUInt(compressed);
9129   int iM = readUInt(compressed + 4);
9130   // int tableLength = readUInt (compressed + 8);
9131   int nBits = readUInt(compressed + 12);
9132 
9133   if (im < 0 || im >= HUF_ENCSIZE || iM < 0 || iM >= HUF_ENCSIZE) return false;
9134 
9135   const char *ptr = compressed + 20;
9136 
9137   //
9138   // Fast decoder needs at least 2x64-bits of compressed data, and
9139   // needs to be run-able on this platform. Otherwise, fall back
9140   // to the original decoder
9141   //
9142 
9143   // if (FastHufDecoder::enabled() && nBits > 128)
9144   //{
9145   //    FastHufDecoder fhd (ptr, nCompressed - (ptr - compressed), im, iM, iM);
9146   //    fhd.decode ((unsigned char*)ptr, nBits, raw, nRaw);
9147   //}
9148   // else
9149   {
9150     std::vector<long long> freq(HUF_ENCSIZE);
9151     std::vector<HufDec> hdec(HUF_DECSIZE);
9152 
9153     hufClearDecTable(&hdec.at(0));
9154 
9155     hufUnpackEncTable(&ptr, nCompressed - (ptr - compressed), im, iM,
9156                       &freq.at(0));
9157 
9158     {
9159       if (nBits > 8 * (nCompressed - (ptr - compressed))) {
9160         return false;
9161       }
9162 
9163       hufBuildDecTable(&freq.at(0), im, iM, &hdec.at(0));
9164       hufDecode(&freq.at(0), &hdec.at(0), ptr, nBits, iM, raw->size(),
9165                 raw->data());
9166     }
9167     // catch (...)
9168     //{
9169     //    hufFreeDecTable (hdec);
9170     //    throw;
9171     //}
9172 
9173     hufFreeDecTable(&hdec.at(0));
9174   }
9175 
9176   return true;
9177 }
9178 
9179 //
9180 // Functions to compress the range of values in the pixel data
9181 //
9182 
9183 const int USHORT_RANGE = (1 << 16);
9184 const int BITMAP_SIZE = (USHORT_RANGE >> 3);
9185 
bitmapFromData(const unsigned short data[],int nData,unsigned char bitmap[BITMAP_SIZE],unsigned short & minNonZero,unsigned short & maxNonZero)9186 static void bitmapFromData(const unsigned short data[/*nData*/], int nData,
9187                            unsigned char bitmap[BITMAP_SIZE],
9188                            unsigned short &minNonZero,
9189                            unsigned short &maxNonZero) {
9190   for (int i = 0; i < BITMAP_SIZE; ++i) bitmap[i] = 0;
9191 
9192   for (int i = 0; i < nData; ++i) bitmap[data[i] >> 3] |= (1 << (data[i] & 7));
9193 
9194   bitmap[0] &= ~1;  // zero is not explicitly stored in
9195                     // the bitmap; we assume that the
9196                     // data always contain zeroes
9197   minNonZero = BITMAP_SIZE - 1;
9198   maxNonZero = 0;
9199 
9200   for (int i = 0; i < BITMAP_SIZE; ++i) {
9201     if (bitmap[i]) {
9202       if (minNonZero > i) minNonZero = i;
9203       if (maxNonZero < i) maxNonZero = i;
9204     }
9205   }
9206 }
9207 
forwardLutFromBitmap(const unsigned char bitmap[BITMAP_SIZE],unsigned short lut[USHORT_RANGE])9208 static unsigned short forwardLutFromBitmap(
9209     const unsigned char bitmap[BITMAP_SIZE], unsigned short lut[USHORT_RANGE]) {
9210   int k = 0;
9211 
9212   for (int i = 0; i < USHORT_RANGE; ++i) {
9213     if ((i == 0) || (bitmap[i >> 3] & (1 << (i & 7))))
9214       lut[i] = k++;
9215     else
9216       lut[i] = 0;
9217   }
9218 
9219   return k - 1;  // maximum value stored in lut[],
9220 }  // i.e. number of ones in bitmap minus 1
9221 
reverseLutFromBitmap(const unsigned char bitmap[BITMAP_SIZE],unsigned short lut[USHORT_RANGE])9222 static unsigned short reverseLutFromBitmap(
9223     const unsigned char bitmap[BITMAP_SIZE], unsigned short lut[USHORT_RANGE]) {
9224   int k = 0;
9225 
9226   for (int i = 0; i < USHORT_RANGE; ++i) {
9227     if ((i == 0) || (bitmap[i >> 3] & (1 << (i & 7)))) lut[k++] = i;
9228   }
9229 
9230   int n = k - 1;
9231 
9232   while (k < USHORT_RANGE) lut[k++] = 0;
9233 
9234   return n;  // maximum k where lut[k] is non-zero,
9235 }  // i.e. number of ones in bitmap minus 1
9236 
applyLut(const unsigned short lut[USHORT_RANGE],unsigned short data[],int nData)9237 static void applyLut(const unsigned short lut[USHORT_RANGE],
9238                      unsigned short data[/*nData*/], int nData) {
9239   for (int i = 0; i < nData; ++i) data[i] = lut[data[i]];
9240 }
9241 
9242 #ifdef __clang__
9243 #pragma clang diagnostic pop
9244 #endif  // __clang__
9245 
9246 #ifdef _MSC_VER
9247 #pragma warning(pop)
9248 #endif
9249 
CompressPiz(unsigned char * outPtr,unsigned int * outSize,const unsigned char * inPtr,size_t inSize,const std::vector<ChannelInfo> & channelInfo,int data_width,int num_lines)9250 static bool CompressPiz(unsigned char *outPtr, unsigned int *outSize,
9251                         const unsigned char *inPtr, size_t inSize,
9252                         const std::vector<ChannelInfo> &channelInfo,
9253                         int data_width, int num_lines) {
9254   std::vector<unsigned char> bitmap(BITMAP_SIZE);
9255   unsigned short minNonZero;
9256   unsigned short maxNonZero;
9257 
9258 #if !MINIZ_LITTLE_ENDIAN
9259   // @todo { PIZ compression on BigEndian architecture. }
9260   TEXR_ASSERT(0);
9261   return false;
9262 #endif
9263 
9264   // Assume `inSize` is multiple of 2 or 4.
9265   std::vector<unsigned short> tmpBuffer(inSize / sizeof(unsigned short));
9266 
9267   std::vector<PIZChannelData> channelData(channelInfo.size());
9268   unsigned short *tmpBufferEnd = &tmpBuffer.at(0);
9269 
9270   for (size_t c = 0; c < channelData.size(); c++) {
9271     PIZChannelData &cd = channelData[c];
9272 
9273     cd.start = tmpBufferEnd;
9274     cd.end = cd.start;
9275 
9276     cd.nx = data_width;
9277     cd.ny = num_lines;
9278     // cd.ys = c.channel().ySampling;
9279 
9280     size_t pixelSize = sizeof(int);  // UINT and FLOAT
9281     if (channelInfo[c].pixel_type == TINYEXR_PIXELTYPE_HALF) {
9282       pixelSize = sizeof(short);
9283     }
9284 
9285     cd.size = static_cast<int>(pixelSize / sizeof(short));
9286 
9287     tmpBufferEnd += cd.nx * cd.ny * cd.size;
9288   }
9289 
9290   const unsigned char *ptr = inPtr;
9291   for (int y = 0; y < num_lines; ++y) {
9292     for (size_t i = 0; i < channelData.size(); ++i) {
9293       PIZChannelData &cd = channelData[i];
9294 
9295       // if (modp (y, cd.ys) != 0)
9296       //    continue;
9297 
9298       size_t n = static_cast<size_t>(cd.nx * cd.size);
9299       memcpy(cd.end, ptr, n * sizeof(unsigned short));
9300       ptr += n * sizeof(unsigned short);
9301       cd.end += n;
9302     }
9303   }
9304 
9305   bitmapFromData(&tmpBuffer.at(0), static_cast<int>(tmpBuffer.size()),
9306                  bitmap.data(), minNonZero, maxNonZero);
9307 
9308   std::vector<unsigned short> lut(USHORT_RANGE);
9309   unsigned short maxValue = forwardLutFromBitmap(bitmap.data(), lut.data());
9310   applyLut(lut.data(), &tmpBuffer.at(0), static_cast<int>(tmpBuffer.size()));
9311 
9312   //
9313   // Store range compression info in _outBuffer
9314   //
9315 
9316   char *buf = reinterpret_cast<char *>(outPtr);
9317 
9318   memcpy(buf, &minNonZero, sizeof(unsigned short));
9319   buf += sizeof(unsigned short);
9320   memcpy(buf, &maxNonZero, sizeof(unsigned short));
9321   buf += sizeof(unsigned short);
9322 
9323   if (minNonZero <= maxNonZero) {
9324     memcpy(buf, reinterpret_cast<char *>(&bitmap[0] + minNonZero),
9325            maxNonZero - minNonZero + 1);
9326     buf += maxNonZero - minNonZero + 1;
9327   }
9328 
9329   //
9330   // Apply wavelet encoding
9331   //
9332 
9333   for (size_t i = 0; i < channelData.size(); ++i) {
9334     PIZChannelData &cd = channelData[i];
9335 
9336     for (int j = 0; j < cd.size; ++j) {
9337       wav2Encode(cd.start + j, cd.nx, cd.size, cd.ny, cd.nx * cd.size,
9338                  maxValue);
9339     }
9340   }
9341 
9342   //
9343   // Apply Huffman encoding; append the result to _outBuffer
9344   //
9345 
9346   // length header(4byte), then huff data. Initialize length header with zero,
9347   // then later fill it by `length`.
9348   char *lengthPtr = buf;
9349   int zero = 0;
9350   memcpy(buf, &zero, sizeof(int));
9351   buf += sizeof(int);
9352 
9353   int length =
9354       hufCompress(&tmpBuffer.at(0), static_cast<int>(tmpBuffer.size()), buf);
9355   memcpy(lengthPtr, &length, sizeof(int));
9356 
9357   (*outSize) = static_cast<unsigned int>(
9358       (reinterpret_cast<unsigned char *>(buf) - outPtr) +
9359       static_cast<unsigned int>(length));
9360 
9361   // Use uncompressed data when compressed data is larger than uncompressed.
9362   // (Issue 40)
9363   if ((*outSize) >= inSize) {
9364     (*outSize) = static_cast<unsigned int>(inSize);
9365     memcpy(outPtr, inPtr, inSize);
9366   }
9367   return true;
9368 }
9369 
DecompressPiz(unsigned char * outPtr,const unsigned char * inPtr,size_t tmpBufSize,size_t inLen,int num_channels,const EXRChannelInfo * channels,int data_width,int num_lines)9370 static bool DecompressPiz(unsigned char *outPtr, const unsigned char *inPtr,
9371                           size_t tmpBufSize, size_t inLen, int num_channels,
9372                           const EXRChannelInfo *channels, int data_width,
9373                           int num_lines) {
9374   if (inLen == tmpBufSize) {
9375     // Data is not compressed(Issue 40).
9376     memcpy(outPtr, inPtr, inLen);
9377     return true;
9378   }
9379 
9380   std::vector<unsigned char> bitmap(BITMAP_SIZE);
9381   unsigned short minNonZero;
9382   unsigned short maxNonZero;
9383 
9384 #if !MINIZ_LITTLE_ENDIAN
9385   // @todo { PIZ compression on BigEndian architecture. }
9386   TEXR_ASSERT(0);
9387   return false;
9388 #endif
9389 
9390   memset(bitmap.data(), 0, BITMAP_SIZE);
9391 
9392   const unsigned char *ptr = inPtr;
9393   // minNonZero = *(reinterpret_cast<const unsigned short *>(ptr));
9394   tinyexr::cpy2(&minNonZero, reinterpret_cast<const unsigned short *>(ptr));
9395   // maxNonZero = *(reinterpret_cast<const unsigned short *>(ptr + 2));
9396   tinyexr::cpy2(&maxNonZero, reinterpret_cast<const unsigned short *>(ptr + 2));
9397   ptr += 4;
9398 
9399   if (maxNonZero >= BITMAP_SIZE) {
9400     return false;
9401   }
9402 
9403   if (minNonZero <= maxNonZero) {
9404     memcpy(reinterpret_cast<char *>(&bitmap[0] + minNonZero), ptr,
9405            maxNonZero - minNonZero + 1);
9406     ptr += maxNonZero - minNonZero + 1;
9407   }
9408 
9409   std::vector<unsigned short> lut(USHORT_RANGE);
9410   memset(lut.data(), 0, sizeof(unsigned short) * USHORT_RANGE);
9411   unsigned short maxValue = reverseLutFromBitmap(bitmap.data(), lut.data());
9412 
9413   //
9414   // Huffman decoding
9415   //
9416 
9417   int length;
9418 
9419   // length = *(reinterpret_cast<const int *>(ptr));
9420   tinyexr::cpy4(&length, reinterpret_cast<const int *>(ptr));
9421   ptr += sizeof(int);
9422 
9423   if (size_t((ptr - inPtr) + length) > inLen) {
9424     return false;
9425   }
9426 
9427   std::vector<unsigned short> tmpBuffer(tmpBufSize);
9428   hufUncompress(reinterpret_cast<const char *>(ptr), length, &tmpBuffer);
9429 
9430   //
9431   // Wavelet decoding
9432   //
9433 
9434   std::vector<PIZChannelData> channelData(static_cast<size_t>(num_channels));
9435 
9436   unsigned short *tmpBufferEnd = &tmpBuffer.at(0);
9437 
9438   for (size_t i = 0; i < static_cast<size_t>(num_channels); ++i) {
9439     const EXRChannelInfo &chan = channels[i];
9440 
9441     size_t pixelSize = sizeof(int);  // UINT and FLOAT
9442     if (chan.pixel_type == TINYEXR_PIXELTYPE_HALF) {
9443       pixelSize = sizeof(short);
9444     }
9445 
9446     channelData[i].start = tmpBufferEnd;
9447     channelData[i].end = channelData[i].start;
9448     channelData[i].nx = data_width;
9449     channelData[i].ny = num_lines;
9450     // channelData[i].ys = 1;
9451     channelData[i].size = static_cast<int>(pixelSize / sizeof(short));
9452 
9453     tmpBufferEnd += channelData[i].nx * channelData[i].ny * channelData[i].size;
9454   }
9455 
9456   for (size_t i = 0; i < channelData.size(); ++i) {
9457     PIZChannelData &cd = channelData[i];
9458 
9459     for (int j = 0; j < cd.size; ++j) {
9460       wav2Decode(cd.start + j, cd.nx, cd.size, cd.ny, cd.nx * cd.size,
9461                  maxValue);
9462     }
9463   }
9464 
9465   //
9466   // Expand the pixel data to their original range
9467   //
9468 
9469   applyLut(lut.data(), &tmpBuffer.at(0), static_cast<int>(tmpBufSize));
9470 
9471   for (int y = 0; y < num_lines; y++) {
9472     for (size_t i = 0; i < channelData.size(); ++i) {
9473       PIZChannelData &cd = channelData[i];
9474 
9475       // if (modp (y, cd.ys) != 0)
9476       //    continue;
9477 
9478       size_t n = static_cast<size_t>(cd.nx * cd.size);
9479       memcpy(outPtr, cd.end, static_cast<size_t>(n * sizeof(unsigned short)));
9480       outPtr += n * sizeof(unsigned short);
9481       cd.end += n;
9482     }
9483   }
9484 
9485   return true;
9486 }
9487 #endif  // TINYEXR_USE_PIZ
9488 
9489 #if TINYEXR_USE_ZFP
9490 struct ZFPCompressionParam {
9491   double rate;
9492   int precision;
9493   double tolerance;
9494   int type;  // TINYEXR_ZFP_COMPRESSIONTYPE_*
9495 
ZFPCompressionParamZFPCompressionParam9496   ZFPCompressionParam() {
9497     type = TINYEXR_ZFP_COMPRESSIONTYPE_RATE;
9498     rate = 2.0;
9499     precision = 0;
9500     tolerance = 0.0f;
9501   }
9502 };
9503 
FindZFPCompressionParam(ZFPCompressionParam * param,const EXRAttribute * attributes,int num_attributes)9504 bool FindZFPCompressionParam(ZFPCompressionParam *param,
9505                              const EXRAttribute *attributes,
9506                              int num_attributes) {
9507   bool foundType = false;
9508 
9509   for (int i = 0; i < num_attributes; i++) {
9510     if ((strcmp(attributes[i].name, "zfpCompressionType") == 0) &&
9511         (attributes[i].size == 1)) {
9512       param->type = static_cast<int>(attributes[i].value[0]);
9513 
9514       foundType = true;
9515     }
9516   }
9517 
9518   if (!foundType) {
9519     return false;
9520   }
9521 
9522   if (param->type == TINYEXR_ZFP_COMPRESSIONTYPE_RATE) {
9523     for (int i = 0; i < num_attributes; i++) {
9524       if ((strcmp(attributes[i].name, "zfpCompressionRate") == 0) &&
9525           (attributes[i].size == 8)) {
9526         param->rate = *(reinterpret_cast<double *>(attributes[i].value));
9527         return true;
9528       }
9529     }
9530   } else if (param->type == TINYEXR_ZFP_COMPRESSIONTYPE_PRECISION) {
9531     for (int i = 0; i < num_attributes; i++) {
9532       if ((strcmp(attributes[i].name, "zfpCompressionPrecision") == 0) &&
9533           (attributes[i].size == 4)) {
9534         param->rate = *(reinterpret_cast<int *>(attributes[i].value));
9535         return true;
9536       }
9537     }
9538   } else if (param->type == TINYEXR_ZFP_COMPRESSIONTYPE_ACCURACY) {
9539     for (int i = 0; i < num_attributes; i++) {
9540       if ((strcmp(attributes[i].name, "zfpCompressionTolerance") == 0) &&
9541           (attributes[i].size == 8)) {
9542         param->tolerance = *(reinterpret_cast<double *>(attributes[i].value));
9543         return true;
9544       }
9545     }
9546   } else {
9547     TEXR_ASSERT(0);
9548   }
9549 
9550   return false;
9551 }
9552 
9553 // Assume pixel format is FLOAT for all channels.
DecompressZfp(float * dst,int dst_width,int dst_num_lines,int num_channels,const unsigned char * src,unsigned long src_size,const ZFPCompressionParam & param)9554 static bool DecompressZfp(float *dst, int dst_width, int dst_num_lines,
9555                           int num_channels, const unsigned char *src,
9556                           unsigned long src_size,
9557                           const ZFPCompressionParam &param) {
9558   size_t uncompressed_size = dst_width * dst_num_lines * num_channels;
9559 
9560   if (uncompressed_size == src_size) {
9561     // Data is not compressed(Issue 40).
9562     memcpy(dst, src, src_size);
9563   }
9564 
9565   zfp_stream *zfp = NULL;
9566   zfp_field *field = NULL;
9567 
9568   TEXR_ASSERT((dst_width % 4) == 0);
9569   TEXR_ASSERT((dst_num_lines % 4) == 0);
9570 
9571   if ((dst_width & 3U) || (dst_num_lines & 3U)) {
9572     return false;
9573   }
9574 
9575   field =
9576       zfp_field_2d(reinterpret_cast<void *>(const_cast<unsigned char *>(src)),
9577                    zfp_type_float, dst_width, dst_num_lines * num_channels);
9578   zfp = zfp_stream_open(NULL);
9579 
9580   if (param.type == TINYEXR_ZFP_COMPRESSIONTYPE_RATE) {
9581     zfp_stream_set_rate(zfp, param.rate, zfp_type_float, /* dimention */ 2,
9582                         /* write random access */ 0);
9583   } else if (param.type == TINYEXR_ZFP_COMPRESSIONTYPE_PRECISION) {
9584     zfp_stream_set_precision(zfp, param.precision, zfp_type_float);
9585   } else if (param.type == TINYEXR_ZFP_COMPRESSIONTYPE_ACCURACY) {
9586     zfp_stream_set_accuracy(zfp, param.tolerance, zfp_type_float);
9587   } else {
9588     TEXR_ASSERT(0);
9589   }
9590 
9591   size_t buf_size = zfp_stream_maximum_size(zfp, field);
9592   std::vector<unsigned char> buf(buf_size);
9593   memcpy(&buf.at(0), src, src_size);
9594 
9595   bitstream *stream = stream_open(&buf.at(0), buf_size);
9596   zfp_stream_set_bit_stream(zfp, stream);
9597   zfp_stream_rewind(zfp);
9598 
9599   size_t image_size = dst_width * dst_num_lines;
9600 
9601   for (int c = 0; c < num_channels; c++) {
9602     // decompress 4x4 pixel block.
9603     for (int y = 0; y < dst_num_lines; y += 4) {
9604       for (int x = 0; x < dst_width; x += 4) {
9605         float fblock[16];
9606         zfp_decode_block_float_2(zfp, fblock);
9607         for (int j = 0; j < 4; j++) {
9608           for (int i = 0; i < 4; i++) {
9609             dst[c * image_size + ((y + j) * dst_width + (x + i))] =
9610                 fblock[j * 4 + i];
9611           }
9612         }
9613       }
9614     }
9615   }
9616 
9617   zfp_field_free(field);
9618   zfp_stream_close(zfp);
9619   stream_close(stream);
9620 
9621   return true;
9622 }
9623 
9624 // Assume pixel format is FLOAT for all channels.
CompressZfp(std::vector<unsigned char> * outBuf,unsigned int * outSize,const float * inPtr,int width,int num_lines,int num_channels,const ZFPCompressionParam & param)9625 bool CompressZfp(std::vector<unsigned char> *outBuf, unsigned int *outSize,
9626                  const float *inPtr, int width, int num_lines, int num_channels,
9627                  const ZFPCompressionParam &param) {
9628   zfp_stream *zfp = NULL;
9629   zfp_field *field = NULL;
9630 
9631   TEXR_ASSERT((width % 4) == 0);
9632   TEXR_ASSERT((num_lines % 4) == 0);
9633 
9634   if ((width & 3U) || (num_lines & 3U)) {
9635     return false;
9636   }
9637 
9638   // create input array.
9639   field = zfp_field_2d(reinterpret_cast<void *>(const_cast<float *>(inPtr)),
9640                        zfp_type_float, width, num_lines * num_channels);
9641 
9642   zfp = zfp_stream_open(NULL);
9643 
9644   if (param.type == TINYEXR_ZFP_COMPRESSIONTYPE_RATE) {
9645     zfp_stream_set_rate(zfp, param.rate, zfp_type_float, 2, 0);
9646   } else if (param.type == TINYEXR_ZFP_COMPRESSIONTYPE_PRECISION) {
9647     zfp_stream_set_precision(zfp, param.precision, zfp_type_float);
9648   } else if (param.type == TINYEXR_ZFP_COMPRESSIONTYPE_ACCURACY) {
9649     zfp_stream_set_accuracy(zfp, param.tolerance, zfp_type_float);
9650   } else {
9651     TEXR_ASSERT(0);
9652   }
9653 
9654   size_t buf_size = zfp_stream_maximum_size(zfp, field);
9655 
9656   outBuf->resize(buf_size);
9657 
9658   bitstream *stream = stream_open(&outBuf->at(0), buf_size);
9659   zfp_stream_set_bit_stream(zfp, stream);
9660   zfp_field_free(field);
9661 
9662   size_t image_size = width * num_lines;
9663 
9664   for (int c = 0; c < num_channels; c++) {
9665     // compress 4x4 pixel block.
9666     for (int y = 0; y < num_lines; y += 4) {
9667       for (int x = 0; x < width; x += 4) {
9668         float fblock[16];
9669         for (int j = 0; j < 4; j++) {
9670           for (int i = 0; i < 4; i++) {
9671             fblock[j * 4 + i] =
9672                 inPtr[c * image_size + ((y + j) * width + (x + i))];
9673           }
9674         }
9675         zfp_encode_block_float_2(zfp, fblock);
9676       }
9677     }
9678   }
9679 
9680   zfp_stream_flush(zfp);
9681   (*outSize) = zfp_stream_compressed_size(zfp);
9682 
9683   zfp_stream_close(zfp);
9684 
9685   return true;
9686 }
9687 
9688 #endif
9689 
9690 //
9691 // -----------------------------------------------------------------
9692 //
9693 
9694 // TODO(syoyo): Refactor function arguments.
DecodePixelData(unsigned char ** out_images,const int * requested_pixel_types,const unsigned char * data_ptr,size_t data_len,int compression_type,int line_order,int width,int height,int x_stride,int y,int line_no,int num_lines,size_t pixel_data_size,size_t num_attributes,const EXRAttribute * attributes,size_t num_channels,const EXRChannelInfo * channels,const std::vector<size_t> & channel_offset_list)9695 static bool DecodePixelData(/* out */ unsigned char **out_images,
9696                             const int *requested_pixel_types,
9697                             const unsigned char *data_ptr, size_t data_len,
9698                             int compression_type, int line_order, int width,
9699                             int height, int x_stride, int y, int line_no,
9700                             int num_lines, size_t pixel_data_size,
9701                             size_t num_attributes,
9702                             const EXRAttribute *attributes, size_t num_channels,
9703                             const EXRChannelInfo *channels,
9704                             const std::vector<size_t> &channel_offset_list) {
9705   if (compression_type == TINYEXR_COMPRESSIONTYPE_PIZ) {  // PIZ
9706 #if TINYEXR_USE_PIZ
9707     if ((width == 0) || (num_lines == 0) || (pixel_data_size == 0)) {
9708       // Invalid input #90
9709       return false;
9710     }
9711 
9712     // Allocate original data size.
9713     std::vector<unsigned char> outBuf(static_cast<size_t>(
9714         static_cast<size_t>(width * num_lines) * pixel_data_size));
9715     size_t tmpBufLen = outBuf.size();
9716 
9717     bool ret = tinyexr::DecompressPiz(
9718         reinterpret_cast<unsigned char *>(&outBuf.at(0)), data_ptr, tmpBufLen,
9719         data_len, static_cast<int>(num_channels), channels, width, num_lines);
9720 
9721     if (!ret) {
9722       return false;
9723     }
9724 
9725     // For PIZ_COMPRESSION:
9726     //   pixel sample data for channel 0 for scanline 0
9727     //   pixel sample data for channel 1 for scanline 0
9728     //   pixel sample data for channel ... for scanline 0
9729     //   pixel sample data for channel n for scanline 0
9730     //   pixel sample data for channel 0 for scanline 1
9731     //   pixel sample data for channel 1 for scanline 1
9732     //   pixel sample data for channel ... for scanline 1
9733     //   pixel sample data for channel n for scanline 1
9734     //   ...
9735     for (size_t c = 0; c < static_cast<size_t>(num_channels); c++) {
9736       if (channels[c].pixel_type == TINYEXR_PIXELTYPE_HALF) {
9737         for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) {
9738           const unsigned short *line_ptr = reinterpret_cast<unsigned short *>(
9739               &outBuf.at(v * pixel_data_size * static_cast<size_t>(width) +
9740                          channel_offset_list[c] * static_cast<size_t>(width)));
9741           for (size_t u = 0; u < static_cast<size_t>(width); u++) {
9742             FP16 hf;
9743 
9744             // hf.u = line_ptr[u];
9745             // use `cpy` to avoid unaligned memory access when compiler's
9746             // optimization is on.
9747             tinyexr::cpy2(&(hf.u), line_ptr + u);
9748 
9749             tinyexr::swap2(reinterpret_cast<unsigned short *>(&hf.u));
9750 
9751             if (requested_pixel_types[c] == TINYEXR_PIXELTYPE_HALF) {
9752               unsigned short *image =
9753                   reinterpret_cast<unsigned short **>(out_images)[c];
9754               if (line_order == 0) {
9755                 image += (static_cast<size_t>(line_no) + v) *
9756                              static_cast<size_t>(x_stride) +
9757                          u;
9758               } else {
9759                 image += static_cast<size_t>(
9760                              (height - 1 - (line_no + static_cast<int>(v)))) *
9761                              static_cast<size_t>(x_stride) +
9762                          u;
9763               }
9764               *image = hf.u;
9765             } else {  // HALF -> FLOAT
9766               FP32 f32 = half_to_float(hf);
9767               float *image = reinterpret_cast<float **>(out_images)[c];
9768               size_t offset = 0;
9769               if (line_order == 0) {
9770                 offset = (static_cast<size_t>(line_no) + v) *
9771                              static_cast<size_t>(x_stride) +
9772                          u;
9773               } else {
9774                 offset = static_cast<size_t>(
9775                              (height - 1 - (line_no + static_cast<int>(v)))) *
9776                              static_cast<size_t>(x_stride) +
9777                          u;
9778               }
9779               image += offset;
9780               *image = f32.f;
9781             }
9782           }
9783         }
9784       } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_UINT) {
9785         TEXR_ASSERT(requested_pixel_types[c] == TINYEXR_PIXELTYPE_UINT);
9786 
9787         for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) {
9788           const unsigned int *line_ptr = reinterpret_cast<unsigned int *>(
9789               &outBuf.at(v * pixel_data_size * static_cast<size_t>(width) +
9790                          channel_offset_list[c] * static_cast<size_t>(width)));
9791           for (size_t u = 0; u < static_cast<size_t>(width); u++) {
9792             unsigned int val;
9793             // val = line_ptr[u];
9794             tinyexr::cpy4(&val, line_ptr + u);
9795 
9796             tinyexr::swap4(&val);
9797 
9798             unsigned int *image =
9799                 reinterpret_cast<unsigned int **>(out_images)[c];
9800             if (line_order == 0) {
9801               image += (static_cast<size_t>(line_no) + v) *
9802                            static_cast<size_t>(x_stride) +
9803                        u;
9804             } else {
9805               image += static_cast<size_t>(
9806                            (height - 1 - (line_no + static_cast<int>(v)))) *
9807                            static_cast<size_t>(x_stride) +
9808                        u;
9809             }
9810             *image = val;
9811           }
9812         }
9813       } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_FLOAT) {
9814         TEXR_ASSERT(requested_pixel_types[c] == TINYEXR_PIXELTYPE_FLOAT);
9815         for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) {
9816           const float *line_ptr = reinterpret_cast<float *>(&outBuf.at(
9817               v * pixel_data_size * static_cast<size_t>(x_stride) +
9818               channel_offset_list[c] * static_cast<size_t>(x_stride)));
9819           for (size_t u = 0; u < static_cast<size_t>(width); u++) {
9820             float val;
9821             // val = line_ptr[u];
9822             tinyexr::cpy4(&val, line_ptr + u);
9823 
9824             tinyexr::swap4(reinterpret_cast<unsigned int *>(&val));
9825 
9826             float *image = reinterpret_cast<float **>(out_images)[c];
9827             if (line_order == 0) {
9828               image += (static_cast<size_t>(line_no) + v) *
9829                            static_cast<size_t>(x_stride) +
9830                        u;
9831             } else {
9832               image += static_cast<size_t>(
9833                            (height - 1 - (line_no + static_cast<int>(v)))) *
9834                            static_cast<size_t>(x_stride) +
9835                        u;
9836             }
9837             *image = val;
9838           }
9839         }
9840       } else {
9841         TEXR_ASSERT(0);
9842       }
9843     }
9844 #else
9845     TEXR_ASSERT(0 && "PIZ is enabled in this build");
9846     return false;
9847 #endif
9848 
9849   } else if (compression_type == TINYEXR_COMPRESSIONTYPE_ZIPS ||
9850              compression_type == TINYEXR_COMPRESSIONTYPE_ZIP) {
9851     // Allocate original data size.
9852     std::vector<unsigned char> outBuf(static_cast<size_t>(width) *
9853                                       static_cast<size_t>(num_lines) *
9854                                       pixel_data_size);
9855 
9856     unsigned long dstLen = static_cast<unsigned long>(outBuf.size());
9857     TEXR_ASSERT(dstLen > 0);
9858     if (!tinyexr::DecompressZip(
9859             reinterpret_cast<unsigned char *>(&outBuf.at(0)), &dstLen, data_ptr,
9860             static_cast<unsigned long>(data_len))) {
9861       return false;
9862     }
9863 
9864     // For ZIP_COMPRESSION:
9865     //   pixel sample data for channel 0 for scanline 0
9866     //   pixel sample data for channel 1 for scanline 0
9867     //   pixel sample data for channel ... for scanline 0
9868     //   pixel sample data for channel n for scanline 0
9869     //   pixel sample data for channel 0 for scanline 1
9870     //   pixel sample data for channel 1 for scanline 1
9871     //   pixel sample data for channel ... for scanline 1
9872     //   pixel sample data for channel n for scanline 1
9873     //   ...
9874     for (size_t c = 0; c < static_cast<size_t>(num_channels); c++) {
9875       if (channels[c].pixel_type == TINYEXR_PIXELTYPE_HALF) {
9876         for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) {
9877           const unsigned short *line_ptr = reinterpret_cast<unsigned short *>(
9878               &outBuf.at(v * static_cast<size_t>(pixel_data_size) *
9879                              static_cast<size_t>(width) +
9880                          channel_offset_list[c] * static_cast<size_t>(width)));
9881           for (size_t u = 0; u < static_cast<size_t>(width); u++) {
9882             tinyexr::FP16 hf;
9883 
9884             // hf.u = line_ptr[u];
9885             tinyexr::cpy2(&(hf.u), line_ptr + u);
9886 
9887             tinyexr::swap2(reinterpret_cast<unsigned short *>(&hf.u));
9888 
9889             if (requested_pixel_types[c] == TINYEXR_PIXELTYPE_HALF) {
9890               unsigned short *image =
9891                   reinterpret_cast<unsigned short **>(out_images)[c];
9892               if (line_order == 0) {
9893                 image += (static_cast<size_t>(line_no) + v) *
9894                              static_cast<size_t>(x_stride) +
9895                          u;
9896               } else {
9897                 image += (static_cast<size_t>(height) - 1U -
9898                           (static_cast<size_t>(line_no) + v)) *
9899                              static_cast<size_t>(x_stride) +
9900                          u;
9901               }
9902               *image = hf.u;
9903             } else {  // HALF -> FLOAT
9904               tinyexr::FP32 f32 = half_to_float(hf);
9905               float *image = reinterpret_cast<float **>(out_images)[c];
9906               size_t offset = 0;
9907               if (line_order == 0) {
9908                 offset = (static_cast<size_t>(line_no) + v) *
9909                              static_cast<size_t>(x_stride) +
9910                          u;
9911               } else {
9912                 offset = (static_cast<size_t>(height) - 1U -
9913                           (static_cast<size_t>(line_no) + v)) *
9914                              static_cast<size_t>(x_stride) +
9915                          u;
9916               }
9917               image += offset;
9918 
9919               *image = f32.f;
9920             }
9921           }
9922         }
9923       } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_UINT) {
9924         TEXR_ASSERT(requested_pixel_types[c] == TINYEXR_PIXELTYPE_UINT);
9925 
9926         for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) {
9927           const unsigned int *line_ptr = reinterpret_cast<unsigned int *>(
9928               &outBuf.at(v * pixel_data_size * static_cast<size_t>(width) +
9929                          channel_offset_list[c] * static_cast<size_t>(width)));
9930           for (size_t u = 0; u < static_cast<size_t>(width); u++) {
9931             unsigned int val;
9932             // val = line_ptr[u];
9933             tinyexr::cpy4(&val, line_ptr + u);
9934 
9935             tinyexr::swap4(&val);
9936 
9937             unsigned int *image =
9938                 reinterpret_cast<unsigned int **>(out_images)[c];
9939             if (line_order == 0) {
9940               image += (static_cast<size_t>(line_no) + v) *
9941                            static_cast<size_t>(x_stride) +
9942                        u;
9943             } else {
9944               image += (static_cast<size_t>(height) - 1U -
9945                         (static_cast<size_t>(line_no) + v)) *
9946                            static_cast<size_t>(x_stride) +
9947                        u;
9948             }
9949             *image = val;
9950           }
9951         }
9952       } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_FLOAT) {
9953         TEXR_ASSERT(requested_pixel_types[c] == TINYEXR_PIXELTYPE_FLOAT);
9954         for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) {
9955           const float *line_ptr = reinterpret_cast<float *>(
9956               &outBuf.at(v * pixel_data_size * static_cast<size_t>(width) +
9957                          channel_offset_list[c] * static_cast<size_t>(width)));
9958           for (size_t u = 0; u < static_cast<size_t>(width); u++) {
9959             float val;
9960             // val = line_ptr[u];
9961             tinyexr::cpy4(&val, line_ptr + u);
9962 
9963             tinyexr::swap4(reinterpret_cast<unsigned int *>(&val));
9964 
9965             float *image = reinterpret_cast<float **>(out_images)[c];
9966             if (line_order == 0) {
9967               image += (static_cast<size_t>(line_no) + v) *
9968                            static_cast<size_t>(x_stride) +
9969                        u;
9970             } else {
9971               image += (static_cast<size_t>(height) - 1U -
9972                         (static_cast<size_t>(line_no) + v)) *
9973                            static_cast<size_t>(x_stride) +
9974                        u;
9975             }
9976             *image = val;
9977           }
9978         }
9979       } else {
9980         TEXR_ASSERT(0);
9981         return false;
9982       }
9983     }
9984   } else if (compression_type == TINYEXR_COMPRESSIONTYPE_RLE) {
9985     // Allocate original data size.
9986     std::vector<unsigned char> outBuf(static_cast<size_t>(width) *
9987                                       static_cast<size_t>(num_lines) *
9988                                       pixel_data_size);
9989 
9990     unsigned long dstLen = static_cast<unsigned long>(outBuf.size());
9991     if (dstLen == 0) {
9992       return false;
9993     }
9994 
9995     if (!tinyexr::DecompressRle(
9996             reinterpret_cast<unsigned char *>(&outBuf.at(0)), dstLen, data_ptr,
9997             static_cast<unsigned long>(data_len))) {
9998       return false;
9999     }
10000 
10001     // For RLE_COMPRESSION:
10002     //   pixel sample data for channel 0 for scanline 0
10003     //   pixel sample data for channel 1 for scanline 0
10004     //   pixel sample data for channel ... for scanline 0
10005     //   pixel sample data for channel n for scanline 0
10006     //   pixel sample data for channel 0 for scanline 1
10007     //   pixel sample data for channel 1 for scanline 1
10008     //   pixel sample data for channel ... for scanline 1
10009     //   pixel sample data for channel n for scanline 1
10010     //   ...
10011     for (size_t c = 0; c < static_cast<size_t>(num_channels); c++) {
10012       if (channels[c].pixel_type == TINYEXR_PIXELTYPE_HALF) {
10013         for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) {
10014           const unsigned short *line_ptr = reinterpret_cast<unsigned short *>(
10015               &outBuf.at(v * static_cast<size_t>(pixel_data_size) *
10016                              static_cast<size_t>(width) +
10017                          channel_offset_list[c] * static_cast<size_t>(width)));
10018           for (size_t u = 0; u < static_cast<size_t>(width); u++) {
10019             tinyexr::FP16 hf;
10020 
10021             // hf.u = line_ptr[u];
10022             tinyexr::cpy2(&(hf.u), line_ptr + u);
10023 
10024             tinyexr::swap2(reinterpret_cast<unsigned short *>(&hf.u));
10025 
10026             if (requested_pixel_types[c] == TINYEXR_PIXELTYPE_HALF) {
10027               unsigned short *image =
10028                   reinterpret_cast<unsigned short **>(out_images)[c];
10029               if (line_order == 0) {
10030                 image += (static_cast<size_t>(line_no) + v) *
10031                              static_cast<size_t>(x_stride) +
10032                          u;
10033               } else {
10034                 image += (static_cast<size_t>(height) - 1U -
10035                           (static_cast<size_t>(line_no) + v)) *
10036                              static_cast<size_t>(x_stride) +
10037                          u;
10038               }
10039               *image = hf.u;
10040             } else {  // HALF -> FLOAT
10041               tinyexr::FP32 f32 = half_to_float(hf);
10042               float *image = reinterpret_cast<float **>(out_images)[c];
10043               if (line_order == 0) {
10044                 image += (static_cast<size_t>(line_no) + v) *
10045                              static_cast<size_t>(x_stride) +
10046                          u;
10047               } else {
10048                 image += (static_cast<size_t>(height) - 1U -
10049                           (static_cast<size_t>(line_no) + v)) *
10050                              static_cast<size_t>(x_stride) +
10051                          u;
10052               }
10053               *image = f32.f;
10054             }
10055           }
10056         }
10057       } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_UINT) {
10058         TEXR_ASSERT(requested_pixel_types[c] == TINYEXR_PIXELTYPE_UINT);
10059 
10060         for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) {
10061           const unsigned int *line_ptr = reinterpret_cast<unsigned int *>(
10062               &outBuf.at(v * pixel_data_size * static_cast<size_t>(width) +
10063                          channel_offset_list[c] * static_cast<size_t>(width)));
10064           for (size_t u = 0; u < static_cast<size_t>(width); u++) {
10065             unsigned int val;
10066             // val = line_ptr[u];
10067             tinyexr::cpy4(&val, line_ptr + u);
10068 
10069             tinyexr::swap4(&val);
10070 
10071             unsigned int *image =
10072                 reinterpret_cast<unsigned int **>(out_images)[c];
10073             if (line_order == 0) {
10074               image += (static_cast<size_t>(line_no) + v) *
10075                            static_cast<size_t>(x_stride) +
10076                        u;
10077             } else {
10078               image += (static_cast<size_t>(height) - 1U -
10079                         (static_cast<size_t>(line_no) + v)) *
10080                            static_cast<size_t>(x_stride) +
10081                        u;
10082             }
10083             *image = val;
10084           }
10085         }
10086       } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_FLOAT) {
10087         TEXR_ASSERT(requested_pixel_types[c] == TINYEXR_PIXELTYPE_FLOAT);
10088         for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) {
10089           const float *line_ptr = reinterpret_cast<float *>(
10090               &outBuf.at(v * pixel_data_size * static_cast<size_t>(width) +
10091                          channel_offset_list[c] * static_cast<size_t>(width)));
10092           for (size_t u = 0; u < static_cast<size_t>(width); u++) {
10093             float val;
10094             // val = line_ptr[u];
10095             tinyexr::cpy4(&val, line_ptr + u);
10096 
10097             tinyexr::swap4(reinterpret_cast<unsigned int *>(&val));
10098 
10099             float *image = reinterpret_cast<float **>(out_images)[c];
10100             if (line_order == 0) {
10101               image += (static_cast<size_t>(line_no) + v) *
10102                            static_cast<size_t>(x_stride) +
10103                        u;
10104             } else {
10105               image += (static_cast<size_t>(height) - 1U -
10106                         (static_cast<size_t>(line_no) + v)) *
10107                            static_cast<size_t>(x_stride) +
10108                        u;
10109             }
10110             *image = val;
10111           }
10112         }
10113       } else {
10114         TEXR_ASSERT(0);
10115         return false;
10116       }
10117     }
10118   } else if (compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) {
10119 #if TINYEXR_USE_ZFP
10120     tinyexr::ZFPCompressionParam zfp_compression_param;
10121     if (!FindZFPCompressionParam(&zfp_compression_param, attributes,
10122                                  num_attributes)) {
10123       TEXR_ASSERT(0);
10124       return false;
10125     }
10126 
10127     // Allocate original data size.
10128     std::vector<unsigned char> outBuf(static_cast<size_t>(width) *
10129                                       static_cast<size_t>(num_lines) *
10130                                       pixel_data_size);
10131 
10132     unsigned long dstLen = outBuf.size();
10133     TEXR_ASSERT(dstLen > 0);
10134     tinyexr::DecompressZfp(reinterpret_cast<float *>(&outBuf.at(0)), width,
10135                            num_lines, num_channels, data_ptr,
10136                            static_cast<unsigned long>(data_len),
10137                            zfp_compression_param);
10138 
10139     // For ZFP_COMPRESSION:
10140     //   pixel sample data for channel 0 for scanline 0
10141     //   pixel sample data for channel 1 for scanline 0
10142     //   pixel sample data for channel ... for scanline 0
10143     //   pixel sample data for channel n for scanline 0
10144     //   pixel sample data for channel 0 for scanline 1
10145     //   pixel sample data for channel 1 for scanline 1
10146     //   pixel sample data for channel ... for scanline 1
10147     //   pixel sample data for channel n for scanline 1
10148     //   ...
10149     for (size_t c = 0; c < static_cast<size_t>(num_channels); c++) {
10150       TEXR_ASSERT(channels[c].pixel_type == TINYEXR_PIXELTYPE_FLOAT);
10151       if (channels[c].pixel_type == TINYEXR_PIXELTYPE_FLOAT) {
10152         TEXR_ASSERT(requested_pixel_types[c] == TINYEXR_PIXELTYPE_FLOAT);
10153         for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) {
10154           const float *line_ptr = reinterpret_cast<float *>(
10155               &outBuf.at(v * pixel_data_size * static_cast<size_t>(width) +
10156                          channel_offset_list[c] * static_cast<size_t>(width)));
10157           for (size_t u = 0; u < static_cast<size_t>(width); u++) {
10158             float val;
10159             tinyexr::cpy4(&val, line_ptr + u);
10160 
10161             tinyexr::swap4(reinterpret_cast<unsigned int *>(&val));
10162 
10163             float *image = reinterpret_cast<float **>(out_images)[c];
10164             if (line_order == 0) {
10165               image += (static_cast<size_t>(line_no) + v) *
10166                            static_cast<size_t>(x_stride) +
10167                        u;
10168             } else {
10169               image += (static_cast<size_t>(height) - 1U -
10170                         (static_cast<size_t>(line_no) + v)) *
10171                            static_cast<size_t>(x_stride) +
10172                        u;
10173             }
10174             *image = val;
10175           }
10176         }
10177       } else {
10178         TEXR_ASSERT(0);
10179         return false;
10180       }
10181     }
10182 #else
10183     (void)attributes;
10184     (void)num_attributes;
10185     (void)num_channels;
10186     TEXR_ASSERT(0);
10187     return false;
10188 #endif
10189   } else if (compression_type == TINYEXR_COMPRESSIONTYPE_NONE) {
10190     for (size_t c = 0; c < num_channels; c++) {
10191       for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) {
10192         if (channels[c].pixel_type == TINYEXR_PIXELTYPE_HALF) {
10193           const unsigned short *line_ptr =
10194               reinterpret_cast<const unsigned short *>(
10195                   data_ptr + v * pixel_data_size * size_t(width) +
10196                   channel_offset_list[c] * static_cast<size_t>(width));
10197 
10198           if (requested_pixel_types[c] == TINYEXR_PIXELTYPE_HALF) {
10199             unsigned short *outLine =
10200                 reinterpret_cast<unsigned short *>(out_images[c]);
10201             if (line_order == 0) {
10202               outLine += (size_t(y) + v) * size_t(x_stride);
10203             } else {
10204               outLine +=
10205                   (size_t(height) - 1 - (size_t(y) + v)) * size_t(x_stride);
10206             }
10207 
10208             for (int u = 0; u < width; u++) {
10209               tinyexr::FP16 hf;
10210 
10211               // hf.u = line_ptr[u];
10212               tinyexr::cpy2(&(hf.u), line_ptr + u);
10213 
10214               tinyexr::swap2(reinterpret_cast<unsigned short *>(&hf.u));
10215 
10216               outLine[u] = hf.u;
10217             }
10218           } else if (requested_pixel_types[c] == TINYEXR_PIXELTYPE_FLOAT) {
10219             float *outLine = reinterpret_cast<float *>(out_images[c]);
10220             if (line_order == 0) {
10221               outLine += (size_t(y) + v) * size_t(x_stride);
10222             } else {
10223               outLine +=
10224                   (size_t(height) - 1 - (size_t(y) + v)) * size_t(x_stride);
10225             }
10226 
10227             if (reinterpret_cast<const unsigned char *>(line_ptr + width) >
10228                 (data_ptr + data_len)) {
10229               // Insufficient data size
10230               return false;
10231             }
10232 
10233             for (int u = 0; u < width; u++) {
10234               tinyexr::FP16 hf;
10235 
10236               // address may not be aliged. use byte-wise copy for safety.#76
10237               // hf.u = line_ptr[u];
10238               tinyexr::cpy2(&(hf.u), line_ptr + u);
10239 
10240               tinyexr::swap2(reinterpret_cast<unsigned short *>(&hf.u));
10241 
10242               tinyexr::FP32 f32 = half_to_float(hf);
10243 
10244               outLine[u] = f32.f;
10245             }
10246           } else {
10247             TEXR_ASSERT(0);
10248             return false;
10249           }
10250         } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_FLOAT) {
10251           const float *line_ptr = reinterpret_cast<const float *>(
10252               data_ptr + v * pixel_data_size * size_t(width) +
10253               channel_offset_list[c] * static_cast<size_t>(width));
10254 
10255           float *outLine = reinterpret_cast<float *>(out_images[c]);
10256           if (line_order == 0) {
10257             outLine += (size_t(y) + v) * size_t(x_stride);
10258           } else {
10259             outLine +=
10260                 (size_t(height) - 1 - (size_t(y) + v)) * size_t(x_stride);
10261           }
10262 
10263           if (reinterpret_cast<const unsigned char *>(line_ptr + width) >
10264               (data_ptr + data_len)) {
10265             // Insufficient data size
10266             return false;
10267           }
10268 
10269           for (int u = 0; u < width; u++) {
10270             float val;
10271             tinyexr::cpy4(&val, line_ptr + u);
10272 
10273             tinyexr::swap4(reinterpret_cast<unsigned int *>(&val));
10274 
10275             outLine[u] = val;
10276           }
10277         } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_UINT) {
10278           const unsigned int *line_ptr = reinterpret_cast<const unsigned int *>(
10279               data_ptr + v * pixel_data_size * size_t(width) +
10280               channel_offset_list[c] * static_cast<size_t>(width));
10281 
10282           unsigned int *outLine =
10283               reinterpret_cast<unsigned int *>(out_images[c]);
10284           if (line_order == 0) {
10285             outLine += (size_t(y) + v) * size_t(x_stride);
10286           } else {
10287             outLine +=
10288                 (size_t(height) - 1 - (size_t(y) + v)) * size_t(x_stride);
10289           }
10290 
10291           for (int u = 0; u < width; u++) {
10292             if (reinterpret_cast<const unsigned char *>(line_ptr + u) >=
10293                 (data_ptr + data_len)) {
10294               // Corrupsed data?
10295               return false;
10296             }
10297 
10298             unsigned int val;
10299             tinyexr::cpy4(&val, line_ptr + u);
10300 
10301             tinyexr::swap4(reinterpret_cast<unsigned int *>(&val));
10302 
10303             outLine[u] = val;
10304           }
10305         }
10306       }
10307     }
10308   }
10309 
10310   return true;
10311 }
10312 
DecodeTiledPixelData(unsigned char ** out_images,int * width,int * height,const int * requested_pixel_types,const unsigned char * data_ptr,size_t data_len,int compression_type,int line_order,int data_width,int data_height,int tile_offset_x,int tile_offset_y,int tile_size_x,int tile_size_y,size_t pixel_data_size,size_t num_attributes,const EXRAttribute * attributes,size_t num_channels,const EXRChannelInfo * channels,const std::vector<size_t> & channel_offset_list)10313 static bool DecodeTiledPixelData(
10314     unsigned char **out_images, int *width, int *height,
10315     const int *requested_pixel_types, const unsigned char *data_ptr,
10316     size_t data_len, int compression_type, int line_order, int data_width,
10317     int data_height, int tile_offset_x, int tile_offset_y, int tile_size_x,
10318     int tile_size_y, size_t pixel_data_size, size_t num_attributes,
10319     const EXRAttribute *attributes, size_t num_channels,
10320     const EXRChannelInfo *channels,
10321     const std::vector<size_t> &channel_offset_list) {
10322   TEXR_ASSERT(tile_offset_x * tile_size_x < data_width);
10323   TEXR_ASSERT(tile_offset_y * tile_size_y < data_height);
10324 
10325   // Compute actual image size in a tile.
10326   if ((tile_offset_x + 1) * tile_size_x >= data_width) {
10327     (*width) = data_width - (tile_offset_x * tile_size_x);
10328   } else {
10329     (*width) = tile_size_x;
10330   }
10331 
10332   if ((tile_offset_y + 1) * tile_size_y >= data_height) {
10333     (*height) = data_height - (tile_offset_y * tile_size_y);
10334   } else {
10335     (*height) = tile_size_y;
10336   }
10337 
10338   // Image size = tile size.
10339   return DecodePixelData(out_images, requested_pixel_types, data_ptr, data_len,
10340                          compression_type, line_order, (*width), tile_size_y,
10341                          /* stride */ tile_size_x, /* y */ 0, /* line_no */ 0,
10342                          (*height), pixel_data_size, num_attributes, attributes,
10343                          num_channels, channels, channel_offset_list);
10344 }
10345 
ComputeChannelLayout(std::vector<size_t> * channel_offset_list,int * pixel_data_size,size_t * channel_offset,int num_channels,const EXRChannelInfo * channels)10346 static bool ComputeChannelLayout(std::vector<size_t> *channel_offset_list,
10347                                  int *pixel_data_size, size_t *channel_offset,
10348                                  int num_channels,
10349                                  const EXRChannelInfo *channels) {
10350   channel_offset_list->resize(static_cast<size_t>(num_channels));
10351 
10352   (*pixel_data_size) = 0;
10353   (*channel_offset) = 0;
10354 
10355   for (size_t c = 0; c < static_cast<size_t>(num_channels); c++) {
10356     (*channel_offset_list)[c] = (*channel_offset);
10357     if (channels[c].pixel_type == TINYEXR_PIXELTYPE_HALF) {
10358       (*pixel_data_size) += sizeof(unsigned short);
10359       (*channel_offset) += sizeof(unsigned short);
10360     } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_FLOAT) {
10361       (*pixel_data_size) += sizeof(float);
10362       (*channel_offset) += sizeof(float);
10363     } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_UINT) {
10364       (*pixel_data_size) += sizeof(unsigned int);
10365       (*channel_offset) += sizeof(unsigned int);
10366     } else {
10367       // ???
10368       return false;
10369     }
10370   }
10371   return true;
10372 }
10373 
AllocateImage(int num_channels,const EXRChannelInfo * channels,const int * requested_pixel_types,int data_width,int data_height)10374 static unsigned char **AllocateImage(int num_channels,
10375                                      const EXRChannelInfo *channels,
10376                                      const int *requested_pixel_types,
10377                                      int data_width, int data_height) {
10378   unsigned char **images =
10379       reinterpret_cast<unsigned char **>(static_cast<float **>(
10380           malloc(sizeof(float *) * static_cast<size_t>(num_channels))));
10381 
10382   for (size_t c = 0; c < static_cast<size_t>(num_channels); c++) {
10383     size_t data_len =
10384         static_cast<size_t>(data_width) * static_cast<size_t>(data_height);
10385     if (channels[c].pixel_type == TINYEXR_PIXELTYPE_HALF) {
10386       // pixel_data_size += sizeof(unsigned short);
10387       // channel_offset += sizeof(unsigned short);
10388       // Alloc internal image for half type.
10389       if (requested_pixel_types[c] == TINYEXR_PIXELTYPE_HALF) {
10390         images[c] =
10391             reinterpret_cast<unsigned char *>(static_cast<unsigned short *>(
10392                 malloc(sizeof(unsigned short) * data_len)));
10393       } else if (requested_pixel_types[c] == TINYEXR_PIXELTYPE_FLOAT) {
10394         images[c] = reinterpret_cast<unsigned char *>(
10395             static_cast<float *>(malloc(sizeof(float) * data_len)));
10396       } else {
10397         TEXR_ASSERT(0);
10398       }
10399     } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_FLOAT) {
10400       // pixel_data_size += sizeof(float);
10401       // channel_offset += sizeof(float);
10402       images[c] = reinterpret_cast<unsigned char *>(
10403           static_cast<float *>(malloc(sizeof(float) * data_len)));
10404     } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_UINT) {
10405       // pixel_data_size += sizeof(unsigned int);
10406       // channel_offset += sizeof(unsigned int);
10407       images[c] = reinterpret_cast<unsigned char *>(
10408           static_cast<unsigned int *>(malloc(sizeof(unsigned int) * data_len)));
10409     } else {
10410       TEXR_ASSERT(0);
10411     }
10412   }
10413 
10414   return images;
10415 }
10416 
ParseEXRHeader(HeaderInfo * info,bool * empty_header,const EXRVersion * version,std::string * err,const unsigned char * buf,size_t size)10417 static int ParseEXRHeader(HeaderInfo *info, bool *empty_header,
10418                           const EXRVersion *version, std::string *err,
10419                           const unsigned char *buf, size_t size) {
10420   const char *marker = reinterpret_cast<const char *>(&buf[0]);
10421 
10422   if (empty_header) {
10423     (*empty_header) = false;
10424   }
10425 
10426   if (version->multipart) {
10427     if (size > 0 && marker[0] == '\0') {
10428       // End of header list.
10429       if (empty_header) {
10430         (*empty_header) = true;
10431       }
10432       return TINYEXR_SUCCESS;
10433     }
10434   }
10435 
10436   // According to the spec, the header of every OpenEXR file must contain at
10437   // least the following attributes:
10438   //
10439   // channels chlist
10440   // compression compression
10441   // dataWindow box2i
10442   // displayWindow box2i
10443   // lineOrder lineOrder
10444   // pixelAspectRatio float
10445   // screenWindowCenter v2f
10446   // screenWindowWidth float
10447   bool has_channels = false;
10448   bool has_compression = false;
10449   bool has_data_window = false;
10450   bool has_display_window = false;
10451   bool has_line_order = false;
10452   bool has_pixel_aspect_ratio = false;
10453   bool has_screen_window_center = false;
10454   bool has_screen_window_width = false;
10455 
10456   info->data_window[0] = 0;
10457   info->data_window[1] = 0;
10458   info->data_window[2] = 0;
10459   info->data_window[3] = 0;
10460   info->line_order = 0;  // @fixme
10461   info->display_window[0] = 0;
10462   info->display_window[1] = 0;
10463   info->display_window[2] = 0;
10464   info->display_window[3] = 0;
10465   info->screen_window_center[0] = 0.0f;
10466   info->screen_window_center[1] = 0.0f;
10467   info->screen_window_width = -1.0f;
10468   info->pixel_aspect_ratio = -1.0f;
10469 
10470   info->tile_size_x = -1;
10471   info->tile_size_y = -1;
10472   info->tile_level_mode = -1;
10473   info->tile_rounding_mode = -1;
10474 
10475   info->attributes.clear();
10476 
10477   // Read attributes
10478   size_t orig_size = size;
10479   for (size_t nattr = 0; nattr < TINYEXR_MAX_HEADER_ATTRIBUTES; nattr++) {
10480     if (0 == size) {
10481       if (err) {
10482         (*err) += "Insufficient data size for attributes.\n";
10483       }
10484       return TINYEXR_ERROR_INVALID_DATA;
10485     } else if (marker[0] == '\0') {
10486       size--;
10487       break;
10488     }
10489 
10490     std::string attr_name;
10491     std::string attr_type;
10492     std::vector<unsigned char> data;
10493     size_t marker_size;
10494     if (!tinyexr::ReadAttribute(&attr_name, &attr_type, &data, &marker_size,
10495                                 marker, size)) {
10496       if (err) {
10497         (*err) += "Failed to read attribute.\n";
10498       }
10499       return TINYEXR_ERROR_INVALID_DATA;
10500     }
10501     marker += marker_size;
10502     size -= marker_size;
10503 
10504     if (version->tiled && attr_name.compare("tiles") == 0) {
10505       unsigned int x_size, y_size;
10506       unsigned char tile_mode;
10507       TEXR_ASSERT(data.size() == 9);
10508       memcpy(&x_size, &data.at(0), sizeof(int));
10509       memcpy(&y_size, &data.at(4), sizeof(int));
10510       tile_mode = data[8];
10511       tinyexr::swap4(&x_size);
10512       tinyexr::swap4(&y_size);
10513 
10514       info->tile_size_x = static_cast<int>(x_size);
10515       info->tile_size_y = static_cast<int>(y_size);
10516 
10517       // mode = levelMode + roundingMode * 16
10518       info->tile_level_mode = tile_mode & 0x3;
10519       info->tile_rounding_mode = (tile_mode >> 4) & 0x1;
10520 
10521     } else if (attr_name.compare("compression") == 0) {
10522       bool ok = false;
10523       if (data[0] < TINYEXR_COMPRESSIONTYPE_PIZ) {
10524         ok = true;
10525       }
10526 
10527       if (data[0] == TINYEXR_COMPRESSIONTYPE_PIZ) {
10528 #if TINYEXR_USE_PIZ
10529         ok = true;
10530 #else
10531         if (err) {
10532           (*err) = "PIZ compression is not supported.";
10533         }
10534         return TINYEXR_ERROR_UNSUPPORTED_FORMAT;
10535 #endif
10536       }
10537 
10538       if (data[0] == TINYEXR_COMPRESSIONTYPE_ZFP) {
10539 #if TINYEXR_USE_ZFP
10540         ok = true;
10541 #else
10542         if (err) {
10543           (*err) = "ZFP compression is not supported.";
10544         }
10545         return TINYEXR_ERROR_UNSUPPORTED_FORMAT;
10546 #endif
10547       }
10548 
10549       if (!ok) {
10550         if (err) {
10551           (*err) = "Unknown compression type.";
10552         }
10553         return TINYEXR_ERROR_UNSUPPORTED_FORMAT;
10554       }
10555 
10556       info->compression_type = static_cast<int>(data[0]);
10557       has_compression = true;
10558 
10559     } else if (attr_name.compare("channels") == 0) {
10560       // name: zero-terminated string, from 1 to 255 bytes long
10561       // pixel type: int, possible values are: UINT = 0 HALF = 1 FLOAT = 2
10562       // pLinear: unsigned char, possible values are 0 and 1
10563       // reserved: three chars, should be zero
10564       // xSampling: int
10565       // ySampling: int
10566 
10567       if (!ReadChannelInfo(info->channels, data)) {
10568         if (err) {
10569           (*err) += "Failed to parse channel info.\n";
10570         }
10571         return TINYEXR_ERROR_INVALID_DATA;
10572       }
10573 
10574       if (info->channels.size() < 1) {
10575         if (err) {
10576           (*err) += "# of channels is zero.\n";
10577         }
10578         return TINYEXR_ERROR_INVALID_DATA;
10579       }
10580 
10581       has_channels = true;
10582 
10583     } else if (attr_name.compare("dataWindow") == 0) {
10584       if (data.size() >= 16) {
10585         memcpy(&info->data_window[0], &data.at(0), sizeof(int));
10586         memcpy(&info->data_window[1], &data.at(4), sizeof(int));
10587         memcpy(&info->data_window[2], &data.at(8), sizeof(int));
10588         memcpy(&info->data_window[3], &data.at(12), sizeof(int));
10589         tinyexr::swap4(reinterpret_cast<unsigned int *>(&info->data_window[0]));
10590         tinyexr::swap4(reinterpret_cast<unsigned int *>(&info->data_window[1]));
10591         tinyexr::swap4(reinterpret_cast<unsigned int *>(&info->data_window[2]));
10592         tinyexr::swap4(reinterpret_cast<unsigned int *>(&info->data_window[3]));
10593         has_data_window = true;
10594       }
10595     } else if (attr_name.compare("displayWindow") == 0) {
10596       if (data.size() >= 16) {
10597         memcpy(&info->display_window[0], &data.at(0), sizeof(int));
10598         memcpy(&info->display_window[1], &data.at(4), sizeof(int));
10599         memcpy(&info->display_window[2], &data.at(8), sizeof(int));
10600         memcpy(&info->display_window[3], &data.at(12), sizeof(int));
10601         tinyexr::swap4(
10602             reinterpret_cast<unsigned int *>(&info->display_window[0]));
10603         tinyexr::swap4(
10604             reinterpret_cast<unsigned int *>(&info->display_window[1]));
10605         tinyexr::swap4(
10606             reinterpret_cast<unsigned int *>(&info->display_window[2]));
10607         tinyexr::swap4(
10608             reinterpret_cast<unsigned int *>(&info->display_window[3]));
10609 
10610         has_display_window = true;
10611       }
10612     } else if (attr_name.compare("lineOrder") == 0) {
10613       if (data.size() >= 1) {
10614         info->line_order = static_cast<int>(data[0]);
10615         has_line_order = true;
10616       }
10617     } else if (attr_name.compare("pixelAspectRatio") == 0) {
10618       if (data.size() >= sizeof(float)) {
10619         memcpy(&info->pixel_aspect_ratio, &data.at(0), sizeof(float));
10620         tinyexr::swap4(
10621             reinterpret_cast<unsigned int *>(&info->pixel_aspect_ratio));
10622         has_pixel_aspect_ratio = true;
10623       }
10624     } else if (attr_name.compare("screenWindowCenter") == 0) {
10625       if (data.size() >= 8) {
10626         memcpy(&info->screen_window_center[0], &data.at(0), sizeof(float));
10627         memcpy(&info->screen_window_center[1], &data.at(4), sizeof(float));
10628         tinyexr::swap4(
10629             reinterpret_cast<unsigned int *>(&info->screen_window_center[0]));
10630         tinyexr::swap4(
10631             reinterpret_cast<unsigned int *>(&info->screen_window_center[1]));
10632         has_screen_window_center = true;
10633       }
10634     } else if (attr_name.compare("screenWindowWidth") == 0) {
10635       if (data.size() >= sizeof(float)) {
10636         memcpy(&info->screen_window_width, &data.at(0), sizeof(float));
10637         tinyexr::swap4(
10638             reinterpret_cast<unsigned int *>(&info->screen_window_width));
10639 
10640         has_screen_window_width = true;
10641       }
10642     } else if (attr_name.compare("chunkCount") == 0) {
10643       if (data.size() >= sizeof(int)) {
10644         memcpy(&info->chunk_count, &data.at(0), sizeof(int));
10645         tinyexr::swap4(reinterpret_cast<unsigned int *>(&info->chunk_count));
10646       }
10647     } else {
10648       // Custom attribute(up to TINYEXR_MAX_CUSTOM_ATTRIBUTES)
10649       if (info->attributes.size() < TINYEXR_MAX_CUSTOM_ATTRIBUTES) {
10650         EXRAttribute attrib;
10651 #ifdef _MSC_VER
10652         strncpy_s(attrib.name, attr_name.c_str(), 255);
10653         strncpy_s(attrib.type, attr_type.c_str(), 255);
10654 #else
10655         strncpy(attrib.name, attr_name.c_str(), 255);
10656         strncpy(attrib.type, attr_type.c_str(), 255);
10657 #endif
10658         attrib.name[255] = '\0';
10659         attrib.type[255] = '\0';
10660         attrib.size = static_cast<int>(data.size());
10661         attrib.value = static_cast<unsigned char *>(malloc(data.size()));
10662         memcpy(reinterpret_cast<char *>(attrib.value), &data.at(0),
10663                data.size());
10664         info->attributes.push_back(attrib);
10665       }
10666     }
10667   }
10668 
10669   // Check if required attributes exist
10670   {
10671     std::stringstream ss_err;
10672 
10673     if (!has_compression) {
10674       ss_err << "\"compression\" attribute not found in the header."
10675              << std::endl;
10676     }
10677 
10678     if (!has_channels) {
10679       ss_err << "\"channels\" attribute not found in the header." << std::endl;
10680     }
10681 
10682     if (!has_line_order) {
10683       ss_err << "\"lineOrder\" attribute not found in the header." << std::endl;
10684     }
10685 
10686     if (!has_display_window) {
10687       ss_err << "\"displayWindow\" attribute not found in the header."
10688              << std::endl;
10689     }
10690 
10691     if (!has_data_window) {
10692       ss_err << "\"dataWindow\" attribute not found in the header or invalid."
10693              << std::endl;
10694     }
10695 
10696     if (!has_pixel_aspect_ratio) {
10697       ss_err << "\"pixelAspectRatio\" attribute not found in the header."
10698              << std::endl;
10699     }
10700 
10701     if (!has_screen_window_width) {
10702       ss_err << "\"screenWindowWidth\" attribute not found in the header."
10703              << std::endl;
10704     }
10705 
10706     if (!has_screen_window_center) {
10707       ss_err << "\"screenWindowCenter\" attribute not found in the header."
10708              << std::endl;
10709     }
10710 
10711     if (!(ss_err.str().empty())) {
10712       if (err) {
10713         (*err) += ss_err.str();
10714       }
10715       return TINYEXR_ERROR_INVALID_HEADER;
10716     }
10717   }
10718 
10719   info->header_len = static_cast<unsigned int>(orig_size - size);
10720 
10721   return TINYEXR_SUCCESS;
10722 }
10723 
10724 // C++ HeaderInfo to C EXRHeader conversion.
ConvertHeader(EXRHeader * exr_header,const HeaderInfo & info)10725 static void ConvertHeader(EXRHeader *exr_header, const HeaderInfo &info) {
10726   exr_header->pixel_aspect_ratio = info.pixel_aspect_ratio;
10727   exr_header->screen_window_center[0] = info.screen_window_center[0];
10728   exr_header->screen_window_center[1] = info.screen_window_center[1];
10729   exr_header->screen_window_width = info.screen_window_width;
10730   exr_header->chunk_count = info.chunk_count;
10731   exr_header->display_window[0] = info.display_window[0];
10732   exr_header->display_window[1] = info.display_window[1];
10733   exr_header->display_window[2] = info.display_window[2];
10734   exr_header->display_window[3] = info.display_window[3];
10735   exr_header->data_window[0] = info.data_window[0];
10736   exr_header->data_window[1] = info.data_window[1];
10737   exr_header->data_window[2] = info.data_window[2];
10738   exr_header->data_window[3] = info.data_window[3];
10739   exr_header->line_order = info.line_order;
10740   exr_header->compression_type = info.compression_type;
10741 
10742   exr_header->tile_size_x = info.tile_size_x;
10743   exr_header->tile_size_y = info.tile_size_y;
10744   exr_header->tile_level_mode = info.tile_level_mode;
10745   exr_header->tile_rounding_mode = info.tile_rounding_mode;
10746 
10747   exr_header->num_channels = static_cast<int>(info.channels.size());
10748 
10749   exr_header->channels = static_cast<EXRChannelInfo *>(malloc(
10750       sizeof(EXRChannelInfo) * static_cast<size_t>(exr_header->num_channels)));
10751   for (size_t c = 0; c < static_cast<size_t>(exr_header->num_channels); c++) {
10752 #ifdef _MSC_VER
10753     strncpy_s(exr_header->channels[c].name, info.channels[c].name.c_str(), 255);
10754 #else
10755     strncpy(exr_header->channels[c].name, info.channels[c].name.c_str(), 255);
10756 #endif
10757     // manually add '\0' for safety.
10758     exr_header->channels[c].name[255] = '\0';
10759 
10760     exr_header->channels[c].pixel_type = info.channels[c].pixel_type;
10761     exr_header->channels[c].p_linear = info.channels[c].p_linear;
10762     exr_header->channels[c].x_sampling = info.channels[c].x_sampling;
10763     exr_header->channels[c].y_sampling = info.channels[c].y_sampling;
10764   }
10765 
10766   exr_header->pixel_types = static_cast<int *>(
10767       malloc(sizeof(int) * static_cast<size_t>(exr_header->num_channels)));
10768   for (size_t c = 0; c < static_cast<size_t>(exr_header->num_channels); c++) {
10769     exr_header->pixel_types[c] = info.channels[c].pixel_type;
10770   }
10771 
10772   // Initially fill with values of `pixel_types`
10773   exr_header->requested_pixel_types = static_cast<int *>(
10774       malloc(sizeof(int) * static_cast<size_t>(exr_header->num_channels)));
10775   for (size_t c = 0; c < static_cast<size_t>(exr_header->num_channels); c++) {
10776     exr_header->requested_pixel_types[c] = info.channels[c].pixel_type;
10777   }
10778 
10779   exr_header->num_custom_attributes = static_cast<int>(info.attributes.size());
10780 
10781   if (exr_header->num_custom_attributes > 0) {
10782     // TODO(syoyo): Report warning when # of attributes exceeds
10783     // `TINYEXR_MAX_CUSTOM_ATTRIBUTES`
10784     if (exr_header->num_custom_attributes > TINYEXR_MAX_CUSTOM_ATTRIBUTES) {
10785       exr_header->num_custom_attributes = TINYEXR_MAX_CUSTOM_ATTRIBUTES;
10786     }
10787 
10788     exr_header->custom_attributes = static_cast<EXRAttribute *>(malloc(
10789         sizeof(EXRAttribute) * size_t(exr_header->num_custom_attributes)));
10790 
10791     for (size_t i = 0; i < info.attributes.size(); i++) {
10792       memcpy(exr_header->custom_attributes[i].name, info.attributes[i].name,
10793              256);
10794       memcpy(exr_header->custom_attributes[i].type, info.attributes[i].type,
10795              256);
10796       exr_header->custom_attributes[i].size = info.attributes[i].size;
10797       // Just copy poiner
10798       exr_header->custom_attributes[i].value = info.attributes[i].value;
10799     }
10800 
10801   } else {
10802     exr_header->custom_attributes = NULL;
10803   }
10804 
10805   exr_header->header_len = info.header_len;
10806 }
10807 
DecodeChunk(EXRImage * exr_image,const EXRHeader * exr_header,const std::vector<tinyexr::tinyexr_uint64> & offsets,const unsigned char * head,const size_t size,std::string * err)10808 static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header,
10809                        const std::vector<tinyexr::tinyexr_uint64> &offsets,
10810                        const unsigned char *head, const size_t size,
10811                        std::string *err) {
10812   int num_channels = exr_header->num_channels;
10813 
10814   int num_scanline_blocks = 1;
10815   if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZIP) {
10816     num_scanline_blocks = 16;
10817   } else if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_PIZ) {
10818     num_scanline_blocks = 32;
10819   } else if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) {
10820     num_scanline_blocks = 16;
10821   }
10822 
10823   int data_width = exr_header->data_window[2] - exr_header->data_window[0] + 1;
10824   int data_height = exr_header->data_window[3] - exr_header->data_window[1] + 1;
10825 
10826   if ((data_width < 0) || (data_height < 0)) {
10827     if (err) {
10828       std::stringstream ss;
10829       ss << "Invalid data width or data height: " << data_width << ", "
10830          << data_height << std::endl;
10831       (*err) += ss.str();
10832     }
10833     return TINYEXR_ERROR_INVALID_DATA;
10834   }
10835 
10836   // Do not allow too large data_width and data_height. header invalid?
10837   {
10838     const int threshold = 1024 * 8192;  // heuristics
10839     if ((data_width > threshold) || (data_height > threshold)) {
10840       if (err) {
10841         std::stringstream ss;
10842         ss << "data_with or data_height too large. data_width: " << data_width
10843            << ", "
10844            << "data_height = " << data_height << std::endl;
10845         (*err) += ss.str();
10846       }
10847       return TINYEXR_ERROR_INVALID_DATA;
10848     }
10849   }
10850 
10851   size_t num_blocks = offsets.size();
10852 
10853   std::vector<size_t> channel_offset_list;
10854   int pixel_data_size = 0;
10855   size_t channel_offset = 0;
10856   if (!tinyexr::ComputeChannelLayout(&channel_offset_list, &pixel_data_size,
10857                                      &channel_offset, num_channels,
10858                                      exr_header->channels)) {
10859     if (err) {
10860       (*err) += "Failed to compute channel layout.\n";
10861     }
10862     return TINYEXR_ERROR_INVALID_DATA;
10863   }
10864 
10865   bool invalid_data = false;  // TODO(LTE): Use atomic lock for MT safety.
10866 
10867   if (exr_header->tiled) {
10868     // value check
10869     if (exr_header->tile_size_x < 0) {
10870       if (err) {
10871         std::stringstream ss;
10872         ss << "Invalid tile size x : " << exr_header->tile_size_x << "\n";
10873         (*err) += ss.str();
10874       }
10875       return TINYEXR_ERROR_INVALID_HEADER;
10876     }
10877 
10878     if (exr_header->tile_size_y < 0) {
10879       if (err) {
10880         std::stringstream ss;
10881         ss << "Invalid tile size y : " << exr_header->tile_size_y << "\n";
10882         (*err) += ss.str();
10883       }
10884       return TINYEXR_ERROR_INVALID_HEADER;
10885     }
10886 
10887     size_t num_tiles = offsets.size();  // = # of blocks
10888 
10889     exr_image->tiles = static_cast<EXRTile *>(
10890         calloc(sizeof(EXRTile), static_cast<size_t>(num_tiles)));
10891 
10892     int err_code = TINYEXR_SUCCESS;
10893 
10894 #if (__cplusplus > 199711L) && (TINYEXR_USE_THREAD > 0)
10895 
10896     std::vector<std::thread> workers;
10897     std::atomic<size_t> tile_count(0);
10898 
10899     int num_threads = std::max(1, int(std::thread::hardware_concurrency()));
10900     if (num_threads > int(num_tiles)) {
10901       num_threads = int(num_tiles);
10902     }
10903 
10904     for (int t = 0; t < num_threads; t++) {
10905       workers.emplace_back(std::thread([&]() {
10906         size_t tile_idx = 0;
10907         while ((tile_idx = tile_count++) < num_tiles) {
10908 
10909 #else
10910     for (size_t tile_idx = 0; tile_idx < num_tiles; tile_idx++) {
10911 #endif
10912           // Allocate memory for each tile.
10913           exr_image->tiles[tile_idx].images = tinyexr::AllocateImage(
10914               num_channels, exr_header->channels,
10915               exr_header->requested_pixel_types, exr_header->tile_size_x,
10916               exr_header->tile_size_y);
10917 
10918           // 16 byte: tile coordinates
10919           // 4 byte : data size
10920           // ~      : data(uncompressed or compressed)
10921           if (offsets[tile_idx] + sizeof(int) * 5 > size) {
10922             // TODO(LTE): atomic
10923             if (err) {
10924               (*err) += "Insufficient data size.\n";
10925             }
10926             err_code = TINYEXR_ERROR_INVALID_DATA;
10927             break;
10928           }
10929 
10930           size_t data_size =
10931               size_t(size - (offsets[tile_idx] + sizeof(int) * 5));
10932           const unsigned char *data_ptr =
10933               reinterpret_cast<const unsigned char *>(head + offsets[tile_idx]);
10934 
10935           int tile_coordinates[4];
10936           memcpy(tile_coordinates, data_ptr, sizeof(int) * 4);
10937           tinyexr::swap4(
10938               reinterpret_cast<unsigned int *>(&tile_coordinates[0]));
10939           tinyexr::swap4(
10940               reinterpret_cast<unsigned int *>(&tile_coordinates[1]));
10941           tinyexr::swap4(
10942               reinterpret_cast<unsigned int *>(&tile_coordinates[2]));
10943           tinyexr::swap4(
10944               reinterpret_cast<unsigned int *>(&tile_coordinates[3]));
10945 
10946           // @todo{ LoD }
10947           if (tile_coordinates[2] != 0) {
10948             err_code = TINYEXR_ERROR_UNSUPPORTED_FEATURE;
10949             break;
10950           }
10951           if (tile_coordinates[3] != 0) {
10952             err_code = TINYEXR_ERROR_UNSUPPORTED_FEATURE;
10953             break;
10954           }
10955 
10956           int data_len;
10957           memcpy(&data_len, data_ptr + 16,
10958                  sizeof(int));  // 16 = sizeof(tile_coordinates)
10959           tinyexr::swap4(reinterpret_cast<unsigned int *>(&data_len));
10960 
10961           if (data_len < 4 || size_t(data_len) > data_size) {
10962             // TODO(LTE): atomic
10963             if (err) {
10964               (*err) += "Insufficient data length.\n";
10965             }
10966             err_code = TINYEXR_ERROR_INVALID_DATA;
10967             break;
10968           }
10969 
10970           // Move to data addr: 20 = 16 + 4;
10971           data_ptr += 20;
10972 
10973           bool ret = tinyexr::DecodeTiledPixelData(
10974               exr_image->tiles[tile_idx].images,
10975               &(exr_image->tiles[tile_idx].width),
10976               &(exr_image->tiles[tile_idx].height),
10977               exr_header->requested_pixel_types, data_ptr,
10978               static_cast<size_t>(data_len), exr_header->compression_type,
10979               exr_header->line_order, data_width, data_height,
10980               tile_coordinates[0], tile_coordinates[1], exr_header->tile_size_x,
10981               exr_header->tile_size_y, static_cast<size_t>(pixel_data_size),
10982               static_cast<size_t>(exr_header->num_custom_attributes),
10983               exr_header->custom_attributes,
10984               static_cast<size_t>(exr_header->num_channels),
10985               exr_header->channels, channel_offset_list);
10986 
10987           if (!ret) {
10988             // TODO(LTE): atomic
10989             if (err) {
10990               (*err) += "Failed to decode tile data.\n";
10991             }
10992             err_code = TINYEXR_ERROR_INVALID_DATA;
10993           }
10994 
10995           exr_image->tiles[tile_idx].offset_x = tile_coordinates[0];
10996           exr_image->tiles[tile_idx].offset_y = tile_coordinates[1];
10997           exr_image->tiles[tile_idx].level_x = tile_coordinates[2];
10998           exr_image->tiles[tile_idx].level_y = tile_coordinates[3];
10999 
11000 #if (__cplusplus > 199711L) && (TINYEXR_USE_THREAD > 0)
11001         }
11002       }));
11003     }  // num_thread loop
11004 
11005     for (auto &t : workers) {
11006       t.join();
11007     }
11008 
11009 #else
11010     }
11011 #endif
11012 
11013     if (err_code != TINYEXR_SUCCESS) {
11014       return err_code;
11015     }
11016 
11017     exr_image->num_tiles = static_cast<int>(num_tiles);
11018   } else {  // scanline format
11019 
11020     // Don't allow too large image(256GB * pixel_data_size or more). Workaround
11021     // for #104.
11022     size_t total_data_len =
11023         size_t(data_width) * size_t(data_height) * size_t(num_channels);
11024     const bool total_data_len_overflown =
11025         sizeof(void *) == 8 ? (total_data_len >= 0x4000000000) : false;
11026     if ((total_data_len == 0) || total_data_len_overflown) {
11027       if (err) {
11028         std::stringstream ss;
11029         ss << "Image data size is zero or too large: width = " << data_width
11030            << ", height = " << data_height << ", channels = " << num_channels
11031            << std::endl;
11032         (*err) += ss.str();
11033       }
11034       return TINYEXR_ERROR_INVALID_DATA;
11035     }
11036 
11037     exr_image->images = tinyexr::AllocateImage(
11038         num_channels, exr_header->channels, exr_header->requested_pixel_types,
11039         data_width, data_height);
11040 
11041 #if (__cplusplus > 199711L) && (TINYEXR_USE_THREAD > 0)
11042     std::vector<std::thread> workers;
11043     std::atomic<int> y_count(0);
11044 
11045     int num_threads = std::max(1, int(std::thread::hardware_concurrency()));
11046     if (num_threads > int(num_blocks)) {
11047       num_threads = int(num_blocks);
11048     }
11049 
11050     for (int t = 0; t < num_threads; t++) {
11051       workers.emplace_back(std::thread([&]() {
11052         int y = 0;
11053         while ((y = y_count++) < int(num_blocks)) {
11054 
11055 #else
11056 
11057 #if TINYEXR_USE_OPENMP
11058 #pragma omp parallel for
11059 #endif
11060     for (int y = 0; y < static_cast<int>(num_blocks); y++) {
11061 
11062 #endif
11063           size_t y_idx = static_cast<size_t>(y);
11064 
11065           if (offsets[y_idx] + sizeof(int) * 2 > size) {
11066             invalid_data = true;
11067           } else {
11068             // 4 byte: scan line
11069             // 4 byte: data size
11070             // ~     : pixel data(uncompressed or compressed)
11071             size_t data_size =
11072                 size_t(size - (offsets[y_idx] + sizeof(int) * 2));
11073             const unsigned char *data_ptr =
11074                 reinterpret_cast<const unsigned char *>(head + offsets[y_idx]);
11075 
11076             int line_no;
11077             memcpy(&line_no, data_ptr, sizeof(int));
11078             int data_len;
11079             memcpy(&data_len, data_ptr + 4, sizeof(int));
11080             tinyexr::swap4(reinterpret_cast<unsigned int *>(&line_no));
11081             tinyexr::swap4(reinterpret_cast<unsigned int *>(&data_len));
11082 
11083             if (size_t(data_len) > data_size) {
11084               invalid_data = true;
11085 
11086             } else if ((line_no > (2 << 20)) || (line_no < -(2 << 20))) {
11087               // Too large value. Assume this is invalid
11088               // 2**20 = 1048576 = heuristic value.
11089               invalid_data = true;
11090             } else if (data_len == 0) {
11091               // TODO(syoyo): May be ok to raise the threshold for example
11092               // `data_len < 4`
11093               invalid_data = true;
11094             } else {
11095               // line_no may be negative.
11096               int end_line_no = (std::min)(line_no + num_scanline_blocks,
11097                                            (exr_header->data_window[3] + 1));
11098 
11099               int num_lines = end_line_no - line_no;
11100 
11101               if (num_lines <= 0) {
11102                 invalid_data = true;
11103               } else {
11104                 // Move to data addr: 8 = 4 + 4;
11105                 data_ptr += 8;
11106 
11107                 // Adjust line_no with data_window.bmin.y
11108 
11109                 // overflow check
11110                 tinyexr_int64 lno =
11111                     static_cast<tinyexr_int64>(line_no) -
11112                     static_cast<tinyexr_int64>(exr_header->data_window[1]);
11113                 if (lno > std::numeric_limits<int>::max()) {
11114                   line_no = -1;  // invalid
11115                 } else if (lno < -std::numeric_limits<int>::max()) {
11116                   line_no = -1;  // invalid
11117                 } else {
11118                   line_no -= exr_header->data_window[1];
11119                 }
11120 
11121                 if (line_no < 0) {
11122                   invalid_data = true;
11123                 } else {
11124                   if (!tinyexr::DecodePixelData(
11125                           exr_image->images, exr_header->requested_pixel_types,
11126                           data_ptr, static_cast<size_t>(data_len),
11127                           exr_header->compression_type, exr_header->line_order,
11128                           data_width, data_height, data_width, y, line_no,
11129                           num_lines, static_cast<size_t>(pixel_data_size),
11130                           static_cast<size_t>(
11131                               exr_header->num_custom_attributes),
11132                           exr_header->custom_attributes,
11133                           static_cast<size_t>(exr_header->num_channels),
11134                           exr_header->channels, channel_offset_list)) {
11135                     invalid_data = true;
11136                   }
11137                 }
11138               }
11139             }
11140           }
11141 
11142 #if (__cplusplus > 199711L) && (TINYEXR_USE_THREAD > 0)
11143         }
11144       }));
11145     }
11146 
11147     for (auto &t : workers) {
11148       t.join();
11149     }
11150 #else
11151     }  // omp parallel
11152 #endif
11153   }
11154 
11155   if (invalid_data) {
11156     if (err) {
11157       std::stringstream ss;
11158       (*err) += "Invalid data found when decoding pixels.\n";
11159     }
11160     return TINYEXR_ERROR_INVALID_DATA;
11161   }
11162 
11163   // Overwrite `pixel_type` with `requested_pixel_type`.
11164   {
11165     for (int c = 0; c < exr_header->num_channels; c++) {
11166       exr_header->pixel_types[c] = exr_header->requested_pixel_types[c];
11167     }
11168   }
11169 
11170   {
11171     exr_image->num_channels = num_channels;
11172 
11173     exr_image->width = data_width;
11174     exr_image->height = data_height;
11175   }
11176 
11177   return TINYEXR_SUCCESS;
11178 }
11179 
ReconstructLineOffsets(std::vector<tinyexr::tinyexr_uint64> * offsets,size_t n,const unsigned char * head,const unsigned char * marker,const size_t size)11180 static bool ReconstructLineOffsets(
11181     std::vector<tinyexr::tinyexr_uint64> *offsets, size_t n,
11182     const unsigned char *head, const unsigned char *marker, const size_t size) {
11183   TEXR_ASSERT(head < marker);
11184   TEXR_ASSERT(offsets->size() == n);
11185 
11186   for (size_t i = 0; i < n; i++) {
11187     size_t offset = static_cast<size_t>(marker - head);
11188     // Offset should not exceed whole EXR file/data size.
11189     if ((offset + sizeof(tinyexr::tinyexr_uint64)) >= size) {
11190       return false;
11191     }
11192 
11193     int y;
11194     unsigned int data_len;
11195 
11196     memcpy(&y, marker, sizeof(int));
11197     memcpy(&data_len, marker + 4, sizeof(unsigned int));
11198 
11199     if (data_len >= size) {
11200       return false;
11201     }
11202 
11203     tinyexr::swap4(reinterpret_cast<unsigned int *>(&y));
11204     tinyexr::swap4(reinterpret_cast<unsigned int *>(&data_len));
11205 
11206     (*offsets)[i] = offset;
11207 
11208     marker += data_len + 8;  // 8 = 4 bytes(y) + 4 bytes(data_len)
11209   }
11210 
11211   return true;
11212 }
11213 
DecodeEXRImage(EXRImage * exr_image,const EXRHeader * exr_header,const unsigned char * head,const unsigned char * marker,const size_t size,const char ** err)11214 static int DecodeEXRImage(EXRImage *exr_image, const EXRHeader *exr_header,
11215                           const unsigned char *head,
11216                           const unsigned char *marker, const size_t size,
11217                           const char **err) {
11218   if (exr_image == NULL || exr_header == NULL || head == NULL ||
11219       marker == NULL || (size <= tinyexr::kEXRVersionSize)) {
11220     tinyexr::SetErrorMessage("Invalid argument for DecodeEXRImage().", err);
11221     return TINYEXR_ERROR_INVALID_ARGUMENT;
11222   }
11223 
11224   int num_scanline_blocks = 1;
11225   if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZIP) {
11226     num_scanline_blocks = 16;
11227   } else if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_PIZ) {
11228     num_scanline_blocks = 32;
11229   } else if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) {
11230     num_scanline_blocks = 16;
11231   }
11232 
11233   int data_width = exr_header->data_window[2] - exr_header->data_window[0];
11234   if (data_width >= std::numeric_limits<int>::max()) {
11235     // Issue 63
11236     tinyexr::SetErrorMessage("Invalid data width value", err);
11237     return TINYEXR_ERROR_INVALID_DATA;
11238   }
11239   data_width++;
11240 
11241   int data_height = exr_header->data_window[3] - exr_header->data_window[1];
11242   if (data_height >= std::numeric_limits<int>::max()) {
11243     tinyexr::SetErrorMessage("Invalid data height value", err);
11244     return TINYEXR_ERROR_INVALID_DATA;
11245   }
11246   data_height++;
11247 
11248   if ((data_width < 0) || (data_height < 0)) {
11249     tinyexr::SetErrorMessage("data width or data height is negative.", err);
11250     return TINYEXR_ERROR_INVALID_DATA;
11251   }
11252 
11253   // Do not allow too large data_width and data_height. header invalid?
11254   {
11255     const int threshold = 1024 * 8192;  // heuristics
11256     if (data_width > threshold) {
11257       tinyexr::SetErrorMessage("data width too large.", err);
11258       return TINYEXR_ERROR_INVALID_DATA;
11259     }
11260     if (data_height > threshold) {
11261       tinyexr::SetErrorMessage("data height too large.", err);
11262       return TINYEXR_ERROR_INVALID_DATA;
11263     }
11264   }
11265 
11266   // Read offset tables.
11267   size_t num_blocks = 0;
11268 
11269   if (exr_header->chunk_count > 0) {
11270     // Use `chunkCount` attribute.
11271     num_blocks = static_cast<size_t>(exr_header->chunk_count);
11272   } else if (exr_header->tiled) {
11273     // @todo { LoD }
11274     size_t num_x_tiles = static_cast<size_t>(data_width) /
11275                          static_cast<size_t>(exr_header->tile_size_x);
11276     if (num_x_tiles * static_cast<size_t>(exr_header->tile_size_x) <
11277         static_cast<size_t>(data_width)) {
11278       num_x_tiles++;
11279     }
11280     size_t num_y_tiles = static_cast<size_t>(data_height) /
11281                          static_cast<size_t>(exr_header->tile_size_y);
11282     if (num_y_tiles * static_cast<size_t>(exr_header->tile_size_y) <
11283         static_cast<size_t>(data_height)) {
11284       num_y_tiles++;
11285     }
11286 
11287     num_blocks = num_x_tiles * num_y_tiles;
11288   } else {
11289     num_blocks = static_cast<size_t>(data_height) /
11290                  static_cast<size_t>(num_scanline_blocks);
11291     if (num_blocks * static_cast<size_t>(num_scanline_blocks) <
11292         static_cast<size_t>(data_height)) {
11293       num_blocks++;
11294     }
11295   }
11296 
11297   std::vector<tinyexr::tinyexr_uint64> offsets(num_blocks);
11298 
11299   for (size_t y = 0; y < num_blocks; y++) {
11300     tinyexr::tinyexr_uint64 offset;
11301     // Issue #81
11302     if ((marker + sizeof(tinyexr_uint64)) >= (head + size)) {
11303       tinyexr::SetErrorMessage("Insufficient data size in offset table.", err);
11304       return TINYEXR_ERROR_INVALID_DATA;
11305     }
11306 
11307     memcpy(&offset, marker, sizeof(tinyexr::tinyexr_uint64));
11308     tinyexr::swap8(&offset);
11309     if (offset >= size) {
11310       tinyexr::SetErrorMessage("Invalid offset value in DecodeEXRImage.", err);
11311       return TINYEXR_ERROR_INVALID_DATA;
11312     }
11313     marker += sizeof(tinyexr::tinyexr_uint64);  // = 8
11314     offsets[y] = offset;
11315   }
11316 
11317   // If line offsets are invalid, we try to reconstruct it.
11318   // See OpenEXR/IlmImf/ImfScanLineInputFile.cpp::readLineOffsets() for details.
11319   for (size_t y = 0; y < num_blocks; y++) {
11320     if (offsets[y] <= 0) {
11321       // TODO(syoyo) Report as warning?
11322       // if (err) {
11323       //  stringstream ss;
11324       //  ss << "Incomplete lineOffsets." << std::endl;
11325       //  (*err) += ss.str();
11326       //}
11327       bool ret =
11328           ReconstructLineOffsets(&offsets, num_blocks, head, marker, size);
11329       if (ret) {
11330         // OK
11331         break;
11332       } else {
11333         tinyexr::SetErrorMessage(
11334             "Cannot reconstruct lineOffset table in DecodeEXRImage.", err);
11335         return TINYEXR_ERROR_INVALID_DATA;
11336       }
11337     }
11338   }
11339 
11340   {
11341     std::string e;
11342     int ret = DecodeChunk(exr_image, exr_header, offsets, head, size, &e);
11343 
11344     if (ret != TINYEXR_SUCCESS) {
11345       if (!e.empty()) {
11346         tinyexr::SetErrorMessage(e, err);
11347       }
11348 
11349 #if 1
11350       FreeEXRImage(exr_image);
11351 #else
11352       // release memory(if exists)
11353       if ((exr_header->num_channels > 0) && exr_image && exr_image->images) {
11354         for (size_t c = 0; c < size_t(exr_header->num_channels); c++) {
11355           if (exr_image->images[c]) {
11356             free(exr_image->images[c]);
11357             exr_image->images[c] = NULL;
11358           }
11359         }
11360         free(exr_image->images);
11361         exr_image->images = NULL;
11362       }
11363 #endif
11364     }
11365 
11366     return ret;
11367   }
11368 }
11369 
GetLayers(const EXRHeader & exr_header,std::vector<std::string> & layer_names)11370 static void GetLayers(const EXRHeader& exr_header, std::vector<std::string>& layer_names) {
11371   // Naive implementation
11372   // Group channels by layers
11373   // go over all channel names, split by periods
11374   // collect unique names
11375   layer_names.clear();
11376   for (int c = 0; c < exr_header.num_channels; c++) {
11377     std::string full_name(exr_header.channels[c].name);
11378     const size_t pos = full_name.find_last_of('.');
11379     if (pos != std::string::npos && pos != 0 && pos + 1 < full_name.size()) {
11380       full_name.erase(pos);
11381       if (std::find(layer_names.begin(), layer_names.end(), full_name) == layer_names.end())
11382         layer_names.push_back(full_name);
11383     }
11384   }
11385 }
11386 
11387 struct LayerChannel {
LayerChannelLayerChannel11388   explicit LayerChannel (size_t i, std::string n)
11389     : index(i)
11390     , name(n)
11391   {}
11392   size_t index;
11393   std::string name;
11394 };
11395 
ChannelsInLayer(const EXRHeader & exr_header,const std::string layer_name,std::vector<LayerChannel> & channels)11396 static void ChannelsInLayer(const EXRHeader& exr_header, const std::string layer_name, std::vector<LayerChannel>& channels) {
11397   channels.clear();
11398   for (int c = 0; c < exr_header.num_channels; c++) {
11399     std::string ch_name(exr_header.channels[c].name);
11400     if (layer_name.empty()) {
11401       const size_t pos = ch_name.find_last_of('.');
11402       if (pos != std::string::npos && pos < ch_name.size()) {
11403         ch_name = ch_name.substr(pos + 1);
11404       }
11405     } else {
11406       const size_t pos = ch_name.find(layer_name + '.');
11407       if (pos == std::string::npos)
11408         continue;
11409       if (pos == 0) {
11410         ch_name = ch_name.substr(layer_name.size() + 1);
11411       }
11412     }
11413     LayerChannel ch(size_t(c), ch_name);
11414     channels.push_back(ch);
11415   }
11416 }
11417 
11418 }  // namespace tinyexr
11419 
EXRLayers(const char * filename,const char ** layer_names[],int * num_layers,const char ** err)11420 int EXRLayers(const char *filename, const char **layer_names[], int *num_layers, const char **err) {
11421   EXRVersion exr_version;
11422   EXRHeader exr_header;
11423   InitEXRHeader(&exr_header);
11424 
11425   {
11426     int ret = ParseEXRVersionFromFile(&exr_version, filename);
11427     if (ret != TINYEXR_SUCCESS) {
11428       tinyexr::SetErrorMessage("Invalid EXR header.", err);
11429       return ret;
11430     }
11431 
11432     if (exr_version.multipart || exr_version.non_image) {
11433       tinyexr::SetErrorMessage(
11434         "Loading multipart or DeepImage is not supported  in LoadEXR() API",
11435         err);
11436       return TINYEXR_ERROR_INVALID_DATA;  // @fixme.
11437     }
11438   }
11439 
11440   int ret = ParseEXRHeaderFromFile(&exr_header, &exr_version, filename, err);
11441   if (ret != TINYEXR_SUCCESS) {
11442     FreeEXRHeader(&exr_header);
11443     return ret;
11444   }
11445 
11446   std::vector<std::string> layer_vec;
11447   tinyexr::GetLayers(exr_header, layer_vec);
11448 
11449   (*num_layers) = int(layer_vec.size());
11450   (*layer_names) = static_cast<const char **>(
11451     malloc(sizeof(const char *) * static_cast<size_t>(layer_vec.size())));
11452   for (size_t c = 0; c < static_cast<size_t>(layer_vec.size()); c++) {
11453 #ifdef _MSC_VER
11454     (*layer_names)[c] = _strdup(layer_vec[c].c_str());
11455 #else
11456     (*layer_names)[c] = strdup(layer_vec[c].c_str());
11457 #endif
11458   }
11459 
11460   FreeEXRHeader(&exr_header);
11461   return TINYEXR_SUCCESS;
11462 }
11463 
LoadEXR(float ** out_rgba,int * width,int * height,const char * filename,const char ** err)11464 int LoadEXR(float **out_rgba, int *width, int *height, const char *filename,
11465             const char **err) {
11466   return LoadEXRWithLayer(out_rgba, width, height, filename, /* layername */NULL, err);
11467 }
11468 
LoadEXRWithLayer(float ** out_rgba,int * width,int * height,const char * filename,const char * layername,const char ** err)11469 int LoadEXRWithLayer(float **out_rgba, int *width, int *height, const char *filename, const char *layername,
11470             const char **err) {
11471   if (out_rgba == NULL) {
11472     tinyexr::SetErrorMessage("Invalid argument for LoadEXR()", err);
11473     return TINYEXR_ERROR_INVALID_ARGUMENT;
11474   }
11475 
11476   EXRVersion exr_version;
11477   EXRImage exr_image;
11478   EXRHeader exr_header;
11479   InitEXRHeader(&exr_header);
11480   InitEXRImage(&exr_image);
11481 
11482   {
11483     int ret = ParseEXRVersionFromFile(&exr_version, filename);
11484     if (ret != TINYEXR_SUCCESS) {
11485       std::stringstream ss;
11486       ss << "Failed to open EXR file or read version info from EXR file. code(" << ret << ")";
11487       tinyexr::SetErrorMessage(ss.str(), err);
11488       return ret;
11489     }
11490 
11491     if (exr_version.multipart || exr_version.non_image) {
11492       tinyexr::SetErrorMessage(
11493           "Loading multipart or DeepImage is not supported  in LoadEXR() API",
11494           err);
11495       return TINYEXR_ERROR_INVALID_DATA;  // @fixme.
11496     }
11497   }
11498 
11499   {
11500     int ret = ParseEXRHeaderFromFile(&exr_header, &exr_version, filename, err);
11501     if (ret != TINYEXR_SUCCESS) {
11502       FreeEXRHeader(&exr_header);
11503       return ret;
11504     }
11505   }
11506 
11507   // Read HALF channel as FLOAT.
11508   for (int i = 0; i < exr_header.num_channels; i++) {
11509     if (exr_header.pixel_types[i] == TINYEXR_PIXELTYPE_HALF) {
11510       exr_header.requested_pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT;
11511     }
11512   }
11513 
11514   // TODO: Probably limit loading to layers (channels) selected by layer index
11515   {
11516     int ret = LoadEXRImageFromFile(&exr_image, &exr_header, filename, err);
11517     if (ret != TINYEXR_SUCCESS) {
11518       FreeEXRHeader(&exr_header);
11519       return ret;
11520     }
11521   }
11522 
11523   // RGBA
11524   int idxR = -1;
11525   int idxG = -1;
11526   int idxB = -1;
11527   int idxA = -1;
11528 
11529   std::vector<std::string> layer_names;
11530   tinyexr::GetLayers(exr_header, layer_names);
11531 
11532   std::vector<tinyexr::LayerChannel> channels;
11533   tinyexr::ChannelsInLayer(exr_header, layername == NULL ? "" : std::string(layername), channels);
11534 
11535   if (channels.size() < 1) {
11536     tinyexr::SetErrorMessage("Layer Not Found", err);
11537     FreeEXRHeader(&exr_header);
11538     FreeEXRImage(&exr_image);
11539     return TINYEXR_ERROR_LAYER_NOT_FOUND;
11540   }
11541 
11542   size_t ch_count = channels.size() < 4 ? channels.size() : 4;
11543   for (size_t c = 0; c < ch_count; c++) {
11544     const tinyexr::LayerChannel &ch = channels[c];
11545 
11546     if (ch.name == "R") {
11547       idxR = int(ch.index);
11548     }
11549     else if (ch.name == "G") {
11550       idxG = int(ch.index);
11551     }
11552     else if (ch.name == "B") {
11553       idxB = int(ch.index);
11554     }
11555     else if (ch.name == "A") {
11556       idxA = int(ch.index);
11557     }
11558   }
11559 
11560   if (channels.size() == 1) {
11561     int chIdx = int(channels.front().index);
11562     // Grayscale channel only.
11563 
11564     (*out_rgba) = reinterpret_cast<float *>(
11565         malloc(4 * sizeof(float) * static_cast<size_t>(exr_image.width) *
11566                static_cast<size_t>(exr_image.height)));
11567 
11568     if (exr_header.tiled) {
11569       for (int it = 0; it < exr_image.num_tiles; it++) {
11570         for (int j = 0; j < exr_header.tile_size_y; j++) {
11571           for (int i = 0; i < exr_header.tile_size_x; i++) {
11572             const int ii =
11573                 exr_image.tiles[it].offset_x * exr_header.tile_size_x + i;
11574             const int jj =
11575                 exr_image.tiles[it].offset_y * exr_header.tile_size_y + j;
11576             const int idx = ii + jj * exr_image.width;
11577 
11578             // out of region check.
11579             if (ii >= exr_image.width) {
11580               continue;
11581             }
11582             if (jj >= exr_image.height) {
11583               continue;
11584             }
11585             const int srcIdx = i + j * exr_header.tile_size_x;
11586             unsigned char **src = exr_image.tiles[it].images;
11587             (*out_rgba)[4 * idx + 0] =
11588                 reinterpret_cast<float **>(src)[chIdx][srcIdx];
11589             (*out_rgba)[4 * idx + 1] =
11590                 reinterpret_cast<float **>(src)[chIdx][srcIdx];
11591             (*out_rgba)[4 * idx + 2] =
11592                 reinterpret_cast<float **>(src)[chIdx][srcIdx];
11593             (*out_rgba)[4 * idx + 3] =
11594                 reinterpret_cast<float **>(src)[chIdx][srcIdx];
11595           }
11596         }
11597       }
11598     } else {
11599       for (int i = 0; i < exr_image.width * exr_image.height; i++) {
11600         const float val = reinterpret_cast<float **>(exr_image.images)[chIdx][i];
11601         (*out_rgba)[4 * i + 0] = val;
11602         (*out_rgba)[4 * i + 1] = val;
11603         (*out_rgba)[4 * i + 2] = val;
11604         (*out_rgba)[4 * i + 3] = val;
11605       }
11606     }
11607   } else {
11608     // Assume RGB(A)
11609 
11610     if (idxR == -1) {
11611       tinyexr::SetErrorMessage("R channel not found", err);
11612 
11613       FreeEXRHeader(&exr_header);
11614       FreeEXRImage(&exr_image);
11615       return TINYEXR_ERROR_INVALID_DATA;
11616     }
11617 
11618     if (idxG == -1) {
11619       tinyexr::SetErrorMessage("G channel not found", err);
11620       FreeEXRHeader(&exr_header);
11621       FreeEXRImage(&exr_image);
11622       return TINYEXR_ERROR_INVALID_DATA;
11623     }
11624 
11625     if (idxB == -1) {
11626       tinyexr::SetErrorMessage("B channel not found", err);
11627       FreeEXRHeader(&exr_header);
11628       FreeEXRImage(&exr_image);
11629       return TINYEXR_ERROR_INVALID_DATA;
11630     }
11631 
11632     (*out_rgba) = reinterpret_cast<float *>(
11633         malloc(4 * sizeof(float) * static_cast<size_t>(exr_image.width) *
11634                static_cast<size_t>(exr_image.height)));
11635     if (exr_header.tiled) {
11636       for (int it = 0; it < exr_image.num_tiles; it++) {
11637         for (int j = 0; j < exr_header.tile_size_y; j++) {
11638           for (int i = 0; i < exr_header.tile_size_x; i++) {
11639             const int ii =
11640                 exr_image.tiles[it].offset_x * exr_header.tile_size_x + i;
11641             const int jj =
11642                 exr_image.tiles[it].offset_y * exr_header.tile_size_y + j;
11643             const int idx = ii + jj * exr_image.width;
11644 
11645             // out of region check.
11646             if (ii >= exr_image.width) {
11647               continue;
11648             }
11649             if (jj >= exr_image.height) {
11650               continue;
11651             }
11652             const int srcIdx = i + j * exr_header.tile_size_x;
11653             unsigned char **src = exr_image.tiles[it].images;
11654             (*out_rgba)[4 * idx + 0] =
11655                 reinterpret_cast<float **>(src)[idxR][srcIdx];
11656             (*out_rgba)[4 * idx + 1] =
11657                 reinterpret_cast<float **>(src)[idxG][srcIdx];
11658             (*out_rgba)[4 * idx + 2] =
11659                 reinterpret_cast<float **>(src)[idxB][srcIdx];
11660             if (idxA != -1) {
11661               (*out_rgba)[4 * idx + 3] =
11662                   reinterpret_cast<float **>(src)[idxA][srcIdx];
11663             } else {
11664               (*out_rgba)[4 * idx + 3] = 1.0;
11665             }
11666           }
11667         }
11668       }
11669     } else {
11670       for (int i = 0; i < exr_image.width * exr_image.height; i++) {
11671         (*out_rgba)[4 * i + 0] =
11672             reinterpret_cast<float **>(exr_image.images)[idxR][i];
11673         (*out_rgba)[4 * i + 1] =
11674             reinterpret_cast<float **>(exr_image.images)[idxG][i];
11675         (*out_rgba)[4 * i + 2] =
11676             reinterpret_cast<float **>(exr_image.images)[idxB][i];
11677         if (idxA != -1) {
11678           (*out_rgba)[4 * i + 3] =
11679               reinterpret_cast<float **>(exr_image.images)[idxA][i];
11680         } else {
11681           (*out_rgba)[4 * i + 3] = 1.0;
11682         }
11683       }
11684     }
11685   }
11686 
11687   (*width) = exr_image.width;
11688   (*height) = exr_image.height;
11689 
11690   FreeEXRHeader(&exr_header);
11691   FreeEXRImage(&exr_image);
11692 
11693   return TINYEXR_SUCCESS;
11694 }
11695 
IsEXR(const char * filename)11696 int IsEXR(const char *filename) {
11697   EXRVersion exr_version;
11698 
11699   int ret = ParseEXRVersionFromFile(&exr_version, filename);
11700   if (ret != TINYEXR_SUCCESS) {
11701     return ret;
11702   }
11703 
11704   return TINYEXR_SUCCESS;
11705 }
11706 
ParseEXRHeaderFromMemory(EXRHeader * exr_header,const EXRVersion * version,const unsigned char * memory,size_t size,const char ** err)11707 int ParseEXRHeaderFromMemory(EXRHeader *exr_header, const EXRVersion *version,
11708                              const unsigned char *memory, size_t size,
11709                              const char **err) {
11710   if (memory == NULL || exr_header == NULL) {
11711     tinyexr::SetErrorMessage(
11712         "Invalid argument. `memory` or `exr_header` argument is null in "
11713         "ParseEXRHeaderFromMemory()",
11714         err);
11715 
11716     // Invalid argument
11717     return TINYEXR_ERROR_INVALID_ARGUMENT;
11718   }
11719 
11720   if (size < tinyexr::kEXRVersionSize) {
11721     tinyexr::SetErrorMessage("Insufficient header/data size.\n", err);
11722     return TINYEXR_ERROR_INVALID_DATA;
11723   }
11724 
11725   const unsigned char *marker = memory + tinyexr::kEXRVersionSize;
11726   size_t marker_size = size - tinyexr::kEXRVersionSize;
11727 
11728   tinyexr::HeaderInfo info;
11729   info.clear();
11730 
11731   std::string err_str;
11732   int ret = ParseEXRHeader(&info, NULL, version, &err_str, marker, marker_size);
11733 
11734   if (ret != TINYEXR_SUCCESS) {
11735     if (err && !err_str.empty()) {
11736       tinyexr::SetErrorMessage(err_str, err);
11737     }
11738   }
11739 
11740   ConvertHeader(exr_header, info);
11741 
11742   // transfoer `tiled` from version.
11743   exr_header->tiled = version->tiled;
11744 
11745   return ret;
11746 }
11747 
LoadEXRFromMemory(float ** out_rgba,int * width,int * height,const unsigned char * memory,size_t size,const char ** err)11748 int LoadEXRFromMemory(float **out_rgba, int *width, int *height,
11749                       const unsigned char *memory, size_t size,
11750                       const char **err) {
11751   if (out_rgba == NULL || memory == NULL) {
11752     tinyexr::SetErrorMessage("Invalid argument for LoadEXRFromMemory", err);
11753     return TINYEXR_ERROR_INVALID_ARGUMENT;
11754   }
11755 
11756   EXRVersion exr_version;
11757   EXRImage exr_image;
11758   EXRHeader exr_header;
11759 
11760   InitEXRHeader(&exr_header);
11761 
11762   int ret = ParseEXRVersionFromMemory(&exr_version, memory, size);
11763   if (ret != TINYEXR_SUCCESS) {
11764     std::stringstream ss;
11765     ss << "Failed to parse EXR version. code(" << ret << ")";
11766     tinyexr::SetErrorMessage(ss.str(), err);
11767     return ret;
11768   }
11769 
11770   ret = ParseEXRHeaderFromMemory(&exr_header, &exr_version, memory, size, err);
11771   if (ret != TINYEXR_SUCCESS) {
11772     return ret;
11773   }
11774 
11775   // Read HALF channel as FLOAT.
11776   for (int i = 0; i < exr_header.num_channels; i++) {
11777     if (exr_header.pixel_types[i] == TINYEXR_PIXELTYPE_HALF) {
11778       exr_header.requested_pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT;
11779     }
11780   }
11781 
11782   InitEXRImage(&exr_image);
11783   ret = LoadEXRImageFromMemory(&exr_image, &exr_header, memory, size, err);
11784   if (ret != TINYEXR_SUCCESS) {
11785     return ret;
11786   }
11787 
11788   // RGBA
11789   int idxR = -1;
11790   int idxG = -1;
11791   int idxB = -1;
11792   int idxA = -1;
11793   for (int c = 0; c < exr_header.num_channels; c++) {
11794     if (strcmp(exr_header.channels[c].name, "R") == 0) {
11795       idxR = c;
11796     } else if (strcmp(exr_header.channels[c].name, "G") == 0) {
11797       idxG = c;
11798     } else if (strcmp(exr_header.channels[c].name, "B") == 0) {
11799       idxB = c;
11800     } else if (strcmp(exr_header.channels[c].name, "A") == 0) {
11801       idxA = c;
11802     }
11803   }
11804 
11805   // TODO(syoyo): Refactor removing same code as used in LoadEXR().
11806   if (exr_header.num_channels == 1) {
11807     // Grayscale channel only.
11808 
11809     (*out_rgba) = reinterpret_cast<float *>(
11810         malloc(4 * sizeof(float) * static_cast<size_t>(exr_image.width) *
11811                static_cast<size_t>(exr_image.height)));
11812 
11813     if (exr_header.tiled) {
11814       for (int it = 0; it < exr_image.num_tiles; it++) {
11815         for (int j = 0; j < exr_header.tile_size_y; j++) {
11816           for (int i = 0; i < exr_header.tile_size_x; i++) {
11817             const int ii =
11818                 exr_image.tiles[it].offset_x * exr_header.tile_size_x + i;
11819             const int jj =
11820                 exr_image.tiles[it].offset_y * exr_header.tile_size_y + j;
11821             const int idx = ii + jj * exr_image.width;
11822 
11823             // out of region check.
11824             if (ii >= exr_image.width) {
11825               continue;
11826             }
11827             if (jj >= exr_image.height) {
11828               continue;
11829             }
11830             const int srcIdx = i + j * exr_header.tile_size_x;
11831             unsigned char **src = exr_image.tiles[it].images;
11832             (*out_rgba)[4 * idx + 0] =
11833                 reinterpret_cast<float **>(src)[0][srcIdx];
11834             (*out_rgba)[4 * idx + 1] =
11835                 reinterpret_cast<float **>(src)[0][srcIdx];
11836             (*out_rgba)[4 * idx + 2] =
11837                 reinterpret_cast<float **>(src)[0][srcIdx];
11838             (*out_rgba)[4 * idx + 3] =
11839                 reinterpret_cast<float **>(src)[0][srcIdx];
11840           }
11841         }
11842       }
11843     } else {
11844       for (int i = 0; i < exr_image.width * exr_image.height; i++) {
11845         const float val = reinterpret_cast<float **>(exr_image.images)[0][i];
11846         (*out_rgba)[4 * i + 0] = val;
11847         (*out_rgba)[4 * i + 1] = val;
11848         (*out_rgba)[4 * i + 2] = val;
11849         (*out_rgba)[4 * i + 3] = val;
11850       }
11851     }
11852 
11853   } else {
11854     // TODO(syoyo): Support non RGBA image.
11855 
11856     if (idxR == -1) {
11857       tinyexr::SetErrorMessage("R channel not found", err);
11858 
11859       // @todo { free exr_image }
11860       return TINYEXR_ERROR_INVALID_DATA;
11861     }
11862 
11863     if (idxG == -1) {
11864       tinyexr::SetErrorMessage("G channel not found", err);
11865       // @todo { free exr_image }
11866       return TINYEXR_ERROR_INVALID_DATA;
11867     }
11868 
11869     if (idxB == -1) {
11870       tinyexr::SetErrorMessage("B channel not found", err);
11871       // @todo { free exr_image }
11872       return TINYEXR_ERROR_INVALID_DATA;
11873     }
11874 
11875     (*out_rgba) = reinterpret_cast<float *>(
11876         malloc(4 * sizeof(float) * static_cast<size_t>(exr_image.width) *
11877                static_cast<size_t>(exr_image.height)));
11878 
11879     if (exr_header.tiled) {
11880       for (int it = 0; it < exr_image.num_tiles; it++) {
11881         for (int j = 0; j < exr_header.tile_size_y; j++)
11882           for (int i = 0; i < exr_header.tile_size_x; i++) {
11883             const int ii =
11884                 exr_image.tiles[it].offset_x * exr_header.tile_size_x + i;
11885             const int jj =
11886                 exr_image.tiles[it].offset_y * exr_header.tile_size_y + j;
11887             const int idx = ii + jj * exr_image.width;
11888 
11889             // out of region check.
11890             if (ii >= exr_image.width) {
11891               continue;
11892             }
11893             if (jj >= exr_image.height) {
11894               continue;
11895             }
11896             const int srcIdx = i + j * exr_header.tile_size_x;
11897             unsigned char **src = exr_image.tiles[it].images;
11898             (*out_rgba)[4 * idx + 0] =
11899                 reinterpret_cast<float **>(src)[idxR][srcIdx];
11900             (*out_rgba)[4 * idx + 1] =
11901                 reinterpret_cast<float **>(src)[idxG][srcIdx];
11902             (*out_rgba)[4 * idx + 2] =
11903                 reinterpret_cast<float **>(src)[idxB][srcIdx];
11904             if (idxA != -1) {
11905               (*out_rgba)[4 * idx + 3] =
11906                   reinterpret_cast<float **>(src)[idxA][srcIdx];
11907             } else {
11908               (*out_rgba)[4 * idx + 3] = 1.0;
11909             }
11910           }
11911       }
11912     } else {
11913       for (int i = 0; i < exr_image.width * exr_image.height; i++) {
11914         (*out_rgba)[4 * i + 0] =
11915             reinterpret_cast<float **>(exr_image.images)[idxR][i];
11916         (*out_rgba)[4 * i + 1] =
11917             reinterpret_cast<float **>(exr_image.images)[idxG][i];
11918         (*out_rgba)[4 * i + 2] =
11919             reinterpret_cast<float **>(exr_image.images)[idxB][i];
11920         if (idxA != -1) {
11921           (*out_rgba)[4 * i + 3] =
11922               reinterpret_cast<float **>(exr_image.images)[idxA][i];
11923         } else {
11924           (*out_rgba)[4 * i + 3] = 1.0;
11925         }
11926       }
11927     }
11928   }
11929 
11930   (*width) = exr_image.width;
11931   (*height) = exr_image.height;
11932 
11933   FreeEXRHeader(&exr_header);
11934   FreeEXRImage(&exr_image);
11935 
11936   return TINYEXR_SUCCESS;
11937 }
11938 
LoadEXRImageFromFile(EXRImage * exr_image,const EXRHeader * exr_header,const char * filename,const char ** err)11939 int LoadEXRImageFromFile(EXRImage *exr_image, const EXRHeader *exr_header,
11940                          const char *filename, const char **err) {
11941   if (exr_image == NULL) {
11942     tinyexr::SetErrorMessage("Invalid argument for LoadEXRImageFromFile", err);
11943     return TINYEXR_ERROR_INVALID_ARGUMENT;
11944   }
11945 
11946 #ifdef _WIN32
11947   FILE *fp = NULL;
11948   fopen_s(&fp, filename, "rb");
11949 #else
11950   FILE *fp = fopen(filename, "rb");
11951 #endif
11952   if (!fp) {
11953     tinyexr::SetErrorMessage("Cannot read file " + std::string(filename), err);
11954     return TINYEXR_ERROR_CANT_OPEN_FILE;
11955   }
11956 
11957   size_t filesize;
11958   // Compute size
11959   fseek(fp, 0, SEEK_END);
11960   filesize = static_cast<size_t>(ftell(fp));
11961   fseek(fp, 0, SEEK_SET);
11962 
11963   if (filesize < 16) {
11964     fclose(fp);
11965     tinyexr::SetErrorMessage("File size too short " + std::string(filename),
11966                              err);
11967     return TINYEXR_ERROR_INVALID_FILE;
11968   }
11969 
11970   std::vector<unsigned char> buf(filesize);  // @todo { use mmap }
11971   {
11972     size_t ret;
11973     ret = fread(&buf[0], 1, filesize, fp);
11974     TEXR_ASSERT(ret == filesize);
11975     fclose(fp);
11976     (void)ret;
11977   }
11978 
11979   return LoadEXRImageFromMemory(exr_image, exr_header, &buf.at(0), filesize,
11980                                 err);
11981 }
11982 
LoadEXRImageFromMemory(EXRImage * exr_image,const EXRHeader * exr_header,const unsigned char * memory,const size_t size,const char ** err)11983 int LoadEXRImageFromMemory(EXRImage *exr_image, const EXRHeader *exr_header,
11984                            const unsigned char *memory, const size_t size,
11985                            const char **err) {
11986   if (exr_image == NULL || memory == NULL ||
11987       (size < tinyexr::kEXRVersionSize)) {
11988     tinyexr::SetErrorMessage("Invalid argument for LoadEXRImageFromMemory",
11989                              err);
11990     return TINYEXR_ERROR_INVALID_ARGUMENT;
11991   }
11992 
11993   if (exr_header->header_len == 0) {
11994     tinyexr::SetErrorMessage("EXRHeader variable is not initialized.", err);
11995     return TINYEXR_ERROR_INVALID_ARGUMENT;
11996   }
11997 
11998   const unsigned char *head = memory;
11999   const unsigned char *marker = reinterpret_cast<const unsigned char *>(
12000       memory + exr_header->header_len +
12001       8);  // +8 for magic number + version header.
12002   return tinyexr::DecodeEXRImage(exr_image, exr_header, head, marker, size,
12003                                  err);
12004 }
12005 
SaveEXRImageToMemory(const EXRImage * exr_image,const EXRHeader * exr_header,unsigned char ** memory_out,const char ** err)12006 size_t SaveEXRImageToMemory(const EXRImage *exr_image,
12007                             const EXRHeader *exr_header,
12008                             unsigned char **memory_out, const char **err) {
12009   if (exr_image == NULL || memory_out == NULL ||
12010       exr_header->compression_type < 0) {
12011     tinyexr::SetErrorMessage("Invalid argument for SaveEXRImageToMemory", err);
12012     return 0;
12013   }
12014 
12015 #if !TINYEXR_USE_PIZ
12016   if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_PIZ) {
12017     tinyexr::SetErrorMessage("PIZ compression is not supported in this build",
12018                              err);
12019     return 0;
12020   }
12021 #endif
12022 
12023 #if !TINYEXR_USE_ZFP
12024   if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) {
12025     tinyexr::SetErrorMessage("ZFP compression is not supported in this build",
12026                              err);
12027     return 0;
12028   }
12029 #endif
12030 
12031 #if TINYEXR_USE_ZFP
12032   for (size_t i = 0; i < static_cast<size_t>(exr_header->num_channels); i++) {
12033     if (exr_header->requested_pixel_types[i] != TINYEXR_PIXELTYPE_FLOAT) {
12034       tinyexr::SetErrorMessage("Pixel type must be FLOAT for ZFP compression",
12035                                err);
12036       return 0;
12037     }
12038   }
12039 #endif
12040 
12041   std::vector<unsigned char> memory;
12042 
12043   // Header
12044   {
12045     const char header[] = {0x76, 0x2f, 0x31, 0x01};
12046     memory.insert(memory.end(), header, header + 4);
12047   }
12048 
12049   // Version, scanline.
12050   {
12051     char marker[] = {2, 0, 0, 0};
12052     /* @todo
12053     if (exr_header->tiled) {
12054       marker[1] |= 0x2;
12055     }
12056     if (exr_header->long_name) {
12057       marker[1] |= 0x4;
12058     }
12059     if (exr_header->non_image) {
12060       marker[1] |= 0x8;
12061     }
12062     if (exr_header->multipart) {
12063       marker[1] |= 0x10;
12064     }
12065     */
12066     memory.insert(memory.end(), marker, marker + 4);
12067   }
12068 
12069   int num_scanlines = 1;
12070   if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZIP) {
12071     num_scanlines = 16;
12072   } else if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_PIZ) {
12073     num_scanlines = 32;
12074   } else if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) {
12075     num_scanlines = 16;
12076   }
12077 
12078   // Write attributes.
12079   std::vector<tinyexr::ChannelInfo> channels;
12080   {
12081     std::vector<unsigned char> data;
12082 
12083     for (int c = 0; c < exr_header->num_channels; c++) {
12084       tinyexr::ChannelInfo info;
12085       info.p_linear = 0;
12086       info.pixel_type = exr_header->requested_pixel_types[c];
12087       info.x_sampling = 1;
12088       info.y_sampling = 1;
12089       info.name = std::string(exr_header->channels[c].name);
12090       channels.push_back(info);
12091     }
12092 
12093     tinyexr::WriteChannelInfo(data, channels);
12094 
12095     tinyexr::WriteAttributeToMemory(&memory, "channels", "chlist", &data.at(0),
12096                                     static_cast<int>(data.size()));
12097   }
12098 
12099   {
12100     int comp = exr_header->compression_type;
12101     tinyexr::swap4(reinterpret_cast<unsigned int *>(&comp));
12102     tinyexr::WriteAttributeToMemory(
12103         &memory, "compression", "compression",
12104         reinterpret_cast<const unsigned char *>(&comp), 1);
12105   }
12106 
12107   {
12108     int data[4] = {0, 0, exr_image->width - 1, exr_image->height - 1};
12109     tinyexr::swap4(reinterpret_cast<unsigned int *>(&data[0]));
12110     tinyexr::swap4(reinterpret_cast<unsigned int *>(&data[1]));
12111     tinyexr::swap4(reinterpret_cast<unsigned int *>(&data[2]));
12112     tinyexr::swap4(reinterpret_cast<unsigned int *>(&data[3]));
12113     tinyexr::WriteAttributeToMemory(
12114         &memory, "dataWindow", "box2i",
12115         reinterpret_cast<const unsigned char *>(data), sizeof(int) * 4);
12116     tinyexr::WriteAttributeToMemory(
12117         &memory, "displayWindow", "box2i",
12118         reinterpret_cast<const unsigned char *>(data), sizeof(int) * 4);
12119   }
12120 
12121   {
12122     unsigned char line_order = 0;  // @fixme { read line_order from EXRHeader }
12123     tinyexr::WriteAttributeToMemory(&memory, "lineOrder", "lineOrder",
12124                                     &line_order, 1);
12125   }
12126 
12127   {
12128     float aspectRatio = 1.0f;
12129     tinyexr::swap4(reinterpret_cast<unsigned int *>(&aspectRatio));
12130     tinyexr::WriteAttributeToMemory(
12131         &memory, "pixelAspectRatio", "float",
12132         reinterpret_cast<const unsigned char *>(&aspectRatio), sizeof(float));
12133   }
12134 
12135   {
12136     float center[2] = {0.0f, 0.0f};
12137     tinyexr::swap4(reinterpret_cast<unsigned int *>(&center[0]));
12138     tinyexr::swap4(reinterpret_cast<unsigned int *>(&center[1]));
12139     tinyexr::WriteAttributeToMemory(
12140         &memory, "screenWindowCenter", "v2f",
12141         reinterpret_cast<const unsigned char *>(center), 2 * sizeof(float));
12142   }
12143 
12144   {
12145     float w = static_cast<float>(exr_image->width);
12146     tinyexr::swap4(reinterpret_cast<unsigned int *>(&w));
12147     tinyexr::WriteAttributeToMemory(&memory, "screenWindowWidth", "float",
12148                                     reinterpret_cast<const unsigned char *>(&w),
12149                                     sizeof(float));
12150   }
12151 
12152   // Custom attributes
12153   if (exr_header->num_custom_attributes > 0) {
12154     for (int i = 0; i < exr_header->num_custom_attributes; i++) {
12155       tinyexr::WriteAttributeToMemory(
12156           &memory, exr_header->custom_attributes[i].name,
12157           exr_header->custom_attributes[i].type,
12158           reinterpret_cast<const unsigned char *>(
12159               exr_header->custom_attributes[i].value),
12160           exr_header->custom_attributes[i].size);
12161     }
12162   }
12163 
12164   {  // end of header
12165     unsigned char e = 0;
12166     memory.push_back(e);
12167   }
12168 
12169   int num_blocks = exr_image->height / num_scanlines;
12170   if (num_blocks * num_scanlines < exr_image->height) {
12171     num_blocks++;
12172   }
12173 
12174   std::vector<tinyexr::tinyexr_uint64> offsets(static_cast<size_t>(num_blocks));
12175 
12176   size_t headerSize = memory.size();
12177   tinyexr::tinyexr_uint64 offset =
12178       headerSize +
12179       static_cast<size_t>(num_blocks) *
12180           sizeof(
12181               tinyexr::tinyexr_int64);  // sizeof(header) + sizeof(offsetTable)
12182 
12183   std::vector<std::vector<unsigned char> > data_list(
12184       static_cast<size_t>(num_blocks));
12185   std::vector<size_t> channel_offset_list(
12186       static_cast<size_t>(exr_header->num_channels));
12187 
12188   int pixel_data_size = 0;
12189   size_t channel_offset = 0;
12190   for (size_t c = 0; c < static_cast<size_t>(exr_header->num_channels); c++) {
12191     channel_offset_list[c] = channel_offset;
12192     if (exr_header->requested_pixel_types[c] == TINYEXR_PIXELTYPE_HALF) {
12193       pixel_data_size += sizeof(unsigned short);
12194       channel_offset += sizeof(unsigned short);
12195     } else if (exr_header->requested_pixel_types[c] ==
12196                TINYEXR_PIXELTYPE_FLOAT) {
12197       pixel_data_size += sizeof(float);
12198       channel_offset += sizeof(float);
12199     } else if (exr_header->requested_pixel_types[c] == TINYEXR_PIXELTYPE_UINT) {
12200       pixel_data_size += sizeof(unsigned int);
12201       channel_offset += sizeof(unsigned int);
12202     } else {
12203       TEXR_ASSERT(0);
12204     }
12205   }
12206 
12207 #if TINYEXR_USE_ZFP
12208   tinyexr::ZFPCompressionParam zfp_compression_param;
12209 
12210   // Use ZFP compression parameter from custom attributes(if such a parameter
12211   // exists)
12212   {
12213     bool ret = tinyexr::FindZFPCompressionParam(
12214         &zfp_compression_param, exr_header->custom_attributes,
12215         exr_header->num_custom_attributes);
12216 
12217     if (!ret) {
12218       // Use predefined compression parameter.
12219       zfp_compression_param.type = 0;
12220       zfp_compression_param.rate = 2;
12221     }
12222   }
12223 #endif
12224 
12225   // TOOD(LTE): C++11 thread
12226 
12227 // Use signed int since some OpenMP compiler doesn't allow unsigned type for
12228 // `parallel for`
12229 #if TINYEXR_USE_OPENMP
12230 #pragma omp parallel for
12231 #endif
12232   for (int i = 0; i < num_blocks; i++) {
12233     size_t ii = static_cast<size_t>(i);
12234     int start_y = num_scanlines * i;
12235     int endY = (std::min)(num_scanlines * (i + 1), exr_image->height);
12236     int h = endY - start_y;
12237 
12238     std::vector<unsigned char> buf(
12239         static_cast<size_t>(exr_image->width * h * pixel_data_size));
12240 
12241     for (size_t c = 0; c < static_cast<size_t>(exr_header->num_channels); c++) {
12242       if (exr_header->pixel_types[c] == TINYEXR_PIXELTYPE_HALF) {
12243         if (exr_header->requested_pixel_types[c] == TINYEXR_PIXELTYPE_FLOAT) {
12244           for (int y = 0; y < h; y++) {
12245             // Assume increasing Y
12246             float *line_ptr = reinterpret_cast<float *>(&buf.at(
12247                 static_cast<size_t>(pixel_data_size * y * exr_image->width) +
12248                 channel_offset_list[c] *
12249                     static_cast<size_t>(exr_image->width)));
12250             for (int x = 0; x < exr_image->width; x++) {
12251               tinyexr::FP16 h16;
12252               h16.u = reinterpret_cast<unsigned short **>(
12253                   exr_image->images)[c][(y + start_y) * exr_image->width + x];
12254 
12255               tinyexr::FP32 f32 = half_to_float(h16);
12256 
12257               tinyexr::swap4(reinterpret_cast<unsigned int *>(&f32.f));
12258 
12259               // line_ptr[x] = f32.f;
12260               tinyexr::cpy4(line_ptr + x, &(f32.f));
12261             }
12262           }
12263         } else if (exr_header->requested_pixel_types[c] ==
12264                    TINYEXR_PIXELTYPE_HALF) {
12265           for (int y = 0; y < h; y++) {
12266             // Assume increasing Y
12267             unsigned short *line_ptr = reinterpret_cast<unsigned short *>(
12268                 &buf.at(static_cast<size_t>(pixel_data_size * y *
12269                                             exr_image->width) +
12270                         channel_offset_list[c] *
12271                             static_cast<size_t>(exr_image->width)));
12272             for (int x = 0; x < exr_image->width; x++) {
12273               unsigned short val = reinterpret_cast<unsigned short **>(
12274                   exr_image->images)[c][(y + start_y) * exr_image->width + x];
12275 
12276               tinyexr::swap2(&val);
12277 
12278               // line_ptr[x] = val;
12279               tinyexr::cpy2(line_ptr + x, &val);
12280             }
12281           }
12282         } else {
12283           TEXR_ASSERT(0);
12284         }
12285 
12286       } else if (exr_header->pixel_types[c] == TINYEXR_PIXELTYPE_FLOAT) {
12287         if (exr_header->requested_pixel_types[c] == TINYEXR_PIXELTYPE_HALF) {
12288           for (int y = 0; y < h; y++) {
12289             // Assume increasing Y
12290             unsigned short *line_ptr = reinterpret_cast<unsigned short *>(
12291                 &buf.at(static_cast<size_t>(pixel_data_size * y *
12292                                             exr_image->width) +
12293                         channel_offset_list[c] *
12294                             static_cast<size_t>(exr_image->width)));
12295             for (int x = 0; x < exr_image->width; x++) {
12296               tinyexr::FP32 f32;
12297               f32.f = reinterpret_cast<float **>(
12298                   exr_image->images)[c][(y + start_y) * exr_image->width + x];
12299 
12300               tinyexr::FP16 h16;
12301               h16 = float_to_half_full(f32);
12302 
12303               tinyexr::swap2(reinterpret_cast<unsigned short *>(&h16.u));
12304 
12305               // line_ptr[x] = h16.u;
12306               tinyexr::cpy2(line_ptr + x, &(h16.u));
12307             }
12308           }
12309         } else if (exr_header->requested_pixel_types[c] ==
12310                    TINYEXR_PIXELTYPE_FLOAT) {
12311           for (int y = 0; y < h; y++) {
12312             // Assume increasing Y
12313             float *line_ptr = reinterpret_cast<float *>(&buf.at(
12314                 static_cast<size_t>(pixel_data_size * y * exr_image->width) +
12315                 channel_offset_list[c] *
12316                     static_cast<size_t>(exr_image->width)));
12317             for (int x = 0; x < exr_image->width; x++) {
12318               float val = reinterpret_cast<float **>(
12319                   exr_image->images)[c][(y + start_y) * exr_image->width + x];
12320 
12321               tinyexr::swap4(reinterpret_cast<unsigned int *>(&val));
12322 
12323               // line_ptr[x] = val;
12324               tinyexr::cpy4(line_ptr + x, &val);
12325             }
12326           }
12327         } else {
12328           TEXR_ASSERT(0);
12329         }
12330       } else if (exr_header->pixel_types[c] == TINYEXR_PIXELTYPE_UINT) {
12331         for (int y = 0; y < h; y++) {
12332           // Assume increasing Y
12333           unsigned int *line_ptr = reinterpret_cast<unsigned int *>(&buf.at(
12334               static_cast<size_t>(pixel_data_size * y * exr_image->width) +
12335               channel_offset_list[c] * static_cast<size_t>(exr_image->width)));
12336           for (int x = 0; x < exr_image->width; x++) {
12337             unsigned int val = reinterpret_cast<unsigned int **>(
12338                 exr_image->images)[c][(y + start_y) * exr_image->width + x];
12339 
12340             tinyexr::swap4(&val);
12341 
12342             // line_ptr[x] = val;
12343             tinyexr::cpy4(line_ptr + x, &val);
12344           }
12345         }
12346       }
12347     }
12348 
12349     if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_NONE) {
12350       // 4 byte: scan line
12351       // 4 byte: data size
12352       // ~     : pixel data(uncompressed)
12353       std::vector<unsigned char> header(8);
12354       unsigned int data_len = static_cast<unsigned int>(buf.size());
12355       memcpy(&header.at(0), &start_y, sizeof(int));
12356       memcpy(&header.at(4), &data_len, sizeof(unsigned int));
12357 
12358       tinyexr::swap4(reinterpret_cast<unsigned int *>(&header.at(0)));
12359       tinyexr::swap4(reinterpret_cast<unsigned int *>(&header.at(4)));
12360 
12361       data_list[ii].insert(data_list[ii].end(), header.begin(), header.end());
12362       data_list[ii].insert(data_list[ii].end(), buf.begin(),
12363                            buf.begin() + data_len);
12364 
12365     } else if ((exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZIPS) ||
12366                (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZIP)) {
12367 #if TINYEXR_USE_MINIZ
12368       std::vector<unsigned char> block(tinyexr::miniz::mz_compressBound(
12369           static_cast<unsigned long>(buf.size())));
12370 #else
12371       std::vector<unsigned char> block(
12372           compressBound(static_cast<uLong>(buf.size())));
12373 #endif
12374       tinyexr::tinyexr_uint64 outSize = block.size();
12375 
12376       tinyexr::CompressZip(&block.at(0), outSize,
12377                            reinterpret_cast<const unsigned char *>(&buf.at(0)),
12378                            static_cast<unsigned long>(buf.size()));
12379 
12380       // 4 byte: scan line
12381       // 4 byte: data size
12382       // ~     : pixel data(compressed)
12383       std::vector<unsigned char> header(8);
12384       unsigned int data_len = static_cast<unsigned int>(outSize);  // truncate
12385       memcpy(&header.at(0), &start_y, sizeof(int));
12386       memcpy(&header.at(4), &data_len, sizeof(unsigned int));
12387 
12388       tinyexr::swap4(reinterpret_cast<unsigned int *>(&header.at(0)));
12389       tinyexr::swap4(reinterpret_cast<unsigned int *>(&header.at(4)));
12390 
12391       data_list[ii].insert(data_list[ii].end(), header.begin(), header.end());
12392       data_list[ii].insert(data_list[ii].end(), block.begin(),
12393                            block.begin() + data_len);
12394 
12395     } else if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_RLE) {
12396       // (buf.size() * 3) / 2 would be enough.
12397       std::vector<unsigned char> block((buf.size() * 3) / 2);
12398 
12399       tinyexr::tinyexr_uint64 outSize = block.size();
12400 
12401       tinyexr::CompressRle(&block.at(0), outSize,
12402                            reinterpret_cast<const unsigned char *>(&buf.at(0)),
12403                            static_cast<unsigned long>(buf.size()));
12404 
12405       // 4 byte: scan line
12406       // 4 byte: data size
12407       // ~     : pixel data(compressed)
12408       std::vector<unsigned char> header(8);
12409       unsigned int data_len = static_cast<unsigned int>(outSize);  // truncate
12410       memcpy(&header.at(0), &start_y, sizeof(int));
12411       memcpy(&header.at(4), &data_len, sizeof(unsigned int));
12412 
12413       tinyexr::swap4(reinterpret_cast<unsigned int *>(&header.at(0)));
12414       tinyexr::swap4(reinterpret_cast<unsigned int *>(&header.at(4)));
12415 
12416       data_list[ii].insert(data_list[ii].end(), header.begin(), header.end());
12417       data_list[ii].insert(data_list[ii].end(), block.begin(),
12418                            block.begin() + data_len);
12419 
12420     } else if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_PIZ) {
12421 #if TINYEXR_USE_PIZ
12422       unsigned int bufLen =
12423           8192 + static_cast<unsigned int>(
12424                      2 * static_cast<unsigned int>(
12425                              buf.size()));  // @fixme { compute good bound. }
12426       std::vector<unsigned char> block(bufLen);
12427       unsigned int outSize = static_cast<unsigned int>(block.size());
12428 
12429       CompressPiz(&block.at(0), &outSize,
12430                   reinterpret_cast<const unsigned char *>(&buf.at(0)),
12431                   buf.size(), channels, exr_image->width, h);
12432 
12433       // 4 byte: scan line
12434       // 4 byte: data size
12435       // ~     : pixel data(compressed)
12436       std::vector<unsigned char> header(8);
12437       unsigned int data_len = outSize;
12438       memcpy(&header.at(0), &start_y, sizeof(int));
12439       memcpy(&header.at(4), &data_len, sizeof(unsigned int));
12440 
12441       tinyexr::swap4(reinterpret_cast<unsigned int *>(&header.at(0)));
12442       tinyexr::swap4(reinterpret_cast<unsigned int *>(&header.at(4)));
12443 
12444       data_list[ii].insert(data_list[ii].end(), header.begin(), header.end());
12445       data_list[ii].insert(data_list[ii].end(), block.begin(),
12446                            block.begin() + data_len);
12447 
12448 #else
12449       TEXR_ASSERT(0);
12450 #endif
12451     } else if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) {
12452 #if TINYEXR_USE_ZFP
12453       std::vector<unsigned char> block;
12454       unsigned int outSize;
12455 
12456       tinyexr::CompressZfp(
12457           &block, &outSize, reinterpret_cast<const float *>(&buf.at(0)),
12458           exr_image->width, h, exr_header->num_channels, zfp_compression_param);
12459 
12460       // 4 byte: scan line
12461       // 4 byte: data size
12462       // ~     : pixel data(compressed)
12463       std::vector<unsigned char> header(8);
12464       unsigned int data_len = outSize;
12465       memcpy(&header.at(0), &start_y, sizeof(int));
12466       memcpy(&header.at(4), &data_len, sizeof(unsigned int));
12467 
12468       tinyexr::swap4(reinterpret_cast<unsigned int *>(&header.at(0)));
12469       tinyexr::swap4(reinterpret_cast<unsigned int *>(&header.at(4)));
12470 
12471       data_list[ii].insert(data_list[ii].end(), header.begin(), header.end());
12472       data_list[ii].insert(data_list[ii].end(), block.begin(),
12473                            block.begin() + data_len);
12474 
12475 #else
12476       TEXR_ASSERT(0);
12477 #endif
12478     } else {
12479       TEXR_ASSERT(0);
12480     }
12481   }  // omp parallel
12482 
12483   for (size_t i = 0; i < static_cast<size_t>(num_blocks); i++) {
12484     offsets[i] = offset;
12485     tinyexr::swap8(reinterpret_cast<tinyexr::tinyexr_uint64 *>(&offsets[i]));
12486     offset += data_list[i].size();
12487   }
12488 
12489   size_t totalSize = static_cast<size_t>(offset);
12490   {
12491     memory.insert(
12492         memory.end(), reinterpret_cast<unsigned char *>(&offsets.at(0)),
12493         reinterpret_cast<unsigned char *>(&offsets.at(0)) +
12494             sizeof(tinyexr::tinyexr_uint64) * static_cast<size_t>(num_blocks));
12495   }
12496 
12497   if (memory.size() == 0) {
12498     tinyexr::SetErrorMessage("Output memory size is zero", err);
12499     return 0;
12500   }
12501 
12502   (*memory_out) = static_cast<unsigned char *>(malloc(totalSize));
12503   memcpy((*memory_out), &memory.at(0), memory.size());
12504   unsigned char *memory_ptr = *memory_out + memory.size();
12505 
12506   for (size_t i = 0; i < static_cast<size_t>(num_blocks); i++) {
12507     memcpy(memory_ptr, &data_list[i].at(0), data_list[i].size());
12508     memory_ptr += data_list[i].size();
12509   }
12510 
12511   return totalSize;  // OK
12512 }
12513 
SaveEXRImageToFile(const EXRImage * exr_image,const EXRHeader * exr_header,const char * filename,const char ** err)12514 int SaveEXRImageToFile(const EXRImage *exr_image, const EXRHeader *exr_header,
12515                        const char *filename, const char **err) {
12516   if (exr_image == NULL || filename == NULL ||
12517       exr_header->compression_type < 0) {
12518     tinyexr::SetErrorMessage("Invalid argument for SaveEXRImageToFile", err);
12519     return TINYEXR_ERROR_INVALID_ARGUMENT;
12520   }
12521 
12522 #if !TINYEXR_USE_PIZ
12523   if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_PIZ) {
12524     tinyexr::SetErrorMessage("PIZ compression is not supported in this build",
12525                              err);
12526     return TINYEXR_ERROR_UNSUPPORTED_FEATURE;
12527   }
12528 #endif
12529 
12530 #if !TINYEXR_USE_ZFP
12531   if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) {
12532     tinyexr::SetErrorMessage("ZFP compression is not supported in this build",
12533                              err);
12534     return TINYEXR_ERROR_UNSUPPORTED_FEATURE;
12535   }
12536 #endif
12537 
12538 #ifdef _WIN32
12539   FILE *fp = NULL;
12540   fopen_s(&fp, filename, "wb");
12541 #else
12542   FILE *fp = fopen(filename, "wb");
12543 #endif
12544   if (!fp) {
12545     tinyexr::SetErrorMessage("Cannot write a file", err);
12546     return TINYEXR_ERROR_CANT_WRITE_FILE;
12547   }
12548 
12549   unsigned char *mem = NULL;
12550   size_t mem_size = SaveEXRImageToMemory(exr_image, exr_header, &mem, err);
12551   if (mem_size == 0) {
12552     fclose(fp);
12553     return TINYEXR_ERROR_SERIALZATION_FAILED;
12554   }
12555 
12556   size_t written_size = 0;
12557   if ((mem_size > 0) && mem) {
12558     written_size = fwrite(mem, 1, mem_size, fp);
12559   }
12560   free(mem);
12561 
12562   fclose(fp);
12563 
12564   if (written_size != mem_size) {
12565     tinyexr::SetErrorMessage("Cannot write a file", err);
12566     return TINYEXR_ERROR_CANT_WRITE_FILE;
12567   }
12568 
12569   return TINYEXR_SUCCESS;
12570 }
12571 
LoadDeepEXR(DeepImage * deep_image,const char * filename,const char ** err)12572 int LoadDeepEXR(DeepImage *deep_image, const char *filename, const char **err) {
12573   if (deep_image == NULL) {
12574     tinyexr::SetErrorMessage("Invalid argument for LoadDeepEXR", err);
12575     return TINYEXR_ERROR_INVALID_ARGUMENT;
12576   }
12577 
12578 #ifdef _MSC_VER
12579   FILE *fp = NULL;
12580   errno_t errcode = fopen_s(&fp, filename, "rb");
12581   if ((0 != errcode) || (!fp)) {
12582     tinyexr::SetErrorMessage("Cannot read a file " + std::string(filename),
12583                              err);
12584     return TINYEXR_ERROR_CANT_OPEN_FILE;
12585   }
12586 #else
12587   FILE *fp = fopen(filename, "rb");
12588   if (!fp) {
12589     tinyexr::SetErrorMessage("Cannot read a file " + std::string(filename),
12590                              err);
12591     return TINYEXR_ERROR_CANT_OPEN_FILE;
12592   }
12593 #endif
12594 
12595   size_t filesize;
12596   // Compute size
12597   fseek(fp, 0, SEEK_END);
12598   filesize = static_cast<size_t>(ftell(fp));
12599   fseek(fp, 0, SEEK_SET);
12600 
12601   if (filesize == 0) {
12602     fclose(fp);
12603     tinyexr::SetErrorMessage("File size is zero : " + std::string(filename),
12604                              err);
12605     return TINYEXR_ERROR_INVALID_FILE;
12606   }
12607 
12608   std::vector<char> buf(filesize);  // @todo { use mmap }
12609   {
12610     size_t ret;
12611     ret = fread(&buf[0], 1, filesize, fp);
12612     TEXR_ASSERT(ret == filesize);
12613     (void)ret;
12614   }
12615   fclose(fp);
12616 
12617   const char *head = &buf[0];
12618   const char *marker = &buf[0];
12619 
12620   // Header check.
12621   {
12622     const char header[] = {0x76, 0x2f, 0x31, 0x01};
12623 
12624     if (memcmp(marker, header, 4) != 0) {
12625       tinyexr::SetErrorMessage("Invalid magic number", err);
12626       return TINYEXR_ERROR_INVALID_MAGIC_NUMBER;
12627     }
12628     marker += 4;
12629   }
12630 
12631   // Version, scanline.
12632   {
12633     // ver 2.0, scanline, deep bit on(0x800)
12634     // must be [2, 0, 0, 0]
12635     if (marker[0] != 2 || marker[1] != 8 || marker[2] != 0 || marker[3] != 0) {
12636       tinyexr::SetErrorMessage("Unsupported version or scanline", err);
12637       return TINYEXR_ERROR_UNSUPPORTED_FORMAT;
12638     }
12639 
12640     marker += 4;
12641   }
12642 
12643   int dx = -1;
12644   int dy = -1;
12645   int dw = -1;
12646   int dh = -1;
12647   int num_scanline_blocks = 1;  // 16 for ZIP compression.
12648   int compression_type = -1;
12649   int num_channels = -1;
12650   std::vector<tinyexr::ChannelInfo> channels;
12651 
12652   // Read attributes
12653   size_t size = filesize - tinyexr::kEXRVersionSize;
12654   for (;;) {
12655     if (0 == size) {
12656       return TINYEXR_ERROR_INVALID_DATA;
12657     } else if (marker[0] == '\0') {
12658       marker++;
12659       size--;
12660       break;
12661     }
12662 
12663     std::string attr_name;
12664     std::string attr_type;
12665     std::vector<unsigned char> data;
12666     size_t marker_size;
12667     if (!tinyexr::ReadAttribute(&attr_name, &attr_type, &data, &marker_size,
12668                                 marker, size)) {
12669       std::stringstream ss;
12670       ss << "Failed to parse attribute\n";
12671       tinyexr::SetErrorMessage(ss.str(), err);
12672       return TINYEXR_ERROR_INVALID_DATA;
12673     }
12674     marker += marker_size;
12675     size -= marker_size;
12676 
12677     if (attr_name.compare("compression") == 0) {
12678       compression_type = data[0];
12679       if (compression_type > TINYEXR_COMPRESSIONTYPE_PIZ) {
12680         std::stringstream ss;
12681         ss << "Unsupported compression type : " << compression_type;
12682         tinyexr::SetErrorMessage(ss.str(), err);
12683         return TINYEXR_ERROR_UNSUPPORTED_FORMAT;
12684       }
12685 
12686       if (compression_type == TINYEXR_COMPRESSIONTYPE_ZIP) {
12687         num_scanline_blocks = 16;
12688       }
12689 
12690     } else if (attr_name.compare("channels") == 0) {
12691       // name: zero-terminated string, from 1 to 255 bytes long
12692       // pixel type: int, possible values are: UINT = 0 HALF = 1 FLOAT = 2
12693       // pLinear: unsigned char, possible values are 0 and 1
12694       // reserved: three chars, should be zero
12695       // xSampling: int
12696       // ySampling: int
12697 
12698       if (!tinyexr::ReadChannelInfo(channels, data)) {
12699         tinyexr::SetErrorMessage("Failed to parse channel info", err);
12700         return TINYEXR_ERROR_INVALID_DATA;
12701       }
12702 
12703       num_channels = static_cast<int>(channels.size());
12704 
12705       if (num_channels < 1) {
12706         tinyexr::SetErrorMessage("Invalid channels format", err);
12707         return TINYEXR_ERROR_INVALID_DATA;
12708       }
12709 
12710     } else if (attr_name.compare("dataWindow") == 0) {
12711       memcpy(&dx, &data.at(0), sizeof(int));
12712       memcpy(&dy, &data.at(4), sizeof(int));
12713       memcpy(&dw, &data.at(8), sizeof(int));
12714       memcpy(&dh, &data.at(12), sizeof(int));
12715       tinyexr::swap4(reinterpret_cast<unsigned int *>(&dx));
12716       tinyexr::swap4(reinterpret_cast<unsigned int *>(&dy));
12717       tinyexr::swap4(reinterpret_cast<unsigned int *>(&dw));
12718       tinyexr::swap4(reinterpret_cast<unsigned int *>(&dh));
12719 
12720     } else if (attr_name.compare("displayWindow") == 0) {
12721       int x;
12722       int y;
12723       int w;
12724       int h;
12725       memcpy(&x, &data.at(0), sizeof(int));
12726       memcpy(&y, &data.at(4), sizeof(int));
12727       memcpy(&w, &data.at(8), sizeof(int));
12728       memcpy(&h, &data.at(12), sizeof(int));
12729       tinyexr::swap4(reinterpret_cast<unsigned int *>(&x));
12730       tinyexr::swap4(reinterpret_cast<unsigned int *>(&y));
12731       tinyexr::swap4(reinterpret_cast<unsigned int *>(&w));
12732       tinyexr::swap4(reinterpret_cast<unsigned int *>(&h));
12733     }
12734   }
12735 
12736   TEXR_ASSERT(dx >= 0);
12737   TEXR_ASSERT(dy >= 0);
12738   TEXR_ASSERT(dw >= 0);
12739   TEXR_ASSERT(dh >= 0);
12740   TEXR_ASSERT(num_channels >= 1);
12741 
12742   int data_width = dw - dx + 1;
12743   int data_height = dh - dy + 1;
12744 
12745   std::vector<float> image(
12746       static_cast<size_t>(data_width * data_height * 4));  // 4 = RGBA
12747 
12748   // Read offset tables.
12749   int num_blocks = data_height / num_scanline_blocks;
12750   if (num_blocks * num_scanline_blocks < data_height) {
12751     num_blocks++;
12752   }
12753 
12754   std::vector<tinyexr::tinyexr_int64> offsets(static_cast<size_t>(num_blocks));
12755 
12756   for (size_t y = 0; y < static_cast<size_t>(num_blocks); y++) {
12757     tinyexr::tinyexr_int64 offset;
12758     memcpy(&offset, marker, sizeof(tinyexr::tinyexr_int64));
12759     tinyexr::swap8(reinterpret_cast<tinyexr::tinyexr_uint64 *>(&offset));
12760     marker += sizeof(tinyexr::tinyexr_int64);  // = 8
12761     offsets[y] = offset;
12762   }
12763 
12764 #if TINYEXR_USE_PIZ
12765   if ((compression_type == TINYEXR_COMPRESSIONTYPE_NONE) ||
12766       (compression_type == TINYEXR_COMPRESSIONTYPE_RLE) ||
12767       (compression_type == TINYEXR_COMPRESSIONTYPE_ZIPS) ||
12768       (compression_type == TINYEXR_COMPRESSIONTYPE_ZIP) ||
12769       (compression_type == TINYEXR_COMPRESSIONTYPE_PIZ)) {
12770 #else
12771   if ((compression_type == TINYEXR_COMPRESSIONTYPE_NONE) ||
12772       (compression_type == TINYEXR_COMPRESSIONTYPE_RLE) ||
12773       (compression_type == TINYEXR_COMPRESSIONTYPE_ZIPS) ||
12774       (compression_type == TINYEXR_COMPRESSIONTYPE_ZIP)) {
12775 #endif
12776     // OK
12777   } else {
12778     tinyexr::SetErrorMessage("Unsupported compression format", err);
12779     return TINYEXR_ERROR_UNSUPPORTED_FORMAT;
12780   }
12781 
12782   deep_image->image = static_cast<float ***>(
12783       malloc(sizeof(float **) * static_cast<size_t>(num_channels)));
12784   for (int c = 0; c < num_channels; c++) {
12785     deep_image->image[c] = static_cast<float **>(
12786         malloc(sizeof(float *) * static_cast<size_t>(data_height)));
12787     for (int y = 0; y < data_height; y++) {
12788     }
12789   }
12790 
12791   deep_image->offset_table = static_cast<int **>(
12792       malloc(sizeof(int *) * static_cast<size_t>(data_height)));
12793   for (int y = 0; y < data_height; y++) {
12794     deep_image->offset_table[y] = static_cast<int *>(
12795         malloc(sizeof(int) * static_cast<size_t>(data_width)));
12796   }
12797 
12798   for (size_t y = 0; y < static_cast<size_t>(num_blocks); y++) {
12799     const unsigned char *data_ptr =
12800         reinterpret_cast<const unsigned char *>(head + offsets[y]);
12801 
12802     // int: y coordinate
12803     // int64: packed size of pixel offset table
12804     // int64: packed size of sample data
12805     // int64: unpacked size of sample data
12806     // compressed pixel offset table
12807     // compressed sample data
12808     int line_no;
12809     tinyexr::tinyexr_int64 packedOffsetTableSize;
12810     tinyexr::tinyexr_int64 packedSampleDataSize;
12811     tinyexr::tinyexr_int64 unpackedSampleDataSize;
12812     memcpy(&line_no, data_ptr, sizeof(int));
12813     memcpy(&packedOffsetTableSize, data_ptr + 4,
12814            sizeof(tinyexr::tinyexr_int64));
12815     memcpy(&packedSampleDataSize, data_ptr + 12,
12816            sizeof(tinyexr::tinyexr_int64));
12817     memcpy(&unpackedSampleDataSize, data_ptr + 20,
12818            sizeof(tinyexr::tinyexr_int64));
12819 
12820     tinyexr::swap4(reinterpret_cast<unsigned int *>(&line_no));
12821     tinyexr::swap8(
12822         reinterpret_cast<tinyexr::tinyexr_uint64 *>(&packedOffsetTableSize));
12823     tinyexr::swap8(
12824         reinterpret_cast<tinyexr::tinyexr_uint64 *>(&packedSampleDataSize));
12825     tinyexr::swap8(
12826         reinterpret_cast<tinyexr::tinyexr_uint64 *>(&unpackedSampleDataSize));
12827 
12828     std::vector<int> pixelOffsetTable(static_cast<size_t>(data_width));
12829 
12830     // decode pixel offset table.
12831     {
12832       unsigned long dstLen =
12833           static_cast<unsigned long>(pixelOffsetTable.size() * sizeof(int));
12834       if (!tinyexr::DecompressZip(
12835               reinterpret_cast<unsigned char *>(&pixelOffsetTable.at(0)),
12836               &dstLen, data_ptr + 28,
12837               static_cast<unsigned long>(packedOffsetTableSize))) {
12838         return false;
12839       }
12840 
12841       TEXR_ASSERT(dstLen == pixelOffsetTable.size() * sizeof(int));
12842       for (size_t i = 0; i < static_cast<size_t>(data_width); i++) {
12843         deep_image->offset_table[y][i] = pixelOffsetTable[i];
12844       }
12845     }
12846 
12847     std::vector<unsigned char> sample_data(
12848         static_cast<size_t>(unpackedSampleDataSize));
12849 
12850     // decode sample data.
12851     {
12852       unsigned long dstLen = static_cast<unsigned long>(unpackedSampleDataSize);
12853       if (dstLen) {
12854         if (!tinyexr::DecompressZip(
12855                 reinterpret_cast<unsigned char *>(&sample_data.at(0)), &dstLen,
12856                 data_ptr + 28 + packedOffsetTableSize,
12857                 static_cast<unsigned long>(packedSampleDataSize))) {
12858           return false;
12859         }
12860         TEXR_ASSERT(dstLen == static_cast<unsigned long>(unpackedSampleDataSize));
12861       }
12862     }
12863 
12864     // decode sample
12865     int sampleSize = -1;
12866     std::vector<int> channel_offset_list(static_cast<size_t>(num_channels));
12867     {
12868       int channel_offset = 0;
12869       for (size_t i = 0; i < static_cast<size_t>(num_channels); i++) {
12870         channel_offset_list[i] = channel_offset;
12871         if (channels[i].pixel_type == TINYEXR_PIXELTYPE_UINT) {  // UINT
12872           channel_offset += 4;
12873         } else if (channels[i].pixel_type == TINYEXR_PIXELTYPE_HALF) {  // half
12874           channel_offset += 2;
12875         } else if (channels[i].pixel_type ==
12876                    TINYEXR_PIXELTYPE_FLOAT) {  // float
12877           channel_offset += 4;
12878         } else {
12879           TEXR_ASSERT(0);
12880         }
12881       }
12882       sampleSize = channel_offset;
12883     }
12884     TEXR_ASSERT(sampleSize >= 2);
12885 
12886     TEXR_ASSERT(static_cast<size_t>(
12887                pixelOffsetTable[static_cast<size_t>(data_width - 1)] *
12888                sampleSize) == sample_data.size());
12889     int samples_per_line = static_cast<int>(sample_data.size()) / sampleSize;
12890 
12891     //
12892     // Alloc memory
12893     //
12894 
12895     //
12896     // pixel data is stored as image[channels][pixel_samples]
12897     //
12898     {
12899       tinyexr::tinyexr_uint64 data_offset = 0;
12900       for (size_t c = 0; c < static_cast<size_t>(num_channels); c++) {
12901         deep_image->image[c][y] = static_cast<float *>(
12902             malloc(sizeof(float) * static_cast<size_t>(samples_per_line)));
12903 
12904         if (channels[c].pixel_type == 0) {  // UINT
12905           for (size_t x = 0; x < static_cast<size_t>(samples_per_line); x++) {
12906             unsigned int ui;
12907             unsigned int *src_ptr = reinterpret_cast<unsigned int *>(
12908                 &sample_data.at(size_t(data_offset) + x * sizeof(int)));
12909             tinyexr::cpy4(&ui, src_ptr);
12910             deep_image->image[c][y][x] = static_cast<float>(ui);  // @fixme
12911           }
12912           data_offset +=
12913               sizeof(unsigned int) * static_cast<size_t>(samples_per_line);
12914         } else if (channels[c].pixel_type == 1) {  // half
12915           for (size_t x = 0; x < static_cast<size_t>(samples_per_line); x++) {
12916             tinyexr::FP16 f16;
12917             const unsigned short *src_ptr = reinterpret_cast<unsigned short *>(
12918                 &sample_data.at(size_t(data_offset) + x * sizeof(short)));
12919             tinyexr::cpy2(&(f16.u), src_ptr);
12920             tinyexr::FP32 f32 = half_to_float(f16);
12921             deep_image->image[c][y][x] = f32.f;
12922           }
12923           data_offset += sizeof(short) * static_cast<size_t>(samples_per_line);
12924         } else {  // float
12925           for (size_t x = 0; x < static_cast<size_t>(samples_per_line); x++) {
12926             float f;
12927             const float *src_ptr = reinterpret_cast<float *>(
12928                 &sample_data.at(size_t(data_offset) + x * sizeof(float)));
12929             tinyexr::cpy4(&f, src_ptr);
12930             deep_image->image[c][y][x] = f;
12931           }
12932           data_offset += sizeof(float) * static_cast<size_t>(samples_per_line);
12933         }
12934       }
12935     }
12936   }  // y
12937 
12938   deep_image->width = data_width;
12939   deep_image->height = data_height;
12940 
12941   deep_image->channel_names = static_cast<const char **>(
12942       malloc(sizeof(const char *) * static_cast<size_t>(num_channels)));
12943   for (size_t c = 0; c < static_cast<size_t>(num_channels); c++) {
12944 #ifdef _WIN32
12945     deep_image->channel_names[c] = _strdup(channels[c].name.c_str());
12946 #else
12947     deep_image->channel_names[c] = strdup(channels[c].name.c_str());
12948 #endif
12949   }
12950   deep_image->num_channels = num_channels;
12951 
12952   return TINYEXR_SUCCESS;
12953 }
12954 
12955 void InitEXRImage(EXRImage *exr_image) {
12956   if (exr_image == NULL) {
12957     return;
12958   }
12959 
12960   exr_image->width = 0;
12961   exr_image->height = 0;
12962   exr_image->num_channels = 0;
12963 
12964   exr_image->images = NULL;
12965   exr_image->tiles = NULL;
12966 
12967   exr_image->num_tiles = 0;
12968 }
12969 
12970 void FreeEXRErrorMessage(const char *msg) {
12971   if (msg) {
12972     free(reinterpret_cast<void *>(const_cast<char *>(msg)));
12973   }
12974   return;
12975 }
12976 
12977 void InitEXRHeader(EXRHeader *exr_header) {
12978   if (exr_header == NULL) {
12979     return;
12980   }
12981 
12982   memset(exr_header, 0, sizeof(EXRHeader));
12983 }
12984 
12985 int FreeEXRHeader(EXRHeader *exr_header) {
12986   if (exr_header == NULL) {
12987     return TINYEXR_ERROR_INVALID_ARGUMENT;
12988   }
12989 
12990   if (exr_header->channels) {
12991     free(exr_header->channels);
12992   }
12993 
12994   if (exr_header->pixel_types) {
12995     free(exr_header->pixel_types);
12996   }
12997 
12998   if (exr_header->requested_pixel_types) {
12999     free(exr_header->requested_pixel_types);
13000   }
13001 
13002   for (int i = 0; i < exr_header->num_custom_attributes; i++) {
13003     if (exr_header->custom_attributes[i].value) {
13004       free(exr_header->custom_attributes[i].value);
13005     }
13006   }
13007 
13008   if (exr_header->custom_attributes) {
13009     free(exr_header->custom_attributes);
13010   }
13011 
13012   return TINYEXR_SUCCESS;
13013 }
13014 
13015 int FreeEXRImage(EXRImage *exr_image) {
13016   if (exr_image == NULL) {
13017     return TINYEXR_ERROR_INVALID_ARGUMENT;
13018   }
13019 
13020   for (int i = 0; i < exr_image->num_channels; i++) {
13021     if (exr_image->images && exr_image->images[i]) {
13022       free(exr_image->images[i]);
13023     }
13024   }
13025 
13026   if (exr_image->images) {
13027     free(exr_image->images);
13028   }
13029 
13030   if (exr_image->tiles) {
13031     for (int tid = 0; tid < exr_image->num_tiles; tid++) {
13032       for (int i = 0; i < exr_image->num_channels; i++) {
13033         if (exr_image->tiles[tid].images && exr_image->tiles[tid].images[i]) {
13034           free(exr_image->tiles[tid].images[i]);
13035         }
13036       }
13037       if (exr_image->tiles[tid].images) {
13038         free(exr_image->tiles[tid].images);
13039       }
13040     }
13041     free(exr_image->tiles);
13042   }
13043 
13044   return TINYEXR_SUCCESS;
13045 }
13046 
13047 int ParseEXRHeaderFromFile(EXRHeader *exr_header, const EXRVersion *exr_version,
13048                            const char *filename, const char **err) {
13049   if (exr_header == NULL || exr_version == NULL || filename == NULL) {
13050     tinyexr::SetErrorMessage("Invalid argument for ParseEXRHeaderFromFile",
13051                              err);
13052     return TINYEXR_ERROR_INVALID_ARGUMENT;
13053   }
13054 
13055 #ifdef _WIN32
13056   FILE *fp = NULL;
13057   fopen_s(&fp, filename, "rb");
13058 #else
13059   FILE *fp = fopen(filename, "rb");
13060 #endif
13061   if (!fp) {
13062     tinyexr::SetErrorMessage("Cannot read file " + std::string(filename), err);
13063     return TINYEXR_ERROR_CANT_OPEN_FILE;
13064   }
13065 
13066   size_t filesize;
13067   // Compute size
13068   fseek(fp, 0, SEEK_END);
13069   filesize = static_cast<size_t>(ftell(fp));
13070   fseek(fp, 0, SEEK_SET);
13071 
13072   std::vector<unsigned char> buf(filesize);  // @todo { use mmap }
13073   {
13074     size_t ret;
13075     ret = fread(&buf[0], 1, filesize, fp);
13076     TEXR_ASSERT(ret == filesize);
13077     fclose(fp);
13078 
13079     if (ret != filesize) {
13080       tinyexr::SetErrorMessage("fread() error on " + std::string(filename),
13081                                err);
13082       return TINYEXR_ERROR_INVALID_FILE;
13083     }
13084   }
13085 
13086   return ParseEXRHeaderFromMemory(exr_header, exr_version, &buf.at(0), filesize,
13087                                   err);
13088 }
13089 
13090 int ParseEXRMultipartHeaderFromMemory(EXRHeader ***exr_headers,
13091                                       int *num_headers,
13092                                       const EXRVersion *exr_version,
13093                                       const unsigned char *memory, size_t size,
13094                                       const char **err) {
13095   if (memory == NULL || exr_headers == NULL || num_headers == NULL ||
13096       exr_version == NULL) {
13097     // Invalid argument
13098     tinyexr::SetErrorMessage(
13099         "Invalid argument for ParseEXRMultipartHeaderFromMemory", err);
13100     return TINYEXR_ERROR_INVALID_ARGUMENT;
13101   }
13102 
13103   if (size < tinyexr::kEXRVersionSize) {
13104     tinyexr::SetErrorMessage("Data size too short", err);
13105     return TINYEXR_ERROR_INVALID_DATA;
13106   }
13107 
13108   const unsigned char *marker = memory + tinyexr::kEXRVersionSize;
13109   size_t marker_size = size - tinyexr::kEXRVersionSize;
13110 
13111   std::vector<tinyexr::HeaderInfo> infos;
13112 
13113   for (;;) {
13114     tinyexr::HeaderInfo info;
13115     info.clear();
13116 
13117     std::string err_str;
13118     bool empty_header = false;
13119     int ret = ParseEXRHeader(&info, &empty_header, exr_version, &err_str,
13120                              marker, marker_size);
13121 
13122     if (ret != TINYEXR_SUCCESS) {
13123       tinyexr::SetErrorMessage(err_str, err);
13124       return ret;
13125     }
13126 
13127     if (empty_header) {
13128       marker += 1;  // skip '\0'
13129       break;
13130     }
13131 
13132     // `chunkCount` must exist in the header.
13133     if (info.chunk_count == 0) {
13134       tinyexr::SetErrorMessage(
13135           "`chunkCount' attribute is not found in the header.", err);
13136       return TINYEXR_ERROR_INVALID_DATA;
13137     }
13138 
13139     infos.push_back(info);
13140 
13141     // move to next header.
13142     marker += info.header_len;
13143     size -= info.header_len;
13144   }
13145 
13146   // allocate memory for EXRHeader and create array of EXRHeader pointers.
13147   (*exr_headers) =
13148       static_cast<EXRHeader **>(malloc(sizeof(EXRHeader *) * infos.size()));
13149   for (size_t i = 0; i < infos.size(); i++) {
13150     EXRHeader *exr_header = static_cast<EXRHeader *>(malloc(sizeof(EXRHeader)));
13151 
13152     ConvertHeader(exr_header, infos[i]);
13153 
13154     // transfoer `tiled` from version.
13155     exr_header->tiled = exr_version->tiled;
13156 
13157     (*exr_headers)[i] = exr_header;
13158   }
13159 
13160   (*num_headers) = static_cast<int>(infos.size());
13161 
13162   return TINYEXR_SUCCESS;
13163 }
13164 
13165 int ParseEXRMultipartHeaderFromFile(EXRHeader ***exr_headers, int *num_headers,
13166                                     const EXRVersion *exr_version,
13167                                     const char *filename, const char **err) {
13168   if (exr_headers == NULL || num_headers == NULL || exr_version == NULL ||
13169       filename == NULL) {
13170     tinyexr::SetErrorMessage(
13171         "Invalid argument for ParseEXRMultipartHeaderFromFile()", err);
13172     return TINYEXR_ERROR_INVALID_ARGUMENT;
13173   }
13174 
13175 #ifdef _WIN32
13176   FILE *fp = NULL;
13177   fopen_s(&fp, filename, "rb");
13178 #else
13179   FILE *fp = fopen(filename, "rb");
13180 #endif
13181   if (!fp) {
13182     tinyexr::SetErrorMessage("Cannot read file " + std::string(filename), err);
13183     return TINYEXR_ERROR_CANT_OPEN_FILE;
13184   }
13185 
13186   size_t filesize;
13187   // Compute size
13188   fseek(fp, 0, SEEK_END);
13189   filesize = static_cast<size_t>(ftell(fp));
13190   fseek(fp, 0, SEEK_SET);
13191 
13192   std::vector<unsigned char> buf(filesize);  // @todo { use mmap }
13193   {
13194     size_t ret;
13195     ret = fread(&buf[0], 1, filesize, fp);
13196     TEXR_ASSERT(ret == filesize);
13197     fclose(fp);
13198 
13199     if (ret != filesize) {
13200       tinyexr::SetErrorMessage("`fread' error. file may be corrupted.", err);
13201       return TINYEXR_ERROR_INVALID_FILE;
13202     }
13203   }
13204 
13205   return ParseEXRMultipartHeaderFromMemory(
13206       exr_headers, num_headers, exr_version, &buf.at(0), filesize, err);
13207 }
13208 
13209 int ParseEXRVersionFromMemory(EXRVersion *version, const unsigned char *memory,
13210                               size_t size) {
13211   if (version == NULL || memory == NULL) {
13212     return TINYEXR_ERROR_INVALID_ARGUMENT;
13213   }
13214 
13215   if (size < tinyexr::kEXRVersionSize) {
13216     return TINYEXR_ERROR_INVALID_DATA;
13217   }
13218 
13219   const unsigned char *marker = memory;
13220 
13221   // Header check.
13222   {
13223     const char header[] = {0x76, 0x2f, 0x31, 0x01};
13224 
13225     if (memcmp(marker, header, 4) != 0) {
13226       return TINYEXR_ERROR_INVALID_MAGIC_NUMBER;
13227     }
13228     marker += 4;
13229   }
13230 
13231   version->tiled = false;
13232   version->long_name = false;
13233   version->non_image = false;
13234   version->multipart = false;
13235 
13236   // Parse version header.
13237   {
13238     // must be 2
13239     if (marker[0] != 2) {
13240       return TINYEXR_ERROR_INVALID_EXR_VERSION;
13241     }
13242 
13243     version->version = 2;
13244 
13245     if (marker[1] & 0x2) {  // 9th bit
13246       version->tiled = true;
13247     }
13248     if (marker[1] & 0x4) {  // 10th bit
13249       version->long_name = true;
13250     }
13251     if (marker[1] & 0x8) {        // 11th bit
13252       version->non_image = true;  // (deep image)
13253     }
13254     if (marker[1] & 0x10) {  // 12th bit
13255       version->multipart = true;
13256     }
13257   }
13258 
13259   return TINYEXR_SUCCESS;
13260 }
13261 
13262 int ParseEXRVersionFromFile(EXRVersion *version, const char *filename) {
13263   if (filename == NULL) {
13264     return TINYEXR_ERROR_INVALID_ARGUMENT;
13265   }
13266 
13267 #ifdef _WIN32
13268   FILE *fp = NULL;
13269   fopen_s(&fp, filename, "rb");
13270 #else
13271   FILE *fp = fopen(filename, "rb");
13272 #endif
13273   if (!fp) {
13274     return TINYEXR_ERROR_CANT_OPEN_FILE;
13275   }
13276 
13277   size_t file_size;
13278   // Compute size
13279   fseek(fp, 0, SEEK_END);
13280   file_size = static_cast<size_t>(ftell(fp));
13281   fseek(fp, 0, SEEK_SET);
13282 
13283   if (file_size < tinyexr::kEXRVersionSize) {
13284     fclose(fp);
13285     return TINYEXR_ERROR_INVALID_FILE;
13286   }
13287 
13288   unsigned char buf[tinyexr::kEXRVersionSize];
13289   size_t ret = fread(&buf[0], 1, tinyexr::kEXRVersionSize, fp);
13290   fclose(fp);
13291 
13292   if (ret != tinyexr::kEXRVersionSize) {
13293     return TINYEXR_ERROR_INVALID_FILE;
13294   }
13295 
13296   return ParseEXRVersionFromMemory(version, buf, tinyexr::kEXRVersionSize);
13297 }
13298 
13299 int LoadEXRMultipartImageFromMemory(EXRImage *exr_images,
13300                                     const EXRHeader **exr_headers,
13301                                     unsigned int num_parts,
13302                                     const unsigned char *memory,
13303                                     const size_t size, const char **err) {
13304   if (exr_images == NULL || exr_headers == NULL || num_parts == 0 ||
13305       memory == NULL || (size <= tinyexr::kEXRVersionSize)) {
13306     tinyexr::SetErrorMessage(
13307         "Invalid argument for LoadEXRMultipartImageFromMemory()", err);
13308     return TINYEXR_ERROR_INVALID_ARGUMENT;
13309   }
13310 
13311   // compute total header size.
13312   size_t total_header_size = 0;
13313   for (unsigned int i = 0; i < num_parts; i++) {
13314     if (exr_headers[i]->header_len == 0) {
13315       tinyexr::SetErrorMessage("EXRHeader variable is not initialized.", err);
13316       return TINYEXR_ERROR_INVALID_ARGUMENT;
13317     }
13318 
13319     total_header_size += exr_headers[i]->header_len;
13320   }
13321 
13322   const char *marker = reinterpret_cast<const char *>(
13323       memory + total_header_size + 4 +
13324       4);  // +8 for magic number and version header.
13325 
13326   marker += 1;  // Skip empty header.
13327 
13328   // NOTE 1:
13329   //   In multipart image, There is 'part number' before chunk data.
13330   //   4 byte : part number
13331   //   4+     : chunk
13332   //
13333   // NOTE 2:
13334   //   EXR spec says 'part number' is 'unsigned long' but actually this is
13335   //   'unsigned int(4 bytes)' in OpenEXR implementation...
13336   //   http://www.openexr.com/openexrfilelayout.pdf
13337 
13338   // Load chunk offset table.
13339   std::vector<std::vector<tinyexr::tinyexr_uint64> > chunk_offset_table_list;
13340   for (size_t i = 0; i < static_cast<size_t>(num_parts); i++) {
13341     std::vector<tinyexr::tinyexr_uint64> offset_table(
13342         static_cast<size_t>(exr_headers[i]->chunk_count));
13343 
13344     for (size_t c = 0; c < offset_table.size(); c++) {
13345       tinyexr::tinyexr_uint64 offset;
13346       memcpy(&offset, marker, 8);
13347       tinyexr::swap8(&offset);
13348 
13349       if (offset >= size) {
13350         tinyexr::SetErrorMessage("Invalid offset size in EXR header chunks.",
13351                                  err);
13352         return TINYEXR_ERROR_INVALID_DATA;
13353       }
13354 
13355       offset_table[c] = offset + 4;  // +4 to skip 'part number'
13356       marker += 8;
13357     }
13358 
13359     chunk_offset_table_list.push_back(offset_table);
13360   }
13361 
13362   // Decode image.
13363   for (size_t i = 0; i < static_cast<size_t>(num_parts); i++) {
13364     std::vector<tinyexr::tinyexr_uint64> &offset_table =
13365         chunk_offset_table_list[i];
13366 
13367     // First check 'part number' is identitical to 'i'
13368     for (size_t c = 0; c < offset_table.size(); c++) {
13369       const unsigned char *part_number_addr =
13370           memory + offset_table[c] - 4;  // -4 to move to 'part number' field.
13371       unsigned int part_no;
13372       memcpy(&part_no, part_number_addr, sizeof(unsigned int));  // 4
13373       tinyexr::swap4(&part_no);
13374 
13375       if (part_no != i) {
13376         tinyexr::SetErrorMessage("Invalid `part number' in EXR header chunks.",
13377                                  err);
13378         return TINYEXR_ERROR_INVALID_DATA;
13379       }
13380     }
13381 
13382     std::string e;
13383     int ret = tinyexr::DecodeChunk(&exr_images[i], exr_headers[i], offset_table,
13384                                    memory, size, &e);
13385     if (ret != TINYEXR_SUCCESS) {
13386       if (!e.empty()) {
13387         tinyexr::SetErrorMessage(e, err);
13388       }
13389       return ret;
13390     }
13391   }
13392 
13393   return TINYEXR_SUCCESS;
13394 }
13395 
13396 int LoadEXRMultipartImageFromFile(EXRImage *exr_images,
13397                                   const EXRHeader **exr_headers,
13398                                   unsigned int num_parts, const char *filename,
13399                                   const char **err) {
13400   if (exr_images == NULL || exr_headers == NULL || num_parts == 0) {
13401     tinyexr::SetErrorMessage(
13402         "Invalid argument for LoadEXRMultipartImageFromFile", err);
13403     return TINYEXR_ERROR_INVALID_ARGUMENT;
13404   }
13405 
13406 #ifdef _WIN32
13407   FILE *fp = NULL;
13408   fopen_s(&fp, filename, "rb");
13409 #else
13410   FILE *fp = fopen(filename, "rb");
13411 #endif
13412   if (!fp) {
13413     tinyexr::SetErrorMessage("Cannot read file " + std::string(filename), err);
13414     return TINYEXR_ERROR_CANT_OPEN_FILE;
13415   }
13416 
13417   size_t filesize;
13418   // Compute size
13419   fseek(fp, 0, SEEK_END);
13420   filesize = static_cast<size_t>(ftell(fp));
13421   fseek(fp, 0, SEEK_SET);
13422 
13423   std::vector<unsigned char> buf(filesize);  //  @todo { use mmap }
13424   {
13425     size_t ret;
13426     ret = fread(&buf[0], 1, filesize, fp);
13427     TEXR_ASSERT(ret == filesize);
13428     fclose(fp);
13429     (void)ret;
13430   }
13431 
13432   return LoadEXRMultipartImageFromMemory(exr_images, exr_headers, num_parts,
13433                                          &buf.at(0), filesize, err);
13434 }
13435 
13436 int SaveEXR(const float *data, int width, int height, int components,
13437             const int save_as_fp16, const char *outfilename, const char **err) {
13438   if ((components == 1) || components == 3 || components == 4) {
13439     // OK
13440   } else {
13441     std::stringstream ss;
13442     ss << "Unsupported component value : " << components << std::endl;
13443 
13444     tinyexr::SetErrorMessage(ss.str(), err);
13445     return TINYEXR_ERROR_INVALID_ARGUMENT;
13446   }
13447 
13448   EXRHeader header;
13449   InitEXRHeader(&header);
13450 
13451   if ((width < 16) && (height < 16)) {
13452     // No compression for small image.
13453     header.compression_type = TINYEXR_COMPRESSIONTYPE_NONE;
13454   } else {
13455     header.compression_type = TINYEXR_COMPRESSIONTYPE_ZIP;
13456   }
13457 
13458   EXRImage image;
13459   InitEXRImage(&image);
13460 
13461   image.num_channels = components;
13462 
13463   std::vector<float> images[4];
13464 
13465   if (components == 1) {
13466     images[0].resize(static_cast<size_t>(width * height));
13467     memcpy(images[0].data(), data, sizeof(float) * size_t(width * height));
13468   } else {
13469     images[0].resize(static_cast<size_t>(width * height));
13470     images[1].resize(static_cast<size_t>(width * height));
13471     images[2].resize(static_cast<size_t>(width * height));
13472     images[3].resize(static_cast<size_t>(width * height));
13473 
13474     // Split RGB(A)RGB(A)RGB(A)... into R, G and B(and A) layers
13475     for (size_t i = 0; i < static_cast<size_t>(width * height); i++) {
13476       images[0][i] = data[static_cast<size_t>(components) * i + 0];
13477       images[1][i] = data[static_cast<size_t>(components) * i + 1];
13478       images[2][i] = data[static_cast<size_t>(components) * i + 2];
13479       if (components == 4) {
13480         images[3][i] = data[static_cast<size_t>(components) * i + 3];
13481       }
13482     }
13483   }
13484 
13485   float *image_ptr[4] = {0, 0, 0, 0};
13486   if (components == 4) {
13487     image_ptr[0] = &(images[3].at(0));  // A
13488     image_ptr[1] = &(images[2].at(0));  // B
13489     image_ptr[2] = &(images[1].at(0));  // G
13490     image_ptr[3] = &(images[0].at(0));  // R
13491   } else if (components == 3) {
13492     image_ptr[0] = &(images[2].at(0));  // B
13493     image_ptr[1] = &(images[1].at(0));  // G
13494     image_ptr[2] = &(images[0].at(0));  // R
13495   } else if (components == 1) {
13496     image_ptr[0] = &(images[0].at(0));  // A
13497   }
13498 
13499   image.images = reinterpret_cast<unsigned char **>(image_ptr);
13500   image.width = width;
13501   image.height = height;
13502 
13503   header.num_channels = components;
13504   header.channels = static_cast<EXRChannelInfo *>(malloc(
13505       sizeof(EXRChannelInfo) * static_cast<size_t>(header.num_channels)));
13506   // Must be (A)BGR order, since most of EXR viewers expect this channel order.
13507   if (components == 4) {
13508 #ifdef _MSC_VER
13509     strncpy_s(header.channels[0].name, "A", 255);
13510     strncpy_s(header.channels[1].name, "B", 255);
13511     strncpy_s(header.channels[2].name, "G", 255);
13512     strncpy_s(header.channels[3].name, "R", 255);
13513 #else
13514     strncpy(header.channels[0].name, "A", 255);
13515     strncpy(header.channels[1].name, "B", 255);
13516     strncpy(header.channels[2].name, "G", 255);
13517     strncpy(header.channels[3].name, "R", 255);
13518 #endif
13519     header.channels[0].name[strlen("A")] = '\0';
13520     header.channels[1].name[strlen("B")] = '\0';
13521     header.channels[2].name[strlen("G")] = '\0';
13522     header.channels[3].name[strlen("R")] = '\0';
13523   } else if (components == 3) {
13524 #ifdef _MSC_VER
13525     strncpy_s(header.channels[0].name, "B", 255);
13526     strncpy_s(header.channels[1].name, "G", 255);
13527     strncpy_s(header.channels[2].name, "R", 255);
13528 #else
13529     strncpy(header.channels[0].name, "B", 255);
13530     strncpy(header.channels[1].name, "G", 255);
13531     strncpy(header.channels[2].name, "R", 255);
13532 #endif
13533     header.channels[0].name[strlen("B")] = '\0';
13534     header.channels[1].name[strlen("G")] = '\0';
13535     header.channels[2].name[strlen("R")] = '\0';
13536   } else {
13537 #ifdef _MSC_VER
13538     strncpy_s(header.channels[0].name, "A", 255);
13539 #else
13540     strncpy(header.channels[0].name, "A", 255);
13541 #endif
13542     header.channels[0].name[strlen("A")] = '\0';
13543   }
13544 
13545   header.pixel_types = static_cast<int *>(
13546       malloc(sizeof(int) * static_cast<size_t>(header.num_channels)));
13547   header.requested_pixel_types = static_cast<int *>(
13548       malloc(sizeof(int) * static_cast<size_t>(header.num_channels)));
13549   for (int i = 0; i < header.num_channels; i++) {
13550     header.pixel_types[i] =
13551         TINYEXR_PIXELTYPE_FLOAT;  // pixel type of input image
13552 
13553     if (save_as_fp16 > 0) {
13554       header.requested_pixel_types[i] =
13555           TINYEXR_PIXELTYPE_HALF;  // save with half(fp16) pixel format
13556     } else {
13557       header.requested_pixel_types[i] =
13558           TINYEXR_PIXELTYPE_FLOAT;  // save with float(fp32) pixel format(i.e.
13559                                     // no precision reduction)
13560     }
13561   }
13562 
13563   int ret = SaveEXRImageToFile(&image, &header, outfilename, err);
13564   if (ret != TINYEXR_SUCCESS) {
13565     return ret;
13566   }
13567 
13568   free(header.channels);
13569   free(header.pixel_types);
13570   free(header.requested_pixel_types);
13571 
13572   return ret;
13573 }
13574 
13575 #ifdef __clang__
13576 // zero-as-null-ppinter-constant
13577 #pragma clang diagnostic pop
13578 #endif
13579 
13580 #endif  // TINYEXR_IMPLEMENTATION_DEIFNED
13581 #endif  // TINYEXR_IMPLEMENTATION
13582