mirror of
https://github.com/cuberite/libdeflate.git
synced 2025-09-10 21:08:19 -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))
|
AR := $(patsubst %-gcc,%-ar,$(CC))
|
||||||
endif
|
endif
|
||||||
WINDOWS := yes
|
WINDOWS := yes
|
||||||
LIB_SUFFIX := .a
|
LIB_SUFFIX := .lib
|
||||||
SHLIB_SUFFIX := .dll
|
SHLIB_SUFFIX := .dll
|
||||||
PROG_SUFFIX := .exe
|
PROG_SUFFIX := .exe
|
||||||
PROG_CFLAGS := -static
|
PROG_SRC := tools/wgetopt.c
|
||||||
GZIP_CFLAGS := -municode
|
PROG_CFLAGS := -static -municode
|
||||||
SHLIB_IS_PIC := no
|
SHLIB_IS_PIC := no
|
||||||
else
|
else
|
||||||
WINDOWS := no
|
WINDOWS := no
|
||||||
LIB_SUFFIX := .a
|
LIB_SUFFIX := .a
|
||||||
SHLIB_SUFFIX := .so
|
SHLIB_SUFFIX := .so
|
||||||
PROG_SUFFIX :=
|
PROG_SUFFIX :=
|
||||||
|
PROG_SRC :=
|
||||||
PROG_CFLAGS :=
|
PROG_CFLAGS :=
|
||||||
GZIP_CFLAGS :=
|
|
||||||
SHLIB_IS_PIC := yes
|
SHLIB_IS_PIC := yes
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -102,6 +102,9 @@ ifneq ($(RUNTIME_CPU_DETECTION),yes)
|
|||||||
override CFLAGS += -DRUNTIME_CPU_DETECTION=0
|
override CFLAGS += -DRUNTIME_CPU_DETECTION=0
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
PROG_CFLAGS += $(CFLAGS)
|
||||||
|
PROG_SRC += libdeflate$(LIB_SUFFIX)
|
||||||
|
|
||||||
SRC := src/aligned_malloc.c
|
SRC := src/aligned_malloc.c
|
||||||
ifeq ($(SUPPORT_COMPRESSION),yes)
|
ifeq ($(SUPPORT_COMPRESSION),yes)
|
||||||
SRC += src/deflate_compress.c
|
SRC += src/deflate_compress.c
|
||||||
@ -151,15 +154,15 @@ libdeflate$(SHLIB_SUFFIX):$(SHLIB_OBJ)
|
|||||||
libdeflate$(LIB_SUFFIX):$(OBJ)
|
libdeflate$(LIB_SUFFIX):$(OBJ)
|
||||||
$(AR) cr $@ $+
|
$(AR) cr $@ $+
|
||||||
|
|
||||||
benchmark$(PROG_SUFFIX):tools/benchmark.c libdeflate$(LIB_SUFFIX)
|
benchmark$(PROG_SUFFIX):tools/benchmark.c $(PROG_SRC)
|
||||||
$(CC) -o $@ $(CFLAGS) -L. $+ libdeflate$(LIB_SUFFIX) -lz
|
$(CC) -o $@ $(PROG_CFLAGS) $+ -lz
|
||||||
|
|
||||||
gzip$(PROG_SUFFIX):tools/gzip.c libdeflate$(LIB_SUFFIX)
|
gzip$(PROG_SUFFIX):tools/gzip.c $(PROG_SRC)
|
||||||
$(CC) -o $@ $(CFLAGS) $(GZIP_CFLAGS) $(PROG_CFLAGS) -L. $+ libdeflate$(LIB_SUFFIX)
|
$(CC) -o $@ $(PROG_CFLAGS) $+
|
||||||
|
|
||||||
ifeq ($(WINDOWS),yes)
|
ifeq ($(WINDOWS),yes)
|
||||||
gunzip$(PROG_SUFFIX):tools/gzip.c libdeflate$(LIB_SUFFIX)
|
gunzip$(PROG_SUFFIX):tools/gzip.c $(PROG_SRC)
|
||||||
$(CC) -o $@ $(CFLAGS) $(GZIP_CFLAGS) $(PROG_CFLAGS) -L. $+ libdeflate$(LIB_SUFFIX)
|
$(CC) -o $@ $(PROG_CFLAGS) $+
|
||||||
else
|
else
|
||||||
gunzip$(PROG_SUFFIX):gzip$(PROG_SUFFIX)
|
gunzip$(PROG_SUFFIX):gzip$(PROG_SUFFIX)
|
||||||
ln -f gzip$(PROG_SUFFIX) $@
|
ln -f gzip$(PROG_SUFFIX) $@
|
||||||
@ -187,10 +190,8 @@ endif
|
|||||||
all:$(TARGETS)
|
all:$(TARGETS)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f libdeflate.a libdeflate.so libdeflate.dll src/*.o \
|
rm -f libdeflate.a libdeflate.so libdeflate.dll src/*.o src/*.obj \
|
||||||
benchmark benchmark.exe \
|
benchmark gzip gunzip *.exe *.lib *.obj *.exp
|
||||||
gzip gzip.exe \
|
|
||||||
gunzip gunzip.exe
|
|
||||||
|
|
||||||
.PHONY: all clean
|
.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
|
Building
|
||||||
========
|
========
|
||||||
|
|
||||||
Currently, the build system is very bare-bones. On a UNIX-like system, just run
|
On a UNIX-like system, just run `make`. You need GNU Make and either GCC or
|
||||||
`make`. You need GNU Make and either GCC or Clang.
|
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
|
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`
|
Makefile for details. As an example, you can run `make SUPPORT_COMPRESSION=no`
|
||||||
to build a decompression-only library.
|
to build a decompression-only library.
|
||||||
|
|
||||||
There is no `make install` yet; just copy the file(s) to where you want.
|
On Windows, a separate Makefile, `Makefile.msc`, is provided for the tools that
|
||||||
|
come with Visual Studio. However, using MinGW (GCC) instead is recommended
|
||||||
It's possible to build Windows binaries using MinGW with a command like this:
|
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 BUILD_PROGRAMS=yes
|
|
||||||
|
|
||||||
|
$ make CC=x86_64-w64-mingw32-gcc
|
||||||
|
|
||||||
API
|
API
|
||||||
===
|
===
|
||||||
|
39
libdeflate.h
39
libdeflate.h
@ -11,6 +11,19 @@ extern "C" {
|
|||||||
|
|
||||||
#include <stddef.h>
|
#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 */
|
/* Compression */
|
||||||
/* ========================================================================== */
|
/* ========================================================================== */
|
||||||
@ -28,7 +41,7 @@ struct deflate_compressor;
|
|||||||
* to 32768, the largest size permissible in the DEFLATE format. It cannot be
|
* to 32768, the largest size permissible in the DEFLATE format. It cannot be
|
||||||
* changed at runtime.
|
* changed at runtime.
|
||||||
*/
|
*/
|
||||||
extern struct deflate_compressor *
|
LIBDEFLATEAPI struct deflate_compressor *
|
||||||
deflate_alloc_compressor(unsigned int compression_level);
|
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
|
* 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.
|
* be compressed to 'out_nbytes_avail' bytes or fewer.
|
||||||
*/
|
*/
|
||||||
extern size_t
|
LIBDEFLATEAPI size_t
|
||||||
deflate_compress(struct deflate_compressor *compressor,
|
deflate_compress(struct deflate_compressor *compressor,
|
||||||
const void *in, size_t in_nbytes,
|
const void *in, size_t in_nbytes,
|
||||||
void *out, size_t out_nbytes_avail);
|
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
|
* and store the data uncompressed if deflate_compress() returns 0, indicating
|
||||||
* that the compressed data did not fit into the provided output buffer.
|
* 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);
|
deflate_compress_bound(struct deflate_compressor *compressor, size_t in_nbytes);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Like deflate_compress(), but stores the data in the zlib wrapper format.
|
* Like deflate_compress(), but stores the data in the zlib wrapper format.
|
||||||
*/
|
*/
|
||||||
extern size_t
|
LIBDEFLATEAPI size_t
|
||||||
zlib_compress(struct deflate_compressor *compressor,
|
zlib_compress(struct deflate_compressor *compressor,
|
||||||
const void *in, size_t in_nbytes,
|
const void *in, size_t in_nbytes,
|
||||||
void *out, size_t out_nbytes_avail);
|
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
|
* Like deflate_compress_bound(), but assumes the data will be compressed with
|
||||||
* zlib_compress() rather than with deflate_compress().
|
* zlib_compress() rather than with deflate_compress().
|
||||||
*/
|
*/
|
||||||
extern size_t
|
LIBDEFLATEAPI size_t
|
||||||
zlib_compress_bound(struct deflate_compressor *compressor, size_t in_nbytes);
|
zlib_compress_bound(struct deflate_compressor *compressor, size_t in_nbytes);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Like deflate_compress(), but stores the data in the gzip wrapper format.
|
* Like deflate_compress(), but stores the data in the gzip wrapper format.
|
||||||
*/
|
*/
|
||||||
extern size_t
|
LIBDEFLATEAPI size_t
|
||||||
gzip_compress(struct deflate_compressor *compressor,
|
gzip_compress(struct deflate_compressor *compressor,
|
||||||
const void *in, size_t in_nbytes,
|
const void *in, size_t in_nbytes,
|
||||||
void *out, size_t out_nbytes_avail);
|
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
|
* Like deflate_compress_bound(), but assumes the data will be compressed with
|
||||||
* gzip_compress() rather than with deflate_compress().
|
* gzip_compress() rather than with deflate_compress().
|
||||||
*/
|
*/
|
||||||
extern size_t
|
LIBDEFLATEAPI size_t
|
||||||
gzip_compress_bound(struct deflate_compressor *compressor, size_t in_nbytes);
|
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
|
* deflate_alloc_compressor(). If a NULL pointer is passed in, no action is
|
||||||
* taken.
|
* taken.
|
||||||
*/
|
*/
|
||||||
extern void
|
LIBDEFLATEAPI void
|
||||||
deflate_free_compressor(struct deflate_compressor *compressor);
|
deflate_free_compressor(struct deflate_compressor *compressor);
|
||||||
|
|
||||||
/* ========================================================================== */
|
/* ========================================================================== */
|
||||||
@ -120,7 +133,7 @@ struct deflate_decompressor;
|
|||||||
* DEFLATE, zlib, or gzip); however, the appropriate decompression function must
|
* DEFLATE, zlib, or gzip); however, the appropriate decompression function must
|
||||||
* be called.
|
* be called.
|
||||||
*/
|
*/
|
||||||
extern struct deflate_decompressor *
|
LIBDEFLATEAPI struct deflate_decompressor *
|
||||||
deflate_alloc_decompressor(void);
|
deflate_alloc_decompressor(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -172,7 +185,7 @@ enum decompress_result {
|
|||||||
* but no other problems were encountered, or another nonzero result code if
|
* but no other problems were encountered, or another nonzero result code if
|
||||||
* decompression failed for another reason.
|
* decompression failed for another reason.
|
||||||
*/
|
*/
|
||||||
extern enum decompress_result
|
LIBDEFLATEAPI enum decompress_result
|
||||||
deflate_decompress(struct deflate_decompressor *decompressor,
|
deflate_decompress(struct deflate_decompressor *decompressor,
|
||||||
const void *in, size_t in_nbytes,
|
const void *in, size_t in_nbytes,
|
||||||
void *out, size_t out_nbytes_avail,
|
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
|
* Like deflate_decompress(), but assumes the zlib wrapper format instead of raw
|
||||||
* DEFLATE.
|
* DEFLATE.
|
||||||
*/
|
*/
|
||||||
extern enum decompress_result
|
LIBDEFLATEAPI enum decompress_result
|
||||||
zlib_decompress(struct deflate_decompressor *decompressor,
|
zlib_decompress(struct deflate_decompressor *decompressor,
|
||||||
const void *in, size_t in_nbytes,
|
const void *in, size_t in_nbytes,
|
||||||
void *out, size_t out_nbytes_avail,
|
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
|
* Like deflate_decompress(), but assumes the gzip wrapper format instead of raw
|
||||||
* DEFLATE.
|
* DEFLATE.
|
||||||
*/
|
*/
|
||||||
extern enum decompress_result
|
LIBDEFLATEAPI enum decompress_result
|
||||||
gzip_decompress(struct deflate_decompressor *decompressor,
|
gzip_decompress(struct deflate_decompressor *decompressor,
|
||||||
const void *in, size_t in_nbytes,
|
const void *in, size_t in_nbytes,
|
||||||
void *out, size_t out_nbytes_avail,
|
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
|
* with deflate_alloc_decompressor(). If a NULL pointer is passed in, no action
|
||||||
* is taken.
|
* is taken.
|
||||||
*/
|
*/
|
||||||
extern void
|
LIBDEFLATEAPI void
|
||||||
deflate_free_decompressor(struct deflate_decompressor *decompressor);
|
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 max_len,
|
||||||
const u32 nice_len,
|
const u32 nice_len,
|
||||||
const u32 max_search_depth,
|
const u32 max_search_depth,
|
||||||
u32 next_hashes[const restrict static 2],
|
u32 next_hashes[restrict 2],
|
||||||
u32 * const restrict best_len_ret,
|
u32 * const restrict best_len_ret,
|
||||||
struct lz_match * restrict lz_matchptr,
|
struct lz_match * restrict lz_matchptr,
|
||||||
const bool record_matches)
|
const bool record_matches)
|
||||||
@ -294,7 +294,7 @@ bt_matchfinder_get_matches(struct bt_matchfinder *mf,
|
|||||||
u32 max_len,
|
u32 max_len,
|
||||||
u32 nice_len,
|
u32 nice_len,
|
||||||
u32 max_search_depth,
|
u32 max_search_depth,
|
||||||
u32 next_hashes[static 2],
|
u32 next_hashes[2],
|
||||||
u32 *best_len_ret,
|
u32 *best_len_ret,
|
||||||
struct lz_match *lz_matchptr)
|
struct lz_match *lz_matchptr)
|
||||||
{
|
{
|
||||||
@ -323,7 +323,7 @@ bt_matchfinder_skip_position(struct bt_matchfinder *mf,
|
|||||||
u32 max_len,
|
u32 max_len,
|
||||||
u32 nice_len,
|
u32 nice_len,
|
||||||
u32 max_search_depth,
|
u32 max_search_depth,
|
||||||
u32 next_hashes[static 2])
|
u32 next_hashes[2])
|
||||||
{
|
{
|
||||||
u32 best_len;
|
u32 best_len;
|
||||||
bt_matchfinder_advance_one_byte(mf,
|
bt_matchfinder_advance_one_byte(mf,
|
||||||
|
@ -2,9 +2,7 @@
|
|||||||
* compiler-gcc.h - definitions for the GNU C compiler (and for clang)
|
* compiler-gcc.h - definitions for the GNU C compiler (and for clang)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#ifdef _WIN32
|
||||||
|
|
||||||
#ifdef __WIN32__
|
|
||||||
# define LIBEXPORT __declspec(dllexport)
|
# define LIBEXPORT __declspec(dllexport)
|
||||||
#else
|
#else
|
||||||
# define LIBEXPORT __attribute__((visibility("default")))
|
# 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. */
|
* define as many of them as possible. */
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
# include "compiler-gcc.h"
|
# include "compiler-gcc.h"
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
# include "compiler-msc.h"
|
||||||
#else
|
#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
|
#endif
|
||||||
|
|
||||||
/* forceinline - force a function to be inlined */
|
/* forceinline - force a function to be inlined */
|
||||||
|
@ -26,6 +26,8 @@ FUNCNAME(struct deflate_decompressor * restrict d,
|
|||||||
u16 nlen;
|
u16 nlen;
|
||||||
unsigned num_litlen_syms;
|
unsigned num_litlen_syms;
|
||||||
unsigned num_offset_syms;
|
unsigned num_offset_syms;
|
||||||
|
u16 tmp16;
|
||||||
|
u32 tmp32;
|
||||||
|
|
||||||
next_block:
|
next_block:
|
||||||
/* Starting to read the next block. */
|
/* Starting to read the next block. */
|
||||||
|
@ -11,13 +11,13 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "libdeflate.h"
|
|
||||||
|
|
||||||
#include "aligned_malloc.h"
|
#include "aligned_malloc.h"
|
||||||
#include "deflate_compress.h"
|
#include "deflate_compress.h"
|
||||||
#include "deflate_constants.h"
|
#include "deflate_constants.h"
|
||||||
#include "unaligned.h"
|
#include "unaligned.h"
|
||||||
|
|
||||||
|
#include "libdeflate.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note: when compiling this file, SUPPORT_NEAR_OPTIMAL_PARSING should be
|
* 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
|
* 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;
|
struct deflate_sequence *next_seq = c->sequences;
|
||||||
u32 litrunlen = 0;
|
u32 litrunlen = 0;
|
||||||
u32 items_remaining = MAX_ITEMS_PER_BLOCK;
|
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_init_output(&os, out, out_nbytes_avail);
|
||||||
deflate_reset_symbol_frequencies(c);
|
deflate_reset_symbol_frequencies(c);
|
||||||
@ -1662,7 +1662,7 @@ deflate_compress_lazy(struct deflate_compressor * restrict c,
|
|||||||
struct deflate_sequence *next_seq = c->sequences;
|
struct deflate_sequence *next_seq = c->sequences;
|
||||||
u32 litrunlen = 0;
|
u32 litrunlen = 0;
|
||||||
u32 items_remaining = MAX_ITEMS_PER_BLOCK;
|
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_init_output(&os, out, out_nbytes_avail);
|
||||||
deflate_reset_symbol_frequencies(c);
|
deflate_reset_symbol_frequencies(c);
|
||||||
@ -2171,7 +2171,7 @@ deflate_compress_near_optimal(struct deflate_compressor * restrict c,
|
|||||||
struct lz_match *cache_end;
|
struct lz_match *cache_end;
|
||||||
const u8 *in_block_begin;
|
const u8 *in_block_begin;
|
||||||
const u8 *in_block_end;
|
const u8 *in_block_end;
|
||||||
u32 next_hashes[2] = {};
|
u32 next_hashes[2] = {0, 0};
|
||||||
|
|
||||||
deflate_init_output(&os, out, out_nbytes_avail);
|
deflate_init_output(&os, out, out_nbytes_avail);
|
||||||
deflate_reset_symbol_frequencies(c);
|
deflate_reset_symbol_frequencies(c);
|
||||||
|
@ -9,10 +9,10 @@
|
|||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* This is a highly optimized DEFLATE decompressor. On x86_64 it decompresses
|
* This is a highly optimized DEFLATE decompressor. When compiled with gcc on
|
||||||
* data in about 52% of the time of zlib (48% if BMI2 instructions are
|
* x86_64, it decompresses data in about 52% of the time of zlib (48% if BMI2
|
||||||
* available). On other architectures it should still be significantly faster
|
* instructions are available). On other architectures it should still be
|
||||||
* than zlib, but the difference may be smaller.
|
* significantly faster than zlib, but the difference may be smaller.
|
||||||
*
|
*
|
||||||
* Why this is faster than zlib's implementation:
|
* Why this is faster than zlib's implementation:
|
||||||
*
|
*
|
||||||
@ -30,19 +30,19 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "libdeflate.h"
|
|
||||||
|
|
||||||
#include "deflate_constants.h"
|
#include "deflate_constants.h"
|
||||||
#include "unaligned.h"
|
#include "unaligned.h"
|
||||||
#include "x86_cpu_features.h"
|
#include "x86_cpu_features.h"
|
||||||
|
|
||||||
|
#include "libdeflate.h"
|
||||||
|
|
||||||
/* By default, if the expression passed to SAFETY_CHECK() evaluates to false,
|
/* By default, if the expression passed to SAFETY_CHECK() evaluates to false,
|
||||||
* then deflate_decompress() immediately returns DECOMPRESS_BAD_DATA as the
|
* then deflate_decompress() immediately returns DECOMPRESS_BAD_DATA as the
|
||||||
* compressed data is invalid. But if unsafe decompression is enabled, then 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
|
* value of the expression is ignored, allowing the compiler to optimize out
|
||||||
* some code. */
|
* some code. */
|
||||||
#if UNSAFE_DECOMPRESSION
|
#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)
|
# define SAFETY_CHECK(expr) (void)(expr)
|
||||||
#else
|
#else
|
||||||
# define SAFETY_CHECK(expr) if (unlikely(!(expr))) return DECOMPRESS_BAD_DATA
|
# define SAFETY_CHECK(expr) if (unlikely(!(expr))) return DECOMPRESS_BAD_DATA
|
||||||
@ -195,15 +195,13 @@ typedef machine_word_t bitbuf_t;
|
|||||||
* checksum against the uncompressed data if they wish to detect corruptions.
|
* checksum against the uncompressed data if they wish to detect corruptions.
|
||||||
*/
|
*/
|
||||||
#define FILL_BITS_BYTEWISE() \
|
#define FILL_BITS_BYTEWISE() \
|
||||||
({ \
|
|
||||||
do { \
|
do { \
|
||||||
if (likely(in_next != in_end)) \
|
if (likely(in_next != in_end)) \
|
||||||
bitbuf |= (bitbuf_t)*in_next++ << bitsleft; \
|
bitbuf |= (bitbuf_t)*in_next++ << bitsleft; \
|
||||||
else \
|
else \
|
||||||
overrun_count++; \
|
overrun_count++; \
|
||||||
bitsleft += 8; \
|
bitsleft += 8; \
|
||||||
} while (bitsleft <= BITBUF_NBITS - 8); \
|
} while (bitsleft <= BITBUF_NBITS - 8)
|
||||||
})
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fill the bitbuffer variable by reading the next word from the input buffer.
|
* Fill the bitbuffer variable by reading the next word from the input buffer.
|
||||||
@ -214,11 +212,11 @@ typedef machine_word_t bitbuf_t;
|
|||||||
* access, such as x86 and x86_64.
|
* access, such as x86 and x86_64.
|
||||||
*/
|
*/
|
||||||
#define FILL_BITS_WORDWISE() \
|
#define FILL_BITS_WORDWISE() \
|
||||||
({ \
|
do { \
|
||||||
bitbuf |= get_unaligned_leword(in_next) << bitsleft; \
|
bitbuf |= get_unaligned_leword(in_next) << bitsleft; \
|
||||||
in_next += (BITBUF_NBITS - bitsleft) >> 3; \
|
in_next += (BITBUF_NBITS - bitsleft) >> 3; \
|
||||||
bitsleft += (BITBUF_NBITS - bitsleft) & ~7; \
|
bitsleft += (BITBUF_NBITS - bitsleft) & ~7; \
|
||||||
})
|
} while (0)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Does the bitbuffer variable currently contain at least 'n' bits?
|
* 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))
|
#define HAVE_BITS(n) (bitsleft >= (n))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Raw form of ENSURE_BITS(): the bitbuffer variable must not already contain
|
* Load more bits from the input buffer until the specified number of bits is
|
||||||
* the requested number of bits.
|
* 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() && \
|
if (CPU_IS_LITTLE_ENDIAN() && \
|
||||||
UNALIGNED_ACCESS_IS_FAST && \
|
UNALIGNED_ACCESS_IS_FAST && \
|
||||||
likely(in_end - in_next >= sizeof(bitbuf_t))) \
|
likely(in_end - in_next >= sizeof(bitbuf_t))) \
|
||||||
FILL_BITS_WORDWISE(); \
|
FILL_BITS_WORDWISE(); \
|
||||||
else \
|
else \
|
||||||
FILL_BITS_BYTEWISE(); \
|
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.
|
* Return the next 'n' bits from the bitbuffer variable without removing them.
|
||||||
*/
|
*/
|
||||||
#define BITS(n) \
|
#define BITS(n) ((u32)bitbuf & (((u32)1 << (n)) - 1))
|
||||||
({ \
|
|
||||||
(u32)bitbuf & (((u32)1 << (n)) - 1); \
|
|
||||||
})
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remove the next 'n' bits from the bitbuffer variable.
|
* Remove the next 'n' bits from the bitbuffer variable.
|
||||||
*/
|
*/
|
||||||
#define REMOVE_BITS(n) \
|
#define REMOVE_BITS(n) (bitbuf >>= (n), bitsleft -= (n))
|
||||||
({ \
|
|
||||||
bitbuf >>= (n); \
|
|
||||||
bitsleft -= (n); \
|
|
||||||
})
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remove and return the next 'n' bits from the bitbuffer variable.
|
* Remove and return the next 'n' bits from the bitbuffer variable.
|
||||||
*/
|
*/
|
||||||
#define POP_BITS(n) \
|
#define POP_BITS(n) (tmp32 = BITS(n), REMOVE_BITS(n), tmp32)
|
||||||
({ \
|
|
||||||
u32 bits = BITS(n); \
|
|
||||||
REMOVE_BITS(n); \
|
|
||||||
bits; \
|
|
||||||
})
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Align the input to the next byte boundary, discarding any remaining bits in
|
* 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.
|
* be actually discarded.
|
||||||
*/
|
*/
|
||||||
#define ALIGN_INPUT() \
|
#define ALIGN_INPUT() \
|
||||||
({ \
|
do { \
|
||||||
in_next -= (bitsleft >> 3) - MIN(overrun_count, bitsleft >> 3); \
|
in_next -= (bitsleft >> 3) - MIN(overrun_count, bitsleft >> 3); \
|
||||||
bitbuf = 0; \
|
bitbuf = 0; \
|
||||||
bitsleft = 0; \
|
bitsleft = 0; \
|
||||||
})
|
} while(0)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read a 16-bit value from the input. This must have been preceded by a call
|
* 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.
|
* to ALIGN_INPUT(), and the caller must have already checked for overrun.
|
||||||
*/
|
*/
|
||||||
#define READ_U16() \
|
#define READ_U16() (tmp16 = get_unaligned_le16(in_next), in_next += 2, tmp16)
|
||||||
({ \
|
|
||||||
u16 v; \
|
|
||||||
\
|
|
||||||
v = get_unaligned_le16(in_next); \
|
|
||||||
in_next += 2; \
|
|
||||||
v; \
|
|
||||||
})
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* Huffman decoding *
|
* Huffman decoding *
|
||||||
|
@ -8,13 +8,13 @@
|
|||||||
* You can do whatever you want with this file.
|
* You can do whatever you want with this file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "libdeflate.h"
|
|
||||||
|
|
||||||
#include "crc32.h"
|
#include "crc32.h"
|
||||||
#include "deflate_compress.h"
|
#include "deflate_compress.h"
|
||||||
#include "gzip_constants.h"
|
#include "gzip_constants.h"
|
||||||
#include "unaligned.h"
|
#include "unaligned.h"
|
||||||
|
|
||||||
|
#include "libdeflate.h"
|
||||||
|
|
||||||
LIBEXPORT size_t
|
LIBEXPORT size_t
|
||||||
gzip_compress(struct deflate_compressor *c, const void *in, size_t in_size,
|
gzip_compress(struct deflate_compressor *c, const void *in, size_t in_size,
|
||||||
void *out, size_t out_nbytes_avail)
|
void *out, size_t out_nbytes_avail)
|
||||||
|
@ -8,12 +8,12 @@
|
|||||||
* You can do whatever you want with this file.
|
* You can do whatever you want with this file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "libdeflate.h"
|
|
||||||
|
|
||||||
#include "crc32.h"
|
#include "crc32.h"
|
||||||
#include "gzip_constants.h"
|
#include "gzip_constants.h"
|
||||||
#include "unaligned.h"
|
#include "unaligned.h"
|
||||||
|
|
||||||
|
#include "libdeflate.h"
|
||||||
|
|
||||||
LIBEXPORT enum decompress_result
|
LIBEXPORT enum decompress_result
|
||||||
gzip_decompress(struct deflate_decompressor *d,
|
gzip_decompress(struct deflate_decompressor *d,
|
||||||
const void *in, size_t in_nbytes,
|
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 max_len,
|
||||||
const u32 nice_len,
|
const u32 nice_len,
|
||||||
const u32 max_search_depth,
|
const u32 max_search_depth,
|
||||||
u32 next_hashes[const restrict static 2],
|
u32 next_hashes[restrict 2],
|
||||||
u32 * const restrict offset_ret)
|
u32 * const restrict offset_ret)
|
||||||
{
|
{
|
||||||
const u8 *in_next = in_base + cur_pos;
|
const u8 *in_next = in_base + cur_pos;
|
||||||
u32 depth_remaining = max_search_depth;
|
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;
|
const mf_pos_t cutoff = cur_pos - MATCHFINDER_WINDOW_SIZE;
|
||||||
mf_pos_t cur_node3, cur_node4;
|
mf_pos_t cur_node3, cur_node4;
|
||||||
u32 hash3, hash4;
|
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 cur_pos,
|
||||||
const ptrdiff_t end_pos,
|
const ptrdiff_t end_pos,
|
||||||
const u32 count,
|
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 *in_next = in_base + cur_pos;
|
||||||
const u8 * const stop_ptr = in_next + count;
|
const u8 * const stop_ptr = in_next + count;
|
||||||
|
@ -8,13 +8,13 @@
|
|||||||
* You can do whatever you want with this file.
|
* You can do whatever you want with this file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "libdeflate.h"
|
|
||||||
|
|
||||||
#include "adler32.h"
|
#include "adler32.h"
|
||||||
#include "deflate_compress.h"
|
#include "deflate_compress.h"
|
||||||
#include "unaligned.h"
|
#include "unaligned.h"
|
||||||
#include "zlib_constants.h"
|
#include "zlib_constants.h"
|
||||||
|
|
||||||
|
#include "libdeflate.h"
|
||||||
|
|
||||||
LIBEXPORT size_t
|
LIBEXPORT size_t
|
||||||
zlib_compress(struct deflate_compressor *c, const void *in, size_t in_size,
|
zlib_compress(struct deflate_compressor *c, const void *in, size_t in_size,
|
||||||
void *out, size_t out_nbytes_avail)
|
void *out, size_t out_nbytes_avail)
|
||||||
|
@ -8,12 +8,12 @@
|
|||||||
* You can do whatever you want with this file.
|
* You can do whatever you want with this file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "libdeflate.h"
|
|
||||||
|
|
||||||
#include "adler32.h"
|
#include "adler32.h"
|
||||||
#include "unaligned.h"
|
#include "unaligned.h"
|
||||||
#include "zlib_constants.h"
|
#include "zlib_constants.h"
|
||||||
|
|
||||||
|
#include "libdeflate.h"
|
||||||
|
|
||||||
LIBEXPORT enum decompress_result
|
LIBEXPORT enum decompress_result
|
||||||
zlib_decompress(struct deflate_decompressor *d,
|
zlib_decompress(struct deflate_decompressor *d,
|
||||||
const void *in, size_t in_nbytes,
|
const void *in, size_t in_nbytes,
|
||||||
|
@ -8,70 +8,37 @@
|
|||||||
* You can do whatever you want with this file.
|
* 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 "util.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 <libdeflate.h>
|
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
|
||||||
|
static const tchar *const optstring = T("s:l:123456789zgYZh");
|
||||||
|
|
||||||
static void
|
static void
|
||||||
usage(FILE *fp)
|
usage(FILE *fp)
|
||||||
{
|
{
|
||||||
static const char * const str =
|
static const char * const str =
|
||||||
"Usage: benchmark [FILE...]\n"
|
"Usage: benchmark [OPTION]... [FILE]...\n"
|
||||||
"\n"
|
"\n"
|
||||||
"A compression and decompression benchmark and testing program.\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"
|
"Benchmarks are run on each FILE specified, or stdin if no file is specified.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Options:\n"
|
"Options:\n"
|
||||||
" -s, --chunk-size=SIZE chunk size\n"
|
" -s SIZE chunk size\n"
|
||||||
" -l, --level=LEVEL compression level [1-12]\n"
|
" -l LEVEL compression level [1-12]\n"
|
||||||
" -1 fastest\n"
|
" -1 fastest\n"
|
||||||
" -9 slow\n"
|
" -9 slow\n"
|
||||||
" -z, --zlib use zlib wrapper\n"
|
" -z use zlib wrapper\n"
|
||||||
" -g, --gzip use gzip wrapper\n"
|
" -g use gzip wrapper\n"
|
||||||
" -Y, --compress-with-libz compress with libz, not libdeflate\n"
|
" -Y compress with libz, not libdeflate\n"
|
||||||
" -Z, --decompress-with-libz decompress with libz, not libdeflate\n"
|
" -Z decompress with libz, not libdeflate\n"
|
||||||
" -h, --help print this help\n"
|
" -h print this help\n"
|
||||||
;
|
;
|
||||||
|
|
||||||
fputs(str, fp);
|
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 {
|
enum wrapper {
|
||||||
NO_WRAPPER,
|
NO_WRAPPER,
|
||||||
ZLIB_WRAPPER,
|
ZLIB_WRAPPER,
|
||||||
@ -293,15 +260,6 @@ decompressor_destroy(struct decompressor *d)
|
|||||||
(*d->free_private)(d->private);
|
(*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
|
static void
|
||||||
do_benchmark(int fd, char *ubuf1, char *ubuf2,
|
do_benchmark(int fd, char *ubuf1, char *ubuf2,
|
||||||
char *cbuf, uint32_t max_chunk_size,
|
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 compress_time_total = 0;
|
||||||
uint64_t decompress_time_total = 0;
|
uint64_t decompress_time_total = 0;
|
||||||
|
|
||||||
#ifdef __WIN32__
|
|
||||||
_setmode(fd, O_BINARY);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
char *p = ubuf1;
|
char *p = ubuf1;
|
||||||
ssize_t bytes_read;
|
int32_t bytes_read;
|
||||||
size_t usize;
|
size_t usize;
|
||||||
size_t csize;
|
size_t csize;
|
||||||
uint64_t start_time;
|
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 * 100 / usize_total),
|
||||||
(unsigned int)(csize_total * 100000 / usize_total % 1000));
|
(unsigned int)(csize_total * 100000 / usize_total % 1000));
|
||||||
printf("\tCompression time: %"PRIu64" ms (%"PRIu64" MB/s)\n",
|
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);
|
1000 * usize_total / compress_time_total);
|
||||||
printf("\tDecompression time: %"PRIu64" ms (%"PRIu64" MB/s)\n",
|
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);
|
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
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, tchar *argv[])
|
||||||
{
|
{
|
||||||
uint32_t chunk_size = 32768;
|
uint32_t chunk_size = 32768;
|
||||||
int level = 6;
|
int level = 6;
|
||||||
@ -415,17 +357,23 @@ main(int argc, char **argv)
|
|||||||
struct decompressor d;
|
struct decompressor d;
|
||||||
int opt_char;
|
int opt_char;
|
||||||
|
|
||||||
while ((opt_char =
|
while ((opt_char = tgetopt(argc, argv, optstring)) != -1) {
|
||||||
getopt_long(argc, argv, optstring, longopts, NULL)) != -1)
|
|
||||||
{
|
|
||||||
switch (opt_char) {
|
switch (opt_char) {
|
||||||
case 's':
|
case 's':
|
||||||
chunk_size = strtoul(optarg, NULL, 10);
|
chunk_size = tstrtoul(toptarg, NULL, 10);
|
||||||
break;
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
level = strtoul(optarg, NULL, 10);
|
level = tstrtoul(toptarg, NULL, 10);
|
||||||
break;
|
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';
|
level = opt_char - '0';
|
||||||
break;
|
break;
|
||||||
case 'z':
|
case 'z':
|
||||||
@ -449,8 +397,8 @@ main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
argc -= optind;
|
argc -= toptind;
|
||||||
argv += optind;
|
argv += toptind;
|
||||||
|
|
||||||
printf("Benchmarking DEFLATE compression:\n");
|
printf("Benchmarking DEFLATE compression:\n");
|
||||||
printf("\tCompression level: %d\n", level);
|
printf("\tCompression level: %d\n", level);
|
||||||
@ -475,14 +423,15 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
if (argc == 0) {
|
if (argc == 0) {
|
||||||
printf("Reading from stdin...\n");
|
printf("Reading from stdin...\n");
|
||||||
|
set_binary_mode(STDIN_FILENO);
|
||||||
do_benchmark(STDIN_FILENO, ubuf1, ubuf2,
|
do_benchmark(STDIN_FILENO, ubuf1, ubuf2,
|
||||||
cbuf, chunk_size, &c, &d);
|
cbuf, chunk_size, &c, &d);
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < argc; i++) {
|
for (int i = 0; i < argc; i++) {
|
||||||
printf("Processing \"%s\"...\n", argv[i]);
|
printf("Processing \"%"TS"\"...\n", argv[i]);
|
||||||
int fd = open(argv[i], O_RDONLY);
|
int fd = topen(argv[i], O_RDONLY | O_BINARY);
|
||||||
ASSERT(fd >= 0,
|
ASSERT(fd >= 0,
|
||||||
"Can't open \"%s\" for reading: %s\n",
|
"Can't open \"%"TS"\" for reading: %s\n",
|
||||||
argv[i], strerror(errno));
|
argv[i], strerror(errno));
|
||||||
do_benchmark(fd, ubuf1, ubuf2, cbuf, chunk_size, &c, &d);
|
do_benchmark(fd, ubuf1, ubuf2, cbuf, chunk_size, &c, &d);
|
||||||
close(fd);
|
close(fd);
|
||||||
|
103
tools/gzip.c
103
tools/gzip.c
@ -8,76 +8,7 @@
|
|||||||
* You can do whatever you want with this file.
|
* You can do whatever you want with this file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define _FILE_OFFSET_BITS 64
|
#include "util.h"
|
||||||
|
|
||||||
#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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
is_gunzip(const tchar *argv0)
|
is_gunzip(const tchar *argv0)
|
||||||
@ -86,7 +17,7 @@ is_gunzip(const tchar *argv0)
|
|||||||
|
|
||||||
if (!tstrcmp(name, T("gunzip")))
|
if (!tstrcmp(name, T("gunzip")))
|
||||||
return true;
|
return true;
|
||||||
#ifdef __WIN32__
|
#ifdef _WIN32
|
||||||
if (!tstrcmp(name, T("gunzip.exe")))
|
if (!tstrcmp(name, T("gunzip.exe")))
|
||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
@ -104,26 +35,6 @@ usage(void)
|
|||||||
exit(1);
|
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 *
|
static void *
|
||||||
map_file_contents(const tchar *path, size_t *size_ret, void **token_ret)
|
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 "
|
"File \"%"TS"\" cannot be processed by "
|
||||||
"this program because it is too large.", path);
|
"this program because it is too large.", path);
|
||||||
|
|
||||||
#ifdef __WIN32__
|
#ifdef _WIN32
|
||||||
HANDLE h = CreateFileMapping((HANDLE)_get_osfhandle(fd),
|
HANDLE h = CreateFileMapping((HANDLE)(intptr_t)_get_osfhandle(fd),
|
||||||
NULL, PAGE_READONLY, 0, 0, NULL);
|
NULL, PAGE_READONLY, 0, 0, NULL);
|
||||||
ASSERT(h != NULL, "Unable create file mapping for \"%"TS"\": "
|
ASSERT(h != NULL, "Unable create file mapping for \"%"TS"\": "
|
||||||
"Windows error %u", path, (unsigned int )GetLastError());
|
"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
|
static void
|
||||||
unmap_file_contents(void *token, void *map, size_t size)
|
unmap_file_contents(void *token, void *map, size_t size)
|
||||||
{
|
{
|
||||||
#ifdef __WIN32__
|
#ifdef _WIN32
|
||||||
UnmapViewOfFile(map);
|
UnmapViewOfFile(map);
|
||||||
CloseHandle((HANDLE)token);
|
CloseHandle((HANDLE)token);
|
||||||
#else
|
#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",
|
ASSERT(ret > 0, "Error writing data to \"%"TS"\": %s",
|
||||||
path, strerror(errno));
|
path, strerror(errno));
|
||||||
size -= ret;
|
size -= ret;
|
||||||
contents += ret;
|
contents = (const uint8_t *)contents + ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(!close(fd), "Error writing data to \"%"TS"\"",
|
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),
|
ASSERT(compressed_size >= sizeof(uint32_t),
|
||||||
"File \"%"TS"\" is not a gzip file.", path);
|
"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)));
|
(compressed_size - sizeof(uint32_t)));
|
||||||
uncompressed_data = malloc(uncompressed_size);
|
uncompressed_data = malloc(uncompressed_size);
|
||||||
ASSERT(uncompressed_data != NULL,
|
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 clean
|
||||||
make -j4 CC=i686-w64-mingw32-gcc BUILD_PROGRAMS=yes
|
make -j4 CC=i686-w64-mingw32-gcc BUILD_PROGRAMS=yes
|
||||||
cp *.exe /j/exe
|
cp -vf *.exe /j/exe/
|
||||||
|
|
||||||
make clean
|
make clean
|
||||||
make -j4 CC=x86_64-w64-mingw32-gcc BUILD_PROGRAMS=yes
|
make -j4 CC=x86_64-w64-mingw32-gcc BUILD_PROGRAMS=yes
|
||||||
cp *.exe /j/exe64
|
cp -vf *.exe /j/exe64/
|
||||||
|
|
||||||
sudo systemctl restart smbd
|
sudo systemctl restart smbd
|
||||||
|
Loading…
x
Reference in New Issue
Block a user