xref: /third_party/astc-encoder/Source/tinyexr.h (revision cc1dc7a3)
1/*
2Copyright (c) 2014 - 2019, Syoyo Fujita and many contributors.
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, 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
16THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
20DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23ON 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
25SOFTWARE, 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
89extern "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
164typedef 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
172typedef 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
180typedef 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
189typedef 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
201typedef 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
244typedef struct _EXRMultiPartHeader {
245  int num_headers;
246  EXRHeader *headers;
247
248} EXRMultiPartHeader;
249
250typedef 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
264typedef struct _EXRMultiPartImage {
265  int num_images;
266  EXRImage *images;
267
268} EXRMultiPartImage;
269
270typedef 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
287extern 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`.
297extern 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//
309extern 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
316extern 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
329extern 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
334extern void InitEXRHeader(EXRHeader *exr_header);
335
336// Initialize EXRImage struct
337extern void InitEXRImage(EXRImage *exr_image);
338
339// Free's internal data of EXRHeader struct
340extern int FreeEXRHeader(EXRHeader *exr_header);
341
342// Free's internal data of EXRImage struct
343extern int FreeEXRImage(EXRImage *exr_image);
344
345// Free's error message
346extern void FreeEXRErrorMessage(const char *msg);
347
348// Parse EXR version header of a file.
349extern int ParseEXRVersionFromFile(EXRVersion *version, const char *filename);
350
351// Parse EXR version header from memory-mapped EXR data.
352extern 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()
358extern 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()
364extern 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()
373extern 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()
383extern 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()
396extern 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()
407extern 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()
419extern 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()
433extern 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()
444extern 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()
455extern 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()
465extern 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()
489extern 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
541namespace tinyexr {
542
543#if __cplusplus > 199711L
544// C++11
545typedef uint64_t tinyexr_uint64;
546typedef 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
554typedef unsigned long long tinyexr_uint64;
555typedef long long tinyexr_int64;
556#ifdef __clang__
557#pragma clang diagnostic pop
558#endif
559#endif
560
561#if TINYEXR_USE_MINIZ
562
563namespace 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
945extern "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!
952typedef 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.
957void 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.
962mz_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.
967mz_ulong mz_crc32(mz_ulong crc, const unsigned char *ptr, size_t buf_len);
968
969// Compression strategies.
970enum {
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.
986typedef void *(*mz_alloc_func)(void *opaque, size_t items, size_t size);
987typedef void (*mz_free_func)(void *opaque, void *address);
988typedef 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).
1000enum {
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.
1010enum {
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.
1026enum {
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
1038struct mz_internal_state;
1039
1040// Compression/decompression stream struct.
1041typedef 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
1063typedef mz_stream *mz_streamp;
1064
1065// Returns the version string of miniz.c.
1066const 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.
1081int 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)
1090int 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().
1095int 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.)
1115int 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.
1121int 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.
1126mz_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.
1131int mz_compress(unsigned char *pDest, mz_ulong *pDest_len,
1132                const unsigned char *pSource, mz_ulong source_len);
1133int 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().
1138mz_ulong mz_compressBound(mz_ulong source_len);
1139
1140// Initializes a decompressor.
1141int 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).
1148int 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).
1176int mz_inflate(mz_streamp pStream, int flush);
1177
1178// Deinitializes a decompressor.
1179int 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.
1184int 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.
1189const 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
1196typedef unsigned char Byte;
1197typedef unsigned int uInt;
1198typedef mz_ulong uLong;
1199typedef Byte Bytef;
1200typedef uInt uIntf;
1201typedef char charf;
1202typedef int intf;
1203typedef void *voidpf;
1204typedef uLong uLongf;
1205typedef void *voidp;
1206typedef 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
1272typedef unsigned char mz_uint8;
1273typedef signed short mz_int16;
1274typedef unsigned short mz_uint16;
1275typedef unsigned int mz_uint32;
1276typedef unsigned int mz_uint;
1277typedef long long mz_int64;
1278typedef unsigned long long mz_uint64;
1279typedef 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
1296enum {
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
1302typedef 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
1323typedef size_t (*mz_file_read_func)(void *pOpaque, mz_uint64 file_ofs,
1324                                    void *pBuf, size_t n);
1325typedef size_t (*mz_file_write_func)(void *pOpaque, mz_uint64 file_ofs,
1326                                     const void *pBuf, size_t n);
1327
1328struct mz_zip_internal_state_tag;
1329typedef struct mz_zip_internal_state_tag mz_zip_internal_state;
1330
1331typedef 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
1338typedef 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
1359typedef 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.
1370mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size,
1371                           mz_uint32 flags);
1372mz_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
1376mz_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.
1381mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip);
1382
1383// Returns detailed information about an archive file entry.
1384mz_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.
1388mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip,
1389                                          mz_uint file_index);
1390mz_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.
1397mz_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.
1403int 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.
1407mz_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);
1412mz_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.
1417mz_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);
1420mz_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.
1425void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index,
1426                                    size_t *pSize, mz_uint flags);
1427void *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.
1432mz_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);
1436mz_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.
1445mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index,
1446                                      const char *pDst_filename, mz_uint flags);
1447mz_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.
1455mz_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.
1462mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size);
1463mz_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
1468mz_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.
1485mz_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.
1495mz_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);
1498mz_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.
1511mz_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.
1519mz_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.
1529mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip);
1530mz_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.
1536mz_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.
1545mz_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.
1552void *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.
1574enum {
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.
1593void *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))
1601size_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.
1609typedef int (*tinfl_put_buf_func_ptr)(const void *pBuf, int len, void *pUser);
1610int 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
1614struct tinfl_decompressor_tag;
1615typedef struct tinfl_decompressor_tag tinfl_decompressor;
1616
1617// Max size of LZ dictionary.
1618#define TINFL_LZ_DICT_SIZE 32768
1619
1620// Return status.
1621typedef 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.
1644tinfl_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.
1651enum {
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
1660typedef 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
1671typedef mz_uint64 tinfl_bit_buf_t;
1672#define TINFL_BITBUF_SIZE (64)
1673#else
1674typedef mz_uint32 tinfl_bit_buf_t;
1675#define TINFL_BITBUF_SIZE (32)
1676#endif
1677
1678struct 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).
1700enum {
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).
1722enum {
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.
1745void *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.
1751size_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.
1770void *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);
1774void *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.
1779typedef 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.
1784mz_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
1788enum {
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
1802enum {
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
1812enum {
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.
1826typedef 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
1834typedef 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.
1842typedef 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.)
1881tdefl_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.
1888tdefl_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.
1895tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf,
1896                                   size_t in_buf_size, tdefl_flush flush);
1897
1898tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d);
1899mz_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
1910mz_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
1925typedef unsigned char mz_validate_uint16[sizeof(mz_uint16) == 2 ? 1 : -1];
1926typedef unsigned char mz_validate_uint32[sizeof(mz_uint32) == 4 ? 1 : -1];
1927typedef 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
1968extern "C" {
1969#endif
1970
1971// ------------------- zlib-style API's
1972
1973mz_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/
1999mz_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
2015void mz_free(void *p) { MZ_FREE(p); }
2016
2017#ifndef MINIZ_NO_ZLIB_APIS
2018
2019static 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}
2023static 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
2033const char *mz_version(void) { return MZ_VERSION; }
2034
2035int 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
2040int 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
2076int 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
2086int 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
2139int 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
2148mz_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
2156int 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
2183int 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
2189mz_ulong mz_compressBound(mz_ulong source_len) {
2190  return mz_deflateBound(NULL, source_len);
2191}
2192
2193typedef 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
2201int 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
2234int mz_inflateInit(mz_streamp pStream) {
2235  return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS);
2236}
2237
2238int 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
2355int 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
2364int 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
2392const 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
2558tinfl_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
2947common_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.
2990void *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
3028size_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
3043int 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.
3079static 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
3099static 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
3112static 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
3141static 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
3164static 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
3173static 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.
3184typedef struct {
3185  mz_uint16 m_key, m_sym_index;
3186} tdefl_sym_freq;
3187static 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.
3221static 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.
3267enum { TDEFL_MAX_SUPPORTED_HUFF_CODESIZE = 32 };
3268static 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
3290static 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
3395static 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
3398static 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
3481static 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
3498static 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
3504static 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
3597static 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
3641static 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
3649static 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)
3781static 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
3836static 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
3879static 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
4060static 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
4072static 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
4103static 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
4245static 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
4266tdefl_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
4331tdefl_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
4337tdefl_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
4374tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d) {
4375  return d->m_prev_return_status;
4376}
4377
4378mz_uint32 tdefl_get_adler32(tdefl_compressor *d) { return d->m_adler32; }
4379
4380mz_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
4397typedef struct {
4398  size_t m_size, m_capacity;
4399  mz_uint8 *m_pBuf;
4400  mz_bool m_expandable;
4401} tdefl_output_buffer;
4402
4403static 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
4424void *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
4440size_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
4455static 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).
4461mz_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.
4502void *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}
4609void *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__)
4630static FILE *mz_fopen(const char *pFilename, const char *pMode) {
4631  FILE *pFile = NULL;
4632  fopen_s(&pFile, pFilename, pMode);
4633  return pFile;
4634}
4635static 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.
4727enum {
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
4776typedef struct {
4777  void *m_p;
4778  size_t m_size, m_capacity;
4779  mz_uint m_element_size;
4780} mz_zip_array;
4781
4782struct 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
4797static 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
4803static 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
4823static 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
4834static 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
4846static 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
4852static 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
4865static 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
4878static 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
4900static 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
4917static 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
4927static 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
4955static MZ_FORCEINLINE mz_bool
4956mz_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.)
4992static 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
5038static 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
5167mz_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
5179static 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
5189mz_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
5209static 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
5220mz_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
5246mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip) {
5247  return pZip ? pZip->m_total_files : 0;
5248}
5249
5250static 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
5261mz_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
5270mz_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
5295mz_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
5340mz_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
5357static 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
5368static 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
5389static 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
5414int 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
5465mz_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
5606mz_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
5616mz_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
5623mz_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
5630void *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
5663void *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
5674mz_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
5851mz_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
5862static 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
5868mz_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
5888mz_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
5915mz_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
5930static void mz_write_le16(mz_uint8 *p, mz_uint16 v) {
5931  p[0] = (mz_uint8)v;
5932  p[1] = (mz_uint8)(v >> 8);
5933}
5934static 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
5943mz_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
5976static 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
6004mz_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
6023static 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
6034mz_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
6063mz_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
6115mz_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
6122typedef 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
6128static 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
6140static 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
6161static 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
6186static 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
6230static 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
6242static 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
6251static 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
6265mz_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
6438mz_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
6631mz_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
6779mz_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
6832mz_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
6845mz_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
6877mz_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
6922void *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
7021static 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
7031static const int kEXRVersionSize = 8;
7032
7033static 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
7041static 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
7063static 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
7073static 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
7083static 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
7100static 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
7116static 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
7131static 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.
7152union 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
7173union 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
7192static 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
7215static 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
7275static 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
7293static 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
7355static 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
7368struct 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
7377struct 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
7400  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
7431static 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
7478static 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
7520static 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
7601static 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
7689const int MIN_RUN_LENGTH = 3;
7690const 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
7697static 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
7748static 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) || inLength < 0) 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
7785static 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
7852static 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
7949struct 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
7975inline 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
7987inline 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
8008const int NBITS = 16;
8009const int A_OFFSET = 1 << (NBITS - 1);
8010const int M_OFFSET = 1 << (NBITS - 1);
8011const int MOD_MASK = (1 << NBITS) - 1;
8012
8013inline 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
8027inline 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
8041static 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
8150static 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
8277const int HUF_ENCBITS = 16;  // literal (value) bit length
8278const int HUF_DECBITS = 14;  // decoding bit size (>= 8)
8279
8280const int HUF_ENCSIZE = (1 << HUF_ENCBITS) + 1;  // encoding table size
8281const int HUF_DECSIZE = 1 << HUF_DECBITS;        // decoding table size
8282const int HUF_DECMASK = HUF_DECSIZE - 1;
8283
8284struct 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
8291inline long long hufLength(long long code) { return code & 63; }
8292
8293inline long long hufCode(long long code) { return code >> 6; }
8294
8295inline 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
8305inline 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
8335static 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
8385struct FHeapCompare {
8386  bool operator()(long long *a, long long *b) { return *a > *b; }
8387};
8388
8389static 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
8567const int SHORT_ZEROCODE_RUN = 59;
8568const int LONG_ZEROCODE_RUN = 63;
8569const int SHORTEST_LONG_RUN = 2 + LONG_ZEROCODE_RUN - SHORT_ZEROCODE_RUN;
8570const int LONGEST_LONG_RUN = 255 + SHORTEST_LONG_RUN;
8571
8572static 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
8617static 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
8679static 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
8698static 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
8786static 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
8800inline void outputCode(long long code, long long &c, int &lc, char *&out) {
8801  outputBits(hufLength(code), hufCode(code), c, lc, out);
8802}
8803
8804inline 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
8826static 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
8908static 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
8947static 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
9063static 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
9070static 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
9079static 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
9090static 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
9120static 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
9183const int USHORT_RANGE = (1 << 16);
9184const int BITMAP_SIZE = (USHORT_RANGE >> 3);
9185
9186static 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
9208static 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
9222static 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
9237static 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
9250static 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
9370static 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
9490struct ZFPCompressionParam {
9491  double rate;
9492  int precision;
9493  double tolerance;
9494  int type;  // TINYEXR_ZFP_COMPRESSIONTYPE_*
9495
9496  ZFPCompressionParam() {
9497    type = TINYEXR_ZFP_COMPRESSIONTYPE_RATE;
9498    rate = 2.0;
9499    precision = 0;
9500    tolerance = 0.0f;
9501  }
9502};
9503
9504bool 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.
9554static 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.
9625bool 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.
9695static 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
10313static 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
10346static 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
10374static 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
10417static 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.
10725static 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
10808static 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
11180static 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
11214static 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
11370static 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
11387struct LayerChannel {
11388  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
11396static 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
11420int 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
11464int 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
11469int 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
11696int 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
11707int 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
11748int 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
11939int 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
11983int 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
12006size_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
12514int 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
12572int 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
12955void 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
12970void FreeEXRErrorMessage(const char *msg) {
12971  if (msg) {
12972    free(reinterpret_cast<void *>(const_cast<char *>(msg)));
12973  }
12974  return;
12975}
12976
12977void InitEXRHeader(EXRHeader *exr_header) {
12978  if (exr_header == NULL) {
12979    return;
12980  }
12981
12982  memset(exr_header, 0, sizeof(EXRHeader));
12983}
12984
12985int 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
13015int 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
13047int 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
13090int 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
13165int 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
13209int 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
13262int 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
13299int 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
13396int 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
13436int 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