mirror of
https://github.com/cuberite/libdeflate.git
synced 2025-09-10 04:41:45 -04:00
Support for Microsoft C / Visual Studio
This commit is contained in:
parent
051d55919b
commit
fb1de37c0e
29
Makefile
29
Makefile
@ -53,19 +53,19 @@ ifneq ($(findstring -mingw,$(CC)),)
|
||||
AR := $(patsubst %-gcc,%-ar,$(CC))
|
||||
endif
|
||||
WINDOWS := yes
|
||||
LIB_SUFFIX := .a
|
||||
LIB_SUFFIX := .lib
|
||||
SHLIB_SUFFIX := .dll
|
||||
PROG_SUFFIX := .exe
|
||||
PROG_CFLAGS := -static
|
||||
GZIP_CFLAGS := -municode
|
||||
PROG_SRC := tools/wgetopt.c
|
||||
PROG_CFLAGS := -static -municode
|
||||
SHLIB_IS_PIC := no
|
||||
else
|
||||
WINDOWS := no
|
||||
LIB_SUFFIX := .a
|
||||
SHLIB_SUFFIX := .so
|
||||
PROG_SUFFIX :=
|
||||
PROG_SRC :=
|
||||
PROG_CFLAGS :=
|
||||
GZIP_CFLAGS :=
|
||||
SHLIB_IS_PIC := yes
|
||||
endif
|
||||
|
||||
@ -102,6 +102,9 @@ ifneq ($(RUNTIME_CPU_DETECTION),yes)
|
||||
override CFLAGS += -DRUNTIME_CPU_DETECTION=0
|
||||
endif
|
||||
|
||||
PROG_CFLAGS += $(CFLAGS)
|
||||
PROG_SRC += libdeflate$(LIB_SUFFIX)
|
||||
|
||||
SRC := src/aligned_malloc.c
|
||||
ifeq ($(SUPPORT_COMPRESSION),yes)
|
||||
SRC += src/deflate_compress.c
|
||||
@ -151,15 +154,15 @@ libdeflate$(SHLIB_SUFFIX):$(SHLIB_OBJ)
|
||||
libdeflate$(LIB_SUFFIX):$(OBJ)
|
||||
$(AR) cr $@ $+
|
||||
|
||||
benchmark$(PROG_SUFFIX):tools/benchmark.c libdeflate$(LIB_SUFFIX)
|
||||
$(CC) -o $@ $(CFLAGS) -L. $+ libdeflate$(LIB_SUFFIX) -lz
|
||||
benchmark$(PROG_SUFFIX):tools/benchmark.c $(PROG_SRC)
|
||||
$(CC) -o $@ $(PROG_CFLAGS) $+ -lz
|
||||
|
||||
gzip$(PROG_SUFFIX):tools/gzip.c libdeflate$(LIB_SUFFIX)
|
||||
$(CC) -o $@ $(CFLAGS) $(GZIP_CFLAGS) $(PROG_CFLAGS) -L. $+ libdeflate$(LIB_SUFFIX)
|
||||
gzip$(PROG_SUFFIX):tools/gzip.c $(PROG_SRC)
|
||||
$(CC) -o $@ $(PROG_CFLAGS) $+
|
||||
|
||||
ifeq ($(WINDOWS),yes)
|
||||
gunzip$(PROG_SUFFIX):tools/gzip.c libdeflate$(LIB_SUFFIX)
|
||||
$(CC) -o $@ $(CFLAGS) $(GZIP_CFLAGS) $(PROG_CFLAGS) -L. $+ libdeflate$(LIB_SUFFIX)
|
||||
gunzip$(PROG_SUFFIX):tools/gzip.c $(PROG_SRC)
|
||||
$(CC) -o $@ $(PROG_CFLAGS) $+
|
||||
else
|
||||
gunzip$(PROG_SUFFIX):gzip$(PROG_SUFFIX)
|
||||
ln -f gzip$(PROG_SUFFIX) $@
|
||||
@ -187,10 +190,8 @@ endif
|
||||
all:$(TARGETS)
|
||||
|
||||
clean:
|
||||
rm -f libdeflate.a libdeflate.so libdeflate.dll src/*.o \
|
||||
benchmark benchmark.exe \
|
||||
gzip gzip.exe \
|
||||
gunzip gunzip.exe
|
||||
rm -f libdeflate.a libdeflate.so libdeflate.dll src/*.o src/*.obj \
|
||||
benchmark gzip gunzip *.exe *.lib *.obj *.exp
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
|
48
Makefile.msc
Normal file
48
Makefile.msc
Normal file
@ -0,0 +1,48 @@
|
||||
#
|
||||
# Makefile for the Microsoft toolchain. It builds a static library and a shared
|
||||
# library (DLL) and its corresponding import library.
|
||||
#
|
||||
# Usage:
|
||||
# nmake /f Makefile.msc
|
||||
#
|
||||
|
||||
CC = cl
|
||||
LD = link
|
||||
AR = lib
|
||||
CFLAGS = /MD /O2 -I.
|
||||
|
||||
STATICLIB = libdeflatestatic.lib
|
||||
SHAREDLIB = libdeflate.dll
|
||||
IMPLIB = libdeflate.lib
|
||||
|
||||
OBJS = src/adler32.obj \
|
||||
src/aligned_malloc.obj \
|
||||
src/crc32.obj \
|
||||
src/deflate_compress.obj \
|
||||
src/deflate_decompress.obj \
|
||||
src/gzip_compress.obj \
|
||||
src/gzip_decompress.obj \
|
||||
src/x86_cpu_features.obj \
|
||||
src/zlib_compress.obj \
|
||||
src/zlib_decompress.obj
|
||||
|
||||
all: $(STATICLIB) $(SHAREDLIB) $(IMPLIB)
|
||||
|
||||
$(STATICLIB): $(OBJS)
|
||||
$(AR) $(ARFLAGS) -out:$@ $(OBJS)
|
||||
|
||||
$(IMPLIB): $(SHAREDLIB)
|
||||
|
||||
$(SHAREDLIB): $(OBJS)
|
||||
$(LD) $(LDFLAGS) -out:$@ -dll -implib:$(IMPLIB) $(OBJS)
|
||||
|
||||
.c.obj:
|
||||
$(CC) -c /Fo:$@ $(CFLAGS) $<
|
||||
|
||||
clean:
|
||||
-del *.lib
|
||||
-del *.dll
|
||||
-del *.exe
|
||||
-del *.exp
|
||||
-del *.obj
|
||||
-del src\*.obj
|
15
README.md
15
README.md
@ -21,19 +21,18 @@ on it, and anyone is free to use it for any reason.
|
||||
Building
|
||||
========
|
||||
|
||||
Currently, the build system is very bare-bones. On a UNIX-like system, just run
|
||||
`make`. You need GNU Make and either GCC or Clang.
|
||||
|
||||
On a UNIX-like system, just run `make`. You need GNU Make and either GCC or
|
||||
Clang. There is no `make install` yet; just copy the file(s) to where you want.
|
||||
There are various options which can be set on the `make` command line; see the
|
||||
Makefile for details. As an example, you can run `make SUPPORT_COMPRESSION=no`
|
||||
to build a decompression-only library.
|
||||
|
||||
There is no `make install` yet; just copy the file(s) to where you want.
|
||||
|
||||
It's possible to build Windows binaries using MinGW with a command like this:
|
||||
|
||||
$ make CC=x86_64-w64-mingw32-gcc BUILD_PROGRAMS=yes
|
||||
On Windows, a separate Makefile, `Makefile.msc`, is provided for the tools that
|
||||
come with Visual Studio. However, using MinGW (GCC) instead is recommended
|
||||
because it is a superior compiler that produces better-performing binaries. You
|
||||
can build Windows binaries using MinGW with a command like this:
|
||||
|
||||
$ make CC=x86_64-w64-mingw32-gcc
|
||||
|
||||
API
|
||||
===
|
||||
|
39
libdeflate.h
39
libdeflate.h
@ -11,6 +11,19 @@ extern "C" {
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/* Microsoft C / Visual Studio garbage. If you want to link to the DLL version
|
||||
* of libdeflate, then #define LIBDEFLATE_DLL. */
|
||||
#ifdef _MSC_VER
|
||||
# ifdef BUILDING_LIBDEFLATE
|
||||
# define LIBDEFLATEAPI __declspec(dllexport)
|
||||
# elif defined(LIBDEFLATE_DLL)
|
||||
# define LIBDEFLATEAPI __declspec(dllimport)
|
||||
# endif
|
||||
#endif
|
||||
#ifndef LIBDEFLATEAPI
|
||||
# define LIBDEFLATEAPI
|
||||
#endif
|
||||
|
||||
/* ========================================================================== */
|
||||
/* Compression */
|
||||
/* ========================================================================== */
|
||||
@ -28,7 +41,7 @@ struct deflate_compressor;
|
||||
* to 32768, the largest size permissible in the DEFLATE format. It cannot be
|
||||
* changed at runtime.
|
||||
*/
|
||||
extern struct deflate_compressor *
|
||||
LIBDEFLATEAPI struct deflate_compressor *
|
||||
deflate_alloc_compressor(unsigned int compression_level);
|
||||
|
||||
/*
|
||||
@ -38,7 +51,7 @@ deflate_alloc_compressor(unsigned int compression_level);
|
||||
* The return value is the compressed size in bytes, or 0 if the data could not
|
||||
* be compressed to 'out_nbytes_avail' bytes or fewer.
|
||||
*/
|
||||
extern size_t
|
||||
LIBDEFLATEAPI size_t
|
||||
deflate_compress(struct deflate_compressor *compressor,
|
||||
const void *in, size_t in_nbytes,
|
||||
void *out, size_t out_nbytes_avail);
|
||||
@ -62,13 +75,13 @@ deflate_compress(struct deflate_compressor *compressor,
|
||||
* and store the data uncompressed if deflate_compress() returns 0, indicating
|
||||
* that the compressed data did not fit into the provided output buffer.
|
||||
*/
|
||||
extern size_t
|
||||
LIBDEFLATEAPI size_t
|
||||
deflate_compress_bound(struct deflate_compressor *compressor, size_t in_nbytes);
|
||||
|
||||
/*
|
||||
* Like deflate_compress(), but stores the data in the zlib wrapper format.
|
||||
*/
|
||||
extern size_t
|
||||
LIBDEFLATEAPI size_t
|
||||
zlib_compress(struct deflate_compressor *compressor,
|
||||
const void *in, size_t in_nbytes,
|
||||
void *out, size_t out_nbytes_avail);
|
||||
@ -77,13 +90,13 @@ zlib_compress(struct deflate_compressor *compressor,
|
||||
* Like deflate_compress_bound(), but assumes the data will be compressed with
|
||||
* zlib_compress() rather than with deflate_compress().
|
||||
*/
|
||||
extern size_t
|
||||
LIBDEFLATEAPI size_t
|
||||
zlib_compress_bound(struct deflate_compressor *compressor, size_t in_nbytes);
|
||||
|
||||
/*
|
||||
* Like deflate_compress(), but stores the data in the gzip wrapper format.
|
||||
*/
|
||||
extern size_t
|
||||
LIBDEFLATEAPI size_t
|
||||
gzip_compress(struct deflate_compressor *compressor,
|
||||
const void *in, size_t in_nbytes,
|
||||
void *out, size_t out_nbytes_avail);
|
||||
@ -92,7 +105,7 @@ gzip_compress(struct deflate_compressor *compressor,
|
||||
* Like deflate_compress_bound(), but assumes the data will be compressed with
|
||||
* gzip_compress() rather than with deflate_compress().
|
||||
*/
|
||||
extern size_t
|
||||
LIBDEFLATEAPI size_t
|
||||
gzip_compress_bound(struct deflate_compressor *compressor, size_t in_nbytes);
|
||||
|
||||
/*
|
||||
@ -100,7 +113,7 @@ gzip_compress_bound(struct deflate_compressor *compressor, size_t in_nbytes);
|
||||
* deflate_alloc_compressor(). If a NULL pointer is passed in, no action is
|
||||
* taken.
|
||||
*/
|
||||
extern void
|
||||
LIBDEFLATEAPI void
|
||||
deflate_free_compressor(struct deflate_compressor *compressor);
|
||||
|
||||
/* ========================================================================== */
|
||||
@ -120,7 +133,7 @@ struct deflate_decompressor;
|
||||
* DEFLATE, zlib, or gzip); however, the appropriate decompression function must
|
||||
* be called.
|
||||
*/
|
||||
extern struct deflate_decompressor *
|
||||
LIBDEFLATEAPI struct deflate_decompressor *
|
||||
deflate_alloc_decompressor(void);
|
||||
|
||||
/*
|
||||
@ -172,7 +185,7 @@ enum decompress_result {
|
||||
* but no other problems were encountered, or another nonzero result code if
|
||||
* decompression failed for another reason.
|
||||
*/
|
||||
extern enum decompress_result
|
||||
LIBDEFLATEAPI enum decompress_result
|
||||
deflate_decompress(struct deflate_decompressor *decompressor,
|
||||
const void *in, size_t in_nbytes,
|
||||
void *out, size_t out_nbytes_avail,
|
||||
@ -182,7 +195,7 @@ deflate_decompress(struct deflate_decompressor *decompressor,
|
||||
* Like deflate_decompress(), but assumes the zlib wrapper format instead of raw
|
||||
* DEFLATE.
|
||||
*/
|
||||
extern enum decompress_result
|
||||
LIBDEFLATEAPI enum decompress_result
|
||||
zlib_decompress(struct deflate_decompressor *decompressor,
|
||||
const void *in, size_t in_nbytes,
|
||||
void *out, size_t out_nbytes_avail,
|
||||
@ -192,7 +205,7 @@ zlib_decompress(struct deflate_decompressor *decompressor,
|
||||
* Like deflate_decompress(), but assumes the gzip wrapper format instead of raw
|
||||
* DEFLATE.
|
||||
*/
|
||||
extern enum decompress_result
|
||||
LIBDEFLATEAPI enum decompress_result
|
||||
gzip_decompress(struct deflate_decompressor *decompressor,
|
||||
const void *in, size_t in_nbytes,
|
||||
void *out, size_t out_nbytes_avail,
|
||||
@ -203,7 +216,7 @@ gzip_decompress(struct deflate_decompressor *decompressor,
|
||||
* with deflate_alloc_decompressor(). If a NULL pointer is passed in, no action
|
||||
* is taken.
|
||||
*/
|
||||
extern void
|
||||
LIBDEFLATEAPI void
|
||||
deflate_free_decompressor(struct deflate_decompressor *decompressor);
|
||||
|
||||
|
||||
|
@ -126,7 +126,7 @@ bt_matchfinder_advance_one_byte(struct bt_matchfinder * const restrict mf,
|
||||
const u32 max_len,
|
||||
const u32 nice_len,
|
||||
const u32 max_search_depth,
|
||||
u32 next_hashes[const restrict static 2],
|
||||
u32 next_hashes[restrict 2],
|
||||
u32 * const restrict best_len_ret,
|
||||
struct lz_match * restrict lz_matchptr,
|
||||
const bool record_matches)
|
||||
@ -294,7 +294,7 @@ bt_matchfinder_get_matches(struct bt_matchfinder *mf,
|
||||
u32 max_len,
|
||||
u32 nice_len,
|
||||
u32 max_search_depth,
|
||||
u32 next_hashes[static 2],
|
||||
u32 next_hashes[2],
|
||||
u32 *best_len_ret,
|
||||
struct lz_match *lz_matchptr)
|
||||
{
|
||||
@ -323,7 +323,7 @@ bt_matchfinder_skip_position(struct bt_matchfinder *mf,
|
||||
u32 max_len,
|
||||
u32 nice_len,
|
||||
u32 max_search_depth,
|
||||
u32 next_hashes[static 2])
|
||||
u32 next_hashes[2])
|
||||
{
|
||||
u32 best_len;
|
||||
bt_matchfinder_advance_one_byte(mf,
|
||||
|
@ -2,9 +2,7 @@
|
||||
* compiler-gcc.h - definitions for the GNU C compiler (and for clang)
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __WIN32__
|
||||
#ifdef _WIN32
|
||||
# define LIBEXPORT __declspec(dllexport)
|
||||
#else
|
||||
# define LIBEXPORT __attribute__((visibility("default")))
|
||||
|
56
src/compiler-msc.h
Normal file
56
src/compiler-msc.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* compiler-msc.h - definitions for the Microsoft C Compiler
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define BUILDING_LIBDEFLATE
|
||||
|
||||
/* MSC __restrict has nonstandard behavior. Don't use it. */
|
||||
#define restrict
|
||||
|
||||
#define LIBEXPORT __declspec(dllexport)
|
||||
#define forceinline __forceinline
|
||||
|
||||
/* Assume a little endian architecture with fast unaligned access. */
|
||||
#define CPU_IS_LITTLE_ENDIAN() 1
|
||||
#define UNALIGNED_ACCESS_IS_FAST 1
|
||||
|
||||
#define compiler_bswap16 _byteswap_ushort
|
||||
#define compiler_bswap32 _byteswap_ulong
|
||||
#define compiler_bswap64 _byteswap_uint64
|
||||
|
||||
static forceinline unsigned
|
||||
compiler_fls32(uint32_t n)
|
||||
{
|
||||
_BitScanReverse(&n, n);
|
||||
return n;
|
||||
}
|
||||
#define compiler_fls32 compiler_fls32
|
||||
|
||||
static forceinline unsigned
|
||||
compiler_ffs32(uint32_t n)
|
||||
{
|
||||
_BitScanForward(&n, n);
|
||||
return n;
|
||||
}
|
||||
#define compiler_ffs32 compiler_ffs32
|
||||
|
||||
#ifdef _M_X64
|
||||
static forceinline unsigned
|
||||
compiler_fls64(uint64_t n)
|
||||
{
|
||||
_BitScanReverse64(&n, n);
|
||||
return n;
|
||||
}
|
||||
#define compiler_fls64 compiler_fls64
|
||||
|
||||
static forceinline unsigned
|
||||
compiler_ffs64(uint64_t n)
|
||||
{
|
||||
_BitScanForward64(&n, n);
|
||||
return n;
|
||||
}
|
||||
#define compiler_ffs64 compiler_ffs64
|
||||
#endif /* _M_X64 */
|
@ -8,8 +8,10 @@
|
||||
* define as many of them as possible. */
|
||||
#ifdef __GNUC__
|
||||
# include "compiler-gcc.h"
|
||||
#elif defined(_MSC_VER)
|
||||
# include "compiler-msc.h"
|
||||
#else
|
||||
# warning "Unrecognized compiler. Please add a header file for your compiler. Compilation will proceed, but performance may suffer!"
|
||||
# pragma message("Unrecognized compiler. Please add a header file for your compiler. Compilation will proceed, but performance may suffer!")
|
||||
#endif
|
||||
|
||||
/* forceinline - force a function to be inlined */
|
||||
|
@ -26,6 +26,8 @@ FUNCNAME(struct deflate_decompressor * restrict d,
|
||||
u16 nlen;
|
||||
unsigned num_litlen_syms;
|
||||
unsigned num_offset_syms;
|
||||
u16 tmp16;
|
||||
u32 tmp32;
|
||||
|
||||
next_block:
|
||||
/* Starting to read the next block. */
|
||||
|
@ -11,13 +11,13 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "libdeflate.h"
|
||||
|
||||
#include "aligned_malloc.h"
|
||||
#include "deflate_compress.h"
|
||||
#include "deflate_constants.h"
|
||||
#include "unaligned.h"
|
||||
|
||||
#include "libdeflate.h"
|
||||
|
||||
/*
|
||||
* Note: when compiling this file, SUPPORT_NEAR_OPTIMAL_PARSING should be
|
||||
* defined to either 0 or 1. When defined to 1, the near-optimal parsing
|
||||
@ -1565,7 +1565,7 @@ deflate_compress_greedy(struct deflate_compressor * restrict c,
|
||||
struct deflate_sequence *next_seq = c->sequences;
|
||||
u32 litrunlen = 0;
|
||||
u32 items_remaining = MAX_ITEMS_PER_BLOCK;
|
||||
u32 next_hashes[2] = {};
|
||||
u32 next_hashes[2] = {0, 0};
|
||||
|
||||
deflate_init_output(&os, out, out_nbytes_avail);
|
||||
deflate_reset_symbol_frequencies(c);
|
||||
@ -1662,7 +1662,7 @@ deflate_compress_lazy(struct deflate_compressor * restrict c,
|
||||
struct deflate_sequence *next_seq = c->sequences;
|
||||
u32 litrunlen = 0;
|
||||
u32 items_remaining = MAX_ITEMS_PER_BLOCK;
|
||||
u32 next_hashes[2] = {};
|
||||
u32 next_hashes[2] = {0, 0};
|
||||
|
||||
deflate_init_output(&os, out, out_nbytes_avail);
|
||||
deflate_reset_symbol_frequencies(c);
|
||||
@ -2171,7 +2171,7 @@ deflate_compress_near_optimal(struct deflate_compressor * restrict c,
|
||||
struct lz_match *cache_end;
|
||||
const u8 *in_block_begin;
|
||||
const u8 *in_block_end;
|
||||
u32 next_hashes[2] = {};
|
||||
u32 next_hashes[2] = {0, 0};
|
||||
|
||||
deflate_init_output(&os, out, out_nbytes_avail);
|
||||
deflate_reset_symbol_frequencies(c);
|
||||
|
@ -9,10 +9,10 @@
|
||||
*
|
||||
* ---------------------------------------------------------------------------
|
||||
*
|
||||
* This is a highly optimized DEFLATE decompressor. On x86_64 it decompresses
|
||||
* data in about 52% of the time of zlib (48% if BMI2 instructions are
|
||||
* available). On other architectures it should still be significantly faster
|
||||
* than zlib, but the difference may be smaller.
|
||||
* This is a highly optimized DEFLATE decompressor. When compiled with gcc on
|
||||
* x86_64, it decompresses data in about 52% of the time of zlib (48% if BMI2
|
||||
* instructions are available). On other architectures it should still be
|
||||
* significantly faster than zlib, but the difference may be smaller.
|
||||
*
|
||||
* Why this is faster than zlib's implementation:
|
||||
*
|
||||
@ -30,19 +30,19 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "libdeflate.h"
|
||||
|
||||
#include "deflate_constants.h"
|
||||
#include "unaligned.h"
|
||||
#include "x86_cpu_features.h"
|
||||
|
||||
#include "libdeflate.h"
|
||||
|
||||
/* By default, if the expression passed to SAFETY_CHECK() evaluates to false,
|
||||
* then deflate_decompress() immediately returns DECOMPRESS_BAD_DATA as the
|
||||
* compressed data is invalid. But if unsafe decompression is enabled, then the
|
||||
* value of the expression is ignored, allowing the compiler to optimize out
|
||||
* some code. */
|
||||
#if UNSAFE_DECOMPRESSION
|
||||
# warning "UNSAFE DECOMPRESSION IS ENABLED. THIS MUST ONLY BE USED IF THE DECOMPRESSOR INPUT WILL ALWAYS BE TRUSTED!"
|
||||
# pragma message("UNSAFE DECOMPRESSION IS ENABLED. THIS MUST ONLY BE USED IF THE DECOMPRESSOR INPUT WILL ALWAYS BE TRUSTED!")
|
||||
# define SAFETY_CHECK(expr) (void)(expr)
|
||||
#else
|
||||
# define SAFETY_CHECK(expr) if (unlikely(!(expr))) return DECOMPRESS_BAD_DATA
|
||||
@ -194,16 +194,14 @@ typedef machine_word_t bitbuf_t;
|
||||
* corrupted in such a way that fully retains its validity. Users should run a
|
||||
* checksum against the uncompressed data if they wish to detect corruptions.
|
||||
*/
|
||||
#define FILL_BITS_BYTEWISE() \
|
||||
({ \
|
||||
do { \
|
||||
if (likely(in_next != in_end)) \
|
||||
bitbuf |= (bitbuf_t)*in_next++ << bitsleft; \
|
||||
else \
|
||||
overrun_count++; \
|
||||
bitsleft += 8; \
|
||||
} while (bitsleft <= BITBUF_NBITS - 8); \
|
||||
})
|
||||
#define FILL_BITS_BYTEWISE() \
|
||||
do { \
|
||||
if (likely(in_next != in_end)) \
|
||||
bitbuf |= (bitbuf_t)*in_next++ << bitsleft; \
|
||||
else \
|
||||
overrun_count++; \
|
||||
bitsleft += 8; \
|
||||
} while (bitsleft <= BITBUF_NBITS - 8)
|
||||
|
||||
/*
|
||||
* Fill the bitbuffer variable by reading the next word from the input buffer.
|
||||
@ -213,12 +211,12 @@ typedef machine_word_t bitbuf_t;
|
||||
* most efficient on little-endian architectures that support fast unaligned
|
||||
* access, such as x86 and x86_64.
|
||||
*/
|
||||
#define FILL_BITS_WORDWISE() \
|
||||
({ \
|
||||
bitbuf |= get_unaligned_leword(in_next) << bitsleft; \
|
||||
in_next += (BITBUF_NBITS - bitsleft) >> 3; \
|
||||
bitsleft += (BITBUF_NBITS - bitsleft) & ~7; \
|
||||
})
|
||||
#define FILL_BITS_WORDWISE() \
|
||||
do { \
|
||||
bitbuf |= get_unaligned_leword(in_next) << bitsleft; \
|
||||
in_next += (BITBUF_NBITS - bitsleft) >> 3; \
|
||||
bitsleft += (BITBUF_NBITS - bitsleft) & ~7; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Does the bitbuffer variable currently contain at least 'n' bits?
|
||||
@ -226,56 +224,34 @@ typedef machine_word_t bitbuf_t;
|
||||
#define HAVE_BITS(n) (bitsleft >= (n))
|
||||
|
||||
/*
|
||||
* Raw form of ENSURE_BITS(): the bitbuffer variable must not already contain
|
||||
* the requested number of bits.
|
||||
* Load more bits from the input buffer until the specified number of bits is
|
||||
* present in the bitbuffer variable. 'n' cannot be too large; see MAX_ENSURE
|
||||
* and CAN_ENSURE().
|
||||
*/
|
||||
#define DO_ENSURE_BITS(n) \
|
||||
({ \
|
||||
#define ENSURE_BITS(n) \
|
||||
if (!HAVE_BITS(n)) { \
|
||||
if (CPU_IS_LITTLE_ENDIAN() && \
|
||||
UNALIGNED_ACCESS_IS_FAST && \
|
||||
likely(in_end - in_next >= sizeof(bitbuf_t))) \
|
||||
FILL_BITS_WORDWISE(); \
|
||||
else \
|
||||
FILL_BITS_BYTEWISE(); \
|
||||
})
|
||||
|
||||
/*
|
||||
* Load more bits from the input buffer until the specified number of bits is
|
||||
* present in the bitbuffer variable. 'n' cannot be too large; see MAX_ENSURE
|
||||
* and CAN_ENSURE().
|
||||
*/
|
||||
#define ENSURE_BITS(n) \
|
||||
({ \
|
||||
if (!HAVE_BITS(n)) \
|
||||
DO_ENSURE_BITS(n); \
|
||||
})
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the next 'n' bits from the bitbuffer variable without removing them.
|
||||
*/
|
||||
#define BITS(n) \
|
||||
({ \
|
||||
(u32)bitbuf & (((u32)1 << (n)) - 1); \
|
||||
})
|
||||
#define BITS(n) ((u32)bitbuf & (((u32)1 << (n)) - 1))
|
||||
|
||||
/*
|
||||
* Remove the next 'n' bits from the bitbuffer variable.
|
||||
*/
|
||||
#define REMOVE_BITS(n) \
|
||||
({ \
|
||||
bitbuf >>= (n); \
|
||||
bitsleft -= (n); \
|
||||
})
|
||||
#define REMOVE_BITS(n) (bitbuf >>= (n), bitsleft -= (n))
|
||||
|
||||
/*
|
||||
* Remove and return the next 'n' bits from the bitbuffer variable.
|
||||
*/
|
||||
#define POP_BITS(n) \
|
||||
({ \
|
||||
u32 bits = BITS(n); \
|
||||
REMOVE_BITS(n); \
|
||||
bits; \
|
||||
})
|
||||
#define POP_BITS(n) (tmp32 = BITS(n), REMOVE_BITS(n), tmp32)
|
||||
|
||||
/*
|
||||
* Align the input to the next byte boundary, discarding any remaining bits in
|
||||
@ -287,24 +263,17 @@ typedef machine_word_t bitbuf_t;
|
||||
* be actually discarded.
|
||||
*/
|
||||
#define ALIGN_INPUT() \
|
||||
({ \
|
||||
do { \
|
||||
in_next -= (bitsleft >> 3) - MIN(overrun_count, bitsleft >> 3); \
|
||||
bitbuf = 0; \
|
||||
bitsleft = 0; \
|
||||
})
|
||||
} while(0)
|
||||
|
||||
/*
|
||||
* Read a 16-bit value from the input. This must have been preceded by a call
|
||||
* to ALIGN_INPUT(), and the caller must have already checked for overrun.
|
||||
*/
|
||||
#define READ_U16() \
|
||||
({ \
|
||||
u16 v; \
|
||||
\
|
||||
v = get_unaligned_le16(in_next); \
|
||||
in_next += 2; \
|
||||
v; \
|
||||
})
|
||||
#define READ_U16() (tmp16 = get_unaligned_le16(in_next), in_next += 2, tmp16)
|
||||
|
||||
/*****************************************************************************
|
||||
* Huffman decoding *
|
||||
|
@ -8,13 +8,13 @@
|
||||
* You can do whatever you want with this file.
|
||||
*/
|
||||
|
||||
#include "libdeflate.h"
|
||||
|
||||
#include "crc32.h"
|
||||
#include "deflate_compress.h"
|
||||
#include "gzip_constants.h"
|
||||
#include "unaligned.h"
|
||||
|
||||
#include "libdeflate.h"
|
||||
|
||||
LIBEXPORT size_t
|
||||
gzip_compress(struct deflate_compressor *c, const void *in, size_t in_size,
|
||||
void *out, size_t out_nbytes_avail)
|
||||
|
@ -8,12 +8,12 @@
|
||||
* You can do whatever you want with this file.
|
||||
*/
|
||||
|
||||
#include "libdeflate.h"
|
||||
|
||||
#include "crc32.h"
|
||||
#include "gzip_constants.h"
|
||||
#include "unaligned.h"
|
||||
|
||||
#include "libdeflate.h"
|
||||
|
||||
LIBEXPORT enum decompress_result
|
||||
gzip_decompress(struct deflate_decompressor *d,
|
||||
const void *in, size_t in_nbytes,
|
||||
|
@ -167,12 +167,12 @@ hc_matchfinder_longest_match(struct hc_matchfinder * const restrict mf,
|
||||
const u32 max_len,
|
||||
const u32 nice_len,
|
||||
const u32 max_search_depth,
|
||||
u32 next_hashes[const restrict static 2],
|
||||
u32 next_hashes[restrict 2],
|
||||
u32 * const restrict offset_ret)
|
||||
{
|
||||
const u8 *in_next = in_base + cur_pos;
|
||||
u32 depth_remaining = max_search_depth;
|
||||
const u8 *best_matchptr = best_matchptr; /* uninitialized */
|
||||
const u8 *best_matchptr = in_next;
|
||||
const mf_pos_t cutoff = cur_pos - MATCHFINDER_WINDOW_SIZE;
|
||||
mf_pos_t cur_node3, cur_node4;
|
||||
u32 hash3, hash4;
|
||||
@ -335,7 +335,7 @@ hc_matchfinder_skip_positions(struct hc_matchfinder * const restrict mf,
|
||||
const ptrdiff_t cur_pos,
|
||||
const ptrdiff_t end_pos,
|
||||
const u32 count,
|
||||
u32 next_hashes[const restrict static 2])
|
||||
u32 next_hashes[restrict 2])
|
||||
{
|
||||
const u8 *in_next = in_base + cur_pos;
|
||||
const u8 * const stop_ptr = in_next + count;
|
||||
|
@ -8,13 +8,13 @@
|
||||
* You can do whatever you want with this file.
|
||||
*/
|
||||
|
||||
#include "libdeflate.h"
|
||||
|
||||
#include "adler32.h"
|
||||
#include "deflate_compress.h"
|
||||
#include "unaligned.h"
|
||||
#include "zlib_constants.h"
|
||||
|
||||
#include "libdeflate.h"
|
||||
|
||||
LIBEXPORT size_t
|
||||
zlib_compress(struct deflate_compressor *c, const void *in, size_t in_size,
|
||||
void *out, size_t out_nbytes_avail)
|
||||
|
@ -8,12 +8,12 @@
|
||||
* You can do whatever you want with this file.
|
||||
*/
|
||||
|
||||
#include "libdeflate.h"
|
||||
|
||||
#include "adler32.h"
|
||||
#include "unaligned.h"
|
||||
#include "zlib_constants.h"
|
||||
|
||||
#include "libdeflate.h"
|
||||
|
||||
LIBEXPORT enum decompress_result
|
||||
zlib_decompress(struct deflate_decompressor *d,
|
||||
const void *in, size_t in_nbytes,
|
||||
|
@ -8,70 +8,37 @@
|
||||
* You can do whatever you want with this file.
|
||||
*/
|
||||
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
#undef _ANSI_SOURCE
|
||||
#define _POSIX_C_SOURCE 199309L
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include "util.h"
|
||||
|
||||
#include <libdeflate.h>
|
||||
#include <zlib.h>
|
||||
|
||||
static const tchar *const optstring = T("s:l:123456789zgYZh");
|
||||
|
||||
static void
|
||||
usage(FILE *fp)
|
||||
{
|
||||
static const char * const str =
|
||||
"Usage: benchmark [FILE...]\n"
|
||||
"Usage: benchmark [OPTION]... [FILE]...\n"
|
||||
"\n"
|
||||
"A compression and decompression benchmark and testing program.\n"
|
||||
"Benchmarks are run on each FILE specified, or stdin if no file is specified.\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
" -s, --chunk-size=SIZE chunk size\n"
|
||||
" -l, --level=LEVEL compression level [1-12]\n"
|
||||
" -1 fastest\n"
|
||||
" -9 slow\n"
|
||||
" -z, --zlib use zlib wrapper\n"
|
||||
" -g, --gzip use gzip wrapper\n"
|
||||
" -Y, --compress-with-libz compress with libz, not libdeflate\n"
|
||||
" -Z, --decompress-with-libz decompress with libz, not libdeflate\n"
|
||||
" -h, --help print this help\n"
|
||||
" -s SIZE chunk size\n"
|
||||
" -l LEVEL compression level [1-12]\n"
|
||||
" -1 fastest\n"
|
||||
" -9 slow\n"
|
||||
" -z use zlib wrapper\n"
|
||||
" -g use gzip wrapper\n"
|
||||
" -Y compress with libz, not libdeflate\n"
|
||||
" -Z decompress with libz, not libdeflate\n"
|
||||
" -h print this help\n"
|
||||
;
|
||||
|
||||
fputs(str, fp);
|
||||
}
|
||||
|
||||
static void
|
||||
fatal_error(const char *fmt, ...)
|
||||
{
|
||||
va_list va;
|
||||
|
||||
va_start(va, fmt);
|
||||
fprintf(stderr, "ERROR: ");
|
||||
vfprintf(stderr, fmt, va);
|
||||
fprintf(stderr, "\n");
|
||||
va_end(va);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#define ASSERT(expr, fmt, ...) \
|
||||
{ \
|
||||
if (!(expr)) \
|
||||
fatal_error((fmt), ## __VA_ARGS__); \
|
||||
}
|
||||
|
||||
enum wrapper {
|
||||
NO_WRAPPER,
|
||||
ZLIB_WRAPPER,
|
||||
@ -293,15 +260,6 @@ decompressor_destroy(struct decompressor *d)
|
||||
(*d->free_private)(d->private);
|
||||
}
|
||||
|
||||
#define TIME_UNIT_PER_MS 1000000
|
||||
static uint64_t
|
||||
current_time(void)
|
||||
{
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
return ((uint64_t)1000000000 * ts.tv_sec) + ts.tv_nsec;
|
||||
}
|
||||
|
||||
static void
|
||||
do_benchmark(int fd, char *ubuf1, char *ubuf2,
|
||||
char *cbuf, uint32_t max_chunk_size,
|
||||
@ -312,13 +270,9 @@ do_benchmark(int fd, char *ubuf1, char *ubuf2,
|
||||
uint64_t compress_time_total = 0;
|
||||
uint64_t decompress_time_total = 0;
|
||||
|
||||
#ifdef __WIN32__
|
||||
_setmode(fd, O_BINARY);
|
||||
#endif
|
||||
|
||||
for (;;) {
|
||||
char *p = ubuf1;
|
||||
ssize_t bytes_read;
|
||||
int32_t bytes_read;
|
||||
size_t usize;
|
||||
size_t csize;
|
||||
uint64_t start_time;
|
||||
@ -381,27 +335,15 @@ do_benchmark(int fd, char *ubuf1, char *ubuf2,
|
||||
(unsigned int)(csize_total * 100 / usize_total),
|
||||
(unsigned int)(csize_total * 100000 / usize_total % 1000));
|
||||
printf("\tCompression time: %"PRIu64" ms (%"PRIu64" MB/s)\n",
|
||||
compress_time_total / TIME_UNIT_PER_MS,
|
||||
compress_time_total / 1000000,
|
||||
1000 * usize_total / compress_time_total);
|
||||
printf("\tDecompression time: %"PRIu64" ms (%"PRIu64" MB/s)\n",
|
||||
decompress_time_total / TIME_UNIT_PER_MS,
|
||||
decompress_time_total / 1000000,
|
||||
1000 * usize_total / decompress_time_total);
|
||||
}
|
||||
|
||||
static const char *const optstring = "s:l:0123456789gzYZh";
|
||||
static const struct option longopts[] = {
|
||||
{"chunk-size", required_argument, NULL, 's'},
|
||||
{"level", required_argument, NULL, 'l'},
|
||||
{"zlib", no_argument, NULL, 'z'},
|
||||
{"gzip", no_argument, NULL, 'g'},
|
||||
{"compress-with-libz", no_argument, NULL, 'Y'},
|
||||
{"decompress-with-libz", no_argument, NULL, 'Z'},
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{NULL, 0, NULL, 0},
|
||||
};
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
main(int argc, tchar *argv[])
|
||||
{
|
||||
uint32_t chunk_size = 32768;
|
||||
int level = 6;
|
||||
@ -415,17 +357,23 @@ main(int argc, char **argv)
|
||||
struct decompressor d;
|
||||
int opt_char;
|
||||
|
||||
while ((opt_char =
|
||||
getopt_long(argc, argv, optstring, longopts, NULL)) != -1)
|
||||
{
|
||||
while ((opt_char = tgetopt(argc, argv, optstring)) != -1) {
|
||||
switch (opt_char) {
|
||||
case 's':
|
||||
chunk_size = strtoul(optarg, NULL, 10);
|
||||
chunk_size = tstrtoul(toptarg, NULL, 10);
|
||||
break;
|
||||
case 'l':
|
||||
level = strtoul(optarg, NULL, 10);
|
||||
level = tstrtoul(toptarg, NULL, 10);
|
||||
break;
|
||||
case '1' ... '9':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
level = opt_char - '0';
|
||||
break;
|
||||
case 'z':
|
||||
@ -449,8 +397,8 @@ main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
argc -= toptind;
|
||||
argv += toptind;
|
||||
|
||||
printf("Benchmarking DEFLATE compression:\n");
|
||||
printf("\tCompression level: %d\n", level);
|
||||
@ -475,14 +423,15 @@ main(int argc, char **argv)
|
||||
|
||||
if (argc == 0) {
|
||||
printf("Reading from stdin...\n");
|
||||
set_binary_mode(STDIN_FILENO);
|
||||
do_benchmark(STDIN_FILENO, ubuf1, ubuf2,
|
||||
cbuf, chunk_size, &c, &d);
|
||||
} else {
|
||||
for (int i = 0; i < argc; i++) {
|
||||
printf("Processing \"%s\"...\n", argv[i]);
|
||||
int fd = open(argv[i], O_RDONLY);
|
||||
printf("Processing \"%"TS"\"...\n", argv[i]);
|
||||
int fd = topen(argv[i], O_RDONLY | O_BINARY);
|
||||
ASSERT(fd >= 0,
|
||||
"Can't open \"%s\" for reading: %s\n",
|
||||
"Can't open \"%"TS"\" for reading: %s\n",
|
||||
argv[i], strerror(errno));
|
||||
do_benchmark(fd, ubuf1, ubuf2, cbuf, chunk_size, &c, &d);
|
||||
close(fd);
|
||||
|
103
tools/gzip.c
103
tools/gzip.c
@ -8,76 +8,7 @@
|
||||
* You can do whatever you want with this file.
|
||||
*/
|
||||
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef __WIN32__
|
||||
# include <wchar.h>
|
||||
# include <windows.h>
|
||||
#else
|
||||
# include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#include "libdeflate.h"
|
||||
|
||||
#ifdef __WIN32__
|
||||
# define main wmain
|
||||
# define tchar wchar_t
|
||||
# define _T(text) L##text
|
||||
# define T(text) _T(text)
|
||||
# define TS "ls"
|
||||
# define tstrcmp wcscmp
|
||||
# define tstrlen wcslen
|
||||
# define tmemcpy wmemcpy
|
||||
# define tstrrchr wcsrchr
|
||||
# define tstrtol wcstol
|
||||
# define topen _wopen
|
||||
# define topen _wopen
|
||||
# define tstat _wstati64
|
||||
# define tunlink _wunlink
|
||||
#else
|
||||
# define main main
|
||||
# define tchar char
|
||||
# define T(text) text
|
||||
# define TS "s"
|
||||
# define tstrcmp strcmp
|
||||
# define tstrlen strlen
|
||||
# define tmemcpy memcpy
|
||||
# define tstrrchr strrchr
|
||||
# define tstrtol strtol
|
||||
# define topen open
|
||||
# define tstat stat
|
||||
# define tunlink unlink
|
||||
#endif
|
||||
|
||||
#ifndef O_BINARY
|
||||
# define O_BINARY 0
|
||||
#endif
|
||||
|
||||
static const tchar *
|
||||
basename(const tchar *argv0)
|
||||
{
|
||||
const tchar *p = tstrrchr(argv0, '/');
|
||||
#ifdef __WIN32__
|
||||
const tchar *p2 = tstrrchr(argv0, '\\');
|
||||
if (p2 && (!p || p2 > p))
|
||||
p = p2;
|
||||
#endif
|
||||
if (p)
|
||||
return p + 1;
|
||||
return argv0;
|
||||
}
|
||||
#include "util.h"
|
||||
|
||||
static bool
|
||||
is_gunzip(const tchar *argv0)
|
||||
@ -86,7 +17,7 @@ is_gunzip(const tchar *argv0)
|
||||
|
||||
if (!tstrcmp(name, T("gunzip")))
|
||||
return true;
|
||||
#ifdef __WIN32__
|
||||
#ifdef _WIN32
|
||||
if (!tstrcmp(name, T("gunzip.exe")))
|
||||
return true;
|
||||
#endif
|
||||
@ -104,26 +35,6 @@ usage(void)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void
|
||||
fatal_error(const char *fmt, ...)
|
||||
{
|
||||
va_list va;
|
||||
|
||||
va_start(va, fmt);
|
||||
fprintf(stderr, "ERROR: ");
|
||||
vfprintf(stderr, fmt, va);
|
||||
fprintf(stderr, "\n");
|
||||
va_end(va);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#define ASSERT(expr, fmt, ...) \
|
||||
{ \
|
||||
if (!(expr)) \
|
||||
fatal_error((fmt), ## __VA_ARGS__); \
|
||||
}
|
||||
|
||||
static void *
|
||||
map_file_contents(const tchar *path, size_t *size_ret, void **token_ret)
|
||||
{
|
||||
@ -148,8 +59,8 @@ map_file_contents(const tchar *path, size_t *size_ret, void **token_ret)
|
||||
"File \"%"TS"\" cannot be processed by "
|
||||
"this program because it is too large.", path);
|
||||
|
||||
#ifdef __WIN32__
|
||||
HANDLE h = CreateFileMapping((HANDLE)_get_osfhandle(fd),
|
||||
#ifdef _WIN32
|
||||
HANDLE h = CreateFileMapping((HANDLE)(intptr_t)_get_osfhandle(fd),
|
||||
NULL, PAGE_READONLY, 0, 0, NULL);
|
||||
ASSERT(h != NULL, "Unable create file mapping for \"%"TS"\": "
|
||||
"Windows error %u", path, (unsigned int )GetLastError());
|
||||
@ -178,7 +89,7 @@ map_file_contents(const tchar *path, size_t *size_ret, void **token_ret)
|
||||
static void
|
||||
unmap_file_contents(void *token, void *map, size_t size)
|
||||
{
|
||||
#ifdef __WIN32__
|
||||
#ifdef _WIN32
|
||||
UnmapViewOfFile(map);
|
||||
CloseHandle((HANDLE)token);
|
||||
#else
|
||||
@ -207,7 +118,7 @@ write_file(const tchar *path, const void *contents, size_t size)
|
||||
ASSERT(ret > 0, "Error writing data to \"%"TS"\": %s",
|
||||
path, strerror(errno));
|
||||
size -= ret;
|
||||
contents += ret;
|
||||
contents = (const uint8_t *)contents + ret;
|
||||
}
|
||||
|
||||
ASSERT(!close(fd), "Error writing data to \"%"TS"\"",
|
||||
@ -253,7 +164,7 @@ decompress_file(struct deflate_decompressor *d, const tchar *path, bool force)
|
||||
|
||||
ASSERT(compressed_size >= sizeof(uint32_t),
|
||||
"File \"%"TS"\" is not a gzip file.", path);
|
||||
uncompressed_size = load_u32_gzip(compressed_data +
|
||||
uncompressed_size = load_u32_gzip((const uint8_t *)compressed_data +
|
||||
(compressed_size - sizeof(uint32_t)));
|
||||
uncompressed_data = malloc(uncompressed_size);
|
||||
ASSERT(uncompressed_data != NULL,
|
||||
|
23
tools/msc_test.bat
Executable file
23
tools/msc_test.bat
Executable file
@ -0,0 +1,23 @@
|
||||
call d:\VS2015\vc\vcvarsall
|
||||
nmake /f Makefile.msc clean
|
||||
nmake /f Makefile.msc
|
||||
cl /MD /O2 /Fe:benchmark.exe -I. -Itools -I..\zlib-msc tools\benchmark.c tools\wgetopt.c libdeflatestatic.lib ..\zlib-msc\zlib.lib
|
||||
cl /MD /O2 /Fe:gzip.exe -I. -Itools tools\gzip.c tools\wgetopt.c libdeflatestatic.lib
|
||||
del j:\exe\gzip.exe 2> nul
|
||||
del j:\exe\gunzip.exe 2> nul
|
||||
copy gzip.exe j:\exe\gzip.exe
|
||||
copy gzip.exe j:\exe\gunzip.exe
|
||||
del j:\exe\benchmark.exe 2> nul
|
||||
copy benchmark.exe j:\exe\benchmark.exe
|
||||
|
||||
call d:\VS2015\vc\vcvarsall x86_amd64
|
||||
nmake /f Makefile.msc clean
|
||||
nmake /f Makefile.msc
|
||||
cl /MD /O2 /Fe:benchmark.exe -I. -Itools -I..\zlib-msc64 tools\benchmark.c tools\wgetopt.c libdeflatestatic.lib ..\zlib-msc64\zlib.lib
|
||||
cl /MD /O2 /Fe:gzip.exe -I. -Itools tools\gzip.c tools\wgetopt.c libdeflatestatic.lib
|
||||
del j:\exe64\gzip.exe 2> nul
|
||||
del j:\exe64\gunzip.exe 2> nul
|
||||
copy gzip.exe j:\exe64\gzip.exe
|
||||
copy gzip.exe j:\exe64\gunzip.exe
|
||||
del j:\exe64\benchmark.exe 2> nul
|
||||
copy benchmark.exe j:\exe64\benchmark.exe
|
135
tools/util.h
Normal file
135
tools/util.h
Normal file
@ -0,0 +1,135 @@
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
#undef _ANSI_SOURCE
|
||||
#define _POSIX_C_SOURCE 199309L
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <wchar.h>
|
||||
# include <windows.h>
|
||||
# include "wgetopt.h"
|
||||
#else
|
||||
# include <sys/mman.h>
|
||||
# include <sys/time.h>
|
||||
# include <unistd.h>
|
||||
# include <getopt.h>
|
||||
#endif
|
||||
|
||||
#include <libdeflate.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
# define main wmain
|
||||
# define tchar wchar_t
|
||||
# define _T(text) L##text
|
||||
# define T(text) _T(text)
|
||||
# define TS "ls"
|
||||
# define tgetopt wgetopt
|
||||
# define toptarg woptarg
|
||||
# define toptind woptind
|
||||
# define tstrcmp wcscmp
|
||||
# define tstrlen wcslen
|
||||
# define tmemcpy wmemcpy
|
||||
# define tstrrchr wcsrchr
|
||||
# define tstrtol wcstol
|
||||
# define tstrtoul wcstoul
|
||||
# define topen _wopen
|
||||
# define tunlink _wunlink
|
||||
# ifdef _MSC_VER
|
||||
# define fstat _fstat64
|
||||
# define stat _stat64
|
||||
# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
|
||||
# endif
|
||||
# define tstat _wstati64
|
||||
#else
|
||||
# define main main
|
||||
# define tchar char
|
||||
# define T(text) text
|
||||
# define TS "s"
|
||||
# define tgetopt getopt
|
||||
# define toptarg optarg
|
||||
# define toptind optind
|
||||
# define tstrcmp strcmp
|
||||
# define tstrlen strlen
|
||||
# define tmemcpy memcpy
|
||||
# define tstrrchr strrchr
|
||||
# define tstrtol strtol
|
||||
# define tstrtoul strtoul
|
||||
# define topen open
|
||||
# define tunlink unlink
|
||||
# define tstat stat
|
||||
#endif
|
||||
|
||||
#ifndef O_BINARY
|
||||
# define O_BINARY 0
|
||||
#endif
|
||||
|
||||
#ifndef STDIN_FILENO
|
||||
# define STDIN_FILENO 0
|
||||
#endif
|
||||
|
||||
static void
|
||||
fatal_error(const char *fmt, ...)
|
||||
{
|
||||
va_list va;
|
||||
|
||||
va_start(va, fmt);
|
||||
fprintf(stderr, "ERROR: ");
|
||||
vfprintf(stderr, fmt, va);
|
||||
fprintf(stderr, "\n");
|
||||
va_end(va);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#define ASSERT(expr, fmt, ...) \
|
||||
{ \
|
||||
if (!(expr)) \
|
||||
fatal_error((fmt), ## __VA_ARGS__); \
|
||||
}
|
||||
|
||||
static inline const tchar *
|
||||
basename(const tchar *argv0)
|
||||
{
|
||||
const tchar *p = tstrrchr(argv0, '/');
|
||||
#ifdef _WIN32
|
||||
const tchar *p2 = tstrrchr(argv0, '\\');
|
||||
if (p2 && (!p || p2 > p))
|
||||
p = p2;
|
||||
#endif
|
||||
if (p)
|
||||
return p + 1;
|
||||
return argv0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
set_binary_mode(int fd)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
_setmode(fd, O_BINARY);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
current_time(void)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
FILETIME ft;
|
||||
GetSystemTimeAsFileTime(&ft);
|
||||
return 100 * (((uint64_t)ft.dwHighDateTime << 32) | ft.dwLowDateTime);
|
||||
#else
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
return ((uint64_t)1000000000 * ts.tv_sec) + ts.tv_nsec;
|
||||
#endif
|
||||
}
|
62
tools/wgetopt.c
Normal file
62
tools/wgetopt.c
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* wide-character getopt for Windows
|
||||
*
|
||||
* Public domain
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "wgetopt.h"
|
||||
|
||||
wchar_t *woptarg; /* Global argument pointer */
|
||||
int woptind = 0; /* Global argv index */
|
||||
|
||||
static wchar_t *scan = NULL; /* Private scan pointer */
|
||||
|
||||
int wgetopt(int argc, wchar_t * const argv[], const wchar_t *optstring)
|
||||
{
|
||||
wchar_t c;
|
||||
wchar_t *place;
|
||||
|
||||
woptarg = NULL;
|
||||
|
||||
if (!scan || *scan == '\0') {
|
||||
if (woptind == 0)
|
||||
woptind++;
|
||||
if (woptind >= argc || argv[woptind][0] != '-'
|
||||
|| argv[woptind][1] == '\0')
|
||||
return EOF;
|
||||
if (argv[woptind][1] == '-' && argv[woptind][2] == '\0') {
|
||||
woptind++;
|
||||
return EOF;
|
||||
}
|
||||
scan = argv[woptind] + 1;
|
||||
woptind++;
|
||||
}
|
||||
|
||||
c = *scan++;
|
||||
place = wcschr(optstring, c);
|
||||
|
||||
if (!place || c == ':') {
|
||||
fprintf(stderr, "%ls: unknown option -%lc\n", argv[0], c);
|
||||
return '?';
|
||||
}
|
||||
|
||||
place++;
|
||||
if (*place == ':') {
|
||||
if (*scan != '\0') {
|
||||
woptarg = scan;
|
||||
scan = NULL;
|
||||
} else if (woptind < argc) {
|
||||
woptarg = argv[woptind];
|
||||
woptind++;
|
||||
} else {
|
||||
fprintf(stderr, "%ls: option requires argument -%lc\n",
|
||||
argv[0], c);
|
||||
return ':';
|
||||
}
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
4
tools/wgetopt.h
Normal file
4
tools/wgetopt.h
Normal file
@ -0,0 +1,4 @@
|
||||
extern wchar_t *woptarg;
|
||||
extern int woptind;
|
||||
|
||||
int wgetopt(int argc, wchar_t * const argv[], const wchar_t *optstring);
|
@ -4,10 +4,10 @@ set -e
|
||||
|
||||
make clean
|
||||
make -j4 CC=i686-w64-mingw32-gcc BUILD_PROGRAMS=yes
|
||||
cp *.exe /j/exe
|
||||
cp -vf *.exe /j/exe/
|
||||
|
||||
make clean
|
||||
make -j4 CC=x86_64-w64-mingw32-gcc BUILD_PROGRAMS=yes
|
||||
cp *.exe /j/exe64
|
||||
cp -vf *.exe /j/exe64/
|
||||
|
||||
sudo systemctl restart smbd
|
||||
|
Loading…
x
Reference in New Issue
Block a user