This commit is contained in:
2025-08-06 13:29:28 +08:00
commit 957a372209
230 changed files with 43801 additions and 0 deletions

22
expkg/vendor/lz4/programs/.gitignore vendored Normal file
View File

@ -0,0 +1,22 @@
# local binary (Makefile)
lz4
unlz4
lz4cat
lz4c
lz4c32
lz4-nomt
lz4-wlib
datagen
frametest
frametest32
fullbench
fullbench32
fuzzer
fuzzer32
*.exe
# tests files
tmp*
# artefacts
*.dSYM

83
expkg/vendor/lz4/programs/COPYING vendored Normal file
View File

@ -0,0 +1,83 @@
Full name:
GNU General Public License v2.0 or later
Short identifier:
GPL-2.0-or-later
Text:
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too.
When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.
We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations.
Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and modification follow.
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program.
You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.
c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program.
In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.
3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.
If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License.
7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.
This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.
10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

236
expkg/vendor/lz4/programs/Makefile vendored Normal file
View File

@ -0,0 +1,236 @@
# ##########################################################################
# LZ4 programs - Makefile
# Copyright (C) Yann Collet 2011-2023
#
# This Makefile is validated for Linux, macOS, *BSD, Hurd, Solaris, MSYS2 targets
#
# GPL v2 License
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# You can contact the author at :
# - LZ4 homepage : http://www.lz4.org
# - LZ4 source repository : https://github.com/lz4/lz4
# ##########################################################################
# lz4 : Command Line Utility, supporting gzip-like arguments
# lz4c : CLU, supporting also legacy lz4demo arguments
# lz4c32: Same as lz4c, but forced to compile in 32-bits mode
# ##########################################################################
SED ?= sed
# Version numbers
LIBLZ4DIR := ../lib
LIBVER_SRC := $(LIBLZ4DIR)/lz4.h
LIBVER_MAJOR_SCRIPT:=`$(SED) -n '/define[[:blank:]][[:blank:]]*LZ4_VERSION_MAJOR/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < $(LIBVER_SRC)`
LIBVER_MINOR_SCRIPT:=`$(SED) -n '/define[[:blank:]][[:blank:]]*LZ4_VERSION_MINOR/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < $(LIBVER_SRC)`
LIBVER_PATCH_SCRIPT:=`$(SED) -n '/define[[:blank:]][[:blank:]]*LZ4_VERSION_RELEASE/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < $(LIBVER_SRC)`
LIBVER_SCRIPT:= $(LIBVER_MAJOR_SCRIPT).$(LIBVER_MINOR_SCRIPT).$(LIBVER_PATCH_SCRIPT)
LIBVER_MAJOR := $(shell echo $(LIBVER_MAJOR_SCRIPT))
LIBVER_MINOR := $(shell echo $(LIBVER_MINOR_SCRIPT))
LIBVER_PATCH := $(shell echo $(LIBVER_PATCH_SCRIPT))
LIBVER := $(shell echo $(LIBVER_SCRIPT))
LIBFILES = $(wildcard $(LIBLZ4DIR)/*.c)
SRCFILES = $(sort $(LIBFILES) $(wildcard *.c))
OBJFILES = $(SRCFILES:.c=.o)
DEBUGFLAGS= -Wall -Wextra -Wundef -Wcast-qual -Wcast-align -Wshadow \
-Wswitch-enum -Wdeclaration-after-statement -Wstrict-prototypes \
-Wpointer-arith -Wstrict-aliasing=1
USERCFLAGS:= -O3 $(CFLAGS) # -O3 can be overruled by user-provided -Ox level
CFLAGS = $(DEBUGFLAGS) $(USERCFLAGS)
CPPFLAGS += -I$(LIBLZ4DIR) -DXXH_NAMESPACE=LZ4_
include ../build/make/lz4defs.make
OS_VERSION ?= $(UNAME) -r
ifeq ($(TARGET_OS)$(shell $(OS_VERSION)),SunOS5.10)
LDFLAGS += -lrt
endif
ALLFLAGS = $(CFLAGS) $(CPPFLAGS) $(LDFLAGS)
.PHONY:default
default: lz4-release
C_SRCDIRS = $(LIBLZ4DIR) .
include ../build/make/multiconf.make
# thread detection
NUM_SYMBOL := \#
NO_THREAD_MSG:= ==> no multithread support: built for single-thread mode only
HAVE_PTHREAD := $(shell printf '$(NUM_SYMBOL)include <pthread.h>\nint main(void) { return 0; }' > have_pthread.c && $(CC) $(ALLFLAGS) -o have_pthread$(EXT) have_pthread.c -pthread 2> $(VOID) && rm -f have_pthread$(EXT) && echo 1 || echo 0; rm have_pthread.c)
HAVE_MULTITHREAD := $(shell [ "$(HAVE_PTHREAD)" -eq "1" -o -n "$(filter Windows%,$(OS))" ] && echo 1 || echo 0)
ifeq ($(HAVE_MULTITHREAD), 1)
THREAD_MSG := ==> built with multithreading support
THREAD_CPP := -DLZ4IO_MULTITHREAD
ifeq ($(HAVE_PTHREAD), 1)
THREAD_LD := -pthread
endif
else
THREAD_MSG := $(NO_THREAD_MSG)
endif
LZ4_VERSION=$(LIBVER)
MD2ROFF = ronn
MD2ROFF_FLAGS = --roff --warnings --manual="User Commands" --organization="lz4 $(LZ4_VERSION)"
# silent mode by default; verbose can be triggered by V=1 or VERBOSE=1
$(V)$(VERBOSE).SILENT:
.PHONY: all
all: lz4 lz4-nomt lz4c unlz4 lz4cat
.PHONY: all32
all32: CFLAGS+=-m32
all32: all
LZ4_OBJS := $(notdir $(OBJFILES))
ifeq ($(WINBASED),yes)
lz4-exe.rc: lz4-exe.rc.in
@echo creating executable resource
$(SED) -e 's|@PROGNAME@|lz4|' \
-e 's|@LIBVER_MAJOR@|$(LIBVER_MAJOR)|g' \
-e 's|@LIBVER_MINOR@|$(LIBVER_MINOR)|g' \
-e 's|@LIBVER_PATCH@|$(LIBVER_PATCH)|g' \
-e 's|@EXT@|.exe|g' \
$< >$@
lz4-exe.o: lz4-exe.rc
$(WINDRES) -i lz4-exe.rc -o lz4-exe.o
lz4: CPPFLAGS += $(THREAD_CPP)
lz4: LDFLAGS += $(THREAD_LD)
$(eval $(call c_program,lz4,$(LZ4_OBJS),lz4-exe.o,echo "$(THREAD_MSG)"))
else # not WINBASED
lz4: CPPFLAGS += $(THREAD_CPP)
lz4: LDFLAGS += $(THREAD_LD)
$(eval $(call c_program,lz4,$(LZ4_OBJS),,echo "$(THREAD_MSG)"))
endif
.PHONY: lz4-release
lz4-release: DEBUGFLAGS=
lz4-release: CPPFLAGS+=-DNDEBUG
lz4-release: lz4
lz4-nomt:
$(eval $(call c_program,lz4-nomt,$(LZ4_OBJS)))
CLEAN += lz4-wlib
lz4-wlib: LIBFILES =
lz4-wlib: SRCFILES+= $(LIBLZ4DIR)/xxhash.c # benchmark unit needs XXH64()
lz4-wlib: LDFLAGS += -L $(LIBLZ4DIR)
lz4-wlib: LDLIBS = -llz4
lz4-wlib: liblz4 $(OBJFILES)
@echo WARNING: $@ must link to an extended variant of the dynamic library which also exposes unstable symbols
$(CC) $(ALLFLAGS) $(OBJFILES) -o $@$(EXT) $(LDLIBS)
.PHONY:liblz4
liblz4:
CPPFLAGS="-DLZ4F_PUBLISH_STATIC_FUNCTIONS -DLZ4_PUBLISH_STATIC_FUNCTIONS" $(MAKE) -C $(LIBLZ4DIR) liblz4
CLEAN += lz4c
lz4c: lz4
$(LN_SF) lz4$(EXT) lz4c$(EXT)
lz4c32: CFLAGS += -m32
$(eval $(call c_program,lz4c32,$(LZ4_OBJS)))
CLEAN += unlz4
unlz4: lz4
$(LN_SF) lz4$(EXT) unlz4$(EXT)
CLEAN += lz4cat
lz4cat: lz4
$(LN_SF) lz4$(EXT) lz4cat$(EXT)
lz4.1: lz4.1.md $(LIBVER_SRC)
cat $< | $(MD2ROFF) $(MD2ROFF_FLAGS) | $(SED) -n '/^\.\\\".*/!p' > $@
.PHONY:man
man: lz4.1
.PHONY:clean-man
clean-man:
$(RM) lz4.1
.PHONY:preview-man
preview-man: clean-man man
man ./lz4.1
.PHONY:clean
clean: clean_cache
ifeq ($(WINBASED),yes)
$(RM) *.rc
endif
$(MAKE) -C $(LIBLZ4DIR) $@ > $(VOID)
$(RM) $(CLEAN) *.o *.test core
$(RM) -r tmp*
@echo Cleaning completed
#-----------------------------------------------------------------------------
# make install is validated only for Linux, OSX, BSD, Hurd and Solaris targets
#-----------------------------------------------------------------------------
ifeq ($(POSIX_ENV),Yes)
DESTDIR ?=
# directory variables : GNU conventions prefer lowercase
# see https://www.gnu.org/prep/standards/html_node/Makefile-Conventions.html
# support both lower and uppercase (BSD), use lowercase in script
PREFIX ?= /usr/local
prefix ?= $(PREFIX)
EXEC_PREFIX ?= $(prefix)
exec_prefix ?= $(EXEC_PREFIX)
BINDIR ?= $(exec_prefix)/bin
bindir ?= $(BINDIR)
DATAROOTDIR ?= $(prefix)/share
datarootdir ?= $(DATAROOTDIR)
MANDIR ?= $(datarootdir)/man
mandir ?= $(MANDIR)
MAN1DIR ?= $(mandir)/man1
man1dir ?= $(MAN1DIR)
.PHONY: install
install: lz4
@echo Installing binaries in $(DESTDIR)$(bindir)
$(MAKE_DIR) $(DESTDIR)$(bindir)/ $(DESTDIR)$(man1dir)/
$(INSTALL_PROGRAM) lz4$(EXT) $(DESTDIR)$(bindir)/lz4$(EXT)
$(LN_SF) lz4$(EXT) $(DESTDIR)$(bindir)/lz4c$(EXT)
$(LN_SF) lz4$(EXT) $(DESTDIR)$(bindir)/lz4cat$(EXT)
$(LN_SF) lz4$(EXT) $(DESTDIR)$(bindir)/unlz4$(EXT)
@echo Installing man pages in $(DESTDIR)$(man1dir)
$(INSTALL_DATA) lz4.1 $(DESTDIR)$(man1dir)/lz4.1
$(LN_SF) lz4.1 $(DESTDIR)$(man1dir)/lz4c.1
$(LN_SF) lz4.1 $(DESTDIR)$(man1dir)/lz4cat.1
$(LN_SF) lz4.1 $(DESTDIR)$(man1dir)/unlz4.1
@echo lz4 installation completed
.PHONY: uninstall
uninstall:
$(RM) $(DESTDIR)$(bindir)/lz4cat$(EXT)
$(RM) $(DESTDIR)$(bindir)/unlz4$(EXT)
$(RM) $(DESTDIR)$(bindir)/lz4$(EXT)
$(RM) $(DESTDIR)$(bindir)/lz4c$(EXT)
$(RM) $(DESTDIR)$(man1dir)/lz4.1
$(RM) $(DESTDIR)$(man1dir)/lz4c.1
$(RM) $(DESTDIR)$(man1dir)/lz4cat.1
$(RM) $(DESTDIR)$(man1dir)/unlz4.1
@echo lz4 programs successfully uninstalled
endif

114
expkg/vendor/lz4/programs/README.md vendored Normal file
View File

@ -0,0 +1,114 @@
Command Line Interface for LZ4 library
============================================
### Build
The `lz4` Command Line Interface (CLI) is generated
using the `make` command, no additional parameter required.
The CLI generates and decodes [LZ4-compressed frames](../doc/lz4_Frame_format.md).
For more control over the build process,
the `Makefile` script supports all [standard conventions](https://www.gnu.org/prep/standards/html_node/Makefile-Conventions.html),
including standard targets (`all`, `install`, `clean`, etc.)
and standard variables (`CC`, `CFLAGS`, `CPPFLAGS`, etc.).
The makefile offer several targets for various use cases:
- `lz4` : default CLI, with a command line syntax similar to gzip
- `lz4c` : supports legacy lz4 commands (incompatible with gzip)
- `lz4c32` : Same as `lz4c`, but generates a 32-bits executable
- `unlz4`, `lz4cat` : symlinks to `lz4`, default to decompression and `cat` compressed files
- `man` : generates the man page, from `lz4.1.md` markdown source
#### Makefile Build variables
- `HAVE_MULTITHREAD` : build with multithreading support. Detection is generally automatic, but can be forced to `0` or `1` if needed. This is for example useful when cross-compiling for Windows from Linux.
- `HAVE_PTHREAD` : determines presence of `<pthread>` support. Detection is automatic, but can be forced to `0` or `1` if needed. This is in turn used by `make` to automatically trigger multithreading support.
#### C Preprocessor Build variables
These variables are read by the preprocessor at compilation time. They influence executable behavior, such as default starting values, and are exposed from `programs/lz4conf.h`. These variables can manipulated by any build system.
Assignment methods vary depending on environments.
On a typical `posix` + `gcc` + `make` setup, they can be defined with `CPPFLAGS=-DVARIABLE=value` assignment.
- `LZ4_CLEVEL_DEFAULT`: default compression level when none provided. Default is `1`.
- `LZ4IO_MULTITHREAD`: enable multithreading support. Default is disabled.
- `LZ4_NBWORKERS_DEFAULT`: default nb of worker threads used in multithreading mode (can be overridden with command `-T#`).
Default is `0`, which means "auto-determine" based on local cpu.
- `LZ4_NBWORKERS_MAX`: absolute maximum nb of workers that can be requested at runtime.
Currently set to 200 by default.
This is mostly meant to protect the system against unreasonable and likely bogus requests, such as a million threads.
- `LZ4_BLOCKSIZEID_DEFAULT`: default `lz4` block size code. Valid values are [4-7], corresponding to 64 KB, 256 KB, 1 MB and 4 MB. At the time of this writing, default is 7, corresponding to 4 MB block size.
#### Environment Variables
It's possible to pass some parameters to `lz4` via environment variables.
This can be useful in situations where `lz4` is known to be invoked (from within a script for example) but there is no way to pass `lz4` parameters to influence the compression session.
The environment variable has higher priority than binary default, but lower priority than corresponding runtime command.
When set as global environment variables, it can enforce personalized defaults different from the binary set ones.
`LZ4_CLEVEL` can be used to specify a default compression level that `lz4` employs for compression when no other compression level is specified on command line. Executable default is generally `1`.
`LZ4_NBWORKERS` can be used to specify a default number of threads that `lz4` will employ for compression. Executable default is generally `0`, which means auto-determined based on local cpu. This functionality is only relevant when `lz4` is compiled with multithreading support. The maximum number of workers is capped at `LZ4_NBWORKERS_MAX` (`200` by default).
### Aggregation of parameters
The `lz4` CLI supports aggregation for short commands. For example, `-d`, `-q`, and `-f` can be joined into `-dqf`.
Aggregation doesn't work for `--long-commands`, which **must** be separated.
### Benchmark in Command Line Interface
`lz4` CLI includes an in-memory compression benchmark module, triggered by command `-b#`, with `#` representing the compression level.
The benchmark is conducted on a provided list of filenames.
The files are then read entirely into memory, to eliminate I/O overhead.
When multiple files are provided, they are bundled into the same benchmark session (though each file is a separate compression / decompression). Using `-S` command separates them (one session per file).
When no file is provided, uses an internal Lorem Ipsum generator instead.
The benchmark measures compressed size, compression factor, compression and decompression speed.
One can select multiple compression levels starting from `-b` and ending with `-e` (ascending).
The `-i` parameter selects a number of seconds used for each session.
### Usage of Command Line Interface
The full list of commands can be obtained with `-h` or `-H` parameter:
```
Usage :
lz4 [arg] [input] [output]
input : a filename
with no FILE, or when FILE is - or stdin, read standard input
Arguments :
-1 : Fast compression (default)
-9 : High compression
-d : decompression (default for .lz4 extension)
-z : force compression
-D FILE: use FILE as dictionary
-f : overwrite output without prompting
-k : preserve source files(s) (default)
--rm : remove source file(s) after successful de/compression
-h/-H : display help/long help and exit
Advanced arguments :
-V : display Version number and exit
-v : verbose mode
-q : suppress warnings; specify twice to suppress errors too
-c : force write to standard output, even if it is the console
-t : test compressed file integrity
-m : multiple input files (implies automatic output filenames)
-r : operate recursively on directories (sets also -m)
-l : compress using Legacy format (Linux kernel compression)
-B# : cut file into blocks of size # bytes [32+]
or predefined block size [4-7] (default: 7)
-BD : Block dependency (improve compression ratio)
-BX : enable block checksum (default:disabled)
--no-frame-crc : disable stream checksum (default:enabled)
--content-size : compressed frame includes original size (default:not present)
--[no-]sparse : sparse mode (default:enabled on file, disabled on stdout)
--favor-decSpeed: compressed files decompress faster, but are less compressed
--fast[=#]: switch to ultra fast compression level (default: 1)
Benchmark arguments :
-b# : benchmark file(s), using # compression level (default : 1)
-e# : test all compression levels from -bX to # (default : 1)
-i# : minimum evaluation time in seconds (default : 3s)```
```
#### License
All files in this directory are licensed under GPL-v2.
See [COPYING](COPYING) for details.
The text of the license is also included at the top of each source file.

865
expkg/vendor/lz4/programs/bench.c vendored Normal file
View File

@ -0,0 +1,865 @@
/*
bench.c - Demo program to benchmark open-source compression algorithms
Copyright (c) Yann Collet. All rights reserved.
GPL v2 License
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
You can contact the author at :
- LZ4 homepage : http://www.lz4.org
- LZ4 source repository : https://github.com/lz4/lz4
*/
/*-************************************
* Compiler options
**************************************/
#ifdef _MSC_VER /* Visual Studio */
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
#endif
/* *************************************
* Includes
***************************************/
#include "platform.h" /* Compiler options */
#include "util.h" /* UTIL_GetFileSize, UTIL_sleep */
#include <stdlib.h> /* malloc, free */
#include <string.h> /* memset */
#include <stdio.h> /* fprintf, fopen, ftello */
#include <time.h> /* clock_t, clock, CLOCKS_PER_SEC */
#include <assert.h> /* assert */
#include "lorem.h" /* LOREM_genBuffer */
#include "xxhash.h"
#include "bench.h"
#include "timefn.h"
#define LZ4_STATIC_LINKING_ONLY
#include "lz4.h"
#define LZ4_HC_STATIC_LINKING_ONLY
#include "lz4hc.h"
#include "lz4frame.h" /* LZ4F_decompress */
/* *************************************
* Constants
***************************************/
#ifndef LZ4_GIT_COMMIT_STRING
# define LZ4_GIT_COMMIT_STRING ""
#else
# define LZ4_GIT_COMMIT_STRING LZ4_EXPAND_AND_QUOTE(LZ4_GIT_COMMIT)
#endif
#define NBSECONDS 3
#define TIMELOOP_MICROSEC 1*1000000ULL /* 1 second */
#define TIMELOOP_NANOSEC 1*1000000000ULL /* 1 second */
#define ACTIVEPERIOD_NANOSEC 70*1000000000ULL /* 70 seconds */
#define COOLPERIOD_SEC 10
#define DECOMP_MULT 1 /* test decompression DECOMP_MULT times longer than compression */
#define KB *(1 <<10)
#define MB *(1 <<20)
#define GB *(1U<<30)
#define LZ4_MAX_DICT_SIZE (64 KB)
static const size_t maxMemory = (sizeof(size_t)==4) ? (2 GB - 64 MB) : (size_t)(1ULL << ((sizeof(size_t)*8)-31));
/* *************************************
* console display
***************************************/
#define DISPLAYOUT(...) fprintf(stdout, __VA_ARGS__)
#define OUTLEVEL(l, ...) if (g_displayLevel>=(l)) { DISPLAYOUT(__VA_ARGS__); }
#define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
#define DISPLAYLEVEL(l, ...) if (g_displayLevel>=(l)) { DISPLAY(__VA_ARGS__); }
static U32 g_displayLevel = 2; /* 0 : no display; 1: errors; 2 : + result + interaction + warnings; 3 : + progression; 4 : + information */
#define DISPLAYUPDATE(l, ...) if (g_displayLevel>=l) { \
if ((clock() - g_time > refreshRate) || (g_displayLevel>=4)) \
{ g_time = clock(); DISPLAY(__VA_ARGS__); \
if (g_displayLevel>=4) fflush(stdout); } }
static const clock_t refreshRate = CLOCKS_PER_SEC * 15 / 100;
static clock_t g_time = 0;
/* *************************************
* DEBUG and error conditions
***************************************/
#ifndef DEBUG
# define DEBUG 0
#endif
#define DEBUGOUTPUT(...) if (DEBUG) DISPLAY(__VA_ARGS__);
#define END_PROCESS(error, ...) \
do { \
DEBUGOUTPUT("Error defined at %s, line %i : \n", __FILE__, __LINE__); \
DISPLAYLEVEL(1, "Error %i : ", error); \
DISPLAYLEVEL(1, __VA_ARGS__); \
DISPLAYLEVEL(1, "\n"); \
exit(error); \
} while (0)
#define LZ4_isError(errcode) (errcode==0)
/* *************************************
* Benchmark Parameters
***************************************/
static U32 g_nbSeconds = NBSECONDS;
static size_t g_blockSize = 0;
int g_additionalParam = 0;
int g_benchSeparately = 0;
int g_decodeOnly = 0;
unsigned g_skipChecksums = 0;
void BMK_setNotificationLevel(unsigned level) { g_displayLevel=level; }
void BMK_setAdditionalParam(int additionalParam) { g_additionalParam=additionalParam; }
void BMK_setNbSeconds(unsigned nbSeconds)
{
g_nbSeconds = nbSeconds;
DISPLAYLEVEL(3, "- test >= %u seconds per compression / decompression -\n", g_nbSeconds);
}
void BMK_setBlockSize(size_t blockSize) { g_blockSize = blockSize; }
void BMK_setBenchSeparately(int separate) { g_benchSeparately = (separate!=0); }
void BMK_setDecodeOnlyMode(int set) { g_decodeOnly = (set!=0); }
void BMK_skipChecksums(int skip) { g_skipChecksums = (skip!=0); }
/* *************************************
* Compression state management
***************************************/
struct compressionParameters
{
int cLevel;
const char* dictBuf;
int dictSize;
LZ4_stream_t* LZ4_stream;
LZ4_stream_t* LZ4_dictStream;
LZ4_streamHC_t* LZ4_streamHC;
LZ4_streamHC_t* LZ4_dictStreamHC;
void (*initFunction)(
struct compressionParameters* pThis);
void (*resetFunction)(
const struct compressionParameters* pThis);
int (*blockFunction)(
const struct compressionParameters* pThis,
const char* src, char* dst, int srcSize, int dstSize);
void (*cleanupFunction)(
const struct compressionParameters* pThis);
};
static void
LZ4_compressInitNoStream(struct compressionParameters* pThis)
{
pThis->LZ4_stream = NULL;
pThis->LZ4_dictStream = NULL;
pThis->LZ4_streamHC = NULL;
pThis->LZ4_dictStreamHC = NULL;
}
static void
LZ4_compressInitStream(struct compressionParameters* pThis)
{
pThis->LZ4_stream = LZ4_createStream();
pThis->LZ4_dictStream = LZ4_createStream();
pThis->LZ4_streamHC = NULL;
pThis->LZ4_dictStreamHC = NULL;
LZ4_loadDictSlow(pThis->LZ4_dictStream, pThis->dictBuf, pThis->dictSize);
}
static void
LZ4_compressInitStreamHC(struct compressionParameters* pThis)
{
pThis->LZ4_stream = NULL;
pThis->LZ4_dictStream = NULL;
pThis->LZ4_streamHC = LZ4_createStreamHC();
pThis->LZ4_dictStreamHC = LZ4_createStreamHC();
LZ4_resetStreamHC_fast(pThis->LZ4_dictStreamHC, pThis->cLevel);
LZ4_loadDictHC(pThis->LZ4_dictStreamHC, pThis->dictBuf, pThis->dictSize);
}
static void
LZ4_compressResetNoStream(const struct compressionParameters* cparams)
{
(void)cparams;
}
static void
LZ4_compressResetStream(const struct compressionParameters* cparams)
{
LZ4_resetStream_fast(cparams->LZ4_stream);
LZ4_attach_dictionary(cparams->LZ4_stream, cparams->LZ4_dictStream);
}
static void
LZ4_compressResetStreamHC(const struct compressionParameters* cparams)
{
LZ4_resetStreamHC_fast(cparams->LZ4_streamHC, cparams->cLevel);
LZ4_attach_HC_dictionary(cparams->LZ4_streamHC, cparams->LZ4_dictStreamHC);
}
static int
LZ4_compressBlockNoStream(const struct compressionParameters* cparams,
const char* src, char* dst,
int srcSize, int dstSize)
{
int const acceleration = (cparams->cLevel < 0) ? -cparams->cLevel + 1 : 1;
return LZ4_compress_fast(src, dst, srcSize, dstSize, acceleration);
}
static int
LZ4_compressBlockNoStreamHC(const struct compressionParameters* cparams,
const char* src, char* dst,
int srcSize, int dstSize)
{
return LZ4_compress_HC(src, dst, srcSize, dstSize, cparams->cLevel);
}
static int
LZ4_compressBlockStream(const struct compressionParameters* cparams,
const char* src, char* dst,
int srcSize, int dstSize)
{
int const acceleration = (cparams->cLevel < 0) ? -cparams->cLevel + 1 : 1;
LZ4_compressResetStream(cparams);
return LZ4_compress_fast_continue(cparams->LZ4_stream, src, dst, srcSize, dstSize, acceleration);
}
static int
LZ4_compressBlockStreamHC(const struct compressionParameters* cparams,
const char* src, char* dst,
int srcSize, int dstSize)
{
LZ4_compressResetStreamHC(cparams);
return LZ4_compress_HC_continue(cparams->LZ4_streamHC, src, dst, srcSize, dstSize);
}
static void
LZ4_compressCleanupNoStream(const struct compressionParameters* cparams)
{
(void)cparams;
}
static void
LZ4_compressCleanupStream(const struct compressionParameters* cparams)
{
LZ4_freeStream(cparams->LZ4_stream);
LZ4_freeStream(cparams->LZ4_dictStream);
}
static void
LZ4_compressCleanupStreamHC(const struct compressionParameters* cparams)
{
LZ4_freeStreamHC(cparams->LZ4_streamHC);
LZ4_freeStreamHC(cparams->LZ4_dictStreamHC);
}
static void
LZ4_buildCompressionParameters(struct compressionParameters* pParams,
int cLevel,
const char* dictBuf, int dictSize)
{
pParams->cLevel = cLevel;
pParams->dictBuf = dictBuf;
pParams->dictSize = dictSize;
if (dictSize) {
if (cLevel < LZ4HC_CLEVEL_MIN) {
pParams->initFunction = LZ4_compressInitStream;
pParams->resetFunction = LZ4_compressResetStream;
pParams->blockFunction = LZ4_compressBlockStream;
pParams->cleanupFunction = LZ4_compressCleanupStream;
} else {
pParams->initFunction = LZ4_compressInitStreamHC;
pParams->resetFunction = LZ4_compressResetStreamHC;
pParams->blockFunction = LZ4_compressBlockStreamHC;
pParams->cleanupFunction = LZ4_compressCleanupStreamHC;
}
} else {
pParams->initFunction = LZ4_compressInitNoStream;
pParams->resetFunction = LZ4_compressResetNoStream;
pParams->cleanupFunction = LZ4_compressCleanupNoStream;
if (cLevel < LZ4HC_CLEVEL_MIN) {
pParams->blockFunction = LZ4_compressBlockNoStream;
} else {
pParams->blockFunction = LZ4_compressBlockNoStreamHC;
}
}
}
typedef int (*DecFunction_f)(const char* src, char* dst,
int srcSize, int dstCapacity,
const char* dictStart, int dictSize);
static LZ4F_dctx* g_dctx = NULL;
static int
LZ4F_decompress_binding(const char* src, char* dst,
int srcSize, int dstCapacity,
const char* dictStart, int dictSize)
{
size_t dstSize = (size_t)dstCapacity;
size_t readSize = (size_t)srcSize;
LZ4F_decompressOptions_t dOpt = { 1, 0, 0, 0 };
size_t decStatus;
dOpt.skipChecksums = g_skipChecksums;
decStatus = LZ4F_decompress(g_dctx,
dst, &dstSize,
src, &readSize,
&dOpt);
if ( (decStatus == 0) /* decompression successful */
&& ((int)readSize==srcSize) /* consume all input */ )
return (int)dstSize;
/* else, error */
return -1;
(void)dictStart; (void)dictSize; /* not compatible with dictionary yet */
}
/* ********************************************************
* Bench functions
**********************************************************/
typedef struct {
const char* srcPtr;
size_t srcSize;
char* cPtr;
size_t cRoom;
size_t cSize;
char* resPtr;
size_t resSize;
} blockParam_t;
#define MIN(a,b) ((a)<(b) ? (a) : (b))
#define MAX(a,b) ((a)>(b) ? (a) : (b))
static int BMK_benchMem(const void* srcBuffer, size_t srcSize,
const char* displayName, int cLevel,
const size_t* fileSizes, U32 nbFiles,
const char* dictBuf, int dictSize)
{
size_t const blockSize = (g_blockSize>=32 && !g_decodeOnly ? g_blockSize : srcSize) + (!srcSize) /* avoid div by 0 */ ;
U32 const maxNbBlocks = (U32)((srcSize + (blockSize-1)) / blockSize) + nbFiles;
blockParam_t* const blockTable = (blockParam_t*) malloc(maxNbBlocks * sizeof(blockParam_t));
size_t const maxCompressedSize = (size_t)LZ4_compressBound((int)srcSize) + (maxNbBlocks * 1024); /* add some room for safety */
void* const compressedBuffer = malloc(maxCompressedSize);
size_t const decMultiplier = g_decodeOnly ? 255 : 1;
size_t const maxInSize = (size_t)LZ4_MAX_INPUT_SIZE / decMultiplier;
size_t const maxDecSize = srcSize < maxInSize ? srcSize * decMultiplier : LZ4_MAX_INPUT_SIZE;
void* const resultBuffer = malloc(maxDecSize);
int benchError = 0;
U32 nbBlocks;
struct compressionParameters compP;
/* checks */
if (!compressedBuffer || !resultBuffer || !blockTable)
END_PROCESS(31, "allocation error : not enough memory");
if (strlen(displayName)>17) displayName += strlen(displayName)-17; /* can only display 17 characters */
/* init */
LZ4_buildCompressionParameters(&compP, cLevel, dictBuf, dictSize);
compP.initFunction(&compP);
if (g_dctx==NULL) {
LZ4F_createDecompressionContext(&g_dctx, LZ4F_VERSION);
if (g_dctx==NULL)
END_PROCESS(1, "allocation error - decompression state");
}
/* Init blockTable data */
{ const char* srcPtr = (const char*)srcBuffer;
char* cPtr = (char*)compressedBuffer;
char* resPtr = (char*)resultBuffer;
U32 fileNb;
for (nbBlocks=0, fileNb=0; fileNb<nbFiles; fileNb++) {
size_t remaining = fileSizes[fileNb];
U32 const nbBlocksforThisFile = (U32)((remaining + (blockSize-1)) / blockSize);
U32 const blockEnd = nbBlocks + nbBlocksforThisFile;
for ( ; nbBlocks<blockEnd; nbBlocks++) {
size_t const thisBlockSize = MIN(remaining, blockSize);
size_t const resMaxSize = thisBlockSize * decMultiplier;
size_t const resCapa = (thisBlockSize < maxInSize) ? resMaxSize : LZ4_MAX_INPUT_SIZE;
blockTable[nbBlocks].srcPtr = srcPtr;
blockTable[nbBlocks].cPtr = cPtr;
blockTable[nbBlocks].resPtr = resPtr;
blockTable[nbBlocks].srcSize = thisBlockSize;
blockTable[nbBlocks].cRoom = (size_t)LZ4_compressBound((int)thisBlockSize);
srcPtr += thisBlockSize;
cPtr += blockTable[nbBlocks].cRoom;
resPtr += resCapa;
remaining -= thisBlockSize;
} } }
/* warming up memory */
memset(compressedBuffer, ' ', maxCompressedSize);
/* decode-only mode : copy input to @compressedBuffer */
if (g_decodeOnly) {
U32 blockNb;
for (blockNb=0; blockNb < nbBlocks; blockNb++) {
memcpy(blockTable[blockNb].cPtr, blockTable[blockNb].srcPtr, blockTable[blockNb].srcSize);
blockTable[blockNb].cSize = blockTable[blockNb].srcSize;
} }
/* Bench */
{ U64 fastestC = (U64)(-1LL), fastestD = (U64)(-1LL);
U64 const crcOrig = XXH64(srcBuffer, srcSize, 0);
TIME_t coolTime = TIME_getTime();
U64 const maxTime = (g_nbSeconds * TIMELOOP_NANOSEC) + 100;
U32 nbCompressionLoops = (U32)((5 MB) / (srcSize+1)) + 1; /* conservative initial compression speed estimate */
U32 nbDecodeLoops = (U32)((200 MB) / (srcSize+1)) + 1; /* conservative initial decode speed estimate */
Duration_ns totalCTime=0, totalDTime=0;
U32 cCompleted=(g_decodeOnly==1), dCompleted=0;
# define NB_MARKS 4
const char* const marks[NB_MARKS] = { " |", " /", " =", "\\" };
U32 markNb = 0;
size_t cSize = srcSize;
size_t totalRSize = srcSize;
double ratio = 0.;
DISPLAYLEVEL(2, "\r%79s\r", "");
if (g_nbSeconds==0) { nbCompressionLoops = 1; nbDecodeLoops = 1; }
while (!cCompleted || !dCompleted) {
/* overheat protection */
if (TIME_clockSpan_ns(coolTime) > ACTIVEPERIOD_NANOSEC) {
DISPLAYLEVEL(2, "\rcooling down ... \r");
UTIL_sleep(COOLPERIOD_SEC);
coolTime = TIME_getTime();
}
/* Compression */
DISPLAYLEVEL(2, "%2s-%-17.17s :%10u ->\r", marks[markNb], displayName, (U32)totalRSize);
if (!cCompleted) {
memset(compressedBuffer, 0xE5, maxCompressedSize); /* warm up and erase compressed buffer */
{ U32 blockNb; for (blockNb=0; blockNb<nbBlocks; blockNb++) blockTable[blockNb].cSize = 0; }
}
UTIL_sleepMilli(1); /* give processor time to other processes */
TIME_waitForNextTick();
if (!cCompleted) { /* still some time to do compression tests */
TIME_t const timeStart = TIME_getTime();
U32 nbLoops;
for (nbLoops=0; nbLoops < nbCompressionLoops; nbLoops++) {
U32 blockNb;
compP.resetFunction(&compP);
for (blockNb=0; blockNb<nbBlocks; blockNb++) {
size_t const rSize = (size_t)compP.blockFunction(
&compP,
blockTable[blockNb].srcPtr, blockTable[blockNb].cPtr,
(int)blockTable[blockNb].srcSize, (int)blockTable[blockNb].cRoom);
if (LZ4_isError(rSize)) {
DISPLAY("LZ4 compression failed on block %u \n", blockNb);
benchError =1 ;
}
blockTable[blockNb].cSize = rSize;
} }
{ Duration_ns const duration_ns = TIME_clockSpan_ns(timeStart);
if (duration_ns > 0) {
if (duration_ns < fastestC * nbCompressionLoops)
fastestC = duration_ns / nbCompressionLoops;
assert(fastestC > 0);
nbCompressionLoops = (U32)(TIMELOOP_NANOSEC / fastestC) + 1; /* aim for ~1sec */
} else {
assert(nbCompressionLoops < 40000000); /* avoid overflow */
nbCompressionLoops *= 100;
}
totalCTime += duration_ns;
cCompleted = totalCTime>maxTime;
}
cSize = 0;
{ U32 blockNb; for (blockNb=0; blockNb<nbBlocks; blockNb++) cSize += blockTable[blockNb].cSize; }
cSize += !cSize; /* avoid div by 0 */
ratio = (double)totalRSize / (double)cSize;
markNb = (markNb+1) % NB_MARKS;
OUTLEVEL(2, "%2s-%-17.17s :%10u ->%10u (%5.3f),%6.1f MB/s\r",
marks[markNb], displayName,
(U32)totalRSize, (U32)cSize, ratio,
((double)totalRSize / (double)fastestC) * 1000 );
fflush(NULL);
}
(void)fastestD; (void)crcOrig; /* unused when decompression disabled */
#if 1
/* Decompression */
if (!dCompleted) memset(resultBuffer, 0xD6, srcSize); /* warm result buffer */
UTIL_sleepMilli(5); /* give processor time to other processes */
TIME_waitForNextTick();
if (!dCompleted) {
const DecFunction_f decFunction = g_decodeOnly ?
LZ4F_decompress_binding : LZ4_decompress_safe_usingDict;
const char* const decString = g_decodeOnly ?
"LZ4F_decompress" : "LZ4_decompress_safe_usingDict";
TIME_t const timeStart = TIME_getTime();
U32 nbLoops;
for (nbLoops=0; nbLoops < nbDecodeLoops; nbLoops++) {
U32 blockNb;
for (blockNb=0; blockNb<nbBlocks; blockNb++) {
size_t const inMaxSize = (size_t)INT_MAX / decMultiplier;
size_t const resCapa = (blockTable[blockNb].srcSize < inMaxSize) ?
blockTable[blockNb].srcSize * decMultiplier :
INT_MAX;
int const regenSize = decFunction(
blockTable[blockNb].cPtr, blockTable[blockNb].resPtr,
(int)blockTable[blockNb].cSize, (int)resCapa,
dictBuf, dictSize);
if (regenSize < 0) {
DISPLAY("%s() failed on block %u of size %u \n",
decString, blockNb, (unsigned)blockTable[blockNb].srcSize);
if (g_decodeOnly)
DISPLAY("Is input using LZ4 Frame format ? \n");
benchError = 1;
break;
}
blockTable[blockNb].resSize = (size_t)regenSize;
} }
{ Duration_ns const duration_ns = TIME_clockSpan_ns(timeStart);
if (duration_ns > 0) {
if (duration_ns < fastestD * nbDecodeLoops)
fastestD = duration_ns / nbDecodeLoops;
assert(fastestD > 0);
nbDecodeLoops = (U32)(TIMELOOP_NANOSEC / fastestD) + 1; /* aim for ~1sec */
} else {
assert(nbDecodeLoops < 40000000); /* avoid overflow */
nbDecodeLoops *= 100;
}
totalDTime += duration_ns;
dCompleted = totalDTime > (DECOMP_MULT*maxTime);
} }
if (g_decodeOnly) {
unsigned u;
totalRSize = 0;
for (u=0; u<nbBlocks; u++) totalRSize += blockTable[u].resSize;
}
markNb = (markNb+1) % NB_MARKS;
ratio = (double)totalRSize / (double)cSize;
OUTLEVEL(2, "%2s-%-17.17s :%10u ->%10u (%5.3f),%6.1f MB/s, %6.1f MB/s\r",
marks[markNb], displayName,
(U32)totalRSize, (U32)cSize, ratio,
((double)totalRSize / (double)fastestC) * 1000,
((double)totalRSize / (double)fastestD) * 1000);
fflush(NULL);
/* CRC Checking (not possible in decode-only mode)*/
if (!g_decodeOnly) {
U64 const crcCheck = XXH64(resultBuffer, srcSize, 0);
if (crcOrig!=crcCheck) {
size_t u;
DISPLAY("\n!!! WARNING !!! %17s : Invalid Checksum : %x != %x \n", displayName, (unsigned)crcOrig, (unsigned)crcCheck);
benchError = 1;
for (u=0; u<srcSize; u++) {
if (((const BYTE*)srcBuffer)[u] != ((const BYTE*)resultBuffer)[u]) {
U32 segNb, bNb, pos;
size_t bacc = 0;
DISPLAY("Decoding error at pos %u ", (U32)u);
for (segNb = 0; segNb < nbBlocks; segNb++) {
if (bacc + blockTable[segNb].srcSize > u) break;
bacc += blockTable[segNb].srcSize;
}
pos = (U32)(u - bacc);
bNb = pos / (128 KB);
DISPLAY("(block %u, sub %u, pos %u) \n", segNb, bNb, pos);
break;
}
if (u==srcSize-1) { /* should never happen */
DISPLAY("no difference detected\n");
} }
break;
} } /* CRC Checking */
#endif
} /* for (testNb = 1; testNb <= (g_nbSeconds + !g_nbSeconds); testNb++) */
OUTLEVEL(2, "%2i#\n", cLevel);
/* quiet mode */
if (g_displayLevel == 1) {
double const cSpeed = ((double)srcSize / (double)fastestC) * 1000;
double const dSpeed = ((double)srcSize / (double)fastestD) * 1000;
DISPLAYOUT("-%-3i%11i (%5.3f) %6.2f MB/s %6.1f MB/s %s ", cLevel, (int)cSize, ratio, cSpeed, dSpeed, displayName);
if (g_additionalParam)
DISPLAYOUT("(param=%d)", g_additionalParam);
DISPLAYOUT("\n");
}
} /* Bench */
/* clean up */
compP.cleanupFunction(&compP);
free(blockTable);
free(compressedBuffer);
free(resultBuffer);
return benchError;
}
static size_t BMK_findMaxMem(U64 requiredMem)
{
size_t step = 64 MB;
BYTE* testmem=NULL;
requiredMem = (((requiredMem >> 26) + 1) << 26);
requiredMem += 2*step;
if (requiredMem > maxMemory) requiredMem = maxMemory;
while (!testmem) {
if (requiredMem > step) requiredMem -= step;
else requiredMem >>= 1;
testmem = (BYTE*) malloc ((size_t)requiredMem);
}
free (testmem);
/* keep some space available */
if (requiredMem > step) requiredMem -= step;
else requiredMem >>= 1;
return (size_t)requiredMem;
}
static int BMK_benchCLevel(void* srcBuffer, size_t benchedSize,
const char* displayName, int cLevel, int cLevelLast,
const size_t* fileSizes, unsigned nbFiles,
const char* dictBuf, int dictSize)
{
int l;
int benchError = 0;
const char* pch = strrchr(displayName, '\\'); /* Windows */
if (!pch) pch = strrchr(displayName, '/'); /* Linux */
if (pch) displayName = pch+1;
SET_REALTIME_PRIORITY;
if (g_displayLevel == 1 && !g_additionalParam)
DISPLAY("bench %s %s: input %u bytes, %u seconds, %u KB blocks\n", LZ4_VERSION_STRING, LZ4_GIT_COMMIT_STRING, (U32)benchedSize, g_nbSeconds, (U32)(g_blockSize>>10));
if (cLevelLast < cLevel) cLevelLast = cLevel;
for (l=cLevel; l <= cLevelLast; l++) {
benchError |= BMK_benchMem(
srcBuffer, benchedSize,
displayName, l,
fileSizes, nbFiles,
dictBuf, dictSize);
}
return benchError;
}
/*! BMK_loadFiles() :
Loads `buffer` with content of files listed within `fileNamesTable`.
At most, fills `buffer` entirely */
static void BMK_loadFiles(void* buffer, size_t bufferSize,
size_t* fileSizes,
const char** fileNamesTable, unsigned nbFiles)
{
size_t pos = 0, totalSize = 0;
unsigned n;
for (n=0; n<nbFiles; n++) {
FILE* f;
U64 fileSize = UTIL_getFileSize(fileNamesTable[n]);
if (UTIL_isDirectory(fileNamesTable[n])) {
DISPLAYLEVEL(2, "Ignoring %s directory... \n", fileNamesTable[n]);
fileSizes[n] = 0;
continue;
}
f = fopen(fileNamesTable[n], "rb");
if (f==NULL) END_PROCESS(10, "impossible to open file %s", fileNamesTable[n]);
DISPLAYUPDATE(2, "Loading %s... \r", fileNamesTable[n]);
if (fileSize > bufferSize-pos) { /* buffer too small - stop after this file */
fileSize = bufferSize-pos;
nbFiles=n;
}
{ size_t const readSize = fread(((char*)buffer)+pos, 1, (size_t)fileSize, f);
if (readSize != (size_t)fileSize) END_PROCESS(11, "could not read %s", fileNamesTable[n]);
pos += readSize; }
fileSizes[n] = (size_t)fileSize;
totalSize += (size_t)fileSize;
fclose(f);
}
if (totalSize == 0) END_PROCESS(12, "no data to bench");
}
static int BMK_benchFileTable(const char** fileNamesTable, unsigned nbFiles,
int cLevel, int cLevelLast,
const char* dictBuf, int dictSize)
{
void* srcBuffer;
size_t benchedSize;
int benchError = 0;
size_t* fileSizes = (size_t*)malloc(nbFiles * sizeof(size_t));
U64 const totalSizeToLoad = UTIL_getTotalFileSize(fileNamesTable, nbFiles);
char mfName[20] = {0};
if (!fileSizes) END_PROCESS(12, "not enough memory for fileSizes");
/* Memory allocation & restrictions */
benchedSize = BMK_findMaxMem(totalSizeToLoad * 3) / 3;
if (benchedSize==0) END_PROCESS(12, "not enough memory");
if ((U64)benchedSize > totalSizeToLoad) benchedSize = (size_t)totalSizeToLoad;
if (benchedSize > LZ4_MAX_INPUT_SIZE) {
benchedSize = LZ4_MAX_INPUT_SIZE;
DISPLAY("File(s) bigger than LZ4's max input size; testing %u MB only...\n", (U32)(benchedSize >> 20));
} else {
if (benchedSize < totalSizeToLoad)
DISPLAY("Not enough memory; testing %u MB only...\n", (U32)(benchedSize >> 20));
}
srcBuffer = malloc(benchedSize + !benchedSize); /* avoid alloc of zero */
if (!srcBuffer) END_PROCESS(12, "not enough memory");
/* Load input buffer */
BMK_loadFiles(srcBuffer, benchedSize, fileSizes, fileNamesTable, nbFiles);
/* Bench */
snprintf (mfName, sizeof(mfName), " %u files", nbFiles);
{ const char* displayName = (nbFiles > 1) ? mfName : fileNamesTable[0];
benchError = BMK_benchCLevel(srcBuffer, benchedSize,
displayName, cLevel, cLevelLast,
fileSizes, nbFiles,
dictBuf, dictSize);
}
/* clean up */
free(srcBuffer);
free(fileSizes);
return benchError;
}
static int BMK_syntheticTest(int cLevel, int cLevelLast,
const char* dictBuf, int dictSize)
{
int benchError = 0;
size_t const benchedSize = 10000000;
void* const srcBuffer = malloc(benchedSize);
/* Memory allocation */
if (!srcBuffer) END_PROCESS(21, "not enough memory");
/* Fill input buffer */
LOREM_genBuffer(srcBuffer, benchedSize, 0);
/* Bench */
benchError = BMK_benchCLevel(srcBuffer, benchedSize,
"Lorem ipsum",
cLevel, cLevelLast,
&benchedSize,
1,
dictBuf, dictSize);
/* clean up */
free(srcBuffer);
return benchError;
}
static int
BMK_benchFilesSeparately(const char** fileNamesTable, unsigned nbFiles,
int cLevel, int cLevelLast,
const char* dictBuf, int dictSize)
{
int benchError = 0;
unsigned fileNb;
if (cLevel > LZ4HC_CLEVEL_MAX) cLevel = LZ4HC_CLEVEL_MAX;
if (cLevelLast > LZ4HC_CLEVEL_MAX) cLevelLast = LZ4HC_CLEVEL_MAX;
if (cLevelLast < cLevel) cLevelLast = cLevel;
for (fileNb=0; fileNb<nbFiles; fileNb++)
benchError |= BMK_benchFileTable(fileNamesTable+fileNb, 1, cLevel, cLevelLast, dictBuf, dictSize);
return benchError;
}
int BMK_benchFiles(const char** fileNamesTable, unsigned nbFiles,
int cLevel, int cLevelLast,
const char* dictFileName)
{
int benchError = 0;
char* dictBuf = NULL;
size_t dictSize = 0;
if (cLevel > LZ4HC_CLEVEL_MAX) cLevel = LZ4HC_CLEVEL_MAX;
if (g_decodeOnly) {
DISPLAYLEVEL(2, "Benchmark Decompression of LZ4 Frame ");
if (g_skipChecksums) {
DISPLAYLEVEL(2, "_without_ checksum even when present \n");
} else {
DISPLAYLEVEL(2, "+ Checksum when present \n");
}
cLevelLast = cLevel;
}
if (cLevelLast > LZ4HC_CLEVEL_MAX) cLevelLast = LZ4HC_CLEVEL_MAX;
if (cLevelLast < cLevel) cLevelLast = cLevel;
if (cLevelLast > cLevel)
DISPLAYLEVEL(2, "Benchmarking levels from %d to %d\n", cLevel, cLevelLast);
if (dictFileName) {
FILE* dictFile = NULL;
U64 const dictFileSize = UTIL_getFileSize(dictFileName);
if (!dictFileSize)
END_PROCESS(25, "Dictionary error : could not stat dictionary file");
if (g_decodeOnly)
END_PROCESS(26, "Error : LZ4 Frame decoder mode not compatible with dictionary yet");
dictFile = fopen(dictFileName, "rb");
if (!dictFile)
END_PROCESS(25, "Dictionary error : could not open dictionary file");
if (dictFileSize > LZ4_MAX_DICT_SIZE) {
dictSize = LZ4_MAX_DICT_SIZE;
if (UTIL_fseek(dictFile, (long)(dictFileSize - dictSize), SEEK_SET))
END_PROCESS(25, "Dictionary error : could not seek dictionary file");
} else {
dictSize = (size_t)dictFileSize;
}
dictBuf = (char*)malloc(dictSize);
if (!dictBuf) END_PROCESS(25, "Allocation error : not enough memory");
if (fread(dictBuf, 1, dictSize, dictFile) != dictSize)
END_PROCESS(25, "Dictionary error : could not read dictionary file");
fclose(dictFile);
}
if (nbFiles == 0) {
benchError = BMK_syntheticTest(cLevel, cLevelLast, dictBuf, (int)dictSize);
} else {
if (g_benchSeparately)
benchError = BMK_benchFilesSeparately(fileNamesTable, nbFiles, cLevel, cLevelLast, dictBuf, (int)dictSize);
else
benchError = BMK_benchFileTable(fileNamesTable, nbFiles, cLevel, cLevelLast, dictBuf, (int)dictSize);
}
free(dictBuf);
return benchError;
}

54
expkg/vendor/lz4/programs/bench.h vendored Normal file
View File

@ -0,0 +1,54 @@
/*
bench.h - Demo program to benchmark open-source compression algorithm
Copyright (c) Yann Collet. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
You can contact the author at :
- LZ4 source repository : https://github.com/lz4/lz4
- LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
*/
#ifndef BENCH_H_125623623633
#define BENCH_H_125623623633
#include <stddef.h>
/* BMK_benchFiles() :
* Benchmark all files provided through array @fileNamesTable.
* All files must be valid, otherwise benchmark fails.
* Roundtrip measurements are done for each file individually, but
* unless BMK_setBenchSeparately() is set, all results are agglomerated.
* The method benchmarks all compression levels from @cLevelStart to @cLevelLast,
* both inclusive, providing one result per compression level.
* If @cLevelLast <= @cLevelStart, BMK_benchFiles() benchmarks @cLevelStart only.
* @dictFileName is optional, it's possible to provide NULL.
* When provided, compression and decompression use the specified file as dictionary.
* Only one dictionary can be provided, in which case it's applied to all benchmarked files.
**/
int BMK_benchFiles(const char** fileNamesTable, unsigned nbFiles,
int cLevelStart, int cLevelLast,
const char* dictFileName);
/* Set Parameters */
void BMK_setNbSeconds(unsigned nbSeconds); /* minimum benchmark duration, in seconds, for both compression and decompression */
void BMK_setBlockSize(size_t blockSize); /* Internally cut input file(s) into independent blocks of specified size */
void BMK_setNotificationLevel(unsigned level); /* Influence verbosity level */
void BMK_setBenchSeparately(int separate); /* When providing multiple files, output one result per file */
void BMK_setDecodeOnlyMode(int set); /* v1.9.4+: set benchmark mode to decode only */
void BMK_skipChecksums(int skip); /* v1.9.4+: only useful for DecodeOnlyMode; do not calculate checksum when present, to save CPU time */
void BMK_setAdditionalParam(int additionalParam); /* hidden param, influence output format, for python parsing */
#endif /* BENCH_H_125623623633 */

366
expkg/vendor/lz4/programs/lorem.c vendored Normal file
View File

@ -0,0 +1,366 @@
/*
lorem.c - lorem ipsum generator
Copyright (c) Yann Collet. All rights reserved.
GPL v2 License
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
You can contact the author at :
- LZ4 source repository : https://github.com/lz4/lz4
- Public forum : https://groups.google.com/forum/#!forum/lz4c
*/
/* Implementation notes:
*
* This is a very simple lorem ipsum generator
* which features a static list of words
* and print them one after another randomly
* with a fake sentence / paragraph structure.
*
* The goal is to generate a printable text
* that can be used to fake a text compression scenario.
* The resulting compression / ratio curve of the lorem ipsum generator
* is more satisfying than the previous statistical generator,
* which was initially designed for entropy compression,
* and lacks a regularity more representative of text.
*
* The compression ratio achievable on the generated lorem ipsum
* is still a bit too good, presumably because the dictionary is a bit too
* small. It would be possible to create some more complex scheme, notably by
* enlarging the dictionary with a word generator, and adding grammatical rules
* (composition) and syntax rules. But that's probably overkill for the intended
* goal.
*/
#include "lorem.h"
#include <assert.h>
#include <limits.h> /* INT_MAX */
#include <stdlib.h> /* malloc, abort */
#include <string.h> /* memcpy */
/* Define the word pool
* Note: all words must have a len <= 16 */
static const char* kWords[] = {
"lorem", "ipsum", "dolor", "sit", "amet",
"consectetur", "adipiscing", "elit", "sed", "do",
"eiusmod", "tempor", "incididunt", "ut", "labore",
"et", "dolore", "magna", "aliqua", "dis",
"lectus", "vestibulum", "mattis", "ullamcorper", "velit",
"commodo", "a", "lacus", "arcu", "magnis",
"parturient", "montes", "nascetur", "ridiculus", "mus",
"mauris", "nulla", "malesuada", "pellentesque", "eget",
"gravida", "in", "dictum", "non", "erat",
"nam", "voluptat", "maecenas", "blandit", "aliquam",
"etiam", "enim", "lobortis", "scelerisque", "fermentum",
"dui", "faucibus", "ornare", "at", "elementum",
"eu", "facilisis", "odio", "morbi", "quis",
"eros", "donec", "ac", "orci", "purus",
"turpis", "cursus", "leo", "vel", "porta",
"consequat", "interdum", "varius", "vulputate", "aliquet",
"pharetra", "nunc", "auctor", "urna", "id",
"metus", "viverra", "nibh", "cras", "mi",
"unde", "omnis", "iste", "natus", "error",
"perspiciatis", "voluptatem", "accusantium", "doloremque", "laudantium",
"totam", "rem", "aperiam", "eaque", "ipsa",
"quae", "ab", "illo", "inventore", "veritatis",
"quasi", "architecto", "beatae", "vitae", "dicta",
"sunt", "explicabo", "nemo", "ipsam", "quia",
"voluptas", "aspernatur", "aut", "odit", "fugit",
"consequuntur", "magni", "dolores", "eos", "qui",
"ratione", "sequi", "nesciunt", "neque", "porro",
"quisquam", "est", "dolorem", "adipisci", "numquam",
"eius", "modi", "tempora", "incidunt", "magnam",
"quaerat", "ad", "minima", "veniam", "nostrum",
"ullam", "corporis", "suscipit", "laboriosam", "nisi",
"aliquid", "ex", "ea", "commodi", "consequatur",
"autem", "eum", "iure", "voluptate", "esse",
"quam", "nihil", "molestiae", "illum", "fugiat",
"quo", "pariatur", "vero", "accusamus", "iusto",
"dignissimos", "ducimus", "blanditiis", "praesentium", "voluptatum",
"deleniti", "atque", "corrupti", "quos", "quas",
"molestias", "excepturi", "sint", "occaecati", "cupiditate",
"provident", "similique", "culpa", "officia", "deserunt",
"mollitia", "animi", "laborum", "dolorum", "fuga",
"harum", "quidem", "rerum", "facilis", "expedita",
"distinctio", "libero", "tempore", "cum", "soluta",
"nobis", "eligendi", "optio", "cumque", "impedit",
"minus", "quod", "maxime", "placeat", "facere",
"possimus", "assumenda", "repellendus", "temporibus", "quibusdam",
"officiis", "debitis", "saepe", "eveniet", "voluptates",
"repudiandae", "recusandae", "itaque", "earum", "hic",
"tenetur", "sapiente", "delectus", "reiciendis", "cillum",
"maiores", "alias", "perferendis", "doloribus", "asperiores",
"repellat", "minim", "nostrud", "exercitation", "ullamco",
"laboris", "aliquip", "duis", "aute", "irure",
};
#define KNBWORDS (sizeof(kWords) / sizeof(kWords[0]))
static const unsigned kNbWords = KNBWORDS;
static const char* g_words[KNBWORDS] = { NULL };
static unsigned g_wordLen[KNBWORDS] = {0};
static char* g_wordBuffer = NULL;
/* simple 1-dimension distribution, based on word's length, favors small words
*/
static const int kWeights[] = { 0, 8, 6, 4, 3, 2 };
static const unsigned kNbWeights = sizeof(kWeights) / sizeof(kWeights[0]);
#define DISTRIB_SIZE_MAX 650
static int g_distrib[DISTRIB_SIZE_MAX] = { 0 };
static unsigned g_distribCount = 0;
static void countFreqs(
const unsigned wordLen[],
size_t nbWords,
const int* weights,
unsigned long nbWeights)
{
unsigned total = 0;
size_t w;
for (w = 0; w < nbWords; w++) {
size_t len = wordLen[w];
int lmax;
if (len >= nbWeights)
len = nbWeights - 1;
lmax = weights[len];
total += (unsigned)lmax;
}
g_distribCount = total;
assert(g_distribCount <= DISTRIB_SIZE_MAX);
}
static void init_word_len(
const char* words[],
size_t nbWords)
{
size_t n;
assert(words != NULL);
for (n=0; n<nbWords; n++) {
assert(words[n] != NULL);
assert(strlen(words[n]) < 256);
g_wordLen[n] = (unsigned char)strlen(words[n]);
}
}
static size_t sumLen(const unsigned* sizes, size_t s)
{
size_t total = 0;
size_t n;
assert(sizes != NULL);
for (n=0; n<s; n++) {
total += sizes[n];
}
return total;
}
static void init_word_buffer(void)
{
size_t n;
size_t const bufSize = sumLen(g_wordLen, kNbWords) + 16;
char* ptr;
assert(g_wordBuffer == NULL);
g_wordBuffer = (char*)calloc(1, bufSize);
if (g_wordBuffer == NULL) abort();
ptr = g_wordBuffer;
for (n=0; n<kNbWords; n++) {
memcpy(ptr, kWords[n], g_wordLen[n]);
g_words[n] = ptr;
ptr += g_wordLen[n];
}
}
static void init_word_distrib(
const unsigned wordLen[],
size_t nbWords,
const int* weights,
unsigned long nbWeights)
{
size_t w, d = 0;
countFreqs(wordLen, nbWords, weights, nbWeights);
for (w = 0; w < nbWords; w++) {
size_t len = wordLen[w];
int l, lmax;
if (len >= nbWeights)
len = nbWeights - 1;
lmax = weights[len];
for (l = 0; l < lmax; l++) {
g_distrib[d++] = (int)w;
}
}
}
/* Note: this unit only works when invoked sequentially.
* No concurrent access is allowed */
static char* g_ptr = NULL;
static size_t g_nbChars = 0;
static size_t g_maxChars = 10000000;
static unsigned g_randRoot = 0;
#define RDG_rotl32(x, r) ((x << r) | (x >> (32 - r)))
static unsigned LOREM_rand(unsigned range)
{
static const unsigned prime1 = 2654435761U;
static const unsigned prime2 = 2246822519U;
unsigned rand32 = g_randRoot;
rand32 *= prime1;
rand32 ^= prime2;
rand32 = RDG_rotl32(rand32, 13);
g_randRoot = rand32;
return (unsigned)(((unsigned long long)rand32 * range) >> 32);
}
static void writeLastCharacters(void)
{
size_t lastChars = g_maxChars - g_nbChars;
assert(g_maxChars >= g_nbChars);
if (lastChars == 0)
return;
g_ptr[g_nbChars++] = '.';
if (lastChars > 2) {
memset(g_ptr + g_nbChars, ' ', lastChars - 2);
}
if (lastChars > 1) {
g_ptr[g_maxChars - 1] = '\n';
}
g_nbChars = g_maxChars;
}
static void generateLastWord(const char* word, size_t wordLen, int upCase)
{
if (g_nbChars + wordLen + 2 > g_maxChars) {
writeLastCharacters();
return;
}
memcpy(g_ptr + g_nbChars, word, wordLen);
if (upCase) {
static const char toUp = 'A' - 'a';
g_ptr[g_nbChars] = (char)(g_ptr[g_nbChars] + toUp);
}
g_nbChars += wordLen;
writeLastCharacters();
}
#define MAX(a,b) ((a)<(b)?(b):(a))
static void generateWord(const char* word, size_t wordLen, const char* separator, size_t sepLen, int upCase)
{
size_t const wlen = MAX(16, wordLen + 2);
if (g_nbChars + wlen > g_maxChars) {
generateLastWord(word, wordLen, upCase);
return;
}
assert(wordLen <= 16);
memcpy(g_ptr + g_nbChars, word, 16);
if (upCase) {
static const char toUp = 'A' - 'a';
g_ptr[g_nbChars] = (char)(g_ptr[g_nbChars] + toUp);
}
g_nbChars += wordLen;
assert(sepLen <= 2);
memcpy(g_ptr + g_nbChars, separator, 2);
g_nbChars += sepLen;
}
static int about(unsigned target)
{
return (int)(LOREM_rand(target) + LOREM_rand(target) + 1);
}
/* Function to generate a random sentence */
static void generateSentence(int nbWords)
{
int commaPos = about(9);
int comma2 = commaPos + about(7);
int qmark = (LOREM_rand(11) == 7);
const char* endSep = qmark ? "? " : ". ";
int i;
for (i = 0; i < nbWords; i++) {
int const wordID = g_distrib[LOREM_rand(g_distribCount)];
const char* sep = " ";
size_t sepLen = 1;
if (i == commaPos)
sep = ", ", sepLen=2;
if (i == comma2)
sep = ", ", sepLen=2;
if (i == nbWords - 1)
sep = endSep, sepLen=2;
generateWord(g_words[wordID], g_wordLen[wordID], sep, sepLen, i == 0);
}
}
static void generateParagraph(int nbSentences)
{
int i;
for (i = 0; i < nbSentences; i++) {
int wordsPerSentence = about(11);
generateSentence(wordsPerSentence);
}
if (g_nbChars < g_maxChars) {
g_ptr[g_nbChars++] = '\n';
}
if (g_nbChars < g_maxChars) {
g_ptr[g_nbChars++] = '\n';
}
}
/* It's "common" for lorem ipsum generators to start with the same first
* pre-defined sentence */
static void generateFirstSentence(void)
{
int i;
for (i = 0; i < 18; i++) {
const char* separator = " ";
size_t sepLen = 1;
if (i == 4)
separator = ", ", sepLen=2;
if (i == 7)
separator = ", ", sepLen=2;
generateWord(g_words[i], g_wordLen[i], separator, sepLen, i == 0);
}
generateWord(g_words[18], g_wordLen[18], ". ", 2, 0);
}
size_t
LOREM_genBlock(void* buffer, size_t size, unsigned seed, int first, int fill)
{
g_ptr = (char*)buffer;
assert(size < INT_MAX);
g_maxChars = size;
g_nbChars = 0;
g_randRoot = seed;
if (g_distribCount == 0) {
init_word_len(kWords, kNbWords);
init_word_buffer();
init_word_distrib(g_wordLen, kNbWords, kWeights, kNbWeights);
}
if (first) {
generateFirstSentence();
}
while (g_nbChars < g_maxChars) {
int sentencePerParagraph = about(7);
generateParagraph(sentencePerParagraph);
if (!fill)
break; /* only generate one paragraph in not-fill mode */
}
g_ptr = NULL;
return g_nbChars;
}
void LOREM_genBuffer(void* buffer, size_t size, unsigned seed)
{
LOREM_genBlock(buffer, size, seed, 1, 1);
}

46
expkg/vendor/lz4/programs/lorem.h vendored Normal file
View File

@ -0,0 +1,46 @@
/*
lorem.h - lorem ipsum generator
Copyright (c) Yann Collet. All rights reserved.
GPL v2 License
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
You can contact the author at :
- LZ4 source repository : https://github.com/lz4/lz4
- Public forum : https://groups.google.com/forum/#!forum/lz4c
*/
#include <stddef.h> /* size_t */
/*
* LOREM_genBuffer():
* Generate @size bytes of compressible data using lorem ipsum generator
* into provided @buffer.
*/
void LOREM_genBuffer(void* buffer, size_t size, unsigned seed);
/*
* LOREM_genBlock():
* Similar to LOREM_genBuffer, with additional controls :
* - @first : generate the first sentence
* - @fill : fill the entire @buffer,
* if ==0: generate one paragraph at most.
* @return : nb of bytes generated into @buffer.
*/
size_t LOREM_genBlock(void* buffer, size_t size,
unsigned seed,
int first, int fill);

26
expkg/vendor/lz4/programs/lz4-exe.rc.in vendored Normal file
View File

@ -0,0 +1,26 @@
1 VERSIONINFO
FILEVERSION @LIBVER_MAJOR@,@LIBVER_MINOR@,@LIBVER_PATCH@,0
PRODUCTVERSION @LIBVER_MAJOR@,@LIBVER_MINOR@,@LIBVER_PATCH@,0
FILEFLAGSMASK 0
FILEOS 0x40000
FILETYPE 1
{
BLOCK "StringFileInfo"
{
BLOCK "040904B0"
{
VALUE "CompanyName", "Yann Collet"
VALUE "FileDescription", "Extremely fast compression"
VALUE "FileVersion", "@LIBVER_MAJOR@.@LIBVER_MINOR@.@LIBVER_PATCH@.0"
VALUE "InternalName", "@PROGNAME@"
VALUE "LegalCopyright", "Copyright (C) 2013-2020, Yann Collet"
VALUE "OriginalFilename", "@PROGNAME@.@EXT@"
VALUE "ProductName", "LZ4"
VALUE "ProductVersion", "@LIBVER_MAJOR@.@LIBVER_MINOR@.@LIBVER_PATCH@.0"
}
}
BLOCK "VarFileInfo"
{
VALUE "Translation", 0x0409, 1200
}
}

264
expkg/vendor/lz4/programs/lz4.1 vendored Normal file
View File

@ -0,0 +1,264 @@
.
.TH "LZ4" "1" "July 2024" "lz4 1.10.0" "User Commands"
.
.SH "NAME"
\fBlz4\fR \- lz4, unlz4, lz4cat \- Compress or decompress \.lz4 files
.
.SH "SYNOPSIS"
\fBlz4\fR [\fIOPTIONS\fR] [\-|INPUT\-FILE] \fIOUTPUT\-FILE\fR
.
.P
\fBunlz4\fR is equivalent to \fBlz4 \-d\fR
.
.P
\fBlz4cat\fR is equivalent to \fBlz4 \-dcfm\fR
.
.P
When writing scripts that need to decompress files, it is recommended to always use the name \fBlz4\fR with appropriate arguments (\fBlz4 \-d\fR or \fBlz4 \-dc\fR) instead of the names \fBunlz4\fR and \fBlz4cat\fR\.
.
.SH "DESCRIPTION"
\fBlz4\fR is a CLI based on \fBliblz4\fR, an extremely fast implementation of lossless compression algorithm\. It provides a default compression speed of typically > 500 MB/s per core\. Speed can traded for higher compression ratio, by increasing the compression level parameter\. While decompression is single\-threaded, it reaches multiple GB/s, generally fast enough to be I/O bound\. \fBlz4\fR native file format is the \fB\.lz4\fR format\.
.
.SS "Difference between lz4 and gzip"
\fBlz4\fR supports a command line syntax similar \fIbut not identical\fR to \fBgzip(1)\fR\. Differences are :
.
.IP "\(bu" 4
\fBlz4\fR compresses a single file by default (see \fB\-m\fR for multiple files)
.
.IP "\(bu" 4
\fBlz4 file1 file2\fR means : compress file1 \fIinto\fR file2
.
.IP "\(bu" 4
\fBlz4 file\.lz4\fR will default to decompression (use \fB\-z\fR to force compression)
.
.IP "\(bu" 4
\fBlz4\fR preserves original files (see \fB\-\-rm\fR to erase source file on completion)
.
.IP "\(bu" 4
\fBlz4\fR shows real\-time notification statistics during compression or decompression of a single file (use \fB\-q\fR to silence them)
.
.IP "\(bu" 4
When no destination is specified, result is sent on implicit output, which depends on \fBstdout\fR status\. When \fBstdout\fR \fIis Not the console\fR, it becomes the implicit output\. Otherwise, if \fBstdout\fR is the console, the implicit output is \fBfilename\.lz4\fR\.
.
.IP "\(bu" 4
It is considered bad practice to rely on implicit output in scripts\. because the script\'s environment may change\. Always use explicit output in scripts\. \fB\-c\fR ensures that output will be \fBstdout\fR\. Conversely, providing a destination name, or using \fB\-m\fR ensures that the output will be either the specified name, or \fBfilename\.lz4\fR respectively\.
.
.IP "" 0
.
.P
Default behaviors can be modified by opt\-in commands, detailed below\.
.
.IP "\(bu" 4
\fBlz4 \-m\fR makes it possible to provide multiple input filenames, which will be compressed into files using suffix \fB\.lz4\fR\. Progress notifications become disabled by default (use \fB\-v\fR to enable them)\. This mode has a behavior which more closely mimics \fBgzip\fR command line, with the main remaining difference being that source files are preserved by default\.
.
.IP "\(bu" 4
Similarly, \fBlz4 \-m \-d\fR can decompress multiple \fB*\.lz4\fR files\.
.
.IP "\(bu" 4
It\'s possible to opt\-in to erase source files on successful compression or decompression, using \fB\-\-rm\fR command\.
.
.IP "\(bu" 4
Consequently, \fBlz4 \-m \-\-rm\fR features a behavior closer to the \fBgzip\fR one\.
.
.IP "" 0
.
.SS "Concatenation of \.lz4 files"
It is possible to concatenate \fB\.lz4\fR files as is\. \fBlz4\fR will decompress such files as if they were a single \fB\.lz4\fR file\. For example:
.
.IP "" 4
.
.nf
lz4 file1 > foo\.lz4
lz4 file2 >> foo\.lz4
.
.fi
.
.IP "" 0
.
.P
Then \fBlz4cat foo\.lz4\fR is equivalent to \fBcat file1 file2\fR\.
.
.SH "OPTIONS"
.
.SS "Short commands concatenation"
In some cases, some options can be expressed using short command \fB\-x\fR or long command \fB\-\-long\-word\fR\. Short commands can be concatenated together\. For example, \fB\-d \-c\fR is equivalent to \fB\-dc\fR\. Long commands cannot be concatenated\. They must be clearly separated by a space\.
.
.SS "Multiple commands"
When multiple contradictory commands are issued on a same command line, only the latest one will be applied\.
.
.SS "Operation mode"
.
.TP
\fB\-z\fR \fB\-\-compress\fR
Compress\. This is the default operation mode when no operation mode option is specified, no other operation mode is implied from the command name (for example, \fBunlz4\fR implies \fB\-\-decompress\fR), nor from the input file name (for example, a file extension \fB\.lz4\fR implies \fB\-\-decompress\fR by default)\. \fB\-z\fR can also be used to force compression of an already compressed \fB\.lz4\fR file\.
.
.TP
\fB\-d\fR \fB\-\-decompress\fR \fB\-\-uncompress\fR
Decompress\. \fB\-\-decompress\fR is also the default operation when the input filename has an \fB\.lz4\fR extension\.
.
.TP
\fB\-t\fR \fB\-\-test\fR
Test the integrity of compressed \fB\.lz4\fR files\. The decompressed data is discarded\. No files are created nor removed\.
.
.TP
\fB\-b#\fR
Benchmark mode, using \fB#\fR compression level\.
.
.TP
\fB\-\-list\fR
List information about \.lz4 files\. For detailed information on files with multiple frames, use \fB\-v\fR\. \fB\-\-list\fR automatically triggers \fB\-m\fR modifier\.
.
.SS "Operation modifiers"
.
.TP
\fB\-#\fR
Compression level, with # being any value from 1 to 12\. Higher values trade compression speed for compression ratio\. Values above 12 are considered the same as 12\. Recommended values are 1 for fast compression (default), and 9 for high compression\. Speed/compression trade\-off will vary depending on data to compress\. Decompression speed remains fast at all settings\.
.
.TP
\fB\-\-fast[=#]\fR
Switch to ultra\-fast compression levels\. The higher the value, the faster the compression speed, at the cost of some compression ratio\. If \fB=#\fR is not present, it defaults to \fB1\fR\. This setting overrides compression level if one was set previously\. Similarly, if a compression level is set after \fB\-\-fast\fR, it overrides it\.
.
.TP
\fB\-\-best\fR
Set highest compression level\. Same as \-12\.
.
.TP
\fB\-T#\fR, \fB\-\-threads=#\fR
Use \fB#\fR threads for compression\. When \fB0\fR, or none provided: automatically determined from nb of detected cores\.
.
.TP
\fB\-\-favor\-decSpeed\fR
Generate compressed data optimized for decompression speed\. Compressed data will be larger as a consequence (typically by ~0\.5%), while decompression speed will be improved by 5\-20%, depending on use cases\. This option only works in combination with very high compression levels (>=10)\.
.
.TP
\fB\-D dictionaryName\fR
Compress, decompress or benchmark using dictionary \fIdictionaryName\fR\. Compression and decompression must use the same dictionary to be compatible\. Using a different dictionary during decompression will either abort due to decompression error, or generate a checksum error\.
.
.TP
\fB\-f\fR \fB\-\-[no\-]force\fR
This option has several effects:
.
.IP
If the target file already exists, overwrite it without prompting\.
.
.IP
When used with \fB\-\-decompress\fR and \fBlz4\fR cannot recognize the type of the source file, copy the source file as is to standard output\. This allows \fBlz4cat \-\-force\fR to be used like \fBcat (1)\fR for files that have not been compressed with \fBlz4\fR\.
.
.TP
\fB\-c\fR \fB\-\-stdout\fR \fB\-\-to\-stdout\fR
Force write to standard output, even if it is the console\.
.
.TP
\fB\-m\fR \fB\-\-multiple\fR
Multiple input files\. Compressed file names will be appended a \fB\.lz4\fR suffix\. This mode also reduces notification level\. Can also be used to list multiple files\. \fBlz4 \-m\fR has a behavior equivalent to \fBgzip \-k\fR (it preserves source files by default)\.
.
.TP
\fB\-r\fR
operate recursively on directories\. This mode also sets \fB\-m\fR (multiple input files)\.
.
.TP
\fB\-B#\fR
Block size [4\-7](default : 7)
.
.br
\fB\-B4\fR= 64KB ; \fB\-B5\fR= 256KB ; \fB\-B6\fR= 1MB ; \fB\-B7\fR= 4MB
.
.TP
\fB\-BI\fR
Produce independent blocks (default)
.
.TP
\fB\-BD\fR
Blocks depend on predecessors (improves compression ratio, more noticeable on small blocks)
.
.TP
\fB\-BX\fR
Generate block checksums (default:disabled)
.
.TP
\fB\-\-[no\-]frame\-crc\fR
Select frame checksum (default:enabled)
.
.TP
\fB\-\-no\-crc\fR
Disable both frame and block checksums
.
.TP
\fB\-\-[no\-]content\-size\fR
Header includes original size (default:not present)
.
.br
Note : this option can only be activated when the original size can be determined, hence for a file\. It won\'t work with unknown source size, such as stdin or pipe\.
.
.TP
\fB\-\-[no\-]sparse\fR
Sparse mode support (default:enabled on file, disabled on stdout)
.
.TP
\fB\-l\fR
Use Legacy format (typically for Linux Kernel compression)
.
.br
Note : \fB\-l\fR is not compatible with \fB\-m\fR (\fB\-\-multiple\fR) nor \fB\-r\fR
.
.SS "Other options"
.
.TP
\fB\-v\fR \fB\-\-verbose\fR
Verbose mode
.
.TP
\fB\-q\fR \fB\-\-quiet\fR
Suppress warnings and real\-time statistics; specify twice to suppress errors too
.
.TP
\fB\-h\fR \fB\-H\fR \fB\-\-help\fR
Display help/long help and exit
.
.TP
\fB\-V\fR \fB\-\-version\fR
Display Version number and exit
.
.TP
\fB\-k\fR \fB\-\-keep\fR
Preserve source files (default behavior)
.
.TP
\fB\-\-rm\fR
Delete source files on successful compression or decompression
.
.TP
\fB\-\-\fR
Treat all subsequent arguments as files
.
.SS "Benchmark mode"
.
.TP
\fB\-b#\fR
Benchmark file(s), using # compression level
.
.TP
\fB\-e#\fR
Benchmark multiple compression levels, from b# to e# (included)
.
.TP
\fB\-i#\fR
Minimum evaluation time in seconds [1\-9] (default : 3)
.
.SS "Environment Variables"
It\'s possible to pass some parameters to \fBlz4\fR via environment variables\. This can be useful in situations where \fBlz4\fR is known to be invoked (from a script for example) but there is no way to pass \fBlz4\fR parameters to influence the compression session\. The environment variable has higher priority than executable default, but lower priority than corresponding runtime command\. When set as global environment variables, it can be a way to enforce personalized defaults different from the executable set ones\.
.
.TP
\fBLZ4_CLEVEL\fR
specify a default compression level that \fBlz4\fR employs for compression when no other compression level is specified on command line\. Executable default is generally \fB1\fR\.
.
.TP
\fBLZ4_NBWORKERS\fR
specify a default number of threads that \fBlz4\fR will employ for compression\. Executable default is generally \fB0\fR, which means auto\-determined based on local cpu\. This functionality is only relevant when \fBlz4\fR is compiled with multithreading support\. The maximum number of workers is capped at \fBLZ4_NBWORKERS_MAX\fR (\fB200\fR by default)\.
.
.SH "BUGS"
Report bugs at: https://github\.com/lz4/lz4/issues
.
.SH "AUTHOR"
Yann Collet

273
expkg/vendor/lz4/programs/lz4.1.md vendored Normal file
View File

@ -0,0 +1,273 @@
lz4(1) -- lz4, unlz4, lz4cat - Compress or decompress .lz4 files
================================================================
SYNOPSIS
--------
`lz4` [*OPTIONS*] [-|INPUT-FILE] <OUTPUT-FILE>
`unlz4` is equivalent to `lz4 -d`
`lz4cat` is equivalent to `lz4 -dcfm`
When writing scripts that need to decompress files,
it is recommended to always use the name `lz4` with appropriate arguments
(`lz4 -d` or `lz4 -dc`) instead of the names `unlz4` and `lz4cat`.
DESCRIPTION
-----------
`lz4` is a CLI based on `liblz4`, an extremely fast implementation of lossless compression algorithm.
It provides a default compression speed of typically > 500 MB/s per core.
Speed can traded for better compression ratio, by increasing the compression level parameter.
While decompression is single-threaded, it reaches multiple GB/s, generally fast enough to be I/O bound.
`lz4` native file format is the `.lz4` format.
### Difference between lz4 and gzip
`lz4` supports a command line syntax similar _but not identical_ to `gzip(1)`.
Differences are :
* `lz4` compresses a single file by default (see `-m` for multiple files)
* `lz4 file1 file2` means : compress file1 _into_ file2
* `lz4 file.lz4` will default to decompression (use `-z` to force compression)
* `lz4` preserves original files (see `--rm` to erase source file on completion)
* `lz4` shows real-time notification statistics
during compression or decompression of a single file
(use `-q` to silence them)
* When no destination is specified, result is sent on implicit output,
which depends on `stdout` status.
When `stdout` _is Not the console_, it becomes the implicit output.
Otherwise, if `stdout` is the console, the implicit output is `filename.lz4`.
* It is considered bad practice to rely on implicit output in scripts.
because the script's environment may change.
Always use explicit output in scripts.
`-c` ensures that output will be `stdout`.
Conversely, providing a destination name, or using `-m`
ensures that the output will be either the specified name, or `filename.lz4` respectively.
Default behaviors can be modified by opt-in commands, detailed below.
* `lz4 -m` makes it possible to provide multiple input filenames,
which will be compressed into files using suffix `.lz4`.
Progress notifications become disabled by default (use `-v` to enable them).
This mode has a behavior which more closely mimics `gzip` command line,
with the main remaining difference being that source files are preserved by default.
* Similarly, `lz4 -m -d` can decompress multiple `*.lz4` files.
* It's possible to opt-in to erase source files
on successful compression or decompression, using `--rm` command.
* Consequently, `lz4 -m --rm` features a behavior closer to the `gzip` one.
### Concatenation of .lz4 files
It is possible to concatenate `.lz4` files as is.
`lz4` will decompress such files as if they were a single `.lz4` file.
For example:
lz4 file1 > foo.lz4
lz4 file2 >> foo.lz4
Then `lz4cat foo.lz4` is equivalent to `cat file1 file2`.
OPTIONS
-------
### Short commands concatenation
In some cases, some options can be expressed using short command `-x`
or long command `--long-word`.
Short commands can be concatenated together.
For example, `-d -c` is equivalent to `-dc`.
Long commands cannot be concatenated. They must be clearly separated by a space.
### Multiple commands
When multiple contradictory commands are issued on a same command line,
only the latest one will be applied.
### Operation mode
* `-z` `--compress`:
Compress.
This is the default operation mode when no operation mode option is
specified, no other operation mode is implied from the command name
(for example, `unlz4` implies `--decompress`),
nor from the input file name
(for example, a file extension `.lz4` implies `--decompress` by default).
`-z` can also be used to force compression of an already compressed
`.lz4` file.
* `-d` `--decompress` `--uncompress`:
Decompress.
`--decompress` is also the default operation when the input filename has an
`.lz4` extension.
* `-t` `--test`:
Test the integrity of compressed `.lz4` files.
The decompressed data is discarded.
No files are created nor removed.
* `-b#`:
Benchmark mode, using `#` compression level.
* `--list`:
List information about .lz4 files.
For detailed information on files with multiple frames, use `-v`.
`--list` automatically triggers `-m` modifier.
### Operation modifiers
* `-#`:
Compression level, with # being any value from 1 to 12.
Higher values trade compression speed for better compression ratio.
Values above 12 are considered the same as 12.
Recommended values are 1 for fast compression (default),
and 9 for high compression.
Speed/compression trade-off will vary depending on data to compress.
Decompression speed remains fast at all settings.
* `--fast[=#]`:
Switch to ultra-fast compression levels.
The higher the value, the faster the compression speed, but at the cost of compressed size.
If `=#` is not present, it defaults to `1`.
This setting overrides compression level if one was set previously.
Similarly, if a compression level is set after `--fast`, it overrides it.
* `--best`:
Set highest compression level. Same as -12.
* `-T#`, `--threads=#`:
Use `#` threads for compression.
When `0`, or none provided: automatically determined from nb of detected cores.
* `--favor-decSpeed`:
Generate compressed data optimized for decompression speed.
Compressed data will be larger as a consequence (typically by ~0.5%),
while decompression speed will be improved by 5-20%, depending on use cases.
This option only works in combination with very high compression levels (>=10).
* `-D dictionaryName`:
Compress, decompress or benchmark using dictionary _dictionaryName_.
Compression and decompression must use the same dictionary to be compatible.
Using a different dictionary during decompression will either
abort due to decompression error, or generate a checksum error.
* `-f` `--[no-]force`:
This option has several effects:
If the target file already exists, overwrite it without prompting.
When used with `--decompress` and `lz4` cannot recognize the type of
the source file, copy the source file as is to standard output.
This allows `lz4cat --force` to be used like `cat (1)` for files
that have not been compressed with `lz4`.
* `-c` `--stdout` `--to-stdout`:
Force write to standard output, even if it is the console.
* `-m` `--multiple`:
Multiple input files.
Compressed file names will be appended a `.lz4` suffix.
This mode also reduces notification level.
Can also be used to list multiple files.
`lz4 -m` has a behavior equivalent to `gzip -k`
(it preserves source files by default).
* `-r` :
operate recursively on directories.
This mode also sets `-m` (multiple input files).
* `-B#`:
Block size \[4-7\](default : 7)<br/>
`-B4`= 64KB ; `-B5`= 256KB ; `-B6`= 1MB ; `-B7`= 4MB
* `-BI`:
Produce independent blocks (default)
* `-BD`:
Blocks depend on predecessors (improves compression ratio, more noticeable on small blocks)
* `-BX`:
Generate block checksums (default:disabled)
* `--[no-]frame-crc`:
Select frame checksum (default:enabled)
* `--no-crc`:
Disable both frame and block checksums
* `--[no-]content-size`:
Header includes original size (default:not present)<br/>
Note : this option can only be activated when the original size can be
determined, hence for a file. It won't work with unknown source size,
such as stdin or pipe.
* `--[no-]sparse`:
Sparse mode support (default:enabled on file, disabled on stdout)
* `-l`:
Use Legacy format (typically for Linux Kernel compression)<br/>
Note : `-l` is not compatible with `-m` (`--multiple`) nor `-r`
### Other options
* `-v` `--verbose`:
Verbose mode
* `-q` `--quiet`:
Suppress warnings and real-time statistics;
specify twice to suppress errors too
* `-h` `-H` `--help`:
Display help/long help and exit
* `-V` `--version`:
Display Version number and exit
* `-k` `--keep`:
Preserve source files (default behavior)
* `--rm` :
Delete source files on successful compression or decompression
* `--` :
Treat all subsequent arguments as files
### Benchmark mode
* `-b#`:
Benchmark file(s), using # compression level
* `-e#`:
Benchmark multiple compression levels, from b# to e# (included)
* `-i#`:
Minimum evaluation time in seconds \[1-9\] (default : 3)
### Environment Variables
It's possible to pass some parameters to `lz4` via environment variables.
This can be useful in situations where `lz4` is known to be invoked (from a script for example) but there is no way to pass `lz4` parameters to influence the compression session.
The environment variable has higher priority than executable default, but lower priority than corresponding runtime command.
When set as global environment variables, it can be a way to enforce personalized defaults different from the executable set ones.
* `LZ4_CLEVEL`:
specify a default compression level that `lz4` employs for compression when no other compression level is specified on command line. Executable default is generally `1`.
* `LZ4_NBWORKERS`:
specify a default number of threads that `lz4` will employ for compression. Executable default is generally `0`, which means auto-determined based on local cpu. This functionality is only relevant when `lz4` is compiled with multithreading support. The maximum number of workers is capped at `LZ4_NBWORKERS_MAX` (`200` by default).
BUGS
----
Report bugs at: https://github.com/lz4/lz4/issues
AUTHOR
------
Yann Collet

892
expkg/vendor/lz4/programs/lz4cli.c vendored Normal file
View File

@ -0,0 +1,892 @@
/*
LZ4cli - LZ4 Command Line Interface
Copyright (c) Yann Collet. All rights reserved.
GPL v2 License
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
You can contact the author at :
- LZ4 source repository : https://github.com/lz4/lz4
- LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
*/
/*
Note : this is stand-alone program.
It is not part of LZ4 compression library, it is a user program of the LZ4 library.
The license of LZ4 library is BSD.
The license of xxHash library is BSD.
The license of this compression CLI program is GPLv2.
*/
/*-************************************
* Compiler options
**************************************/
#ifdef _MSC_VER /* Visual Studio */
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
#endif
/****************************
* Includes
*****************************/
#include "platform.h" /* Compiler options, IS_CONSOLE */
#include "util.h" /* UTIL_HAS_CREATEFILELIST, UTIL_createFileList */
#include <stdio.h> /* fprintf, getchar */
#include <stdlib.h> /* exit, calloc, free */
#include <string.h> /* strcmp, strlen */
#include "lz4conf.h" /* compile-time constants */
#include "bench.h" /* BMK_benchFile, BMK_SetNbIterations, BMK_SetBlocksize, BMK_SetPause */
#include "lz4io.h" /* LZ4IO_compressFilename, LZ4IO_decompressFilename, LZ4IO_compressMultipleFilenames */
#include "lz4hc.h" /* LZ4HC_CLEVEL_MAX */
#include "lz4.h" /* LZ4_VERSION_STRING */
/*****************************
* Constants
******************************/
#if LZ4IO_MULTITHREAD
# define IO_MT "multithread"
#else
# define IO_MT "single-thread"
#endif
#define COMPRESSOR_NAME "lz4"
#define AUTHOR "Yann Collet"
#define WELCOME_MESSAGE "*** %s v%s %i-bit %s, by %s ***\n", COMPRESSOR_NAME, LZ4_versionString(), (int)(sizeof(void*)*8), IO_MT, AUTHOR
#define LZ4_EXTENSION ".lz4"
#define LZ4CAT "lz4cat"
#define UNLZ4 "unlz4"
#define LZ4_LEGACY "lz4c"
static int g_lz4c_legacy_commands = 0;
#define KB *(1U<<10)
#define MB *(1U<<20)
#define GB *(1U<<30)
/*-************************************
* Macros
***************************************/
#define DISPLAYOUT(...) fprintf(stdout, __VA_ARGS__)
#define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
#define DISPLAYLEVEL(l, ...) do { if (displayLevel>=l) DISPLAY(__VA_ARGS__); } while (0)
static unsigned displayLevel = 2; /* 0 : no display ; 1: errors only ; 2 : downgradable normal ; 3 : non-downgradable normal; 4 : + information */
/*-************************************
* Errors and Messages
***************************************/
#ifndef DEBUG
# define DEBUG 0
#endif
#define DEBUGOUTPUT(...) do { if (DEBUG) DISPLAY(__VA_ARGS__); } while (0)
#define END_PROCESS(error, ...) \
do { \
DEBUGOUTPUT("Error in %s, line %i : \n", __FILE__, __LINE__); \
DISPLAYLEVEL(1, "Error %i : ", error); \
DISPLAYLEVEL(1, __VA_ARGS__); \
DISPLAYLEVEL(1, "\n"); \
exit(error); \
} while (0)
static void errorOut(const char* msg)
{
DISPLAYLEVEL(1, "%s \n", msg); exit(1);
}
/*-************************************
* Version modifiers
***************************************/
#define DEFAULT_COMPRESSOR LZ4IO_compressFilename
#define DEFAULT_DECOMPRESSOR LZ4IO_decompressFilename
int LZ4IO_compressFilename_Legacy(const char* input_filename, const char* output_filename, int compressionlevel, const LZ4IO_prefs_t* prefs); /* hidden function */
int LZ4IO_compressMultipleFilenames_Legacy(
const char** inFileNamesTable, int ifntSize,
const char* suffix,
int compressionLevel, const LZ4IO_prefs_t* prefs);
/*-***************************
* Functions
*****************************/
static int usage(const char* exeName)
{
DISPLAY( "Usage : \n");
DISPLAY( " %s [arg] [input] [output] \n", exeName);
DISPLAY( "\n");
DISPLAY( "input : a filename \n");
DISPLAY( " with no FILE, or when FILE is - or %s, read standard input\n", stdinmark);
DISPLAY( "Arguments : \n");
DISPLAY( " -1 : fast compression (default) \n");
DISPLAY( " -%2d : slowest compression level \n", LZ4HC_CLEVEL_MAX);
#if LZ4IO_MULTITHREAD
DISPLAY( " -T# : use # threads for compression (default:%i==auto) \n", LZ4_NBWORKERS_DEFAULT);
#endif
DISPLAY( " -d : decompression (default for %s extension)\n", LZ4_EXTENSION);
DISPLAY( " -f : overwrite output without prompting \n");
DISPLAY( " -k : preserve source files(s) (default) \n");
DISPLAY( "--rm : remove source file(s) after successful de/compression \n");
DISPLAY( " -h/-H : display help/long help and exit \n");
return 0;
}
static int usage_advanced(const char* exeName)
{
DISPLAY(WELCOME_MESSAGE);
usage(exeName);
DISPLAY( "\n");
DISPLAY( "Advanced arguments :\n");
DISPLAY( " -V : display Version number and exit \n");
DISPLAY( " -v : verbose mode \n");
DISPLAY( " -q : suppress warnings; specify twice to suppress errors too\n");
DISPLAY( " -c : force write to standard output, even if it is the console\n");
DISPLAY( " -t : test compressed file integrity\n");
DISPLAY( " -m : multiple input files (implies automatic output filenames)\n");
#ifdef UTIL_HAS_CREATEFILELIST
DISPLAY( " -r : operate recursively on directories (sets also -m) \n");
#endif
DISPLAY( " -l : compress using Legacy format (Linux kernel compression)\n");
DISPLAY( " -z : force compression \n");
DISPLAY( " -D FILE: use FILE as dictionary (compression & decompression)\n");
DISPLAY( " -B# : cut file into blocks of size # bytes [32+] \n");
DISPLAY( " or predefined block size [4-7] (default: %i) \n", LZ4_BLOCKSIZEID_DEFAULT);
DISPLAY( " -BI : Block Independence (default) \n");
DISPLAY( " -BD : Block dependency (improves compression ratio) \n");
DISPLAY( " -BX : enable block checksum (default:disabled) \n");
DISPLAY( "--no-frame-crc : disable stream checksum (default:enabled) \n");
DISPLAY( "--content-size : compressed frame includes original size (default:not present)\n");
DISPLAY( "--list FILE : lists information about .lz4 files (useful for files compressed with --content-size flag)\n");
DISPLAY( "--[no-]sparse : sparse mode (default:enabled on file, disabled on stdout)\n");
DISPLAY( "--favor-decSpeed: compressed files decompress faster, but are less compressed \n");
DISPLAY( "--fast[=#]: switch to ultra fast compression level (default: %i)\n", 1);
DISPLAY( "--best : same as -%d\n", LZ4HC_CLEVEL_MAX);
DISPLAY( "Benchmark arguments : \n");
DISPLAY( " -b# : benchmark file(s), using # compression level (default : 1) \n");
DISPLAY( " -e# : test all compression levels from -bX to # (default : 1)\n");
DISPLAY( " -i# : minimum evaluation time in seconds (default : 3s) \n");
if (g_lz4c_legacy_commands) {
DISPLAY( "Legacy arguments : \n");
DISPLAY( " -c0 : fast compression \n");
DISPLAY( " -c1 : high compression \n");
DISPLAY( " -c2,-hc: very high compression \n");
DISPLAY( " -y : overwrite output without prompting \n");
}
return 0;
}
static int usage_longhelp(const char* exeName)
{
usage_advanced(exeName);
DISPLAY( "\n");
DISPLAY( "****************************\n");
DISPLAY( "***** Advanced comment *****\n");
DISPLAY( "****************************\n");
DISPLAY( "\n");
DISPLAY( "Which values can [output] have ? \n");
DISPLAY( "---------------------------------\n");
DISPLAY( "[output] : a filename \n");
DISPLAY( " '%s', or '-' for standard output (pipe mode)\n", stdoutmark);
DISPLAY( " '%s' to discard output (test mode) \n", NULL_OUTPUT);
DISPLAY( "[output] can be left empty. In this case, it receives the following value :\n");
DISPLAY( " - if stdout is not the console, then [output] = stdout \n");
DISPLAY( " - if stdout is console : \n");
DISPLAY( " + for compression, output to filename%s \n", LZ4_EXTENSION);
DISPLAY( " + for decompression, output to filename without '%s'\n", LZ4_EXTENSION);
DISPLAY( " > if input filename has no '%s' extension : error \n", LZ4_EXTENSION);
DISPLAY( "\n");
DISPLAY( "Compression levels : \n");
DISPLAY( "---------------------\n");
DISPLAY( "-0 => Default level, identical to -%u \n", LZ4_CLEVEL_DEFAULT);
DISPLAY( "-1 => Fast compression \n");
DISPLAY( "-2 .. -%d => High compression; higher number == more compression but slower\n", LZ4HC_CLEVEL_MAX);
DISPLAY( "--best => Highest available compression level (-%d) \n", LZ4HC_CLEVEL_MAX);
DISPLAY( "--fast=# => Faster compression; higher number == faster but compress less\n");
DISPLAY( "\n");
DISPLAY( "stdin, stdout and the console : \n");
DISPLAY( "--------------------------------\n");
DISPLAY( "To protect the console from binary flooding (bad argument mistake)\n");
DISPLAY( "%s will refuse to read from console, or write to console \n", exeName);
DISPLAY( "except if '-c' command is specified, to force output to console \n");
DISPLAY( "\n");
DISPLAY( "Simple example :\n");
DISPLAY( "----------------\n");
DISPLAY( "1 : compress 'filename' fast, using default output name 'filename.lz4'\n");
DISPLAY( " %s filename\n", exeName);
DISPLAY( "\n");
DISPLAY( "Short arguments can be aggregated. For example :\n");
DISPLAY( "----------------------------------\n");
DISPLAY( "2 : compress 'filename' in high compression mode, overwrite output if exists\n");
DISPLAY( " %s -9 -f filename \n", exeName);
DISPLAY( " is equivalent to :\n");
DISPLAY( " %s -9f filename \n", exeName);
DISPLAY( "\n");
DISPLAY( "%s can be used in 'pure pipe mode'. For example :\n", exeName);
DISPLAY( "-------------------------------------\n");
DISPLAY( "3 : compress data stream from 'generator', send result to 'consumer'\n");
DISPLAY( " generator | %s | consumer \n", exeName);
if (g_lz4c_legacy_commands) {
DISPLAY( "\n");
DISPLAY( "***** Warning ***** \n");
DISPLAY( "Legacy arguments take precedence. Therefore : \n");
DISPLAY( "--------------------------------- \n");
DISPLAY( " %s -hc filename \n", exeName);
DISPLAY( "means 'compress filename in high compression mode' \n");
DISPLAY( "It is not equivalent to : \n");
DISPLAY( " %s -h -c filename \n", exeName);
DISPLAY( "which displays help text and exits \n");
}
return 0;
}
static int badusage(const char* exeName)
{
DISPLAYLEVEL(1, "Incorrect parameters\n");
if (displayLevel >= 1) usage(exeName);
exit(1);
}
static void waitEnter(void)
{
DISPLAY("Press enter to continue...\n");
(void)getchar();
}
static const char* lastNameFromPath(const char* path)
{
const char* name = path;
if (strrchr(name, '/')) name = strrchr(name, '/') + 1;
if (strrchr(name, '\\')) name = strrchr(name, '\\') + 1; /* windows */
return name;
}
/*! exeNameMatch() :
@return : a non-zero value if exeName matches test, excluding the extension
*/
static int exeNameMatch(const char* exeName, const char* test)
{
return !strncmp(exeName, test, strlen(test)) &&
(exeName[strlen(test)] == '\0' || exeName[strlen(test)] == '.');
}
/*! readU32FromChar() :
* @return : unsigned integer value read from input in `char` format
* allows and interprets K, KB, KiB, M, MB and MiB suffix.
* Will also modify `*stringPtr`, advancing it to position where it stopped reading.
* Note : function result can overflow if digit string > MAX_UINT */
static unsigned readU32FromChar(const char** stringPtr)
{
unsigned result = 0;
while ((**stringPtr >='0') && (**stringPtr <='9')) {
result *= 10;
result += (unsigned)(**stringPtr - '0');
(*stringPtr)++ ;
}
if ((**stringPtr=='K') || (**stringPtr=='M')) {
result <<= 10;
if (**stringPtr=='M') result <<= 10;
(*stringPtr)++ ;
if (**stringPtr=='i') (*stringPtr)++;
if (**stringPtr=='B') (*stringPtr)++;
}
return result;
}
#define CLEAN_RETURN(i) { operationResult = (i); goto _cleanup; }
#define NEXT_FIELD(ptr) { \
if (*argument == '=') { \
ptr = ++argument; \
argument += strlen(ptr); \
} else { \
argNb++; \
if (argNb >= argCount) { \
DISPLAYLEVEL(1, "error: missing command argument \n"); \
CLEAN_RETURN(1); \
} \
ptr = argv[argNb]; \
assert(ptr != NULL); \
if (ptr[0]=='-') { \
DISPLAYLEVEL(1, "error: command cannot be separated from its argument by another command \n"); \
CLEAN_RETURN(1); \
} } }
#define NEXT_UINT32(val32) { \
const char* __nb; \
NEXT_FIELD(__nb); \
val32 = readU32FromChar(&__nb); \
if(*__nb != 0) { \
errorOut("error: only numeric values with optional suffixes K, KB, KiB, M, MB, MiB are allowed"); \
} \
}
/** longCommandWArg() :
* check if *stringPtr is the same as longCommand.
* If yes, @return 1 and advances *stringPtr to the position which immediately follows longCommand.
* @return 0 and doesn't modify *stringPtr otherwise.
*/
static int longCommandWArg(const char** stringPtr, const char* longCommand)
{
size_t const comSize = strlen(longCommand);
int const result = !strncmp(*stringPtr, longCommand, comSize);
if (result) *stringPtr += comSize;
return result;
}
typedef enum { om_auto, om_compress, om_decompress, om_test, om_bench, om_list } operationMode_e;
/** determineOpMode() :
* auto-determine operation mode, based on input filename extension
* @return `om_decompress` if input filename has .lz4 extension and `om_compress` otherwise.
*/
static operationMode_e determineOpMode(const char* inputFilename)
{
size_t const inSize = strlen(inputFilename);
size_t const extSize = strlen(LZ4_EXTENSION);
size_t const extStart= (inSize > extSize) ? inSize-extSize : 0;
if (!strcmp(inputFilename+extStart, LZ4_EXTENSION)) return om_decompress;
else return om_compress;
}
#define ENV_NBTHREADS "LZ4_NBWORKERS"
static unsigned init_nbWorkers(void)
{
const char* const env = getenv(ENV_NBTHREADS);
if (env != NULL) {
const char* ptr = env;
if ((*ptr>='0') && (*ptr<='9')) {
return readU32FromChar(&ptr);
}
DISPLAYLEVEL(2, "Ignore environment variable setting %s=%s: not a valid unsigned value \n", ENV_NBTHREADS, env);
}
return LZ4_NBWORKERS_DEFAULT;
}
#define ENV_CLEVEL "LZ4_CLEVEL"
static int init_cLevel(void)
{
const char* const env = getenv(ENV_CLEVEL);
if (env != NULL) {
const char* ptr = env;
if ((*ptr>='0') && (*ptr<='9')) {
return (int)readU32FromChar(&ptr);
}
DISPLAYLEVEL(2, "Ignore environment variable setting %s=%s: not a valid unsigned value \n", ENV_CLEVEL, env);
}
return LZ4_CLEVEL_DEFAULT;
}
int main(int argCount, const char** argv)
{
int argNb,
cLevel=init_cLevel(),
cLevelLast=-10000,
legacy_format=0,
forceStdout=0,
forceOverwrite=0,
main_pause=0,
multiple_inputs=0,
all_arguments_are_files=0,
operationResult=0;
unsigned nbWorkers = init_nbWorkers();
operationMode_e mode = om_auto;
const char* input_filename = NULL;
const char* output_filename= NULL;
const char* dictionary_filename = NULL;
char* dynNameSpace = NULL;
const char** inFileNames = (const char**)calloc((size_t)argCount, sizeof(char*));
unsigned ifnIdx=0;
LZ4IO_prefs_t* const prefs = LZ4IO_defaultPreferences();
const char nullOutput[] = NULL_OUTPUT;
const char extension[] = LZ4_EXTENSION;
size_t blockSize = LZ4IO_setBlockSizeID(prefs, LZ4_BLOCKSIZEID_DEFAULT);
const char* const exeName = lastNameFromPath(argv[0]);
char* fileNamesBuf = NULL;
#ifdef UTIL_HAS_CREATEFILELIST
unsigned fileNamesNb, recursive=0;
#endif
/* Init */
if (inFileNames==NULL) {
DISPLAY("Allocation error : not enough memory \n");
operationResult = 1;
goto _cleanup;
}
inFileNames[0] = stdinmark;
LZ4IO_setOverwrite(prefs, 0);
/* predefined behaviors, based on binary/link name */
if (exeNameMatch(exeName, LZ4CAT)) {
mode = om_decompress;
LZ4IO_setOverwrite(prefs, 1);
LZ4IO_setPassThrough(prefs, 1);
LZ4IO_setRemoveSrcFile(prefs, 0);
forceStdout=1;
output_filename=stdoutmark;
displayLevel=1;
multiple_inputs=1;
}
if (exeNameMatch(exeName, UNLZ4)) { mode = om_decompress; }
if (exeNameMatch(exeName, LZ4_LEGACY)) { g_lz4c_legacy_commands=1; }
/* command switches */
for(argNb=1; argNb<argCount; argNb++) {
const char* argument = argv[argNb];
if(!argument) continue; /* Protection if argument empty */
/* Short commands (note : aggregated short commands are allowed) */
if (!all_arguments_are_files && argument[0]=='-') {
/* '-' means stdin/stdout */
if (argument[1]==0) {
if (!input_filename) input_filename=stdinmark;
else output_filename=stdoutmark;
continue;
}
/* long commands (--long-word) */
if (argument[1]=='-') {
if (!strcmp(argument, "--")) { all_arguments_are_files = 1; continue; }
if (!strcmp(argument, "--compress")) { mode = om_compress; continue; }
if ( (!strcmp(argument, "--decompress"))
|| (!strcmp(argument, "--uncompress"))) {
if (mode != om_bench) mode = om_decompress;
BMK_setDecodeOnlyMode(1);
continue;
}
if (!strcmp(argument, "--multiple")) { multiple_inputs = 1; continue; }
if (!strcmp(argument, "--test")) { mode = om_test; continue; }
if (!strcmp(argument, "--force")) { LZ4IO_setOverwrite(prefs, 1); continue; }
if (!strcmp(argument, "--no-force")) { LZ4IO_setOverwrite(prefs, 0); continue; }
if ((!strcmp(argument, "--stdout"))
|| (!strcmp(argument, "--to-stdout"))) { forceStdout=1; output_filename=stdoutmark; continue; }
if (!strcmp(argument, "--frame-crc")) { LZ4IO_setStreamChecksumMode(prefs, 1); BMK_skipChecksums(0); continue; }
if (!strcmp(argument, "--no-frame-crc")) { LZ4IO_setStreamChecksumMode(prefs, 0); BMK_skipChecksums(1); continue; }
if (!strcmp(argument, "--no-crc")) { LZ4IO_setStreamChecksumMode(prefs, 0); LZ4IO_setBlockChecksumMode(prefs, 0); BMK_skipChecksums(1); continue; }
if (!strcmp(argument, "--content-size")) { LZ4IO_setContentSize(prefs, 1); continue; }
if (!strcmp(argument, "--no-content-size")) { LZ4IO_setContentSize(prefs, 0); continue; }
if (!strcmp(argument, "--list")) { mode = om_list; multiple_inputs = 1; continue; }
if (!strcmp(argument, "--sparse")) { LZ4IO_setSparseFile(prefs, 2); continue; }
if (!strcmp(argument, "--no-sparse")) { LZ4IO_setSparseFile(prefs, 0); continue; }
if (!strcmp(argument, "--favor-decSpeed")) { LZ4IO_favorDecSpeed(prefs, 1); continue; }
if (!strcmp(argument, "--verbose")) { displayLevel++; continue; }
if (!strcmp(argument, "--quiet")) { if (displayLevel) displayLevel--; continue; }
if (!strcmp(argument, "--version")) { DISPLAYOUT(WELCOME_MESSAGE); goto _cleanup; }
if (!strcmp(argument, "--help")) { usage_advanced(exeName); goto _cleanup; }
if (!strcmp(argument, "--keep")) { LZ4IO_setRemoveSrcFile(prefs, 0); continue; } /* keep source file (default) */
if (!strcmp(argument, "--rm")) { LZ4IO_setRemoveSrcFile(prefs, 1); continue; }
if (longCommandWArg(&argument, "--threads")) {
NEXT_UINT32(nbWorkers);
continue;
}
if (longCommandWArg(&argument, "--fast")) {
/* Parse optional acceleration factor */
if (*argument == '=') {
U32 fastLevel;
++argument;
fastLevel = readU32FromChar(&argument);
if (fastLevel) {
cLevel = -(int)fastLevel;
} else {
badusage(exeName);
}
} else if (*argument != 0) {
/* Invalid character following --fast */
badusage(exeName);
} else {
cLevel = -1; /* default for --fast */
}
continue;
}
/* For gzip(1) compatibility */
if (!strcmp(argument, "--best")) { cLevel=LZ4HC_CLEVEL_MAX; continue; }
}
while (argument[1]!=0) {
argument ++;
if (g_lz4c_legacy_commands) {
/* Legacy commands (-c0, -c1, -hc, -y) */
if (!strcmp(argument, "c0")) { cLevel=0; argument++; continue; } /* -c0 (fast compression) */
if (!strcmp(argument, "c1")) { cLevel=9; argument++; continue; } /* -c1 (high compression) */
if (!strcmp(argument, "c2")) { cLevel=12; argument++; continue; } /* -c2 (very high compression) */
if (!strcmp(argument, "hc")) { cLevel=12; argument++; continue; } /* -hc (very high compression) */
if (!strcmp(argument, "y")) { LZ4IO_setOverwrite(prefs, 1); continue; } /* -y (answer 'yes' to overwrite permission) */
}
if ((*argument>='0') && (*argument<='9')) {
cLevel = (int)readU32FromChar(&argument);
argument--;
continue;
}
switch(argument[0])
{
/* Display help */
case 'V': DISPLAYOUT(WELCOME_MESSAGE); goto _cleanup; /* Version */
case 'h': usage_advanced(exeName); goto _cleanup;
case 'H': usage_longhelp(exeName); goto _cleanup;
case 'e':
argument++;
cLevelLast = (int)readU32FromChar(&argument);
argument--;
break;
/* Compression (default) */
case 'z': mode = om_compress; break;
/* Modify Nb Worker threads (compression only) */
case 'T':
{ argument++;
nbWorkers = readU32FromChar(&argument);
argument--;
}
break;
case 'D':
if (argument[1] == '\0') {
/* path is next arg */
if (argNb + 1 == argCount) {
/* there is no next arg */
badusage(exeName);
}
dictionary_filename = argv[++argNb];
} else {
/* path follows immediately */
dictionary_filename = argument + 1;
}
/* skip to end of argument so that we jump to parsing next argument */
argument += strlen(argument) - 1;
break;
/* Use Legacy format (ex : Linux kernel compression) */
case 'l': legacy_format = 1; blockSize = 8 MB; break;
/* Decoding */
case 'd':
if (mode != om_bench) mode = om_decompress;
BMK_setDecodeOnlyMode(1);
break;
/* Force stdout, even if stdout==console */
case 'c':
forceStdout=1;
output_filename=stdoutmark;
LZ4IO_setPassThrough(prefs, 1);
break;
/* Test integrity */
case 't': mode = om_test; break;
/* Overwrite */
case 'f': forceOverwrite=1; LZ4IO_setOverwrite(prefs, 1); break;
/* Verbose mode */
case 'v': displayLevel++; break;
/* Quiet mode */
case 'q': if (displayLevel) displayLevel--; break;
/* keep source file (default anyway, so useless) (for xz/lzma compatibility) */
case 'k': LZ4IO_setRemoveSrcFile(prefs, 0); break;
/* Modify Block Properties */
case 'B':
while (argument[1]!=0) {
int exitBlockProperties=0;
switch(argument[1])
{
case 'D': LZ4IO_setBlockMode(prefs, LZ4IO_blockLinked); argument++; break;
case 'I': LZ4IO_setBlockMode(prefs, LZ4IO_blockIndependent); argument++; break;
case 'X': LZ4IO_setBlockChecksumMode(prefs, 1); argument ++; break; /* disabled by default */
default :
if (argument[1] < '0' || argument[1] > '9') {
exitBlockProperties=1;
break;
} else {
unsigned B;
argument++;
B = readU32FromChar(&argument);
argument--;
if (B < 4) badusage(exeName);
if (B <= 7) {
blockSize = LZ4IO_setBlockSizeID(prefs, B);
BMK_setBlockSize(blockSize);
DISPLAYLEVEL(2, "using blocks of size %u KB \n", (U32)(blockSize>>10));
} else {
if (B < 32) badusage(exeName);
blockSize = LZ4IO_setBlockSize(prefs, B);
BMK_setBlockSize(blockSize);
if (blockSize >= 1024) {
DISPLAYLEVEL(2, "using blocks of size %u KB \n", (U32)(blockSize>>10));
} else {
DISPLAYLEVEL(2, "using blocks of size %u bytes \n", (U32)(blockSize));
}
}
break;
}
}
if (exitBlockProperties) break;
}
break;
/* Benchmark */
case 'b': mode = om_bench; multiple_inputs=1;
break;
/* hidden command : benchmark files, but do not fuse result */
case 'S': BMK_setBenchSeparately(1);
break;
#ifdef UTIL_HAS_CREATEFILELIST
/* recursive */
case 'r': recursive=1;
#endif
/* fall-through */
/* Treat non-option args as input files. See https://code.google.com/p/lz4/issues/detail?id=151 */
case 'm': multiple_inputs=1;
break;
/* Modify Nb Seconds (benchmark only) */
case 'i':
{ unsigned iters;
argument++;
iters = readU32FromChar(&argument);
argument--;
BMK_setNotificationLevel(displayLevel);
BMK_setNbSeconds(iters); /* notification if displayLevel >= 3 */
}
break;
/* Pause at the end (hidden option) */
case 'p': main_pause=1; break;
/* Unrecognised command */
default : badusage(exeName);
}
}
continue;
}
/* Store in *inFileNames[] if -m is used. */
if (multiple_inputs) { inFileNames[ifnIdx++] = argument; continue; }
/* original cli logic : lz4 input output */
/* First non-option arg is input_filename. */
if (!input_filename) { input_filename = argument; continue; }
/* Second non-option arg is output_filename */
if (!output_filename) {
output_filename = argument;
if (!strcmp (output_filename, nullOutput)) output_filename = nulmark;
continue;
}
/* 3rd+ non-option arg should not exist */
DISPLAYLEVEL(1, "%s : %s won't be used ! Do you want multiple input files (-m) ? \n",
forceOverwrite ? "Warning" : "Error",
argument);
if (!forceOverwrite) exit(1);
}
DISPLAYLEVEL(3, WELCOME_MESSAGE);
#ifdef _POSIX_C_SOURCE
DISPLAYLEVEL(4, "_POSIX_C_SOURCE defined: %ldL\n", (long) _POSIX_C_SOURCE);
#endif
#ifdef _POSIX_VERSION
DISPLAYLEVEL(4, "_POSIX_VERSION defined: %ldL\n", (long) _POSIX_VERSION);
#endif
#ifdef PLATFORM_POSIX_VERSION
DISPLAYLEVEL(4, "PLATFORM_POSIX_VERSION defined: %ldL\n", (long) PLATFORM_POSIX_VERSION);
#endif
#ifdef _FILE_OFFSET_BITS
DISPLAYLEVEL(5, "_FILE_OFFSET_BITS defined: %ldL\n", (long) _FILE_OFFSET_BITS);
#endif
#if !LZ4IO_MULTITHREAD
if (nbWorkers > 1) {
DISPLAYLEVEL(2, "warning: this executable doesn't support multithreading \n");
}
#endif
if ((mode == om_compress) || (mode == om_bench)) {
DISPLAYLEVEL(4, "Blocks size : %u KB\n", (U32)(blockSize>>10));
}
if (multiple_inputs) {
input_filename = inFileNames[0];
#ifdef UTIL_HAS_CREATEFILELIST
if (recursive) { /* at this stage, filenameTable is a list of paths, which can contain both files and directories */
const char** extendedFileList = UTIL_createFileList(inFileNames, ifnIdx, &fileNamesBuf, &fileNamesNb);
if (extendedFileList) {
unsigned u;
for (u=0; u<fileNamesNb; u++) DISPLAYLEVEL(4, "%u %s\n", u, extendedFileList[u]);
free((void*)inFileNames);
inFileNames = extendedFileList;
ifnIdx = fileNamesNb;
} }
#endif
}
if (dictionary_filename) {
if (!strcmp(dictionary_filename, stdinmark) && IS_CONSOLE(stdin)) {
DISPLAYLEVEL(1, "refusing to read from a console\n");
exit(1);
}
LZ4IO_setDictionaryFilename(prefs, dictionary_filename);
}
/* benchmark and test modes */
if (mode == om_bench) {
BMK_setNotificationLevel(displayLevel);
operationResult = BMK_benchFiles(inFileNames, ifnIdx, cLevel, cLevelLast, dictionary_filename);
goto _cleanup;
}
if (mode == om_test) {
LZ4IO_setTestMode(prefs, 1);
output_filename = nulmark;
mode = om_decompress; /* defer to decompress */
}
/* No input provided => use stdin */
if (!input_filename) input_filename = stdinmark;
/* Refuse to use the console as input */
if (!strcmp(input_filename, stdinmark) && IS_CONSOLE(stdin) ) {
DISPLAYLEVEL(1, "refusing to read from a console\n");
exit(1);
}
if (!strcmp(input_filename, stdinmark)) {
/* if input==stdin and no output defined, stdout becomes default output */
if (!output_filename) output_filename = stdoutmark;
}
/* No output filename ==> try to select one automatically (when possible) */
if ((!output_filename) && (multiple_inputs==0)) {
if (mode == om_auto) { /* auto-determine compression or decompression, based on file extension */
mode = determineOpMode(input_filename);
}
if (mode == om_compress) { /* compression to file */
size_t const l = strlen(input_filename);
dynNameSpace = (char*)calloc(1,l+5);
if (dynNameSpace==NULL) { perror(exeName); exit(1); }
strcpy(dynNameSpace, input_filename);
strcat(dynNameSpace, LZ4_EXTENSION);
output_filename = dynNameSpace;
DISPLAYLEVEL(2, "Compressed filename will be : %s \n", output_filename);
}
if (mode == om_decompress) {
/* decompress to file (automatic output name only works if input filename has correct format extension) */
size_t outl;
size_t const inl = strlen(input_filename);
dynNameSpace = (char*)calloc(1,inl+1);
if (dynNameSpace==NULL) { perror(exeName); exit(1); }
strcpy(dynNameSpace, input_filename);
outl = inl;
if (inl>4)
while ((outl >= inl-4) && (input_filename[outl] == extension[outl-inl+4])) dynNameSpace[outl--]=0;
if (outl != inl-5) { DISPLAYLEVEL(1, "Cannot determine an output filename \n"); badusage(exeName); }
output_filename = dynNameSpace;
DISPLAYLEVEL(2, "Decoding file %s \n", output_filename);
}
}
if (mode == om_list) {
if (!multiple_inputs) inFileNames[ifnIdx++] = input_filename;
} else {
if (!multiple_inputs) assert(output_filename != NULL);
}
/* when multiple_inputs==1, output_filename may simply be useless,
* however, output_filename must be !NULL for next strcmp() tests */
if (!output_filename) output_filename = "*\\dummy^!//";
/* Check if output is defined as console; trigger an error in this case */
if ( !strcmp(output_filename,stdoutmark)
&& mode != om_list
&& IS_CONSOLE(stdout)
&& !forceStdout) {
DISPLAYLEVEL(1, "refusing to write to console without -c \n");
exit(1);
}
/* Downgrade notification level in stdout and multiple file mode */
if (!strcmp(output_filename,stdoutmark) && (displayLevel==2)) displayLevel=1;
if ((multiple_inputs) && (displayLevel==2)) displayLevel=1;
/* Auto-determine compression or decompression, based on file extension */
if (mode == om_auto) {
mode = determineOpMode(input_filename);
}
/* IO Stream/File */
LZ4IO_setNotificationLevel((int)displayLevel);
if (ifnIdx == 0) multiple_inputs = 0;
if (mode == om_decompress) {
if (multiple_inputs) {
const char* dec_extension = LZ4_EXTENSION;
if (!strcmp(output_filename, stdoutmark)) dec_extension = stdoutmark;
if (!strcmp(output_filename, nulmark)) dec_extension = nulmark;
assert(ifnIdx < INT_MAX);
operationResult = LZ4IO_decompressMultipleFilenames(inFileNames, (int)ifnIdx, dec_extension, prefs);
} else {
operationResult = DEFAULT_DECOMPRESSOR(input_filename, output_filename, prefs);
}
} else if (mode == om_list){
operationResult = LZ4IO_displayCompressedFilesInfo(inFileNames, ifnIdx);
} else { /* compression is default action */
#if LZ4IO_MULTITHREAD
if (nbWorkers != 1) {
if (nbWorkers==0)
nbWorkers = (unsigned)LZ4IO_defaultNbWorkers();
if (nbWorkers > LZ4_NBWORKERS_MAX) {
DISPLAYLEVEL(3, "Requested %u threads too large => automatically reduced to %u \n",
nbWorkers, LZ4_NBWORKERS_MAX);
nbWorkers = LZ4_NBWORKERS_MAX;
} else {
DISPLAYLEVEL(3, "Using %u threads for compression \n", nbWorkers);
}
}
LZ4IO_setNbWorkers(prefs, (int)nbWorkers);
#endif
if (legacy_format) {
DISPLAYLEVEL(3, "! Generating LZ4 Legacy format (deprecated) ! \n");
if(multiple_inputs){
const char* const leg_extension = !strcmp(output_filename,stdoutmark) ? stdoutmark : LZ4_EXTENSION;
operationResult = LZ4IO_compressMultipleFilenames_Legacy(inFileNames, (int)ifnIdx, leg_extension, cLevel, prefs);
} else {
operationResult = LZ4IO_compressFilename_Legacy(input_filename, output_filename, cLevel, prefs);
}
} else {
if (multiple_inputs) {
const char* const comp_extension = !strcmp(output_filename,stdoutmark) ? stdoutmark : LZ4_EXTENSION;
assert(ifnIdx <= INT_MAX);
operationResult = LZ4IO_compressMultipleFilenames(inFileNames, (int)ifnIdx, comp_extension, cLevel, prefs);
} else {
operationResult = DEFAULT_COMPRESSOR(input_filename, output_filename, cLevel, prefs);
} } }
_cleanup:
if (main_pause) waitEnter();
free(dynNameSpace);
free(fileNamesBuf);
LZ4IO_freePreferences(prefs);
free((void*)inFileNames);
return operationResult;
}

72
expkg/vendor/lz4/programs/lz4conf.h vendored Normal file
View File

@ -0,0 +1,72 @@
/*
LZ4conf.h - compile-time parameters
Copyright (c) Yann Collet. All rights reserved.
GPL v2 License
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
You can contact the author at :
- LZ4 source repository : https://github.com/lz4/lz4
- LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
*/
#ifndef LZ4CONF_H_32432
#define LZ4CONF_H_32432
/* Default compression level.
* Can be overridden by environment variable LZ4_CLEVEL.
* Is overridden at runtime by command -# */
#ifndef LZ4_CLEVEL_DEFAULT
# define LZ4_CLEVEL_DEFAULT 1
#endif
/* Determines if multithreading is enabled or not
* Default: enabled on Windows, disabled on other platforms */
#ifndef LZ4IO_MULTITHREAD
# ifdef _WIN32
/* Windows supports Completion Ports */
# define LZ4IO_MULTITHREAD 1
# else
/* Requires <pthread> support.
* Can't be reliably and portably tested at source code level
* so must be set a build level */
# define LZ4IO_MULTITHREAD 0
# endif
#endif
/* Determines default nb of threads for compression
* Default value is 0, which means "auto" :
* nb of threads is determined from detected local cpu.
* Can be overridden by Environment Variable LZ4_NBWORKERS.
* Can be overridden at runtime using -T# command */
#ifndef LZ4_NBWORKERS_DEFAULT
# define LZ4_NBWORKERS_DEFAULT 0
#endif
/* Maximum nb of compression threads selectable at runtime */
#ifndef LZ4_NBWORKERS_MAX
# define LZ4_NBWORKERS_MAX 200
#endif
/* Determines default lz4 block size when none provided.
* Default value is 7, which represents 4 MB.
* Can be overridden at runtime using -B# command */
#ifndef LZ4_BLOCKSIZEID_DEFAULT
# define LZ4_BLOCKSIZEID_DEFAULT 7
#endif
#endif /* LZ4CONF_H_32432 */

2907
expkg/vendor/lz4/programs/lz4io.c vendored Normal file

File diff suppressed because it is too large Load Diff

135
expkg/vendor/lz4/programs/lz4io.h vendored Normal file
View File

@ -0,0 +1,135 @@
/*
LZ4io.h - LZ4 File/Stream Interface
Copyright (c) Yann Collet. All rights reserved.
GPL v2 License
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
You can contact the author at :
- LZ4 source repository : https://github.com/lz4/lz4
- LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
*/
/*
Note : this is stand-alone program.
It is not part of LZ4 compression library, it is a user code of the LZ4 library.
- The license of LZ4 library is BSD.
- The license of xxHash library is BSD.
- The license of this source file is GPLv2.
*/
#ifndef LZ4IO_H_237902873
#define LZ4IO_H_237902873
/*--- Dependency ---*/
#include <stddef.h> /* size_t */
/* ************************************************** */
/* Special input/output values */
/* ************************************************** */
#define stdinmark "stdin"
#define stdoutmark "stdout"
#define NULL_OUTPUT "null"
#ifdef _WIN32
#define nulmark "nul"
#else
#define nulmark "/dev/null"
#endif
/* ************************************************** */
/* ****************** Type Definitions ************** */
/* ************************************************** */
typedef struct LZ4IO_prefs_s LZ4IO_prefs_t;
LZ4IO_prefs_t* LZ4IO_defaultPreferences(void);
void LZ4IO_freePreferences(LZ4IO_prefs_t* prefs);
/* *************************************************** */
/* ****************** Processing ********************* */
/* *************************************************** */
/* if output_filename == stdoutmark, writes to stdout */
int LZ4IO_compressFilename(const char* input_filename, const char* output_filename, int compressionlevel, const LZ4IO_prefs_t* prefs);
int LZ4IO_decompressFilename(const char* input_filename, const char* output_filename, const LZ4IO_prefs_t* prefs);
/* if suffix == stdoutmark, writes to stdout */
int LZ4IO_compressMultipleFilenames(const char** inFileNamesTable, int ifntSize, const char* suffix, int compressionlevel, const LZ4IO_prefs_t* prefs);
int LZ4IO_decompressMultipleFilenames(const char** inFileNamesTable, int ifntSize, const char* suffix, const LZ4IO_prefs_t* prefs);
/* ************************************************** */
/* ****************** Parameters ******************** */
/* ************************************************** */
int LZ4IO_setNbWorkers(LZ4IO_prefs_t* const prefs, int nbWorkers);
int LZ4IO_defaultNbWorkers(void);
int LZ4IO_setDictionaryFilename(LZ4IO_prefs_t* const prefs, const char* dictionaryFilename);
/* Default setting : passThrough = 0;
return : passThrough mode (0/1) */
int LZ4IO_setPassThrough(LZ4IO_prefs_t* const prefs, int yes);
/* Default setting : overwrite = 1;
return : overwrite mode (0/1) */
int LZ4IO_setOverwrite(LZ4IO_prefs_t* const prefs, int yes);
/* Default setting : testMode = 0;
return : testMode (0/1) */
int LZ4IO_setTestMode(LZ4IO_prefs_t* const prefs, int yes);
/* blockSizeID : valid values : 4-5-6-7
return : 0 if error, blockSize if OK */
size_t LZ4IO_setBlockSizeID(LZ4IO_prefs_t* const prefs, unsigned blockSizeID);
/* blockSize : valid values : 32 -> 4MB
return : 0 if error, actual blocksize if OK */
size_t LZ4IO_setBlockSize(LZ4IO_prefs_t* const prefs, size_t blockSize);
/* Default setting : independent blocks */
typedef enum { LZ4IO_blockLinked=0, LZ4IO_blockIndependent} LZ4IO_blockMode_t;
int LZ4IO_setBlockMode(LZ4IO_prefs_t* const prefs, LZ4IO_blockMode_t blockMode);
/* Default setting : no block checksum */
int LZ4IO_setBlockChecksumMode(LZ4IO_prefs_t* const prefs, int xxhash);
/* Default setting : stream checksum enabled */
int LZ4IO_setStreamChecksumMode(LZ4IO_prefs_t* const prefs, int xxhash);
/* Default setting : 0 (no notification) */
int LZ4IO_setNotificationLevel(int level);
/* Default setting : 0 (disabled) */
int LZ4IO_setSparseFile(LZ4IO_prefs_t* const prefs, int enable);
/* Default setting : 0 == no content size present in frame header */
int LZ4IO_setContentSize(LZ4IO_prefs_t* const prefs, int enable);
/* Default setting : 0 == src file preserved */
void LZ4IO_setRemoveSrcFile(LZ4IO_prefs_t* const prefs, unsigned flag);
/* Default setting : 0 == favor compression ratio
* Note : 1 only works for high compression levels (10+) */
void LZ4IO_favorDecSpeed(LZ4IO_prefs_t* const prefs, int favor);
/* implement --list
* @return 0 on success, 1 on error */
int LZ4IO_displayCompressedFilesInfo(const char** inFileNames, size_t ifnIdx);
#endif /* LZ4IO_H_237902873 */

157
expkg/vendor/lz4/programs/platform.h vendored Normal file
View File

@ -0,0 +1,157 @@
/*
platform.h - compiler and OS detection
Copyright (c) Przemyslaw Skibinski, Yann Collet. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef PLATFORM_H_MODULE
#define PLATFORM_H_MODULE
#if defined (__cplusplus)
extern "C" {
#endif
/* **************************************
* Compiler Options
****************************************/
#if defined(_MSC_VER)
# define _CRT_SECURE_NO_WARNINGS /* Disable Visual Studio warning messages for fopen, strncpy, strerror */
# if (_MSC_VER <= 1800) /* (1800 = Visual Studio 2013) */
# define _CRT_SECURE_NO_DEPRECATE /* VS2005 - must be declared before <io.h> and <windows.h> */
# define snprintf sprintf_s /* snprintf unsupported by Visual <= 2013 */
# endif
#endif
/* **************************************
* Detect 64-bit OS
* http://nadeausoftware.com/articles/2012/02/c_c_tip_how_detect_processor_type_using_compiler_predefined_macros
****************************************/
#if defined __ia64 || defined _M_IA64 /* Intel Itanium */ \
|| defined __powerpc64__ || defined __ppc64__ || defined __PPC64__ /* POWER 64-bit */ \
|| (defined __sparc && (defined __sparcv9 || defined __sparc_v9__ || defined __arch64__)) || defined __sparc64__ /* SPARC 64-bit */ \
|| defined __x86_64__s || defined _M_X64 /* x86 64-bit */ \
|| defined __arm64__ || defined __aarch64__ || defined __ARM64_ARCH_8__ /* ARM 64-bit */ \
|| (defined __mips && (__mips == 64 || __mips == 4 || __mips == 3)) /* MIPS 64-bit */ \
|| defined __loongarch64 /* LoongArch 64-bit */ \
|| (defined __riscv && defined __riscv_xlen && (__riscv_xlen == 64)) /* Riscv 64-bit */ \
|| defined _LP64 || defined __LP64__ /* NetBSD, OpenBSD */ || defined __64BIT__ /* AIX */ || defined _ADDR64 /* Cray */ \
|| (defined __SIZEOF_POINTER__ && __SIZEOF_POINTER__ == 8) /* gcc */
# if !defined(__64BIT__)
# define __64BIT__ 1
# endif
#endif
/* *********************************************************
* Turn on Large Files support (>4GB) for 32-bit Linux/Unix
***********************************************************/
#if !defined(__64BIT__) || defined(__MINGW32__) /* No point defining Large file for 64 bit but MinGW-w64 requires it */
# if !defined(_FILE_OFFSET_BITS)
# define _FILE_OFFSET_BITS 64 /* turn off_t into a 64-bit type for ftello, fseeko */
# endif
# if !defined(_LARGEFILE_SOURCE) /* obsolete macro, replaced with _FILE_OFFSET_BITS */
# define _LARGEFILE_SOURCE 1 /* Large File Support extension (LFS) - fseeko, ftello */
# endif
# if defined(_AIX) || defined(__hpux)
# define _LARGE_FILES /* Large file support on 32-bits AIX and HP-UX */
# endif
#endif
/* ************************************************************
* Detect POSIX version
* PLATFORM_POSIX_VERSION = -1 for non-Unix e.g. Windows
* PLATFORM_POSIX_VERSION = 0 for Unix-like non-POSIX
* PLATFORM_POSIX_VERSION >= 1 is equal to found _POSIX_VERSION
************************************************************** */
#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)) /* UNIX-like OS */ \
|| defined(__midipix__) || defined(__VMS))
# if (defined(__APPLE__) && defined(__MACH__)) || defined(__SVR4) || defined(_AIX) || defined(__hpux) /* POSIX.1-2001 (SUSv3) conformant */ \
|| defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__MidnightBSD__) /* BSD distros */ \
|| defined(__HAIKU__)
# define PLATFORM_POSIX_VERSION 200112L
# else
# if defined(__linux__) || defined(__linux)
# ifndef _POSIX_C_SOURCE
# define _POSIX_C_SOURCE 200809L /* use feature test macro */
# endif
# endif
# include <unistd.h> /* declares _POSIX_VERSION */
# if defined(_POSIX_VERSION) /* POSIX compliant */
# define PLATFORM_POSIX_VERSION _POSIX_VERSION
# else
# define PLATFORM_POSIX_VERSION 0
# endif
# endif
#endif
#if !defined(PLATFORM_POSIX_VERSION)
# define PLATFORM_POSIX_VERSION -1
#endif
/*-*********************************************
* Detect if isatty() and fileno() are available
*********************************************** */
#if (defined(__linux__) && (PLATFORM_POSIX_VERSION >= 1)) || (PLATFORM_POSIX_VERSION >= 200112L) || defined(__DJGPP__)
# include <unistd.h> /* isatty */
# define IS_CONSOLE(stdStream) isatty(fileno(stdStream))
#elif defined(MSDOS) || defined(OS2) || defined(__CYGWIN__)
# include <io.h> /* _isatty */
# define IS_CONSOLE(stdStream) _isatty(_fileno(stdStream))
#elif defined(WIN32) || defined(_WIN32)
# include <io.h> /* _isatty */
# include <windows.h> /* DeviceIoControl, HANDLE, FSCTL_SET_SPARSE */
# include <stdio.h> /* FILE */
static __inline int IS_CONSOLE(FILE* stdStream)
{
DWORD dummy;
return _isatty(_fileno(stdStream)) && GetConsoleMode((HANDLE)_get_osfhandle(_fileno(stdStream)), &dummy);
}
#else
# define IS_CONSOLE(stdStream) 0
#endif
/******************************
* OS-specific Includes
***************************** */
#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(_WIN32)
# include <fcntl.h> /* _O_BINARY */
# include <io.h> /* _setmode, _fileno, _get_osfhandle */
# if !defined(__DJGPP__)
# include <windows.h> /* DeviceIoControl, HANDLE, FSCTL_SET_SPARSE */
# include <winioctl.h> /* FSCTL_SET_SPARSE */
# define SET_BINARY_MODE(file) { int unused=_setmode(_fileno(file), _O_BINARY); (void)unused; }
# define SET_SPARSE_FILE_MODE(file) { DWORD dw; DeviceIoControl((HANDLE) _get_osfhandle(_fileno(file)), FSCTL_SET_SPARSE, 0, 0, 0, 0, &dw, 0); }
# else
# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
# define SET_SPARSE_FILE_MODE(file)
# endif
#else
# define SET_BINARY_MODE(file)
# define SET_SPARSE_FILE_MODE(file)
#endif
#if defined (__cplusplus)
}
#endif
#endif /* PLATFORM_H_MODULE */

430
expkg/vendor/lz4/programs/threadpool.c vendored Normal file
View File

@ -0,0 +1,430 @@
/*
threadpool.h - part of lz4 project
Copyright (c) Yann Collet. All rights reserved.
GPL v2 License
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
You can contact the author at :
- LZ4 source repository : https://github.com/lz4/lz4
- LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
*/
/* ====== Dependencies ======= */
#include <assert.h>
#include "lz4conf.h" /* LZ4IO_MULTITHREAD */
#include "threadpool.h"
/* ====== Compiler specifics ====== */
#if defined(_MSC_VER)
# pragma warning(disable : 4204) /* disable: C4204: non-constant aggregate initializer */
#endif
#if !LZ4IO_MULTITHREAD
/* ===================================================== */
/* Backup implementation with no multi-threading support */
/* ===================================================== */
/* Non-zero size, to ensure g_poolCtx != NULL */
struct TPool_s {
int dummy;
};
static TPool g_poolCtx;
TPool* TPool_create(int numThreads, int queueSize) {
(void)numThreads;
(void)queueSize;
return &g_poolCtx;
}
void TPool_free(TPool* ctx) {
assert(!ctx || ctx == &g_poolCtx);
(void)ctx;
}
void TPool_submitJob(TPool* ctx, void (*job_function)(void*), void* arg) {
(void)ctx;
job_function(arg);
}
void TPool_jobsCompleted(TPool* ctx) {
assert(!ctx || ctx == &g_poolCtx);
(void)ctx;
}
#elif defined(_WIN32)
/* Window TPool implementation using Completion Ports */
#include <windows.h>
typedef struct TPool_s {
HANDLE completionPort;
HANDLE* workerThreads;
int nbWorkers;
int queueSize;
LONG nbPendingJobs;
HANDLE jobSlotAvail; /* For queue size control */
HANDLE allJobsCompleted; /* Event */
} TPool;
void TPool_free(TPool* pool)
{
if (!pool) return;
/* Signal workers to exit by posting NULL completions */
{ int i;
for (i = 0; i < pool->nbWorkers; i++) {
PostQueuedCompletionStatus(pool->completionPort, 0, 0, NULL);
}
}
/* Wait for worker threads to finish */
WaitForMultipleObjects(pool->nbWorkers, pool->workerThreads, TRUE, INFINITE);
/* Close thread handles and completion port */
{ int i;
for (i = 0; i < pool->nbWorkers; i++) {
CloseHandle(pool->workerThreads[i]);
}
}
free(pool->workerThreads);
CloseHandle(pool->completionPort);
/* Clean up synchronization objects */
CloseHandle(pool->jobSlotAvail);
CloseHandle(pool->allJobsCompleted);
free(pool);
}
static DWORD WINAPI WorkerThread(LPVOID lpParameter)
{
TPool* const pool = (TPool*)lpParameter;
DWORD bytesTransferred;
ULONG_PTR completionKey;
LPOVERLAPPED overlapped;
while (GetQueuedCompletionStatus(pool->completionPort,
&bytesTransferred, &completionKey,
&overlapped, INFINITE)) {
/* End signal */
if (overlapped == NULL) { break; }
/* Execute job */
((void (*)(void*))completionKey)(overlapped);
/* Signal job completion */
if (InterlockedDecrement(&pool->nbPendingJobs) == 0) {
SetEvent(pool->allJobsCompleted);
}
ReleaseSemaphore(pool->jobSlotAvail, 1, NULL);
}
return 0;
}
TPool* TPool_create(int nbWorkers, int queueSize)
{
TPool* pool;
/* parameters sanitization */
if (nbWorkers <= 0 || queueSize <= 0) return NULL;
if (nbWorkers>LZ4_NBWORKERS_MAX) nbWorkers=LZ4_NBWORKERS_MAX;
pool = calloc(1, sizeof(TPool));
if (!pool) return NULL;
/* Create completion port */
pool->completionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, nbWorkers);
if (!pool->completionPort) { goto _cleanup; }
/* Create worker threads */
pool->nbWorkers = nbWorkers;
pool->workerThreads = (HANDLE*)malloc(sizeof(HANDLE) * nbWorkers);
if (pool->workerThreads == NULL) { goto _cleanup; }
{ int i;
for (i = 0; i < nbWorkers; i++) {
pool->workerThreads[i] = CreateThread(NULL, 0, WorkerThread, pool, 0, NULL);
if (!pool->workerThreads[i]) { goto _cleanup; }
}
}
/* Initialize sync objects members */
pool->queueSize = queueSize;
pool->nbPendingJobs = 0;
pool->jobSlotAvail = CreateSemaphore(NULL, queueSize+nbWorkers, queueSize+nbWorkers, NULL);
if (!pool->jobSlotAvail) { goto _cleanup; }
pool->allJobsCompleted = CreateEvent(NULL, FALSE, FALSE, NULL);
if (!pool->allJobsCompleted) { goto _cleanup; }
return pool;
_cleanup:
TPool_free(pool);
return NULL;
}
void TPool_submitJob(TPool* pool, void (*job_function)(void*), void* arg)
{
assert(pool);
/* Atomically increment pending jobs and check for overflow */
WaitForSingleObject(pool->jobSlotAvail, INFINITE);
ResetEvent(pool->allJobsCompleted);
InterlockedIncrement(&pool->nbPendingJobs);
/* Post the job directly to the completion port */
PostQueuedCompletionStatus(pool->completionPort,
0, /* Bytes transferred not used */
(ULONG_PTR)job_function, /* Store function pointer in completionKey */
(LPOVERLAPPED)arg); /* Store argument in overlapped */
}
void TPool_jobsCompleted(TPool* pool)
{
assert(pool);
WaitForSingleObject(pool->allJobsCompleted, INFINITE);
}
#else
/* pthread availability assumed */
#include <stdlib.h> /* malloc, free */
#include <pthread.h> /* pthread_* */
/* A job is just a function with an opaque argument */
typedef struct TPool_job_s {
void (*job_function)(void*);
void *arg;
} TPool_job;
struct TPool_s {
pthread_t* threads;
size_t threadCapacity;
size_t threadLimit;
/* The queue is a circular buffer */
TPool_job* queue;
size_t queueHead;
size_t queueTail;
size_t queueSize;
/* The number of threads working on jobs */
size_t numThreadsBusy;
/* Indicates if the queue is empty */
int queueEmpty;
/* The mutex protects the queue */
pthread_mutex_t queueMutex;
/* Condition variable for pushers to wait on when the queue is full */
pthread_cond_t queuePushCond;
/* Condition variables for poppers to wait on when the queue is empty */
pthread_cond_t queuePopCond;
/* Indicates if the queue is shutting down */
int shutdown;
};
static void TPool_shutdown(TPool* ctx);
void TPool_free(TPool* ctx) {
if (!ctx) { return; }
TPool_shutdown(ctx);
pthread_mutex_destroy(&ctx->queueMutex);
pthread_cond_destroy(&ctx->queuePushCond);
pthread_cond_destroy(&ctx->queuePopCond);
free(ctx->queue);
free(ctx->threads);
free(ctx);
}
static void* TPool_thread(void* opaque);
TPool* TPool_create(int nbThreads, int queueSize)
{
TPool* ctx;
/* Check parameters */
if (nbThreads<1 || queueSize<1) { return NULL; }
/* Allocate the context and zero initialize */
ctx = (TPool*)calloc(1, sizeof(TPool));
if (!ctx) { return NULL; }
/* init pthread variables */
{ int error = 0;
error |= pthread_mutex_init(&ctx->queueMutex, NULL);
error |= pthread_cond_init(&ctx->queuePushCond, NULL);
error |= pthread_cond_init(&ctx->queuePopCond, NULL);
if (error) { TPool_free(ctx); return NULL; }
}
/* Initialize the job queue.
* It needs one extra space since one space is wasted to differentiate
* empty and full queues.
*/
ctx->queueSize = (size_t)queueSize + 1;
ctx->queue = (TPool_job*)calloc(1, ctx->queueSize * sizeof(TPool_job));
if (ctx->queue == NULL) {
TPool_free(ctx);
return NULL;
}
ctx->queueHead = 0;
ctx->queueTail = 0;
ctx->numThreadsBusy = 0;
ctx->queueEmpty = 1;
ctx->shutdown = 0;
/* Allocate space for the thread handles */
ctx->threads = (pthread_t*)calloc(1, (size_t)nbThreads * sizeof(pthread_t));
if (ctx->threads == NULL) {
TPool_free(ctx);
return NULL;
}
ctx->threadCapacity = 0;
/* Initialize the threads */
{ int i;
for (i = 0; i < nbThreads; ++i) {
if (pthread_create(&ctx->threads[i], NULL, &TPool_thread, ctx)) {
ctx->threadCapacity = (size_t)i;
TPool_free(ctx);
return NULL;
} }
ctx->threadCapacity = (size_t)nbThreads;
ctx->threadLimit = (size_t)nbThreads;
}
return ctx;
}
/* TPool_thread() :
* Work thread for the thread pool.
* Waits for jobs and executes them.
* @returns : NULL on failure else non-null.
*/
static void* TPool_thread(void* opaque) {
TPool* const ctx = (TPool*)opaque;
if (!ctx) { return NULL; }
for (;;) {
/* Lock the mutex and wait for a non-empty queue or until shutdown */
pthread_mutex_lock(&ctx->queueMutex);
while ( ctx->queueEmpty
|| (ctx->numThreadsBusy >= ctx->threadLimit) ) {
if (ctx->shutdown) {
/* even if !queueEmpty, (possible if numThreadsBusy >= threadLimit),
* a few threads will be shutdown while !queueEmpty,
* but enough threads will remain active to finish the queue */
pthread_mutex_unlock(&ctx->queueMutex);
return opaque;
}
pthread_cond_wait(&ctx->queuePopCond, &ctx->queueMutex);
}
/* Pop a job off the queue */
{ TPool_job const job = ctx->queue[ctx->queueHead];
ctx->queueHead = (ctx->queueHead + 1) % ctx->queueSize;
ctx->numThreadsBusy++;
ctx->queueEmpty = (ctx->queueHead == ctx->queueTail);
/* Unlock the mutex, signal a pusher, and run the job */
pthread_cond_signal(&ctx->queuePushCond);
pthread_mutex_unlock(&ctx->queueMutex);
job.job_function(job.arg);
/* If the intended queue size was 0, signal after finishing job */
pthread_mutex_lock(&ctx->queueMutex);
ctx->numThreadsBusy--;
pthread_cond_signal(&ctx->queuePushCond);
pthread_mutex_unlock(&ctx->queueMutex);
}
} /* for (;;) */
assert(0); /* Unreachable */
}
/*! TPool_shutdown() :
Shutdown the queue, wake any sleeping threads, and join all of the threads.
*/
static void TPool_shutdown(TPool* ctx) {
/* Shut down the queue */
pthread_mutex_lock(&ctx->queueMutex);
ctx->shutdown = 1;
pthread_mutex_unlock(&ctx->queueMutex);
/* Wake up sleeping threads */
pthread_cond_broadcast(&ctx->queuePushCond);
pthread_cond_broadcast(&ctx->queuePopCond);
/* Join all of the threads */
{ size_t i;
for (i = 0; i < ctx->threadCapacity; ++i) {
pthread_join(ctx->threads[i], NULL); /* note : could fail */
} }
}
/*! TPool_jobsCompleted() :
* Waits for all queued jobs to finish executing.
*/
void TPool_jobsCompleted(TPool* ctx){
pthread_mutex_lock(&ctx->queueMutex);
while(!ctx->queueEmpty || ctx->numThreadsBusy > 0) {
pthread_cond_wait(&ctx->queuePushCond, &ctx->queueMutex);
}
pthread_mutex_unlock(&ctx->queueMutex);
}
/**
* Returns 1 if the queue is full and 0 otherwise.
*
* When queueSize is 1 (pool was created with an intended queueSize of 0),
* then a queue is empty if there is a thread free _and_ no job is waiting.
*/
static int isQueueFull(TPool const* ctx) {
if (ctx->queueSize > 1) {
return ctx->queueHead == ((ctx->queueTail + 1) % ctx->queueSize);
} else {
return (ctx->numThreadsBusy == ctx->threadLimit) ||
!ctx->queueEmpty;
}
}
static void
TPool_submitJob_internal(TPool* ctx, void (*job_function)(void*), void *arg)
{
TPool_job job;
job.job_function = job_function;
job.arg = arg;
assert(ctx != NULL);
if (ctx->shutdown) return;
ctx->queueEmpty = 0;
ctx->queue[ctx->queueTail] = job;
ctx->queueTail = (ctx->queueTail + 1) % ctx->queueSize;
pthread_cond_signal(&ctx->queuePopCond);
}
void TPool_submitJob(TPool* ctx, void (*job_function)(void*), void* arg)
{
assert(ctx != NULL);
pthread_mutex_lock(&ctx->queueMutex);
/* Wait until there is space in the queue for the new job */
while (isQueueFull(ctx) && (!ctx->shutdown)) {
pthread_cond_wait(&ctx->queuePushCond, &ctx->queueMutex);
}
TPool_submitJob_internal(ctx, job_function, arg);
pthread_mutex_unlock(&ctx->queueMutex);
}
#endif /* LZ4IO_NO_MT */

68
expkg/vendor/lz4/programs/threadpool.h vendored Normal file
View File

@ -0,0 +1,68 @@
/*
threadpool.h - part of lz4 project
Copyright (c) Yann Collet. All rights reserved.
GPL v2 License
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
You can contact the author at :
- LZ4 source repository : https://github.com/lz4/lz4
- LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
*/
#ifndef THREADPOOL_H
#define THREADPOOL_H
#if defined (__cplusplus)
extern "C" {
#endif
typedef struct TPool_s TPool;
/*! TPool_create() :
* Create a thread pool with at most @nbThreads.
* @nbThreads must be at least 1.
* @queueSize is the maximum number of pending jobs before blocking.
* @return : TPool* pointer on success, else NULL.
*/
TPool* TPool_create(int nbThreads, int queueSize);
/*! TPool_free() :
* Free a thread pool returned by TPool_create().
* Waits for the completion of running jobs before freeing resources.
*/
void TPool_free(TPool* ctx);
/*! TPool_submitJob() :
* Add @job_function(arg) to the thread pool.
* @ctx must be valid.
* Invocation can block if queue is full.
* Note: Ensure @arg's lifetime extends until @job_function completes.
* Alternatively, @arg's lifetime must be managed by @job_function.
*/
void TPool_submitJob(TPool* ctx, void (*job_function)(void*), void* arg);
/*! TPool_jobsCompleted() :
* Blocks until all queued jobs are completed.
*/
void TPool_jobsCompleted(TPool* ctx);
#if defined (__cplusplus)
}
#endif
#endif /* THREADPOOL_H */

175
expkg/vendor/lz4/programs/timefn.c vendored Normal file
View File

@ -0,0 +1,175 @@
/*
timefn.c - portable time measurement functions
Copyright (c) Yann Collet. All rights reserved.
GPL v2 License
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
You can contact the author at :
- LZ4 source repository : https://github.com/lz4/lz4
- LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
*/
/* === Dependencies === */
#include "timefn.h"
#include <time.h> /* CLOCK_MONOTONIC, TIME_UTC */
/*-****************************************
* Time functions
******************************************/
#if defined(_WIN32) /* Windows */
# include <stdio.h> /* perror */
# include <stdlib.h> /* abort */
# include <windows.h> /* LARGE_INTEGER */
TIME_t TIME_getTime(void)
{
static LARGE_INTEGER ticksPerSecond;
static int init = 0;
if (!init) {
if (!QueryPerformanceFrequency(&ticksPerSecond)) {
perror("timefn::QueryPerformanceFrequency");
abort();
}
init = 1;
}
{
TIME_t r;
LARGE_INTEGER x;
QueryPerformanceCounter(&x);
r.t = (Duration_ns)(x.QuadPart * 1000000000ULL / ticksPerSecond.QuadPart);
return r;
}
}
#elif defined(__APPLE__) && defined(__MACH__)
# include <mach/mach_time.h> /* mach_timebase_info_data_t, mach_timebase_info, mach_absolute_time */
TIME_t TIME_getTime(void)
{
static mach_timebase_info_data_t rate;
static int init = 0;
if (!init) {
mach_timebase_info(&rate);
init = 1;
}
{
TIME_t r;
r.t = mach_absolute_time() * (Duration_ns)rate.numer
/ (Duration_ns)rate.denom;
return r;
}
}
/* POSIX.1-2001 (optional) */
#elif defined(CLOCK_MONOTONIC)
#include <stdlib.h> /* abort */
#include <stdio.h> /* perror */
TIME_t TIME_getTime(void)
{
/* time must be initialized, othersize it may fail msan test.
* No good reason, likely a limitation of timespec_get() for some target */
struct timespec time = { 0, 0 };
if (clock_gettime(CLOCK_MONOTONIC, &time) != 0) {
perror("timefn::clock_gettime(CLOCK_MONOTONIC)");
abort();
}
{ TIME_t r;
r.t = (Duration_ns)time.tv_sec * 1000000000ULL
+ (Duration_ns)time.tv_nsec;
return r;
}
}
/* C11 requires support of timespec_get().
* However, FreeBSD 11 claims C11 compliance while lacking timespec_get().
* Double confirm timespec_get() support by checking the definition of TIME_UTC.
* However, some versions of Android manage to simultaneously define TIME_UTC
* and lack timespec_get() support... */
#elif (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* C11 */) \
&& defined(TIME_UTC) && !defined(__ANDROID__)
# include <stdio.h> /* perror */
# include <stdlib.h> /* abort */
TIME_t TIME_getTime(void)
{
/* time must be initialized, othersize it may fail msan test */
struct timespec time = { 0, 0 };
if (timespec_get(&time, TIME_UTC) != TIME_UTC) {
perror("timefn::timespec_get(TIME_UTC)");
abort();
}
{
TIME_t r;
r.t = (Duration_ns)time.tv_sec * 1000000000ULL
+ (Duration_ns)time.tv_nsec;
return r;
}
}
#else /* relies on standard C90 (note : clock_t produces wrong measurements \
for multi-threaded workloads) */
TIME_t TIME_getTime(void)
{
TIME_t r;
r.t = (Duration_ns)clock() * 1000000000ULL / CLOCKS_PER_SEC;
return r;
}
# define TIME_MT_MEASUREMENTS_NOT_SUPPORTED
#endif
/* ==== Common functions, valid for all time API ==== */
Duration_ns TIME_span_ns(TIME_t clockStart, TIME_t clockEnd)
{
return clockEnd.t - clockStart.t;
}
Duration_ns TIME_clockSpan_ns(TIME_t clockStart)
{
TIME_t const clockEnd = TIME_getTime();
return TIME_span_ns(clockStart, clockEnd);
}
void TIME_waitForNextTick(void)
{
TIME_t const clockStart = TIME_getTime();
TIME_t clockEnd;
do {
clockEnd = TIME_getTime();
} while (TIME_span_ns(clockStart, clockEnd) == 0);
}
int TIME_support_MT_measurements(void)
{
#if defined(TIME_MT_MEASUREMENTS_NOT_SUPPORTED)
return 0;
#else
return 1;
#endif
}

72
expkg/vendor/lz4/programs/timefn.h vendored Normal file
View File

@ -0,0 +1,72 @@
/*
timefn.h - portable time measurement functions
Copyright (c) Yann Collet. All rights reserved.
GPL v2 License
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
You can contact the author at :
- LZ4 source repository : https://github.com/lz4/lz4
- LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
*/
#ifndef TIMEFN
#define TIMEFN
#if defined(__cplusplus)
extern "C" {
#endif
/*-****************************************
* Types
******************************************/
typedef unsigned long long Duration_ns;
/* TIME_t contains a nanosecond time counter.
* The absolute value is not meaningful.
* It's only valid to compute Duration_ns between 2 measurements. */
typedef struct {
Duration_ns t;
} TIME_t;
#define TIME_INITIALIZER { 0 }
/*-****************************************
* Time functions
******************************************/
/* @return a TIME_t value to be compared to another one in order to compute a duration.
* The absolute value returned is meaningless */
TIME_t TIME_getTime(void);
/* Timer resolution can be low on some platforms.
* To improve accuracy, it's recommended to wait for a new tick
* before starting benchmark measurements */
void TIME_waitForNextTick(void);
/* tells if TIME_getTime() returns correct time measurements
* in scenarios involving multi-threaded workload.
* note : this is not the case if only C90 clock_t measurements are available */
int TIME_support_MT_measurements(void);
Duration_ns TIME_span_ns(TIME_t clockStart, TIME_t clockEnd);
Duration_ns TIME_clockSpan_ns(TIME_t clockStart);
#if defined(__cplusplus)
}
#endif
#endif /* TIMEFN */

165
expkg/vendor/lz4/programs/util.c vendored Normal file
View File

@ -0,0 +1,165 @@
/*
util.h - utility functions
Copyright (c) Yann Collet. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#if defined (__cplusplus)
extern "C" {
#endif
/*-****************************************
* Dependencies
******************************************/
#include "util.h" /* note : ensure that platform.h is included first ! */
/*-****************************************
* count the number of cores
******************************************/
#if defined(_WIN32)
#include <windows.h>
int UTIL_countCores(void)
{
static int numCores = 0;
if (numCores != 0) return numCores;
{ SYSTEM_INFO sysinfo;
GetSystemInfo(&sysinfo);
numCores = sysinfo.dwNumberOfProcessors;
}
if (numCores == 0) {
/* Unexpected result, fall back on 1 */
return numCores = 1;
}
return numCores;
}
#elif defined(__APPLE__)
#include <sys/sysctl.h>
/* Use apple-provided syscall
* see: man 3 sysctl */
int UTIL_countCores(void)
{
static S32 numCores = 0; /* apple specifies int32_t */
if (numCores != 0) return (int)numCores;
{ size_t size = sizeof(S32);
int const ret = sysctlbyname("hw.logicalcpu", &numCores, &size, NULL, 0);
if (ret != 0) {
/* error: fall back on 1 */
numCores = 1;
}
}
return (int)numCores;
}
#elif defined(__linux__)
int UTIL_countCores(void)
{
static int numCores = 0;
if (numCores != 0) return numCores;
numCores = (int)sysconf(_SC_NPROCESSORS_ONLN);
if (numCores == -1) {
/* value not queryable, fall back on 1 */
return numCores = 1;
}
return numCores;
}
#elif defined(__FreeBSD__)
#include <stdio.h> /* perror */
#include <errno.h>
#include <sys/param.h>
#include <sys/sysctl.h>
/* Use physical core sysctl when available
* see: man 4 smp, man 3 sysctl */
int UTIL_countCores(void)
{
static int numCores = 0; /* freebsd sysctl is native int sized */
if (numCores != 0) return numCores;
#if __FreeBSD_version >= 1300008
{ size_t size = sizeof(numCores);
int ret = sysctlbyname("kern.smp.cores", &numCores, &size, NULL, 0);
if (ret == 0) {
int perCore = 1;
ret = sysctlbyname("kern.smp.threads_per_core", &perCore, &size, NULL, 0);
/* default to physical cores if logical cannot be read */
if (ret != 0) /* error */
return numCores;
numCores *= perCore;
return numCores;
}
if (errno != ENOENT) {
perror("lz4: can't get number of cpus");
exit(1);
}
/* sysctl not present, fall through to older sysconf method */
}
#endif
numCores = (int)sysconf(_SC_NPROCESSORS_ONLN);
if (numCores == -1) {
/* value not queryable, fall back on 1 */
numCores = 1;
}
return numCores;
}
#elif defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__CYGWIN__)
/* Use POSIX sysconf
* see: man 3 sysconf */
int UTIL_countCores(void)
{
static int numCores = 0;
if (numCores != 0) return numCores;
numCores = (int)sysconf(_SC_NPROCESSORS_ONLN);
if (numCores == -1) {
/* value not queryable, fall back on 1 */
numCores = 1;
}
return numCores;
}
#else
int UTIL_countCores(void)
{
/* no clue */
return 1;
}
#endif
#if defined (__cplusplus)
}
#endif

574
expkg/vendor/lz4/programs/util.h vendored Normal file
View File

@ -0,0 +1,574 @@
/*
util.h - utility functions
Copyright (c) Yann Collet. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef UTIL_H_MODULE
#define UTIL_H_MODULE
#if defined (__cplusplus)
extern "C" {
#endif
/*-****************************************
* Dependencies
******************************************/
#include "platform.h" /* PLATFORM_POSIX_VERSION */
#include <stddef.h> /* size_t, ptrdiff_t */
#include <stdlib.h> /* malloc */
#include <string.h> /* strlen, strncpy */
#include <stdio.h> /* fprintf, fileno */
#include <assert.h>
#include <sys/types.h> /* stat, utime */
#include <sys/stat.h> /* stat */
#if defined(_WIN32)
# include <sys/utime.h> /* utime */
# include <io.h> /* _chmod */
#else
# include <unistd.h> /* chown, stat */
# if PLATFORM_POSIX_VERSION < 200809L
# include <utime.h> /* utime */
# else
# include <fcntl.h> /* AT_FDCWD */
# include <sys/stat.h> /* for utimensat */
# endif
#endif
#include <time.h> /* time */
#include <limits.h> /* INT_MAX */
#include <errno.h>
/*-**************************************************************
* Basic Types
*****************************************************************/
#if !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )
# include <stdint.h>
typedef uint8_t BYTE;
typedef uint16_t U16;
typedef int16_t S16;
typedef uint32_t U32;
typedef int32_t S32;
typedef uint64_t U64;
typedef int64_t S64;
#else
typedef unsigned char BYTE;
typedef unsigned short U16;
typedef signed short S16;
typedef unsigned int U32;
typedef signed int S32;
typedef unsigned long long U64;
typedef signed long long S64;
#endif
/* ************************************************************
* Avoid fseek()'s 2GiB barrier with MSVC, MacOS, *BSD, MinGW
***************************************************************/
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
# define UTIL_fseek _fseeki64
#elif !defined(__64BIT__) && (PLATFORM_POSIX_VERSION >= 200112L) /* No point defining Large file for 64 bit */
# define UTIL_fseek fseeko
#elif defined(__MINGW32__) && defined(__MSVCRT__) && !defined(__STRICT_ANSI__) && !defined(__NO_MINGW_LFS)
# define UTIL_fseek fseeko64
#else
# define UTIL_fseek fseek
#endif
/*-****************************************
* Local host Core counting
******************************************/
int UTIL_countCores(void);
/*-****************************************
* Sleep functions: Windows - Posix - others
******************************************/
#if defined(_WIN32)
# include <windows.h>
# define SET_REALTIME_PRIORITY SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS)
# define UTIL_sleep(s) Sleep(1000*s)
# define UTIL_sleepMilli(milli) Sleep(milli)
#elif PLATFORM_POSIX_VERSION >= 0 /* Unix-like operating system */
# include <unistd.h>
# include <sys/resource.h> /* setpriority */
# include <time.h> /* clock_t, nanosleep, clock, CLOCKS_PER_SEC */
# if defined(PRIO_PROCESS)
# define SET_REALTIME_PRIORITY setpriority(PRIO_PROCESS, 0, -20)
# else
# define SET_REALTIME_PRIORITY /* disabled */
# endif
# define UTIL_sleep(s) sleep(s)
# if (defined(__linux__) && (PLATFORM_POSIX_VERSION >= 199309L)) || (PLATFORM_POSIX_VERSION >= 200112L) /* nanosleep requires POSIX.1-2001 */
# define UTIL_sleepMilli(milli) { struct timespec t; t.tv_sec=0; t.tv_nsec=milli*1000000ULL; nanosleep(&t, NULL); }
# else
# define UTIL_sleepMilli(milli) /* disabled */
# endif
#else
# define SET_REALTIME_PRIORITY /* disabled */
# define UTIL_sleep(s) /* disabled */
# define UTIL_sleepMilli(milli) /* disabled */
#endif
/*-****************************************
* stat() functions
******************************************/
#if defined(_MSC_VER)
# define UTIL_TYPE_stat __stat64
# define UTIL_stat _stat64
# define UTIL_fstat _fstat64
# define UTIL_STAT_MODE_ISREG(st_mode) ((st_mode) & S_IFREG)
#elif defined(__MINGW32__) && defined (__MSVCRT__)
# define UTIL_TYPE_stat _stati64
# define UTIL_stat _stati64
# define UTIL_fstat _fstati64
# define UTIL_STAT_MODE_ISREG(st_mode) ((st_mode) & S_IFREG)
#else
# define UTIL_TYPE_stat stat
# define UTIL_stat stat
# define UTIL_fstat fstat
# define UTIL_STAT_MODE_ISREG(st_mode) (S_ISREG(st_mode))
#endif
/*-****************************************
* fileno() function
******************************************/
#if defined(_MSC_VER)
# define UTIL_fileno _fileno
#else
# define UTIL_fileno fileno
#endif
/* *************************************
* Constants
***************************************/
#define LIST_SIZE_INCREASE (8*1024)
/*-****************************************
* Compiler specifics
******************************************/
#if defined(__INTEL_COMPILER)
# pragma warning(disable : 177) /* disable: message #177: function was declared but never referenced, useful with UTIL_STATIC */
#endif
#if defined(__GNUC__)
# define UTIL_STATIC static __attribute__((unused))
#elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
# define UTIL_STATIC static inline
#elif defined(_MSC_VER)
# define UTIL_STATIC static __inline
#else
# define UTIL_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */
#endif
/*-****************************************
* Allocation functions
******************************************/
/*
* A modified version of realloc().
* Original block is always freed.
*/
UTIL_STATIC void* UTIL_realloc(void* prevPtr, size_t newSize)
{
if (newSize == 0) {
free(prevPtr);
return NULL;
}
/* newSize > 0 */
{ void* const newptr = realloc(prevPtr, newSize);
if (newptr) return newptr;
}
/* realloc failed */
free(prevPtr);
return NULL;
}
/*-****************************************
* String functions
******************************************/
/* supports a==NULL or b==NULL */
UTIL_STATIC int UTIL_sameString(const char* a, const char* b)
{
assert(a != NULL || b != NULL); /* unsupported scenario */
if (a==NULL) return 0;
if (b==NULL) return 0;
return !strcmp(a,b);
}
/*-****************************************
* File functions
******************************************/
#if defined(_MSC_VER)
#define chmod _chmod
typedef struct __stat64 stat_t;
#else
typedef struct stat stat_t;
#endif
UTIL_STATIC int UTIL_isRegFile(const char* infilename);
UTIL_STATIC int UTIL_isRegFD(int fd);
UTIL_STATIC int UTIL_setFileStat(const char *filename, stat_t *statbuf)
{
int res = 0;
if (!UTIL_isRegFile(filename))
return -1;
{
#if defined(_WIN32) || (PLATFORM_POSIX_VERSION < 200809L)
struct utimbuf timebuf;
timebuf.actime = time(NULL);
timebuf.modtime = statbuf->st_mtime;
res += utime(filename, &timebuf); /* set access and modification times */
#else
struct timespec timebuf[2];
memset(timebuf, 0, sizeof(timebuf));
timebuf[0].tv_nsec = UTIME_NOW;
timebuf[1].tv_sec = statbuf->st_mtime;
res += utimensat(AT_FDCWD, filename, timebuf, 0); /* set access and modification times */
#endif
}
#if !defined(_WIN32)
res += chown(filename, statbuf->st_uid, statbuf->st_gid); /* Copy ownership */
#endif
res += chmod(filename, statbuf->st_mode & 07777); /* Copy file permissions */
errno = 0;
return -res; /* number of errors is returned */
}
UTIL_STATIC int UTIL_getFDStat(int fd, stat_t *statbuf)
{
int r;
#if defined(_MSC_VER)
r = _fstat64(fd, statbuf);
if (r || !(statbuf->st_mode & S_IFREG)) return 0; /* No good... */
#else
r = fstat(fd, statbuf);
if (r || !S_ISREG(statbuf->st_mode)) return 0; /* No good... */
#endif
return 1;
}
UTIL_STATIC int UTIL_getFileStat(const char* infilename, stat_t *statbuf)
{
int r;
#if defined(_MSC_VER)
r = _stat64(infilename, statbuf);
if (r || !(statbuf->st_mode & S_IFREG)) return 0; /* No good... */
#else
r = stat(infilename, statbuf);
if (r || !S_ISREG(statbuf->st_mode)) return 0; /* No good... */
#endif
return 1;
}
UTIL_STATIC int UTIL_isRegFD(int fd)
{
stat_t statbuf;
#ifdef _WIN32
/* Windows runtime library always open file descriptors 0, 1 and 2 in text mode, therefore we can't use them for binary I/O */
if(fd < 3) return 0;
#endif
return UTIL_getFDStat(fd, &statbuf); /* Only need to know whether it is a regular file */
}
UTIL_STATIC int UTIL_isRegFile(const char* infilename)
{
stat_t statbuf;
return UTIL_getFileStat(infilename, &statbuf); /* Only need to know whether it is a regular file */
}
UTIL_STATIC int UTIL_isDirectory(const char* infilename)
{
stat_t statbuf;
int r;
#if defined(_MSC_VER)
r = _stat64(infilename, &statbuf);
if (r) return 0;
return (statbuf.st_mode & S_IFDIR);
#else
r = stat(infilename, &statbuf);
if (r) return 0;
return (S_ISDIR(statbuf.st_mode));
#endif
}
UTIL_STATIC U64 UTIL_getOpenFileSize(FILE* file)
{
int r;
int fd;
struct UTIL_TYPE_stat statbuf;
fd = UTIL_fileno(file);
if (fd < 0) {
perror("fileno");
exit(1);
}
r = UTIL_fstat(fd, &statbuf);
if (r || !UTIL_STAT_MODE_ISREG(statbuf.st_mode)) return 0; /* No good... */
return (U64)statbuf.st_size;
}
UTIL_STATIC U64 UTIL_getFileSize(const char* infilename)
{
int r;
struct UTIL_TYPE_stat statbuf;
r = UTIL_stat(infilename, &statbuf);
if (r || !UTIL_STAT_MODE_ISREG(statbuf.st_mode)) return 0; /* No good... */
return (U64)statbuf.st_size;
}
UTIL_STATIC U64 UTIL_getTotalFileSize(const char** fileNamesTable, unsigned nbFiles)
{
U64 total = 0;
unsigned n;
for (n=0; n<nbFiles; n++)
total += UTIL_getFileSize(fileNamesTable[n]);
return total;
}
#ifdef _WIN32
# define UTIL_HAS_CREATEFILELIST
UTIL_STATIC int UTIL_prepareFileList(const char* dirName, char** bufStart, size_t* pos, char** bufEnd)
{
char* path;
size_t dirLength, nbFiles = 0;
WIN32_FIND_DATAA cFile;
HANDLE hFile;
dirLength = strlen(dirName);
path = (char*) malloc(dirLength + 3);
if (!path) return 0;
memcpy(path, dirName, dirLength);
path[dirLength] = '\\';
path[dirLength+1] = '*';
path[dirLength+2] = 0;
hFile=FindFirstFileA(path, &cFile);
if (hFile == INVALID_HANDLE_VALUE) {
fprintf(stderr, "Cannot open directory '%s'\n", dirName);
return 0;
}
free(path);
do {
size_t pathLength;
int const fnameLength = (int)strlen(cFile.cFileName);
path = (char*) malloc(dirLength + fnameLength + 2);
if (!path) { FindClose(hFile); return 0; }
memcpy(path, dirName, dirLength);
path[dirLength] = '\\';
memcpy(path+dirLength+1, cFile.cFileName, fnameLength);
pathLength = dirLength+1+fnameLength;
path[pathLength] = 0;
if (cFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
if (strcmp (cFile.cFileName, "..") == 0 ||
strcmp (cFile.cFileName, ".") == 0) continue;
nbFiles += UTIL_prepareFileList(path, bufStart, pos, bufEnd); /* Recursively call "UTIL_prepareFileList" with the new path. */
if (*bufStart == NULL) { free(path); FindClose(hFile); return 0; }
}
else if ((cFile.dwFileAttributes & FILE_ATTRIBUTE_NORMAL) || (cFile.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) || (cFile.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED)) {
if (*bufStart + *pos + pathLength >= *bufEnd) {
ptrdiff_t newListSize = (*bufEnd - *bufStart) + LIST_SIZE_INCREASE;
*bufStart = (char*)UTIL_realloc(*bufStart, newListSize);
*bufEnd = *bufStart + newListSize;
if (*bufStart == NULL) { free(path); FindClose(hFile); return 0; }
}
if (*bufStart + *pos + pathLength < *bufEnd) {
strncpy(*bufStart + *pos, path, *bufEnd - (*bufStart + *pos));
*pos += pathLength + 1;
nbFiles++;
}
}
free(path);
} while (FindNextFileA(hFile, &cFile));
FindClose(hFile);
assert(nbFiles < INT_MAX);
return (int)nbFiles;
}
#elif defined(__linux__) || (PLATFORM_POSIX_VERSION >= 200112L) /* opendir, readdir require POSIX.1-2001 */
# define UTIL_HAS_CREATEFILELIST
# include <dirent.h> /* opendir, readdir */
# include <string.h> /* strerror, memcpy */
UTIL_STATIC int UTIL_prepareFileList(const char* dirName, char** bufStart, size_t* pos, char** bufEnd)
{
DIR* dir;
struct dirent * entry;
size_t dirLength;
int nbFiles = 0;
if (!(dir = opendir(dirName))) {
fprintf(stderr, "Cannot open directory '%s': %s\n", dirName, strerror(errno));
return 0;
}
dirLength = strlen(dirName);
errno = 0;
while ((entry = readdir(dir)) != NULL) {
char* path;
size_t fnameLength, pathLength;
if (strcmp (entry->d_name, "..") == 0 ||
strcmp (entry->d_name, ".") == 0) continue;
fnameLength = strlen(entry->d_name);
path = (char*)malloc(dirLength + fnameLength + 2);
if (!path) { closedir(dir); return 0; }
memcpy(path, dirName, dirLength);
path[dirLength] = '/';
memcpy(path+dirLength+1, entry->d_name, fnameLength);
pathLength = dirLength+1+fnameLength;
path[pathLength] = 0;
if (UTIL_isDirectory(path)) {
nbFiles += UTIL_prepareFileList(path, bufStart, pos, bufEnd); /* Recursively call "UTIL_prepareFileList" with the new path. */
if (*bufStart == NULL) { free(path); closedir(dir); return 0; }
} else {
if (*bufStart + *pos + pathLength >= *bufEnd) {
size_t const newListSize = (size_t)(*bufEnd - *bufStart) + LIST_SIZE_INCREASE;
*bufStart = (char*)UTIL_realloc(*bufStart, newListSize);
*bufEnd = *bufStart + newListSize;
if (*bufStart == NULL) { free(path); closedir(dir); return 0; }
}
if (*bufStart + *pos + pathLength < *bufEnd) {
strncpy(*bufStart + *pos, path, *bufEnd - (*bufStart + *pos));
*pos += pathLength + 1;
nbFiles++;
}
}
free(path);
errno = 0; /* clear errno after UTIL_isDirectory, UTIL_prepareFileList */
}
if (errno != 0) {
fprintf(stderr, "readdir(%s) error: %s\n", dirName, strerror(errno));
free(*bufStart);
*bufStart = NULL;
}
closedir(dir);
return nbFiles;
}
#else
UTIL_STATIC int UTIL_prepareFileList(const char* dirName, char** bufStart, size_t* pos, char** bufEnd)
{
(void)bufStart; (void)bufEnd; (void)pos;
fprintf(stderr, "Directory %s ignored (compiled without _WIN32 or _POSIX_C_SOURCE)\n", dirName);
return 0;
}
#endif /* #ifdef _WIN32 */
/*
* UTIL_createFileList - takes a list of files and directories (params: inputNames, inputNamesNb), scans directories,
* and returns a new list of files (params: return value, allocatedBuffer, allocatedNamesNb).
* After finishing usage of the list the structures should be freed with UTIL_freeFileList(params: return value, allocatedBuffer)
* In case of error UTIL_createFileList returns NULL and UTIL_freeFileList should not be called.
*/
UTIL_STATIC const char**
UTIL_createFileList(const char** inputNames, unsigned inputNamesNb,
char** allocatedBuffer, unsigned* allocatedNamesNb)
{
size_t pos;
unsigned i, nbFiles;
char* buf = (char*)malloc(LIST_SIZE_INCREASE);
size_t bufSize = LIST_SIZE_INCREASE;
const char** fileTable;
if (!buf) return NULL;
for (i=0, pos=0, nbFiles=0; i<inputNamesNb; i++) {
if (!UTIL_isDirectory(inputNames[i])) {
size_t const len = strlen(inputNames[i]) + 1; /* include nul char */
if (pos + len >= bufSize) {
while (pos + len >= bufSize) bufSize += LIST_SIZE_INCREASE;
buf = (char*)UTIL_realloc(buf, bufSize);
if (!buf) return NULL;
}
assert(pos + len < bufSize);
memcpy(buf + pos, inputNames[i], len);
pos += len;
nbFiles++;
} else {
char* bufend = buf + bufSize;
nbFiles += (unsigned)UTIL_prepareFileList(inputNames[i], &buf, &pos, &bufend);
if (buf == NULL) return NULL;
assert(bufend > buf);
bufSize = (size_t)(bufend - buf);
} }
if (nbFiles == 0) { free(buf); return NULL; }
fileTable = (const char**)malloc(((size_t)nbFiles+1) * sizeof(const char*));
if (!fileTable) { free(buf); return NULL; }
for (i=0, pos=0; i<nbFiles; i++) {
fileTable[i] = buf + pos;
pos += strlen(fileTable[i]) + 1;
}
if (pos > bufSize) {
free(buf);
free((void*)fileTable);
return NULL;
} /* can this happen ? */
*allocatedBuffer = buf;
*allocatedNamesNb = nbFiles;
return fileTable;
}
UTIL_STATIC void
UTIL_freeFileList(const char** filenameTable, char* allocatedBuffer)
{
free(allocatedBuffer);
free((void*)filenameTable);
}
#if defined (__cplusplus)
}
#endif
#endif /* UTIL_H_MODULE */