remove unused miniz, a faster zip library that didn't pan out

This commit is contained in:
adelikat 2020-04-12 15:20:00 -05:00
parent 1ef5c2083f
commit b964ff4c32
14 changed files with 0 additions and 8473 deletions

View File

@ -1,49 +0,0 @@
using System;
using System.Runtime.InteropServices;
namespace BizHawk.Client.Common.Miniz
{
public static class LibMiniz
{
private const string DllName = "libminiz.dll";
private const CallingConvention CC = CallingConvention.Cdecl;
public enum mz_zip_flags : uint
{
MZ_ZIP_FLAG_CASE_SENSITIVE = 0x0100,
MZ_ZIP_FLAG_IGNORE_PATH = 0x0200,
MZ_ZIP_FLAG_COMPRESSED_DATA = 0x0400,
MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY = 0x0800
}
enum mz_compression_level : uint
{
MZ_NO_COMPRESSION = 0,
MZ_BEST_SPEED = 1,
MZ_BEST_COMPRESSION = 9,
MZ_UBER_COMPRESSION = 10,
MZ_DEFAULT_LEVEL = 6,
MZ_DEFAULT_COMPRESSION = unchecked((uint)-1)
}
[DllImport(DllName, CallingConvention = CC)]
public static extern bool mz_zip_writer_init_file(IntPtr pZip, string pFilename, long size_to_reserve_at_beginning);
// Adds the contents of a memory buffer to an archive. These functions record the current local time into the archive.
// To add a directory entry, call this method with an archive name ending in a forwardslash with empty buffer.
// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION.
[DllImport(DllName, CallingConvention = CC)]
public static extern bool mz_zip_writer_add_mem(IntPtr pZip, string pArchive_name, byte[] pBuf, ulong buf_size, uint level_and_flags);
// Finalizes the archive by writing the central directory records followed by the end of central directory record.
// After an archive is finalized, the only valid call on the mz_zip_archive struct is mz_zip_writer_end().
// An archive must be manually finalized by calling this function for it to be valid.
[DllImport(DllName, CallingConvention = CC)]
public static extern bool mz_zip_writer_finalize_archive(IntPtr pZip);
// Ends archive writing, freeing all allocations, and closing the output file if mz_zip_writer_init_file() was used.
// Note for the archive to be valid, it must have been finalized before ending.
[DllImport(DllName, CallingConvention = CC)]
public static extern bool mz_zip_writer_end(IntPtr pZip);
}
}

View File

@ -1,66 +0,0 @@
using System;
using System.IO;
using System.Runtime.InteropServices;
namespace BizHawk.Client.Common.Miniz
{
public class MinizZipWriter : IZipWriter
{
private IntPtr _zip;
private uint _flags;
private static readonly byte[] _shitcock = new byte[32 * 1024 * 1024];
/// <exception cref="InvalidOperationException">unmanaged call failed</exception>
public MinizZipWriter(string path, int compressionlevel)
{
_zip = Marshal.AllocHGlobal(128);
unsafe
{
var p = (int*)_zip;
for (int i = 0; i < 32; i++)
p[i] = 0;
}
if (!LibMiniz.mz_zip_writer_init_file(_zip, path, 0))
{
Marshal.FreeHGlobal(_zip);
_zip = IntPtr.Zero;
throw new InvalidOperationException("mz_zip_writer_init_file returned FALSE");
}
_flags = (uint)compressionlevel;
}
void IDisposable.Dispose()
{
Dispose();
GC.SuppressFinalize(this);
}
~MinizZipWriter()
{
Dispose();
}
private void Dispose()
{
if (_zip != IntPtr.Zero)
{
if (LibMiniz.mz_zip_writer_finalize_archive(_zip))
LibMiniz.mz_zip_writer_end(_zip);
Marshal.FreeHGlobal(_zip);
_zip = IntPtr.Zero;
}
}
/// <exception cref="InvalidOperationException">unmanaged call failed</exception>
public void WriteItem(string name, Action<Stream> callback)
{
lock (_shitcock)
{
var ms = new MemoryStream(_shitcock);
callback(ms);
if (!LibMiniz.mz_zip_writer_add_mem(_zip, name, _shitcock /*ms.GetBuffer()*/, (ulong)ms.Position, _flags))
throw new InvalidOperationException("mz_zip_writer_add_mem returned FALSE");
}
}
}
}

View File

@ -1,40 +0,0 @@
CXX = gcc
CXXFLAGS = -Wall -O3 -std=c99 -fomit-frame-pointer -Wno-attributes -s
MACHINE = $(shell $(CXX) -dumpmachine)
ifneq (,$(findstring i686,$(MACHINE)))
ARCH = 32
else ifneq (,$(findstring x86_64,$(MACHINE)))
ARCH = 64
else
$(error Unknown arch)
endif
LDFLAGS_32 =
LDFLAGS_64 =
LDFLAGS = -shared $(LDFLAGS_$(ARCH)) $(CXXFLAGS)
TARGET = libminiz.dll
RM = rm
CP = cp
SRCS = miniz.c
OBJS = $(SRCS:.c=.o)
DEST_32 = ../output/dll
DEST_64 = ../output64/dll
all: $(TARGET)
%.o: %.c
$(CXX) -c -o $@ $< $(CXXFLAGS)
$(TARGET) : $(OBJS)
$(CXX) -o $@ $(LDFLAGS) $(OBJS)
clean:
$(RM) $(OBJS)
$(RM) $(TARGET)
install:
$(CP) $(TARGET) $(DEST_$(ARCH))

View File

@ -1,105 +0,0 @@
// example1.c - Demonstrates miniz.c's compress() and uncompress() functions (same as zlib's).
// Public domain, May 15 2011, Rich Geldreich, richgel99@gmail.com. See "unlicense" statement at the end of tinfl.c.
#include "miniz.c"
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint;
// The string to compress.
static const char *s_pStr = "Good morning Dr. Chandra. This is Hal. I am ready for my first lesson." \
"Good morning Dr. Chandra. This is Hal. I am ready for my first lesson." \
"Good morning Dr. Chandra. This is Hal. I am ready for my first lesson." \
"Good morning Dr. Chandra. This is Hal. I am ready for my first lesson." \
"Good morning Dr. Chandra. This is Hal. I am ready for my first lesson." \
"Good morning Dr. Chandra. This is Hal. I am ready for my first lesson." \
"Good morning Dr. Chandra. This is Hal. I am ready for my first lesson.";
int main(int argc, char *argv[])
{
uint step = 0;
int cmp_status;
uLong src_len = (uLong)strlen(s_pStr);
uLong cmp_len = compressBound(src_len);
uLong uncomp_len = src_len;
uint8 *pCmp, *pUncomp;
uint total_succeeded = 0;
(void)argc, (void)argv;
printf("miniz.c version: %s\n", MZ_VERSION);
do
{
// Allocate buffers to hold compressed and uncompressed data.
pCmp = (mz_uint8 *)malloc((size_t)cmp_len);
pUncomp = (mz_uint8 *)malloc((size_t)src_len);
if ((!pCmp) || (!pUncomp))
{
printf("Out of memory!\n");
return EXIT_FAILURE;
}
// Compress the string.
cmp_status = compress(pCmp, &cmp_len, (const unsigned char *)s_pStr, src_len);
if (cmp_status != Z_OK)
{
printf("compress() failed!\n");
free(pCmp);
free(pUncomp);
return EXIT_FAILURE;
}
printf("Compressed from %u to %u bytes\n", (mz_uint32)src_len, (mz_uint32)cmp_len);
if (step)
{
// Purposely corrupt the compressed data if fuzzy testing (this is a very crude fuzzy test).
uint n = 1 + (rand() % 3);
while (n--)
{
uint i = rand() % cmp_len;
pCmp[i] ^= (rand() & 0xFF);
}
}
// Decompress.
cmp_status = uncompress(pUncomp, &uncomp_len, pCmp, cmp_len);
total_succeeded += (cmp_status == Z_OK);
if (step)
{
printf("Simple fuzzy test: step %u total_succeeded: %u\n", step, total_succeeded);
}
else
{
if (cmp_status != Z_OK)
{
printf("uncompress failed!\n");
free(pCmp);
free(pUncomp);
return EXIT_FAILURE;
}
printf("Decompressed from %u to %u bytes\n", (mz_uint32)cmp_len, (mz_uint32)uncomp_len);
// Ensure uncompress() returned the expected data.
if ((uncomp_len != src_len) || (memcmp(pUncomp, s_pStr, (size_t)src_len)))
{
printf("Decompression failed!\n");
free(pCmp);
free(pUncomp);
return EXIT_FAILURE;
}
}
free(pCmp);
free(pUncomp);
step++;
// Keep on fuzzy testing if there's a non-empty command line.
} while (argc >= 2);
printf("Success.\n");
return EXIT_SUCCESS;
}

View File

@ -1,95 +0,0 @@
// example2.c - Simple demonstration of miniz.c's ZIP archive API's.
// Public domain, May 15 2011, Rich Geldreich, richgel99@gmail.com. See "unlicense" statement at the end of tinfl.c.
#include "miniz.c"
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint;
// The string to compress.
static const char *s_pStr =
"MISSION CONTROL I wouldn't worry too much about the computer. First of all, there is still a chance that he is right, despite your tests, and" \
"if it should happen again, we suggest eliminating this possibility by allowing the unit to remain in place and seeing whether or not it" \
"actually fails. If the computer should turn out to be wrong, the situation is still not alarming. The type of obsessional error he may be" \
"guilty of is not unknown among the latest generation of HAL 9000 computers. It has almost always revolved around a single detail, such as" \
"the one you have described, and it has never interfered with the integrity or reliability of the computer's performance in other areas." \
"No one is certain of the cause of this kind of malfunctioning. It may be over-programming, but it could also be any number of reasons. In any" \
"event, it is somewhat analogous to human neurotic behavior. Does this answer your query? Zero-five-three-Zero, MC, transmission concluded.";
static const char *s_pComment = "This is a comment";
int main(int argc, char *argv[])
{
uint i;
mz_bool status;
size_t uncomp_size;
mz_zip_archive zip_archive;
void *p;
printf("miniz.c version: %s\n", MZ_VERSION);
(void)argc, (void)argv;
// Append a bunch of text files to test.zip
for (i = 0; i < 50; i++)
{
char archive_filename[64];
sprintf(archive_filename, "%u.txt", i);
status = mz_zip_add_mem_to_archive_file_in_place("test.zip", archive_filename, s_pStr, strlen(s_pStr), s_pComment, (uint16)strlen(s_pComment), MZ_BEST_COMPRESSION);
if (!status)
{
printf("mz_zip_add_mem_to_archive_file_in_place failed!\n");
return EXIT_FAILURE;
}
}
// Now try to open the archive.
memset(&zip_archive, 0, sizeof(zip_archive));
status = mz_zip_reader_init_file(&zip_archive, "test.zip", 0);
if (!status)
{
printf("mz_zip_reader_init_file() failed!\n");
return EXIT_FAILURE;
}
// Get and print information about each file in the archive.
for (i = 0; i < mz_zip_reader_get_num_files(&zip_archive); i++)
{
mz_zip_archive_file_stat file_stat;
if (!mz_zip_reader_file_stat(&zip_archive, i, &file_stat))
{
printf("mz_zip_reader_file_stat() failed!\n");
mz_zip_reader_end(&zip_archive);
return EXIT_FAILURE;
}
printf("Filename: \"%s\", Comment: \"%s\", Uncompressed size: %u, Compressed size: %u\n", file_stat.m_filename, file_stat.m_comment, (uint)file_stat.m_uncomp_size, (uint)file_stat.m_comp_size);
}
// Try to extract 0.txt to the heap.
p = mz_zip_reader_extract_file_to_heap(&zip_archive, "0.txt", &uncomp_size, 0);
if (!p)
{
printf("mz_zip_reader_extract_file_to_heap() failed!\n");
mz_zip_reader_end(&zip_archive);
return EXIT_FAILURE;
}
// Make sure the extraction really succeeded.
if ((uncomp_size != strlen(s_pStr)) || (memcmp(p, s_pStr, strlen(s_pStr))))
{
printf("mz_zip_reader_extract_file_to_heap() failed to extract the proper data\n");
free(p);
mz_zip_reader_end(&zip_archive);
return EXIT_FAILURE;
}
printf("Successfully extracted file \"0.txt\", size %u\n", (uint)uncomp_size);
// We're done.
free(p);
mz_zip_reader_end(&zip_archive);
printf("Success.\n");
return EXIT_SUCCESS;
}

View File

@ -1,268 +0,0 @@
// example3.c - Demonstrates how to use miniz.c's deflate() and inflate() functions for simple file compression.
// Public domain, May 15 2011, Rich Geldreich, richgel99@gmail.com. See "unlicense" statement at the end of tinfl.c.
// For simplicity, this example is limited to files smaller than 4GB, but this is not a limitation of miniz.c.
#include "miniz.c"
#include <limits.h>
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint;
#define my_max(a,b) (((a) > (b)) ? (a) : (b))
#define my_min(a,b) (((a) < (b)) ? (a) : (b))
#define BUF_SIZE (1024 * 1024)
static uint8 s_inbuf[BUF_SIZE];
static uint8 s_outbuf[BUF_SIZE];
int main(int argc, char *argv[])
{
const char *pMode;
FILE *pInfile, *pOutfile;
uint infile_size;
int level = Z_BEST_COMPRESSION;
z_stream stream;
int p = 1;
const char *pSrc_filename;
const char *pDst_filename;
long file_loc;
printf("miniz.c version: %s\n", MZ_VERSION);
if (argc < 4)
{
printf("Usage: example3 [options] [mode:c or d] infile outfile\n");
printf("\nModes:\n");
printf("c - Compresses file infile to a zlib stream in file outfile\n");
printf("d - Decompress zlib stream in file infile to file outfile\n");
printf("\nOptions:\n");
printf("-l[0-10] - Compression level, higher values are slower.\n");
return EXIT_FAILURE;
}
while ((p < argc) && (argv[p][0] == '-'))
{
switch (argv[p][1])
{
case 'l':
{
level = atoi(&argv[1][2]);
if ((level < 0) || (level > 10))
{
printf("Invalid level!\n");
return EXIT_FAILURE;
}
break;
}
default:
{
printf("Invalid option: %s\n", argv[p]);
return EXIT_FAILURE;
}
}
p++;
}
if ((argc - p) < 3)
{
printf("Must specify mode, input filename, and output filename after options!\n");
return EXIT_FAILURE;
}
else if ((argc - p) > 3)
{
printf("Too many filenames!\n");
return EXIT_FAILURE;
}
pMode = argv[p++];
if (!strchr("cCdD", pMode[0]))
{
printf("Invalid mode!\n");
return EXIT_FAILURE;
}
pSrc_filename = argv[p++];
pDst_filename = argv[p++];
printf("Mode: %c, Level: %u\nInput File: \"%s\"\nOutput File: \"%s\"\n", pMode[0], level, pSrc_filename, pDst_filename);
// Open input file.
pInfile = fopen(pSrc_filename, "rb");
if (!pInfile)
{
printf("Failed opening input file!\n");
return EXIT_FAILURE;
}
// Determine input file's size.
fseek(pInfile, 0, SEEK_END);
file_loc = ftell(pInfile);
fseek(pInfile, 0, SEEK_SET);
if ((file_loc < 0) || (file_loc > INT_MAX))
{
// This is not a limitation of miniz or tinfl, but this example.
printf("File is too large to be processed by this example.\n");
return EXIT_FAILURE;
}
infile_size = (uint)file_loc;
// Open output file.
pOutfile = fopen(pDst_filename, "wb");
if (!pOutfile)
{
printf("Failed opening output file!\n");
return EXIT_FAILURE;
}
printf("Input file size: %u\n", infile_size);
// Init the z_stream
memset(&stream, 0, sizeof(stream));
stream.next_in = s_inbuf;
stream.avail_in = 0;
stream.next_out = s_outbuf;
stream.avail_out = BUF_SIZE;
if ((pMode[0] == 'c') || (pMode[0] == 'C'))
{
// Compression.
uint infile_remaining = infile_size;
if (deflateInit(&stream, level) != Z_OK)
{
printf("deflateInit() failed!\n");
return EXIT_FAILURE;
}
for ( ; ; )
{
int status;
if (!stream.avail_in)
{
// Input buffer is empty, so read more bytes from input file.
uint n = my_min(BUF_SIZE, infile_remaining);
if (fread(s_inbuf, 1, n, pInfile) != n)
{
printf("Failed reading from input file!\n");
return EXIT_FAILURE;
}
stream.next_in = s_inbuf;
stream.avail_in = n;
infile_remaining -= n;
//printf("Input bytes remaining: %u\n", infile_remaining);
}
status = deflate(&stream, infile_remaining ? Z_NO_FLUSH : Z_FINISH);
if ((status == Z_STREAM_END) || (!stream.avail_out))
{
// Output buffer is full, or compression is done, so write buffer to output file.
uint n = BUF_SIZE - stream.avail_out;
if (fwrite(s_outbuf, 1, n, pOutfile) != n)
{
printf("Failed writing to output file!\n");
return EXIT_FAILURE;
}
stream.next_out = s_outbuf;
stream.avail_out = BUF_SIZE;
}
if (status == Z_STREAM_END)
break;
else if (status != Z_OK)
{
printf("deflate() failed with status %i!\n", status);
return EXIT_FAILURE;
}
}
if (deflateEnd(&stream) != Z_OK)
{
printf("deflateEnd() failed!\n");
return EXIT_FAILURE;
}
}
else if ((pMode[0] == 'd') || (pMode[0] == 'D'))
{
// Decompression.
uint infile_remaining = infile_size;
if (inflateInit(&stream))
{
printf("inflateInit() failed!\n");
return EXIT_FAILURE;
}
for ( ; ; )
{
int status;
if (!stream.avail_in)
{
// Input buffer is empty, so read more bytes from input file.
uint n = my_min(BUF_SIZE, infile_remaining);
if (fread(s_inbuf, 1, n, pInfile) != n)
{
printf("Failed reading from input file!\n");
return EXIT_FAILURE;
}
stream.next_in = s_inbuf;
stream.avail_in = n;
infile_remaining -= n;
}
status = inflate(&stream, Z_SYNC_FLUSH);
if ((status == Z_STREAM_END) || (!stream.avail_out))
{
// Output buffer is full, or decompression is done, so write buffer to output file.
uint n = BUF_SIZE - stream.avail_out;
if (fwrite(s_outbuf, 1, n, pOutfile) != n)
{
printf("Failed writing to output file!\n");
return EXIT_FAILURE;
}
stream.next_out = s_outbuf;
stream.avail_out = BUF_SIZE;
}
if (status == Z_STREAM_END)
break;
else if (status != Z_OK)
{
printf("inflate() failed with status %i!\n", status);
return EXIT_FAILURE;
}
}
if (inflateEnd(&stream) != Z_OK)
{
printf("inflateEnd() failed!\n");
return EXIT_FAILURE;
}
}
else
{
printf("Invalid mode!\n");
return EXIT_FAILURE;
}
fclose(pInfile);
if (EOF == fclose(pOutfile))
{
printf("Failed writing to output file!\n");
return EXIT_FAILURE;
}
printf("Total input bytes: %u\n", (mz_uint32)stream.total_in);
printf("Total output bytes: %u\n", (mz_uint32)stream.total_out);
printf("Success.\n");
return EXIT_SUCCESS;
}

View File

@ -1,101 +0,0 @@
// example4.c - Uses tinfl.c to decompress a zlib stream in memory to an output file
// Public domain, May 15 2011, Rich Geldreich, richgel99@gmail.com. See "unlicense" statement at the end of tinfl.c.
#include "tinfl.c"
#include <stdio.h>
#include <limits.h>
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint;
#define my_max(a,b) (((a) > (b)) ? (a) : (b))
#define my_min(a,b) (((a) < (b)) ? (a) : (b))
static int tinfl_put_buf_func(const void* pBuf, int len, void *pUser)
{
return len == (int)fwrite(pBuf, 1, len, (FILE*)pUser);
}
int main(int argc, char *argv[])
{
int status;
FILE *pInfile, *pOutfile;
uint infile_size, outfile_size;
size_t in_buf_size;
uint8 *pCmp_data;
long file_loc;
if (argc != 3)
{
printf("Usage: example4 infile outfile\n");
printf("Decompresses zlib stream in file infile to file outfile.\n");
printf("Input file must be able to fit entirely in memory.\n");
return EXIT_FAILURE;
}
// Open input file.
pInfile = fopen(argv[1], "rb");
if (!pInfile)
{
printf("Failed opening input file!\n");
return EXIT_FAILURE;
}
// Determine input file's size.
fseek(pInfile, 0, SEEK_END);
file_loc = ftell(pInfile);
fseek(pInfile, 0, SEEK_SET);
if ((file_loc < 0) || (file_loc > INT_MAX))
{
// This is not a limitation of miniz or tinfl, but this example.
printf("File is too large to be processed by this example.\n");
return EXIT_FAILURE;
}
infile_size = (uint)file_loc;
pCmp_data = (uint8 *)malloc(infile_size);
if (!pCmp_data)
{
printf("Out of memory!\n");
return EXIT_FAILURE;
}
if (fread(pCmp_data, 1, infile_size, pInfile) != infile_size)
{
printf("Failed reading input file!\n");
return EXIT_FAILURE;
}
// Open output file.
pOutfile = fopen(argv[2], "wb");
if (!pOutfile)
{
printf("Failed opening output file!\n");
return EXIT_FAILURE;
}
printf("Input file size: %u\n", infile_size);
in_buf_size = infile_size;
status = tinfl_decompress_mem_to_callback(pCmp_data, &in_buf_size, tinfl_put_buf_func, pOutfile, TINFL_FLAG_PARSE_ZLIB_HEADER);
if (!status)
{
printf("tinfl_decompress_mem_to_callback() failed with status %i!\n", status);
return EXIT_FAILURE;
}
outfile_size = ftell(pOutfile);
fclose(pInfile);
if (EOF == fclose(pOutfile))
{
printf("Failed writing to output file!\n");
return EXIT_FAILURE;
}
printf("Total input bytes: %u\n", (uint)in_buf_size);
printf("Total output bytes: %u\n", outfile_size);
printf("Success.\n");
return EXIT_SUCCESS;
}

View File

@ -1,327 +0,0 @@
// example5.c - Demonstrates how to use miniz.c's low-level tdefl_compress() and tinfl_inflate() API's for simple file to file compression/decompression.
// The low-level API's are the fastest, make no use of dynamic memory allocation, and are the most flexible functions exposed by miniz.c.
// Public domain, April 11 2012, Rich Geldreich, richgel99@gmail.com. See "unlicense" statement at the end of tinfl.c.
// For simplicity, this example is limited to files smaller than 4GB, but this is not a limitation of miniz.c.
// Purposely disable a whole bunch of stuff this low-level example doesn't use.
#define MINIZ_NO_STDIO
#define MINIZ_NO_ARCHIVE_APIS
#define MINIZ_NO_TIME
#define MINIZ_NO_ZLIB_APIS
#define MINIZ_NO_MALLOC
#include "miniz.c"
// Now include stdio.h because this test uses fopen(), etc. (but we still don't want miniz.c's stdio stuff, for testing).
#include <stdio.h>
#include <limits.h>
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint;
#define my_max(a,b) (((a) > (b)) ? (a) : (b))
#define my_min(a,b) (((a) < (b)) ? (a) : (b))
// IN_BUF_SIZE is the size of the file read buffer.
// IN_BUF_SIZE must be >= 1
#define IN_BUF_SIZE (1024*512)
static uint8 s_inbuf[IN_BUF_SIZE];
// COMP_OUT_BUF_SIZE is the size of the output buffer used during compression.
// COMP_OUT_BUF_SIZE must be >= 1 and <= OUT_BUF_SIZE
#define COMP_OUT_BUF_SIZE (1024*512)
// OUT_BUF_SIZE is the size of the output buffer used during decompression.
// OUT_BUF_SIZE must be a power of 2 >= TINFL_LZ_DICT_SIZE (because the low-level decompressor not only writes, but reads from the output buffer as it decompresses)
//#define OUT_BUF_SIZE (TINFL_LZ_DICT_SIZE)
#define OUT_BUF_SIZE (1024*512)
static uint8 s_outbuf[OUT_BUF_SIZE];
// tdefl_compressor contains all the state needed by the low-level compressor so it's a pretty big struct (~300k).
// This example makes it a global vs. putting it on the stack, of course in real-world usage you'll probably malloc() or new it.
tdefl_compressor g_deflator;
int main(int argc, char *argv[])
{
const char *pMode;
FILE *pInfile, *pOutfile;
uint infile_size;
int level = 9;
int p = 1;
const char *pSrc_filename;
const char *pDst_filename;
const void *next_in = s_inbuf;
size_t avail_in = 0;
void *next_out = s_outbuf;
size_t avail_out = OUT_BUF_SIZE;
size_t total_in = 0, total_out = 0;
long file_loc;
assert(COMP_OUT_BUF_SIZE <= OUT_BUF_SIZE);
printf("miniz.c example5 (demonstrates tinfl/tdefl)\n");
if (argc < 4)
{
printf("File to file compression/decompression using the low-level tinfl/tdefl API's.\n");
printf("Usage: example5 [options] [mode:c or d] infile outfile\n");
printf("\nModes:\n");
printf("c - Compresses file infile to a zlib stream in file outfile\n");
printf("d - Decompress zlib stream in file infile to file outfile\n");
printf("\nOptions:\n");
printf("-l[0-10] - Compression level, higher values are slower, 0 is none.\n");
return EXIT_FAILURE;
}
while ((p < argc) && (argv[p][0] == '-'))
{
switch (argv[p][1])
{
case 'l':
{
level = atoi(&argv[1][2]);
if ((level < 0) || (level > 10))
{
printf("Invalid level!\n");
return EXIT_FAILURE;
}
break;
}
default:
{
printf("Invalid option: %s\n", argv[p]);
return EXIT_FAILURE;
}
}
p++;
}
if ((argc - p) < 3)
{
printf("Must specify mode, input filename, and output filename after options!\n");
return EXIT_FAILURE;
}
else if ((argc - p) > 3)
{
printf("Too many filenames!\n");
return EXIT_FAILURE;
}
pMode = argv[p++];
if (!strchr("cCdD", pMode[0]))
{
printf("Invalid mode!\n");
return EXIT_FAILURE;
}
pSrc_filename = argv[p++];
pDst_filename = argv[p++];
printf("Mode: %c, Level: %u\nInput File: \"%s\"\nOutput File: \"%s\"\n", pMode[0], level, pSrc_filename, pDst_filename);
// Open input file.
pInfile = fopen(pSrc_filename, "rb");
if (!pInfile)
{
printf("Failed opening input file!\n");
return EXIT_FAILURE;
}
// Determine input file's size.
fseek(pInfile, 0, SEEK_END);
file_loc = ftell(pInfile);
fseek(pInfile, 0, SEEK_SET);
if ((file_loc < 0) || (file_loc > INT_MAX))
{
// This is not a limitation of miniz or tinfl, but this example.
printf("File is too large to be processed by this example.\n");
return EXIT_FAILURE;
}
infile_size = (uint)file_loc;
// Open output file.
pOutfile = fopen(pDst_filename, "wb");
if (!pOutfile)
{
printf("Failed opening output file!\n");
return EXIT_FAILURE;
}
printf("Input file size: %u\n", infile_size);
if ((pMode[0] == 'c') || (pMode[0] == 'C'))
{
// The number of dictionary probes to use at each compression level (0-10). 0=implies fastest/minimal possible probing.
static const mz_uint s_tdefl_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 };
tdefl_status status;
uint infile_remaining = infile_size;
// create tdefl() compatible flags (we have to compose the low-level flags ourselves, or use tdefl_create_comp_flags_from_zip_params() but that means MINIZ_NO_ZLIB_APIS can't be defined).
mz_uint comp_flags = TDEFL_WRITE_ZLIB_HEADER | s_tdefl_num_probes[MZ_MIN(10, level)] | ((level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0);
if (!level)
comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS;
// Initialize the low-level compressor.
status = tdefl_init(&g_deflator, NULL, NULL, comp_flags);
if (status != TDEFL_STATUS_OKAY)
{
printf("tdefl_init() failed!\n");
return EXIT_FAILURE;
}
avail_out = COMP_OUT_BUF_SIZE;
// Compression.
for ( ; ; )
{
size_t in_bytes, out_bytes;
if (!avail_in)
{
// Input buffer is empty, so read more bytes from input file.
uint n = my_min(IN_BUF_SIZE, infile_remaining);
if (fread(s_inbuf, 1, n, pInfile) != n)
{
printf("Failed reading from input file!\n");
return EXIT_FAILURE;
}
next_in = s_inbuf;
avail_in = n;
infile_remaining -= n;
//printf("Input bytes remaining: %u\n", infile_remaining);
}
in_bytes = avail_in;
out_bytes = avail_out;
// Compress as much of the input as possible (or all of it) to the output buffer.
status = tdefl_compress(&g_deflator, next_in, &in_bytes, next_out, &out_bytes, infile_remaining ? TDEFL_NO_FLUSH : TDEFL_FINISH);
next_in = (const char *)next_in + in_bytes;
avail_in -= in_bytes;
total_in += in_bytes;
next_out = (char *)next_out + out_bytes;
avail_out -= out_bytes;
total_out += out_bytes;
if ((status != TDEFL_STATUS_OKAY) || (!avail_out))
{
// Output buffer is full, or compression is done or failed, so write buffer to output file.
uint n = COMP_OUT_BUF_SIZE - (uint)avail_out;
if (fwrite(s_outbuf, 1, n, pOutfile) != n)
{
printf("Failed writing to output file!\n");
return EXIT_FAILURE;
}
next_out = s_outbuf;
avail_out = COMP_OUT_BUF_SIZE;
}
if (status == TDEFL_STATUS_DONE)
{
// Compression completed successfully.
break;
}
else if (status != TDEFL_STATUS_OKAY)
{
// Compression somehow failed.
printf("tdefl_compress() failed with status %i!\n", status);
return EXIT_FAILURE;
}
}
}
else if ((pMode[0] == 'd') || (pMode[0] == 'D'))
{
// Decompression.
uint infile_remaining = infile_size;
tinfl_decompressor inflator;
tinfl_init(&inflator);
for ( ; ; )
{
size_t in_bytes, out_bytes;
tinfl_status status;
if (!avail_in)
{
// Input buffer is empty, so read more bytes from input file.
uint n = my_min(IN_BUF_SIZE, infile_remaining);
if (fread(s_inbuf, 1, n, pInfile) != n)
{
printf("Failed reading from input file!\n");
return EXIT_FAILURE;
}
next_in = s_inbuf;
avail_in = n;
infile_remaining -= n;
}
in_bytes = avail_in;
out_bytes = avail_out;
status = tinfl_decompress(&inflator, (const mz_uint8 *)next_in, &in_bytes, s_outbuf, (mz_uint8 *)next_out, &out_bytes, (infile_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0) | TINFL_FLAG_PARSE_ZLIB_HEADER);
avail_in -= in_bytes;
next_in = (const mz_uint8 *)next_in + in_bytes;
total_in += in_bytes;
avail_out -= out_bytes;
next_out = (mz_uint8 *)next_out + out_bytes;
total_out += out_bytes;
if ((status <= TINFL_STATUS_DONE) || (!avail_out))
{
// Output buffer is full, or decompression is done, so write buffer to output file.
uint n = OUT_BUF_SIZE - (uint)avail_out;
if (fwrite(s_outbuf, 1, n, pOutfile) != n)
{
printf("Failed writing to output file!\n");
return EXIT_FAILURE;
}
next_out = s_outbuf;
avail_out = OUT_BUF_SIZE;
}
// If status is <= TINFL_STATUS_DONE then either decompression is done or something went wrong.
if (status <= TINFL_STATUS_DONE)
{
if (status == TINFL_STATUS_DONE)
{
// Decompression completed successfully.
break;
}
else
{
// Decompression failed.
printf("tinfl_decompress() failed with status %i!\n", status);
return EXIT_FAILURE;
}
}
}
}
else
{
printf("Invalid mode!\n");
return EXIT_FAILURE;
}
fclose(pInfile);
if (EOF == fclose(pOutfile))
{
printf("Failed writing to output file!\n");
return EXIT_FAILURE;
}
printf("Total input bytes: %u\n", (mz_uint32)total_in);
printf("Total output bytes: %u\n", (mz_uint32)total_out);
printf("Success.\n");
return EXIT_SUCCESS;
}

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,152 +0,0 @@
// File: timer.cpp - Simple high-precision timer class. Supports Win32, X360, and POSIX/Linux
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <time.h>
#include "timer.h"
#if defined(WIN32)
#include <windows.h>
#elif defined(_XBOX)
#include <xtl.h>
#endif
unsigned long long timer::g_init_ticks;
unsigned long long timer::g_freq;
double timer::g_inv_freq;
#if defined(WIN32) || defined(_XBOX)
inline void query_counter(timer_ticks *pTicks)
{
QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER*>(pTicks));
}
inline void query_counter_frequency(timer_ticks *pTicks)
{
QueryPerformanceFrequency(reinterpret_cast<LARGE_INTEGER*>(pTicks));
}
#elif defined(__GNUC__)
#include <sys/timex.h>
inline void query_counter(timer_ticks *pTicks)
{
struct timeval cur_time;
gettimeofday(&cur_time, NULL);
*pTicks = static_cast<unsigned long long>(cur_time.tv_sec)*1000000ULL + static_cast<unsigned long long>(cur_time.tv_usec);
}
inline void query_counter_frequency(timer_ticks *pTicks)
{
*pTicks = 1000000;
}
#endif
timer::timer() :
m_start_time(0),
m_stop_time(0),
m_started(false),
m_stopped(false)
{
if (!g_inv_freq)
init();
}
timer::timer(timer_ticks start_ticks)
{
if (!g_inv_freq)
init();
m_start_time = start_ticks;
m_started = true;
m_stopped = false;
}
void timer::start(timer_ticks start_ticks)
{
m_start_time = start_ticks;
m_started = true;
m_stopped = false;
}
void timer::start()
{
query_counter(&m_start_time);
m_started = true;
m_stopped = false;
}
void timer::stop()
{
assert(m_started);
query_counter(&m_stop_time);
m_stopped = true;
}
double timer::get_elapsed_secs() const
{
assert(m_started);
if (!m_started)
return 0;
timer_ticks stop_time = m_stop_time;
if (!m_stopped)
query_counter(&stop_time);
timer_ticks delta = stop_time - m_start_time;
return delta * g_inv_freq;
}
timer_ticks timer::get_elapsed_us() const
{
assert(m_started);
if (!m_started)
return 0;
timer_ticks stop_time = m_stop_time;
if (!m_stopped)
query_counter(&stop_time);
timer_ticks delta = stop_time - m_start_time;
return (delta * 1000000ULL + (g_freq >> 1U)) / g_freq;
}
void timer::init()
{
if (!g_inv_freq)
{
query_counter_frequency(&g_freq);
g_inv_freq = 1.0f / g_freq;
query_counter(&g_init_ticks);
}
}
timer_ticks timer::get_init_ticks()
{
if (!g_inv_freq)
init();
return g_init_ticks;
}
timer_ticks timer::get_ticks()
{
if (!g_inv_freq)
init();
timer_ticks ticks;
query_counter(&ticks);
return ticks - g_init_ticks;
}
double timer::ticks_to_secs(timer_ticks ticks)
{
if (!g_inv_freq)
init();
return ticks * g_inv_freq;
}

View File

@ -1,40 +0,0 @@
// File: timer.h
#pragma once
typedef unsigned long long timer_ticks;
class timer
{
public:
timer();
timer(timer_ticks start_ticks);
void start();
void start(timer_ticks start_ticks);
void stop();
double get_elapsed_secs() const;
inline double get_elapsed_ms() const { return get_elapsed_secs() * 1000.0f; }
timer_ticks get_elapsed_us() const;
static void init();
static inline timer_ticks get_ticks_per_sec() { return g_freq; }
static timer_ticks get_init_ticks();
static timer_ticks get_ticks();
static double ticks_to_secs(timer_ticks ticks);
static inline double ticks_to_ms(timer_ticks ticks) { return ticks_to_secs(ticks) * 1000.0f; }
static inline double get_secs() { return ticks_to_secs(get_ticks()); }
static inline double get_ms() { return ticks_to_ms(get_ticks()); }
private:
static timer_ticks g_init_ticks;
static timer_ticks g_freq;
static double g_inv_freq;
timer_ticks m_start_time;
timer_ticks m_stop_time;
bool m_started : 1;
bool m_stopped : 1;
};

View File

@ -1,592 +0,0 @@
/* tinfl.c v1.11 - public domain inflate with zlib header parsing/adler32 checking (inflate-only subset of miniz.c)
See "unlicense" statement at the end of this file.
Rich Geldreich <richgel99@gmail.com>, last updated May 20, 2011
Implements RFC 1950: http://www.ietf.org/rfc/rfc1950.txt and RFC 1951: http://www.ietf.org/rfc/rfc1951.txt
The entire decompressor coroutine is implemented in tinfl_decompress(). The other functions are optional high-level helpers.
*/
#ifndef TINFL_HEADER_INCLUDED
#define TINFL_HEADER_INCLUDED
#include <stdlib.h>
typedef unsigned char mz_uint8;
typedef signed short mz_int16;
typedef unsigned short mz_uint16;
typedef unsigned int mz_uint32;
typedef unsigned int mz_uint;
typedef unsigned long long mz_uint64;
#if defined(_M_IX86) || defined(_M_X64)
// Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 if integer loads and stores to unaligned addresses are acceptable on the target platform (slightly faster).
#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1
// Set MINIZ_LITTLE_ENDIAN to 1 if the processor is little endian.
#define MINIZ_LITTLE_ENDIAN 1
#endif
#if defined(_WIN64) || defined(__MINGW64__) || defined(_LP64) || defined(__LP64__)
// Set MINIZ_HAS_64BIT_REGISTERS to 1 if the processor has 64-bit general purpose registers (enables 64-bit bitbuffer in inflator)
#define MINIZ_HAS_64BIT_REGISTERS 1
#endif
// Works around MSVC's spammy "warning C4127: conditional expression is constant" message.
#ifdef _MSC_VER
#define MZ_MACRO_END while (0, 0)
#else
#define MZ_MACRO_END while (0)
#endif
// Decompression flags used by tinfl_decompress().
// TINFL_FLAG_PARSE_ZLIB_HEADER: If set, the input has a valid zlib header and ends with an adler32 checksum (it's a valid zlib stream). Otherwise, the input is a raw deflate stream.
// TINFL_FLAG_HAS_MORE_INPUT: If set, there are more input bytes available beyond the end of the supplied input buffer. If clear, the input buffer contains all remaining input.
// TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF: If set, the output buffer is large enough to hold the entire decompressed stream. If clear, the output buffer is at least the size of the dictionary (typically 32KB).
// TINFL_FLAG_COMPUTE_ADLER32: Force adler-32 checksum computation of the decompressed bytes.
enum
{
TINFL_FLAG_PARSE_ZLIB_HEADER = 1,
TINFL_FLAG_HAS_MORE_INPUT = 2,
TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF = 4,
TINFL_FLAG_COMPUTE_ADLER32 = 8
};
// High level decompression functions:
// tinfl_decompress_mem_to_heap() decompresses a block in memory to a heap block allocated via malloc().
// On entry:
// pSrc_buf, src_buf_len: Pointer and size of the Deflate or zlib source data to decompress.
// On return:
// Function returns a pointer to the decompressed data, or NULL on failure.
// *pOut_len will be set to the decompressed data's size, which could be larger than src_buf_len on uncompressible data.
// The caller must free() the returned block when it's no longer needed.
void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags);
// tinfl_decompress_mem_to_mem() decompresses a block in memory to another block in memory.
// Returns TINFL_DECOMPRESS_MEM_TO_MEM_FAILED on failure, or the number of bytes written on success.
#define TINFL_DECOMPRESS_MEM_TO_MEM_FAILED ((size_t)(-1))
size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags);
// tinfl_decompress_mem_to_callback() decompresses a block in memory to an internal 32KB buffer, and a user provided callback function will be called to flush the buffer.
// Returns 1 on success or 0 on failure.
typedef int (*tinfl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser);
int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);
struct tinfl_decompressor_tag; typedef struct tinfl_decompressor_tag tinfl_decompressor;
// Max size of LZ dictionary.
#define TINFL_LZ_DICT_SIZE 32768
// Return status.
typedef enum
{
TINFL_STATUS_BAD_PARAM = -3,
TINFL_STATUS_ADLER32_MISMATCH = -2,
TINFL_STATUS_FAILED = -1,
TINFL_STATUS_DONE = 0,
TINFL_STATUS_NEEDS_MORE_INPUT = 1,
TINFL_STATUS_HAS_MORE_OUTPUT = 2
} tinfl_status;
// Initializes the decompressor to its initial state.
#define tinfl_init(r) do { (r)->m_state = 0; } MZ_MACRO_END
#define tinfl_get_adler32(r) (r)->m_check_adler32
// Main low-level decompressor coroutine function. This is the only function actually needed for decompression. All the other functions are just high-level helpers for improved usability.
// This is a universal API, i.e. it can be used as a building block to build any desired higher level decompression API. In the limit case, it can be called once per every byte input or output.
tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags);
// Internal/private bits follow.
enum
{
TINFL_MAX_HUFF_TABLES = 3, TINFL_MAX_HUFF_SYMBOLS_0 = 288, TINFL_MAX_HUFF_SYMBOLS_1 = 32, TINFL_MAX_HUFF_SYMBOLS_2 = 19,
TINFL_FAST_LOOKUP_BITS = 10, TINFL_FAST_LOOKUP_SIZE = 1 << TINFL_FAST_LOOKUP_BITS
};
typedef struct
{
mz_uint8 m_code_size[TINFL_MAX_HUFF_SYMBOLS_0];
mz_int16 m_look_up[TINFL_FAST_LOOKUP_SIZE], m_tree[TINFL_MAX_HUFF_SYMBOLS_0 * 2];
} tinfl_huff_table;
#if MINIZ_HAS_64BIT_REGISTERS
#define TINFL_USE_64BIT_BITBUF 1
#endif
#if TINFL_USE_64BIT_BITBUF
typedef mz_uint64 tinfl_bit_buf_t;
#define TINFL_BITBUF_SIZE (64)
#else
typedef mz_uint32 tinfl_bit_buf_t;
#define TINFL_BITBUF_SIZE (32)
#endif
struct tinfl_decompressor_tag
{
mz_uint32 m_state, m_num_bits, m_zhdr0, m_zhdr1, m_z_adler32, m_final, m_type, m_check_adler32, m_dist, m_counter, m_num_extra, m_table_sizes[TINFL_MAX_HUFF_TABLES];
tinfl_bit_buf_t m_bit_buf;
size_t m_dist_from_out_buf_start;
tinfl_huff_table m_tables[TINFL_MAX_HUFF_TABLES];
mz_uint8 m_raw_header[4], m_len_codes[TINFL_MAX_HUFF_SYMBOLS_0 + TINFL_MAX_HUFF_SYMBOLS_1 + 137];
};
#endif // #ifdef TINFL_HEADER_INCLUDED
// ------------------- End of Header: Implementation follows. (If you only want the header, define MINIZ_HEADER_FILE_ONLY.)
#ifndef TINFL_HEADER_FILE_ONLY
#include <string.h>
// MZ_MALLOC, etc. are only used by the optional high-level helper functions.
#ifdef MINIZ_NO_MALLOC
#define MZ_MALLOC(x) NULL
#define MZ_FREE(x) x, ((void)0)
#define MZ_REALLOC(p, x) NULL
#else
#define MZ_MALLOC(x) malloc(x)
#define MZ_FREE(x) free(x)
#define MZ_REALLOC(p, x) realloc(p, x)
#endif
#define MZ_MAX(a,b) (((a)>(b))?(a):(b))
#define MZ_MIN(a,b) (((a)<(b))?(a):(b))
#define MZ_CLEAR_OBJ(obj) memset(&(obj), 0, sizeof(obj))
#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
#define MZ_READ_LE16(p) *((const mz_uint16 *)(p))
#define MZ_READ_LE32(p) *((const mz_uint32 *)(p))
#else
#define MZ_READ_LE16(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U))
#define MZ_READ_LE32(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U) | ((mz_uint32)(((const mz_uint8 *)(p))[2]) << 16U) | ((mz_uint32)(((const mz_uint8 *)(p))[3]) << 24U))
#endif
#define TINFL_MEMCPY(d, s, l) memcpy(d, s, l)
#define TINFL_MEMSET(p, c, l) memset(p, c, l)
#define TINFL_CR_BEGIN switch(r->m_state) { case 0:
#define TINFL_CR_RETURN(state_index, result) do { status = result; r->m_state = state_index; goto common_exit; case state_index:; } MZ_MACRO_END
#define TINFL_CR_RETURN_FOREVER(state_index, result) do { for ( ; ; ) { TINFL_CR_RETURN(state_index, result); } } MZ_MACRO_END
#define TINFL_CR_FINISH }
// TODO: If the caller has indicated that there's no more input, and we attempt to read beyond the input buf, then something is wrong with the input because the inflator never
// reads ahead more than it needs to. Currently TINFL_GET_BYTE() pads the end of the stream with 0's in this scenario.
#define TINFL_GET_BYTE(state_index, c) do { \
if (pIn_buf_cur >= pIn_buf_end) { \
for ( ; ; ) { \
if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) { \
TINFL_CR_RETURN(state_index, TINFL_STATUS_NEEDS_MORE_INPUT); \
if (pIn_buf_cur < pIn_buf_end) { \
c = *pIn_buf_cur++; \
break; \
} \
} else { \
c = 0; \
break; \
} \
} \
} else c = *pIn_buf_cur++; } MZ_MACRO_END
#define TINFL_NEED_BITS(state_index, n) do { mz_uint c; TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; } while (num_bits < (mz_uint)(n))
#define TINFL_SKIP_BITS(state_index, n) do { if (num_bits < (mz_uint)(n)) { TINFL_NEED_BITS(state_index, n); } bit_buf >>= (n); num_bits -= (n); } MZ_MACRO_END
#define TINFL_GET_BITS(state_index, b, n) do { if (num_bits < (mz_uint)(n)) { TINFL_NEED_BITS(state_index, n); } b = bit_buf & ((1 << (n)) - 1); bit_buf >>= (n); num_bits -= (n); } MZ_MACRO_END
// TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes remaining in the input buffer falls below 2.
// It reads just enough bytes from the input stream that are needed to decode the next Huffman code (and absolutely no more). It works by trying to fully decode a
// Huffman code by using whatever bits are currently present in the bit buffer. If this fails, it reads another byte, and tries again until it succeeds or until the
// bit buffer contains >=15 bits (deflate's max. Huffman code size).
#define TINFL_HUFF_BITBUF_FILL(state_index, pHuff) \
do { \
temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]; \
if (temp >= 0) { \
code_len = temp >> 9; \
if ((code_len) && (num_bits >= code_len)) \
break; \
} else if (num_bits > TINFL_FAST_LOOKUP_BITS) { \
code_len = TINFL_FAST_LOOKUP_BITS; \
do { \
temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \
} while ((temp < 0) && (num_bits >= (code_len + 1))); if (temp >= 0) break; \
} TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; \
} while (num_bits < 15);
// TINFL_HUFF_DECODE() decodes the next Huffman coded symbol. It's more complex than you would initially expect because the zlib API expects the decompressor to never read
// beyond the final byte of the deflate stream. (In other words, when this macro wants to read another byte from the input, it REALLY needs another byte in order to fully
// decode the next Huffman code.) Handling this properly is particularly important on raw deflate (non-zlib) streams, which aren't followed by a byte aligned adler-32.
// The slow path is only executed at the very end of the input buffer.
#define TINFL_HUFF_DECODE(state_index, sym, pHuff) do { \
int temp; mz_uint code_len, c; \
if (num_bits < 15) { \
if ((pIn_buf_end - pIn_buf_cur) < 2) { \
TINFL_HUFF_BITBUF_FILL(state_index, pHuff); \
} else { \
bit_buf |= (((tinfl_bit_buf_t)pIn_buf_cur[0]) << num_bits) | (((tinfl_bit_buf_t)pIn_buf_cur[1]) << (num_bits + 8)); pIn_buf_cur += 2; num_bits += 16; \
} \
} \
if ((temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) \
code_len = temp >> 9, temp &= 511; \
else { \
code_len = TINFL_FAST_LOOKUP_BITS; do { temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; } while (temp < 0); \
} sym = temp; bit_buf >>= code_len; num_bits -= code_len; } MZ_MACRO_END
tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags)
{
static const int s_length_base[31] = { 3,4,5,6,7,8,9,10,11,13, 15,17,19,23,27,31,35,43,51,59, 67,83,99,115,131,163,195,227,258,0,0 };
static const int s_length_extra[31]= { 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 };
static const int s_dist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, 257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0};
static const int s_dist_extra[32] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
static const mz_uint8 s_length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 };
static const int s_min_table_sizes[3] = { 257, 1, 4 };
tinfl_status status = TINFL_STATUS_FAILED; mz_uint32 num_bits, dist, counter, num_extra; tinfl_bit_buf_t bit_buf;
const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = pIn_buf_next + *pIn_buf_size;
mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = pOut_buf_next + *pOut_buf_size;
size_t out_buf_size_mask = (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF) ? (size_t)-1 : ((pOut_buf_next - pOut_buf_start) + *pOut_buf_size) - 1, dist_from_out_buf_start;
// Ensure the output buffer's size is a power of 2, unless the output buffer is large enough to hold the entire output file (in which case it doesn't matter).
if (((out_buf_size_mask + 1) & out_buf_size_mask) || (pOut_buf_next < pOut_buf_start)) { *pIn_buf_size = *pOut_buf_size = 0; return TINFL_STATUS_BAD_PARAM; }
num_bits = r->m_num_bits; bit_buf = r->m_bit_buf; dist = r->m_dist; counter = r->m_counter; num_extra = r->m_num_extra; dist_from_out_buf_start = r->m_dist_from_out_buf_start;
TINFL_CR_BEGIN
bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0; r->m_z_adler32 = r->m_check_adler32 = 1;
if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
{
TINFL_GET_BYTE(1, r->m_zhdr0); TINFL_GET_BYTE(2, r->m_zhdr1);
counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8));
if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) || ((out_buf_size_mask + 1) < (size_t)(1U << (8U + (r->m_zhdr0 >> 4)))));
if (counter) { TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED); }
}
do
{
TINFL_GET_BITS(3, r->m_final, 3); r->m_type = r->m_final >> 1;
if (r->m_type == 0)
{
TINFL_SKIP_BITS(5, num_bits & 7);
for (counter = 0; counter < 4; ++counter) { if (num_bits) TINFL_GET_BITS(6, r->m_raw_header[counter], 8); else TINFL_GET_BYTE(7, r->m_raw_header[counter]); }
if ((counter = (r->m_raw_header[0] | (r->m_raw_header[1] << 8))) != (mz_uint)(0xFFFF ^ (r->m_raw_header[2] | (r->m_raw_header[3] << 8)))) { TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED); }
while ((counter) && (num_bits))
{
TINFL_GET_BITS(51, dist, 8);
while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT); }
*pOut_buf_cur++ = (mz_uint8)dist;
counter--;
}
while (counter)
{
size_t n; while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT); }
while (pIn_buf_cur >= pIn_buf_end)
{
if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT)
{
TINFL_CR_RETURN(38, TINFL_STATUS_NEEDS_MORE_INPUT);
}
else
{
TINFL_CR_RETURN_FOREVER(40, TINFL_STATUS_FAILED);
}
}
n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur), (size_t)(pIn_buf_end - pIn_buf_cur)), counter);
TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n); pIn_buf_cur += n; pOut_buf_cur += n; counter -= (mz_uint)n;
}
}
else if (r->m_type == 3)
{
TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED);
}
else
{
if (r->m_type == 1)
{
mz_uint8 *p = r->m_tables[0].m_code_size; mz_uint i;
r->m_table_sizes[0] = 288; r->m_table_sizes[1] = 32; TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32);
for ( i = 0; i <= 143; ++i) *p++ = 8; for ( ; i <= 255; ++i) *p++ = 9; for ( ; i <= 279; ++i) *p++ = 7; for ( ; i <= 287; ++i) *p++ = 8;
}
else
{
for (counter = 0; counter < 3; counter++) { TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]); r->m_table_sizes[counter] += s_min_table_sizes[counter]; }
MZ_CLEAR_OBJ(r->m_tables[2].m_code_size); for (counter = 0; counter < r->m_table_sizes[2]; counter++) { mz_uint s; TINFL_GET_BITS(14, s, 3); r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s; }
r->m_table_sizes[2] = 19;
}
for ( ; (int)r->m_type >= 0; r->m_type--)
{
int tree_next, tree_cur; tinfl_huff_table *pTable;
mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16]; pTable = &r->m_tables[r->m_type]; MZ_CLEAR_OBJ(total_syms); MZ_CLEAR_OBJ(pTable->m_look_up); MZ_CLEAR_OBJ(pTable->m_tree);
for (i = 0; i < r->m_table_sizes[r->m_type]; ++i) total_syms[pTable->m_code_size[i]]++;
used_syms = 0, total = 0; next_code[0] = next_code[1] = 0;
for (i = 1; i <= 15; ++i) { used_syms += total_syms[i]; next_code[i + 1] = (total = ((total + total_syms[i]) << 1)); }
if ((65536 != total) && (used_syms > 1))
{
TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED);
}
for (tree_next = -1, sym_index = 0; sym_index < r->m_table_sizes[r->m_type]; ++sym_index)
{
mz_uint rev_code = 0, l, cur_code, code_size = pTable->m_code_size[sym_index]; if (!code_size) continue;
cur_code = next_code[code_size]++; for (l = code_size; l > 0; l--, cur_code >>= 1) rev_code = (rev_code << 1) | (cur_code & 1);
if (code_size <= TINFL_FAST_LOOKUP_BITS) { mz_int16 k = (mz_int16)((code_size << 9) | sym_index); while (rev_code < TINFL_FAST_LOOKUP_SIZE) { pTable->m_look_up[rev_code] = k; rev_code += (1 << code_size); } continue; }
if (0 == (tree_cur = pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)])) { pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; }
rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1);
for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--)
{
tree_cur -= ((rev_code >>= 1) & 1);
if (!pTable->m_tree[-tree_cur - 1]) { pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; } else tree_cur = pTable->m_tree[-tree_cur - 1];
}
tree_cur -= ((rev_code >>= 1) & 1); pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index;
}
if (r->m_type == 2)
{
for (counter = 0; counter < (r->m_table_sizes[0] + r->m_table_sizes[1]); )
{
mz_uint s; TINFL_HUFF_DECODE(16, dist, &r->m_tables[2]); if (dist < 16) { r->m_len_codes[counter++] = (mz_uint8)dist; continue; }
if ((dist == 16) && (!counter))
{
TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED);
}
num_extra = "\02\03\07"[dist - 16]; TINFL_GET_BITS(18, s, num_extra); s += "\03\03\013"[dist - 16];
TINFL_MEMSET(r->m_len_codes + counter, (dist == 16) ? r->m_len_codes[counter - 1] : 0, s); counter += s;
}
if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter)
{
TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED);
}
TINFL_MEMCPY(r->m_tables[0].m_code_size, r->m_len_codes, r->m_table_sizes[0]); TINFL_MEMCPY(r->m_tables[1].m_code_size, r->m_len_codes + r->m_table_sizes[0], r->m_table_sizes[1]);
}
}
for ( ; ; )
{
mz_uint8 *pSrc;
for ( ; ; )
{
if (((pIn_buf_end - pIn_buf_cur) < 4) || ((pOut_buf_end - pOut_buf_cur) < 2))
{
TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]);
if (counter >= 256)
break;
while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT); }
*pOut_buf_cur++ = (mz_uint8)counter;
}
else
{
int sym2; mz_uint code_len;
#if TINFL_USE_64BIT_BITBUF
if (num_bits < 30) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits); pIn_buf_cur += 4; num_bits += 32; }
#else
if (num_bits < 15) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); pIn_buf_cur += 2; num_bits += 16; }
#endif
if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
code_len = sym2 >> 9;
else
{
code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0);
}
counter = sym2; bit_buf >>= code_len; num_bits -= code_len;
if (counter & 256)
break;
#if !TINFL_USE_64BIT_BITBUF
if (num_bits < 15) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); pIn_buf_cur += 2; num_bits += 16; }
#endif
if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
code_len = sym2 >> 9;
else
{
code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0);
}
bit_buf >>= code_len; num_bits -= code_len;
pOut_buf_cur[0] = (mz_uint8)counter;
if (sym2 & 256)
{
pOut_buf_cur++;
counter = sym2;
break;
}
pOut_buf_cur[1] = (mz_uint8)sym2;
pOut_buf_cur += 2;
}
}
if ((counter &= 511) == 256) break;
num_extra = s_length_extra[counter - 257]; counter = s_length_base[counter - 257];
if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(25, extra_bits, num_extra); counter += extra_bits; }
TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]);
num_extra = s_dist_extra[dist]; dist = s_dist_base[dist];
if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(27, extra_bits, num_extra); dist += extra_bits; }
dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start;
if ((dist > dist_from_out_buf_start) && (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))
{
TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED);
}
pSrc = pOut_buf_start + ((dist_from_out_buf_start - dist) & out_buf_size_mask);
if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end)
{
while (counter--)
{
while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT); }
*pOut_buf_cur++ = pOut_buf_start[(dist_from_out_buf_start++ - dist) & out_buf_size_mask];
}
continue;
}
#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
else if ((counter >= 9) && (counter <= dist))
{
const mz_uint8 *pSrc_end = pSrc + (counter & ~7);
do
{
((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0];
((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1];
pOut_buf_cur += 8;
} while ((pSrc += 8) < pSrc_end);
if ((counter &= 7) < 3)
{
if (counter)
{
pOut_buf_cur[0] = pSrc[0];
if (counter > 1)
pOut_buf_cur[1] = pSrc[1];
pOut_buf_cur += counter;
}
continue;
}
}
#endif
do
{
pOut_buf_cur[0] = pSrc[0];
pOut_buf_cur[1] = pSrc[1];
pOut_buf_cur[2] = pSrc[2];
pOut_buf_cur += 3; pSrc += 3;
} while ((int)(counter -= 3) > 2);
if ((int)counter > 0)
{
pOut_buf_cur[0] = pSrc[0];
if ((int)counter > 1)
pOut_buf_cur[1] = pSrc[1];
pOut_buf_cur += counter;
}
}
}
} while (!(r->m_final & 1));
if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
{
TINFL_SKIP_BITS(32, num_bits & 7); for (counter = 0; counter < 4; ++counter) { mz_uint s; if (num_bits) TINFL_GET_BITS(41, s, 8); else TINFL_GET_BYTE(42, s); r->m_z_adler32 = (r->m_z_adler32 << 8) | s; }
}
TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE);
TINFL_CR_FINISH
common_exit:
r->m_num_bits = num_bits; r->m_bit_buf = bit_buf; r->m_dist = dist; r->m_counter = counter; r->m_num_extra = num_extra; r->m_dist_from_out_buf_start = dist_from_out_buf_start;
*pIn_buf_size = pIn_buf_cur - pIn_buf_next; *pOut_buf_size = pOut_buf_cur - pOut_buf_next;
if ((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0))
{
const mz_uint8 *ptr = pOut_buf_next; size_t buf_len = *pOut_buf_size;
mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, s2 = r->m_check_adler32 >> 16; size_t block_len = buf_len % 5552;
while (buf_len)
{
for (i = 0; i + 7 < block_len; i += 8, ptr += 8)
{
s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; s1 += ptr[2], s2 += s1; s1 += ptr[3], s2 += s1;
s1 += ptr[4], s2 += s1; s1 += ptr[5], s2 += s1; s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1;
}
for ( ; i < block_len; ++i) s1 += *ptr++, s2 += s1;
s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552;
}
r->m_check_adler32 = (s2 << 16) + s1; if ((status == TINFL_STATUS_DONE) && (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && (r->m_check_adler32 != r->m_z_adler32)) status = TINFL_STATUS_ADLER32_MISMATCH;
}
return status;
}
// Higher level helper functions.
void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags)
{
tinfl_decompressor decomp; void *pBuf = NULL, *pNew_buf; size_t src_buf_ofs = 0, out_buf_capacity = 0;
*pOut_len = 0;
tinfl_init(&decomp);
for ( ; ; )
{
size_t src_buf_size = src_buf_len - src_buf_ofs, dst_buf_size = out_buf_capacity - *pOut_len, new_out_buf_capacity;
tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8*)pSrc_buf + src_buf_ofs, &src_buf_size, (mz_uint8*)pBuf, pBuf ? (mz_uint8*)pBuf + *pOut_len : NULL, &dst_buf_size,
(flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT))
{
MZ_FREE(pBuf); *pOut_len = 0; return NULL;
}
src_buf_ofs += src_buf_size;
*pOut_len += dst_buf_size;
if (status == TINFL_STATUS_DONE) break;
new_out_buf_capacity = out_buf_capacity * 2; if (new_out_buf_capacity < 128) new_out_buf_capacity = 128;
pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity);
if (!pNew_buf)
{
MZ_FREE(pBuf); *pOut_len = 0; return NULL;
}
pBuf = pNew_buf; out_buf_capacity = new_out_buf_capacity;
}
return pBuf;
}
size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags)
{
tinfl_decompressor decomp; tinfl_status status; tinfl_init(&decomp);
status = tinfl_decompress(&decomp, (const mz_uint8*)pSrc_buf, &src_buf_len, (mz_uint8*)pOut_buf, (mz_uint8*)pOut_buf, &out_buf_len, (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
return (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED : out_buf_len;
}
int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
{
int result = 0;
tinfl_decompressor decomp;
mz_uint8 *pDict = (mz_uint8*)MZ_MALLOC(TINFL_LZ_DICT_SIZE); size_t in_buf_ofs = 0, dict_ofs = 0;
if (!pDict)
return TINFL_STATUS_FAILED;
tinfl_init(&decomp);
for ( ; ; )
{
size_t in_buf_size = *pIn_buf_size - in_buf_ofs, dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs;
tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8*)pIn_buf + in_buf_ofs, &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size,
(flags & ~(TINFL_FLAG_HAS_MORE_INPUT | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)));
in_buf_ofs += in_buf_size;
if ((dst_buf_size) && (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user)))
break;
if (status != TINFL_STATUS_HAS_MORE_OUTPUT)
{
result = (status == TINFL_STATUS_DONE);
break;
}
dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1);
}
MZ_FREE(pDict);
*pIn_buf_size = in_buf_ofs;
return result;
}
#endif // #ifndef TINFL_HEADER_FILE_ONLY
/*
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>
*/