[
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n\n[Makefile*]\nindent_style = tab\n\n[*.{c,h}]\nindent_style = tab\nindent_size = 8\n\n[*.yml]\nindent_style = space\nindent_size = 2\n"
  },
  {
    "path": ".github/workflows/tinf-ci-workflow.yaml",
    "content": "name: tinf CI\n\non: [push, pull_request]\n\njobs:\n  windows:\n    name: Windows ${{ matrix.config.name }}\n    runs-on: windows-latest\n\n    strategy:\n      matrix:\n        config:\n          - name: MSVC x64\n            generator: Visual Studio 16 2019\n            cmake-flags: -A x64\n\n    steps:\n      - uses: actions/checkout@v2\n\n      - name: Configure\n        run: cmake -G \"${{ matrix.config.generator }}\" ${{ matrix.config.cmake-flags }} -B build\n\n      - name: Build\n        run: cd build && cmake --build . --config Debug\n\n      - name: Test\n        run: cd build && ctest -V --output-on-failure --interactive-debug-mode 0 -C Debug\n\n  linux:\n    name: Linux ${{ matrix.config.name }}\n    runs-on: ubuntu-latest\n    env:\n      CC: ${{ matrix.config.cc }}\n\n    strategy:\n      matrix:\n        config:\n          - name: Clang UBSan\n            cc: clang\n            cmake-flags: -DCMAKE_C_FLAGS_DEBUG='-g -fsanitize=undefined'\n\n          - name: Clang ASan\n            cc: clang\n            cmake-flags: -DCMAKE_C_FLAGS_DEBUG='-O1 -g -fsanitize=address -fno-omit-frame-pointer'\n\n    steps:\n      - uses: actions/checkout@v2\n\n      - name: Configure\n        run: cmake ${{ matrix.config.cmake-flags }} -DCMAKE_BUILD_TYPE=Debug -B build\n\n      - name: Build\n        run: cd build && make VERBOSE=1\n\n      - name: Test\n        run: cd build && ctest -V --output-on-failure --interactive-debug-mode 0\n\n  coverage:\n    name: Linux Coverage\n    runs-on: ubuntu-latest\n\n    steps:\n      - uses: actions/checkout@v2\n\n      - name: Configure\n        run: cmake -DCMAKE_C_FLAGS_DEBUG='-g -O0 --coverage' -DCMAKE_BUILD_TYPE=Debug -B build\n\n      - name: Build\n        run: cd build && make VERBOSE=1\n\n      - name: Test\n        run: cd build && ctest -V --output-on-failure --interactive-debug-mode 0\n\n      - name: Generate coverage\n        run: cd build && gcov -abcfu CMakeFiles/tinf.dir/src/*.c.gcno -o CMakeFiles/tinf.dir/src\n\n      - name: Upload coverage to Codecov\n        uses: codecov/codecov-action@v2\n        with:\n          directory: ./build/\n"
  },
  {
    "path": ".gitignore",
    "content": "*.o\n*.obj\n\n*.a\n*.lib\n\n*.so\n*.so.*\n*.dll\n\n*.exe\n\n/build/\n/doc/\n"
  },
  {
    "path": "CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.16)\n\nproject(tinf C)\n\ninclude(CheckCCompilerFlag)\ninclude(CTest)\n\n# Check if tinf is the top-level project (standalone), or a subproject\nset(_tinf_standalone FALSE)\nif(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)\n  set(_tinf_standalone TRUE)\nendif()\n\n# TINF_BUILD_TESTING controls if tinf adds testing support\n#\n# When built standalone, it defaults to the value of BUILD_TESTING if set.\n# An optional prefix for the test names can be set with TINF_TEST_PREFIX.\nset(_tinf_testing_default ON)\nif(_tinf_standalone)\n  if(DEFINED BUILD_TESTING)\n    set(_tinf_testing_default ${BUILD_TESTING})\n  endif()\nelse()\n  set(_tinf_testing_default OFF)\nendif()\noption(TINF_BUILD_TESTING \"Add testing support\" ${_tinf_testing_default})\nunset(_tinf_testing_default)\n\nmark_as_advanced(TINF_TEST_PREFIX)\n\n# Take a list of compiler flags and add those which the compiler accepts to\n# the COMPILE_OPTIONS directory property\nfunction(add_valid_c_compile_options)\n  foreach(flag IN LISTS ARGN)\n    string(REGEX REPLACE \"[^a-zA-Z0-9]+\" \"_\" flag_var \"CFLAG_${flag}\")\n    check_c_compiler_flag(\"${flag}\" ${flag_var})\n    if(${flag_var})\n      add_compile_options(\"${flag}\")\n    endif()\n  endforeach()\nendfunction()\n\nif(MSVC)\n  add_valid_c_compile_options(/W3)\nelse()\n  add_valid_c_compile_options(-Wall -Wextra -pedantic)\nendif()\n\n#\n# tinf\n#\nadd_library(tinf\n  src/adler32.c\n  src/crc32.c\n  src/tinfgzip.c\n  src/tinflate.c\n  src/tinfzlib.c\n  src/tinf.h\n)\ntarget_include_directories(tinf PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/src>)\n\n#\n# tgunzip\n#\nadd_executable(tgunzip examples/tgunzip/tgunzip.c)\ntarget_link_libraries(tgunzip PRIVATE tinf)\nif(MSVC)\n  target_compile_definitions(tgunzip PRIVATE _CRT_SECURE_NO_WARNINGS)\nendif()\n\n#\n# Tests\n#\nif(TINF_BUILD_TESTING)\n  add_executable(test_tinf test/test_tinf.c)\n  target_link_libraries(test_tinf PRIVATE tinf)\n  if(MSVC)\n    target_compile_definitions(test_tinf PRIVATE _CRT_SECURE_NO_WARNINGS)\n  endif()\n\n  add_test(\"${TINF_TEST_PREFIX}tinf\" test_tinf)\nendif()\n"
  },
  {
    "path": "LICENSE",
    "content": "The zlib License (Zlib)\n\nCopyright (c) 2003-2019 Joergen Ibsen\n\nThis software is provided 'as-is', without any express or implied\nwarranty. In no event will the authors be held liable for any damages\narising from the use of this software.\n\nPermission is granted to anyone to use this software for any purpose,\nincluding commercial applications, and to alter it and redistribute it\nfreely, subject to the following restrictions:\n\n  1. The origin of this software must not be misrepresented; you must\n     not claim that you wrote the original software. If you use this\n     software in a product, an acknowledgment in the product\n     documentation would be appreciated but is not required.\n\n  2. Altered source versions must be plainly marked as such, and must\n     not be misrepresented as being the original software.\n\n  3. This notice may not be removed or altered from any source\n     distribution.\n"
  },
  {
    "path": "README.md",
    "content": "\ntinf - tiny inflate library\n===========================\n\nVersion 1.2.1\n\nCopyright (c) 2003-2019 Joergen Ibsen\n\n<http://www.ibsensoftware.com/>\n\n[![tinf CI](https://github.com/jibsen/tinf/actions/workflows/tinf-ci-workflow.yaml/badge.svg)](https://github.com/jibsen/tinf/actions) [![codecov](https://codecov.io/gh/jibsen/tinf/branch/master/graph/badge.svg)](https://codecov.io/gh/jibsen/tinf)\n\nAbout\n-----\n\ntinf is a small library implementing the decompression algorithm for the\n[deflate][wpdeflate] compressed data format (called 'inflate'). Deflate\ncompression is used in e.g. zlib, gzip, zip, and png.\n\nI wrote it because I needed a small in-memory zlib decompressor for a self-\nextracting archive, and the zlib library added 15k to my program. The tinf\ncode added only 2k.\n\nNaturally the size difference is insignificant in most cases. Also, the\nzlib library has many more features, is well-tested, and mostly faster.\nBut if you have a project that calls for a small and simple deflate\ndecompressor, give it a try :-)\n\n[wpdeflate]: https://en.wikipedia.org/wiki/DEFLATE\n\n\nUsage\n-----\n\nThe include file `src/tinf.h` contains documentation in the form of\n[doxygen][] comments.\n\nWrappers for decompressing zlib and gzip data in memory are supplied.\n\ntgunzip, an example command-line gzip decompressor in C, is included.\n\ntinf uses [CMake][] to generate build systems. To create one for the tools on\nyour platform, and build tinf, use something along the lines of:\n\n~~~sh\nmkdir build\ncd build\ncmake -DCMAKE_BUILD_TYPE=Release ..\ncmake --build . --config Release\n~~~\n\nYou can also compile the source files and link them into your project. CMake\njust provides an easy way to build and test across various platforms and\ntoolsets.\n\n[doxygen]: http://www.doxygen.org/\n[CMake]: http://www.cmake.org/\n\n\nNotes\n-----\n\ntinf requires int to be at least 32-bit.\n\nThe inflate algorithm and data format are from 'DEFLATE Compressed Data\nFormat Specification version 1.3' ([RFC 1951][deflate]).\n\nThe zlib data format is from 'ZLIB Compressed Data Format Specification\nversion 3.3' ([RFC 1950][zlib]).\n\nThe gzip data format is from 'GZIP file format specification version 4.3'\n([RFC 1952][gzip]).\n\nThe original version of tinf assumed it was given valid compressed data, and\nthat there was sufficient space for the decompressed data. If code size is\nof the utmost importance, and you are absolutely sure you can trust the\ncompressed data, you may want to check out [tinf 1.1.0][tinf110] (last\nrelease without security checks).\n\nIdeas for future versions:\n\n  - Memory for the `tinf_data` object should be passed, to avoid using more\n    than 1k of stack space\n  - Wrappers for unpacking zip archives and png images\n  - Blocking of some sort, so everything does not have to be in memory\n  - Optional table-based Huffman decoder\n  - Small compressor using fixed Huffman trees\n\n[deflate]: http://www.rfc-editor.org/rfc/rfc1951.txt\n[zlib]: http://www.rfc-editor.org/rfc/rfc1950.txt\n[gzip]: http://www.rfc-editor.org/rfc/rfc1952.txt\n[tinf110]: https://github.com/jibsen/tinf/releases/tag/v1.1.0\n\n\nRelated Projects\n----------------\n\n  - [puff](https://github.com/madler/zlib) (in the contrib folder of zlib)\n  - [tinfl](https://github.com/richgel999/miniz) (part of miniz)\n  - [uzlib](https://github.com/pfalcon/uzlib)\n  - [gdunzip](https://github.com/jellehermsen/gdunzip) (GDScript)\n  - [TinyDeflate](https://github.com/bisqwit/TinyDeflate) (C++)\n  - [tiny-inflate](https://github.com/foliojs/tiny-inflate) (JavaScript)\n  - [tinflate](http://achurch.org/tinflate.c) (unrelated to this project)\n  - The [Wikipedia page for deflate](https://en.wikipedia.org/wiki/DEFLATE)\n    has a list of implementations\n\n\nLicense\n-------\n\nThis projected is licensed under the [zlib License](LICENSE) (Zlib).\n"
  },
  {
    "path": "examples/tgunzip/tgunzip.c",
    "content": "/*\n * tgunzip - gzip decompressor example\n *\n * Copyright (c) 2003-2019 Joergen Ibsen\n *\n * This software is provided 'as-is', without any express or implied\n * warranty. In no event will the authors be held liable for any damages\n * arising from the use of this software.\n *\n * Permission is granted to anyone to use this software for any purpose,\n * including commercial applications, and to alter it and redistribute it\n * freely, subject to the following restrictions:\n *\n *   1. The origin of this software must not be misrepresented; you must\n *      not claim that you wrote the original software. If you use this\n *      software in a product, an acknowledgment in the product\n *      documentation would be appreciated but is not required.\n *\n *   2. Altered source versions must be plainly marked as such, and must\n *      not be misrepresented as being the original software.\n *\n *   3. This notice may not be removed or altered from any source\n *      distribution.\n */\n\n#include <stdarg.h>\n#include <stdlib.h>\n#include <stdio.h>\n\n#include \"tinf.h\"\n\nstatic unsigned int read_le32(const unsigned char *p)\n{\n\treturn ((unsigned int) p[0])\n\t     | ((unsigned int) p[1] << 8)\n\t     | ((unsigned int) p[2] << 16)\n\t     | ((unsigned int) p[3] << 24);\n}\n\nstatic void printf_error(const char *fmt, ...)\n{\n\tva_list arg;\n\n\tfputs(\"tgunzip: \", stderr);\n\n\tva_start(arg, fmt);\n\tvfprintf(stderr, fmt, arg);\n\tva_end(arg);\n\n\tfputs(\"\\n\", stderr);\n}\n\nint main(int argc, char *argv[])\n{\n\tFILE *fin = NULL;\n\tFILE *fout = NULL;\n\tunsigned char *source = NULL;\n\tunsigned char *dest = NULL;\n\tunsigned int len, dlen, outlen;\n\tint retval = EXIT_FAILURE;\n\tint res;\n\n\tprintf(\"tgunzip \" TINF_VER_STRING \" - example from the tiny inflate library (www.ibsensoftware.com)\\n\\n\");\n\n\tif (argc != 3) {\n\t\tfputs(\"usage: tgunzip INFILE OUTFILE\\n\\n\"\n\t\t      \"Both input and output are kept in memory, so do not use this on huge files.\\n\", stderr);\n\t\treturn EXIT_FAILURE;\n\t}\n\n\ttinf_init();\n\n\t/* -- Open files -- */\n\n\tif ((fin = fopen(argv[1], \"rb\")) == NULL) {\n\t\tprintf_error(\"unable to open input file '%s'\", argv[1]);\n\t\tgoto out;\n\t}\n\n\tif ((fout = fopen(argv[2], \"wb\")) == NULL) {\n\t\tprintf_error(\"unable to create output file '%s'\", argv[2]);\n\t\tgoto out;\n\t}\n\n\t/* -- Read source -- */\n\n\tfseek(fin, 0, SEEK_END);\n\n\tlen = ftell(fin);\n\n\tfseek(fin, 0, SEEK_SET);\n\n\tif (len < 18) {\n\t\tprintf_error(\"input too small to be gzip\");\n\t\tgoto out;\n\t}\n\n\tsource = (unsigned char *) malloc(len);\n\n\tif (source == NULL) {\n\t\tprintf_error(\"not enough memory\");\n\t\tgoto out;\n\t}\n\n\tif (fread(source, 1, len, fin) != len) {\n\t\tprintf_error(\"error reading input file\");\n\t\tgoto out;\n\t}\n\n\t/* -- Get decompressed length -- */\n\n\tdlen = read_le32(&source[len - 4]);\n\n\tdest = (unsigned char *) malloc(dlen ? dlen : 1);\n\n\tif (dest == NULL) {\n\t\tprintf_error(\"not enough memory\");\n\t\tgoto out;\n\t}\n\n\t/* -- Decompress data -- */\n\n\toutlen = dlen;\n\n\tres = tinf_gzip_uncompress(dest, &outlen, source, len);\n\n\tif ((res != TINF_OK) || (outlen != dlen)) {\n\t\tprintf_error(\"decompression failed\");\n\t\tgoto out;\n\t}\n\n\tprintf(\"decompressed %u bytes\\n\", outlen);\n\n\t/* -- Write output -- */\n\n\tfwrite(dest, 1, outlen, fout);\n\n\tretval = EXIT_SUCCESS;\n\nout:\n\tif (fin != NULL) {\n\t\tfclose(fin);\n\t}\n\n\tif (fout != NULL) {\n\t\tfclose(fout);\n\t}\n\n\tif (source != NULL) {\n\t\tfree(source);\n\t}\n\n\tif (dest != NULL) {\n\t\tfree(dest);\n\t}\n\n\treturn retval;\n}\n"
  },
  {
    "path": "src/adler32.c",
    "content": "/*\n * Adler-32 checksum\n *\n * Copyright (c) 2003-2019 Joergen Ibsen\n *\n * This software is provided 'as-is', without any express or implied\n * warranty. In no event will the authors be held liable for any damages\n * arising from the use of this software.\n *\n * Permission is granted to anyone to use this software for any purpose,\n * including commercial applications, and to alter it and redistribute it\n * freely, subject to the following restrictions:\n *\n *   1. The origin of this software must not be misrepresented; you must\n *      not claim that you wrote the original software. If you use this\n *      software in a product, an acknowledgment in the product\n *      documentation would be appreciated but is not required.\n *\n *   2. Altered source versions must be plainly marked as such, and must\n *      not be misrepresented as being the original software.\n *\n *   3. This notice may not be removed or altered from any source\n *      distribution.\n */\n\n/*\n * Adler-32 algorithm taken from the zlib source, which is\n * Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler\n */\n\n#include \"tinf.h\"\n\n#define A32_BASE 65521\n#define A32_NMAX 5552\n\nunsigned int tinf_adler32(const void *data, unsigned int length)\n{\n\tconst unsigned char *buf = (const unsigned char *) data;\n\n\tunsigned int s1 = 1;\n\tunsigned int s2 = 0;\n\n\twhile (length > 0) {\n\t\tint k = length < A32_NMAX ? length : A32_NMAX;\n\t\tint i;\n\n\t\tfor (i = k / 16; i; --i, buf += 16) {\n\t\t\ts1 += buf[0];\n\t\t\ts2 += s1;\n\t\t\ts1 += buf[1];\n\t\t\ts2 += s1;\n\t\t\ts1 += buf[2];\n\t\t\ts2 += s1;\n\t\t\ts1 += buf[3];\n\t\t\ts2 += s1;\n\t\t\ts1 += buf[4];\n\t\t\ts2 += s1;\n\t\t\ts1 += buf[5];\n\t\t\ts2 += s1;\n\t\t\ts1 += buf[6];\n\t\t\ts2 += s1;\n\t\t\ts1 += buf[7];\n\t\t\ts2 += s1;\n\n\t\t\ts1 += buf[8];\n\t\t\ts2 += s1;\n\t\t\ts1 += buf[9];\n\t\t\ts2 += s1;\n\t\t\ts1 += buf[10];\n\t\t\ts2 += s1;\n\t\t\ts1 += buf[11];\n\t\t\ts2 += s1;\n\t\t\ts1 += buf[12];\n\t\t\ts2 += s1;\n\t\t\ts1 += buf[13];\n\t\t\ts2 += s1;\n\t\t\ts1 += buf[14];\n\t\t\ts2 += s1;\n\t\t\ts1 += buf[15];\n\t\t\ts2 += s1;\n\t\t}\n\n\t\tfor (i = k % 16; i; --i) {\n\t\t\ts1 += *buf++;\n\t\t\ts2 += s1;\n\t\t}\n\n\t\ts1 %= A32_BASE;\n\t\ts2 %= A32_BASE;\n\n\t\tlength -= k;\n\t}\n\n\treturn (s2 << 16) | s1;\n}\n"
  },
  {
    "path": "src/crc32.c",
    "content": "/*\n * CRC32 checksum\n *\n * Copyright (c) 1998-2019 Joergen Ibsen\n *\n * This software is provided 'as-is', without any express or implied\n * warranty. In no event will the authors be held liable for any damages\n * arising from the use of this software.\n *\n * Permission is granted to anyone to use this software for any purpose,\n * including commercial applications, and to alter it and redistribute it\n * freely, subject to the following restrictions:\n *\n *   1. The origin of this software must not be misrepresented; you must\n *      not claim that you wrote the original software. If you use this\n *      software in a product, an acknowledgment in the product\n *      documentation would be appreciated but is not required.\n *\n *   2. Altered source versions must be plainly marked as such, and must\n *      not be misrepresented as being the original software.\n *\n *   3. This notice may not be removed or altered from any source\n *      distribution.\n */\n\n/*\n * CRC32 algorithm taken from the zlib source, which is\n * Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler\n */\n\n#include \"tinf.h\"\n\nstatic const unsigned int tinf_crc32tab[16] = {\n\t0x00000000, 0x1DB71064, 0x3B6E20C8, 0x26D930AC, 0x76DC4190,\n\t0x6B6B51F4, 0x4DB26158, 0x5005713C, 0xEDB88320, 0xF00F9344,\n\t0xD6D6A3E8, 0xCB61B38C, 0x9B64C2B0, 0x86D3D2D4, 0xA00AE278,\n\t0xBDBDF21C\n};\n\nunsigned int tinf_crc32(const void *data, unsigned int length)\n{\n\tconst unsigned char *buf = (const unsigned char *) data;\n\tunsigned int crc = 0xFFFFFFFF;\n\tunsigned int i;\n\n\tif (length == 0) {\n\t\treturn 0;\n\t}\n\n\tfor (i = 0; i < length; ++i) {\n\t\tcrc ^= buf[i];\n\t\tcrc = tinf_crc32tab[crc & 0x0F] ^ (crc >> 4);\n\t\tcrc = tinf_crc32tab[crc & 0x0F] ^ (crc >> 4);\n\t}\n\n\treturn crc ^ 0xFFFFFFFF;\n}\n"
  },
  {
    "path": "src/tinf.h",
    "content": "/*\n * tinf - tiny inflate library (inflate, gzip, zlib)\n *\n * Copyright (c) 2003-2019 Joergen Ibsen\n *\n * This software is provided 'as-is', without any express or implied\n * warranty. In no event will the authors be held liable for any damages\n * arising from the use of this software.\n *\n * Permission is granted to anyone to use this software for any purpose,\n * including commercial applications, and to alter it and redistribute it\n * freely, subject to the following restrictions:\n *\n *   1. The origin of this software must not be misrepresented; you must\n *      not claim that you wrote the original software. If you use this\n *      software in a product, an acknowledgment in the product\n *      documentation would be appreciated but is not required.\n *\n *   2. Altered source versions must be plainly marked as such, and must\n *      not be misrepresented as being the original software.\n *\n *   3. This notice may not be removed or altered from any source\n *      distribution.\n */\n\n#ifndef TINF_H_INCLUDED\n#define TINF_H_INCLUDED\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define TINF_VER_MAJOR 1        /**< Major version number */\n#define TINF_VER_MINOR 2        /**< Minor version number */\n#define TINF_VER_PATCH 1        /**< Patch version number */\n#define TINF_VER_STRING \"1.2.1\" /**< Version number as a string */\n\n#ifndef TINFCC\n#  ifdef __WATCOMC__\n#    define TINFCC __cdecl\n#  else\n#    define TINFCC\n#  endif\n#endif\n\n/**\n * Status codes returned.\n *\n * @see tinf_uncompress, tinf_gzip_uncompress, tinf_zlib_uncompress\n */\ntypedef enum {\n\tTINF_OK         = 0,  /**< Success */\n\tTINF_DATA_ERROR = -3, /**< Input error */\n\tTINF_BUF_ERROR  = -5  /**< Not enough room for output */\n} tinf_error_code;\n\n/**\n * Initialize global data used by tinf.\n *\n * @deprecated No longer required, may be removed in a future version.\n */\nvoid TINFCC tinf_init(void);\n\n/**\n * Decompress `sourceLen` bytes of deflate data from `source` to `dest`.\n *\n * The variable `destLen` points to must contain the size of `dest` on entry,\n * and will be set to the size of the decompressed data on success.\n *\n * Reads at most `sourceLen` bytes from `source`.\n * Writes at most `*destLen` bytes to `dest`.\n *\n * @param dest pointer to where to place decompressed data\n * @param destLen pointer to variable containing size of `dest`\n * @param source pointer to compressed data\n * @param sourceLen size of compressed data\n * @return `TINF_OK` on success, error code on error\n */\nint TINFCC tinf_uncompress(void *dest, unsigned int *destLen,\n                           const void *source, unsigned int sourceLen);\n\n/**\n * Decompress `sourceLen` bytes of gzip data from `source` to `dest`.\n *\n * The variable `destLen` points to must contain the size of `dest` on entry,\n * and will be set to the size of the decompressed data on success.\n *\n * Reads at most `sourceLen` bytes from `source`.\n * Writes at most `*destLen` bytes to `dest`.\n *\n * @param dest pointer to where to place decompressed data\n * @param destLen pointer to variable containing size of `dest`\n * @param source pointer to compressed data\n * @param sourceLen size of compressed data\n * @return `TINF_OK` on success, error code on error\n */\nint TINFCC tinf_gzip_uncompress(void *dest, unsigned int *destLen,\n                                const void *source, unsigned int sourceLen);\n\n/**\n * Decompress `sourceLen` bytes of zlib data from `source` to `dest`.\n *\n * The variable `destLen` points to must contain the size of `dest` on entry,\n * and will be set to the size of the decompressed data on success.\n *\n * Reads at most `sourceLen` bytes from `source`.\n * Writes at most `*destLen` bytes to `dest`.\n *\n * @param dest pointer to where to place decompressed data\n * @param destLen pointer to variable containing size of `dest`\n * @param source pointer to compressed data\n * @param sourceLen size of compressed data\n * @return `TINF_OK` on success, error code on error\n */\nint TINFCC tinf_zlib_uncompress(void *dest, unsigned int *destLen,\n                                const void *source, unsigned int sourceLen);\n\n/**\n * Compute Adler-32 checksum of `length` bytes starting at `data`.\n *\n * @param data pointer to data\n * @param length size of data\n * @return Adler-32 checksum\n */\nunsigned int TINFCC tinf_adler32(const void *data, unsigned int length);\n\n/**\n * Compute CRC32 checksum of `length` bytes starting at `data`.\n *\n * @param data pointer to data\n * @param length size of data\n * @return CRC32 checksum\n */\nunsigned int TINFCC tinf_crc32(const void *data, unsigned int length);\n\n#ifdef __cplusplus\n} /* extern \"C\" */\n#endif\n\n#endif /* TINF_H_INCLUDED */\n"
  },
  {
    "path": "src/tinfgzip.c",
    "content": "/*\n * tinfgzip - tiny gzip decompressor\n *\n * Copyright (c) 2003-2019 Joergen Ibsen\n *\n * This software is provided 'as-is', without any express or implied\n * warranty. In no event will the authors be held liable for any damages\n * arising from the use of this software.\n *\n * Permission is granted to anyone to use this software for any purpose,\n * including commercial applications, and to alter it and redistribute it\n * freely, subject to the following restrictions:\n *\n *   1. The origin of this software must not be misrepresented; you must\n *      not claim that you wrote the original software. If you use this\n *      software in a product, an acknowledgment in the product\n *      documentation would be appreciated but is not required.\n *\n *   2. Altered source versions must be plainly marked as such, and must\n *      not be misrepresented as being the original software.\n *\n *   3. This notice may not be removed or altered from any source\n *      distribution.\n */\n\n#include \"tinf.h\"\n\ntypedef enum {\n\tFTEXT    = 1,\n\tFHCRC    = 2,\n\tFEXTRA   = 4,\n\tFNAME    = 8,\n\tFCOMMENT = 16\n} tinf_gzip_flag;\n\nstatic unsigned int read_le16(const unsigned char *p)\n{\n\treturn ((unsigned int) p[0])\n\t     | ((unsigned int) p[1] << 8);\n}\n\nstatic unsigned int read_le32(const unsigned char *p)\n{\n\treturn ((unsigned int) p[0])\n\t     | ((unsigned int) p[1] << 8)\n\t     | ((unsigned int) p[2] << 16)\n\t     | ((unsigned int) p[3] << 24);\n}\n\nint tinf_gzip_uncompress(void *dest, unsigned int *destLen,\n                         const void *source, unsigned int sourceLen)\n{\n\tconst unsigned char *src = (const unsigned char *) source;\n\tunsigned char *dst = (unsigned char *) dest;\n\tconst unsigned char *start;\n\tunsigned int dlen, crc32;\n\tint res;\n\tunsigned char flg;\n\n\t/* -- Check header -- */\n\n\t/* Check room for at least 10 byte header and 8 byte trailer */\n\tif (sourceLen < 18) {\n\t\treturn TINF_DATA_ERROR;\n\t}\n\n\t/* Check id bytes */\n\tif (src[0] != 0x1F || src[1] != 0x8B) {\n\t\treturn TINF_DATA_ERROR;\n\t}\n\n\t/* Check method is deflate */\n\tif (src[2] != 8) {\n\t\treturn TINF_DATA_ERROR;\n\t}\n\n\t/* Get flag byte */\n\tflg = src[3];\n\n\t/* Check that reserved bits are zero */\n\tif (flg & 0xE0) {\n\t\treturn TINF_DATA_ERROR;\n\t}\n\n\t/* -- Find start of compressed data -- */\n\n\t/* Skip base header of 10 bytes */\n\tstart = src + 10;\n\n\t/* Skip extra data if present */\n\tif (flg & FEXTRA) {\n\t\tunsigned int xlen = read_le16(start);\n\n\t\tif (xlen > sourceLen - 12) {\n\t\t\treturn TINF_DATA_ERROR;\n\t\t}\n\n\t\tstart += xlen + 2;\n\t}\n\n\t/* Skip file name if present */\n\tif (flg & FNAME) {\n\t\tdo {\n\t\t\tif (start - src >= sourceLen) {\n\t\t\t\treturn TINF_DATA_ERROR;\n\t\t\t}\n\t\t} while (*start++);\n\t}\n\n\t/* Skip file comment if present */\n\tif (flg & FCOMMENT) {\n\t\tdo {\n\t\t\tif (start - src >= sourceLen) {\n\t\t\t\treturn TINF_DATA_ERROR;\n\t\t\t}\n\t\t} while (*start++);\n\t}\n\n\t/* Check header crc if present */\n\tif (flg & FHCRC) {\n\t\tunsigned int hcrc;\n\n\t\tif (start - src > sourceLen - 2) {\n\t\t\treturn TINF_DATA_ERROR;\n\t\t}\n\n\t\thcrc = read_le16(start);\n\n\t\tif (hcrc != (tinf_crc32(src, start - src) & 0x0000FFFF)) {\n\t\t\treturn TINF_DATA_ERROR;\n\t\t}\n\n\t\tstart += 2;\n\t}\n\n\t/* -- Get decompressed length -- */\n\n\tdlen = read_le32(&src[sourceLen - 4]);\n\n\tif (dlen > *destLen) {\n\t\treturn TINF_BUF_ERROR;\n\t}\n\n\t/* -- Get CRC32 checksum of original data -- */\n\n\tcrc32 = read_le32(&src[sourceLen - 8]);\n\n\t/* -- Decompress data -- */\n\n\tif ((src + sourceLen) - start < 8) {\n\t\treturn TINF_DATA_ERROR;\n\t}\n\n\tres = tinf_uncompress(dst, destLen, start,\n\t                      (src + sourceLen) - start - 8);\n\n\tif (res != TINF_OK) {\n\t\treturn TINF_DATA_ERROR;\n\t}\n\n\tif (*destLen != dlen) {\n\t\treturn TINF_DATA_ERROR;\n\t}\n\n\t/* -- Check CRC32 checksum -- */\n\n\tif (crc32 != tinf_crc32(dst, dlen)) {\n\t\treturn TINF_DATA_ERROR;\n\t}\n\n\treturn TINF_OK;\n}\n"
  },
  {
    "path": "src/tinflate.c",
    "content": "/*\n * tinflate - tiny inflate\n *\n * Copyright (c) 2003-2019 Joergen Ibsen\n *\n * This software is provided 'as-is', without any express or implied\n * warranty. In no event will the authors be held liable for any damages\n * arising from the use of this software.\n *\n * Permission is granted to anyone to use this software for any purpose,\n * including commercial applications, and to alter it and redistribute it\n * freely, subject to the following restrictions:\n *\n *   1. The origin of this software must not be misrepresented; you must\n *      not claim that you wrote the original software. If you use this\n *      software in a product, an acknowledgment in the product\n *      documentation would be appreciated but is not required.\n *\n *   2. Altered source versions must be plainly marked as such, and must\n *      not be misrepresented as being the original software.\n *\n *   3. This notice may not be removed or altered from any source\n *      distribution.\n */\n\n#include \"tinf.h\"\n\n#include <assert.h>\n#include <limits.h>\n\n#if defined(UINT_MAX) && (UINT_MAX) < 0xFFFFFFFFUL\n#  error \"tinf requires unsigned int to be at least 32-bit\"\n#endif\n\n/* -- Internal data structures -- */\n\nstruct tinf_tree {\n\tunsigned short counts[16]; /* Number of codes with a given length */\n\tunsigned short symbols[288]; /* Symbols sorted by code */\n\tint max_sym;\n};\n\nstruct tinf_data {\n\tconst unsigned char *source;\n\tconst unsigned char *source_end;\n\tunsigned int tag;\n\tint bitcount;\n\tint overflow;\n\n\tunsigned char *dest_start;\n\tunsigned char *dest;\n\tunsigned char *dest_end;\n\n\tstruct tinf_tree ltree; /* Literal/length tree */\n\tstruct tinf_tree dtree; /* Distance tree */\n};\n\n/* -- Utility functions -- */\n\nstatic unsigned int read_le16(const unsigned char *p)\n{\n\treturn ((unsigned int) p[0])\n\t     | ((unsigned int) p[1] << 8);\n}\n\n/* Build fixed Huffman trees */\nstatic void tinf_build_fixed_trees(struct tinf_tree *lt, struct tinf_tree *dt)\n{\n\tint i;\n\n\t/* Build fixed literal/length tree */\n\tfor (i = 0; i < 16; ++i) {\n\t\tlt->counts[i] = 0;\n\t}\n\n\tlt->counts[7] = 24;\n\tlt->counts[8] = 152;\n\tlt->counts[9] = 112;\n\n\tfor (i = 0; i < 24; ++i) {\n\t\tlt->symbols[i] = 256 + i;\n\t}\n\tfor (i = 0; i < 144; ++i) {\n\t\tlt->symbols[24 + i] = i;\n\t}\n\tfor (i = 0; i < 8; ++i) {\n\t\tlt->symbols[24 + 144 + i] = 280 + i;\n\t}\n\tfor (i = 0; i < 112; ++i) {\n\t\tlt->symbols[24 + 144 + 8 + i] = 144 + i;\n\t}\n\n\tlt->max_sym = 285;\n\n\t/* Build fixed distance tree */\n\tfor (i = 0; i < 16; ++i) {\n\t\tdt->counts[i] = 0;\n\t}\n\n\tdt->counts[5] = 32;\n\n\tfor (i = 0; i < 32; ++i) {\n\t\tdt->symbols[i] = i;\n\t}\n\n\tdt->max_sym = 29;\n}\n\n/* Given an array of code lengths, build a tree */\nstatic int tinf_build_tree(struct tinf_tree *t, const unsigned char *lengths,\n                           unsigned int num)\n{\n\tunsigned short offs[16];\n\tunsigned int i, num_codes, available;\n\n\tassert(num <= 288);\n\n\tfor (i = 0; i < 16; ++i) {\n\t\tt->counts[i] = 0;\n\t}\n\n\tt->max_sym = -1;\n\n\t/* Count number of codes for each non-zero length */\n\tfor (i = 0; i < num; ++i) {\n\t\tassert(lengths[i] <= 15);\n\n\t\tif (lengths[i]) {\n\t\t\tt->max_sym = i;\n\t\t\tt->counts[lengths[i]]++;\n\t\t}\n\t}\n\n\t/* Compute offset table for distribution sort */\n\tfor (available = 1, num_codes = 0, i = 0; i < 16; ++i) {\n\t\tunsigned int used = t->counts[i];\n\n\t\t/* Check length contains no more codes than available */\n\t\tif (used > available) {\n\t\t\treturn TINF_DATA_ERROR;\n\t\t}\n\t\tavailable = 2 * (available - used);\n\n\t\toffs[i] = num_codes;\n\t\tnum_codes += used;\n\t}\n\n\t/*\n\t * Check all codes were used, or for the special case of only one\n\t * code that it has length 1\n\t */\n\tif ((num_codes > 1 && available > 0)\n\t || (num_codes == 1 && t->counts[1] != 1)) {\n\t\treturn TINF_DATA_ERROR;\n\t}\n\n\t/* Fill in symbols sorted by code */\n\tfor (i = 0; i < num; ++i) {\n\t\tif (lengths[i]) {\n\t\t\tt->symbols[offs[lengths[i]]++] = i;\n\t\t}\n\t}\n\n\t/*\n\t * For the special case of only one code (which will be 0) add a\n\t * code 1 which results in a symbol that is too large\n\t */\n\tif (num_codes == 1) {\n\t\tt->counts[1] = 2;\n\t\tt->symbols[1] = t->max_sym + 1;\n\t}\n\n\treturn TINF_OK;\n}\n\n/* -- Decode functions -- */\n\nstatic void tinf_refill(struct tinf_data *d, int num)\n{\n\tassert(num >= 0 && num <= 32);\n\n\t/* Read bytes until at least num bits available */\n\twhile (d->bitcount < num) {\n\t\tif (d->source != d->source_end) {\n\t\t\td->tag |= (unsigned int) *d->source++ << d->bitcount;\n\t\t}\n\t\telse {\n\t\t\td->overflow = 1;\n\t\t}\n\t\td->bitcount += 8;\n\t}\n\n\tassert(d->bitcount <= 32);\n}\n\nstatic unsigned int tinf_getbits_no_refill(struct tinf_data *d, int num)\n{\n\tunsigned int bits;\n\n\tassert(num >= 0 && num <= d->bitcount);\n\n\t/* Get bits from tag */\n\tbits = d->tag & ((1UL << num) - 1);\n\n\t/* Remove bits from tag */\n\td->tag >>= num;\n\td->bitcount -= num;\n\n\treturn bits;\n}\n\n/* Get num bits from source stream */\nstatic unsigned int tinf_getbits(struct tinf_data *d, int num)\n{\n\ttinf_refill(d, num);\n\treturn tinf_getbits_no_refill(d, num);\n}\n\n/* Read a num bit value from stream and add base */\nstatic unsigned int tinf_getbits_base(struct tinf_data *d, int num, int base)\n{\n\treturn base + (num ? tinf_getbits(d, num) : 0);\n}\n\n/* Given a data stream and a tree, decode a symbol */\nstatic int tinf_decode_symbol(struct tinf_data *d, const struct tinf_tree *t)\n{\n\tint base = 0, offs = 0;\n\tint len;\n\n\t/*\n\t * Get more bits while code index is above number of codes\n\t *\n\t * Rather than the actual code, we are computing the position of the\n\t * code in the sorted order of codes, which is the index of the\n\t * corresponding symbol.\n\t *\n\t * Conceptually, for each code length (level in the tree), there are\n\t * counts[len] leaves on the left and internal nodes on the right.\n\t * The index we have decoded so far is base + offs, and if that\n\t * falls within the leaves we are done. Otherwise we adjust the range\n\t * of offs and add one more bit to it.\n\t */\n\tfor (len = 1; ; ++len) {\n\t\toffs = 2 * offs + tinf_getbits(d, 1);\n\n\t\tassert(len <= 15);\n\n\t\tif (offs < t->counts[len]) {\n\t\t\tbreak;\n\t\t}\n\n\t\tbase += t->counts[len];\n\t\toffs -= t->counts[len];\n\t}\n\n\tassert(base + offs >= 0 && base + offs < 288);\n\n\treturn t->symbols[base + offs];\n}\n\n/* Given a data stream, decode dynamic trees from it */\nstatic int tinf_decode_trees(struct tinf_data *d, struct tinf_tree *lt,\n                             struct tinf_tree *dt)\n{\n\tunsigned char lengths[288 + 32];\n\n\t/* Special ordering of code length codes */\n\tstatic const unsigned char clcidx[19] = {\n\t\t16, 17, 18, 0,  8, 7,  9, 6, 10, 5,\n\t\t11,  4, 12, 3, 13, 2, 14, 1, 15\n\t};\n\n\tunsigned int hlit, hdist, hclen;\n\tunsigned int i, num, length;\n\tint res;\n\n\t/* Get 5 bits HLIT (257-286) */\n\thlit = tinf_getbits_base(d, 5, 257);\n\n\t/* Get 5 bits HDIST (1-32) */\n\thdist = tinf_getbits_base(d, 5, 1);\n\n\t/* Get 4 bits HCLEN (4-19) */\n\thclen = tinf_getbits_base(d, 4, 4);\n\n\t/*\n\t * The RFC limits the range of HLIT to 286, but lists HDIST as range\n\t * 1-32, even though distance codes 30 and 31 have no meaning. While\n\t * we could allow the full range of HLIT and HDIST to make it possible\n\t * to decode the fixed trees with this function, we consider it an\n\t * error here.\n\t *\n\t * See also: https://github.com/madler/zlib/issues/82\n\t */\n\tif (hlit > 286 || hdist > 30) {\n\t\treturn TINF_DATA_ERROR;\n\t}\n\n\tfor (i = 0; i < 19; ++i) {\n\t\tlengths[i] = 0;\n\t}\n\n\t/* Read code lengths for code length alphabet */\n\tfor (i = 0; i < hclen; ++i) {\n\t\t/* Get 3 bits code length (0-7) */\n\t\tunsigned int clen = tinf_getbits(d, 3);\n\n\t\tlengths[clcidx[i]] = clen;\n\t}\n\n\t/* Build code length tree (in literal/length tree to save space) */\n\tres = tinf_build_tree(lt, lengths, 19);\n\n\tif (res != TINF_OK) {\n\t\treturn res;\n\t}\n\n\t/* Check code length tree is not empty */\n\tif (lt->max_sym == -1) {\n\t\treturn TINF_DATA_ERROR;\n\t}\n\n\t/* Decode code lengths for the dynamic trees */\n\tfor (num = 0; num < hlit + hdist; ) {\n\t\tint sym = tinf_decode_symbol(d, lt);\n\n\t\tif (sym > lt->max_sym) {\n\t\t\treturn TINF_DATA_ERROR;\n\t\t}\n\n\t\tswitch (sym) {\n\t\tcase 16:\n\t\t\t/* Copy previous code length 3-6 times (read 2 bits) */\n\t\t\tif (num == 0) {\n\t\t\t\treturn TINF_DATA_ERROR;\n\t\t\t}\n\t\t\tsym = lengths[num - 1];\n\t\t\tlength = tinf_getbits_base(d, 2, 3);\n\t\t\tbreak;\n\t\tcase 17:\n\t\t\t/* Repeat code length 0 for 3-10 times (read 3 bits) */\n\t\t\tsym = 0;\n\t\t\tlength = tinf_getbits_base(d, 3, 3);\n\t\t\tbreak;\n\t\tcase 18:\n\t\t\t/* Repeat code length 0 for 11-138 times (read 7 bits) */\n\t\t\tsym = 0;\n\t\t\tlength = tinf_getbits_base(d, 7, 11);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\t/* Values 0-15 represent the actual code lengths */\n\t\t\tlength = 1;\n\t\t\tbreak;\n\t\t}\n\n\t\tif (length > hlit + hdist - num) {\n\t\t\treturn TINF_DATA_ERROR;\n\t\t}\n\n\t\twhile (length--) {\n\t\t\tlengths[num++] = sym;\n\t\t}\n\t}\n\n\t/* Check EOB symbol is present */\n\tif (lengths[256] == 0) {\n\t\treturn TINF_DATA_ERROR;\n\t}\n\n\t/* Build dynamic trees */\n\tres = tinf_build_tree(lt, lengths, hlit);\n\n\tif (res != TINF_OK) {\n\t\treturn res;\n\t}\n\n\tres = tinf_build_tree(dt, lengths + hlit, hdist);\n\n\tif (res != TINF_OK) {\n\t\treturn res;\n\t}\n\n\treturn TINF_OK;\n}\n\n/* -- Block inflate functions -- */\n\n/* Given a stream and two trees, inflate a block of data */\nstatic int tinf_inflate_block_data(struct tinf_data *d, struct tinf_tree *lt,\n                                   struct tinf_tree *dt)\n{\n\t/* Extra bits and base tables for length codes */\n\tstatic const unsigned char length_bits[30] = {\n\t\t0, 0, 0, 0, 0, 0, 0, 0, 1, 1,\n\t\t1, 1, 2, 2, 2, 2, 3, 3, 3, 3,\n\t\t4, 4, 4, 4, 5, 5, 5, 5, 0, 127\n\t};\n\n\tstatic const unsigned short length_base[30] = {\n\t\t 3,  4,  5,   6,   7,   8,   9,  10,  11,  13,\n\t\t15, 17, 19,  23,  27,  31,  35,  43,  51,  59,\n\t\t67, 83, 99, 115, 131, 163, 195, 227, 258,   0\n\t};\n\n\t/* Extra bits and base tables for distance codes */\n\tstatic const unsigned char dist_bits[30] = {\n\t\t0, 0,  0,  0,  1,  1,  2,  2,  3,  3,\n\t\t4, 4,  5,  5,  6,  6,  7,  7,  8,  8,\n\t\t9, 9, 10, 10, 11, 11, 12, 12, 13, 13\n\t};\n\n\tstatic const unsigned short dist_base[30] = {\n\t\t   1,    2,    3,    4,    5,    7,    9,    13,    17,    25,\n\t\t  33,   49,   65,   97,  129,  193,  257,   385,   513,   769,\n\t\t1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577\n\t};\n\n\tfor (;;) {\n\t\tint sym = tinf_decode_symbol(d, lt);\n\n\t\t/* Check for overflow in bit reader */\n\t\tif (d->overflow) {\n\t\t\treturn TINF_DATA_ERROR;\n\t\t}\n\n\t\tif (sym < 256) {\n\t\t\tif (d->dest == d->dest_end) {\n\t\t\t\treturn TINF_BUF_ERROR;\n\t\t\t}\n\t\t\t*d->dest++ = sym;\n\t\t}\n\t\telse {\n\t\t\tint length, dist, offs;\n\t\t\tint i;\n\n\t\t\t/* Check for end of block */\n\t\t\tif (sym == 256) {\n\t\t\t\treturn TINF_OK;\n\t\t\t}\n\n\t\t\t/* Check sym is within range and distance tree is not empty */\n\t\t\tif (sym > lt->max_sym || sym - 257 > 28 || dt->max_sym == -1) {\n\t\t\t\treturn TINF_DATA_ERROR;\n\t\t\t}\n\n\t\t\tsym -= 257;\n\n\t\t\t/* Possibly get more bits from length code */\n\t\t\tlength = tinf_getbits_base(d, length_bits[sym],\n\t\t\t                           length_base[sym]);\n\n\t\t\tdist = tinf_decode_symbol(d, dt);\n\n\t\t\t/* Check dist is within range */\n\t\t\tif (dist > dt->max_sym || dist > 29) {\n\t\t\t\treturn TINF_DATA_ERROR;\n\t\t\t}\n\n\t\t\t/* Possibly get more bits from distance code */\n\t\t\toffs = tinf_getbits_base(d, dist_bits[dist],\n\t\t\t                         dist_base[dist]);\n\n\t\t\tif (offs > d->dest - d->dest_start) {\n\t\t\t\treturn TINF_DATA_ERROR;\n\t\t\t}\n\n\t\t\tif (d->dest_end - d->dest < length) {\n\t\t\t\treturn TINF_BUF_ERROR;\n\t\t\t}\n\n\t\t\t/* Copy match */\n\t\t\tfor (i = 0; i < length; ++i) {\n\t\t\t\td->dest[i] = d->dest[i - offs];\n\t\t\t}\n\n\t\t\td->dest += length;\n\t\t}\n\t}\n}\n\n/* Inflate an uncompressed block of data */\nstatic int tinf_inflate_uncompressed_block(struct tinf_data *d)\n{\n\tunsigned int length, invlength;\n\n\tif (d->source_end - d->source < 4) {\n\t\treturn TINF_DATA_ERROR;\n\t}\n\n\t/* Get length */\n\tlength = read_le16(d->source);\n\n\t/* Get one's complement of length */\n\tinvlength = read_le16(d->source + 2);\n\n\t/* Check length */\n\tif (length != (~invlength & 0x0000FFFF)) {\n\t\treturn TINF_DATA_ERROR;\n\t}\n\n\td->source += 4;\n\n\tif (d->source_end - d->source < length) {\n\t\treturn TINF_DATA_ERROR;\n\t}\n\n\tif (d->dest_end - d->dest < length) {\n\t\treturn TINF_BUF_ERROR;\n\t}\n\n\t/* Copy block */\n\twhile (length--) {\n\t\t*d->dest++ = *d->source++;\n\t}\n\n\t/* Make sure we start next block on a byte boundary */\n\td->tag = 0;\n\td->bitcount = 0;\n\n\treturn TINF_OK;\n}\n\n/* Inflate a block of data compressed with fixed Huffman trees */\nstatic int tinf_inflate_fixed_block(struct tinf_data *d)\n{\n\t/* Build fixed Huffman trees */\n\ttinf_build_fixed_trees(&d->ltree, &d->dtree);\n\n\t/* Decode block using fixed trees */\n\treturn tinf_inflate_block_data(d, &d->ltree, &d->dtree);\n}\n\n/* Inflate a block of data compressed with dynamic Huffman trees */\nstatic int tinf_inflate_dynamic_block(struct tinf_data *d)\n{\n\t/* Decode trees from stream */\n\tint res = tinf_decode_trees(d, &d->ltree, &d->dtree);\n\n\tif (res != TINF_OK) {\n\t\treturn res;\n\t}\n\n\t/* Decode block using decoded trees */\n\treturn tinf_inflate_block_data(d, &d->ltree, &d->dtree);\n}\n\n/* -- Public functions -- */\n\n/* Initialize global (static) data */\nvoid tinf_init(void)\n{\n\treturn;\n}\n\n/* Inflate stream from source to dest */\nint tinf_uncompress(void *dest, unsigned int *destLen,\n                    const void *source, unsigned int sourceLen)\n{\n\tstruct tinf_data d;\n\tint bfinal;\n\n\t/* Initialise data */\n\td.source = (const unsigned char *) source;\n\td.source_end = d.source + sourceLen;\n\td.tag = 0;\n\td.bitcount = 0;\n\td.overflow = 0;\n\n\td.dest = (unsigned char *) dest;\n\td.dest_start = d.dest;\n\td.dest_end = d.dest + *destLen;\n\n\tdo {\n\t\tunsigned int btype;\n\t\tint res;\n\n\t\t/* Read final block flag */\n\t\tbfinal = tinf_getbits(&d, 1);\n\n\t\t/* Read block type (2 bits) */\n\t\tbtype = tinf_getbits(&d, 2);\n\n\t\t/* Decompress block */\n\t\tswitch (btype) {\n\t\tcase 0:\n\t\t\t/* Decompress uncompressed block */\n\t\t\tres = tinf_inflate_uncompressed_block(&d);\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\t/* Decompress block with fixed Huffman trees */\n\t\t\tres = tinf_inflate_fixed_block(&d);\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\t/* Decompress block with dynamic Huffman trees */\n\t\t\tres = tinf_inflate_dynamic_block(&d);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tres = TINF_DATA_ERROR;\n\t\t\tbreak;\n\t\t}\n\n\t\tif (res != TINF_OK) {\n\t\t\treturn res;\n\t\t}\n\t} while (!bfinal);\n\n\t/* Check for overflow in bit reader */\n\tif (d.overflow) {\n\t\treturn TINF_DATA_ERROR;\n\t}\n\n\t*destLen = d.dest - d.dest_start;\n\n\treturn TINF_OK;\n}\n\n/* clang -g -O1 -fsanitize=fuzzer,address -DTINF_FUZZING tinflate.c */\n#if defined(TINF_FUZZING)\n#include <limits.h>\n#include <stddef.h>\n#include <stdint.h>\n#include <stdlib.h>\n#include <string.h>\n\nunsigned char depacked[64 * 1024];\n\nextern int\nLLVMFuzzerTestOneInput(const uint8_t *data, size_t size)\n{\n\tif (size > UINT_MAX / 2) { return 0; }\n\tunsigned int destLen = sizeof(depacked);\n\ttinf_uncompress(depacked, &destLen, data, size);\n\treturn 0;\n}\n#endif\n"
  },
  {
    "path": "src/tinfzlib.c",
    "content": "/*\n * tinfzlib - tiny zlib decompressor\n *\n * Copyright (c) 2003-2019 Joergen Ibsen\n *\n * This software is provided 'as-is', without any express or implied\n * warranty. In no event will the authors be held liable for any damages\n * arising from the use of this software.\n *\n * Permission is granted to anyone to use this software for any purpose,\n * including commercial applications, and to alter it and redistribute it\n * freely, subject to the following restrictions:\n *\n *   1. The origin of this software must not be misrepresented; you must\n *      not claim that you wrote the original software. If you use this\n *      software in a product, an acknowledgment in the product\n *      documentation would be appreciated but is not required.\n *\n *   2. Altered source versions must be plainly marked as such, and must\n *      not be misrepresented as being the original software.\n *\n *   3. This notice may not be removed or altered from any source\n *      distribution.\n */\n\n#include \"tinf.h\"\n\nstatic unsigned int read_be32(const unsigned char *p)\n{\n\treturn ((unsigned int) p[0] << 24)\n\t     | ((unsigned int) p[1] << 16)\n\t     | ((unsigned int) p[2] << 8)\n\t     | ((unsigned int) p[3]);\n}\n\nint tinf_zlib_uncompress(void *dest, unsigned int *destLen,\n                         const void *source, unsigned int sourceLen)\n{\n\tconst unsigned char *src = (const unsigned char *) source;\n\tunsigned char *dst = (unsigned char *) dest;\n\tunsigned int a32;\n\tint res;\n\tunsigned char cmf, flg;\n\n\t/* -- Check header -- */\n\n\t/* Check room for at least 2 byte header and 4 byte trailer */\n\tif (sourceLen < 6) {\n\t\treturn TINF_DATA_ERROR;\n\t}\n\n\t/* Get header bytes */\n\tcmf = src[0];\n\tflg = src[1];\n\n\t/* Check checksum */\n\tif ((256 * cmf + flg) % 31) {\n\t\treturn TINF_DATA_ERROR;\n\t}\n\n\t/* Check method is deflate */\n\tif ((cmf & 0x0F) != 8) {\n\t\treturn TINF_DATA_ERROR;\n\t}\n\n\t/* Check window size is valid */\n\tif ((cmf >> 4) > 7) {\n\t\treturn TINF_DATA_ERROR;\n\t}\n\n\t/* Check there is no preset dictionary */\n\tif (flg & 0x20) {\n\t\treturn TINF_DATA_ERROR;\n\t}\n\n\t/* -- Get Adler-32 checksum of original data -- */\n\n\ta32 = read_be32(&src[sourceLen - 4]);\n\n\t/* -- Decompress data -- */\n\n\tres = tinf_uncompress(dst, destLen, src + 2, sourceLen - 6);\n\n\tif (res != TINF_OK) {\n\t\treturn TINF_DATA_ERROR;\n\t}\n\n\t/* -- Check Adler-32 checksum -- */\n\n\tif (a32 != tinf_adler32(dst, *destLen)) {\n\t\treturn TINF_DATA_ERROR;\n\t}\n\n\treturn TINF_OK;\n}\n"
  },
  {
    "path": "test/greatest.h",
    "content": "/*\n * Copyright (c) 2011-2021 Scott Vokes <vokes.s@gmail.com>\n *\n * Permission to use, copy, modify, and/or distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n#ifndef GREATEST_H\n#define GREATEST_H\n\n#if defined(__cplusplus) && !defined(GREATEST_NO_EXTERN_CPLUSPLUS)\nextern \"C\" {\n#endif\n\n/* 1.5.0 */\n#define GREATEST_VERSION_MAJOR 1\n#define GREATEST_VERSION_MINOR 5\n#define GREATEST_VERSION_PATCH 0\n\n/* A unit testing system for C, contained in 1 file.\n * It doesn't use dynamic allocation or depend on anything\n * beyond ANSI C89.\n *\n * An up-to-date version can be found at:\n *     https://github.com/silentbicycle/greatest/\n */\n\n\n/*********************************************************************\n * Minimal test runner template\n *********************************************************************/\n#if 0\n\n#include \"greatest.h\"\n\nTEST foo_should_foo(void) {\n    PASS();\n}\n\nstatic void setup_cb(void *data) {\n    printf(\"setup callback for each test case\\n\");\n}\n\nstatic void teardown_cb(void *data) {\n    printf(\"teardown callback for each test case\\n\");\n}\n\nSUITE(suite) {\n    /* Optional setup/teardown callbacks which will be run before/after\n     * every test case. If using a test suite, they will be cleared when\n     * the suite finishes. */\n    SET_SETUP(setup_cb, voidp_to_callback_data);\n    SET_TEARDOWN(teardown_cb, voidp_to_callback_data);\n\n    RUN_TEST(foo_should_foo);\n}\n\n/* Add definitions that need to be in the test runner's main file. */\nGREATEST_MAIN_DEFS();\n\n/* Set up, run suite(s) of tests, report pass/fail/skip stats. */\nint run_tests(void) {\n    GREATEST_INIT();            /* init. greatest internals */\n    /* List of suites to run (if any). */\n    RUN_SUITE(suite);\n\n    /* Tests can also be run directly, without using test suites. */\n    RUN_TEST(foo_should_foo);\n\n    GREATEST_PRINT_REPORT();          /* display results */\n    return greatest_all_passed();\n}\n\n/* main(), for a standalone command-line test runner.\n * This replaces run_tests above, and adds command line option\n * handling and exiting with a pass/fail status. */\nint main(int argc, char **argv) {\n    GREATEST_MAIN_BEGIN();      /* init & parse command-line args */\n    RUN_SUITE(suite);\n    GREATEST_MAIN_END();        /* display results */\n}\n\n#endif\n/*********************************************************************/\n\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <ctype.h>\n\n/***********\n * Options *\n ***********/\n\n/* Default column width for non-verbose output. */\n#ifndef GREATEST_DEFAULT_WIDTH\n#define GREATEST_DEFAULT_WIDTH 72\n#endif\n\n/* FILE *, for test logging. */\n#ifndef GREATEST_STDOUT\n#define GREATEST_STDOUT stdout\n#endif\n\n/* Remove GREATEST_ prefix from most commonly used symbols? */\n#ifndef GREATEST_USE_ABBREVS\n#define GREATEST_USE_ABBREVS 1\n#endif\n\n/* Set to 0 to disable all use of setjmp/longjmp. */\n#ifndef GREATEST_USE_LONGJMP\n#define GREATEST_USE_LONGJMP 0\n#endif\n\n/* Make it possible to replace fprintf with another\n * function with the same interface. */\n#ifndef GREATEST_FPRINTF\n#define GREATEST_FPRINTF fprintf\n#endif\n\n#if GREATEST_USE_LONGJMP\n#include <setjmp.h>\n#endif\n\n/* Set to 0 to disable all use of time.h / clock(). */\n#ifndef GREATEST_USE_TIME\n#define GREATEST_USE_TIME 1\n#endif\n\n#if GREATEST_USE_TIME\n#include <time.h>\n#endif\n\n/* Floating point type, for ASSERT_IN_RANGE. */\n#ifndef GREATEST_FLOAT\n#define GREATEST_FLOAT double\n#define GREATEST_FLOAT_FMT \"%g\"\n#endif\n\n/* Size of buffer for test name + optional '_' separator and suffix */\n#ifndef GREATEST_TESTNAME_BUF_SIZE\n#define GREATEST_TESTNAME_BUF_SIZE 128\n#endif\n\n\n/*********\n * Types *\n *********/\n\n/* Info for the current running suite. */\ntypedef struct greatest_suite_info {\n    unsigned int tests_run;\n    unsigned int passed;\n    unsigned int failed;\n    unsigned int skipped;\n\n#if GREATEST_USE_TIME\n    /* timers, pre/post running suite and individual tests */\n    clock_t pre_suite;\n    clock_t post_suite;\n    clock_t pre_test;\n    clock_t post_test;\n#endif\n} greatest_suite_info;\n\n/* Type for a suite function. */\ntypedef void greatest_suite_cb(void);\n\n/* Types for setup/teardown callbacks. If non-NULL, these will be run\n * and passed the pointer to their additional data. */\ntypedef void greatest_setup_cb(void *udata);\ntypedef void greatest_teardown_cb(void *udata);\n\n/* Type for an equality comparison between two pointers of the same type.\n * Should return non-0 if equal, otherwise 0.\n * UDATA is a closure value, passed through from ASSERT_EQUAL_T[m]. */\ntypedef int greatest_equal_cb(const void *expd, const void *got, void *udata);\n\n/* Type for a callback that prints a value pointed to by T.\n * Return value has the same meaning as printf's.\n * UDATA is a closure value, passed through from ASSERT_EQUAL_T[m]. */\ntypedef int greatest_printf_cb(const void *t, void *udata);\n\n/* Callbacks for an arbitrary type; needed for type-specific\n * comparisons via GREATEST_ASSERT_EQUAL_T[m].*/\ntypedef struct greatest_type_info {\n    greatest_equal_cb *equal;\n    greatest_printf_cb *print;\n} greatest_type_info;\n\ntypedef struct greatest_memory_cmp_env {\n    const unsigned char *exp;\n    const unsigned char *got;\n    size_t size;\n} greatest_memory_cmp_env;\n\n/* Callbacks for string and raw memory types. */\nextern greatest_type_info greatest_type_info_string;\nextern greatest_type_info greatest_type_info_memory;\n\ntypedef enum {\n    GREATEST_FLAG_FIRST_FAIL = 0x01,\n    GREATEST_FLAG_LIST_ONLY = 0x02,\n    GREATEST_FLAG_ABORT_ON_FAIL = 0x04\n} greatest_flag_t;\n\n/* Internal state for a PRNG, used to shuffle test order. */\nstruct greatest_prng {\n    unsigned char random_order; /* use random ordering? */\n    unsigned char initialized;  /* is random ordering initialized? */\n    unsigned char pad_0[6];\n    unsigned long state;        /* PRNG state */\n    unsigned long count;        /* how many tests, this pass */\n    unsigned long count_ceil;   /* total number of tests */\n    unsigned long count_run;    /* total tests run */\n    unsigned long a;            /* LCG multiplier */\n    unsigned long c;            /* LCG increment */\n    unsigned long m;            /* LCG modulus, based on count_ceil */\n};\n\n/* Struct containing all test runner state. */\ntypedef struct greatest_run_info {\n    unsigned char flags;\n    unsigned char verbosity;\n    unsigned char running_test; /* guard for nested RUN_TEST calls */\n    unsigned char exact_name_match;\n\n    unsigned int tests_run;     /* total test count */\n\n    /* currently running test suite */\n    greatest_suite_info suite;\n\n    /* overall pass/fail/skip counts */\n    unsigned int passed;\n    unsigned int failed;\n    unsigned int skipped;\n    unsigned int assertions;\n\n    /* info to print about the most recent failure */\n    unsigned int fail_line;\n    unsigned int pad_1;\n    const char *fail_file;\n    const char *msg;\n\n    /* current setup/teardown hooks and userdata */\n    greatest_setup_cb *setup;\n    void *setup_udata;\n    greatest_teardown_cb *teardown;\n    void *teardown_udata;\n\n    /* formatting info for \".....s...F\"-style output */\n    unsigned int col;\n    unsigned int width;\n\n    /* only run a specific suite or test */\n    const char *suite_filter;\n    const char *test_filter;\n    const char *test_exclude;\n    const char *name_suffix;    /* print suffix with test name */\n    char name_buf[GREATEST_TESTNAME_BUF_SIZE];\n\n    struct greatest_prng prng[2]; /* 0: suites, 1: tests */\n\n#if GREATEST_USE_TIME\n    /* overall timers */\n    clock_t begin;\n    clock_t end;\n#endif\n\n#if GREATEST_USE_LONGJMP\n    int pad_jmp_buf;\n    unsigned char pad_2[4];\n    jmp_buf jump_dest;\n#endif\n} greatest_run_info;\n\nstruct greatest_report_t {\n    /* overall pass/fail/skip counts */\n    unsigned int passed;\n    unsigned int failed;\n    unsigned int skipped;\n    unsigned int assertions;\n};\n\n/* Global var for the current testing context.\n * Initialized by GREATEST_MAIN_DEFS(). */\nextern greatest_run_info greatest_info;\n\n/* Type for ASSERT_ENUM_EQ's ENUM_STR argument. */\ntypedef const char *greatest_enum_str_fun(int value);\n\n\n/**********************\n * Exported functions *\n **********************/\n\n/* These are used internally by greatest macros. */\nint greatest_test_pre(const char *name);\nvoid greatest_test_post(int res);\nint greatest_do_assert_equal_t(const void *expd, const void *got,\n    greatest_type_info *type_info, void *udata);\nvoid greatest_prng_init_first_pass(int id);\nint greatest_prng_init_second_pass(int id, unsigned long seed);\nvoid greatest_prng_step(int id);\n\n/* These are part of the public greatest API. */\nvoid GREATEST_SET_SETUP_CB(greatest_setup_cb *cb, void *udata);\nvoid GREATEST_SET_TEARDOWN_CB(greatest_teardown_cb *cb, void *udata);\nvoid GREATEST_INIT(void);\nvoid GREATEST_PRINT_REPORT(void);\nint greatest_all_passed(void);\nvoid greatest_set_suite_filter(const char *filter);\nvoid greatest_set_test_filter(const char *filter);\nvoid greatest_set_test_exclude(const char *filter);\nvoid greatest_set_exact_name_match(void);\nvoid greatest_stop_at_first_fail(void);\nvoid greatest_abort_on_fail(void);\nvoid greatest_list_only(void);\nvoid greatest_get_report(struct greatest_report_t *report);\nunsigned int greatest_get_verbosity(void);\nvoid greatest_set_verbosity(unsigned int verbosity);\nvoid greatest_set_flag(greatest_flag_t flag);\nvoid greatest_set_test_suffix(const char *suffix);\n\n\n/********************\n* Language Support *\n********************/\n\n/* If __VA_ARGS__ (C99) is supported, allow parametric testing\n* without needing to manually manage the argument struct. */\n#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 19901L) ||        \\\n    (defined(_MSC_VER) && _MSC_VER >= 1800)\n#define GREATEST_VA_ARGS\n#endif\n\n\n/**********\n * Macros *\n **********/\n\n/* Define a suite. (The duplication is intentional -- it eliminates\n * a warning from -Wmissing-declarations.) */\n#define GREATEST_SUITE(NAME) void NAME(void); void NAME(void)\n\n/* Declare a suite, provided by another compilation unit. */\n#define GREATEST_SUITE_EXTERN(NAME) void NAME(void)\n\n/* Start defining a test function.\n * The arguments are not included, to allow parametric testing. */\n#define GREATEST_TEST static enum greatest_test_res\n\n/* PASS/FAIL/SKIP result from a test. Used internally. */\ntypedef enum greatest_test_res {\n    GREATEST_TEST_RES_PASS = 0,\n    GREATEST_TEST_RES_FAIL = -1,\n    GREATEST_TEST_RES_SKIP = 1\n} greatest_test_res;\n\n/* Run a suite. */\n#define GREATEST_RUN_SUITE(S_NAME) greatest_run_suite(S_NAME, #S_NAME)\n\n/* Run a test in the current suite. */\n#define GREATEST_RUN_TEST(TEST)                                         \\\n    do {                                                                \\\n        if (greatest_test_pre(#TEST) == 1) {                            \\\n            enum greatest_test_res res = GREATEST_SAVE_CONTEXT();       \\\n            if (res == GREATEST_TEST_RES_PASS) {                        \\\n                res = TEST();                                           \\\n            }                                                           \\\n            greatest_test_post(res);                                    \\\n        }                                                               \\\n    } while (0)\n\n/* Ignore a test, don't warn about it being unused. */\n#define GREATEST_IGNORE_TEST(TEST) (void)TEST\n\n/* Run a test in the current suite with one void * argument,\n * which can be a pointer to a struct with multiple arguments. */\n#define GREATEST_RUN_TEST1(TEST, ENV)                                   \\\n    do {                                                                \\\n        if (greatest_test_pre(#TEST) == 1) {                            \\\n            enum greatest_test_res res = GREATEST_SAVE_CONTEXT();       \\\n            if (res == GREATEST_TEST_RES_PASS) {                        \\\n                res = TEST(ENV);                                        \\\n            }                                                           \\\n            greatest_test_post(res);                                    \\\n        }                                                               \\\n    } while (0)\n\n#ifdef GREATEST_VA_ARGS\n#define GREATEST_RUN_TESTp(TEST, ...)                                   \\\n    do {                                                                \\\n        if (greatest_test_pre(#TEST) == 1) {                            \\\n            enum greatest_test_res res = GREATEST_SAVE_CONTEXT();       \\\n            if (res == GREATEST_TEST_RES_PASS) {                        \\\n                res = TEST(__VA_ARGS__);                                \\\n            }                                                           \\\n            greatest_test_post(res);                                    \\\n        }                                                               \\\n    } while (0)\n#endif\n\n\n/* Check if the test runner is in verbose mode. */\n#define GREATEST_IS_VERBOSE() ((greatest_info.verbosity) > 0)\n#define GREATEST_LIST_ONLY()                                            \\\n    (greatest_info.flags & GREATEST_FLAG_LIST_ONLY)\n#define GREATEST_FIRST_FAIL()                                           \\\n    (greatest_info.flags & GREATEST_FLAG_FIRST_FAIL)\n#define GREATEST_ABORT_ON_FAIL()                                        \\\n    (greatest_info.flags & GREATEST_FLAG_ABORT_ON_FAIL)\n#define GREATEST_FAILURE_ABORT()                                        \\\n    (GREATEST_FIRST_FAIL() &&                                           \\\n        (greatest_info.suite.failed > 0 || greatest_info.failed > 0))\n\n/* Message-less forms of tests defined below. */\n#define GREATEST_PASS() GREATEST_PASSm(NULL)\n#define GREATEST_FAIL() GREATEST_FAILm(NULL)\n#define GREATEST_SKIP() GREATEST_SKIPm(NULL)\n#define GREATEST_ASSERT(COND)                                           \\\n    GREATEST_ASSERTm(#COND, COND)\n#define GREATEST_ASSERT_OR_LONGJMP(COND)                                \\\n    GREATEST_ASSERT_OR_LONGJMPm(#COND, COND)\n#define GREATEST_ASSERT_FALSE(COND)                                     \\\n    GREATEST_ASSERT_FALSEm(#COND, COND)\n#define GREATEST_ASSERT_EQ(EXP, GOT)                                    \\\n    GREATEST_ASSERT_EQm(#EXP \" != \" #GOT, EXP, GOT)\n#define GREATEST_ASSERT_NEQ(EXP, GOT)                                   \\\n    GREATEST_ASSERT_NEQm(#EXP \" == \" #GOT, EXP, GOT)\n#define GREATEST_ASSERT_GT(EXP, GOT)                                    \\\n    GREATEST_ASSERT_GTm(#EXP \" <= \" #GOT, EXP, GOT)\n#define GREATEST_ASSERT_GTE(EXP, GOT)                                   \\\n    GREATEST_ASSERT_GTEm(#EXP \" < \" #GOT, EXP, GOT)\n#define GREATEST_ASSERT_LT(EXP, GOT)                                    \\\n    GREATEST_ASSERT_LTm(#EXP \" >= \" #GOT, EXP, GOT)\n#define GREATEST_ASSERT_LTE(EXP, GOT)                                   \\\n    GREATEST_ASSERT_LTEm(#EXP \" > \" #GOT, EXP, GOT)\n#define GREATEST_ASSERT_EQ_FMT(EXP, GOT, FMT)                           \\\n    GREATEST_ASSERT_EQ_FMTm(#EXP \" != \" #GOT, EXP, GOT, FMT)\n#define GREATEST_ASSERT_IN_RANGE(EXP, GOT, TOL)                         \\\n    GREATEST_ASSERT_IN_RANGEm(#EXP \" != \" #GOT \" +/- \" #TOL, EXP, GOT, TOL)\n#define GREATEST_ASSERT_EQUAL_T(EXP, GOT, TYPE_INFO, UDATA)             \\\n    GREATEST_ASSERT_EQUAL_Tm(#EXP \" != \" #GOT, EXP, GOT, TYPE_INFO, UDATA)\n#define GREATEST_ASSERT_STR_EQ(EXP, GOT)                                \\\n    GREATEST_ASSERT_STR_EQm(#EXP \" != \" #GOT, EXP, GOT)\n#define GREATEST_ASSERT_STRN_EQ(EXP, GOT, SIZE)                         \\\n    GREATEST_ASSERT_STRN_EQm(#EXP \" != \" #GOT, EXP, GOT, SIZE)\n#define GREATEST_ASSERT_MEM_EQ(EXP, GOT, SIZE)                          \\\n    GREATEST_ASSERT_MEM_EQm(#EXP \" != \" #GOT, EXP, GOT, SIZE)\n#define GREATEST_ASSERT_ENUM_EQ(EXP, GOT, ENUM_STR)                     \\\n    GREATEST_ASSERT_ENUM_EQm(#EXP \" != \" #GOT, EXP, GOT, ENUM_STR)\n\n/* The following forms take an additional message argument first,\n * to be displayed by the test runner. */\n\n/* Fail if a condition is not true, with message. */\n#define GREATEST_ASSERTm(MSG, COND)                                     \\\n    do {                                                                \\\n        greatest_info.assertions++;                                     \\\n        if (!(COND)) { GREATEST_FAILm(MSG); }                           \\\n    } while (0)\n\n/* Fail if a condition is not true, longjmping out of test. */\n#define GREATEST_ASSERT_OR_LONGJMPm(MSG, COND)                          \\\n    do {                                                                \\\n        greatest_info.assertions++;                                     \\\n        if (!(COND)) { GREATEST_FAIL_WITH_LONGJMPm(MSG); }              \\\n    } while (0)\n\n/* Fail if a condition is not false, with message. */\n#define GREATEST_ASSERT_FALSEm(MSG, COND)                               \\\n    do {                                                                \\\n        greatest_info.assertions++;                                     \\\n        if ((COND)) { GREATEST_FAILm(MSG); }                            \\\n    } while (0)\n\n/* Internal macro for relational assertions */\n#define GREATEST__REL(REL, MSG, EXP, GOT)                               \\\n    do {                                                                \\\n        greatest_info.assertions++;                                     \\\n        if (!((EXP) REL (GOT))) { GREATEST_FAILm(MSG); }                \\\n    } while (0)\n\n/* Fail if EXP is not ==, !=, >, <, >=, or <= to GOT. */\n#define GREATEST_ASSERT_EQm(MSG,E,G) GREATEST__REL(==, MSG,E,G)\n#define GREATEST_ASSERT_NEQm(MSG,E,G) GREATEST__REL(!=, MSG,E,G)\n#define GREATEST_ASSERT_GTm(MSG,E,G) GREATEST__REL(>, MSG,E,G)\n#define GREATEST_ASSERT_GTEm(MSG,E,G) GREATEST__REL(>=, MSG,E,G)\n#define GREATEST_ASSERT_LTm(MSG,E,G) GREATEST__REL(<, MSG,E,G)\n#define GREATEST_ASSERT_LTEm(MSG,E,G) GREATEST__REL(<=, MSG,E,G)\n\n/* Fail if EXP != GOT (equality comparison by ==).\n * Warning: FMT, EXP, and GOT will be evaluated more\n * than once on failure. */\n#define GREATEST_ASSERT_EQ_FMTm(MSG, EXP, GOT, FMT)                     \\\n    do {                                                                \\\n        greatest_info.assertions++;                                     \\\n        if ((EXP) != (GOT)) {                                           \\\n            GREATEST_FPRINTF(GREATEST_STDOUT, \"\\nExpected: \");          \\\n            GREATEST_FPRINTF(GREATEST_STDOUT, FMT, EXP);                \\\n            GREATEST_FPRINTF(GREATEST_STDOUT, \"\\n     Got: \");          \\\n            GREATEST_FPRINTF(GREATEST_STDOUT, FMT, GOT);                \\\n            GREATEST_FPRINTF(GREATEST_STDOUT, \"\\n\");                    \\\n            GREATEST_FAILm(MSG);                                        \\\n        }                                                               \\\n    } while (0)\n\n/* Fail if EXP is not equal to GOT, printing enum IDs. */\n#define GREATEST_ASSERT_ENUM_EQm(MSG, EXP, GOT, ENUM_STR)               \\\n    do {                                                                \\\n        int greatest_EXP = (int)(EXP);                                  \\\n        int greatest_GOT = (int)(GOT);                                  \\\n        greatest_enum_str_fun *greatest_ENUM_STR = ENUM_STR;            \\\n        if (greatest_EXP != greatest_GOT) {                             \\\n            GREATEST_FPRINTF(GREATEST_STDOUT, \"\\nExpected: %s\",         \\\n                greatest_ENUM_STR(greatest_EXP));                       \\\n            GREATEST_FPRINTF(GREATEST_STDOUT, \"\\n     Got: %s\\n\",       \\\n                greatest_ENUM_STR(greatest_GOT));                       \\\n            GREATEST_FAILm(MSG);                                        \\\n        }                                                               \\\n    } while (0)                                                         \\\n\n/* Fail if GOT not in range of EXP +|- TOL. */\n#define GREATEST_ASSERT_IN_RANGEm(MSG, EXP, GOT, TOL)                   \\\n    do {                                                                \\\n        GREATEST_FLOAT greatest_EXP = (EXP);                            \\\n        GREATEST_FLOAT greatest_GOT = (GOT);                            \\\n        GREATEST_FLOAT greatest_TOL = (TOL);                            \\\n        greatest_info.assertions++;                                     \\\n        if ((greatest_EXP > greatest_GOT &&                             \\\n                greatest_EXP - greatest_GOT > greatest_TOL) ||          \\\n            (greatest_EXP < greatest_GOT &&                             \\\n                greatest_GOT - greatest_EXP > greatest_TOL)) {          \\\n            GREATEST_FPRINTF(GREATEST_STDOUT,                           \\\n                \"\\nExpected: \" GREATEST_FLOAT_FMT                       \\\n                \" +/- \" GREATEST_FLOAT_FMT                              \\\n                \"\\n     Got: \" GREATEST_FLOAT_FMT                       \\\n                \"\\n\",                                                   \\\n                greatest_EXP, greatest_TOL, greatest_GOT);              \\\n            GREATEST_FAILm(MSG);                                        \\\n        }                                                               \\\n    } while (0)\n\n/* Fail if EXP is not equal to GOT, according to strcmp. */\n#define GREATEST_ASSERT_STR_EQm(MSG, EXP, GOT)                          \\\n    do {                                                                \\\n        GREATEST_ASSERT_EQUAL_Tm(MSG, EXP, GOT,                         \\\n            &greatest_type_info_string, NULL);                          \\\n    } while (0)                                                         \\\n\n/* Fail if EXP is not equal to GOT, according to strncmp. */\n#define GREATEST_ASSERT_STRN_EQm(MSG, EXP, GOT, SIZE)                   \\\n    do {                                                                \\\n        size_t size = SIZE;                                             \\\n        GREATEST_ASSERT_EQUAL_Tm(MSG, EXP, GOT,                         \\\n            &greatest_type_info_string, &size);                         \\\n    } while (0)                                                         \\\n\n/* Fail if EXP is not equal to GOT, according to memcmp. */\n#define GREATEST_ASSERT_MEM_EQm(MSG, EXP, GOT, SIZE)                    \\\n    do {                                                                \\\n        greatest_memory_cmp_env env;                                    \\\n        env.exp = (const unsigned char *)EXP;                           \\\n        env.got = (const unsigned char *)GOT;                           \\\n        env.size = SIZE;                                                \\\n        GREATEST_ASSERT_EQUAL_Tm(MSG, env.exp, env.got,                 \\\n            &greatest_type_info_memory, &env);                          \\\n    } while (0)                                                         \\\n\n/* Fail if EXP is not equal to GOT, according to a comparison\n * callback in TYPE_INFO. If they are not equal, optionally use a\n * print callback in TYPE_INFO to print them. */\n#define GREATEST_ASSERT_EQUAL_Tm(MSG, EXP, GOT, TYPE_INFO, UDATA)       \\\n    do {                                                                \\\n        greatest_type_info *type_info = (TYPE_INFO);                    \\\n        greatest_info.assertions++;                                     \\\n        if (!greatest_do_assert_equal_t(EXP, GOT,                       \\\n                type_info, UDATA)) {                                    \\\n            if (type_info == NULL || type_info->equal == NULL) {        \\\n                GREATEST_FAILm(\"type_info->equal callback missing!\");   \\\n            } else {                                                    \\\n                GREATEST_FAILm(MSG);                                    \\\n            }                                                           \\\n        }                                                               \\\n    } while (0)                                                         \\\n\n/* Pass. */\n#define GREATEST_PASSm(MSG)                                             \\\n    do {                                                                \\\n        greatest_info.msg = MSG;                                        \\\n        return GREATEST_TEST_RES_PASS;                                  \\\n    } while (0)\n\n/* Fail. */\n#define GREATEST_FAILm(MSG)                                             \\\n    do {                                                                \\\n        greatest_info.fail_file = __FILE__;                             \\\n        greatest_info.fail_line = __LINE__;                             \\\n        greatest_info.msg = MSG;                                        \\\n        if (GREATEST_ABORT_ON_FAIL()) { abort(); }                      \\\n        return GREATEST_TEST_RES_FAIL;                                  \\\n    } while (0)\n\n/* Optional GREATEST_FAILm variant that longjmps. */\n#if GREATEST_USE_LONGJMP\n#define GREATEST_FAIL_WITH_LONGJMP() GREATEST_FAIL_WITH_LONGJMPm(NULL)\n#define GREATEST_FAIL_WITH_LONGJMPm(MSG)                                \\\n    do {                                                                \\\n        greatest_info.fail_file = __FILE__;                             \\\n        greatest_info.fail_line = __LINE__;                             \\\n        greatest_info.msg = MSG;                                        \\\n        longjmp(greatest_info.jump_dest, GREATEST_TEST_RES_FAIL);       \\\n    } while (0)\n#endif\n\n/* Skip the current test. */\n#define GREATEST_SKIPm(MSG)                                             \\\n    do {                                                                \\\n        greatest_info.msg = MSG;                                        \\\n        return GREATEST_TEST_RES_SKIP;                                  \\\n    } while (0)\n\n/* Check the result of a subfunction using ASSERT, etc. */\n#define GREATEST_CHECK_CALL(RES)                                        \\\n    do {                                                                \\\n        enum greatest_test_res greatest_RES = RES;                      \\\n        if (greatest_RES != GREATEST_TEST_RES_PASS) {                   \\\n            return greatest_RES;                                        \\\n        }                                                               \\\n    } while (0)                                                         \\\n\n#if GREATEST_USE_TIME\n#define GREATEST_SET_TIME(NAME)                                         \\\n    NAME = clock();                                                     \\\n    if (NAME == (clock_t) -1) {                                         \\\n        GREATEST_FPRINTF(GREATEST_STDOUT,                               \\\n            \"clock error: %s\\n\", #NAME);                                \\\n        exit(EXIT_FAILURE);                                             \\\n    }\n\n#define GREATEST_CLOCK_DIFF(C1, C2)                                     \\\n    GREATEST_FPRINTF(GREATEST_STDOUT, \" (%lu ticks, %.3f sec)\",         \\\n        (long unsigned int) (C2) - (long unsigned int)(C1),             \\\n        (double)((C2) - (C1)) / (1.0 * (double)CLOCKS_PER_SEC))\n#else\n#define GREATEST_SET_TIME(UNUSED)\n#define GREATEST_CLOCK_DIFF(UNUSED1, UNUSED2)\n#endif\n\n#if GREATEST_USE_LONGJMP\n#define GREATEST_SAVE_CONTEXT()                                         \\\n        /* setjmp returns 0 (GREATEST_TEST_RES_PASS) on first call *    \\\n         * so the test runs, then RES_FAIL from FAIL_WITH_LONGJMP. */   \\\n        ((enum greatest_test_res)(setjmp(greatest_info.jump_dest)))\n#else\n#define GREATEST_SAVE_CONTEXT()                                         \\\n    /*a no-op, since setjmp/longjmp aren't being used */                \\\n    GREATEST_TEST_RES_PASS\n#endif\n\n/* Run every suite / test function run within BODY in pseudo-random\n * order, seeded by SEED. (The top 3 bits of the seed are ignored.)\n *\n * This should be called like:\n *     GREATEST_SHUFFLE_TESTS(seed, {\n *         GREATEST_RUN_TEST(some_test);\n *         GREATEST_RUN_TEST(some_other_test);\n *         GREATEST_RUN_TEST(yet_another_test);\n *     });\n *\n * Note that the body of the second argument will be evaluated\n * multiple times. */\n#define GREATEST_SHUFFLE_SUITES(SD, BODY) GREATEST_SHUFFLE(0, SD, BODY)\n#define GREATEST_SHUFFLE_TESTS(SD, BODY) GREATEST_SHUFFLE(1, SD, BODY)\n#define GREATEST_SHUFFLE(ID, SD, BODY)                                  \\\n    do {                                                                \\\n        struct greatest_prng *prng = &greatest_info.prng[ID];           \\\n        greatest_prng_init_first_pass(ID);                              \\\n        do {                                                            \\\n            prng->count = 0;                                            \\\n            if (prng->initialized) { greatest_prng_step(ID); }          \\\n            BODY;                                                       \\\n            if (!prng->initialized) {                                   \\\n                if (!greatest_prng_init_second_pass(ID, SD)) { break; } \\\n            } else if (prng->count_run == prng->count_ceil) {           \\\n                break;                                                  \\\n            }                                                           \\\n        } while (!GREATEST_FAILURE_ABORT());                            \\\n        prng->count_run = prng->random_order = prng->initialized = 0;   \\\n    } while(0)\n\n/* Include several function definitions in the main test file. */\n#define GREATEST_MAIN_DEFS()                                            \\\n                                                                        \\\n/* Is FILTER a subset of NAME? */                                       \\\nstatic int greatest_name_match(const char *name, const char *filter,    \\\n        int res_if_none) {                                              \\\n    size_t offset = 0;                                                  \\\n    size_t filter_len = filter ? strlen(filter) : 0;                    \\\n    if (filter_len == 0) { return res_if_none; } /* no filter */        \\\n    if (greatest_info.exact_name_match && strlen(name) != filter_len) { \\\n        return 0; /* ignore substring matches */                        \\\n    }                                                                   \\\n    while (name[offset] != '\\0') {                                      \\\n        if (name[offset] == filter[0]) {                                \\\n            if (0 == strncmp(&name[offset], filter, filter_len)) {      \\\n                return 1;                                               \\\n            }                                                           \\\n        }                                                               \\\n        offset++;                                                       \\\n    }                                                                   \\\n                                                                        \\\n    return 0;                                                           \\\n}                                                                       \\\n                                                                        \\\nstatic void greatest_buffer_test_name(const char *name) {               \\\n    struct greatest_run_info *g = &greatest_info;                       \\\n    size_t len = strlen(name), size = sizeof(g->name_buf);              \\\n    memset(g->name_buf, 0x00, size);                                    \\\n    (void)strncat(g->name_buf, name, size - 1);                         \\\n    if (g->name_suffix && (len + 1 < size)) {                           \\\n        g->name_buf[len] = '_';                                         \\\n        strncat(&g->name_buf[len+1], g->name_suffix, size-(len+2));     \\\n    }                                                                   \\\n}                                                                       \\\n                                                                        \\\n/* Before running a test, check the name filtering and                  \\\n * test shuffling state, if applicable, and then call setup hooks. */   \\\nint greatest_test_pre(const char *name) {                               \\\n    struct greatest_run_info *g = &greatest_info;                       \\\n    int match;                                                          \\\n    greatest_buffer_test_name(name);                                    \\\n    match = greatest_name_match(g->name_buf, g->test_filter, 1) &&      \\\n      !greatest_name_match(g->name_buf, g->test_exclude, 0);            \\\n    if (GREATEST_LIST_ONLY()) {   /* just listing test names */         \\\n        if (match) {                                                    \\\n            GREATEST_FPRINTF(GREATEST_STDOUT, \"  %s\\n\", g->name_buf);   \\\n        }                                                               \\\n        goto clear;                                                     \\\n    }                                                                   \\\n    if (match && (!GREATEST_FIRST_FAIL() || g->suite.failed == 0)) {    \\\n            struct greatest_prng *p = &g->prng[1];                      \\\n        if (p->random_order) {                                          \\\n            p->count++;                                                 \\\n            if (!p->initialized || ((p->count - 1) != p->state)) {      \\\n                goto clear;       /* don't run this test yet */         \\\n            }                                                           \\\n        }                                                               \\\n        if (g->running_test) {                                          \\\n            fprintf(stderr, \"Error: Test run inside another test.\\n\");  \\\n            return 0;                                                   \\\n        }                                                               \\\n        GREATEST_SET_TIME(g->suite.pre_test);                           \\\n        if (g->setup) { g->setup(g->setup_udata); }                     \\\n        p->count_run++;                                                 \\\n        g->running_test = 1;                                            \\\n        return 1;                 /* test should be run */              \\\n    } else {                                                            \\\n        goto clear;               /* skipped */                         \\\n    }                                                                   \\\nclear:                                                                  \\\n    g->name_suffix = NULL;                                              \\\n    return 0;                                                           \\\n}                                                                       \\\n                                                                        \\\nstatic void greatest_do_pass(void) {                                    \\\n    struct greatest_run_info *g = &greatest_info;                       \\\n    if (GREATEST_IS_VERBOSE()) {                                        \\\n        GREATEST_FPRINTF(GREATEST_STDOUT, \"PASS %s: %s\",                \\\n            g->name_buf, g->msg ? g->msg : \"\");                         \\\n    } else {                                                            \\\n        GREATEST_FPRINTF(GREATEST_STDOUT, \".\");                         \\\n    }                                                                   \\\n    g->suite.passed++;                                                  \\\n}                                                                       \\\n                                                                        \\\nstatic void greatest_do_fail(void) {                                    \\\n    struct greatest_run_info *g = &greatest_info;                       \\\n    if (GREATEST_IS_VERBOSE()) {                                        \\\n        GREATEST_FPRINTF(GREATEST_STDOUT,                               \\\n            \"FAIL %s: %s (%s:%u)\", g->name_buf,                         \\\n            g->msg ? g->msg : \"\", g->fail_file, g->fail_line);          \\\n    } else {                                                            \\\n        GREATEST_FPRINTF(GREATEST_STDOUT, \"F\");                         \\\n        g->col++;  /* add linebreak if in line of '.'s */               \\\n        if (g->col != 0) {                                              \\\n            GREATEST_FPRINTF(GREATEST_STDOUT, \"\\n\");                    \\\n            g->col = 0;                                                 \\\n        }                                                               \\\n        GREATEST_FPRINTF(GREATEST_STDOUT, \"FAIL %s: %s (%s:%u)\\n\",      \\\n            g->name_buf, g->msg ? g->msg : \"\",                          \\\n            g->fail_file, g->fail_line);                                \\\n    }                                                                   \\\n    g->suite.failed++;                                                  \\\n}                                                                       \\\n                                                                        \\\nstatic void greatest_do_skip(void) {                                    \\\n    struct greatest_run_info *g = &greatest_info;                       \\\n    if (GREATEST_IS_VERBOSE()) {                                        \\\n        GREATEST_FPRINTF(GREATEST_STDOUT, \"SKIP %s: %s\",                \\\n            g->name_buf, g->msg ? g->msg : \"\");                         \\\n    } else {                                                            \\\n        GREATEST_FPRINTF(GREATEST_STDOUT, \"s\");                         \\\n    }                                                                   \\\n    g->suite.skipped++;                                                 \\\n}                                                                       \\\n                                                                        \\\nvoid greatest_test_post(int res) {                                      \\\n    GREATEST_SET_TIME(greatest_info.suite.post_test);                   \\\n    if (greatest_info.teardown) {                                       \\\n        void *udata = greatest_info.teardown_udata;                     \\\n        greatest_info.teardown(udata);                                  \\\n    }                                                                   \\\n                                                                        \\\n    greatest_info.running_test = 0;                                     \\\n    if (res <= GREATEST_TEST_RES_FAIL) {                                \\\n        greatest_do_fail();                                             \\\n    } else if (res >= GREATEST_TEST_RES_SKIP) {                         \\\n        greatest_do_skip();                                             \\\n    } else if (res == GREATEST_TEST_RES_PASS) {                         \\\n        greatest_do_pass();                                             \\\n    }                                                                   \\\n    greatest_info.name_suffix = NULL;                                   \\\n    greatest_info.suite.tests_run++;                                    \\\n    greatest_info.col++;                                                \\\n    if (GREATEST_IS_VERBOSE()) {                                        \\\n        GREATEST_CLOCK_DIFF(greatest_info.suite.pre_test,               \\\n            greatest_info.suite.post_test);                             \\\n        GREATEST_FPRINTF(GREATEST_STDOUT, \"\\n\");                        \\\n    } else if (greatest_info.col % greatest_info.width == 0) {          \\\n        GREATEST_FPRINTF(GREATEST_STDOUT, \"\\n\");                        \\\n        greatest_info.col = 0;                                          \\\n    }                                                                   \\\n    fflush(GREATEST_STDOUT);                                            \\\n}                                                                       \\\n                                                                        \\\nstatic void report_suite(void) {                                        \\\n    if (greatest_info.suite.tests_run > 0) {                            \\\n        GREATEST_FPRINTF(GREATEST_STDOUT,                               \\\n            \"\\n%u test%s - %u passed, %u failed, %u skipped\",           \\\n            greatest_info.suite.tests_run,                              \\\n            greatest_info.suite.tests_run == 1 ? \"\" : \"s\",              \\\n            greatest_info.suite.passed,                                 \\\n            greatest_info.suite.failed,                                 \\\n            greatest_info.suite.skipped);                               \\\n        GREATEST_CLOCK_DIFF(greatest_info.suite.pre_suite,              \\\n            greatest_info.suite.post_suite);                            \\\n        GREATEST_FPRINTF(GREATEST_STDOUT, \"\\n\");                        \\\n    }                                                                   \\\n}                                                                       \\\n                                                                        \\\nstatic void update_counts_and_reset_suite(void) {                       \\\n    greatest_info.setup = NULL;                                         \\\n    greatest_info.setup_udata = NULL;                                   \\\n    greatest_info.teardown = NULL;                                      \\\n    greatest_info.teardown_udata = NULL;                                \\\n    greatest_info.passed += greatest_info.suite.passed;                 \\\n    greatest_info.failed += greatest_info.suite.failed;                 \\\n    greatest_info.skipped += greatest_info.suite.skipped;               \\\n    greatest_info.tests_run += greatest_info.suite.tests_run;           \\\n    memset(&greatest_info.suite, 0, sizeof(greatest_info.suite));       \\\n    greatest_info.col = 0;                                              \\\n}                                                                       \\\n                                                                        \\\nstatic int greatest_suite_pre(const char *suite_name) {                 \\\n    struct greatest_prng *p = &greatest_info.prng[0];                   \\\n    if (!greatest_name_match(suite_name, greatest_info.suite_filter, 1) \\\n        || (GREATEST_FAILURE_ABORT())) { return 0; }                    \\\n    if (p->random_order) {                                              \\\n        p->count++;                                                     \\\n        if (!p->initialized || ((p->count - 1) != p->state)) {          \\\n            return 0; /* don't run this suite yet */                    \\\n        }                                                               \\\n    }                                                                   \\\n    p->count_run++;                                                     \\\n    update_counts_and_reset_suite();                                    \\\n    GREATEST_FPRINTF(GREATEST_STDOUT, \"\\n* Suite %s:\\n\", suite_name);   \\\n    GREATEST_SET_TIME(greatest_info.suite.pre_suite);                   \\\n    return 1;                                                           \\\n}                                                                       \\\n                                                                        \\\nstatic void greatest_suite_post(void) {                                 \\\n    GREATEST_SET_TIME(greatest_info.suite.post_suite);                  \\\n    report_suite();                                                     \\\n}                                                                       \\\n                                                                        \\\nstatic void greatest_run_suite(greatest_suite_cb *suite_cb,             \\\n                               const char *suite_name) {                \\\n    if (greatest_suite_pre(suite_name)) {                               \\\n        suite_cb();                                                     \\\n        greatest_suite_post();                                          \\\n    }                                                                   \\\n}                                                                       \\\n                                                                        \\\nint greatest_do_assert_equal_t(const void *expd, const void *got,       \\\n        greatest_type_info *type_info, void *udata) {                   \\\n    int eq = 0;                                                         \\\n    if (type_info == NULL || type_info->equal == NULL) { return 0; }    \\\n    eq = type_info->equal(expd, got, udata);                            \\\n    if (!eq) {                                                          \\\n        if (type_info->print != NULL) {                                 \\\n            GREATEST_FPRINTF(GREATEST_STDOUT, \"\\nExpected: \");          \\\n            (void)type_info->print(expd, udata);                        \\\n            GREATEST_FPRINTF(GREATEST_STDOUT, \"\\n     Got: \");          \\\n            (void)type_info->print(got, udata);                         \\\n            GREATEST_FPRINTF(GREATEST_STDOUT, \"\\n\");                    \\\n        }                                                               \\\n    }                                                                   \\\n    return eq;                                                          \\\n}                                                                       \\\n                                                                        \\\nstatic void greatest_usage(const char *name) {                          \\\n    GREATEST_FPRINTF(GREATEST_STDOUT,                                   \\\n        \"Usage: %s [-hlfavex] [-s SUITE] [-t TEST] [-x EXCLUDE]\\n\"      \\\n        \"  -h, --help  print this Help\\n\"                               \\\n        \"  -l          List suites and tests, then exit (dry run)\\n\"    \\\n        \"  -f          Stop runner after first failure\\n\"               \\\n        \"  -a          Abort on first failure (implies -f)\\n\"           \\\n        \"  -v          Verbose output\\n\"                                \\\n        \"  -s SUITE    only run suites containing substring SUITE\\n\"    \\\n        \"  -t TEST     only run tests containing substring TEST\\n\"      \\\n        \"  -e          only run exact name match for -s or -t\\n\"        \\\n        \"  -x EXCLUDE  exclude tests containing substring EXCLUDE\\n\",   \\\n        name);                                                          \\\n}                                                                       \\\n                                                                        \\\nstatic void greatest_parse_options(int argc, char **argv) {             \\\n    int i = 0;                                                          \\\n    for (i = 1; i < argc; i++) {                                        \\\n        if (argv[i][0] == '-') {                                        \\\n            char f = argv[i][1];                                        \\\n            if ((f == 's' || f == 't' || f == 'x') && argc <= i + 1) {  \\\n                greatest_usage(argv[0]); exit(EXIT_FAILURE);            \\\n            }                                                           \\\n            switch (f) {                                                \\\n            case 's': /* suite name filter */                           \\\n                greatest_set_suite_filter(argv[i + 1]); i++; break;     \\\n            case 't': /* test name filter */                            \\\n                greatest_set_test_filter(argv[i + 1]); i++; break;      \\\n            case 'x': /* test name exclusion */                         \\\n                greatest_set_test_exclude(argv[i + 1]); i++; break;     \\\n            case 'e': /* exact name match */                            \\\n                greatest_set_exact_name_match(); break;                 \\\n            case 'f': /* first fail flag */                             \\\n                greatest_stop_at_first_fail(); break;                   \\\n            case 'a': /* abort() on fail flag */                        \\\n                greatest_abort_on_fail(); break;                        \\\n            case 'l': /* list only (dry run) */                         \\\n                greatest_list_only(); break;                            \\\n            case 'v': /* first fail flag */                             \\\n                greatest_info.verbosity++; break;                       \\\n            case 'h': /* help */                                        \\\n                greatest_usage(argv[0]); exit(EXIT_SUCCESS);            \\\n            default:                                                    \\\n            case '-':                                                   \\\n                if (0 == strncmp(\"--help\", argv[i], 6)) {               \\\n                    greatest_usage(argv[0]); exit(EXIT_SUCCESS);        \\\n                } else if (0 == strcmp(\"--\", argv[i])) {                \\\n                    return; /* ignore following arguments */            \\\n                }                                                       \\\n                GREATEST_FPRINTF(GREATEST_STDOUT,                       \\\n                    \"Unknown argument '%s'\\n\", argv[i]);                \\\n                greatest_usage(argv[0]);                                \\\n                exit(EXIT_FAILURE);                                     \\\n            }                                                           \\\n        }                                                               \\\n    }                                                                   \\\n}                                                                       \\\n                                                                        \\\nint greatest_all_passed(void) { return (greatest_info.failed == 0); }   \\\n                                                                        \\\nvoid greatest_set_test_filter(const char *filter) {                     \\\n    greatest_info.test_filter = filter;                                 \\\n}                                                                       \\\n                                                                        \\\nvoid greatest_set_test_exclude(const char *filter) {                    \\\n    greatest_info.test_exclude = filter;                                \\\n}                                                                       \\\n                                                                        \\\nvoid greatest_set_suite_filter(const char *filter) {                    \\\n    greatest_info.suite_filter = filter;                                \\\n}                                                                       \\\n                                                                        \\\nvoid greatest_set_exact_name_match(void) {                              \\\n    greatest_info.exact_name_match = 1;                                 \\\n}                                                                       \\\n                                                                        \\\nvoid greatest_stop_at_first_fail(void) {                                \\\n    greatest_set_flag(GREATEST_FLAG_FIRST_FAIL);                        \\\n}                                                                       \\\n                                                                        \\\nvoid greatest_abort_on_fail(void) {                                     \\\n    greatest_set_flag(GREATEST_FLAG_ABORT_ON_FAIL);                     \\\n}                                                                       \\\n                                                                        \\\nvoid greatest_list_only(void) {                                         \\\n    greatest_set_flag(GREATEST_FLAG_LIST_ONLY);                         \\\n}                                                                       \\\n                                                                        \\\nvoid greatest_get_report(struct greatest_report_t *report) {            \\\n    if (report) {                                                       \\\n        report->passed = greatest_info.passed;                          \\\n        report->failed = greatest_info.failed;                          \\\n        report->skipped = greatest_info.skipped;                        \\\n        report->assertions = greatest_info.assertions;                  \\\n    }                                                                   \\\n}                                                                       \\\n                                                                        \\\nunsigned int greatest_get_verbosity(void) {                             \\\n    return greatest_info.verbosity;                                     \\\n}                                                                       \\\n                                                                        \\\nvoid greatest_set_verbosity(unsigned int verbosity) {                   \\\n    greatest_info.verbosity = (unsigned char)verbosity;                 \\\n}                                                                       \\\n                                                                        \\\nvoid greatest_set_flag(greatest_flag_t flag) {                          \\\n    greatest_info.flags = (unsigned char)(greatest_info.flags | flag);  \\\n}                                                                       \\\n                                                                        \\\nvoid greatest_set_test_suffix(const char *suffix) {                     \\\n    greatest_info.name_suffix = suffix;                                 \\\n}                                                                       \\\n                                                                        \\\nvoid GREATEST_SET_SETUP_CB(greatest_setup_cb *cb, void *udata) {        \\\n    greatest_info.setup = cb;                                           \\\n    greatest_info.setup_udata = udata;                                  \\\n}                                                                       \\\n                                                                        \\\nvoid GREATEST_SET_TEARDOWN_CB(greatest_teardown_cb *cb, void *udata) {  \\\n    greatest_info.teardown = cb;                                        \\\n    greatest_info.teardown_udata = udata;                               \\\n}                                                                       \\\n                                                                        \\\nstatic int greatest_string_equal_cb(const void *expd, const void *got,  \\\n    void *udata) {                                                      \\\n    size_t *size = (size_t *)udata;                                     \\\n    return (size != NULL                                                \\\n        ? (0 == strncmp((const char *)expd, (const char *)got, *size))  \\\n        : (0 == strcmp((const char *)expd, (const char *)got)));        \\\n}                                                                       \\\n                                                                        \\\nstatic int greatest_string_printf_cb(const void *t, void *udata) {      \\\n    (void)udata; /* note: does not check \\0 termination. */             \\\n    return GREATEST_FPRINTF(GREATEST_STDOUT, \"%s\", (const char *)t);    \\\n}                                                                       \\\n                                                                        \\\ngreatest_type_info greatest_type_info_string = {                        \\\n    greatest_string_equal_cb, greatest_string_printf_cb,                \\\n};                                                                      \\\n                                                                        \\\nstatic int greatest_memory_equal_cb(const void *expd, const void *got,  \\\n    void *udata) {                                                      \\\n    greatest_memory_cmp_env *env = (greatest_memory_cmp_env *)udata;    \\\n    return (0 == memcmp(expd, got, env->size));                         \\\n}                                                                       \\\n                                                                        \\\n/* Hexdump raw memory, with differences highlighted */                  \\\nstatic int greatest_memory_printf_cb(const void *t, void *udata) {      \\\n    greatest_memory_cmp_env *env = (greatest_memory_cmp_env *)udata;    \\\n    const unsigned char *buf = (const unsigned char *)t;                \\\n    unsigned char diff_mark = ' ';                                      \\\n    FILE *out = GREATEST_STDOUT;                                        \\\n    size_t i, line_i, line_len = 0;                                     \\\n    int len = 0;   /* format hexdump with differences highlighted */    \\\n    for (i = 0; i < env->size; i+= line_len) {                          \\\n        diff_mark = ' ';                                                \\\n        line_len = env->size - i;                                       \\\n        if (line_len > 16) { line_len = 16; }                           \\\n        for (line_i = i; line_i < i + line_len; line_i++) {             \\\n            if (env->exp[line_i] != env->got[line_i]) diff_mark = 'X';  \\\n        }                                                               \\\n        len += GREATEST_FPRINTF(out, \"\\n%04x %c \",                      \\\n            (unsigned int)i, diff_mark);                                \\\n        for (line_i = i; line_i < i + line_len; line_i++) {             \\\n            int m = env->exp[line_i] == env->got[line_i]; /* match? */  \\\n            len += GREATEST_FPRINTF(out, \"%02x%c\",                      \\\n                buf[line_i], m ? ' ' : '<');                            \\\n        }                                                               \\\n        for (line_i = 0; line_i < 16 - line_len; line_i++) {            \\\n            len += GREATEST_FPRINTF(out, \"   \");                        \\\n        }                                                               \\\n        GREATEST_FPRINTF(out, \" \");                                     \\\n        for (line_i = i; line_i < i + line_len; line_i++) {             \\\n            unsigned char c = buf[line_i];                              \\\n            len += GREATEST_FPRINTF(out, \"%c\", isprint(c) ? c : '.');   \\\n        }                                                               \\\n    }                                                                   \\\n    len += GREATEST_FPRINTF(out, \"\\n\");                                 \\\n    return len;                                                         \\\n}                                                                       \\\n                                                                        \\\nvoid greatest_prng_init_first_pass(int id) {                            \\\n    greatest_info.prng[id].random_order = 1;                            \\\n    greatest_info.prng[id].count_run = 0;                               \\\n}                                                                       \\\n                                                                        \\\nint greatest_prng_init_second_pass(int id, unsigned long seed) {        \\\n    struct greatest_prng *p = &greatest_info.prng[id];                  \\\n    if (p->count == 0) { return 0; }                                    \\\n    p->count_ceil = p->count;                                           \\\n    for (p->m = 1; p->m < p->count; p->m <<= 1) {}                      \\\n    p->state = seed & 0x1fffffff;     /* only use lower 29 bits */      \\\n    p->a = 4LU * p->state;            /* to avoid overflow when */      \\\n    p->a = (p->a ? p->a : 4) | 1;            /* multiplied by 4 */      \\\n    p->c = 2147483647;        /* and so p->c ((2 ** 31) - 1) is */      \\\n    p->initialized = 1;     /* always relatively prime to p->a. */      \\\n    fprintf(stderr, \"init_second_pass: a %lu, c %lu, state %lu\\n\",      \\\n        p->a, p->c, p->state);                                          \\\n    return 1;                                                           \\\n}                                                                       \\\n                                                                        \\\n/* Step the pseudorandom number generator until its state reaches       \\\n * another test ID between 0 and the test count.                        \\\n * This use a linear congruential pseudorandom number generator,        \\\n * with the power-of-two ceiling of the test count as the modulus, the  \\\n * masked seed as the multiplier, and a prime as the increment. For     \\\n * each generated value < the test count, run the corresponding test.   \\\n * This will visit all IDs 0 <= X < mod once before repeating,          \\\n * with a starting position chosen based on the initial seed.           \\\n * For details, see: Knuth, The Art of Computer Programming             \\\n * Volume. 2, section 3.2.1. */                                         \\\nvoid greatest_prng_step(int id) {                                       \\\n    struct greatest_prng *p = &greatest_info.prng[id];                  \\\n    do {                                                                \\\n        p->state = ((p->a * p->state) + p->c) & (p->m - 1);             \\\n    } while (p->state >= p->count_ceil);                                \\\n}                                                                       \\\n                                                                        \\\nvoid GREATEST_INIT(void) {                                              \\\n    /* Suppress unused function warning if features aren't used */      \\\n    (void)greatest_run_suite;                                           \\\n    (void)greatest_parse_options;                                       \\\n    (void)greatest_prng_step;                                           \\\n    (void)greatest_prng_init_first_pass;                                \\\n    (void)greatest_prng_init_second_pass;                               \\\n    (void)greatest_set_test_suffix;                                     \\\n                                                                        \\\n    memset(&greatest_info, 0, sizeof(greatest_info));                   \\\n    greatest_info.width = GREATEST_DEFAULT_WIDTH;                       \\\n    GREATEST_SET_TIME(greatest_info.begin);                             \\\n}                                                                       \\\n                                                                        \\\n/* Report passes, failures, skipped tests, the number of                \\\n * assertions, and the overall run time. */                             \\\nvoid GREATEST_PRINT_REPORT(void) {                                      \\\n    if (!GREATEST_LIST_ONLY()) {                                        \\\n        update_counts_and_reset_suite();                                \\\n        GREATEST_SET_TIME(greatest_info.end);                           \\\n        GREATEST_FPRINTF(GREATEST_STDOUT,                               \\\n            \"\\nTotal: %u test%s\",                                       \\\n            greatest_info.tests_run,                                    \\\n            greatest_info.tests_run == 1 ? \"\" : \"s\");                   \\\n        GREATEST_CLOCK_DIFF(greatest_info.begin,                        \\\n            greatest_info.end);                                         \\\n        GREATEST_FPRINTF(GREATEST_STDOUT, \", %u assertion%s\\n\",         \\\n            greatest_info.assertions,                                   \\\n            greatest_info.assertions == 1 ? \"\" : \"s\");                  \\\n        GREATEST_FPRINTF(GREATEST_STDOUT,                               \\\n            \"Pass: %u, fail: %u, skip: %u.\\n\",                          \\\n            greatest_info.passed,                                       \\\n            greatest_info.failed, greatest_info.skipped);               \\\n    }                                                                   \\\n}                                                                       \\\n                                                                        \\\ngreatest_type_info greatest_type_info_memory = {                        \\\n    greatest_memory_equal_cb, greatest_memory_printf_cb,                \\\n};                                                                      \\\n                                                                        \\\ngreatest_run_info greatest_info\n\n/* Handle command-line arguments, etc. */\n#define GREATEST_MAIN_BEGIN()                                           \\\n    do {                                                                \\\n        GREATEST_INIT();                                                \\\n        greatest_parse_options(argc, argv);                             \\\n    } while (0)\n\n/* Report results, exit with exit status based on results. */\n#define GREATEST_MAIN_END()                                             \\\n    do {                                                                \\\n        GREATEST_PRINT_REPORT();                                        \\\n        return (greatest_all_passed() ? EXIT_SUCCESS : EXIT_FAILURE);   \\\n    } while (0)\n\n/* Make abbreviations without the GREATEST_ prefix for the\n * most commonly used symbols. */\n#if GREATEST_USE_ABBREVS\n#define TEST           GREATEST_TEST\n#define SUITE          GREATEST_SUITE\n#define SUITE_EXTERN   GREATEST_SUITE_EXTERN\n#define RUN_TEST       GREATEST_RUN_TEST\n#define RUN_TEST1      GREATEST_RUN_TEST1\n#define RUN_SUITE      GREATEST_RUN_SUITE\n#define IGNORE_TEST    GREATEST_IGNORE_TEST\n#define ASSERT         GREATEST_ASSERT\n#define ASSERTm        GREATEST_ASSERTm\n#define ASSERT_FALSE   GREATEST_ASSERT_FALSE\n#define ASSERT_EQ      GREATEST_ASSERT_EQ\n#define ASSERT_NEQ     GREATEST_ASSERT_NEQ\n#define ASSERT_GT      GREATEST_ASSERT_GT\n#define ASSERT_GTE     GREATEST_ASSERT_GTE\n#define ASSERT_LT      GREATEST_ASSERT_LT\n#define ASSERT_LTE     GREATEST_ASSERT_LTE\n#define ASSERT_EQ_FMT  GREATEST_ASSERT_EQ_FMT\n#define ASSERT_IN_RANGE GREATEST_ASSERT_IN_RANGE\n#define ASSERT_EQUAL_T GREATEST_ASSERT_EQUAL_T\n#define ASSERT_STR_EQ  GREATEST_ASSERT_STR_EQ\n#define ASSERT_STRN_EQ GREATEST_ASSERT_STRN_EQ\n#define ASSERT_MEM_EQ  GREATEST_ASSERT_MEM_EQ\n#define ASSERT_ENUM_EQ GREATEST_ASSERT_ENUM_EQ\n#define ASSERT_FALSEm  GREATEST_ASSERT_FALSEm\n#define ASSERT_EQm     GREATEST_ASSERT_EQm\n#define ASSERT_NEQm    GREATEST_ASSERT_NEQm\n#define ASSERT_GTm     GREATEST_ASSERT_GTm\n#define ASSERT_GTEm    GREATEST_ASSERT_GTEm\n#define ASSERT_LTm     GREATEST_ASSERT_LTm\n#define ASSERT_LTEm    GREATEST_ASSERT_LTEm\n#define ASSERT_EQ_FMTm GREATEST_ASSERT_EQ_FMTm\n#define ASSERT_IN_RANGEm GREATEST_ASSERT_IN_RANGEm\n#define ASSERT_EQUAL_Tm GREATEST_ASSERT_EQUAL_Tm\n#define ASSERT_STR_EQm GREATEST_ASSERT_STR_EQm\n#define ASSERT_STRN_EQm GREATEST_ASSERT_STRN_EQm\n#define ASSERT_MEM_EQm GREATEST_ASSERT_MEM_EQm\n#define ASSERT_ENUM_EQm GREATEST_ASSERT_ENUM_EQm\n#define PASS           GREATEST_PASS\n#define FAIL           GREATEST_FAIL\n#define SKIP           GREATEST_SKIP\n#define PASSm          GREATEST_PASSm\n#define FAILm          GREATEST_FAILm\n#define SKIPm          GREATEST_SKIPm\n#define SET_SETUP      GREATEST_SET_SETUP_CB\n#define SET_TEARDOWN   GREATEST_SET_TEARDOWN_CB\n#define CHECK_CALL     GREATEST_CHECK_CALL\n#define SHUFFLE_TESTS  GREATEST_SHUFFLE_TESTS\n#define SHUFFLE_SUITES GREATEST_SHUFFLE_SUITES\n\n#ifdef GREATEST_VA_ARGS\n#define RUN_TESTp      GREATEST_RUN_TESTp\n#endif\n\n#if GREATEST_USE_LONGJMP\n#define ASSERT_OR_LONGJMP  GREATEST_ASSERT_OR_LONGJMP\n#define ASSERT_OR_LONGJMPm GREATEST_ASSERT_OR_LONGJMPm\n#define FAIL_WITH_LONGJMP  GREATEST_FAIL_WITH_LONGJMP\n#define FAIL_WITH_LONGJMPm GREATEST_FAIL_WITH_LONGJMPm\n#endif\n\n#endif /* USE_ABBREVS */\n\n#if defined(__cplusplus) && !defined(GREATEST_NO_EXTERN_CPLUSPLUS)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "test/test_tinf.c",
    "content": "/*\n * tinf unit test\n *\n * Copyright (c) 2014-2022 Joergen Ibsen\n *\n * This software is provided 'as-is', without any express or implied\n * warranty. In no event will the authors be held liable for any damages\n * arising from the use of this software.\n *\n * Permission is granted to anyone to use this software for any purpose,\n * including commercial applications, and to alter it and redistribute it\n * freely, subject to the following restrictions:\n *\n *   1. The origin of this software must not be misrepresented; you must\n *      not claim that you wrote the original software. If you use this\n *      software in a product, an acknowledgment in the product\n *      documentation would be appreciated but is not required.\n *\n *   2. Altered source versions must be plainly marked as such, and must\n *      not be misrepresented as being the original software.\n *\n *   3. This notice may not be removed or altered from any source\n *      distribution.\n */\n\n#include \"tinf.h\"\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <time.h>\n\n#include \"greatest.h\"\n\n#ifndef ARRAY_SIZE\n#  define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))\n#endif\n\nstatic const unsigned char robuffer[] = { 0 };\n\nstatic unsigned char buffer[4096];\n\nstruct packed_data {\n\tunsigned int src_size;\n\tunsigned int depacked_size;\n\tconst unsigned char data[32];\n};\n\nstatic const struct packed_data inflate_errors[] = {\n\t/* Unable to read first byte */\n\t{ 0, 1, { 0x42 } },\n\t/* No next block after non-final block */\n\t{ 5, 1, { 0x00, 0x00, 0x00, 0xFF, 0xFF } },\n\t/* Invalid block type 11 */\n\t{ 13, 1, { 0x07, 0xCA, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0xFF, 0x6B, 0x01, 0x00 } },\n\n\t/* Uncompressed block incomplete */\n\t{ 4, 1, { 0x01, 0x00, 0x00, 0xFF } },\n\t/* Uncompressed block inv length wrong */\n\t{ 5, 1, { 0x01, 0x00, 0x00, 0x00, 0x00 } },\n\t/* Uncompressed block missing data */\n\t{ 5, 1, { 0x01, 0x01, 0x00, 0xFE, 0xFF } },\n\t/* Uncompressed block writing one past end */\n\t{ 7, 1, { 0x01, 0x02, 0x00, 0xFD, 0xFF, 0x42, 0x42 } },\n\n\t/* Fixed incomplete */\n\t{ 2, 1, { 0x63, 0x00 } },\n\t/* Fixed reading one byte before start */\n\t{ 4, 4, { 0x63, 0x00, 0x42, 0x00 } },\n\t/* Fixed literal writing one byte past end */\n\t{ 4, 1, { 0x63, 0x60, 0x00, 0x00 } },\n\t/* Fixed match writing one byte past end */\n\t{ 4, 3, { 0x63, 0x00, 0x02, 0x00 } },\n\t/* Fixed len > 285 */\n\t{ 4, 1024, { 0x63, 0x18, 0x03, 0x00 } },\n\t/* Fixed dist > 29 */\n\t{ 4, 4, { 0x63, 0x00, 0x3E, 0x00 } },\n\n\t/* Dynamic incomplete no HDIST */\n\t{ 1, 1, { 0x05 } },\n\t/* Dynamic incomplete HCLEN */\n\t{ 2, 1, { 0x05, 0x00 } },\n\t/* Dynamic incomplete code length code lengths */\n\t{ 4, 1, { 0x05, 0x40, 0x00, 0x04 } },\n\t/* Dynamic code length code lengths all zero*/\n\t{ 6, 1, { 0x05, 0x0B, 0x00, 0x00, 0x00, 0x00 } },\n\t/* Dynamic incomplete literal code lengths */\n\t{ 4, 1, { 0x05, 0x20, 0x00, 0x04 } },\n\t/* Dynamic 256 has code length 0 */\n\t{ 13, 1, { 0x05, 0xCB, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xFF, 0xD7, 0x02, 0x00 } },\n\t/* Dynamic only 256 available, but data contains 1 bit */\n\t{ 13, 1, { 0x05, 0xCA, 0x81, 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x7F, 0xEB, 0x00, 0x02 } },\n\t/* Dynamic only one distance code, but compressed data contains 1 bit */\n\t{ 13, 4, { 0x0D, 0xC0, 0x81, 0x00, 0x00, 0x00, 0x00, 0x80, 0xA0, 0xFC, 0xA9, 0x3F, 0x0F } },\n\t/* Dynamic all distance codes zero, but compressed data contains match */\n\t{ 14, 4, { 0x0D, 0xCA, 0x81, 0x00, 0x00, 0x00, 0x00, 0x80, 0xA0, 0xFC, 0xA9, 0x1F, 0xC0, 0x02 } },\n\t/* Dynamic only one code length code length, but compressed data contains 1 bit */\n\t{ 8, 4, { 0x05, 0x00, 0x80, 0xC0, 0xBF, 0x37, 0x00, 0x00 } },\n\t/* Dynamic first code length code is copy prev length  */\n\t{ 13, 1, { 0x05, 0xCA, 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0xF1, 0x87, 0x0E, 0x00 } },\n\t/* Dynamic underfull code length in code length code (missing len 2 code) */\n\t{ 13, 1, { 0x05, 0xCA, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x7F, 0xEB, 0x00, 0x00 } },\n\t/* Dynamic overfull code length in code length code (extra len 2 code) */\n\t{ 13, 1, { 0x05, 0xCA, 0x81, 0x00, 0x00, 0x00, 0x00, 0x82, 0x20, 0x7F, 0xEB, 0x00, 0x00 } },\n\t/* Dynamic overfull code length in literal/length code (extra len 1 codes) */\n\t{ 15, 4, { 0x0D, 0xC3, 0x37, 0x01, 0x00, 0x00, 0x00, 0x80, 0x20, 0x46, 0xFF, 0xCE, 0xCA, 0x61, 0x01 } },\n\t/* Dynamic underfull code length in distance code (missing len 2 code) */\n\t{ 14, 4, { 0x0D, 0xCE, 0x81, 0x00, 0x00, 0x00, 0x00, 0x80, 0xA0, 0xFD, 0xA9, 0xBB, 0x09, 0x1A } },\n\t/* Dynamic overfull code length in distance code (extra len 2 code) */\n\t{ 15, 4, { 0x0D, 0xCE, 0x81, 0x00, 0x00, 0x00, 0x00, 0x80, 0xA0, 0xFD, 0xA9, 0xBB, 0x1F, 0xA0, 0x01 } },\n\t/* Dynamic HLIT too large (30 = 287) */\n\t{ 15, 4, { 0xF5, 0xCB, 0x81, 0x00, 0x00, 0x00, 0x00, 0x80, 0xA0, 0xFC, 0xA9, 0x9F, 0x24, 0x00, 0x01 } },\n\t/* Dynamic HDIST too large (30 = 31) */\n\t{ 15, 4, { 0xED, 0xDE, 0x81, 0x00, 0x00, 0x00, 0x00, 0x80, 0xA0, 0xFC, 0xA9, 0x5F, 0x24, 0x13, 0x01 } },\n\t/* Dynamic number of literal/length codes too large (last repeat exceeds limit) */\n\t{ 15, 4, { 0x0D, 0xCB, 0x37, 0x01, 0x00, 0x00, 0x00, 0x80, 0x20, 0xFA, 0xA7, 0x56, 0x08, 0x60, 0x01 } }\n};\n\nstatic const struct packed_data zlib_errors[] = {\n\t/* Too short (not enough room for 2 byte header and 4 byte trailer) */\n\t{ 5, 1, { 0x78, 0x9C, 0x63, 0x00, 0x00 } },\n\t/* Too short, but last 4 bytes are valid Adler-32 */\n\t{ 8, 1, { 0x78, 0x9C, 0x63, 0x04, 0x00, 0x02, 0x00, 0x02 } },\n\t/* Header checksum error */\n\t{ 9, 1, { 0x78, 0x9D, 0x63, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01 } },\n\t/* Method not deflate */\n\t{ 9, 1, { 0x74, 0x9D, 0x63, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01 } },\n\t/* Window size invalid */\n\t{ 9, 1, { 0x88, 0x98, 0x63, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01 } },\n\t/* Preset dictionary (not supported by tinf) */\n\t{ 13, 1, { 0x78, 0xBB, 0x00, 0x00, 0x00, 0x01, 0x63, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01 } },\n\n\t/* Adler-32 checksum does not match value in trailer */\n\t{ 9, 1, { 0x78, 0x9C, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } },\n\n\t/* Decompression error (bad block type) */\n\t{ 9, 1, { 0x78, 0x9C, 0x67, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01 } }\n};\n\nstatic const struct packed_data gzip_errors[] = {\n\t/* Too short (not enough room for 10 byte header and 8 byte trailer) */\n\t{ 17, 1, { 0x1F, 0x8B, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0B, 0x63, 0x00, 0x00, 0x8D, 0xEF, 0x02, 0xD2 } },\n\t/* Too short, but last 8 bytes are valid CRC32 and size */\n\t{ 19, 1, { 0x1F, 0x8B, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0B, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t/* Error in first id byte */\n\t{ 21, 1, { 0x1E, 0x8B, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0B, 0x63, 0x00, 0x00, 0x8D, 0xEF, 0x02, 0xD2, 0x01, 0x00, 0x00, 0x00 } },\n\t/* Error in second id byte */\n\t{ 21, 1, { 0x1F, 0x8A, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0B, 0x63, 0x00, 0x00, 0x8D, 0xEF, 0x02, 0xD2, 0x01, 0x00, 0x00, 0x00 } },\n\t/* Method not deflate */\n\t{ 21, 1, { 0x1F, 0x8B, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0B, 0x63, 0x00, 0x00, 0x8D, 0xEF, 0x02, 0xD2, 0x01, 0x00, 0x00, 0x00 } },\n\t/* Reserved flag bit set */\n\t{ 21, 1, { 0x1F, 0x8B, 0x08, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0B, 0x63, 0x00, 0x00, 0x8D, 0xEF, 0x02, 0xD2, 0x01, 0x00, 0x00, 0x00 } },\n\t/* Header CRC16 error */\n\t{ 23, 1, { 0x1F, 0x8B, 0x08, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0B, 0x17, 0x9C, 0x63, 0x00, 0x00, 0x8D, 0xEF, 0x02, 0xD2, 0x01, 0x00, 0x00, 0x00 } },\n\t/* Header CRC16 exceeds input size */\n\t{ 19, 1, { 0x1F, 0x8B, 0x08, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0B, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x00, 0x2E } },\n\t/* Filename exceeds input size */\n\t{ 19, 1, { 0x1F, 0x8B, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0B, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39 } },\n\t/* Comment exceeds input size */\n\t{ 19, 1, { 0x1F, 0x8B, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0B, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39 } },\n\t/* Extra data exceeds input size */\n\t{ 19, 1, { 0x1F, 0x8B, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0B, 0x08, 0x00, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37 } },\n\t/* Not enough room for trailer after comment */\n\t{ 19, 1, { 0x1F, 0x8B, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0B, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x00 } },\n\n\t/* Decompressed size does not match size in trailer */\n\t{ 21, 1, { 0x1F, 0x8B, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0B, 0x63, 0x00, 0x00, 0x8D, 0xEF, 0x02, 0xD2, 0x02, 0x00, 0x00, 0x00 } },\n\t/* CRC32 checksum does not match value in trailer */\n\t{ 21, 1, { 0x1F, 0x8B, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0B, 0x63, 0x00, 0x00, 0x8D, 0xEF, 0x01, 0xD2, 0x01, 0x00, 0x00, 0x00 } },\n\n\t/* Decompression error (bad block type) */\n\t{ 21, 1, { 0x1F, 0x8B, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0B, 0x67, 0x00, 0x00, 0x8D, 0xEF, 0x02, 0xD2, 0x01, 0x00, 0x00, 0x00 } }\n};\n\n/* tinflate */\n\nTEST inflate_padding(void)\n{\n\t/* Empty buffer, fixed, 6 bits of padding in the second byte set to 1 */\n\tstatic const unsigned char data[] = {\n\t\t0x03, 0xFC\n\t};\n\tunsigned int dlen = 0;\n\tint res;\n\n\tres = tinf_uncompress((void *) robuffer, &dlen, data, ARRAY_SIZE(data));\n\n\tASSERT(res == TINF_OK && dlen == 0);\n\n\tPASS();\n}\n\nTEST inflate_empty_no_literals(void)\n{\n\t/* Empty buffer, dynamic with 256 as only literal/length code\n\t *\n\t * You could argue that since the RFC only has an exception allowing\n\t * one symbol for the distance tree, the literal/length tree should\n\t * be complete. However gzip allows this.\n\t *\n\t * See also: https://github.com/madler/zlib/issues/75\n\t */\n\tstatic const unsigned char data[] = {\n\t\t0x05, 0xCA, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0xFF,\n\t\t0x6B, 0x01, 0x00\n\t};\n\tunsigned int dlen = 0;\n\tint res;\n\n\tres = tinf_uncompress((void *) robuffer, &dlen, data, ARRAY_SIZE(data));\n\n\tASSERT(res == TINF_OK && dlen == 0);\n\n\tPASS();\n}\n\nTEST inflate_huffman_only(void)\n{\n\t/* 256 zero bytes compressed using Huffman only (no match or distance codes) */\n\tstatic const unsigned char data[] = {\n\t\t0x05, 0xCA, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xFF,\n\t\t0xD5, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t\t0x00, 0x00, 0x00, 0x00, 0x02\n\t};\n\tunsigned char out[256];\n\tunsigned int dlen = ARRAY_SIZE(out);\n\tint res;\n\tsize_t i;\n\n\tmemset(out, 0xFF, ARRAY_SIZE(out));\n\n\tres = tinf_uncompress(out, &dlen, data, ARRAY_SIZE(data));\n\n\tASSERT(res == TINF_OK && dlen == ARRAY_SIZE(out));\n\n\tfor (i = 0; i < ARRAY_SIZE(out); ++i) {\n\t\tif (out[i]) {\n\t\t\tFAIL();\n\t\t}\n\t}\n\n\tPASS();\n}\n\nTEST inflate_rle(void)\n{\n\t/* 256 zero bytes compressed using RLE (only one distance code) */\n\tstatic const unsigned char data[] = {\n\t\t0xE5, 0xC0, 0x81, 0x00, 0x00, 0x00, 0x00, 0x80, 0xA0, 0xFC,\n\t\t0xA9, 0x07, 0x39, 0x73, 0x01\n\t};\n\tunsigned char out[256];\n\tunsigned int dlen = ARRAY_SIZE(out);\n\tint res;\n\tsize_t i;\n\n\tmemset(out, 0xFF, ARRAY_SIZE(out));\n\n\tres = tinf_uncompress(out, &dlen, data, ARRAY_SIZE(data));\n\n\tASSERT(res == TINF_OK && dlen == ARRAY_SIZE(out));\n\n\tfor (i = 0; i < ARRAY_SIZE(out); ++i) {\n\t\tif (out[i]) {\n\t\t\tFAIL();\n\t\t}\n\t}\n\n\tPASS();\n}\n\nTEST inflate_max_matchlen(void)\n{\n\t/* 259 zero bytes compressed using literal/length code 285 (len 258) */\n\tstatic const unsigned char data[] = {\n\t\t0xED, 0xCC, 0x81, 0x00, 0x00, 0x00, 0x00, 0x80, 0xA0, 0xFC,\n\t\t0xA9, 0x17, 0xB9, 0x00, 0x2C\n\t};\n\tunsigned char out[259];\n\tunsigned int dlen = ARRAY_SIZE(out);\n\tint res;\n\tsize_t i;\n\n\tmemset(out, 0xFF, ARRAY_SIZE(out));\n\n\tres = tinf_uncompress(out, &dlen, data, ARRAY_SIZE(data));\n\n\tASSERT(res == TINF_OK && dlen == ARRAY_SIZE(out));\n\n\tfor (i = 0; i < ARRAY_SIZE(out); ++i) {\n\t\tif (out[i]) {\n\t\t\tFAIL();\n\t\t}\n\t}\n\n\tPASS();\n}\n\nTEST inflate_max_matchlen_alt(void)\n{\n\t/* 259 zero bytes compressed using literal/length code 284 + 31 (len 258)\n\t *\n\t * Technically, this is outside the range specified in the RFC, but\n\t * gzip allows it.\n\t *\n\t * See also: https://github.com/madler/zlib/issues/75\n\t */\n\tstatic const unsigned char data[] = {\n\t\t0xE5, 0xCC, 0x81, 0x00, 0x00, 0x00, 0x00, 0x80, 0xA0, 0xFC,\n\t\t0xA9, 0x07, 0xB9, 0x00, 0xFC, 0x05\n\t};\n\tunsigned char out[259];\n\tunsigned int dlen = ARRAY_SIZE(out);\n\tint res;\n\tsize_t i;\n\n\tmemset(out, 0xFF, ARRAY_SIZE(out));\n\n\tres = tinf_uncompress(out, &dlen, data, ARRAY_SIZE(data));\n\n\tASSERT(res == TINF_OK && dlen == ARRAY_SIZE(out));\n\n\tfor (i = 0; i < ARRAY_SIZE(out); ++i) {\n\t\tif (out[i]) {\n\t\t\tFAIL();\n\t\t}\n\t}\n\n\tPASS();\n}\n\nTEST inflate_max_matchdist(void)\n{\n\t/* A match of length 3 with a distance of 32768 */\n\tstatic const unsigned char data[] = {\n\t\t0xED, 0xDD, 0x01, 0x01, 0x00, 0x00, 0x08, 0x02, 0x20, 0xED,\n\t\t0xFF, 0xE8, 0xFA, 0x11, 0x1C, 0x61, 0x9A, 0xF7, 0x00, 0x00,\n\t\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0,\n\t\t0xFE, 0xFF, 0x05\n\t};\n\tunsigned char out[32771];\n\tunsigned int dlen = ARRAY_SIZE(out);\n\tint res;\n\tsize_t i;\n\n\tmemset(out, 0xFF, ARRAY_SIZE(out));\n\n\tres = tinf_uncompress(out, &dlen, data, ARRAY_SIZE(data));\n\n\tASSERT(res == TINF_OK && dlen == ARRAY_SIZE(out));\n\n\tASSERT(out[0] == 2 && out[1] == 1 && out[2] == 0);\n\n\tfor (i = 3; i < ARRAY_SIZE(out) - 3; ++i) {\n\t\tif (out[i]) {\n\t\t\tFAIL();\n\t\t}\n\t}\n\n\tASSERT(out[ARRAY_SIZE(out) - 3] == 2);\n\tASSERT(out[ARRAY_SIZE(out) - 2] == 1);\n\tASSERT(out[ARRAY_SIZE(out) - 1] == 0);\n\n\tPASS();\n}\n\nTEST inflate_code_length_codes(void)\n{\n\t/* 4 zero bytes compressed, code length codes include codes 16, 17, and 18 */\n\tstatic const unsigned char data[] = {\n\t\t0x0D, 0xC3, 0x37, 0x01, 0x00, 0x00, 0x00, 0x80, 0x20, 0xFA,\n\t\t0x77, 0x1E, 0xCA, 0x61, 0x01\n\t};\n\tunsigned char out[4];\n\tunsigned int dlen = ARRAY_SIZE(out);\n\tint res;\n\tsize_t i;\n\n\tmemset(out, 0xFF, ARRAY_SIZE(out));\n\n\tres = tinf_uncompress(out, &dlen, data, ARRAY_SIZE(data));\n\n\tASSERT(res == TINF_OK && dlen == ARRAY_SIZE(out));\n\n\tfor (i = 0; i < ARRAY_SIZE(out); ++i) {\n\t\tif (out[i]) {\n\t\t\tFAIL();\n\t\t}\n\t}\n\n\tPASS();\n}\n\nTEST inflate_max_codelen(void)\n{\n\t/* Use all codeword lengths including 15 */\n\tstatic const unsigned char data[] = {\n\t\t0x05, 0xEA, 0x01, 0x82, 0x24, 0x49, 0x92, 0x24, 0x49, 0x02,\n\t\t0x12, 0x8B, 0x9A, 0x47, 0x56, 0xCF, 0xDE, 0xFF, 0x9F, 0x7B,\n\t\t0x0F, 0xD0, 0xEE, 0x7D, 0xBF, 0xBF, 0x7F, 0xFF, 0xFD, 0xEF,\n\t\t0xFF, 0xFE, 0xDF, 0xFF, 0xF7, 0xFF, 0xFB, 0xFF, 0x03\n\t};\n\tunsigned char out[15];\n\tunsigned int dlen = ARRAY_SIZE(out);\n\tint res;\n\tsize_t i;\n\n\tmemset(out, 0xFF, ARRAY_SIZE(out));\n\n\tres = tinf_uncompress(out, &dlen, data, ARRAY_SIZE(data));\n\n\tASSERT(res == TINF_OK && dlen == ARRAY_SIZE(out));\n\n\tfor (i = 0; i < ARRAY_SIZE(out); ++i) {\n\t\tif (out[i] != i) {\n\t\t\tFAIL();\n\t\t}\n\t}\n\n\tPASS();\n}\n\n/* Test tinf_uncompress on random data */\nTEST inflate_random(void)\n{\n\tunsigned char data[256];\n\tunsigned int len;\n\n\tfor (len = 1; len < ARRAY_SIZE(data); ++len) {\n\t\tunsigned int dlen = ARRAY_SIZE(buffer);\n\t\tsize_t i;\n\n\t\tfor (i = 0; i < len; ++i) {\n\t\t\tdata[i] = (unsigned char) rand();\n\t\t}\n\n\t\t/* Make sure btype is valid */\n\t\tif ((data[0] & 0x06) == 0x06) {\n\t\t\tdata[0] &= (rand() > RAND_MAX / 2) ? ~0x02 : ~0x04;\n\t\t}\n\n\t\ttinf_uncompress(buffer, &dlen, data, len);\n\t}\n\n\tPASS();\n}\n\n/* Test tinf_uncompress on compressed data with errors */\nTEST inflate_error_case(const void *closure)\n{\n\tconst struct packed_data *pd = (const struct packed_data *) closure;\n\tint res;\n\n\tunsigned int size = pd->depacked_size;\n\tres = tinf_uncompress(buffer, &size, pd->data, pd->src_size);\n\n\tASSERT(res != TINF_OK);\n\n\tPASS();\n}\n\nSUITE(tinflate)\n{\n\tchar suffix[32];\n\tsize_t i;\n\n\tRUN_TEST(inflate_padding);\n\tRUN_TEST(inflate_empty_no_literals);\n\tRUN_TEST(inflate_huffman_only);\n\tRUN_TEST(inflate_rle);\n\tRUN_TEST(inflate_max_matchlen);\n\tRUN_TEST(inflate_max_matchlen_alt);\n\tRUN_TEST(inflate_max_matchdist);\n\tRUN_TEST(inflate_code_length_codes);\n\tRUN_TEST(inflate_max_codelen);\n\n\tRUN_TEST(inflate_random);\n\n\tfor (i = 0; i < ARRAY_SIZE(inflate_errors); ++i) {\n\t\tsprintf(suffix, \"%d\", (int) i);\n\t\tgreatest_set_test_suffix(suffix);\n\t\tRUN_TEST1(inflate_error_case, &inflate_errors[i]);\n\t}\n}\n\n/* tinfzlib */\n\nTEST zlib_empty_raw(void)\n{\n\t/* Empty buffer, uncompressed */\n\tstatic const unsigned char data[] = {\n\t\t0x78, 0x9C, 0x01, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00,\n\t\t0x01\n\t};\n\tunsigned int dlen = 0;\n\tint res;\n\n\tres = tinf_zlib_uncompress((void *) robuffer, &dlen, data, ARRAY_SIZE(data));\n\n\tASSERT(res == TINF_OK && dlen == 0);\n\n\tPASS();\n}\n\nTEST zlib_empty_fixed(void)\n{\n\t/* Empty buffer, fixed Huffman */\n\tstatic const unsigned char data[] = {\n\t\t0x78, 0x9C, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01\n\t};\n\tunsigned int dlen = 0;\n\tint res;\n\n\tres = tinf_zlib_uncompress((void *) robuffer, &dlen, data, ARRAY_SIZE(data));\n\n\tASSERT(res == TINF_OK && dlen == 0);\n\n\tPASS();\n}\n\nTEST zlib_empty_dynamic(void)\n{\n\t/* Empty buffer, dynamic Huffman */\n\tstatic const unsigned char data[] = {\n\t\t0x78, 0x9C, 0x05, 0xC1, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t\t0x10, 0xFF, 0xD5, 0x08, 0x00, 0x00, 0x00, 0x01\n\t};\n\tunsigned int dlen = 0;\n\tint res;\n\n\tres = tinf_zlib_uncompress((void *) robuffer, &dlen, data, ARRAY_SIZE(data));\n\n\tASSERT(res == TINF_OK && dlen == 0);\n\n\tPASS();\n}\n\nTEST zlib_onebyte_raw(void)\n{\n\t/* One byte 00, uncompressed */\n\tstatic const unsigned char data[] = {\n\t\t0x78, 0x9C, 0x01, 0x01, 0x00, 0xFE, 0xFF, 0x00, 0x00, 0x01,\n\t\t0x00, 0x01\n\t};\n\tunsigned char out[] = { 0xFF };\n\tunsigned int dlen = 1;\n\tint res;\n\n\tres = tinf_zlib_uncompress(out, &dlen, data, ARRAY_SIZE(data));\n\n\tASSERT(res == TINF_OK && dlen == 1 && out[0] == 0);\n\n\tPASS();\n}\n\nTEST zlib_onebyte_fixed(void)\n{\n\t/* One byte 00, fixed Huffman */\n\tstatic const unsigned char data[] = {\n\t\t0x78, 0x9C, 0x63, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01\n\t};\n\tunsigned char out[] = { 0xFF };\n\tunsigned int dlen = 1;\n\tint res;\n\n\tres = tinf_zlib_uncompress(out, &dlen, data, ARRAY_SIZE(data));\n\n\tASSERT(res == TINF_OK && dlen == 1 && out[0] == 0);\n\n\tPASS();\n}\n\nTEST zlib_onebyte_dynamic(void)\n{\n\t/* One byte 00, dynamic Huffman */\n\tstatic const unsigned char data[] = {\n\t\t0x78, 0x9C, 0x05, 0xC1, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t\t0x10, 0xFF, 0xD5, 0x10, 0x00, 0x01, 0x00, 0x01\n\t};\n\tunsigned char out[] = { 0xFF };\n\tunsigned int dlen = 1;\n\tint res;\n\n\tres = tinf_zlib_uncompress(out, &dlen, data, ARRAY_SIZE(data));\n\n\tASSERT(res == TINF_OK && dlen == 1 && out[0] == 0);\n\n\tPASS();\n}\n\nTEST zlib_zeroes(void)\n{\n\t/* 256 zero bytes, to test unrolling in Adler-32 */\n\tstatic const unsigned char data[] = {\n\t\t0x78, 0x9C, 0x63, 0x60, 0x18, 0xD9, 0x00, 0x00, 0x01, 0x00,\n\t\t0x00, 0x01\n\t};\n\tunsigned char out[256];\n\tunsigned int dlen = ARRAY_SIZE(out);\n\tint res;\n\tsize_t i;\n\n\tmemset(out, 0xFF, ARRAY_SIZE(out));\n\n\tres = tinf_zlib_uncompress(out, &dlen, data, ARRAY_SIZE(data));\n\n\tASSERT(res == TINF_OK && dlen == ARRAY_SIZE(out));\n\n\tfor (i = 0; i < ARRAY_SIZE(out); ++i) {\n\t\tif (out[i]) {\n\t\t\tFAIL();\n\t\t}\n\t}\n\n\tPASS();\n}\n\n/* Test tinf_zlib_uncompress on compressed data with errors */\nTEST zlib_error_case(const void *closure)\n{\n\tconst struct packed_data *pd = (const struct packed_data *) closure;\n\tint res;\n\n\tunsigned int size = pd->depacked_size;\n\tres = tinf_zlib_uncompress(buffer, &size, pd->data, pd->src_size);\n\n\tASSERT(res != TINF_OK);\n\n\tPASS();\n}\n\nSUITE(tinfzlib)\n{\n\tchar suffix[32];\n\tsize_t i;\n\n\tRUN_TEST(zlib_empty_raw);\n\tRUN_TEST(zlib_empty_fixed);\n\tRUN_TEST(zlib_empty_dynamic);\n\n\tRUN_TEST(zlib_onebyte_raw);\n\tRUN_TEST(zlib_onebyte_fixed);\n\tRUN_TEST(zlib_onebyte_dynamic);\n\tRUN_TEST(zlib_zeroes);\n\n\tfor (i = 0; i < ARRAY_SIZE(zlib_errors); ++i) {\n\t\tsprintf(suffix, \"%d\", (int) i);\n\t\tgreatest_set_test_suffix(suffix);\n\t\tRUN_TEST1(zlib_error_case, &zlib_errors[i]);\n\t}\n}\n\n/* tinfgzip */\n\nTEST gzip_empty_raw(void)\n{\n\t/* Empty buffer, uncompressed */\n\tstatic const unsigned char data[] = {\n\t\t0x1F, 0x8B, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0B,\n\t\t0x01, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t\t0x00, 0x00, 0x00\n\t};\n\tunsigned int dlen = 0;\n\tint res;\n\n\tres = tinf_gzip_uncompress((void *) robuffer, &dlen, data, ARRAY_SIZE(data));\n\n\tASSERT(res == TINF_OK && dlen == 0);\n\n\tPASS();\n}\n\nTEST gzip_empty_fixed(void)\n{\n\t/* Empty buffer, fixed Huffman */\n\tstatic const unsigned char data[] = {\n\t\t0x1F, 0x8B, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0B,\n\t\t0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00\n\t};\n\tunsigned int dlen = 0;\n\tint res;\n\n\tres = tinf_gzip_uncompress((void *) robuffer, &dlen, data, ARRAY_SIZE(data));\n\n\tASSERT(res == TINF_OK && dlen == 0);\n\n\tPASS();\n}\n\nTEST gzip_empty_dynamic(void)\n{\n\t/* Empty buffer, dynamic Huffman */\n\tstatic const unsigned char data[] = {\n\t\t0x1F, 0x8B, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0B,\n\t\t0x05, 0xC1, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xFF,\n\t\t0xD5, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00\n\t};\n\tunsigned int dlen = 0;\n\tint res;\n\n\tres = tinf_gzip_uncompress((void *) robuffer, &dlen, data, ARRAY_SIZE(data));\n\n\tASSERT(res == TINF_OK && dlen == 0);\n\n\tPASS();\n}\n\nTEST gzip_onebyte_raw(void)\n{\n\t/* One byte 00, uncompressed */\n\tstatic const unsigned char data[] = {\n\t\t0x1F, 0x8B, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0B,\n\t\t0x01, 0x01, 0x00, 0xFE, 0xFF, 0x00, 0x8D, 0xEF, 0x02, 0xD2,\n\t\t0x01, 0x00, 0x00, 0x00\n\t};\n\tunsigned char out[] = { 0xFF };\n\tunsigned int dlen = 1;\n\tint res;\n\n\tres = tinf_gzip_uncompress(out, &dlen, data, ARRAY_SIZE(data));\n\n\tASSERT(res == TINF_OK && dlen == 1 && out[0] == 0);\n\n\tPASS();\n}\n\nTEST gzip_onebyte_fixed(void)\n{\n\t/* One byte 00, fixed Huffman */\n\tstatic const unsigned char data[] = {\n\t\t0x1F, 0x8B, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0B,\n\t\t0x63, 0x00, 0x00, 0x8D, 0xEF, 0x02, 0xD2, 0x01, 0x00, 0x00,\n\t\t0x00\n\t};\n\tunsigned char out[] = { 0xFF };\n\tunsigned int dlen = 1;\n\tint res;\n\n\tres = tinf_gzip_uncompress(out, &dlen, data, ARRAY_SIZE(data));\n\n\tASSERT(res == TINF_OK && dlen == 1 && out[0] == 0);\n\n\tPASS();\n}\n\nTEST gzip_onebyte_dynamic(void)\n{\n\t/* One byte 00, dynamic Huffman */\n\tstatic const unsigned char data[] = {\n\t\t0x1F, 0x8B, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0B,\n\t\t0x05, 0xC1, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xFF,\n\t\t0xD5, 0x10, 0x8D, 0xEF, 0x02, 0xD2, 0x01, 0x00, 0x00, 0x00\n\t};\n\tunsigned char out[] = { 0xFF };\n\tunsigned int dlen = 1;\n\tint res;\n\n\tres = tinf_gzip_uncompress(out, &dlen, data, ARRAY_SIZE(data));\n\n\tASSERT(res == TINF_OK && dlen == 1 && out[0] == 0);\n\n\tPASS();\n}\n\nTEST gzip_fhcrc(void)\n{\n\t/* One byte 00, uncompressed, fhcrc */\n\tstatic const unsigned char data[] = {\n\t\t0x1F, 0x8B, 0x08, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0B,\n\t\t0x17, 0x9D, 0x01, 0x01, 0x00, 0xFE, 0xFF, 0x00, 0x8D, 0xEF,\n\t\t0x02, 0xD2, 0x01, 0x00, 0x00, 0x00\n\t};\n\tunsigned char out[] = { 0xFF };\n\tunsigned int dlen = 1;\n\tint res;\n\n\tres = tinf_gzip_uncompress(out, &dlen, data, ARRAY_SIZE(data));\n\n\tASSERT(res == TINF_OK && dlen == 1 && out[0] == 0);\n\n\tPASS();\n}\n\nTEST gzip_fextra(void)\n{\n\t/* One byte 00, uncompressed, fextra */\n\tstatic const unsigned char data[] = {\n\t\t0x1F, 0x8B, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0B,\n\t\t0x04, 0x00, 0x64, 0x61, 0x74, 0x61, 0x01, 0x01, 0x00, 0xFE,\n\t\t0xFF, 0x00, 0x8D, 0xEF, 0x02, 0xD2, 0x01, 0x00, 0x00, 0x00\n\t};\n\tunsigned char out[] = { 0xFF };\n\tunsigned int dlen = 1;\n\tint res;\n\n\tres = tinf_gzip_uncompress(out, &dlen, data, ARRAY_SIZE(data));\n\n\tASSERT(res == TINF_OK && dlen == 1 && out[0] == 0);\n\n\tPASS();\n}\n\nTEST gzip_fname(void)\n{\n\t/* One byte 00, uncompressed, fname */\n\tstatic const unsigned char data[] = {\n\t\t0x1F, 0x8B, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0B,\n\t\t0x66, 0x6F, 0x6F, 0x2E, 0x63, 0x00, 0x01, 0x01, 0x00, 0xFE,\n\t\t0xFF, 0x00, 0x8D, 0xEF, 0x02, 0xD2, 0x01, 0x00, 0x00, 0x00\n\t};\n\tunsigned char out[] = { 0xFF };\n\tunsigned int dlen = 1;\n\tint res;\n\n\tres = tinf_gzip_uncompress(out, &dlen, data, ARRAY_SIZE(data));\n\n\tASSERT(res == TINF_OK && dlen == 1 && out[0] == 0);\n\n\tPASS();\n}\n\nTEST gzip_fcomment(void)\n{\n\t/* One byte 00, uncompressed, fcomment */\n\tstatic const unsigned char data[] = {\n\t\t0x1F, 0x8B, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0B,\n\t\t0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x00, 0x01, 0x01, 0x00, 0xFE,\n\t\t0xFF, 0x00, 0x8D, 0xEF, 0x02, 0xD2, 0x01, 0x00, 0x00, 0x00\n\t};\n\tunsigned char out[] = { 0xFF };\n\tunsigned int dlen = 1;\n\tint res;\n\n\tres = tinf_gzip_uncompress(out, &dlen, data, ARRAY_SIZE(data));\n\n\tASSERT(res == TINF_OK && dlen == 1 && out[0] == 0);\n\n\tPASS();\n}\n\n/* Test tinf_gzip_uncompress on compressed data with errors */\nTEST gzip_error_case(const void *closure)\n{\n\tconst struct packed_data *pd = (const struct packed_data *) closure;\n\tint res;\n\n\tunsigned int size = pd->depacked_size;\n\tres = tinf_gzip_uncompress(buffer, &size, pd->data, pd->src_size);\n\n\tASSERT(res != TINF_OK);\n\n\tPASS();\n}\n\nSUITE(tinfgzip)\n{\n\tchar suffix[32];\n\tsize_t i;\n\n\tRUN_TEST(gzip_empty_raw);\n\tRUN_TEST(gzip_empty_fixed);\n\tRUN_TEST(gzip_empty_dynamic);\n\n\tRUN_TEST(gzip_onebyte_raw);\n\tRUN_TEST(gzip_onebyte_fixed);\n\tRUN_TEST(gzip_onebyte_dynamic);\n\n\tRUN_TEST(gzip_fhcrc);\n\tRUN_TEST(gzip_fextra);\n\tRUN_TEST(gzip_fname);\n\tRUN_TEST(gzip_fcomment);\n\n\tfor (i = 0; i < ARRAY_SIZE(gzip_errors); ++i) {\n\t\tsprintf(suffix, \"%d\", (int) i);\n\t\tgreatest_set_test_suffix(suffix);\n\t\tRUN_TEST1(gzip_error_case, &gzip_errors[i]);\n\t}\n}\n\nGREATEST_MAIN_DEFS();\n\nint main(int argc, char *argv[])\n{\n\tGREATEST_MAIN_BEGIN();\n\n\tsrand(time(NULL));\n\n\ttinf_init();\n\n\tRUN_SUITE(tinflate);\n\tRUN_SUITE(tinfzlib);\n\tRUN_SUITE(tinfgzip);\n\n\tGREATEST_MAIN_END();\n}\n"
  },
  {
    "path": "tools/gengztest.py",
    "content": "#!/usr/bin/env python3\n\n# Copyright (c) 2014-2019 Joergen Ibsen\n#\n# Permission is hereby granted, free of charge, to any person obtaining a\n# copy of this software and associated documentation files (the \"Software\"),\n# to deal in the Software without restriction, including without limitation\n# the rights to use, copy, modify, merge, publish, distribute, sublicense,\n# and/or sell copies of the Software, and to permit persons to whom the\n# Software is furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n# DEALINGS IN THE SOFTWARE.\n\n\"\"\"\nGzip test file generator.\n\nGenerates gzip test files with specified fields in the header.\n\"\"\"\n\nimport argparse\nimport struct\nimport zlib\nimport textwrap\n\ndef write_gzip(f, args):\n    \"\"\"Write gzip data to file f.\"\"\"\n\n    # gzip header\n    data = bytearray.fromhex('1f 8b 08 00 00 00 00 00 02 0b')\n\n    flags = 0\n\n    if args.s:\n        flags |= 2\n\n    if args.extra:\n        flags |= 4\n        edata = args.extra.encode('ascii')\n        data.extend(struct.pack('<H', len(edata)))\n        data.extend(edata)\n\n    if args.filename:\n        flags |= 8\n        data.extend(args.filename.encode('ascii'))\n        data.extend(b'\\x00')\n\n    if args.comment:\n        flags |= 16\n        data.extend(args.comment.encode('ascii'))\n        data.extend(b'\\x00')\n\n    data[3] = flags\n\n    if args.s:\n        # write low two bytes of CRC32 of header up to here\n        data.extend(struct.pack('<H', zlib.crc32(data) & 0xffff))\n\n    if args.data == 'empty':\n        if args.method == 'raw':\n            # empty buffer, uncompressed\n            data.extend(bytes.fromhex('01 00 00 ff ff'))\n        elif args.method == 'fixed':\n            # empty buffer, fixed Huffman\n            data.extend(bytes.fromhex('03 00'))\n        elif args.method == 'dynamic':\n            # empty buffer, dynamic Huffman\n            data.extend(bytes.fromhex('05 c1 81 00 00 00 00 00 10 ff d5 08'))\n        # CRC32 of empty buffer\n        data.extend(struct.pack('<I', 0))\n        # ISIZE 0\n        data.extend(struct.pack('<I', 0))\n    elif args.data == 'byte00':\n        if args.method == 'raw':\n            # one byte 00, uncompressed\n            data.extend(bytes.fromhex('01 01 00 fe ff 00'))\n        elif args.method == 'fixed':\n            # one byte 00, fixed Huffman\n            data.extend(bytes.fromhex('63 00 00'))\n        elif args.method == 'dynamic':\n            # one byte 00, dynamic Huffman\n            data.extend(bytes.fromhex('05 c1 81 00 00 00 00 00 10 ff d5 10'))\n        # CRC32 of one byte 00\n        data.extend(struct.pack('<I', zlib.crc32(b'\\x00')))\n        # ISIZE 1\n        data.extend(struct.pack('<I', 1))\n\n    if args.i:\n        s = textwrap.fill(', '.join('0x{:02X}'.format(b) for b in data))\n        f.write(s.encode('utf-8'))\n    else:\n        f.write(data)\n\nif __name__ == '__main__':\n    parser = argparse.ArgumentParser(description='gzip test file generator.')\n    parser.add_argument('-f', '--filename', type=str, help='original filename')\n    parser.add_argument('-c', '--comment', type=str, help='file comment')\n    parser.add_argument('-e', '--extra', type=str, help='extra data')\n    parser.add_argument('-d', '--data', type=str,\n                        choices=['empty', 'byte00'], default='empty',\n                        help='compressed data')\n    parser.add_argument('-m', '--method', type=str,\n                        choices=['raw', 'fixed', 'dynamic'], default='fixed',\n                        help='compression method')\n    parser.add_argument('-s', action='store_true', help='add header CRC16')\n    parser.add_argument('-i', action='store_true', help='generate include file')\n    parser.add_argument('outfile', type=argparse.FileType('wb'), help='output file')\n    args = parser.parse_args()\n\n    write_gzip(args.outfile, args)\n"
  },
  {
    "path": "tools/genzlibtest.py",
    "content": "#!/usr/bin/env python3\n\n# Copyright (c) 2014-2019 Joergen Ibsen\n#\n# Permission is hereby granted, free of charge, to any person obtaining a\n# copy of this software and associated documentation files (the \"Software\"),\n# to deal in the Software without restriction, including without limitation\n# the rights to use, copy, modify, merge, publish, distribute, sublicense,\n# and/or sell copies of the Software, and to permit persons to whom the\n# Software is furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n# DEALINGS IN THE SOFTWARE.\n\n\"\"\"\nzlib test file generator.\n\nGenerates zlib test files with specified fields in the header.\n\"\"\"\n\nimport argparse\nimport struct\nimport zlib\nimport textwrap\n\ndef write_zlib(f, args):\n    \"\"\"Write zlib data to file f.\"\"\"\n\n    # zlib header\n    data = bytearray.fromhex('00 00')\n\n    cmf = 8\n    flg = 0\n\n    if args.window_size:\n        cmf |= args.window_size << 4\n\n    if args.level:\n        flg = args.level << 6\n\n    if args.preset_dict:\n        flg |= 1 << 5\n        # Write Adler-32 of preset dictionary\n        data.extend(struct.pack('>I', args.preset_dict))\n\n    flg |= 31 - ((256 * cmf + flg) % 31)\n\n    data[0] = cmf\n    data[1] = flg\n\n    if args.data == 'empty':\n        if args.method == 'raw':\n            # empty buffer, uncompressed\n            data.extend(bytes.fromhex('01 00 00 ff ff'))\n        elif args.method == 'fixed':\n            # empty buffer, fixed Huffman\n            data.extend(bytes.fromhex('03 00'))\n        elif args.method == 'dynamic':\n            # empty buffer, dynamic Huffman\n            data.extend(bytes.fromhex('05 c1 81 00 00 00 00 00 10 ff d5 08'))\n        # Adler-32 of empty buffer\n        data.extend(struct.pack('>I', 1))\n    elif args.data == 'byte00':\n        if args.method == 'raw':\n            # one byte 00, uncompressed\n            data.extend(bytes.fromhex('01 01 00 fe ff 00'))\n        elif args.method == 'fixed':\n            # one byte 00, fixed Huffman\n            data.extend(bytes.fromhex('63 00 00'))\n        elif args.method == 'dynamic':\n            # one byte 00, dynamic Huffman\n            data.extend(bytes.fromhex('05 c1 81 00 00 00 00 00 10 ff d5 10'))\n        # Adler-32 of one byte 00\n        data.extend(struct.pack('>I', zlib.adler32(b'\\x00')))\n\n    if args.i:\n        s = textwrap.fill(', '.join('0x{:02X}'.format(b) for b in data))\n        f.write(s.encode('utf-8'))\n    else:\n        f.write(data)\n\nif __name__ == '__main__':\n    parser = argparse.ArgumentParser(description='zlib test file generator.')\n    parser.add_argument('-d', '--data', type=str,\n                        choices=['empty', 'byte00'], default='empty',\n                        help='compressed data')\n    parser.add_argument('-m', '--method', type=str,\n                        choices=['raw', 'fixed', 'dynamic'], default='fixed',\n                        help='compression method')\n    parser.add_argument('-l', '--level', type=int,\n                        choices=range(0, 4), default=2,\n                        help='compression level')\n    parser.add_argument('-w', '--window_size', type=int,\n                        choices=range(0, 8), default=7,\n                        help='window size')\n    parser.add_argument('-p', '--preset_dict', type=int,\n                        help='preset dictionary Adler-32')\n    parser.add_argument('-i', action='store_true', help='generate include file')\n    parser.add_argument('outfile', type=argparse.FileType('wb'), help='output file')\n    args = parser.parse_args()\n\n    write_zlib(args.outfile, args)\n"
  },
  {
    "path": "tools/mkzdata.c",
    "content": "/*\n * mkzdata - generate deflate compressed data testcases\n *\n * Copyright (c) 2014-2019 Joergen Ibsen\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n\n#include \"tinf.h\"\n\n#include <assert.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n\nstruct lsb_bitwriter {\n\tunsigned char *next_out;\n\tuint32_t tag;\n\tint bitcount;\n};\n\nstatic void\nlbw_init(struct lsb_bitwriter *lbw, unsigned char *dst)\n{\n\tlbw->next_out = dst;\n\tlbw->tag = 0;\n\tlbw->bitcount = 0;\n}\n\nstatic unsigned char*\nlbw_finalize(struct lsb_bitwriter *lbw)\n{\n\t/* Write bytes until no bits left in tag */\n\twhile (lbw->bitcount > 0) {\n\t\t*lbw->next_out++ = lbw->tag;\n\t\tlbw->tag >>= 8;\n\t\tlbw->bitcount -= 8;\n\t}\n\n\treturn lbw->next_out;\n}\n\nstatic void\nlbw_flush(struct lsb_bitwriter *lbw, int num) {\n\tassert(num >= 0 && num <= 32);\n\n\t/* Write bytes until at least num bits free */\n\twhile (lbw->bitcount > 32 - num) {\n\t\t*lbw->next_out++ = lbw->tag;\n\t\tlbw->tag >>= 8;\n\t\tlbw->bitcount -= 8;\n\t}\n\n\tassert(lbw->bitcount >= 0);\n}\n\nstatic void\nlbw_putbits_no_flush(struct lsb_bitwriter *lbw, uint32_t bits, int num) {\n\tassert(num >= 0 && num <= 32 - lbw->bitcount);\n\tassert((bits & (~0ULL << num)) == 0);\n\n\t/* Add bits to tag */\n\tlbw->tag |= bits << lbw->bitcount;\n\tlbw->bitcount += num;\n}\n\nstatic void\nlbw_putbits(struct lsb_bitwriter *lbw, uint32_t bits, int num) {\n\tlbw_flush(lbw, num);\n\tlbw_putbits_no_flush(lbw, bits, num);\n}\n\nstatic void\nlbw_putbits_rev(struct lsb_bitwriter *lbw, uint32_t bits, int num) {\n\tlbw_flush(lbw, num);\n\twhile (num-- > 0) {\n\t\tlbw_putbits_no_flush(lbw, (bits >> num) & 1, 1);\n\t}\n}\n\n// 256 00 bytes compressed with Z_RLE (one distance code)\nvoid\nwrite_256_rle(struct lsb_bitwriter *lbw)\n{\n\t// bfinal\n\tlbw_putbits(lbw, 1, 1);\n\n\t// btype\n\tlbw_putbits(lbw, 2, 2);\n\n\t// hlit\n\tlbw_putbits(lbw, 28, 5);\n\n\t// hdist\n\tlbw_putbits(lbw, 0, 5);\n\n\t// hclen\n\tlbw_putbits(lbw, 14, 4);\n\n\tlbw_putbits(lbw, 0, 3); // 16\n\tlbw_putbits(lbw, 0, 3); // 17\n\tlbw_putbits(lbw, 1, 3); // 18\n\tlbw_putbits(lbw, 0, 3); // 0\n\tlbw_putbits(lbw, 0, 3); // 8\n\tlbw_putbits(lbw, 0, 3); // 7\n\tlbw_putbits(lbw, 0, 3); // 9\n\tlbw_putbits(lbw, 0, 3); // 6\n\tlbw_putbits(lbw, 0, 3); // 10\n\tlbw_putbits(lbw, 0, 3); // 5\n\tlbw_putbits(lbw, 0, 3); // 11\n\tlbw_putbits(lbw, 0, 3); // 4\n\tlbw_putbits(lbw, 0, 3); // 12\n\tlbw_putbits(lbw, 0, 3); // 3\n\tlbw_putbits(lbw, 0, 3); // 13\n\tlbw_putbits(lbw, 2, 3); // 2\n\tlbw_putbits(lbw, 0, 3); // 14\n\tlbw_putbits(lbw, 2, 3); // 1\n\n\t// code lengths for literal/length\n\tlbw_putbits_rev(lbw, 2, 2); // 0 has len 1\n\n\tlbw_putbits_rev(lbw, 0, 1); // repeat len 0 for 138 times\n\tlbw_putbits(lbw, 127, 7);\n\n\tlbw_putbits_rev(lbw, 0, 1); // repeat len 0 for 117 times\n\tlbw_putbits(lbw, 106, 7);\n\n\tlbw_putbits_rev(lbw, 3, 2); // 256 has len 2\n\n\tlbw_putbits_rev(lbw, 0, 1); // repeat len 0 for 27 times\n\tlbw_putbits(lbw, 16, 7);\n\n\tlbw_putbits_rev(lbw, 3, 2); // 284 has len 2\n\n\t// code lengths for distance\n\tlbw_putbits_rev(lbw, 2, 2); // 1 has len 1\n\n\t// compressed data\n\tlbw_putbits_rev(lbw, 0, 1); // 00 byte\n\n\tlbw_putbits_rev(lbw, 3, 2); // match len 255\n\tlbw_putbits(lbw, 28, 5);\n\n\tlbw_putbits_rev(lbw, 0, 1); // distance 1\n\n\t// end of block\n\tlbw_putbits_rev(lbw, 2, 2); // 256 = EOB\n}\n\n// 256 00 bytes compressed with Z_HUFFMAN_ONLY (no distance codes)\nvoid\nwrite_256_huffman(struct lsb_bitwriter *lbw)\n{\n\t// bfinal\n\tlbw_putbits(lbw, 1, 1);\n\n\t// btype\n\tlbw_putbits(lbw, 2, 2);\n\n\t// hlit\n\tlbw_putbits(lbw, 0, 5);\n\n\t// hdist\n\tlbw_putbits(lbw, 10, 5);\n\n\t// hclen\n\tlbw_putbits(lbw, 14, 4);\n\n\tlbw_putbits(lbw, 0, 3); // 16\n\tlbw_putbits(lbw, 0, 3); // 17\n\tlbw_putbits(lbw, 1, 3); // 18\n\tlbw_putbits(lbw, 0, 3); // 0\n\tlbw_putbits(lbw, 0, 3); // 8\n\tlbw_putbits(lbw, 0, 3); // 7\n\tlbw_putbits(lbw, 0, 3); // 9\n\tlbw_putbits(lbw, 0, 3); // 6\n\tlbw_putbits(lbw, 0, 3); // 10\n\tlbw_putbits(lbw, 0, 3); // 5\n\tlbw_putbits(lbw, 0, 3); // 11\n\tlbw_putbits(lbw, 0, 3); // 4\n\tlbw_putbits(lbw, 0, 3); // 12\n\tlbw_putbits(lbw, 0, 3); // 3\n\tlbw_putbits(lbw, 0, 3); // 13\n\tlbw_putbits(lbw, 0, 3); // 2\n\tlbw_putbits(lbw, 0, 3); // 14\n\tlbw_putbits(lbw, 1, 3); // 1\n\n\t// code lengths for literal/length\n\tlbw_putbits_rev(lbw, 0, 1); // 0 has len 1\n\n\tlbw_putbits_rev(lbw, 1, 1); // repeat len 0 for 138 times\n\tlbw_putbits(lbw, 127, 7);\n\n\tlbw_putbits_rev(lbw, 1, 1); // repeat len 0 for 117 times\n\tlbw_putbits(lbw, 106, 7);\n\n\tlbw_putbits_rev(lbw, 0, 1); // 256 has len 1\n\n\t// code lengths for distance\n\tlbw_putbits_rev(lbw, 1, 1); // repeat len 0 for 11 times\n\tlbw_putbits(lbw, 0, 7);\n\n\t// compressed data\n\tfor (int i = 0; i < 256; ++i) {\n\t\tlbw_putbits_rev(lbw, 0, 1); // 00 byte\n\t}\n\n\t// end of block\n\tlbw_putbits_rev(lbw, 1, 1); // 256 = EOB\n}\n\n// empty with no literal symbols and no distance codes (only 256 has len 1)\nvoid\nwrite_no_lit(struct lsb_bitwriter *lbw)\n{\n\t// bfinal\n\tlbw_putbits(lbw, 1, 1);\n\n\t// btype\n\tlbw_putbits(lbw, 2, 2);\n\n\t// hlit\n\tlbw_putbits(lbw, 0, 5);\n\n\t// hdist\n\tlbw_putbits(lbw, 10, 5);\n\n\t// hclen\n\tlbw_putbits(lbw, 14, 4);\n\n\tlbw_putbits(lbw, 0, 3); // 16\n\tlbw_putbits(lbw, 0, 3); // 17\n\tlbw_putbits(lbw, 1, 3); // 18\n\tlbw_putbits(lbw, 0, 3); // 0\n\tlbw_putbits(lbw, 0, 3); // 8\n\tlbw_putbits(lbw, 0, 3); // 7\n\tlbw_putbits(lbw, 0, 3); // 9\n\tlbw_putbits(lbw, 0, 3); // 6\n\tlbw_putbits(lbw, 0, 3); // 10\n\tlbw_putbits(lbw, 0, 3); // 5\n\tlbw_putbits(lbw, 0, 3); // 11\n\tlbw_putbits(lbw, 0, 3); // 4\n\tlbw_putbits(lbw, 0, 3); // 12\n\tlbw_putbits(lbw, 0, 3); // 3\n\tlbw_putbits(lbw, 0, 3); // 13\n\tlbw_putbits(lbw, 0, 3); // 2\n\tlbw_putbits(lbw, 0, 3); // 14\n\tlbw_putbits(lbw, 1, 3); // 1\n\n\t// code lengths for literal/length\n\tlbw_putbits_rev(lbw, 1, 1); // repeat len 0 for 138 times\n\tlbw_putbits(lbw, 127, 7);\n\n\tlbw_putbits_rev(lbw, 1, 1); // repeat len 0 for 118 times\n\tlbw_putbits(lbw, 107, 7);\n\n\tlbw_putbits_rev(lbw, 0, 1); // 256 has len 1\n\n\t// code lengths for distance\n\tlbw_putbits_rev(lbw, 1, 1); // repeat len 0 for 11 times\n\tlbw_putbits(lbw, 0, 7);\n\n\t// no compressed data\n\n\t// end of block\n\tlbw_putbits_rev(lbw, 0, 1); // 256 = EOB\n}\n\n// copy with max distance 32768\nvoid\nwrite_max_dist(struct lsb_bitwriter *lbw)\n{\n\t// bfinal\n\tlbw_putbits(lbw, 1, 1);\n\n\t// btype\n\tlbw_putbits(lbw, 2, 2);\n\n\t// hlit\n\tlbw_putbits(lbw, 286 - 257, 5);\n\n\t// hdist\n\tlbw_putbits(lbw, 30 - 1, 5);\n\n\t// hclen\n\tlbw_putbits(lbw, 14, 4);\n\n\tlbw_putbits(lbw, 0, 3); // 16\n\tlbw_putbits(lbw, 0, 3); // 17\n\tlbw_putbits(lbw, 2, 3); // 18\n\tlbw_putbits(lbw, 0, 3); // 0\n\tlbw_putbits(lbw, 0, 3); // 8\n\tlbw_putbits(lbw, 0, 3); // 7\n\tlbw_putbits(lbw, 0, 3); // 9\n\tlbw_putbits(lbw, 0, 3); // 6\n\tlbw_putbits(lbw, 0, 3); // 10\n\tlbw_putbits(lbw, 0, 3); // 5\n\tlbw_putbits(lbw, 0, 3); // 11\n\tlbw_putbits(lbw, 2, 3); // 4\n\tlbw_putbits(lbw, 0, 3); // 12\n\tlbw_putbits(lbw, 2, 3); // 3\n\tlbw_putbits(lbw, 0, 3); // 13\n\tlbw_putbits(lbw, 0, 3); // 2\n\tlbw_putbits(lbw, 0, 3); // 14\n\tlbw_putbits(lbw, 2, 3); // 1\n\n\t// code lengths for literal/length\n\tlbw_putbits_rev(lbw, 1, 2); // 0 has len 3\n\tlbw_putbits_rev(lbw, 1, 2); // 1 has len 3\n\tlbw_putbits_rev(lbw, 2, 2); // 2 has len 4\n\n\tlbw_putbits_rev(lbw, 3, 2); // repeat len 0 for 138 times\n\tlbw_putbits(lbw, 127, 7);\n\n\tlbw_putbits_rev(lbw, 3, 2); // repeat len 0 for 115 times\n\tlbw_putbits(lbw, 104, 7);\n\n\tlbw_putbits_rev(lbw, 2, 2); // 256 has len 4\n\tlbw_putbits_rev(lbw, 2, 2); // 257 has len 4\n\n\tlbw_putbits_rev(lbw, 3, 2); // repeat len 0 for 26 times\n\tlbw_putbits(lbw, 15, 7);\n\n\tlbw_putbits_rev(lbw, 2, 2); // 284 has len 4\n\n\tlbw_putbits_rev(lbw, 0, 2); // 285 has len 1\n\n\t// code lengths for distance\n\tlbw_putbits_rev(lbw, 0, 2); // 0 has len 1\n\n\tlbw_putbits_rev(lbw, 3, 2); // repeat len 0 for 28 times\n\tlbw_putbits(lbw, 17, 7);\n\n\tlbw_putbits_rev(lbw, 0, 2); // 29 has len 1\n\n\t// no compressed data\n\tlbw_putbits_rev(lbw, 12, 4); // literal 02\n\tlbw_putbits_rev(lbw, 5, 3); // literal 01\n\tlbw_putbits_rev(lbw, 4, 3); // literal 00\n\n\tlbw_putbits_rev(lbw, 15, 4); // 284 = copy len 257\n\tlbw_putbits(lbw, 30, 5);\n\n\tlbw_putbits_rev(lbw, 0, 1); // distance 1\n\n\tfor (int i = 0; i < 126; ++i) {\n\t\tlbw_putbits_rev(lbw, 0, 1); // 285 = copy len 258\n\n\t\tlbw_putbits_rev(lbw, 0, 1); // distance 1\n\t}\n\n\tlbw_putbits_rev(lbw, 14, 4); // 257 = copy len 3\n\n\tlbw_putbits_rev(lbw, 1, 1); // distance 32768\n\tlbw_putbits(lbw, 8191, 13);\n\n\t// end of block\n\tlbw_putbits_rev(lbw, 13, 4); // 256 = EOB\n}\n\n// Use length 15 codeword\nvoid\nwrite_max_codelen(struct lsb_bitwriter *lbw)\n{\n\t// bfinal\n\tlbw_putbits(lbw, 1, 1);\n\n\t// btype\n\tlbw_putbits(lbw, 2, 2);\n\n\t// hlit\n\tlbw_putbits(lbw, 0, 5);\n\n\t// hdist\n\tlbw_putbits(lbw, 10, 5);\n\n\t// hclen\n\tlbw_putbits(lbw, 15, 4);\n\n\tlbw_putbits(lbw, 0, 3); // 16\n\tlbw_putbits(lbw, 0, 3); // 17\n\tlbw_putbits(lbw, 4, 3); // 18\n\tlbw_putbits(lbw, 0, 3); // 0\n\tlbw_putbits(lbw, 4, 3); // 8\n\tlbw_putbits(lbw, 4, 3); // 7\n\tlbw_putbits(lbw, 4, 3); // 9\n\tlbw_putbits(lbw, 4, 3); // 6\n\tlbw_putbits(lbw, 4, 3); // 10\n\tlbw_putbits(lbw, 4, 3); // 5\n\tlbw_putbits(lbw, 4, 3); // 11\n\tlbw_putbits(lbw, 4, 3); // 4\n\tlbw_putbits(lbw, 4, 3); // 12\n\tlbw_putbits(lbw, 4, 3); // 3\n\tlbw_putbits(lbw, 4, 3); // 13\n\tlbw_putbits(lbw, 4, 3); // 2\n\tlbw_putbits(lbw, 4, 3); // 14\n\tlbw_putbits(lbw, 4, 3); // 1\n\tlbw_putbits(lbw, 4, 3); // 15\n\n\t// code lengths for literal/length\n\tlbw_putbits_rev(lbw, 0, 4); // 0 has len 1\n\tlbw_putbits_rev(lbw, 1, 4); // 1 has len 2\n\tlbw_putbits_rev(lbw, 2, 4); // 2 has len 3\n\tlbw_putbits_rev(lbw, 3, 4); // 3 has len 4\n\tlbw_putbits_rev(lbw, 4, 4); // 4 has len 5\n\tlbw_putbits_rev(lbw, 5, 4); // 5 has len 6\n\tlbw_putbits_rev(lbw, 6, 4); // 6 has len 7\n\tlbw_putbits_rev(lbw, 7, 4); // 7 has len 8\n\tlbw_putbits_rev(lbw, 8, 4); // 8 has len 9\n\tlbw_putbits_rev(lbw, 9, 4); // 9 has len 10\n\tlbw_putbits_rev(lbw, 10, 4); // 10 has len 11\n\tlbw_putbits_rev(lbw, 11, 4); // 11 has len 12\n\tlbw_putbits_rev(lbw, 12, 4); // 12 has len 13\n\tlbw_putbits_rev(lbw, 13, 4); // 13 has len 14\n\tlbw_putbits_rev(lbw, 14, 4); // 14 has len 15\n\n\tlbw_putbits_rev(lbw, 15, 4); // repeat len 0 for 138 times\n\tlbw_putbits(lbw, 127, 7);\n\n\tlbw_putbits_rev(lbw, 15, 4); // repeat len 0 for 103 times\n\tlbw_putbits(lbw, 92, 7);\n\n\tlbw_putbits_rev(lbw, 14, 4); // 256 has len 15\n\n\t// code lengths for distance\n\tlbw_putbits_rev(lbw, 15, 4); // repeat len 0 for 11 times\n\tlbw_putbits(lbw, 0, 7);\n\n\t// compressed data\n\tlbw_putbits_rev(lbw, 0, 1); // literal 0\n\tlbw_putbits_rev(lbw, 2, 2); // literal 1\n\tlbw_putbits_rev(lbw, 6, 3); // literal 2\n\tlbw_putbits_rev(lbw, 14, 4); // literal 3\n\tlbw_putbits_rev(lbw, 30, 5); // literal 4\n\tlbw_putbits_rev(lbw, 62, 6); // literal 5\n\tlbw_putbits_rev(lbw, 126, 7); // literal 6\n\tlbw_putbits_rev(lbw, 254, 8); // literal 7\n\tlbw_putbits_rev(lbw, 510, 9); // literal 8\n\tlbw_putbits_rev(lbw, 1022, 10); // literal 9\n\tlbw_putbits_rev(lbw, 2046, 11); // literal 10\n\tlbw_putbits_rev(lbw, 4094, 12); // literal 11\n\tlbw_putbits_rev(lbw, 8190, 13); // literal 12\n\tlbw_putbits_rev(lbw, 16382, 14); // literal 13\n\tlbw_putbits_rev(lbw, 32766, 15); // literal 14\n\n\t// end of block\n\tlbw_putbits_rev(lbw, 32767, 15); // 256 = EOB\n}\n\nunsigned char buffer[64 * 1024];\n\nint\nmain(int argc, char *argv[])\n{\n\tif (argc > 2) {\n\t\tfputs(\"syntax: mkzdata FILE\\n\", stderr);\n\t\treturn EXIT_FAILURE;\n\t}\n\n\tconst unsigned char org_data[1024] = {0};\n\n\tunsigned char data[4096];\n\n\tstruct lsb_bitwriter lbw;\n\n\tlbw_init(&lbw, &data[0]);\n\n\twrite_max_codelen(&lbw);\n\n\tuint32_t size = lbw_finalize(&lbw) - &data[0];\n\n\tfor (int i = 0; i < size; ++i) {\n\t\tif (i > 0) {\n\t\t\tfputs(\", \", stdout);\n\t\t}\n\t\tprintf(\"0x%02X\", data[i]);\n\t}\n\tprintf(\"\\n\");\n\n\tif (argc > 1) {\n\t\tFILE *fout = fopen(argv[1], \"wb\");\n\n\t\tconst unsigned char gzip_header[10] = {\n\t\t\t0x1F, 0x8B, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0B\n\t\t};\n\n\t\tfwrite(gzip_header, 1, sizeof(gzip_header), fout);\n\n\t\tfwrite(data, 1, size, fout);\n\n\t\tunsigned int dsize = sizeof(buffer);\n\t\tint res = tinf_uncompress(buffer, &dsize, data, size);\n\n\t\tif (res != TINF_OK) {\n\t\t\tfputs(\"mkzdata: decompression error\\n\", stderr);\n\t\t\treturn EXIT_FAILURE;\n\t\t}\n\n\t\t// Note: only works on little-endian\n\t\tuint32_t crc = tinf_crc32(&buffer[0], dsize);\n\t\tfwrite(&crc, sizeof(crc), 1, fout);\n\t\tuint32_t org_size = dsize;\n\t\tfwrite(&org_size, sizeof(org_size), 1, fout);\n\n\t\tfclose(fout);\n\t}\n\n\treturn 0;\n}\n"
  }
]