pax_global_header00006660000000000000000000000064126613224420014514gustar00rootroot0000000000000052 comment=c580b75eb1ad0f654659ab434f322ac0337b8219 zstd-0.5.1/000077500000000000000000000000001266132244200125035ustar00rootroot00000000000000zstd-0.5.1/.gitattributes000066400000000000000000000003601266132244200153750ustar00rootroot00000000000000# Set the default behavior * text eol=lf # Explicitly declare source files *.c text eol=lf *.h text eol=lf # Denote files that should not be modified. *.odt binary *.png binary # Visual Studio *.sln binary *.suo binary *.vcxproj* binary zstd-0.5.1/.gitignore000066400000000000000000000007371266132244200145020ustar00rootroot00000000000000# Object files *.o *.ko # Libraries *.lib *.a # Shared objects (inc. Windows DLLs) *.dll *.so *.so.* *.dylib # Executables *.exe *.out *.app # Visual solution files *.suo *.user # Build results [Dd]ebug/ [Rr]elease/ [Rr]eleases/ x64/ x86/ [Bb]in/ [Oo]bj/ # Visual C++ cache files ipch/ *.aps *.ncb *.opendb *.opensdf *.sdf *.cachefile # IDEA solution files *.idea # Other files .directory _codelite _zstdbench lib/zstd_opt_LZ5.c lib/zstd_opt_llen.c lib/zstd_opt_nollen.czstd-0.5.1/.travis.yml000066400000000000000000000013661266132244200146220ustar00rootroot00000000000000language: c before_install: - sudo apt-get update -qq - sudo apt-get install -qq clang - sudo apt-get install -qq g++-multilib - sudo apt-get install -qq gcc-multilib - sudo apt-get install -qq valgrind env: - ZSTD_TRAVIS_CI_ENV=travis-install - ZSTD_TRAVIS_CI_ENV=cmaketest - ZSTD_TRAVIS_CI_ENV=clangtest - ZSTD_TRAVIS_CI_ENV=gpptest - ZSTD_TRAVIS_CI_ENV=armtest-w-install - ZSTD_TRAVIS_CI_ENV=test - ZSTD_TRAVIS_CI_ENV="-C programs test32" - ZSTD_TRAVIS_CI_ENV="-C programs test-zstd_nolegacy" - ZSTD_TRAVIS_CI_ENV=usan - ZSTD_TRAVIS_CI_ENV=asan - ZSTD_TRAVIS_CI_ENV=asan32 - ZSTD_TRAVIS_CI_ENV="-C programs valgrindTest" compiler: gcc script: - make $ZSTD_TRAVIS_CI_ENV matrix: fast_finish: true zstd-0.5.1/Makefile000066400000000000000000000102351266132244200141440ustar00rootroot00000000000000# ################################################################ # zstd - Makefile # Copyright (C) Yann Collet 2014-2016 # All rights reserved. # # BSD license # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright notice, this # list of conditions and the following disclaimer in the documentation and/or # other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # You can contact the author at : # - zstd homepage : http://www.zstd.net/ # ################################################################ # force a version number : uncomment below export (otherwise, default to the one declared into zstd.h) #export VERSION := 0.5.1 PRGDIR = programs ZSTDDIR = lib # Define nul output ifneq (,$(filter Windows%,$(OS))) VOID = nul else VOID = /dev/null endif .PHONY: default all zstdprogram clean install uninstall travis-install test clangtest gpptest armtest usan asan uasan default: zstdprogram all: $(MAKE) -C $(ZSTDDIR) $@ $(MAKE) -C $(PRGDIR) $@ zstdprogram: $(MAKE) -C $(PRGDIR) clean: @$(MAKE) -C $(ZSTDDIR) $@ > $(VOID) @$(MAKE) -C $(PRGDIR) $@ > $(VOID) @echo Cleaning completed #------------------------------------------------------------------------ #make install is validated only for Linux, OSX, kFreeBSD and Hurd targets ifneq (,$(filter $(shell uname),Linux Darwin GNU/kFreeBSD GNU)) install: $(MAKE) -C $(ZSTDDIR) $@ $(MAKE) -C $(PRGDIR) $@ uninstall: $(MAKE) -C $(ZSTDDIR) $@ $(MAKE) -C $(PRGDIR) $@ travis-install: $(MAKE) install PREFIX=~/install_test_dir test: $(MAKE) -C $(PRGDIR) $@ cmaketest: cd contrib/cmake ; cmake . ; $(MAKE) clangtest: clean clang -v $(MAKE) all CC=clang MOREFLAGS="-Werror -Wconversion -Wno-sign-conversion" gpptest: clean $(MAKE) all CC=g++ CFLAGS="-O3 -Wall -Wextra -Wundef -Wshadow -Wcast-align -Werror" armtest: clean # $(MAKE) -C $(ZSTDDIR) all CC=arm-linux-gnueabi-gcc MOREFLAGS="-Werror" $(MAKE) -C $(PRGDIR) datagen # use native, faster $(MAKE) -C $(PRGDIR) test CC=arm-linux-gnueabi-gcc ZSTDRTTEST= MOREFLAGS=-static # MOREFLAGS="-Werror -static" # for Travis CI arminstall: clean sudo apt-get install -q qemu sudo apt-get install -q binfmt-support sudo apt-get install -q qemu-user-static sudo apt-get install -q gcc-arm-linux-gnueabi # for Travis CI armtest-w-install: clean arminstall armtest ppctest: clean $(MAKE) -C $(PRGDIR) datagen # use native, faster $(MAKE) -C $(PRGDIR) test CC=powerpc-linux-gnu-gcc ZSTDRTTEST= MOREFLAGS=-static # MOREFLAGS="-Werror -static" # for Travis CI ppcinstall: clean sudo apt-get install -q qemu sudo apt-get install -q binfmt-support sudo apt-get install -q qemu-user-static sudo apt-get update -q sudo apt-get install -q gcc-powerpc-linux-gnu # unfortunately, doesn't work on Travis CI (package not available) # for Travis CI ppctest-w-install: clean ppcinstall ppctest usan: clean $(MAKE) test CC=clang MOREFLAGS="-g -fsanitize=undefined" asan: clean $(MAKE) test CC=clang MOREFLAGS="-g -fsanitize=address" asan32: clean $(MAKE) -C $(PRGDIR) test32 CC=clang MOREFLAGS="-g -fsanitize=address" uasan: clean $(MAKE) test CC=clang MOREFLAGS="-g -fsanitize=address -fsanitize=undefined" endif zstd-0.5.1/NEWS000066400000000000000000000042321266132244200132030ustar00rootroot00000000000000v0.5.1 New : Optimal parsing => Very high compression modes, thanks to Przemyslaw Skibinski Changed : Dictionary builder integrated into libzstd and zstd cli Changed (!) : zstd cli now uses "multiple input files" as default mode. See `zstd -h`. Fix : high compression modes for big-endian platforms New : zstd cli : `-t` | `--test` command v0.5.0 New : dictionary builder utility Changed : streaming & dictionary API Improved : better compression of small data v0.4.7 Improved : small compression speed improvement in HC mode Changed : `zstd_decompress.c` has ZSTD_LEGACY_SUPPORT to 0 by default fix : bt search bug v0.4.6 fix : fast compression mode on Windows New : cmake configuration file, thanks to Artyom Dymchenko Improved : high compression mode on repetitive data New : block-level API New : ZSTD_duplicateCCtx() v0.4.5 new : -m/--multiple : compress/decompress multiple files v0.4.4 Fixed : high compression modes for Windows 32 bits new : external dictionary API extended to buffered mode and accessible through command line new : windows DLL project, thanks to Christophe Chevalier v0.4.3 : new : external dictionary API new : zstd-frugal v0.4.2 : Generic minor improvements for small blocks Fixed : big-endian compatibility, by Peter Harris (#85) v0.4.1 Fixed : ZSTD_LEGACY_SUPPORT=0 build mode (reported by Luben) removed `zstd.c` v0.4.0 Command line utility compatible with high compression levels Removed zstdhc => merged into zstd Added : ZBUFF API (see zstd_buffered.h) Rolling buffer support v0.3.6 small blocks params v0.3.5 minor generic compression improvements v0.3.4 Faster fast cLevels v0.3.3 Small compression ratio improvement v0.3.2 Fixed Visual Studio v0.3.1 : Small compression ratio improvement v0.3 HC mode : compression levels 2-26 v0.2.2 Fix : Visual Studio 2013 & 2015 release compilation, by Christophe Chevalier v0.2.1 Fix : Read errors, advanced fuzzer tests, by Hanno Böck v0.2.0 **Breaking format change** Faster decompression speed Can still decode v0.1 format v0.1.3 fix uninitialization warning, reported by Evan Nemerson v0.1.2 frame concatenation support v0.1.1 fix compression bug detects write-flush errors v0.1.0 first release zstd-0.5.1/README.md000066400000000000000000000156341266132244200137730ustar00rootroot00000000000000 **Zstd**, short for Zstandard, is a fast lossless compression algorithm, targeting real-time compression scenarios at zlib-level compression ratio. It is provided as a BSD-license package, hosted on Github. |Branch |Status | |------------|---------| |master | [![Build Status](https://travis-ci.org/Cyan4973/zstd.svg?branch=master)](https://travis-ci.org/Cyan4973/zstd) | |dev | [![Build Status](https://travis-ci.org/Cyan4973/zstd.svg?branch=dev)](https://travis-ci.org/Cyan4973/zstd) | As a reference, several fast compression algorithms were tested and compared to [zlib] on a Core i7-3930K CPU @ 4.5GHz, using [lzbench], an open-source in-memory benchmark by @inikep compiled with gcc 5.2.1, on the [Silesia compression corpus]. [lzbench]: https://github.com/inikep/lzbench [Silesia compression corpus]: http://sun.aei.polsl.pl/~sdeor/index.php?page=silesia |Name | Ratio | C.speed | D.speed | |-----------------|-------|--------:|--------:| | | | MB/s | MB/s | |**zstd 0.5.1 -1**|**2.876**|**330**| **890** | | [zlib] 1.2.8 -1 | 2.730 | 95 | 360 | | brotli -0 | 2.708 | 220 | 430 | | QuickLZ 1.5 | 2.237 | 510 | 605 | | LZO 2.09 | 2.106 | 610 | 870 | | [LZ4] r131 | 2.101 | 620 | 3100 | | Snappy 1.1.3 | 2.091 | 480 | 1600 | | LZF 3.6 | 2.077 | 375 | 790 | [zlib]:http://www.zlib.net/ [LZ4]: http://www.lz4.org/ Zstd can also offer stronger compression ratio at the cost of compression speed. Speed vs Compression trade-off is configurable by small increment. Decompression speed is preserved and remain roughly the same at all settings, a property shared by most LZ compression algorithms, such as [zlib]. The following test is run on a Core i7-3930K CPU @ 4.5GHz, using [lzbench], an open-source in-memory benchmark by @inikep compiled with gcc 5.2.1, on the [Silesia compression corpus]. Compression Speed vs Ratio | Decompression Speed ---------------------------|-------------------- ![Compression Speed vs Ratio](images/Cspeed4.png "Compression Speed vs Ratio") | ![Decompression Speed](images/Dspeed4.png "Decompression Speed") Several algorithms can produce higher compression ratio at slower speed, falling outside of the graph. For a larger picture including very slow modes, [click on this link](images/DCspeed5.png) . ### The case for Small Data compression Above chart provides results applicable to large files or large streams scenarios (200 MB for this case). Small data (< 64 KB) come with different perspectives. The smaller the amount of data to compress, the more difficult it is to achieve any significant compression. On reaching the 1 KB region, it becomes almost impossible to compress anything. This problem is common to any compression algorithms, and throwing CPU power at it achieves little gains. The reason is, compression algorithms learn from past data how to compress future data. But at the beginning of a new file, there is no "past" to build upon. To solve this situation, Zstd now offers a __training mode__, which can be used to make the algorithm fit a selected type of data, by providing it with some samples. The result of the training is a file called "dictionary", which can be loaded before compression and decompression. Using this dictionary, the compression ratio achievable on small data improves dramatically : | Collection Name | Direct compression | Dictionary Compression | Gains | Average unit | Range | | --------------- | ------------------ | ---------------------- | --------- | ------------:| ----- | | Small JSON records | x1.331 - x1.366 | x5.860 - x6.830 | ~ __x4.7__ | 300 | 200 - 400 | | Mercurial events | x2.322 - x2.538 | x3.377 - x4.462 | ~ __x1.5__ | 1.5 KB | 20 - 200 KB | | Large JSON docs | x3.813 - x4.043 | x8.935 - x13.366 | ~ __x2.8__ | 6 KB | 800 - 20 KB | These compression gains are achieved without any speed loss, and prove in general a bit faster to compress and decompress. Dictionary work if there is some correlation in a family of small data (there is no _universal dictionary_). Hence, deploying one dictionary per type of data will provide the greater benefits. Large documents will benefit proportionally less, since dictionary gains are mostly effective in the first few KB. Then, the compression algorithm will rely more and more on already decoded content to compress the rest of the file. #### Dictionary compression How To : ##### _Using the Command Line Utility_ : 1) Create the dictionary `zstd --train FullPathToTrainingSet/* -o dictionaryName` 2) Compression with dictionary `zstd FILE -D dictionaryName` 3) Decompress with dictionary `zstd --decompress FILE.zst -D dictionaryName` ##### _Using API_ : 1) Create dictionary ``` #include "zdict.h" (...) /* Train a dictionary from a memory buffer `samplesBuffer`, where `nbSamples` samples have been stored concatenated. */ size_t dictSize = ZDICT_trainFromBuffer(dictBuffer, dictBufferCapacity, samplesBuffer, samplesSizes, nbSamples); ``` 2) Compression with dictionary ``` #include "zstd.h" (...) ZSTD_CCtx* context = ZSTD_createCCtx(); size_t compressedSize = ZSTD_compress_usingDict(context, dst, dstCapacity, src, srcSize, dict, dictSize, compressionLevel); ``` 3) Decompress with dictionary ``` #include "zstd.h" (...) ZSTD_DCtx* context = ZSTD_createDCtx(); size_t regeneratedSize = ZSTD_decompress_usingDict(context, dst, dstCapacity, cSrc, cSrcSize, dict, dictSize); ``` ### Status Zstd has not yet reached "stable format" status. It doesn't guarantee yet that its current compression format will remain stable in future versions. During this period, it can still change to adapt new optimizations still being investigated. "Stable Format" is projected H1 2016, and will be tagged `v1.0`. That being said, the library is now fairly robust, able to withstand hazards situations, including invalid inputs. It also features legacy support, so that documents compressed with current and previous version of zstd can still be decoded in the future. Library reliability has been tested using [Fuzz Testing](https://en.wikipedia.org/wiki/Fuzz_testing), with both [internal tools](programs/fuzzer.c) and [external ones](http://lcamtuf.coredump.cx/afl). Therefore, Zstandard is considered safe for testings, even within production environments. ### Branch Policy The "dev" branch is the one where all contributions will be merged before reaching "master". If you plan to propose a patch, please commit into the "dev" branch or its own feature branch. Direct commit to "master" are not permitted. ### Trivia Zstd entropy stage is provided by [Huff0 and FSE, from Finite State Entropy library](https://github.com/Cyan4973/FiniteStateEntropy). Its memory requirement can be configured to fit into low-memory hardware configurations, or servers handling multiple connections/contexts in parallel. zstd-0.5.1/contrib/000077500000000000000000000000001266132244200141435ustar00rootroot00000000000000zstd-0.5.1/contrib/cmake/000077500000000000000000000000001266132244200152235ustar00rootroot00000000000000zstd-0.5.1/contrib/cmake/CMakeLists.txt000066400000000000000000000053241266132244200177670ustar00rootroot00000000000000# ################################################################ # zstd - Makefile # Copyright (C) Yann Collet 2014-2016 # All rights reserved. # # BSD license # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright notice, this # list of conditions and the following disclaimer in the documentation and/or # other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # You can contact the author at : # - zstd source repository : https://github.com/Cyan4973/zstd # - Public forum : https://groups.google.com/forum/#!forum/lz4c # ################################################################ PROJECT(zstd) CMAKE_MINIMUM_REQUIRED(VERSION 2.8.7) OPTION(ZSTD_LEGACY_SUPPORT "LEGACY SUPPORT" OFF) IF (ZSTD_LEGACY_SUPPORT) MESSAGE(STATUS "ZSTD_LEGACY_SUPPORT defined!") ADD_DEFINITIONS(-DZSTD_LEGACY_SUPPORT=1) ELSE (ZSTD_LEGACY_SUPPORT) MESSAGE(STATUS "ZSTD_LEGACY_SUPPORT not defined!") ADD_DEFINITIONS(-DZSTD_LEGACY_SUPPORT=0) ENDIF (ZSTD_LEGACY_SUPPORT) # TARGET_INCLUDE_DIRECTORIES can use in version 2.8.11 and greate IF ((${CMAKE_MAJOR_VERSION} EQUAL 2) AND (${CMAKE_MINOR_VERSION} EQUAL 8) AND (${CMAKE_PATCH_VERSION} LESS 11)) SET(WORKAROUND_OUTDATED_CODE_STYLE TRUE) ELSE () SET(WORKAROUND_OUTDATED_CODE_STYLE FALSE) ENDIF ((${CMAKE_MAJOR_VERSION} EQUAL 2) AND (${CMAKE_MINOR_VERSION} EQUAL 8) AND (${CMAKE_PATCH_VERSION} LESS 11)) ADD_SUBDIRECTORY(lib) ADD_SUBDIRECTORY(programs) #----------------------------------------------------------------------------- # Add extra compilation flags #----------------------------------------------------------------------------- INCLUDE(CMakeModules/AddExtraCompilationFlags.cmake) ADD_EXTRA_COMPILATION_FLAGS() zstd-0.5.1/contrib/cmake/CMakeModules/000077500000000000000000000000001266132244200175345ustar00rootroot00000000000000zstd-0.5.1/contrib/cmake/CMakeModules/AddExtraCompilationFlags.cmake000066400000000000000000000371711266132244200254170ustar00rootroot00000000000000MACRO(ADD_EXTRA_COMPILATION_FLAGS) include(CheckCXXCompilerFlag) include(CheckCCompilerFlag) if (CMAKE_COMPILER_IS_GNUCXX OR MINGW) #Not only UNIX but also WIN32 for MinGW set(POSITION_INDEPENDENT_CODE_FLAG "-fPIC") CHECK_C_COMPILER_FLAG(${POSITION_INDEPENDENT_CODE_FLAG} POSITION_INDEPENDENT_CODE_FLAG_ALLOWED) if (POSITION_INDEPENDENT_CODE_FLAG_ALLOWED) MESSAGE("Compiler flag ${POSITION_INDEPENDENT_CODE_FLAG} allowed") set(ACTIVATE_POSITION_INDEPENDENT_CODE_FLAG "ON" CACHE BOOL "activate -fPIC flag") else () MESSAGE("Compiler flag ${POSITION_INDEPENDENT_CODE_FLAG} not allowed") endif (POSITION_INDEPENDENT_CODE_FLAG_ALLOWED) set(WARNING_UNDEF "-Wundef") CHECK_C_COMPILER_FLAG(${WARNING_UNDEF} WARNING_UNDEF_ALLOWED) if (WARNING_UNDEF_ALLOWED) MESSAGE("Compiler flag ${WARNING_UNDEF} allowed") set(ACTIVATE_WARNING_UNDEF "ON" CACHE BOOL "activate -Wundef flag") else () MESSAGE("Compiler flag ${WARNING_UNDEF} not allowed") endif (WARNING_UNDEF_ALLOWED) set(WARNING_SHADOW "-Wshadow") CHECK_C_COMPILER_FLAG(${WARNING_SHADOW} WARNING_SHADOW_ALLOWED) if (WARNING_SHADOW_ALLOWED) MESSAGE("Compiler flag ${WARNING_SHADOW} allowed") set(ACTIVATE_WARNING_SHADOW "ON" CACHE BOOL "activate -Wshadow flag") else () MESSAGE("Compiler flag ${WARNING_SHADOW} not allowed") endif (WARNING_SHADOW_ALLOWED) set(WARNING_CAST_ALIGN "-Wcast-align") CHECK_C_COMPILER_FLAG(${WARNING_CAST_ALIGN} WARNING_CAST_ALIGN_ALLOWED) if (WARNING_CAST_ALIGN_ALLOWED) MESSAGE("Compiler flag ${WARNING_CAST_ALIGN} allowed") set(ACTIVATE_WARNING_CAST_ALIGN "ON" CACHE BOOL "activate -Wcast-align flag") else () MESSAGE("Compiler flag ${WARNING_CAST_ALIGN} not allowed") endif (WARNING_CAST_ALIGN_ALLOWED) set(WARNING_CAST_QUAL "-Wcast-qual") CHECK_C_COMPILER_FLAG(${WARNING_CAST_QUAL} WARNING_CAST_QUAL_ALLOWED) if (WARNING_CAST_QUAL_ALLOWED) MESSAGE("Compiler flag ${WARNING_CAST_QUAL} allowed") set(ACTIVATE_WARNING_CAST_QUAL "ON" CACHE BOOL "activate -Wcast-qual flag") else () MESSAGE("Compiler flag ${WARNING_CAST_QUAL} not allowed") endif (WARNING_CAST_QUAL_ALLOWED) set(WARNING_STRICT_PROTOTYPES "-Wstrict-prototypes") CHECK_C_COMPILER_FLAG(${WARNING_STRICT_PROTOTYPES} WARNING_STRICT_PROTOTYPES_ALLOWED) if (WARNING_STRICT_PROTOTYPES_ALLOWED) MESSAGE("Compiler flag ${WARNING_STRICT_PROTOTYPES} allowed") set(ACTIVATE_WARNING_STRICT_PROTOTYPES "ON" CACHE BOOL "activate -Wstrict-prototypes flag") else () MESSAGE("Compiler flag ${WARNING_STRICT_PROTOTYPES} not allowed") endif (WARNING_STRICT_PROTOTYPES_ALLOWED) set(WARNING_ALL "-Wall") CHECK_C_COMPILER_FLAG(${WARNING_ALL} WARNING_ALL_ALLOWED) if (WARNING_ALL_ALLOWED) MESSAGE("Compiler flag ${WARNING_ALL} allowed") set(ACTIVATE_WARNING_ALL "ON" CACHE BOOL "activate -Wall flag") else () MESSAGE("Compiler flag ${WARNING_ALL} not allowed") endif (WARNING_ALL_ALLOWED) set(WARNING_EXTRA "-Wextra") CHECK_C_COMPILER_FLAG(${WARNING_EXTRA} WARNING_EXTRA_ALLOWED) if (WARNING_EXTRA_ALLOWED) MESSAGE("Compiler flag ${WARNING_EXTRA} allowed") set(ACTIVATE_WARNING_EXTRA "ON" CACHE BOOL "activate -Wextra flag") else () MESSAGE("Compiler flag ${WARNING_EXTRA} not allowed") endif (WARNING_EXTRA_ALLOWED) set(WARNING_FLOAT_EQUAL "-Wfloat-equal") CHECK_C_COMPILER_FLAG(${WARNING_FLOAT_EQUAL} WARNING_FLOAT_EQUAL_ALLOWED) if (WARNING_FLOAT_EQUAL_ALLOWED) MESSAGE("Compiler flag ${WARNING_FLOAT_EQUAL} allowed") set(ACTIVATE_WARNING_FLOAT_EQUAL "OFF" CACHE BOOL "activate -Wfloat-equal flag") else () MESSAGE("Compiler flag ${WARNING_FLOAT_EQUAL} not allowed") endif (WARNING_FLOAT_EQUAL_ALLOWED) set(WARNING_SIGN_CONVERSION "-Wsign-conversion") CHECK_C_COMPILER_FLAG(${WARNING_SIGN_CONVERSION} WARNING_SIGN_CONVERSION_ALLOWED) if (WARNING_SIGN_CONVERSION_ALLOWED) MESSAGE("Compiler flag ${WARNING_SIGN_CONVERSION} allowed") set(ACTIVATE_WARNING_SIGN_CONVERSION "OFF" CACHE BOOL "activate -Wsign-conversion flag") else () MESSAGE("Compiler flag ${WARNING_SIGN_CONVERSION} not allowed") endif (WARNING_SIGN_CONVERSION_ALLOWED) if (ACTIVATE_POSITION_INDEPENDENT_CODE_FLAG) list(APPEND CMAKE_C_FLAGS ${POSITION_INDEPENDENT_CODE_FLAG}) else () string(REPLACE ${POSITION_INDEPENDENT_CODE_FLAG} "" CMAKE_C_FLAGS "${POSITION_INDEPENDENT_CODE_FLAG}") endif (ACTIVATE_POSITION_INDEPENDENT_CODE_FLAG) if (ACTIVATE_WARNING_UNDEF) list(APPEND CMAKE_CXX_FLAGS ${WARNING_UNDEF}) list(APPEND CMAKE_C_FLAGS ${WARNING_UNDEF}) else () string(REPLACE ${WARNING_UNDEF} "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") string(REPLACE ${WARNING_UNDEF} "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") endif (ACTIVATE_WARNING_UNDEF) if (ACTIVATE_WARNING_SHADOW) list(APPEND CMAKE_CXX_FLAGS ${WARNING_SHADOW}) list(APPEND CMAKE_C_FLAGS ${WARNING_SHADOW}) else () string(REPLACE ${WARNING_SHADOW} "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") string(REPLACE ${WARNING_SHADOW} "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") endif (ACTIVATE_WARNING_SHADOW) if (ACTIVATE_WARNING_CAST_QUAL) list(APPEND CMAKE_CXX_FLAGS ${WARNING_CAST_QUAL}) list(APPEND CMAKE_C_FLAGS ${WARNING_CAST_QUAL}) else () string(REPLACE ${WARNING_CAST_QUAL} "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") string(REPLACE ${WARNING_CAST_QUAL} "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") endif (ACTIVATE_WARNING_CAST_QUAL) if (ACTIVATE_WARNING_CAST_ALIGN) list(APPEND CMAKE_CXX_FLAGS ${WARNING_CAST_ALIGN}) list(APPEND CMAKE_C_FLAGS ${WARNING_CAST_ALIGN}) else () string(REPLACE ${WARNING_CAST_ALIGN} "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") string(REPLACE ${WARNING_CAST_ALIGN} "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") endif (ACTIVATE_WARNING_CAST_ALIGN) if (ACTIVATE_WARNING_STRICT_PROTOTYPES) list(APPEND CMAKE_CXX_FLAGS ${WARNING_STRICT_PROTOTYPES}) list(APPEND CMAKE_C_FLAGS ${WARNING_STRICT_PROTOTYPES}) else () string(REPLACE ${WARNING_STRICT_PROTOTYPES} "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") string(REPLACE ${WARNING_STRICT_PROTOTYPES} "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") endif (ACTIVATE_WARNING_STRICT_PROTOTYPES) if (ACTIVATE_WARNING_ALL) list(APPEND CMAKE_CXX_FLAGS ${WARNING_ALL}) list(APPEND CMAKE_C_FLAGS ${WARNING_ALL}) else () string(REPLACE ${WARNING_ALL} "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") string(REPLACE ${WARNING_ALL} "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") endif (ACTIVATE_WARNING_ALL) if (ACTIVATE_WARNING_EXTRA) list(APPEND CMAKE_CXX_FLAGS ${WARNING_EXTRA}) list(APPEND CMAKE_C_FLAGS ${WARNING_EXTRA}) else () string(REPLACE ${WARNING_EXTRA} "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") string(REPLACE ${WARNING_EXTRA} "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") endif (ACTIVATE_WARNING_EXTRA) if (ACTIVATE_WARNING_FLOAT_EQUAL) list(APPEND CMAKE_CXX_FLAGS ${WARNING_FLOAT_EQUAL}) list(APPEND CMAKE_C_FLAGS ${WARNING_FLOAT_EQUAL}) else () string(REPLACE ${WARNING_FLOAT_EQUAL} "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") string(REPLACE ${WARNING_FLOAT_EQUAL} "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") endif (ACTIVATE_WARNING_FLOAT_EQUAL) if (ACTIVATE_WARNING_SIGN_CONVERSION) list(APPEND CMAKE_CXX_FLAGS ${WARNING_SIGN_CONVERSION}) list(APPEND CMAKE_C_FLAGS ${WARNING_SIGN_CONVERSION}) else () string(REPLACE ${WARNING_SIGN_CONVERSION} "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") string(REPLACE ${WARNING_SIGN_CONVERSION} "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") endif (ACTIVATE_WARNING_SIGN_CONVERSION) #Set c++11 by default list(APPEND CMAKE_CXX_FLAGS "-std=c++11") #Set c99 by default list(APPEND CMAKE_C_FLAGS "-std=c99") elseif (MSVC) # Add specific compilation flags for Windows Visual set(WARNING_ALL "/Wall") CHECK_C_COMPILER_FLAG(${WARNING_ALL} WARNING_ALL_ALLOWED) if (WARNING_ALL_ALLOWED) MESSAGE("Compiler flag ${WARNING_ALL} allowed") set(ACTIVATE_WARNING_ALL "OFF" CACHE BOOL "activate /Wall flag") else () MESSAGE("Compiler flag ${WARNING_ALL} not allowed") endif (WARNING_ALL_ALLOWED) set(RTC_FLAG "/RTC1") CHECK_C_COMPILER_FLAG(${RTC_FLAG} RTC_FLAG_ALLOWED) if (RTC_FLAG_ALLOWED) MESSAGE("Compiler flag ${RTC_FLAG} allowed") set(ACTIVATE_RTC_FLAG "ON" CACHE BOOL "activate /RTC1 flag") else () MESSAGE("Compiler flag ${RTC_FLAG} not allowed") endif (RTC_FLAG_ALLOWED) set(ZC_FLAG "/Zc:forScope") CHECK_C_COMPILER_FLAG(${ZC_FLAG} ZC_FLAG_ALLOWED) if (ZC_FLAG_ALLOWED) MESSAGE("Compiler flag ${ZC_FLAG} allowed") set(ACTIVATE_ZC_FLAG "ON" CACHE BOOL "activate /Zc:forScope flag") else () MESSAGE("Compiler flag ${ZC_FLAG} not allowed") endif (ZC_FLAG_ALLOWED) set(GD_FLAG "/Gd") CHECK_C_COMPILER_FLAG(${GD_FLAG} GD_FLAG_ALLOWED) if (GD_FLAG_ALLOWED) MESSAGE("Compiler flag ${GD_FLAG} allowed") set(ACTIVATE_GD_FLAG "ON" CACHE BOOL "activate /Gd flag") else () MESSAGE("Compiler flag ${GD_FLAG} not allowed") endif (GD_FLAG_ALLOWED) set(ANALYZE_FLAG "/analyze:stacksize25000") CHECK_C_COMPILER_FLAG(${ANALYZE_FLAG} ANALYZE_FLAG_ALLOWED) if (ANALYZE_FLAG_ALLOWED) MESSAGE("Compiler flag ${ANALYZE_FLAG} allowed") set(ACTIVATE_ANALYZE_FLAG "ON" CACHE BOOL "activate /ANALYZE flag") else () MESSAGE("Compiler flag ${ANALYZE_FLAG} not allowed") endif (ANALYZE_FLAG_ALLOWED) if (ACTIVATE_WARNING_ALL) list(APPEND CMAKE_CXX_FLAGS ${WARNING_ALL}) list(APPEND CMAKE_C_FLAGS ${WARNING_ALL}) else () string(REPLACE ${WARNING_ALL} "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") string(REPLACE ${WARNING_ALL} "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") endif (ACTIVATE_WARNING_ALL) # Only for DEBUG version if (ACTIVATE_RTC_FLAG) list(APPEND CMAKE_CXX_FLAGS_DEBUG ${RTC_FLAG}) list(APPEND CMAKE_C_FLAGS_DEBUG ${RTC_FLAG}) else () string(REPLACE ${RTC_FLAG} "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") string(REPLACE ${RTC_FLAG} "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") endif (ACTIVATE_RTC_FLAG) if (ACTIVATE_ZC_FLAG) list(APPEND CMAKE_CXX_FLAGS ${ZC_FLAG}) list(APPEND CMAKE_C_FLAGS ${ZC_FLAG}) else () string(REPLACE ${ZC_FLAG} "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") string(REPLACE ${ZC_FLAG} "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") endif (ACTIVATE_ZC_FLAG) if (ACTIVATE_GD_FLAG) list(APPEND CMAKE_CXX_FLAGS ${GD_FLAG}) list(APPEND CMAKE_C_FLAGS ${GD_FLAG}) else () string(REPLACE ${GD_FLAG} "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") string(REPLACE ${GD_FLAG} "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") endif (ACTIVATE_GD_FLAG) if (ACTIVATE_ANALYZE_FLAG) list(APPEND CMAKE_CXX_FLAGS ${ANALYZE_FLAG}) list(APPEND CMAKE_C_FLAGS ${ANALYZE_FLAG}) else () string(REPLACE ${ANALYZE_FLAG} "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") string(REPLACE ${ANALYZE_FLAG} "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") endif (ACTIVATE_ANALYZE_FLAG) if (MSVC80 OR MSVC90 OR MSVC10 OR MSVC11) # To avoid compiler warning (level 4) C4571, compile with /EHa if you still want # your catch(...) blocks to catch structured exceptions. list(APPEND CMAKE_CXX_FLAGS "/EHa") endif (MSVC80 OR MSVC90 OR MSVC10 OR MSVC11) set(MULTITHREADED_COMPILATION "/MP") MESSAGE("Compiler flag ${MULTITHREADED_COMPILATION} allowed") set(ACTIVATE_MULTITHREADED_COMPILATION "ON" CACHE BOOL "activate /MP flag") if (ACTIVATE_MULTITHREADED_COMPILATION) list(APPEND CMAKE_CXX_FLAGS ${MULTITHREADED_COMPILATION}) list(APPEND CMAKE_C_FLAGS ${MULTITHREADED_COMPILATION}) else () string(REPLACE ${MULTITHREADED_COMPILATION} "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") string(REPLACE ${MULTITHREADED_COMPILATION} "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") endif (ACTIVATE_MULTITHREADED_COMPILATION) #For exceptions list(APPEND CMAKE_CXX_FLAGS "/EHsc") list(APPEND CMAKE_C_FLAGS "/EHsc") # UNICODE SUPPORT list(APPEND CMAKE_CXX_FLAGS "/D_UNICODE /DUNICODE") list(APPEND CMAKE_C_FLAGS "/D_UNICODE /DUNICODE") endif () # Remove duplicates compilation flags FOREACH (flag_var CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) separate_arguments(${flag_var}) list(REMOVE_DUPLICATES ${flag_var}) string(REPLACE ";" " " ${flag_var} "${${flag_var}}") set(${flag_var} "${${flag_var}}" CACHE STRING "common build flags" FORCE) ENDFOREACH (flag_var) if (MSVC) # Replace /MT to /MD flag # Replace /O2 to /O3 flag FOREACH (flag_var CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) STRING(REGEX REPLACE "/MT" "/MD" ${flag_var} "${${flag_var}}") STRING(REGEX REPLACE "/O2" "/Ox" ${flag_var} "${${flag_var}}") ENDFOREACH (flag_var) endif () set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" CACHE STRING "Updated flags" FORCE) set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}" CACHE STRING "Updated flags" FORCE) set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}" CACHE STRING "Updated flags" FORCE) set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL}" CACHE STRING "Updated flags" FORCE) set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}" CACHE STRING "Updated flags" FORCE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "Updated flags" FORCE) set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}" CACHE STRING "Updated flags" FORCE) set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}" CACHE STRING "Updated flags" FORCE) set(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL}" CACHE STRING "Updated flags" FORCE) set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}" CACHE STRING "Updated flags" FORCE) ENDMACRO(ADD_EXTRA_COMPILATION_FLAGS) zstd-0.5.1/contrib/cmake/cmake_uninstall.cmake.in000066400000000000000000000017551266132244200220130ustar00rootroot00000000000000 if(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt") message(FATAL_ERROR "Cannot find install manifest: @CMAKE_BINARY_DIR@/install_manifest.txt") endif(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt") file(READ "@CMAKE_BINARY_DIR@/install_manifest.txt" files) string(REGEX REPLACE "\n" ";" files "${files}") foreach(file ${files}) message(STATUS "Uninstalling $ENV{DESTDIR}${file}") if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") exec_program( "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" OUTPUT_VARIABLE rm_out RETURN_VALUE rm_retval ) if(NOT "${rm_retval}" STREQUAL 0) message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}") endif(NOT "${rm_retval}" STREQUAL 0) else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") message(STATUS "File $ENV{DESTDIR}${file} does not exist.") endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") endforeach(file) zstd-0.5.1/contrib/cmake/lib/000077500000000000000000000000001266132244200157715ustar00rootroot00000000000000zstd-0.5.1/contrib/cmake/lib/CMakeLists.txt000066400000000000000000000205541266132244200205370ustar00rootroot00000000000000# ################################################################ # zstd - Makefile # Copyright (C) Yann Collet 2014-2016 # All rights reserved. # # BSD license # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright notice, this # list of conditions and the following disclaimer in the documentation and/or # other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # You can contact the author at : # - zstd homepage : http://www.zstd.net/ # ################################################################ # Get library version based on information from input content (use regular exp) function(GetLibraryVersion _content _outputVar1 _outputVar2 _outputVar3) string(REGEX MATCHALL ".*define ZSTD_VERSION_MAJOR+.* ([0-9]+).*define ZSTD_VERSION_MINOR+.* ([0-9]+).*define ZSTD_VERSION_RELEASE+.* ([0-9]+)" VERSION_REGEX "${_content}") SET(${_outputVar1} ${CMAKE_MATCH_1} PARENT_SCOPE) SET(${_outputVar2} ${CMAKE_MATCH_2} PARENT_SCOPE) SET(${_outputVar3} ${CMAKE_MATCH_3} PARENT_SCOPE) endfunction() PROJECT(libzstd) SET(CMAKE_INCLUDE_CURRENT_DIR TRUE) # Define project root directory SET(ROOT_DIR ../../..) # Define library directory, where sources and header files are located SET(LIBRARY_DIR ${ROOT_DIR}/lib) INCLUDE_DIRECTORIES(${LIBRARY_DIR}) # Read file content FILE(READ ${LIBRARY_DIR}/zstd.h HEADER_CONTENT) # Parse version GetLibraryVersion("${HEADER_CONTENT}" LIBVER_MAJOR LIBVER_MINOR LIBVER_RELEASE) MESSAGE("ZSTD VERSION ${LIBVER_MAJOR}.${LIBVER_MINOR}.${LIBVER_RELEASE}") SET(Sources ${LIBRARY_DIR}/divsufsort.c ${LIBRARY_DIR}/fse.c ${LIBRARY_DIR}/huff0.c ${LIBRARY_DIR}/zbuff.c ${LIBRARY_DIR}/zdict.c ${LIBRARY_DIR}/zstd_compress.c ${LIBRARY_DIR}/zstd_decompress.c) SET(Headers ${LIBRARY_DIR}/bitstream.h ${LIBRARY_DIR}/error_private.h ${LIBRARY_DIR}/error_public.h ${LIBRARY_DIR}/fse.h ${LIBRARY_DIR}/fse_static.h ${LIBRARY_DIR}/huff0.h ${LIBRARY_DIR}/huff0_static.h ${LIBRARY_DIR}/mem.h ${LIBRARY_DIR}/zbuff.h ${LIBRARY_DIR}/zbuff_static.h ${LIBRARY_DIR}/zdict.h ${LIBRARY_DIR}/zdict_static.h ${LIBRARY_DIR}/zstd_internal.h ${LIBRARY_DIR}/zstd_static.h ${LIBRARY_DIR}/zstd.h) IF (ZSTD_LEGACY_SUPPORT) SET(LIBRARY_LEGACY_DIR ${LIBRARY_DIR}/legacy) INCLUDE_DIRECTORIES(${LIBRARY_LEGACY_DIR}) SET(Sources ${Sources} ${LIBRARY_LEGACY_DIR}/zstd_v01.c ${LIBRARY_LEGACY_DIR}/zstd_v02.c ${LIBRARY_LEGACY_DIR}/zstd_v03.c ${LIBRARY_LEGACY_DIR}/zstd_v04.c) SET(Headers ${Headers} ${LIBRARY_LEGACY_DIR}/zstd_legacy.h ${LIBRARY_LEGACY_DIR}/zstd_v01.h ${LIBRARY_LEGACY_DIR}/zstd_v02.h ${LIBRARY_LEGACY_DIR}/zstd_v03.h ${LIBRARY_LEGACY_DIR}/zstd_v04.h) ENDIF (ZSTD_LEGACY_SUPPORT) IF (MSVC) SET(MSVC_RESOURCE_DIR ${ROOT_DIR}/visual/2013/zstdlib) SET(PlatformDependResources ${MSVC_RESOURCE_DIR}/resource.h ${MSVC_RESOURCE_DIR}/zstdlib.rc) ENDIF (MSVC) # Split project to static and shared libraries build ADD_LIBRARY(libzstd_static STATIC ${Sources} ${Headers} ${PlatformDependResources}) ADD_LIBRARY(libzstd_shared SHARED ${Sources} ${Headers} ${PlatformDependResources}) # Add specific compile definitions for MSVC project IF (MSVC) SET_TARGET_PROPERTIES(libzstd_static PROPERTIES COMPILE_DEFINITIONS "ZSTD_HEAPMODE=0;_CRT_SECURE_NO_WARNINGS") SET_TARGET_PROPERTIES(libzstd_shared PROPERTIES COMPILE_DEFINITIONS "ZSTD_DLL_EXPORT=1;ZSTD_HEAPMODE=0;_CONSOLE;_CRT_SECURE_NO_WARNINGS") ENDIF (MSVC) # Define include directories IF (NOT WORKAROUND_OUTDATED_CODE_STYLE) TARGET_INCLUDE_DIRECTORIES(libzstd_static PUBLIC ${LIBRARY_DIR}) TARGET_INCLUDE_DIRECTORIES(libzstd_shared PUBLIC ${LIBRARY_DIR}) IF (ZSTD_LEGACY_SUPPORT) TARGET_INCLUDE_DIRECTORIES(libzstd_static PUBLIC ${LIBRARY_LEGACY_DIR}) TARGET_INCLUDE_DIRECTORIES(libzstd_shared PUBLIC ${LIBRARY_LEGACY_DIR}) ENDIF (ZSTD_LEGACY_SUPPORT) ENDIF (NOT WORKAROUND_OUTDATED_CODE_STYLE) # Define library base name IF (UNIX) SET(LIBRARY_BASE_NAME libzstd) ELSEIF (MSVC) SET(LIBRARY_BASE_NAME zstdlib) ELSE () MESSAGE(FATAL_ERROR "Unsupported build type") ENDIF (UNIX) # Define static and shared library names SET(STATIC_LIBRARY_OUTPUT_NAME ${LIBRARY_BASE_NAME}) SET(SHARED_LIBRARY_OUTPUT_NAME ${LIBRARY_BASE_NAME}.${LIBVER_MAJOR}.${LIBVER_MINOR}.${LIBVER_RELEASE}) IF (MSVC) IF (CMAKE_SIZEOF_VOID_P MATCHES "8") SET(STATIC_LIBRARY_OUTPUT_NAME ${STATIC_LIBRARY_OUTPUT_NAME}_x64) SET(SHARED_LIBRARY_OUTPUT_NAME ${SHARED_LIBRARY_OUTPUT_NAME}_x64) ELSE () SET(STATIC_LIBRARY_OUTPUT_NAME ${STATIC_LIBRARY_OUTPUT_NAME}_x86) SET(SHARED_LIBRARY_OUTPUT_NAME ${SHARED_LIBRARY_OUTPUT_NAME}_x86) ENDIF (CMAKE_SIZEOF_VOID_P MATCHES "8") ENDIF (MSVC) SET_TARGET_PROPERTIES( libzstd_static PROPERTIES PREFIX "" OUTPUT_NAME ${STATIC_LIBRARY_OUTPUT_NAME}) SET_TARGET_PROPERTIES( libzstd_shared PROPERTIES PREFIX "" OUTPUT_NAME ${SHARED_LIBRARY_OUTPUT_NAME}) IF (UNIX) SET(PREFIX /usr/local) SET(INSTALL_LIBRARY_DIR ${PREFIX}/lib) SET(INSTALL_INCLUDE_DIR ${PREFIX}/include) # install target INSTALL(FILES ${LIBRARY_DIR}/zstd.h ${LIBRARY_DIR}/zstd_buffered.h ${LIBRARY_DIR}/dictBuilder.h DESTINATION ${INSTALL_INCLUDE_DIR}) INSTALL(TARGETS libzstd_static DESTINATION ${INSTALL_LIBRARY_DIR}) INSTALL(TARGETS libzstd_shared LIBRARY DESTINATION ${INSTALL_LIBRARY_DIR}) # Create symlinks and setup this files SET(SHARED_LIBRARY_LINK ${SHARED_LIBRARY_OUTPUT_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX}) SET(SHARED_LIBRARY_SYMLINK1 ${LIBRARY_BASE_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX}) SET(SHARED_LIBRARY_SYMLINK2 ${LIBRARY_BASE_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX}.${LIBVER_MAJOR}) SET(SHARED_LIBRARY_LINK_PATH ${CMAKE_CURRENT_BINARY_DIR}/${SHARED_LIBRARY_LINK}) SET(SHARED_LIBRARY_SYMLINK1_PATH ${CMAKE_CURRENT_BINARY_DIR}/${SHARED_LIBRARY_SYMLINK1}) SET(SHARED_LIBRARY_SYMLINK2_PATH ${CMAKE_CURRENT_BINARY_DIR}/${SHARED_LIBRARY_SYMLINK2}) if (EXISTS ${SHARED_LIBRARY_SYMLINK1_PATH}) FILE(REMOVE ${SHARED_LIBRARY_SYMLINK1_PATH}) endif (EXISTS ${SHARED_LIBRARY_SYMLINK1_PATH}) if (EXISTS ${SHARED_LIBRARY_SYMLINK2_PATH}) FILE(REMOVE ${SHARED_LIBRARY_SYMLINK2_PATH}) endif (EXISTS ${SHARED_LIBRARY_SYMLINK2_PATH}) ADD_CUSTOM_COMMAND(TARGET libzstd_shared POST_BUILD COMMAND ln -s ${SHARED_LIBRARY_LINK} ${SHARED_LIBRARY_SYMLINK1} DEPENDS ${SHARED_LIBRARY_LINK_PATH} COMMENT "Generating symbolic link") ADD_CUSTOM_COMMAND(TARGET libzstd_shared POST_BUILD COMMAND ln -s ${SHARED_LIBRARY_LINK} ${SHARED_LIBRARY_SYMLINK2} DEPENDS ${SHARED_LIBRARY_LINK_PATH} COMMENT "Generating symbolic link") INSTALL(FILES ${SHARED_LIBRARY_SYMLINK1_PATH} DESTINATION ${INSTALL_LIBRARY_DIR}) INSTALL(FILES ${SHARED_LIBRARY_SYMLINK2_PATH} DESTINATION ${INSTALL_LIBRARY_DIR}) # uninstall target CONFIGURE_FILE( "${CMAKE_SOURCE_DIR}/cmake_uninstall.cmake.in" "${CMAKE_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY) ADD_CUSTOM_TARGET(uninstall COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/cmake_uninstall.cmake) ENDIF (UNIX) zstd-0.5.1/contrib/cmake/programs/000077500000000000000000000000001266132244200170555ustar00rootroot00000000000000zstd-0.5.1/contrib/cmake/programs/CMakeLists.txt000066400000000000000000000071431266132244200216220ustar00rootroot00000000000000# ################################################################ # zstd - Makefile # Copyright (C) Yann Collet 2014-2016 # All rights reserved. # # BSD license # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright notice, this # list of conditions and the following disclaimer in the documentation and/or # other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # You can contact the author at : # - zstd homepage : http://www.zstd.net/ # ################################################################ PROJECT(programs) SET(CMAKE_INCLUDE_CURRENT_DIR TRUE) # Define project root directory SET(ROOT_DIR ../../..) # Define programs directory, where sources and header files are located SET(PROGRAMS_DIR ${ROOT_DIR}/programs) INCLUDE_DIRECTORIES(${PROGRAMS_DIR}) IF (WORKAROUND_OUTDATED_CODE_STYLE) # Define library directory, where sources and header files are located SET(LIBRARY_DIR ${ROOT_DIR}/lib) INCLUDE_DIRECTORIES(${LIBRARY_DIR}) ENDIF (WORKAROUND_OUTDATED_CODE_STYLE) IF (ZSTD_LEGACY_SUPPORT) SET(PROGRAMS_LEGACY_DIR ${PROGRAMS_DIR}/legacy) INCLUDE_DIRECTORIES(${PROGRAMS_LEGACY_DIR}) IF (WORKAROUND_OUTDATED_CODE_STYLE) INCLUDE_DIRECTORIES(${LIBRARY_DIR}/legacy) ENDIF (WORKAROUND_OUTDATED_CODE_STYLE) SET(ZSTD_FILEIO_LEGACY ${PROGRAMS_LEGACY_DIR}/fileio_legacy.c) ENDIF (ZSTD_LEGACY_SUPPORT) ADD_EXECUTABLE(zstd ${PROGRAMS_DIR}/zstdcli.c ${PROGRAMS_DIR}/fileio.c ${PROGRAMS_DIR}/bench.c ${PROGRAMS_DIR}/xxhash.c ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/dibio.c ${ZSTD_FILEIO_LEGACY}) TARGET_LINK_LIBRARIES(zstd libzstd_static) ADD_EXECUTABLE(fullbench ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/fullbench.c) TARGET_LINK_LIBRARIES(fullbench libzstd_static) ADD_EXECUTABLE(fuzzer ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/xxhash.c ${PROGRAMS_DIR}/fuzzer.c) TARGET_LINK_LIBRARIES(fuzzer libzstd_static) IF (UNIX) ADD_EXECUTABLE(zstd-frugal ${PROGRAMS_DIR}/zstdcli.c ${PROGRAMS_DIR}/fileio.c) TARGET_LINK_LIBRARIES(zstd-frugal libzstd_static) SET_TARGET_PROPERTIES(zstd-frugal PROPERTIES COMPILE_DEFINITIONS "ZSTD_NOBENCH;ZSTD_NODICT") ADD_EXECUTABLE(zbufftest ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/xxhash.c ${PROGRAMS_DIR}/zbufftest.c) TARGET_LINK_LIBRARIES(zbufftest libzstd_static) ADD_EXECUTABLE(paramgrill ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/xxhash.c ${PROGRAMS_DIR}/paramgrill.c) TARGET_LINK_LIBRARIES(paramgrill libzstd_static m) #m is math library ADD_EXECUTABLE(datagen ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/datagencli.c) TARGET_LINK_LIBRARIES(datagen libzstd_static) ENDIF (UNIX) zstd-0.5.1/images/000077500000000000000000000000001266132244200137505ustar00rootroot00000000000000zstd-0.5.1/images/Cspeed4.png000066400000000000000000001344201266132244200157510ustar00rootroot00000000000000PNG  IHDRzC7sRGBgAMA a pHYsodtEXtSoftwarepaint.net 4.0.9l3~NIDATx^W\W&z]7o[ݾVVge,gYtjgU(SNld@h$ ЄF5!ɒ,!!C0 f}Żu1Ɖoga8-Onxu [@'P< -Onxu [@'P< -Onxu [@皚 jrƂm۶.;fH PsPC 8+ 5 5$K=' ܣ)jkk:@NBѮ$-޹4d9dq`W3|,Qͣy:@NBb>}i0+}nm$zR>7Tw.[uKj <5I?ݽ@;AHoM$-Ō?i_3n"Puu5+P-{anh=Ng;vlۺExu [`-Ch&D>2F|'qzB5qDwtECt s_P;jsuNzz 4Z**4&kwU#njB̺:*Qzyw3 m/&/9AaFOgA:<诈Yx=-p1g;X/`-9]gڡlz'Utr}h_i\;_ U9{ p~bc"/% !j /Lw&$xj|1!D?@BQ 87b;ߴgtwKޣ%$twa׾)Bwu#} Mp~kpƎ/0q[p[_! ?$+&?@! դr8=%K P`{~p0@ hhVRC-ڑ>]@U{Wtږ`Z4 궟XvV?zک6[׵OūThU-g[17L[`7]ٵ~^߿jnGy/9D5&0n_TJIdhR+ ,9 @2,9ٵ~k_TUc\W)S 6= ,!@ .{XתUj P^ 6= ,!@ . Xע&P%Wjd3f#{&?@ݲB dYBŋŇ4()9AxP $&CݲB dYBe>_=XMn!@ ,!@Ω[E\Uj:1';@rP쁐e gYre -4BZ~}w׮@rP쁐e gYre gB+oj-Γ1N)Wo^9[@2,9 @2;ӯ>х꽢Ӽ%:;pT8J] u `P쁐e gYre gY]w-*W!--P쁐e gYre MYEξKԶP\@ݲB dYB7QEZuшڶ-P쁐e gYre $]m~ξ6ݵ/"j[P\@ݲB dYB7 9?ֻoͨmICpuYre gYrNo|ò.ݵ>~m [@2,9 @2s+n#j&ne,9 @2,9D`È.Zu u -{ dYB dْsGU۲ [@2,9 @2"e?q2P\@ݲB dYB6|g?8[.n!@ ,!sˡChvG6@脺= ,!@ <8[wl< u -{ dYB dzuP\@ݲB dYBᷜChWԑ]W u -{ dYB dyp2#= ,!@ l@Ea -P쁐e gYre!tϩm@puYre gYFsB'-P쁐e gYred6/-> u -{ dYB dc+O tBpuYre gYFFr[;]v@脺= ,!@ /=ڲMw@脺= ,!@ ɜ»袵q߼f;-P쁐e gYre:'<79o N[.n!@ ,!9Yj|O ' N[.n!@ ,!:Ч{AK;,mu -{ dYB d|cZL/m9u -{ dYB dEk޶KԶ= ,!@s1Ѝi X˺Ɨy~BpuYre gY‹CS?Wtoj|9Qa[.n!@ ,!pժ:nw̪9u -{ dYB dy5{z߾.Z뻖ck|6>VkC[.n!@ ,!lγ_?}gT,su -{ dYB dy5魪u.h񲽤C֠ne,9 @2,cS9C[$8e@puYre gYF9F"=*u+]g`  [@2,9 @269 uw]}䰳kWq4-P쁐e gYre˩GC\by/YUkP\@ݲB dYB9 -ݼ[yԨU u~@P\@ݲB dYB:Ǐ[]8(-1/]ǎ(5`?o/uvң)׊ u -{ dYB dOËC;+ʌ UK5|?Euc̶Dž8P\@ݲB dY!/LΧn!L۳˗>Z[UͅccK;Og7]0z9@puYre gCUƕj$422FMRˁb>L/?UI.uW [@2,9 Hkqų8>r!:t  W5xg_ZtFB+[[(,,TQ$rd 6d= ,!@ݵxAbcc9e+^:4(Olh9SѪ;^Q.Z^~ŏ pW/Hu(Ar][[˛uYre g1C׵x b|1-G8Vh-6EΪۏ:g5C e!//ZId}y/>+&?@ݲB dY@̐kQD7jjvZDF]j(ϝI48tM_‹Ck=jGot|ʞ=s.u8fEY%[@2,9 0Bs*zCvmoPh{cH㴕Lu?vZZߵ*ZQ`ݩ%ؤV2Mn䬶V\4H'ut,AΫ'wfv;|P__^"mOnqwbt-DIh^,8ehuv@U[[nckƾ`M~e,9 @2k^4O\[pm$A]jٙc5qbYڵV8Uc+JK}42̅ jCǕ=F\.=Rwo[ԅ出>Qb h̤9Ĺ P쁐e gYr,OߏVxy"mSܣ={mjI>[.n!@ʙ*VO7z\v/o$`> yeqq#/nޘ__"uˡiTF`s [@2,#wrvv-^nk|^28FUǯiyLT'䥑 tcfW}ҡ{l *h8]xjl7-P쁐e gYFݵR$d6H(43vZwa\ut閧_ /:}mE#Kj^d6܁= ,!ȅt-ZJmzeEH+3- >xTw'YXEUч>prnɼ{Zd$= ,!ȅtXN~zC2'劗#FXY\TwH`ԎFzg_CC j7$se[.n!@\t'F2_H%HdyݕǠeM=!^UWyw QW7Y23$u -{ dYB 9'>0iJȳ\rx52^zYοl~? +LP2Z.j_^23$u -{ dYB#9k\]y5魪D725d/#vnkBPpuΰ)[.n!@ s.%ӵ-^f= _D9NL"Sc7/4ZvVX/6)sMApuYreؚZuqu-.d-[]kY×.P%'YMʪ9rBpuYreX3uíqgmSߩ kD7UZ]ơ-c8UGtz: T5~aP\@ݲB dZ%OS2g!F"s=݁Cz9P<~~qcvAKЍ͓zԉ;/hѲm+8g.,fswP\@ݲB d,;6!zw{*̖Xb^0I 0%AѲvpza&I;OhqT$3u -{ dYBaYΝӍ~ZdÐWṮP9Y\(ܬ7]٣~^T9?}}mXZl3 [@2,òm't- W/.;ltċ\;fgEAO'AΐF[.n!@ , :=|ѣhʣƠלPTNsxo)?4Ot-P쁐e gY9 Kj!O>Y=*hҜuWB6%mf9sne,9 @2,ep3jg8䅁IџP<||o?P8t`~i]l/PNZϠne,9 @2=j&/|yԨDΫQ]vx/@heA\Qs*QF:;͜-P\@ݲB dٞsܵj䲿Bpjj@iQΜmo_ {Q㳡ST1\.=R͜-P\@ݲB dYpQϹn=F3m5phYԻ}-Pg!~=WqcnAϟ,\ܫe<ٗE!)Yu -{ dYB9;O#<_hUmȜTӣcF(l6 ys~-teZmHhr>}`*Ǖ=Fq w^F}酕Ohsղ͜]P\@ݲB dٛD㯚'&Ʈ_3 (|ia` ^ ^.?U*NM]\c4jِgSK:huv3ۏkx9Czne,9 @27gW[kgˢȡחiB~ӵVU+'f*n~z7b}l6p΋֡;;rBpuYredogZ&i`#91̸ F̐ow̮]˱Dmd߱cC^]D>u -{ dYB7+43ͮCΖ8PXsw|ɾ-{5Rh/:Zirwuw/Z ݍ h]gq@+-s6A2P\@ݲB d>ybqO?QhPXtlhM_<1&%]y@2P\@ݲB d>ﹷ;ήί~QtO >j|^}sŗZFŭzϻZ1VV5x{gˢjj8]C r= ,!mm㏸keWZ\_o^X8s(ZCfoC r= ,!Ij򭶙c7>?ݿ@; |f+Ulϴ=뭪t⑫ | -P쁐e gYFr[ ?pr_Ǖ=U.sZ_>g:; T+Z%Css2-S!,u -{ dYB!shnQG^a'cuC[;Δ˯hۮC.9W dB,u -{ dYBQsK N^qhJ1˺h{zܪԞ==4Z~Ow9VoULkKF!Br= ,!HWΓ!I's~ E/oxku#Kˡz53mϸD>yP{b2pfg5|%]!CbY [@2,C|c-te'38-+-{v.8tW|}x8^ Zk8v⣺b2|au7! -P쁐e gYQh];8ˡӁlد߾d_ōQm}ˡ>28xycS6|}k ~`fene,9 @2(Ϫξtك #W*B&9F']^~qr+.983%fene,9 @2N]TVkOy{nr>ɁI_g#&_Y\T 2 -P쁐e gYƿVǕ=Fn͌NROK}OFѢpxiIBx3@2P\@ݲB dPAڲYU㋧ h5jbѲl{fene,9 @Ȟ=tD+c^ҡさz*ʌr% ݲ 2 -P쁐e g Բ.=yT ]gԝja``.pبU =7 ,u -{ dYBNPe:f/n]0BL=J:D*|BcXkNG6x3@2P\@ݲB h^,vDm~`[:wV[B -I#6<66z!PZbKf}&cy^wE=VYr= ,!bza܃*>ղ6jUeu9uzU8V͉td̝\- ZӁWoxvZxXRjSh^jyw2}][/7 jGj}=[&Vѝj[Mj D@Vy2;U6ugZ$FV/t>:>w-Z_U ۸[ܲXeō+ |SbnR+\sm*n3-ܿ6tG,Uk:Oռ=nꬪ|[J:뮬kB46@Vq]4gzVMj p2= ,@8RōE ҦE62$ޞl{;w*Y/JKt9/u΋+ӕZ mRluj%JǗ1;v = ,@&w^|Xet'Z-KXDzŢKt (|pk;ӐAC2R1+ڕ3N}uYriȣӯj'߲ z-^΃Z97*FM!e[ԅ出>J\g&x P쁐e g^?ݿey nYOsx*ơ-^^|>fDIcp2!4dА wu ǡn!@R}u3[^z=Zexz>c-C9'qN"^ 9@puYrJc/3`-{>?2[?LkQ/Q-4ԕ] 9@puYr"{Ut-+{.=Y~b_z*rfM}] 9@puYr|ˡHCΓ}FŢ僃w^ OTKM< Z;|ή};VY?Tu:׺r= ,`Ðiֻ-`2"zY\kNaΩh\Fs g[.n!@<8j|Ѳm];xc֦ `$wyu.[ߣUj+ g[.n!@C^E6mUOq55̶;?xL :xyD7=3zra}///߱cֵb.,,ljjRBݲBv B7Z^m3RQw-k{IGō%#Vk hu900m3gBe]kqѢl۶V WP쁐e tY /%ݵv>nprQJ[Q+{=ggoJhfZjBssj+x3 @2 Vuu5+,*`yyyj-{ d9]tVgyUlkˇe]LINsnX PoA d Yu+??V8P) -{ d9-nw̮]+ξrJF"E+'oojD75< 4,xIBݲBbAVE/UR^юEKt꭪ NMm)7_LwI raw*((V+8)BݲB"Jw9̸KPHmKO_`I rawݪݶm@ uWP쁐e x@ѯejCxfҷVe5< 4,E\mݺme,9htUQWieCc>-<}3m'[Kj('y2hYuPE W[:-{ d5*Zꆷm{[֮Cs)C-DŽW]jږn޽ë!Z_5,}]eBH;-{ dم`躢ųKO\ c7R/׭_\]ene,9oV:mj酕O;yy\ ZSP<^$W/nu2w!ra_*//vL<-{ d9ySOU*062vp{I-\z4Zk900yӜ;^޸3rlieV*OC 9˰nlݺN @ݲBt˺nw$S!kr*LA2 8>S e,9ohr>>V6uYrN܃ 7FÑMr!d㓵z -ţ5<  Yu+5 05-{ d9B0\xqHw*׽]B'[C^.;HDmr[]3wP(d0 g֭򼼼Bx#N#n!ٜtVݬ^/ooz]2閧\l{ڐ9\k[Kj(y2 [+((I-{ dٵNk9.@e!F"cׯZ=eccj[FyW? /Q`@2[AݲB9921]gt)sgt8U2""E3ZZr!C4,5>>^[[N%t![@2r3~e,K:t&Dϱ ݵF ysx5Ts[WE 9˰nm۶cTn!͜Q\ O1(z28{V-95q:PK{ra}=\ȹ{lNݵ*nzq+, 9 _Vܜ{iϹy2׭kC%j(=d 9_y[@2A0Ɩm -A髮]k%_}ҞGn=|qF 弴 1!gV֭5j1ǐ:-{ dv|$U,ZT, "euךOmiBo׭;j(=d 9˰nm۶QڱcߠE,//ogm`.n!˰5pd`-Zj8<1JKf;;Ԇ:~ubyibB2[T1hU_n ie,ʜCݵo/B޴_}Sj$2]}PlylLm6iϹ~KZm1M'Uz*!CLY}u+??V,`CݲBa_Ԭ~[իV!ɋې__%ݵҞsd5?4T뀟R +wY_puYe9Otתj|6d?CfEJw0F4l,9ȑ c@zn!˰):hmvڐi> yidLwF2| 0u>>Yraeڱcm۶!cH= kr1緐g;;%\gڞ Y.9/~?Z9+NzCx VyyjT nA*P쁐eؑ󅇓\hy{lIm_]vxڐқwE|Y—A{"J]zCx -{ dٞs8zڨZUt|r$z^wEw̌f|poQCR -P쁐eduˡH!ݵv[6?C+jtt!/-9Lސ!,u -{ dٛ +ݵwVV6x/y cDKcK+ܵ`MC -P쁐ediS*uת16RfC t*֞ƜG;nU5i @2P\@ݲB9F/䢵eoۥGSj_e0A#1F[z IcȐr=Aܻ۹kэje$px[ݵz*_M<Ɯu5k2$ene,#r{CݲB9#{/{VԶl / 9@2眅e gv׭;v׫u4AݲBCw҈ږ%BnyJ>!7 ,^@ݲB'C l G|Z ݼEc)_1ҘGKcȐraw*,,U+1Ѝ8/Q+YuYs_|܃ !xr$tAw3V""镮wF!x#]!CbYu)//o||\g`ۿ,AEAv.oнԶXeМT~uYos~:/eoۭ! yrhnJwԾԶUo?PCFBĐ Vmm;hϛwʄ1߬쀚!saaZW+ɡR<^G⺕̑L;d[BϜN SjZPw!/T5ڐҕ[-ߨ!x#]!CbYuv՞uTv3v,[6g%^_5"EtnkYFfsyvq,{<<pѢjCJWΧ>?פt !gv-N7TSӄ M%=91<ǏS̺ݔtOhHn1-x !TP@q;.!O>jT- 9,]9n}L2$en pRK;~}yЉFhoGzizܩ_c>]oDŽ ![@2r>0vZtaϜڐ3 yeqq)ݵ/_Ar9ڙ|bˉoTOf)YDxKi'2$׮|jOpuY9_m~eowK;#KjC.0Dϱ ݵ^ܺa1WRk5Y rnDKƕ`&OjķlPSSSuuMnA*P쁐ex{\h{x*6!/u*8P<ڢ6&%9L)BB2-C^^5"s&pދgqJ P쁐exs8ZqcTwVwy%yU,ZTؼ9'qkEs2l rE o3ǾlJEcc#=,juY9S*??ݿSb]Eʣ) \sVL C2R[ԂQQ9gNEe,&m۶y'#Z ZK[o*k?NwMVkkguZU--jdHK#c `)uKܵbΌy~ *]bnR+I֏SPP@.u =]smj8=n(۵ΞloW bU  jyqG;VOEؘ i^ o!dYE]Y~) ޚLOffQ㪮vVA]Η=s>02NZ5'V6H̰!,9pWp<e43 Ofo8-{ d)|$-Z>,2NUѷ|) mV)!YrneF| = 9dqeO.qݵꟇ#j1>y`}\s.̰YYrawn7P쁐el6gõNy6zݵOTw67,`ofp!@2[-=MYr~j8pZ|aM !gYrawݲsJ~H PCRj|ԷCݲB|gNm7=*tH>dHre gv-Bݢǯo %P#a >_o==$s{<JlP)b1 R dYu>ήVnqc m7fM&6ZMKBݲBLU/hQE7>\+T#Xܵ/>V$29 @2 8m篡o,atEqyZ t%>Dwu~VW*P쁐e$9 <ه2F"hW]j!C gYrawݢZcmƻ\FiI-~k7]je MN1.-{ dF'c:Ph[.ZNLm!G,9˰nmh쩀H!ݸZ$īXیP z|]Xu$Z[ ds~ZC]k8pFwsghDmKofYBe]HSSBdqyڵQ{-c5i~Xt݊~4ZY3le셅` 1vE cc=ek%0F4e gYra}bThrTտk7thKKE~p2x?5$3Vy@ؒFL=j5_E/) gYraw*..ޱc.v:Zpu9E*uts9Ł3fs9J., 9 @2 V~~~}}ZqS ![@ȩ1vݵ_;]0gs^s¨UuW\ِ!gYraw*((@/n!Cƨ.ZT̪mfγR-Oof,9˰nQf5>>ҠZpuم酕'tq{x*ők9F"wV=eχ6Zș dYu+][5F=fW{{yh9r*ЅkלXWۼS!gre gv-})pb!l={0N7.>^PP@{ѲqEw-^y{O6odiSM~ց閧j/eiY9 @2 VSSӎ;b;TbM-:1[SңшZY|W’P쑃!W tŠ晬9 >j䓵˺re gv-ڹ}OKtkgsTDwhuOnIxs-{TjU+{0y,r^[yTwsg|ZeW 9 @2 VSSՃs6.qjL`n 4Nb-C~Mnf͊4Hn#wB6>a E9ϴi{g5Q-BjYBe],FD7Uke R+iเe A{EoO dEΑ`pj.Z]J纻նl![9 @2\[MɜGuy,]ZI =9zaD-/>8yidyǎږ%,9˰n^mh]+((3 s"|j%e[;Ǖ=kt#W#'^kBjss6A ,{[t~f-ZF]W"rnB ,#G@zn!s~ZFC4 #'U1byiddYh2ya#srJ~H PC^Zr WǷmr =B0\xg_kw֫K:Ӣy5 NL̶]]vhYz魪B됁!dXuR_hh\13$þU]]MJP+n!ZY^ xvpn) .WCssTBek 5'foKZ)-!ÆR:)| 류3$ɾUPP󳶜v؁?Tn÷!]+T뻖cyOm|baVHs$\4[7G=W][y,%o_J2rN,-U'_/h\Rg_J#1ǐ"-{6=~e,PSshf7o6z+M|Xl=e A ī:nIa^?^jvro9s^~_>)?g ofխZG^^u o/9s^ҡf985[x9V[yt̩s#uo7δ=[ 1\hjYgr6Wp_zuҽs&U}h8~[z?4WkQJZ-H=|muvcO6b?;SMfS1 ĿuW0ŷofˤGOMi`SSG=TPk:K*NB>d%{/"Аb_";DV]]M] W&nß!Nr~Ve8t*tašA)H?I1gvi<- S}:Q}|[>>ng@}ZB">DF ^xZ-| O<17^籿5W/8АdejjjuVjV4B_ [[cK~:KӰ2?OٲGβ̶J%ggJ{C/کWP3AU\*-twjPn]`W;z'EOGOJO]wMJ3CkHY@׊)Ŝ!I-n#!S_j^j|Q,˞??oB]kzaE=o̶simmVk --x3{-o朒|ίBKTW7,] >zONҳ?N/cE;i:ɇekœzΐ -H lݺգCollLDj%nC>٢K:E l~fuv8-\z4Zd5}s%@iZGFFh|9!vʩВ`^9>CobYrי޺EyLVP_xBw*[>Mh^Z$-{7`Qhmu1;80gn98Ж^f5bBȩpv-^Ƶou־ʿ9g&XvSu]k{>?[fene# OJ9f:ѸsѾZcn#!ZN}u+{Nߛ eޜ!&ZtUCX:d,Gtvoyfxς ofY X]'V_MI }pFݺ&n,DwB i 7nGM_Eox'țe4|cvMZW_Vwj$s#1g!%^Qj|rիВzD?VLx3@2-C'qdæb=!&>mǻ\D,hD7 n%[&zAc48nn#!9?h+cɖ&ޔwBGcκe1iݠMthxIBݲGCε> X>Ɯ!W;o~ ,9HnήǨ[{ݩh7&|{t+PZ2zoD ]7/qt;!IηV%InAת6_˧mjZZ:+bɖTU2WۯwPۯ~d?iA=+,a"1떱{ 6\W[ŋ^co]&[Ʀ0Z\fk@݂>\@55۵uan9U ѓ.=_}M7VQrnEp]4B̺Ej} ='ؤVrqA%(q"'|(H Vw>q>BGӜb<ݠUâG 푮+nXv G#=?t{{hB@$ 4=\'EŒre g-B;ۚQ+ktrY ݬb.4AMM6/O7.$(H<9'].#$x4B=Y05 =xrKuL%Pҡo녺ŠCOЉN< g:O\?ѵʹjv= 4LuXE.,!@2Rxvu+>4p'ؔP5.S+CIѶMAݲG!]nHݵK:huvң)kkvv87*R!Swzڏ>)W+fS~ut!dYE]Y~hWXqt5[Lzx)*E2&ultԪ_K ]8M%gHReNq`Ne gq6Hє|-ʓAHMmLy[prtR,^^9V]* q3$y=x>!@2-ew!Z"×.p:TjMaSl yÖ=[s,9@pu.B5- }jt3\ eY~kYe9Bene!; ]kid$pw&6˚.o-K&g?C2 -Pِ_Trf/ٜly)8OU*eeiٞsV@2 -P챩/=]`ÈE5yysSg?%#^n疥䆖iݵ{ʹp (^I^&3琩bVtJö+OJ+^>;7sBene$C>0eow'rk~?ek=5V9C*|k?͙k{V9iuG.&Yr= 90vZ],ל5pli )g]+z]O{E3g dY [0ܵ>^XQ6~wC5 s0 m|z)8 |} ,u -{$y9]k{ITPmaZ̴$‡!WƲÜ탐e g[.n#Akm>|Y$ +_FS gH<8F2/fgl%,9@pu B.][mi8.+q( //є%?!O 4슾Kfl1,9@puBv~V]}wfڞqעeOC!2O~U1{Wv-⇜e g[.n#fOe Qۅff_ܺF$fΐ^ 9f*=apS3k# ,u -{D<<|֧{C+YDΜW] Ԇ4.S!,Z.7Ҭf,s Bene#d?8ȑ˾閧ܵ_1r/ȇP3b?/]眃 ,u -{8CGVw](Bss4hZ9sHLw,Z9g!dY [p\sw-x0 _]j5Vi<"Rp!9RL9!@2P\@ݲq߼ZM\0]15n:g!_5>98V^뜁 dY [G_cTr@xy0w_ЉsV+ OC~veϱ-΢:͹Ӝ!dY [[:?aYBГi[Z=*~5B'x2u*jV΢_SDr'r',9@puNsʩc>ZC, !h/=h}v'ON_9)9C4,9@puWUעzP(wцoըgfƐ'g7g]X Ϋ9,9C<YrV1ЍwǷIu #jRnxq&weϏ, -!-N taWXV%gH !@2P\@> p!} X> GV<68PukCz of)~#;.Z~5֤3$!@2P\@>oVe[HKjcx3 H%]wkg*93ܤ6C*9C ,u ԭ,scv_ZjK55L5=u44'ix3 pdϡڏE_ Q e g[.ne=~e,Y[+Բnl~F7͆xkϴ>;{-r IlBene>80l/%?Z]Dj$F7M{]tG\x0A2 -P [|>]+1, ɐ&{N.ZfH9C* ,u ԭ,ɄZDOTs-6 y%!ك@ 0gHBeneZ_ת\.=3^6?u7!4_{08gH ,9@pu+쮍{7m+jY\$, ^K7ESOr-^ΐFYrV9ywhYPzG%| of1CnEk灿|ZmWb 酐e g[.ne-{۸_%:;pT{!/pעE {ofo! -G]h/3j3e ^@2 -PI8h7w+{9WЬ!?8RCHg,9@pu+Լ9SA5!g 9XwgxN A2 -P4º1.?hwBfw>A 7>:rꢵ_k96C,!@2P\@Ǖ=ܵ>}6CyVٝsF-N#7]]OǷ^YBenφz (溵|Xf9gU,YtV<ۯwݵ.ڇ ,u ԭ,i␇.sZ|vA΁{j*xofYr%s!5>Zš_&֜Ew-粧\kx3 @2 -P.!F"}U\Qeew'T  ,u -_ &s!2閧ܵkg9+=Q;5<7,9@pu˿‘OryOg_ԯߩwL/(9g+cCߪ dY [Ux;ڢ?8}!n[Uً;ٗsF$>e? YBenS㳡ws:}oB&dYȡ}, yi񏍢E 0ZY ,u -uvǕ=ȪMȲ/_5trΠc?1-Ե ,!@2P\@ܵm ,э wDRؔs=l+֮:mE2,9@puwK:n9F`MȫHj[cׯQ߰& ZXOb=@k_}QKZ!@ ,u -{yVrhׇ&vZ]G,.Q߰& ._Z RYre g[.nyZ<XPɱ#HjO9pעgIe gYrꖏ,"yܵ Ѥ\㞊2|3% 9TQ ,!@2P\@c7ǸkW1VI pZ׭OԨXs= 4p*8Ky5!@ ,u -[ڲi59gЫuk3 B dY [m4ׇsZ|w9gӮܵt|J!@ ,u ԭ jhqA[, Y=-KsάUJ!@ ,u ԭ'Pj1d硭Ąl9vk[}#j(!,9 @2 -P2e֖m.?hː!C[뮨!Ɯ3ke?w$IY,9 @2 -P2`n)^Q׭j4eYr6"YslUͿ dYBenEϹk,"j4eYr6"YsƕödYre g[.nIk^EÞ95r"ٕs-?)u-wayFn!@ ,u -QGܵTi!F"#u뮌|m6"Y4u󡭒yj( Yre g[.n:`ֻ'Cj4M"vnY GVh?d}hK/Ywh?g$Wj(9Yre g[.n y=]ȒM+}h+p# n5uԫ dYBen%a9`5n>9-46gqsSg?~EZGr%JmNB dY [㮵c!V琣mBYw9gu?~ nYRe gYr'[+djKs\s1musf9^>-1IC2,9p]QXXFcUn[ "@@mXF$q[x/wO!o6xxɺ\9bv-Z>?nre gVyyXܦ5.ȫtzߦAZ o'[޺;F7+ې%p6 ׵xMm\Yre g!oZYu"EM|8+VM~塹{E\N ѯ&9gPe,?!gYruݢT^^V'cd 6ꖇ sۋ26uW~e,aǾ9JNX,9 @27x](zW)WtOIdh)WZ\C欇U:PҢOZ~}ύDTZ-jSԎ#Tu8?pBUbnR+gmy65ΞQu<|rӢg-ZеbݢR] ThEJIdN&DqZ~Ж!,.JKn'<66 D.b-Z\\$!dYBeRk(1R|26k ]8osΠuG2ŮE ,!@2\-VTqeBN[dw-?hϐW\h6gt>ݵ..䯾E ,!@2-Z17!ՈmC[ĘI5L7u+$?hϐ纻kUW,Ϝ3ٵMB dYs,ۑє4x2s" 6dVnw9?-gֹϐ/]5H e9ήuh: dYBe[9u˽`+c]ea+Ե_Fsg.?I%a ,!@2P\@rMjuw{$A> y|hk%5|0jV5 Z!@ ,u -nw̮]˱\m~JaȽU\溻PaΒY9CE"9,!@2P\@riA_A5UB^|>]j$Fr*TzCݵxm C., 9 @2 -P\`WƲCMⷐG5pj,fnq? t-! C ,u -PB[)CY?~ ݵn6U ͐!gYrKL쀚*W!ϴp8Ul᫜e h/8\>)ѝjgr0@ ,u -Z_ת\.=>㫐ΜEK W9 _pעO$~Zș dY [{kɾ\ܭw@iI$TO>)woYmXNAYBenE u-ڤ& OqZ,⟜$-Z~_W/Nș dY [{ YI8OrȫukU\Q gYr=|gjV%tעd! re g[.n![&!C^[k]Om[C,!@2P\@ݲBLB⇜nec[tAڐ!VCYBene?l9u#E듢i>6d}!re g[.n#!™$9ѵve!re g[.n#!™$9k<]? fS~ dY [xȹp&!xbtf 琳,9@pu 985]3 Ifsvmnq쇴 Zs"YrA ,u -{d6䩇?pz^wE Y*9C_{٧CIяZ{ny!g#,!@2P\@ݲGfC8sl{Tfsvٵx?|?0d]Y 9 @2 -PWkը2 ]˹4uԫy>]!g/,!@2P\@ݲGCi{uk5d Y?|(BjYBene <|׭Ԑ2fШXƲTɢre g[.n#S!GB@i ׭̌Wrvtѯ_>E!g5,!@2P\@ݲGBW]]H|2!mɄ99 @2 -P쑩G5pݚO Y-S9qk 9{!gYr=2rwa[K##jjٵ}GYԵHօ,9@pu *w25d䜊o-ɺre g[.n##!O|kjvٵᦷE/E+셜 dY [H'n-!e$gw"0+Z5 h6Ȣre g[.nC>yZҒH(Fm'kwOsO⠖E!g5,!@2P\@ݲ|3mϸn ]8r|,eqݺTFD퐳,9@pu!\q9#ܵ/"rC ,u -{t9uK5svyhY,9@pu!KVUCA8gw?ߦJVl,!@2P\@ݲpqʝK3]C[!9 @2 -P![sj(7B"YBeneɐWk%d.Xph)Q5|,9@pu2!TqZrLΛr\]D e9l%,!@2P\@ݲ@TkQRCG MY <\Fh[ȶB ,u -{<[PySn6Us6v[ȶB ,u -{L94o;U~~~Mj ' uڳDLUj.QԑzFUSU݊IdP"QXh 9IչB(DEʌpt \9a+c j*fp2zQ<480f9 6(Xh 4E]dvz LY u ]+ᦘ<ИIsN P+ԝMDh},&C'P< -Onxu [@'P< -Onn]Vm[Hj ̌@r֭yyyjj VbL@Č pjtC($ޖ*5-P00QCIsXs&`?+49-q?:$!=u+zTeuVD.lV!c5^z&O]Mbq2V6$37{bԵ跨^uަ/ 1ˌE!S1~y8nP(0=Z8wO9x]h=_մ?]h~Koo8ņ y} iLXC jp-:jqztˑw$[5!ԭ%Yx{MUH۔Zooz'U 3LބV#j҇2w iè[ݢU!q1y{PyI矉oP8Qh :FwTL#*n~6s,m)y̆?1(X8EK#HiRǿ([҈4 i[N.$j% "j6!Oh$m_3Q,O(f$~2&Ԇin%1 #5Si櫕6Dg#jZ<|4ӂ4~P4V 51_[),~J nIkk%⊎;3FEƼ et-.W u+Is@^RAoom| u+z[Mub4 Z藇GhzfB<W_!1nU}dDkqL}Uw ZN[ܢߢpUg #Rѿ[Sg5~8sIH-=Ҝ?IOP+wO<1(E56A‰NުZwп㍭yS(F\sy6At.@bOcF?cnAHQ $!'A'P< -Onxu [@'P< -Onxu [_Vb+//W+߶m[kjjںukccZ([PP@{ fbi_3;v׫ ׭ZzymP2i&G-h>X>BShn:qh \).U7~gw'4& ozMCK;_s0i6z(~IzX2qH#1Rf&["_>|d~{]x~.J;)^mR+S^0%V蘨?~0뚤ݗSujqz'64Iw{꼕iD|›.%&]3<]_݂/& {Qଡ଼=5݋_T[ 4^ͧ ΆqhQDҋt ~t&p:x+`zvnE_z@"2hpD߅WyMi:x)=|;n:c7:̨3ox<:nSpvn58w5ڛqO%712_Hp~:FHOIs(g,<1̹x hz-^ݢ46_ ~z2D^u/ѫGS+S,VlhCsF%GSD'm8Nw:Gݧ2F1ϻq~e9ȷk#TbΣv:c xe,zk݊_-zWi3zK0H9v[5U ٥}egQoM]mg{a-n6EWi zʝ/v&CwCx/_?A4*׫3RztI ݋ OWK[Y M5_,==)Wy"_Hq~Sx =phSj [:d z4 Vi=7;GiSt4nLzp??Zy&AsqJiDt>^ 1ݑ"_o }Pw&//oRÙ`-uS9j4 jDO)|&a6p'P< -Onxu [@'P< -Onxu [@'P< -Onxu [@*es'׮IENDB`zstd-0.5.1/images/DCspeed5.png000066400000000000000000002074141266132244200160620ustar00rootroot00000000000000PNG  IHDRsRGBgAMA a pHYsodtEXtSoftwarepaint.net 4.0.9l3~NIDATx^wם/z?}u׽w=޻ֽgs&'d&s2c9cx(8Nirf8wLl# 096~ c^ j-vս{}?k/VծV%}} PSAm)ʠj @ePE5vj 25PvqQ] j;Ʈ@MT@\TcWA^xojy5 OW#:rȳ>`^xL&k.__PE5vj l۸qc%X-ݑ#GM ˗/=u!ӽ0cj @\TcWVz v 9rVWk;^^Dm@\TcW,.6nțZ[[xYPFt+> N  C-S=쳼Z/&B/ms_Q'QAm)(K ^|E>t+U߿_eO#tG[Is4~ j; 5^lq=7j_|Q_J 랎Lwڟo#mL&:[IF<2xv@PE5vj *s{E <5… ˯.LV蕨{ӟ;5kX|RxOv@PE5vj se>.X]"<T;R\,[M_'d2_o[EmDO|Oj;Ʈ@M|tɕdTCLIg ~g+lŢ ~KPAm)(+q d2ŵ3_$K:'xABO{ .+PSPkւ qt ^ze>Ek oIuegU%ףWH+?W] 퀠j O 3Jp1}Wm޳ҍ߿_fMl=í^]q +E!Ȅ .+PSPQ1܇-\P^u}B7$IsBjd7zZPwpg _ޟmQwwwSA_k@)jllLU v๮%K,Z[PL&C[M}t:ܬֹ qiAM՗ /-KtttuTcWD+P+Pv%KpIahl8 /:::Ra kkkP,uTcWr###Zo)?\Ӳ:;;SM&qDwwwdE 9(ꎩ+Nz7&lDO_dZ"5 j $8O=#nmݺʄ^`m9ս0R]Ofj.]rїCK+<4::g2=pҢ֓ڎB[ Bg?FpƮ@Mx'ّ}GXY,xaPep(6(]vyZ`˝b4Ah^==lIhKӖۘw! VZ@Wj#c|.Q끧59›B_6'xU7&Nhw׬gBBOEw/I Jz`yl OzI~^-~:ZSP|űQlqX:yUWJ1",8Q]Kc>D_)Ti &esFî0wR/T[N!H2ʻ_#ܤ|fPOR)y7ϭ1%UBٹ%K,u^yLx^*<zWٺuk(B;Yo$zZj G{alQ9PATC\(,)4W*cрh뒢+o*$U Kܟn^ƫ⭅G۩Q( *v!NW*qevROK4H%ioKԧR;f~a 9NwBx:o*=ΕEZ^)ѹ( 5)^@o.Ossg#09R_2@BƮ@M$;'iFA@mQO)NA|")_˔8?NVd2VPCk. *+坋"+~lዄ|]Q\-= Y핢_'|0*F2ݙQD_BT_ }2_wok H6>'+PSI'BDĝ¢NVpk@{7PDy݌i+r],sVCq񤋘')ޙL07\!z|^X ~z_u)Q4y )wyX%Qs!_~#_ Qe4|9P+PS'BDB[[q:;;$#]&޳pa OuUl[J5 fW'נ?/Ǹ ѡ{zxkBW^%߀>O65_waD?^=2Fp=![_! z?$c5Lcccj=FA@mQouwwð޳:ʦbITP|kSPzZV>)PfWW+A`4:wf`8`k+м<}ФiVWg_*tqF_sSWHo`hXuyFIMU.H?#TcW& sPFA@mQN L35GpnhAp̢]S>ۈ UӜROQ6$5i,YBO;F4)W4_k#j= }QJ* sC9biӋ_8,}<~x@wvQD/Cв>h72}9A V~ooͼ TcWO2 27j; @]uV_l!TcWٻO2 27j; @]ŢƮ@M$wednvj;BmEmNQ]pDRNӌ́BmPW)+PS cD( ssPU;@J TcW\O2 27j; @\TcWܓO2 27j; @\TcWfGFFJbD .+PS.I'BD .+PSnH'BD .+PSH'BD .+PS 'BD .+PS'BD .+PS 'BD .+PSuƪOD .+PS'BD .+PS'BD .+PSu'BD .+PSrfdnvj;Ʈ@MI'BD .+PSrPFA@mQj @ D}"Q9PAT5`O2 27j; @\TcWxPFA@mQj %b>( *vqQ]A'BD .+PS'BDڮC߫wRVf 2-P&Ʈ@M`bbƆ2 27j;*1]iڎTL6j:\M5R] N+( dvܦџUvtY誮&Ʈ@MDfq]yFA@mQ%㶮ڮ9N>wlj @DD%́J@mNG R _q7'ٕP#)Dzme\@{l\6̦Էb2)PSIv3 27j;ڮYjj;xgZlw wc)PSIvU0 27j;ڎ{Pj҂_smǵZ񗜟6$ELI$ELI$,c)pD[RHgn3ߡWdN<#$)bDHL"$)bDHL"$`3LMOT( v|Rt'I\fS$<#$)bDHL"$)bDHL"$`3LM52 27j;ʟڎW5㌹V2*3B"O$B"O$B 1AX@>{T }vFA@mQ%sj;I>I>I*$&X SS iV3 677+×t=WfSp-FA@mQg$ELI$ELI$,c)h`OGte\pSlZ6R+P ssPف3B"O$B"O$B 14Z uW;>Z(:]FA@mQg$ELI$ELI$,c)h4*VJ.JvsL&^1\ ssPف3B"O$B"O$B 14q{L懺#I>I*$&X SST*.ܒؕrccc#0 27Ghm8`bbBU vv󌐤!1!1BbE|05dhw%gAT@m!I'Bb!I'Bb!Iaj \jhUq|>7z&(oll,3́Bmgj;I>I>I*$&X SSh|K Cm6]f M* џj=6FA@mQg$ELI$ELI$,c)1 J̌́Bmgj;I>I>I*$&X SSrl6gdnvj;;PyFHR􉐘DHR􉐘DHR!1">f]wednvj;;PyFHR􉐘DHR􉐘DHR!1">fZ>( *vv󌐤!1!1BbE|05)0wednvj;;PyFHR􉐘DHR􉐘DHR!1">fQ=>( *vv󌐤!1!1BbE|05}"Q9PAT@m!I'Bb!I'Bb!Iaj #lvddD4Q9PAT@m!I'Bb!I'Bb!Iaj  ?N3 27j; <#$)bDHL"$)bDHL"$`3LM$_c>( *vv󌐤!1!1BbE|05p D( ssPف3B"O$B"O$B 1@b9rPFA@mQg$ELI$ELI$,c)dŕBmgj;I>I>I*$&X SS 'BDv1}"$&1}"$&THLO2 27j; <#$)bDHL"$)bDHL"$`3LM$wednvj;;PyFHR􉐘DHR􉐘DHR!1">fH>( *vv󌐤!1!1BbE|05<>( *vv󌐤!1!1BbE|05නdDv1}"$&1}"$&THL\ƪ1 27j; <#$)bDHL"$)bDHL"$`3LM8)Awednvj;;PyFHR􉐘DHR􉐘DHR!1">fpL>( *vv󌐤!1!1BbE|05$}"Q9PAT@m!I'Bb!I'Bb!Iaj  D( ssPف3B"O$B"O$B 1}PFA@mQg$ELI$ELI$,c)FK'BDv1}"$&ԑ)r$f܄$B 1@qPFA@mQg$ELI$u!fvz|sO^oiB͝ 1@HL"$`3LM4ĄgDv1}"$&1]|]cևDHR!1">f;Oӌ́Bmgj;I>Iؘŝ]cc֍DHR!1">fl6IvQ9PAT@m!I'Bb!ITgns$$&THL˻O2 27j; <#$)bDHL"$icHU1eQ֬1IHL"$`3LMԅ ćBmgj;I>IocKSjך50f= I$,c)}PFA@mQg$ELI$m`L\$kDHR!1">f4 ssPف3B"O$B66;ZnIQ!1BbE|05!wednvj;;PyFHR􉐘DH|za# YOBb!Iaj r>( *vv󌐤!13KղqtvQ1LHL"$`3LM& ssPف3B"O$B6$ѽ?f>Q9PATɸ%t_];_J$2"Am!I'Bb!INHѠZu#VbOHL"$`3LMcdnvUk;.tŖNu[ss3mecT*UɦHPyFHR􉐘DHcf7K:Zv:;R{DI*$&X SSU3 27j;ʟڎЪfC;7Ug$ELI$1f3;1fRI$,c)pZDe<#$)bDHL"$i-1tv;2ϺّZb&DHR!1">f( ckgdnvj;;PyFHR􉐘DHҪc^=F[Ǧf;GT3Y$B 1A]rU'1l>aQ9PAT@m!I'Bb!IoFUgmg.fI$,c)p@SSS:e󗚛S/wtt2,2 27j; <#$)bDHL"$i1\[Rp@1HHL"$`3LMAqOG9tqdx&l>aQ9PAT@m!I'Bb!IƬ}pl I$,c)h4ۡ>.NN_0JBL&SfZH.S+`Q9PAT@m!I'Bb!I#92`gG"L.!1BbE|05nŽ^e6uh( ssPف3B"O$BFƩ_%1V3$B 18 U!,7nQ-l;&bcdnNpz@m!I'Bb!I#,߹rя3$B 14ZqݖNiB9Zvms'&&0 27Ghm8n;<#$)bDHL"$iԘ;7բL(!1BbE|05V+s2`^lvddD(HBmgj;I>IZEΎT3$B 14p|U,U]2 >N( *vv󌐤!1 6wwv#$&THLiNL]f v cJ̌́Bmgj;I>IZu3[r#UL!1BbE|05 XZQ9PAT@m!I'Bb!I'Bb!Iaj w|]. 2 27j; <#$)bDHL"$)bDHL"$`3LMxwednvj;;PyFHR􉐘DHR􉐘DHR!1">fXOӌ́Bmgj;I>I>I*$&X SS>'BDv1}"$&1}"$&THLSO2 27j; <#$)bDHL"$)bDHL"$`3LMx!wednvj;;PyFHR􉐘DHR􉐘DHR!1">fE>( *vv󌐤!1!1BbE|05}"Q9PAT@m!I'Bb!I'Bb!Iaj ~PFA@mQg$ELI$ELI$,c)$śBmgj;I>I>I*$&X SS'BDv1}"$&1}"$&THLhbb ćBmgj;I>I>I*$&X SSIvQ9PAT@m!I'Bb!I'Bb!Iaj 9٬'iFA@mQg$ELI$ELI$,c)ṕBmgj;I>I>I*$&X SSKʅAFA@mQg$ELI$ELI$,c)PFA@mQg$ELI$ELI$,c)W%$;( *vv󌐤!1!1BbE|05}"Q9PAT@m!I'Bb!I'Bb!Iaj =ɺD( ssPف3B"O$B"O$B 1K}alQ9PAT@m!I'Bb!I'Bb!Iaj I?N3 27j; <#$)bDHL"$)bDHL"$`3LM84 ssPف3B"O$B"fT3x~jC4hag1'$`3LM4Z6R+0 27j; <#$)bDHL"$)bVnvf7[n;o-^S;5 $`3LM4wednvj;;PyFHR􉐘DHRĬ\hg>'~3$,c) ssPف3B"O$B"ffNkTu}"Q9PAT@m!I'Bb!IB.tykڵqjB 1@}}fdnvj;;PyFHR􉐘DHRĬ̝SW;7N1CHR!1">f#/>( *vv󌐤!1I6?r"K}(jzTHL׻O2 27j; <#$)bDHL"$en;3g2ÅR!Iaj ~B. 2 27j; <#$)bDHL"$enk} cLߥqJ􏐤BbE|053>( *vv󌐤!1c{sػc7sᅳ9AykW;[6PhL/ I*$&X SSxfdnvj;;PyFHR􉐘DHR19濟^S{%-scwvwkИ^THL!́Bmgj;I>I*9Ԧw9[i;{mٱИ^THLb ́Bmgj;I>I*9fuBczn|~iAMnL|alQ9PAT@m!I'Bb!I%ǜ"YnIhL/MzU`7&H SSȼD( ssPف3B"O$BJ9ӳ9oIhL/YL:ϟٲk;Zp;1A>f'́JRmTѡKhnn2ZgV5[PJ󌐤!1cNmܨp民Iv<:bLj&́JLm*h*[&H}eikkt:w()v1}"$&Tr̙3^WF[ÝFKO wb|05P}"Q9PATɨ㊭Tm 8P(㚛JI e6E3B"O$B9q{ݷTI{w=a#)+[ISxs 3LMT/?:DڎۺV\577iRBM󌐤!12cΎOm;- xb](#jO:O=Z wiaj *8ɮ< ssPۥiѪhlg$ELI$s6{mk0{ o$52rw6fu waj "}FA@mQ^uuuθ5=wmlMpm@z>eP{Ǻ/}576)PSQ2 27j;ڮYjm@2}۞֪o }Wm$cG;N?bn̏[G@ @MT V( *k;B=vl;K!$)bDHL"$w^ΎLA#Sxnw~-֙۷'z8wOfuWM\a lx;j) [aj DTFA@mQ%튯{p'*iCHR􉐘DHR91/즻AȻIa׾$fgf߷ˬYu'7v0@rP惓`dnvUk;ػ⊭3LRe6E3B"O$B y6UzGȻIvNshݱϦoTK !o(X SS%0 27j;*IPyFHR􉐘DHRcΎ^mn2wKm&k4tqfO>3~MdBPDv1}"$&',g>T9en|>n[/w?oPVKӓe6U w( *vv󌐤!1>]v_v9̩vM4 o( SSt:S/'z̦$;[́Bmgj;I>Iq;/rgw{_ JjW[7c)p p]]]z9xT-T}. ssPف3B"O$Bsٵ~}{1 ,v4<;7c)pLt:ZPfSp 댂́Bmgj;I>Ieُo+rH3^,}̳;=1hC:>ftuu5uMR\&)IW ( *vv󌐤!1Ŝ:x{ݷ{ M31/otƠԮ^ aj \bqJJ6&^1}"FA@mQg$ELI$,fֱSҷ,f)Bb!Iaj dzζ, ssv*ԛ.Amgj;I>IU̝g[5w;B 18#N7tul;#S011*pj;;PyFHR􉐘DHRb}Iuv_x_ !1BbE|05nSZ/dE\ ss"Y <#$)bDHL"$71gNӝob'$&THL .qI]>]]]Zf111122Vbcdnvj;;PyFHR􉐘DHR?buuطEs^Bb!Iaj  I3z=5[P\'iFA@mQg$ELI$ ą͝ݝ?2wKm f%$B 1 l'iFA@mQg$ELI$M|ܭ?n72Bb!Iaj @ŁZ ssPف3B"O$B&;f~ξ縳z|dǬDHR!1">fZ=/ 2 27j; <#$)bDHL"$icN^uv_TarBb!Iaj _D( ssPف3B"O$B&7Lo?\fKHnH$B 1ufdnvj;;PyFHR􉐘DH҄̏^M{PBBcF%$&THLSO2 27j; <#$)bDHL"$icfMmz;?u!1 $&THLRO2 27j; <#$)bDHL"$ibgt<ÝuߚVe%/fU$B 1/~alQ9PAT@m!I'Bb!I3kzjv>Y!1BbE|05 Nӌ́Bmgj;I>I܆MjɊY5!1BbE|05pNdDv1}"$&3x~jC4hanCbSe\iDHR!1">fHl6;44V\bdnvj;;PyFHR􉐘DHR7cNuFXg oCfL$B 1@b9rPFA@mQg$ELI$u3foTx 7cZ'$&THL ćBmgj;I>I`̙SU]aܚ[9OZ1cAHL"$`3LM$kwednvj;;PyFHR􉐘DHRc<툃1 $&THL4 ssPف3B"O$B:sjCFOg ]+`8I$,c)ṕBmgj;I>I`LvUI*$&X SSI'BDv1}"$&_$/ƌDHR!1">fp[. 2 27j; <#$)bDHL"$1gzs=AaԮs0f$B 1qPFA@mQg$ELI$u3OUwv|QU͘ I$,c)'%$;( *vv󌐤!1Ɯp{ǝ-kj(!1BbE|05d}"Q9PAT@m!I'Bb!I9sΎsI7v79~w=w1bCHL"$`3LM8&qwednvj;;PyFHR􉐘DHRbN[5[3bDHL"$`3LM8#Dv1}"$&ԩ3U]gNQ683>Bb!Iaj ɽD( ssPف3B"O$BGڭSi;𼚵ĝI*$&X SSIvQ9PAT@m!I'Bb!I]HNT3fBb!Iaj Ij% ?6CW*?Z>}u5kI*$&X SSҟj;FA@mQg$ELI$1Ls c,V;5{sljO5L !1BbE|05PwdDv1}"$&Ƙs`gwKwUY6;{ΝTwgԼm5L !1BbE|05PG^}"Q9PAT@m!I'Bb!Ikyz SMwoΎF\A-1DHL"$`3LMԋwednvj;;PyFHR􉐘DHZb.3ltX1v s{_qg7z5Zb&DHR!1">f Dv1}"$&=1]էv-2;usj_gԆx3A$B 1@̼D( ssPف3B"O$BV37={xӊ3F.pgw{go\R.fI$,c)8I;N3 27j; <#$)bDHL"$iԘS3o|<ؚ~ J1ӳ_uv_x_)j̄I*$&X SSsPFA@mQg$ELI$<;߹Eg:0{uoqg;;5c&DHR!1">fO2 27j; <#$)bDHL"$i%1O,k3{\YkȘcz mΝ?nj?|cVILI$,c)^ddnvj;;PyFHR􉐘DH1?}G\ɍON sm' >;k9{uPƯ|LoI$,c){d}"Q9PAT tӜT*ftuu 5[dl-06Ug$ELI$-Ӂ?|(=)6]]1>Kw ;z5N]o!PfS$<#$)bDHL_ɩ炭[z>~(kbUa.hu: %$&THLj cK1 27j;*I][[>XssQJUVZ()v1}"$&/\gw2Xݟ,•};>QY~lorg7Z5[_$B 1@UṕJ@mm+ޭWiOZյq+ڮԦHSߍ*}V+=fmhWmʨ*5NQ9PAT H@I{fh)ue6E-=FIg[رѽKˮ3WP1# @AS'*ddnvUj;>9wAzf|%r~1}"$&,k3FOgGW]ɟ;;3'F,EHL"$`3LMT wQ9PAT - >^NNiCHR􉐘ijfoOL;܁lxn"$&THL*36661Q'Q9PATvt:X5772+Њ8)3JzHPyFHR􉐘ijKv5z:c,egN;ԦΎgo77R$B 1|p*Dg->,<㝙qz]MCm!I'BbWzsEcѫjNu{:c vj2$B 1@YDúJEBm!I'Bb?gW}h탴zLUJuv4kψ~I*$&X SS%0 27j; <#$)bDHLA~Fws;WxT̩wǭޏxnVBHL"$`3LM'jddnvj;;PyFHR􉐘$I3#[ӯ&fh:]Gc鮡?3wy]Յ;o-V6H I$,c)pǦ3㎈e6wQ9PAT@m!I'BbD'=xb=\+16=dtƘpڵAtDHR!1">fܜJxٸaMUrCCCD팂́Bmgj;I>$4av W#$B 189N.w8LBMU',2 27j; <#$)bDHLĤs_qVwv-.QJsd}W +1'$&THL2LSSSWWZHjv2OXgdnvj;;PyFHR􉐘$qIGnН]ssy4+1gzs=AaԮ b%$B 147NOT*e22zŲȈZḰBmgj;I>$+il>6V;o-6:=n2n d+$B 14vUU^-IW '( *vv󌐤!1I_݀s6{ޟ;[hکqltDHR!1">fF+宩mq0 27j; <#$)bDHL;>'=|TsĞ;o-p?;{mlϳcvc:KHL"$`3LMAqml;]d⫃cbdnNpn vv󌐤!1Ig+;iNms?!Iaj -S%EGGZTr'.N}\ ssl;'HkiiimmU|3B"O$%=w}fh[Ǯ>㫛T5絹3&!Iaj Jr]]]ul2s\ ssb-ZwcL35w<#$)bDHLNɩtCW훚-0>N D}.4 27j;*nɒ%---F3tZ{g$ELII:ٝ VuK_O݉+􌐤BbE|05 C}Nӌ́ 'YhZj;I>8pBOwogo>ČbzFHR!1">f  0 27j;ZWBm!I'BbG.3ltX1v#1㆘THL|'BD{mhѢn2g%6$ELIIڌU}jת83n!Iaj _u06( kt:N?nɒ%j <#$)bDHLHRvV g$,c)ÓmiiijjjnnNRz ^󌐤!1#I|錱tWMH̸!g$,c)4$;( k;2::֖NoRt<#$)bDHL3o_P\ᾱcѫUix@LI*$&X SS~'BDUNv1}"$&ilw5xL~V=*Y7!Iaj # D( ssPف3B"O$ L:8z>7=^cij50f=!g$,c)/palQ9PATvK 8^z?󌐤!1I~+\=g_cU}4wjٱFŬ3􌐤BbE|05|D( ssbrSiPyFHR􉐘!Iw|8O[M!6 Y!Iaj \;N3 27j;*.SVd@m!I'Bb:'˧<;.QT瘍THLˑO2 27j; mgj;I>3镛m>;e÷sy-f@!Iaj ܹD( ssbRZ d2tZxg$ELIꖴ|5uʇUn1 1=#$`3LM$ _Ku'D{mW3vI$ !I'Bb$}+z{{&ԆzŎCLI*$&X SSIvQ9PAT1v]MMMڪYv1}"$&;L~$gFnmuwLG g$,c)ṕ{Z[[~^@m!I'BbXNN,5;_l93>9W1݁THLO2 27j;*n֭mmmMMMgPWWWww<#$)bDHL_WnН􌐤BbE|05༤\ddnvUmܬ3B"O$1%=6xWzug 95ALI*$&X SSK'BD{m'j;I>đtc{ q 􌐤BbE|05$dDU.A46{g$ELI&MϾ|> Lm e73B 1{uPFA@mQ^uvv=(=3B"O$^Ŗ3goܚQbL!g$,c)$́kiiYdIWASS/dgg <#$)bDHLb+ifckug3Yb:1=#$`3LM$D{m4::y;^j;I>XIzĸ0;ZUVb1=#$`3LM!wednvU=j;Tj;I>Ԙt&? $gFnm.1fR g$,c)xsfdnvU]*|' YhOg$ELIjI:>90;Z1L􌐤BbE|05P}"Q9PAT%E*厎3NPyFHR􉐘/3 Zk`{gfBnڡ3T!Iaj q{g}?z eKZ_vUgۑT*Nղ~@m!I'BbI'foݜ/}av]UpU@LI*$&X SS cxTEA_|7qܧGm'j;I>O;\NrCFGW<7vX@LI*$&X SSu'Uџ\ܧjLm֦V3B"O$e^uiLL g$,c)JIvZLr/28Y̳m} j;H;dɒnݺu+I?󌐤!1I;;1R&O3B 1@tXk;vU,]gg'sT\hQ&^MӺj;I>IJGW]W&O3B 1@]$tm2믫_~ j>B U;?FrW~H/smG3϶Kn:ˣK,3h=3B"O$?\k3B 1@&&&Ԋ+~ށWuǥ ^5psWImG{.j XjL&ViFy^Bm!I'BbRIuwj{FOgp[3BzF]OҠ5e`եr1@rP>Jv7nCTJ_㏢b/J h^$+N-͡Q#v1}"$&1޾ti쓏動?w}ch\ZgbzFHҤǼ}{SsWڎ?\ikk}Xss-¯J*1@lD(}Zg} 5^?L7n'+$WN-y g$ELNHѠ5|wse :U\K%1oϪgq^I.T=gh6wWѪ掏b'Bv\*/s#q3z:vุjԽg <#$)b8fvz|sO^oiЂ3;v[m_y{\sm'->8>9( P/!g$MnΎG]=C:vAڟ^Z=]pYxV1m}"T,Xn-v\vK,Q\YjXVQI@=5U`|V+3B"O.',/{tW+.]]Ww{r+{i~˻Vtq7A1 bzFH҄,񨥹 N`=t>V\٪y2Vc)D(H϶ vxo϶O!k;ڙ3v7u^ߡڋ|,=̦HPyFHRI0fqg#Y]nb~cwwoz}GO>w^ݨ8czCLITC[OFXo>>[`UxpYZCF?׍K\vp4zrz*rhv,[`hڑ#Gx^ v4t+/uCGlws\zmg殮ƣ2"Am!I':fΎG|~iAM0566gwlo}yugؓ; wxw_v4xuU ٓC~CLIT%3W@?T뢭|m;;•Z UzrGH?[xR1 OyP|I_|E..\x!/4?d[wН?c7L C *?k;@kG?U j;I>1w2Czo/7hfy4^B%wogW4~ty?zY~CLIT̆mϭ񏟬W`oe+UeAƣ}*A\$J1@mDúJRm? ͗bP}:5W j;I>Wnol}oֵ]M:?ճ/:dtsFc: f7W<6ֿwOGݿ+H@JgW7)_OAcy^+~6Z >'?~y_RAS c}:FA@mQ% |)3)x2"NKOB"fo_Whh9?}꟮6nLѨQ\ 3[6}{/{qӉtאz<;nKALIA٫lo>R{gG'g<&*UџC]+ȸS3FƏ5T'-|05OT( zv}SU+Sۅz-w6̦HPyFHRLm݆/~qr=3RΝ]>yw9~]fͪ+59ӛ]Zzpб洞6q;/􌐤BbE|05P1}rFA@mQ^uvv6(+NK4w9^ ϨRa{? rM󌐤龙\xW?Go=CcfǷeT}:ۛ к{qK+;/<=g+X}p&?7?!Iaj 2D$FA@mQ^577/Y[Gk"&fze6Ug$ENH.Lix3:c{߹v-hTٙɡp[9}o5Zm>~ĕM4iFuTHL*ODednvU]SSZj;I -qk.ލ?%o%m{kǺ˜XwvǶ oeL+[v<>`Tr8 e cU}4jC_o[O g$,c)pDU2Zj;IxCl*>nc\Ys6Ϟ=ufFqjݚ=_L߼Iݱ؁ѕkW֢ۺW<_:$ubDHL"$`3LMOriGZf/񛟿9`Tuۺu%KԊPyFHRl.t<~_>z|x^3 8gm|ѫv~cϮmwlzD{.^6:1}"$&THLe|[Zv|ɏG˨D{mֶhѢԽQJ"Nk{ .PAb@m!I8K3ƖԮUzo/p fgfk_h[7u'޵ ^^ uYg|M?V4'Bb!Iaj P2.Z(j|aZDdGcPہu@m!I_$K-e$l>ffnhϘ^8O[K:=wzϹ ~x%fe/>lh,\ٷХnVIR O$B 18TmNJF;BM'۾Ki@mvթd2?Q5v1/_mZ:;RIL}?ap ;O|^i7ntO8v57]*I􉐘DHR!1">f4ݫSTh7GҖ٤+Ok=׬r|? v`W=j BwS|3B"fK]$[cgG<.ts]_gp:3#Vv\c`&bDHL"$`3LMcRLpsw{{Ɩ٤+^?Y:NPyFHRĬ̞/Kղwvdޘ'N=S\:^MNͤ<,x,]m8`l}lMV 5oR? O$B 1~E_Ti!U`^Xm֭jeʹ/󌐤YO[%ݫ4ߖyfKSwvL̩W/n*1ж>+ٯuv'hm8s{XÆ*'!1BbE|05[g 5 #spتTfm^ەgwCm!Inŝc{լU1o9}n3qKYpBwog6~w+S1 M􉐘DHR!1">fd2QNu(lvhhHgzv@mDr~1Wwv^fm Ɯ?yOCRְ|ϰQwo7q;z 1}"$&THL JT林8ڍVnXQf's `v---Hr~1`bjdrgƩ_gg8t6;ч֯3#{+OӋ'U+BLI$,c)p@S@sjCujjW m.+^uvvtGGGWW2q<#$)bց E{?X Rߵ35ǝZnpතqv6,}p̏3ƣ꫱oh O$B 1QOPk;ѱhѢ¿F(j/PyFHRČ[xwvٸ^C;yc۟g_y-2c7׿syNcJ?Į>I*$&X SSIvUGmGFGGxy"1j;I{Z5kl>;/J deW>~~Y}cCǾWճW:CLI$,c)ED(vNPyFHRČsgLLYfgf&z08je;n_D;97X}8kbDHL"$d2MMMjݪwuub SSPXj_7wl^;g$EHqg55}ח~|m-6:&=hʌx}+7KtueÏ꣱tоWuI>IA|~iAMݼaj GVNPXj^.|]8<#$)bZ9[y+j[iS3s3r7nʬY,Nojv|_2_:rFһzoo/}soF,|C1}"$&ԃ{{ -ح횛Z>fKw@m!IӮޟpaパMj[Ye>WugVÕlس=,~}tU} 'SBLI$Mz|^:*-~jy1GjD(v޵}mkkT;3B"Eŝ+}{|\ڼE]ϭj^_27U7sU= m8􉐘DHҤԧ;ݬR)Z D?<󤹹' 4 vɭaj v/ Bmbnݪsӷ·U~@m!IӖΎM&S >.t<ߟYgޏ2w~2vwp^wT7!1<ՎG'qFtF|Ɯd=՞>îvbPk;KbyyѢEKtj;IVx=ߨ n^>p]tkrj'sYG*pPvCLI$u*cݧ֭ pu7L<^AXTO )x[ j;D$; ߃;;;iYWxz<#$)bZo[jlITN>zam-śH:nnnV+zZFm8> kiii+|-GGG./g$EL+8K3Ɩx+7sotC/GDEW:]GdѫI?ώ'bDHL"$S1r]fͪ+~^j 1@2tPXdZղ@m!Iӊ#cŧpm\F_BEwLwI>IИşj|]q/z -_$JP)҅7n,XVSAmbHww7}3oj/,YBj <#$)bZqV~ґŽƲ~Hƃ/}̊WW7/K_2vУ򏢋;;$ELI$MhLţ[rfk\m@~YT*</ ϖ|05(U}^^'xVO^ Uyms҂[~|+o/X0VjvP$@m!Iӊ{=hv4;_ya'c+M5Fwݨ!I'Bb!Im 5"nfZ +S,?py|28>fHH'iFm˺Xۭn)v| ɻ_Ng$E]Q#rUϹ vvū?l}#.[G5B"O$B&4A;]6>fHZ>z݋/ȫk~;4vhyeGڍr|Amu{muV}' ɓ~@m!I3{&߻7.\ǭcqUc?,ɲ~^tjVL I>I*$&X SSΫFmgX_|mg ~1y*xW?xV}j;_]sssfS-ZwhkkkiiI?󌐤b|k34hqǮ=8-gJUj~ml܊..ϰc I>I*$&X SSnsг=(tmG=L뼕qm}k_Ki]~Ob_o -_A]m~@m!Id[Ceşwq]|%{:=]Ijx'Ž y7!1BbE|05નw-(3NbXƵݛ/<ϛV?3I*$&X SSN$b|>fpL-w 7nbȑ#/tGho|kC_Ankkӗǒ%KФZj;I*!=FV~,\ٷcxLJGN( ?ǵη[_ſ{/}F㿮lG# FM&$)bDHL"$`3LMƻO9r?OcQk;ck;}G-?"v\Ƒ/8k=3|/ZQI3BJڌQgewO_V˓TcM'hZ.wک$LHR􉐘DHR!1">fpĄZ .Tw݂ zg=g_!Kɼ3EmuP.ɤT*/ݺu+/xg$>feW]|Ʃ̎~Gq7swS1}"$&THL円*D_|BiYl;+T`lOUO fd:]>MO ڮ{ѢEMMMT%Kxܡ󌐤JγtW+SS׎u~}wv4_̖ͳzLn1}"$&THLOqJv|imh<uL_JCJ]75ʫO }c Aݒ%K(-ڮ3Be[Fᾱcѫe&&.(fsx;m<ۺ wI>I*$&X SSS' v| }+_O .f/0ƻOj;{mԔN;::he^P{xg$u0 ?6CWOn8ev->~-7Us?8~]ˬYu{_sgS3QgXjmmmj/PyFHRbNNͤI*$&X SSuauգc]s*|3B:s;l?Kw 3_ĖWnm['zQ;͙ͭ;v7>Sn('B"O$B 1@ȈZI v,מ΀3BpBwogWbl'C U*f>C;ױ{ڣȩԔ3J􏐤!1BbE|05d}"j;{mԄr~4~PF[nxncՔKtL I>I*$&X SS%=\fzm7|}uQj;kT*eFѤڣݾe2z`k~o_= se6E3Bs{fGW.1'ͬY57(s%>EMc I>I*$&X SSV%W/,y=8>GQj;zv=G577{(]Օ j;ISJ>.|N ^U]ɓtaGc܍jse3^!Kbz7$$)bDHL"$R .c){wCt혃Y#j;hk;!tZlg$)Tcʾx:J}+oa`tawzSP[ʝWȒM I>I0!Q~_X/ *kAzHaj 0V$AN#vpI{gGGZvAjCnO j;IS{+Sj9ӿ~㬱'Cb4Ϗtp`?-/r9 ;2{wε t!1ɍQq('s.bmy_ڸ+DP v}ԟ0 2ƃOPہ QuwwӷRBF8*Fxl\JGv6Eµn Ro_}oycڎbgv.3؍'$h|ij;pJ>a@mj;*nѢEvm8XW^oz+}V=< j;I5M.=<~aXyIߜǮ.i,5UT;=.zovfqFOg-}O]P]$1}"$&ԩ7)gU`eV-[C4z6{Q=؟IhE-aj }j;=PATv0B3ލ_jFƫ=8̦ʡ󌐤MϾ{rߟ1~d7ξ3q;[ԩv0:KHR􉐘DHRb6l^=*_&aڎvMlzfmWYO^>fL>  kE-Y)2Zojm֭jBm!I9pڃ#ſ<6C?_S5HSh&S fΎT3q$ELI$Mh̃';x;zU]-݂=@ОF qF ̜g~RCm лOBmj;mW wb󌐤bg_l1O{ T5l>zcqff}]N;%fI>Iܘ:JޕFV*5&[6JzbX3h&C7K:ڤ_'CmܻOBmj;*ڎUBX-'3>8f$O?~gGj B"O$B&7fL7-&c=]p~ё6wvFZDqn'13LMIvj;=PATvBgI'fo3~FxKU#oWzW}!3rql>?z(x5'ǝݦfg;;Rc1}"$&41p(01@ }"j;=PAT@mϒuv'rSSlOCױ|.w}FC:.ݼݚSS%fI>I*$&X SSED(vzQmݺ5Fmj;pBwogWb%}|mh_<1vsmn Z ։/Ԇ n\ε݉+PS%fI>I*$&X SSIWWW26*)sr+:^}"j;=PATv55v)鼵ݣԮ}TdwjjCejy7=ŵŬC-1EHR􉐘DHR!1">f7R)n낵-*/31-T_>  k%KtvvOIY3]CjW}Gwvg6o3~MmXl;;m5몪c&!1BbE|05Sx9XۥRn.ɔ٤+& vzbaή{uww=3~$MϾ؃[:|.wn |}n~7GoήԔê8B"O$B 18O v6&%D{mB/+j;x43r+ϴ]Tlmp`>W2~7ǻs5尪c&!1BbE|05N\϶]%=g^-ZD^@m癤'WN+?rZL{]ygڙugWMcCUn~|\۽arX1GHR􉐘DHR!1">fFknn.Ib_]C9Z( Cm]S% >%gÆBm&˯x.~wѫ|>݁cWu ?]C4b[##֯.Ԇjjb\{KM9ꘉ#$)bDHL"$`3LMct'Y9P運d!kEI]_gp8MONb=3k1o d֬Ժ56Ԡ꘿)v7jꘉ#$)bDHL"$`3LMcijjeOūe6A:ctdvkVϮ 3.'ItzjVյG:b^;Yfu+wv7QjSuU?ȵ]vn+긪c&!1BbE|051j;`|t-+ˍD{mٹh".nݪj;ϸt;#pWwr*paGcp;ԆU٭A5b&!1BbE|05 X-"Y=PATlR^@mg^+{3#q$l>ug7{Usg\mvwƯٲYwvW>Dm8"v'V]$1}"$&THL|ҟj= zvywoYvq6.ݕdon]fujC #,v&{Ԕ۪DB"O$B 1wBOPkkkkjjjmmUhՕNiSvq6w}cUksukgN .k'rm趼 W]$1}"$&THLI*$&X SS^P+eDU.HO&wnnxeÏ꣱tmtg|ҡtgwvǶ'[TEn࿪)U3$ELI$ fvz|@d2}GGZ"|05p\nhh(PkiiEސӆkIw:;*Ϊ+n1g;ױ;_U[\۽ar^1JHR􉐘DHҤNo ڛvE5ZUmf5[`KУ>ړqY+3k$6v1@T~P@mQթj;4<\~YǰֿszgGb9u \eVN|6]1ם|TSΫ"fB I>IṬW}n3^;ĕ?WPl` ;UU.`UǥR)+. OG4C,d3LM$_['BDKmg|-F[۶7PyIoήjmż52rjhQcNL%kN|OM%AԘ%$)bDHL"$S1_;Piu+(QOG+B9F}l +Uά[R#>fH*>  Xj%K1Zj;40pTmAL1o ;[##jCD9z N-J1KHR􉐘DHRb6l+k,6ըXh_qEX =ix5Ӊ|05༪>  XjEh+V3J:>9ͧugU!qĜ";Qc-?\M%AԘ%$)bDHL"$ircl"vi+/A>/gegkomc)eNvU,-0T%$j;4$u׎usaGcp\ [kQԘF1/$3$ELI$MtΎ\q宕v\WQ+E*/D* SSuNvU\gە2ՊPyI݃+z=Ysp6m}բ|zM[j* L.!I'Bb!I3ّ`+GҲqip3hl嫴 tV2I]O_HTv1}"j;=PATv G׵HOuN:z=>\Wbf+l>?vw;jQcWefTD\B"O$Bz3;=-̖jH^,؁jڎ'yڭ:O =wcj;-c)غD(vzbE,YB jjʹE_gթ׿#VbsoӝH|^msCԘ)vWn$3$ELI$,c)ؽD(vzbHggEnZZZ uϿgꖴ=f~jjxN]:ks͉qmVSI5fr I>I*$&X SSΰ~P@mQUۑѶ6]ՑEiγcT)ٽvrJH1MHR􉐘DHR!1">fpCwNvU(I*$&X SSP'}UY`s *vv󌕤{;ڵAƜ";_S)΁v&{TBDhB"O$B 1@ݍUqO<1omG;C0kGz_|ޏ˻]y侟 ='8PہPف3V>6ctxtUڵA*9zKwvgwlaԢV_M%G1NHR􉐘DHR!1">f>`m'˖~g^{-w v&vv󌕤~vŃԝ\NmKJbl/vzI'$)bDHL"$`3LM'ƍx ,5_&ygnZnr׿3h/kiUwjŃtOgiKO *"^x&}Y^[w… 3˗xZ믿Nzgj|#ӵSB#\<;PہPف3Vn:tcڵAĜfئ;?PLLVHVs7o֯߆q@LI$,c)xrPŵ@p˗/2,vzμ vVӟUǫ4:j;^jt:4'J0T 2-PƦ LI߻htxڵqJݸ1uLmHR1YΎG1"qg_?84!1BbE|05>ʨO ,| +聴S=SϢqtsWfO^mkkUn4e6E35& vv =reYh,5ՆgBcv}vխ|ߌڅv2Ϩ]V>f͜zרxܚ[9OkIc>I*$&X SSVYD`mwv +Q7nܸe?~qv\s/m.Pہvl*jnnV+eLƣtUWfS$:PہT۵555uttҌ=iR̦HPyH0捁VNoZTsΎP1}"$&THLjf;κ],3:2j;pSj;XήԞj\-)wc={~kOoO?_;cj^G,*Mݵן1z:c\jWR?T@4j 6q}"V@mQ%"B#פV I 9N}7yٽݩ ;NP;tvns9F @G@ @MT vM]'ܳmg6"%Mܵݐo՝\NmHͬNo<]Unب/"1}"$&THL'bNvUj k׽&6̦HPy¤3ٕv^vvw39vgύŽƝ-II〘>I3x~jC4hagPL&Syw3LMDГ4vz\tDknnŜZTML%Ig7%rڧ;8ϫmީ1gN Ӹ㻪>ώ9.􉐘DHƜO)4ҵk`O?0++g-aj d}"j;=PAT 8N}#-g4na9t3|SPyfޤFg 즳_g7z8R1!1!1ɍ9eFke8ڪ?-~(s-aj bD(vzvPy|=]{Ն$ysp7!$&1}"$&41gN[79Oq\ޕj⸧S+Eym 3LMT Dv)v.x`B;;No;G ohw'Bb!I'Bb!I3wy]Յ;o-VFl4-k|7_Jv,xrEh7E6Xڎzª)311Ivj;=PAT@mRIvխ7NeJ bzFHR􉐘DHRbN{o\cSBOʌ'y Zp2}ʛ(ڟW3$/F_ՊU|05PZOl9>=ҩè <6$Auk4?!I'Bb!I9]SϠ^A.Xb4,~?պ̓yk;ŗ SS%d١!iQ98w $j;;Py8/Ihgwc` UuvݚUqL/!g$ELI$u*fCζӟnR _yxtM\8]5z6_X SSawkGvqmcj;H(vvٍ\wv76+I$ELI$Mh̙wU_݃w]#25^ kk;tkk`K[ SS/VsP=IMUKⅱ(?_CmɅv &2ؚ~.\j/]=g.h n2}CLI>IܘwZlTuze~FѯR)*_ۥ箊eu.T+>aaj 0RxU}XAHXfSՒwXOCmv~8w}f~-=O>J/wvQynxԔ67!g$ELI$Mn;{nv4nMjFSVe~xsl?'?*LhVeX SS0x0#̦$$;2{k8>.0:; Pف.&foz.8~|b#tgG\Nm BLI>I3'ykԆikc=ώqZ*p 3v`FӡV{mWx{Vudaj P㭴PfSw Pف.:\ҩV b..O wԝݥC|1 􌐤!1BbE|05.3u*[ze6%A@muvvz 7>U:zo/7t0͞ݶUwvc|v j@LI>I*$&X SSnsAU_ZL@$j;=PA]-3ltX1vul>ff.Noj?ݶ3[O|v*7Ԁ1}"$&THL1•I\ Pف._1z:cfd{X϶K.vzتiLLLv.x6Q{j@LI>I*$&X SS]_zx$PvP@mh^$tx =#j||}C !I'Bb!Iaj #X馹d -|>]%@mj;vvK.ݭ[<vuIv4hԭc 􌐤!1BbE|05H>N3>NTIvz:@mgjz+z.8oϪ]2qQqWToh1􌐤!1BbE|05d@muv ˺k]Hyx%73kVmp 1=#$)bDHL"$`3LM$j;=PA]g_>p^s-8vuYmw653F%'􆖁1}"$&THL Pف.Y&foԝ]Csr[##֯3Jqv6\ibzFHR􉐘DHR!1">fH2vz:@mgj9u٭b)u&q*Yj4t19.􌐤!1BbE|05d@muvI•}\=[ĺjQʝnp{P-7cZ1}"$&THL Pف.>~M4Wz6q-l>{ܺ%w䋯k1c1}"$&THL Pفq3ٵGZfʔƩ\޽3?UWΩALI>I*$&X SSINvP@mf~Y->8>9NlvxNٍ9p'f3B"O$B 1@j;;P9թ'7ҝ/߀#Is[nK7􌐤!1BbE|05d@muvn:6xWz{pEϾ7(BۣOo.{\Y!I'Bb!Iaj P ( T*gO[:5n V5 ;g6o3~MmAcbzFHR􉐘DHR!1">fHl6;2w2j;=PA#Go7ѝ]7(֐33#ownh٬Ĭ?􌐤!1BbE|05(ccc/&@muv.(s=x*E'fv; s9-6!I'Bb!Iaj !X2Pفڮ}pYdpeCjCUtjlvٍ~l>ũ11=#$)bDHL"$`3LM$XZ @mj;vvk۹a=>W7]:zl 􌐤!1BbE|056} ~/vz:@mgjF9u-549t6ހb`k նŎCLI>I*$&X SS }"j;=PA]C9}C.VwbuH:s{tg7uKnbBm:tbzFHR􉐘DHR!1">fpqP@muvQ]=rϻ',&G:\8?qu fG;,tbzFHR􉐘DHR!1">fpO'Bj;;PL_tKmb뽽槦..2[=bL!g$ELI$,c)ǔD(vz:@mgj2S{~i[Ig3[6sCG 7Ϝ dG˷*؊8􌐤!1BbE|05wNvP@mWL?n;>`+>ծx\|`~;VL!g$ELI$,c)7LLLTxalj;=PA]/3 Z8xb|&?E]=J=1JvqzSASCYDǼfד4hAMPyʟM'M4􉐘DHR!1">fh*NPlIyNsz,jOn85|%Ԭ$3qnOGC>JL%7{?Ӡ-[1#=*Lt!1BbE|05Pl4vz:@mgj;[:;_-/3|;-YcRuҩWQ8es𖲍UudIh`VIVĮJz1}"$&THL''Bj;;PYqz ycfuЕ|KYRck<ʴlƬ94oR? O$B 1@#ralj;=PA =1u ]cIoޜ8yb΁ [-Ý8ZW1oo5K6ïo^R=Z?ҿ_?Uo4/_x*=U&bDHL"$`3LM]uwNvP@mgk3FOgGW]cD{3kVۼc`kwa[Ƽ19.7 eqX']8t'Og'vލeϭQjulzΫ M:􉐘DHR!1">f#['i@muvV4G:\8πfGw]zj:ҡ|ɡ<_ݸ1;3OHf<ڵ~CQI*l&n^;{|=ҳOs _o>lwOgvsKUW􉐘DHR!1">f> PفڮFs{&jc!{rF 7NeN[5ûw^;Tmp`IvmP6}S>ҳPqp=>u7zfzazt{Ok/8wOGgg7!1BbE|05P}"j;=PA])/3 Z8xb\m(~>4(5ƾ|̖\z®j?OUFO+swFx~7m~^=7쏟ojbF[ݸ$dduvdޤ~@LI$,c)Y06PفڮLsFFcY._۴ǘczvKvqvO>sU7qNt̉z#῾VN[oozpͮ'|vo^OY.^~qH[YFtS%I=>I*$&X SSq$; Pۥ9TJ͖L{f2>[lA+ڮ\gw2Xt8>9ڒvz\.R&f6j]|uՎܡR}Qj|iue\$\kM&M:􉐘DHR!1">fG'i@muzmѡL&Tz#ƫe6Epzn t)ȂǮ.~tUj<;zMҦʓ&1=Tpj_v1in7?X /諿ȼ/wtSI 1}"$&THLbfx1vz:HETYKp\t:mp8JjG&iSI̓7Jtvco^(=Oꜚ9r$3N]8a5aI0&a"L+#.āHq _o 6BF`˒9yݽVkIzW~?k۽.ZR^ZFn{>v WZuf٥H3$$$&<}F[I>v@8*r`ռPeh]f,]6푶鸼뤍@UgOydٶ_3ZNkVg'x5IRb$"ĄG(捱ivnPۡM톆FFFl|m'nN뿂UBm1gmU.Ziܸ|1Wuͻ'3fۍ߻o][~3˘q2f"IJ̐DSD4HeS'eD[vnPۡ Ssvvmmy߫{oly~au|^۴'oTuYK//_?zK+嫯bWlߏq^D.N)`Ѫ?Ρsh؛d/Ww}}A϶8p`scێ|:[oƁ+=]flh{W/n][״|\51! i6,Ne>v@j;Ϲvm;O?ژ5'{˖$ q'%]~<5_]jk׃on1?XiYl X*?}-j;7Pv { .cLU-[mW^{US'lNI1lݾ [w.\(t]$1E$IHbHF>l X16 j;T`D&Y[l900Fҫ.?q%ݭsVqǶcOq}tZ۝l.6]b~͝/?΍~vt쵂Sm%N*fy")"IJ̐DSD4HeS'ڢshv})32[mZXeN+X=j;]gvטM;G.ڊvI:ࣉWܷLU'Һ=l.TbV " I$1E$I# tQ6GMNsܠC&ڢSNN}gwl;ƞ٩''m9Sk(#sxLk;~әu_x{Ͷ[ bA$1E$IHbHF>l Zo?}-j;7Pj;?vv6htovv2& ԝ' F1';Gn&e5?sc/vʎY$%fH")"IILx);=􉶨ܠCp 5zy3}tp:~Y-T4$Lwv:~W~ʃw=x]zRƆ'g 5}+5f}DSD!$$i$13ʦ퍱ivnPۡv~D^^u}Vٴqvzf uJb;O?;T^Z$$)1CILIHb#gMmQ۹Am Pym7޽:zfa!d|QK))朝mk:ٲn")"IJ̐DSD4HeS@u>Ρs#.ѱO"K~pvve]h4<%\LO?{i%JY7$%fH")"IILx)~D[vnPۡv~D[۝?O'l6N=K;C?<޺Ob|72=]f36DI1&" I$1E$I# tQ6K+lE_liUQOh j;TΏ8kgmiC>:VL8Cl;~dzHl5ǬHbH3$$$&<}Fzj:l{+X`Xזk j;TΏ8k{w6[fflڨOl2IC1ř n}2%]fT 1," I$1E$I# tQ6ZƵZ-]%r`Ղ5$; j;TΏkN {'t>μvvׯxnޟN0_1_m>`tvW̚$$)1CILIHb#gMfҵ`+]+ V-@#>}-j;7Pj;?bun1][5xu4lW=ڟz=wG$%fH")"IILx)@\*Xe]kʧOEm*@mGTGӳ7>pP;|dfO=ݱG^]_Ӥm}On}umo /Ug'A")"IJ̐DSD4HeSѾ!]׫[ʖָ7ƦQ۹Am PUmS]bjS?xvv2>zm'Mj ZXٙ^ֵw+>w/Lh[b6N$1E$IHbHF>l uח.rg5vvO;;/VOؼI;S~eqb{% []K D$%fH")"IILx)F___o5jhy#omK?iw:65_'Q,ϻFr\5NӅ]^omu+fsESD!$$i$13ʦP [Om"j;78#3Op֥7]mLONOxWmvA"92̯+? [V_Mg.e̦$$)1CILIHb#gM;('CfExP۹Am Pdmw{#]}i7dl|xxaDDr\Mcpgn8wV7A71ILIRb$"ĄG(Bysl*u6)j;7Pj;?«^~]٥3gÇccɐ6PWϊMvKf8f0")"IJ̐DSD4HeS@Q۹Am P^mw3=]f9r6R;;lj"9*h\awk~ڣ{gt7 b$" I$1E$I# tQ64vv\tUmnA$$)1CILIHb#gMMFm*@mGxݜoc1۴ξg_wqjf't̋3v2~ϟӵHbH3$$$&<}FdvnPۡv~Wzz.ض?ۦ=5{ hm^E|w=K\awpb-" I$1E$I# tQ64vvXs-Ggf/v=u嗴;K3>0!*yKl.OSB")"IJ̐DSD4HeS@Q۹Am Pdmw'2m[=Eۨ.NM֬nb_lևP&lQ\EwݼZɅ ! ̈$$)1CILIHb#gMMFm*@mGxݟ}zVM{}Mγݥ͗fgmև &~ɅVnꭓ6O}.^qgwڿ <;ҫY " I$1E$I# tQ64_td5v!vw83v9pڝy̦O[LUm6 THfHbH3$$$&<}FLgm*@mG0ݟNơ?+jrq{j'jԋUgz̸gxm^$%fH")"IILx)iƦ2vav3$ϼe)59xkٝ| &I(~o C$1E$IHbHF>l h1[K j;TΏ0j'v](:m?sF;;rf}CR&o?g ;?zKm^N")"IJ̐DSD4HeS@COsܠC;WpN 6U:$hrjk?~諯JH1; $" I$1E$I# tQ64T$; j;TΏj; 2DhÝjZSDϓuZ}]g795XNH3$$$&<}FP{p5j;7Pj;?^۵>NƟٜmTsyR~Vu2^?}[ngx=b f`"IJ̐DSD4HeS@}clvM#9rܦƅig'SDo?7!,@D!$$i$13ʦtCm*@mGk8u=uͶۣST;ۤ]pkmwt5"ňH3$$$&<}FP?sdP۹Am P3vG߱zx1=1ZSDgN^bS),FD!$$i$13ʦ:v-̅ j;TΏvGvã w݉'20_=jS),FD!$$i$13ʦ:)􉶨ܠChhmw셯lvϽqf;FTNlzԯٙ[V_{ٔ0bΉ$)1CILIHb#gMcӨܠChhm7 u*ԫj7MWI:x~6u0bΉ$)1CILIHb#gM5ͧOEm*@mGk}'!mPO6.NM֬T;ѓjM]-s"f`"IJ̐DSD4HeS@O-$; j;TΏ&vvvn?aSsƙN;cl$w /ljaĜ1IRb$"ĄG(zg^>v^;W~ 6;6fϟ?~vUԻɩq~gڿ1IRb$"ĄG(zd>vͪ/^꿿wl Um\۹-M2cWeҒvFnbv$)1CILIHb#gM[cӨܠChVmKgڪ.Ty}Zxu[Q*ds7TN1AD!$$i$13ʦj-'ڢsA.^bvϼvKG6or.̣^\ʒdvvu_;l61DD!$$i$13ʦx<ΡsAgnC3l;mdN۱VT%{ݾ 6Ncv$)1CILIHb#gMXOEm*@mGSj޽Z9Z5GSdy*&wSk('WغvsH3$$$&<}FP>/>v@j+lQ.aWljlfU]jJmwojgwǶK5GStȤD5Ij[F/)[Nc.1IRb$"ĄG(鍱wd– j;TȈ괕Z^zjɪ!]P빂U҈OGigwݽ{Oh#>I՝5q1$)1CILIHb#gM)'ݩK>sg/ߵ+e&w~Ӗz#_S}39wC0&فitJVN[*᪺URnfMimvטSGmOQ w$mg'(lvsH3$$$&<}FP9?}Wź6[_tfZإ}3JbSWnfP!vp\~܎ ݎ?kgw.SY>t*O+;G:;kP f`"IJ̐DSD4HeSo|DOj |NTOp5ضqںp=+ZۿwF^l;v}$ߟY*9Vr`ռԼp{b6;emjNњm7f̸o iNb.1IRb$"ĄG('2ݵZƍʕ+n[ݻe_,^i5kܙt⛗ϠK^kizr:ҞNE91hRm7447::jWˬq\ȼU]miռhmg?'ܧ7ݷ&hLOvϦ.3~<).N)}ck˅V\i)-_N1[Nq-vՉr+f:Zv.z^^Am`4ӿU2~^;RWj^\ۍ?rg'\8lO/e:7dl`O4 |$;dwޭ\EWmܸ1xm;z.jlkTYu:yJF7p_[|f?˧ NAm`4.ӯII߶{qw=~k[2M(6;SG[mNnʦz{v2hV#f`"IJ̐DSD4HeSmkwyG;GyDgַ袶uw7dl{ie{47ɾr_ig'u5\#)vVkIV/u3'*=`ռԤ'ˌ~yn>ڸ4;{ͣ6 e'~$ŜhP f`"IJ̐DSD4HeS"tm;믿^n[Om4]z?Ke\~^rkk{ʞj;vvmO+x۬vvzl)&z`ռԤٽ.4xe-BGS'kgw 6#e'מ}g'sH3$$$&<}FP}clZI;N\??ΆKwg:r']^K7A[Wn~ŵdGmԽL:G[L&tjjtc9`UP۽Kg^{6]6~YNG*SvR/ҝW[&r=KD#b.1IRb$"ĄG(o^>V{wU]]ЉT;k]g mj;1IQsuzxˌ;Gۦ UƥimwlGJME}u􂘁$)1CILIHb#gM󴘓ݻwk%;vK_En[]gɿzB\'_;%qv2 w7M>t"}2o\.dP!v~ԡVˌo.TGM6;&]{Ӷbq$ L$IHbHF>l h>v5Ԏ?9rk˸c۱8TIGS'kgwtxMZII&=V1CD!$$i$13ʦP}}}###|̫ڂUQOh j;TΏZv)h~ݙΦz P^g'T L$IHbHF>l 5j{˵ozYV7(Xclvvqd&>^+)|ى,1IRb$"ĄG(B h]z2Nm99NU VOh j;TjufgmH:_?o uv1+@D!$$i$13ʦPnppCCC\(X0oI L$IHbHF>l j;7zRۭ~x@v~Ps紳kYuiffkc9MNx3;;Qe"f`"IJ̐DSD4HeS@mP۹Qqmw7tFm|ov'?eSu1fgg;;Qe"f`"IJ̐DSD4HeS@mP۹QemIvvujׯ{WmN<&K?fmNTH3$$$&<}FPvnTS};9Bm|vξgSu1iٙ^ۺ^}[ngxI5,fo30$%fH")"IILx)6Ul j;7POv~Pu3ٴѦKbN+>QgPdTH3$$$&<}FPvnPۡ?jmw]6U?^{hǀv[waS f30$%fH")"IILx)6ܠC=QAm׽O=MՏ&o^ NV5AD!$$i$13ʦڠsKm˨v]4;{p.NMl,>ivonͶmʎY L$IHbHF>l j;7_mPAmץNjgwtxMs{w &H3$$$&<}FPvn,[ej.;M8p%n_3lJY L$IHbHF>l j;7\=|J@m]N<ݹ#m0/)5f}30$%fH")"IILx)6XXmcQ6j;?1;=ZJkm@({Hy1k$)1CILIHb#gMAmFn ''; {2QAm׍/Zd;_ZMNy1k$)1CILIHb#gMAmFn g j;?qN.T]-2im7g81뉘$)1CILIHb#gMAmjnvS'T]-2i}U:wn쌭1k$)1CILIHb#gMAmj9]5fzX[LҌ|g'㙗=1f30$%fH")"IILx)6ܠC=QAm7l4mg''dm;b1IRb$"ĄG(j j;vs{fvg_Mb::;͝GD!$$i$13ʦ;LGVAmQAm7CܯĄMb:kݘ2-7ئ=%f30$%fH")"IILx)ƎS#UmezjbvvG6oz[pҴUgz̸gxm#^b1IRb$"ĄG(zLB.&Y72?'}ޢڮW{T-8io b& I$1E$I# tQ6d755vnk~sv~P;1vyԦmI3:5wu섯5GD!$$i$13ʦ:v-$>Ι5@m]Vf\z[XҶ]M:;1f30$%fH")"IILx)cӨ$;v9ڝy̦joaI;I7wߘED!$$i$13ʦjc_[N{vӿ}-j;P ]100`96J?Dղل&2DmwivM;}-j;¬2-+v\(X5/vStȤ61CILIRb$"ĄG(IvPs {Аl*ݜdWj^ɦpeҦ#fH")"IJ̐DSD4HeSo|D[Qvc`hRme-w)d1WYjNEk;{,Sع!l#f|hal Oh+n˷?w[hvyLigrL[熬 lK?;%l goM㽱hfveN3o|7´vѠp,5v |Ovm۟㍱hv]vvzk n:FO+XysÙ.3d5v m'9vO߹BMVN;}۬lDfKFr*,[;t!ئ@謱K \ Ǔow@(^ h˖yJWLW M Ohݺ'h5#)qK gΜO퀚Xc)`;Oh9j;(5v קOEmMmQ5Gme.aS@D[v@Q@YK02>}v/eFme.aS@g}D[MXc)R?}v7Xc)4P6h|D[ 8qXc)4`__^nZ1[VSj?3oكbBme.aSh&FFFlʙwP՟dLNC̨,%l 422jlGGGeFy7Vb]¦Lzn]K׽?}@QMυNuW |Y4ҟ:N<~"V7YˣWy:ꫬ6JˤM2P6XUh[H|6T};Z\~D.mG ]%Vҏ`h!}BƼXc)4~~CXeO>}@Qͭ{q5}d&ݱB-)U/ˣ,v:~tG5[݋be1 ʪf[sLZHfʐT-W^D-m Mxl!jMIGN+?Y &TKn [^:7hAe.aSh&Ζ>ʒ/iQ%u^Gu5i=.wkPqyA(-+}YNӜ/sn ~՜ 걣&^\/Xe 0mA?"'Qlq2_{iT| 7M#+znn#9_7wRg|rj bLk6ON%Wa]¦Xe_JEm7obNlwЖѸ@N?Glo_8;e+;LNu=LrmH|f8 I҇诋Of7}{}C /^.Ҷ$c׵'嫲+K۩ ͹g uYc)4n~9jyøAX/WX=%FQ!k 5\sAIN0|fܠ״e,Z+͘dFrh +X7W/I.>#_iȅq{o>vQ+߯j7چ͐B-#P!%l P-e;r4wK9,>HCjFt" )fI7n.Mg IϴDFmKx{u4T^7GȊCK2c5xX"'~CżXc)Cm7omWtl'$_s%۸"@.=Bm3/hn|dh[L_M[Aڜc~F/}CQf2ߊӸ3%BS,D^\7o)oimg'Gk6@w&Gf89Jiֶ[֙Y=cf#W=mo&N\'˗Ir [h QW{Zo}U_wt$swP ֬$yñ~q\v_UzA?=fs8JצM7CKݡ߇ͦ<IDATz𚑹njJ.T_pVտ ϼЎ^+mv26H3tҿ"Zjuizm`få/e7G䂥*/_Uyf^F+RrBIMj;(5v ;vPk6@w,%l P@YKݡXc)Cme.aStb]¦,H__-qXc)k}Wuv M]HP]QXc)kNhs'2Q@YKе|m'ӓ=لlf+Z^}M--JftQfJGFFZa+܎޻NSHdIRL#b]¦ $l mrzV%yWW䂻mfr݂ޚpWL7v3KߎvҏS\?'MI!7;F/ Y%l!r Bme.aS@.w]WJ+vZo>N۫t󕖟OuVݍƙI_QWu8N w 23ǖy@P@YKеLq\ ~'^nT~^.ˌLەLٸv ]Tm'0FXc)kIo˖oN LەwY6ٸv #Wmw'2fSCsQ@YKе7wj?iU~>=i2.d[m\p;Uڶ{Iwd̑eL\dҥKO>m@Yc)k҅ޤ )9qG;Je9&qr'w^TۥV.oGL.nvRouH![  Bm jrl2).DFtK.Oc+9>;wLʕ+uUD]'C.{H-`]¦ɱx8DzeJ_U2mCNfN~-\Qp6z&Wt"%@'ҥKG ={Ow?{) N>-/_*vsm'I+[ғZy_w\ObF++WrDw@HKL5 v"K ҥKk=vڣ+6nk}s]z3MA*@m FO^t)^>W j;iN;8=.'auN.3-[&` ٳGd l%l Pj;1ڹsg_:}$EOiC4::,nPr&Ȍg[ ܸ܅ۑIyTVcջpdݗW{tgrmʤ^Vz ?\WnA7H? }>KR CܑEyEZAg=uzޜ-$4\<3rSJm j;<<[BtR̔t2)!.aSt@2uLӧ%'jZryҥL&F+˗/en/t{W.F2##z/1^4}5׫6$ eΤA;ǯB-ṻȐHnJ65WMOkec$kZy 6C[HN%];s(2pYܓfqJXYI,G/-Bd]¦e꘼L"N'mJu-Ll)E w}d1=KBL3g |ZvTz{tQ%kW%4~Zvg 9rG.ޑk'EiFO/Ŭmv!24^N_Q_Jm2.:r_șɐ[5v ;vbTܤa9|ۢ%-\i]ߙS7Ѝ*r!}Z .Ͻot0}H? =~t:pҥKlkٲeDL{(_%TnmlYN;y䙗,6ܔȖ 2ey;W-Ok%& $%l P@IkRi>"߶b^5>}ݔzo&M%br5S>AR2SWU[zk"4JvܩZynMi+HO[6{Oq#@nH 5v ;v"u:V=Jg388JZ|Pf\mDtgt{~Ǖqr_E;{N.h&˗/&#ww!Yq)5n)WGDRzʍܬSYk }@*fTsjOo34ގ$U(܋"2C*npqȑIu,5v p)vu:3pɟ˖-sВhiG_-tHNֳl_rfw'}*Bʑ#c OܹS _7es˼uӷ ]ak:ܝj sGB\y#;vzD^O$WQܝ̸>n{ tё- ysdLfBc]¦q(FmUbgvj>-uЙA.aS@ޢ!3+@m*Pܲ-`ݛj.aS@ntQŨ v=WA;d x%l =l9`r+rz2RVn`5j;j;\$O3%5<-K`" H%l ûk.fzYb}sū܍Bb]¦mUDHe!v$y;^k*ɅUB.bvPk6ԕ6nGvBVi閮ҺYnbvPk6Ԙ6wYۥ 8g^bvPk6ԘvNLm^1UYeWXc)Nݜ\w[^%t5n###s'\e^.Ame.aS@觻'$8e+H_QD* 7o:Xc)!.vW7n*Fme.aS@CP=Gme.aS@CP=Gme.aStb]¦Mj;(5v ;vPk6@w,%l P@YKݡXc)Cme.aStb]¦Mj;(5v ɪv)IENDB`zstd-0.5.1/images/Dspeed4.png000066400000000000000000000224331266132244200157520ustar00rootroot00000000000000PNG  IHDRҹ}&sRGBgAMA aPLTE2Rz3T}5VL^&N`'Pc(Sg*Wl,Xn-Zp._u1d{3g5@@@ACGCD@CEGGJ@BHOHDDJN@IIIJJJCKVNT@DP^RJJZONQY@T^@VVVYYYETdFWlG[sH_zXb@[g@_l@dTTlYYu^^bq@crAev@i{@```hifjjjlll~cb}iwvvv|||6X7Z:^;`Kfw0-zνf_BhxܢB}pw蔿d=zF6,Zƍ9OxaܹhWnqL;^`Jc0)q4Qw'(Fwk&7NP~lMw}ISTI=NS Qc ?u>1 3v6^=̛ic^6CQoNod^'Ɯ-SsNo9s|}1NO\;C7I'Μks \X5L!!Q߽G:(oOq~H>u~o}I;Sf3|boZ AT_3ƺ)7}o8uz:ݯ˷ MQ;14g|sHw`P[/s6ggơA47 ouzi'V:q0/n7:vF3(pv @mؿmk:k$9gH篝!_M۶Y5JF _Tg^cƓZ8$|1s5o<1Nkm|7Ә7п.Wc䞯N@.ۂs2' _]}Mj\9@&Zm/7(>ر|nBM5Qﱬ2U S'K9bO?4Qy?'Iͤ@~(-P[ ɡO RK ?)t{C~BhtKz 䧂fc ?|,4Mz 䧀vc ?ԓ!1;%151+1/11+>q71%=1 1Aq&1,121 AQ81<18 $=򛦉@~4oM#ݿ-ٛ =+3 t$%'nsKjؖwԀ ZZW4ZJJZ^ *j5WccɵtOz j^x-Wc,/R _Ki$NjVr|-rՒs=Qj հmϦ;kv9a Swӥzc ?U$=Vc ?Itn A~(O@~jh$=Bu'OO @~:%=A11>{C~&=@91IOz ǎ@~|XG߇uA~ȏoIhȏe8 XVȏIȏI~ȏȏ@IȏpIXhGBФ@~Mz @@~Oz 7NIi"10MO@~4oIWLt+ |/IL%ʝF _M[Vղv$t$p|]lI-]/Ilm^]Kһ]x|Ul_m81Ɏ'VpJKW< _WEZU _wz^K|c _]WOS5V>zn WùD_ ?iC~TNz K@~(Dј#4QY )rp{[OE@ ?14}B~R(%=SB+1˽!?}B~*h&=@71IPOz Ǐ~c ?z<$=#Kc ?n$=cWc ?b%=_c ?V|&=#kc ?J<'=cwc ?BNz GG@~lHz E@~TJz D@~^ q≼n[ W#%uxt k-%'> _햭O'Vl>1Ŷ=jy ݼ1~ C$ D-j _mw/ҭz|-v5 }MO@w[K# _;gM[&'ME@0u' ?]jd.O-&*˽!?En A~h-P{,+䧆Fc ?14Bw䧄roO@~2(&=SA31I$PNz 䧀vc ?~!19^q'15Ua ʘ7/rkkƬq뢑0]ƜX쮟3s=roϛ3[}@**IO*q'ǍZs6?c"R;TY3gqϿ$ڳgh?t3fƋnU~롕&7[[VvOS۸qޜf #8 _ 9=Yx\{fn$_穏7)d(J(|_2 ,u;7 6V ɿr}^-iwv&}s. ɧaY5НWmG_"4y^^Gw ]xaޘSYoPq+?D|lо{[=S2~iY.0{Am9ʿ=/;k#ⴙ[څfN@ȯ[6W`Yhw>R&kٌ^~MG!sA۫fIsu>](/\i3sf~=ϯW[=e<);$:^ގd-݁0uz1F?Q:#NnwA_c| tvh'zj\wW+>18 $=<֞ >?}kπxIz{KÇ?8N'U%^EGHؚ /D"Gw<+[$0縲-WMITKGc_-+#=('= %յ$qqM>!G._PWStCd#;緩w i4_|"KC&= 'n'CҝxRꓤ}M&_9@~/7mطe=uҜ+uz!3^/PON1ƼzGyn ՘iǎykDG8,_5#<)>;(6o A(=窩ɷx1B|֣ay{BCP:Z5vR4g_E4ޛFwowGnl<0_8}20 q^3 sy?j{Ǫ|D2 9"EC/T޾z^$QNUvQXs9 W{a_@=ܽ|/Ʌ}ܽ/֦bsɗRqvX_ݖ()|] <_ܶ5E}ӳG6Y'SRƝF _mw8Oc~_9@/WjQWg _zrox |0kR0|~-\0|~,?G L71/`J|! #n A)?r5 H_@c _@Gv{$."  _@ CK-Ad I˽!_@'.|Iʟ0[ _@%E5!_@zݞ|ɟI|iɗ !_@Bݞ|&=$#_RC!Dc _@ Kw{$ \c _@K&=.ʐo|/ݞ|1˯jI|ʯ1[ _@+'=)f' _@$=(Vc _@|I| KBc _@T5"6[ _@<Oԅ=^Ej'"|`|Ť@?[VVLIRKW{ȷ/wxg_TKW{'þ-'iþ'SOz= _7;Iߡtg+%tWwo_l=@wۛ0|I kRr|^o[+AjK-A?=N繾Kz 7f`L[C/`:C?& I|}k$/"  _@GO@Lz HX _@_ R?i' HT@$|ro|AOJz HMĤ@ /Iz HI(1/ ¤@dK/Oz HC~@$Iz H@~@Lz ]~@Oz [~@WJz X~@hWMz U~@HWOz R~@Jz OB' _@t&=&vc _@\u| JFc _@D=⑯|D"5ZC=_@o. "mk&em:@~Il9%Iu-Y_+r]=Cݻ%H'0߿C|vqԘe@4܆y\ȥQ@~pIO(1.?aLfKG u}c!]C#,`rg\[6ʟy'wG];br Ĝ^Q}1KV,7gyvq{'h 0ֽ}€mRjN[ _i'.?f;34O܁/OPC:>ܜ^&ނyC޷:-o#29:-tr;k3G`w@+t'3G_=;sܥ˗~ĥ//({6u|1]u|;lЍkwoݮe+j&5GK<.=۩>fۑ`n_@\+ݽ Jb%Io^Gͬ=K¥S%t5?|&}7 /nt^B7o ~oxWDKk)$?TJ85g%t'?ek:׺בUq,bEMν0Z?Woi_H %i&QO~"Ͽ[o &-|`@~u W@~Z@~u W'u{?T8GE"iv5@HY]3??o_h'Ҵd=r4}6+?!ߒ|_"QI ,tnc :>ȯNb򫓖IIRK_|ȯN2=򫓊 IDDŽ, #TR?:1?3OxXW8?qz^?eC%vH?o[aI # =CIcM˟Ow?+Rc :ʟȯNI)_ȯNeID(_ȯN|I&81_Hz{TRI"GySNL+Z!yN<+Zҗ]O=/uXOzHzL$=FW$=&VA?MflJ3ھzt $W[)+6@դjH~VQofjH V#ڄl/!AI?$#No BwuqƏ`A|@ 3 0?@ 3 0?@ 3C7).BM؛M03%Z!+V;Xw|R/{ 8ґ݊] {.ئWm.^-ҲH_}o^:x`}5勺m}e״v$_}%!VNJlҒ}{}C/V~K1Lj.td@G ξ+}t}toy~U{w;{pk0{%԰,}}ܡ~2CE)Gam:/-}3nw~2C}.{Y {|vw}ыdKwߵ| >du?ݦ>ɝO>mgA}[O{Ⱦ6|O.|~Wumo ˶L~wW%}|==0oY;W@oO)}@~r@~5B>0?@ 3 0?@ 3 0?@ 3K{ i|IENDB`zstd-0.5.1/lib/000077500000000000000000000000001266132244200132515ustar00rootroot00000000000000zstd-0.5.1/lib/LICENSE000066400000000000000000000024551266132244200142640ustar00rootroot00000000000000ZSTD Library Copyright (c) 2014-2015, Yann Collet All rights reserved. BSD License Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. zstd-0.5.1/lib/Makefile000066400000000000000000000133051266132244200147130ustar00rootroot00000000000000# ################################################################ # ZSTD library - Makefile # Copyright (C) Yann Collet 2015-2016 # All rights reserved. # # BSD license # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright notice, this # list of conditions and the following disclaimer in the documentation and/or # other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # You can contact the author at : # - ZSTD homepage : http://www.zstd.net # ################################################################ # Version numbers LIBVER_MAJOR_SCRIPT:=`sed -n '/define ZSTD_VERSION_MAJOR/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < zstd.h` LIBVER_MINOR_SCRIPT:=`sed -n '/define ZSTD_VERSION_MINOR/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < zstd.h` LIBVER_PATCH_SCRIPT:=`sed -n '/define ZSTD_VERSION_RELEASE/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < zstd.h` 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)) VERSION?= $(LIBVER) DESTDIR?= PREFIX ?= /usr/local CPPFLAGS= -I. CFLAGS ?= -O3 CFLAGS += -std=c99 -Wall -Wextra -Wundef -Wshadow -Wcast-qual -Wcast-align -Wstrict-prototypes -Wstrict-aliasing=1 FLAGS = $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $(MOREFLAGS) LIBDIR ?= $(PREFIX)/lib INCLUDEDIR=$(PREFIX)/include ZSTD_FILES := zstd_compress.c zstd_decompress.c fse.c huff0.c zdict.c divsufsort.c ZSTD_LEGACY:= legacy/zstd_v01.c legacy/zstd_v02.c legacy/zstd_v03.c legacy/zstd_v04.c ifeq ($(ZSTD_LEGACY_SUPPORT), 0) CPPFLAGS += -DZSTD_LEGACY_SUPPORT=0 else ZSTD_FILES+= $(ZSTD_LEGACY) CPPFLAGS += -I./legacy -DZSTD_LEGACY_SUPPORT=1 endif # OS X linker doesn't support -soname, and use different extension # see : https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/DynamicLibraries/100-Articles/DynamicLibraryDesignGuidelines.html ifeq ($(shell uname), Darwin) SHARED_EXT = dylib SHARED_EXT_MAJOR = $(LIBVER_MAJOR).$(SHARED_EXT) SHARED_EXT_VER = $(LIBVER).$(SHARED_EXT) SONAME_FLAGS = -install_name $(PREFIX)/lib/$@.$(SHARED_EXT_MAJOR) -compatibility_version $(LIBVER_MAJOR) -current_version $(LIBVER) else SONAME_FLAGS = -Wl,-soname=$@.$(SHARED_EXT).$(LIBVER_MAJOR) SHARED_EXT = so SHARED_EXT_MAJOR = $(SHARED_EXT).$(LIBVER_MAJOR) SHARED_EXT_VER = $(SHARED_EXT).$(LIBVER) endif .PHONY: default all clean install uninstall default: clean libzstd all: clean libzstd libzstd: $(ZSTD_FILES) @echo compiling static library @$(CC) $(FLAGS) -c $^ @$(AR) rcs $@.a *.o @echo compiling dynamic library $(LIBVER) @$(CC) $(FLAGS) -shared $^ -fPIC $(SONAME_FLAGS) -o $@.$(SHARED_EXT_VER) @echo creating versioned links @ln -sf $@.$(SHARED_EXT_VER) $@.$(SHARED_EXT_MAJOR) @ln -sf $@.$(SHARED_EXT_VER) $@.$(SHARED_EXT) clean: @rm -f core *.o *.a *.gcda *.$(SHARED_EXT) *.$(SHARED_EXT).* libzstd.pc @echo Cleaning library completed #------------------------------------------------------------------------ #make install is validated only for Linux, OSX, kFreeBSD and Hurd targets ifneq (,$(filter $(shell uname),Linux Darwin GNU/kFreeBSD GNU)) libzstd.pc: libzstd.pc: libzstd.pc.in @echo creating pkgconfig @sed -e 's|@PREFIX@|$(PREFIX)|' \ -e 's|@LIBDIR@|$(LIBDIR)|' \ -e 's|@INCLUDEDIR@|$(INCLUDEDIR)|' \ -e 's|@VERSION@|$(VERSION)|' \ $< >$@ install: libzstd libzstd.pc @install -d -m 755 $(DESTDIR)$(LIBDIR)/pkgconfig/ $(DESTDIR)$(INCLUDEDIR)/ @install -m 755 libzstd.$(SHARED_EXT_VER) $(DESTDIR)$(LIBDIR)/libzstd.$(SHARED_EXT_VER) @cp -a libzstd.$(SHARED_EXT_MAJOR) $(DESTDIR)$(LIBDIR) @cp -a libzstd.$(SHARED_EXT) $(DESTDIR)$(LIBDIR) @cp -a libzstd.pc $(DESTDIR)$(LIBDIR)/pkgconfig/ @install -m 644 libzstd.a $(DESTDIR)$(LIBDIR)/libzstd.a @install -m 644 zstd.h $(DESTDIR)$(INCLUDEDIR)/zstd.h @install -m 644 zstd.h $(DESTDIR)$(INCLUDEDIR)/zbuff.h @install -m 644 zstd.h $(DESTDIR)$(INCLUDEDIR)/zdict.h @echo zstd static and shared library installed uninstall: @rm -f $(DESTDIR)$(LIBDIR)/libzstd.$(SHARED_EXT) @rm -f $(DESTDIR)$(LIBDIR)/libzstd.$(SHARED_EXT_MAJOR) @rm -f $(DESTDIR)$(LIBDIR)/pkgconfig/libzstd.pc @[ -x $(DESTDIR)$(LIBDIR)/libzstd.$(SHARED_EXT_VER) ] && rm -f $(DESTDIR)$(LIBDIR)/libzstd.$(SHARED_EXT_VER) @[ -f $(DESTDIR)$(LIBDIR)/libzstd.a ] && rm -f $(DESTDIR)$(LIBDIR)/libzstd.a @[ -f $(DESTDIR)$(INCLUDEDIR)/zstd.h ] && rm -f $(DESTDIR)$(INCLUDEDIR)/zstd.h @[ -f $(DESTDIR)$(INCLUDEDIR)/zstd.h ] && rm -f $(DESTDIR)$(INCLUDEDIR)/zbuff.h @[ -f $(DESTDIR)$(INCLUDEDIR)/zstd.h ] && rm -f $(DESTDIR)$(INCLUDEDIR)/zdict.h @echo zstd libraries successfully uninstalled endif zstd-0.5.1/lib/README.md000066400000000000000000000020671266132244200145350ustar00rootroot00000000000000zstd - library files ================================ The __lib__ directory contains several files, but depending on target use case, some of them may not be necessary. #### Minimal library files ##### Shared ressources - [mem.h](mem.h) - [error_private.h](error_private.h) - [error_public.h](error_public.h) ##### zstd core compression - [bitstream.h](bitstream.h) - fse.c - fse.h - fse_static.h - huff0.c - huff0.h - huff0_static.h - zstd_compress.c - zstd_decompress.c - zstd_internal.h - zstd_opt.h - zstd.h - zstd_static.h #### Buffered streaming This complementary API makes streaming integration easier. It is used by `zstd` command line utility : - zbuff.c - zbuff.h - zbuff_static.h #### Dictionary builder To create dictionaries from training sets : - divsufsort.c - divsufsort.h - zdict.c - zdict.h - zdict_static.h #### Miscellaneous The other files are not source code. There are : - LICENSE : contains the BSD license text - Makefile : script to compile or install zstd library (static or dynamic) - libzstd.pc.in : for pkg-config (make install) zstd-0.5.1/lib/bitstream.h000066400000000000000000000341551266132244200154240ustar00rootroot00000000000000/* ****************************************************************** bitstream Part of FSE library header file (to include) Copyright (C) 2013-2016, Yann Collet. BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. You can contact the author at : - Source repository : https://github.com/Cyan4973/FiniteStateEntropy ****************************************************************** */ #ifndef BITSTREAM_H_MODULE #define BITSTREAM_H_MODULE #if defined (__cplusplus) extern "C" { #endif /* * This API consists of small unitary functions, which highly benefit from being inlined. * Since link-time-optimization is not available for all compilers, * these functions are defined into a .h to be included. */ /*-**************************************** * Dependencies ******************************************/ #include "mem.h" /* unaligned access routines */ #include "error_private.h" /* error codes and messages */ /*-****************************************** * bitStream encoding API (write forward) ********************************************/ /*! * bitStream can mix input from multiple sources. * A critical property of these streams is that they encode and decode in **reverse** direction. * So the first bit sequence you add will be the last to be read, like a LIFO stack. */ typedef struct { size_t bitContainer; int bitPos; char* startPtr; char* ptr; char* endPtr; } BIT_CStream_t; MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC, void* dstBuffer, size_t dstCapacity); MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC, size_t value, unsigned nbBits); MEM_STATIC void BIT_flushBits(BIT_CStream_t* bitC); MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC); /*! * Start by initCStream, providing the size of buffer to write into. * bitStream will never write outside of this buffer. * @dstCapacity must be >= sizeof(size_t), otherwise @return will be an error code. * * bits are first added to a local register. * Local register is size_t, hence 64-bits on 64-bits systems, or 32-bits on 32-bits systems. * Writing data into memory is an explicit operation, performed by the flushBits function. * Hence keep track how many bits are potentially stored into local register to avoid register overflow. * After a flushBits, a maximum of 7 bits might still be stored into local register. * * Avoid storing elements of more than 24 bits if you want compatibility with 32-bits bitstream readers. * * Last operation is to close the bitStream. * The function returns the final size of CStream in bytes. * If data couldn't fit into @dstBuffer, it will return a 0 ( == not storable) */ /*-******************************************** * bitStream decoding API (read backward) **********************************************/ typedef struct { size_t bitContainer; unsigned bitsConsumed; const char* ptr; const char* start; } BIT_DStream_t; typedef enum { BIT_DStream_unfinished = 0, BIT_DStream_endOfBuffer = 1, BIT_DStream_completed = 2, BIT_DStream_overflow = 3 } BIT_DStream_status; /* result of BIT_reloadDStream() */ /* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */ MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize); MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits); MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD); MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* bitD); /*! * Start by invoking BIT_initDStream(). * A chunk of the bitStream is then stored into a local register. * Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (size_t). * You can then retrieve bitFields stored into the local register, **in reverse order**. * Local register is explicitly reloaded from memory by the BIT_reloadDStream() method. * A reload guarantee a minimum of ((8*sizeof(size_t))-7) bits when its result is BIT_DStream_unfinished. * Otherwise, it can be less than that, so proceed accordingly. * Checking if DStream has reached its end can be performed with BIT_endOfDStream() */ /*-**************************************** * unsafe API ******************************************/ MEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC, size_t value, unsigned nbBits); /* faster, but works only if value is "clean", meaning all high bits above nbBits are 0 */ MEM_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC); /* unsafe version; does not check buffer overflow */ MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits); /* faster, but works only if nbBits >= 1 */ /*-************************************************************** * Helper functions ****************************************************************/ MEM_STATIC unsigned BIT_highbit32 (register U32 val) { # if defined(_MSC_VER) /* Visual */ unsigned long r=0; _BitScanReverse ( &r, val ); return (unsigned) r; # elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */ return 31 - __builtin_clz (val); # else /* Software version */ static const unsigned DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 }; U32 v = val; unsigned r; v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16; r = DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27]; return r; # endif } /*-************************************************************** * bitStream encoding ****************************************************************/ MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC, void* startPtr, size_t maxSize) { bitC->bitContainer = 0; bitC->bitPos = 0; bitC->startPtr = (char*)startPtr; bitC->ptr = bitC->startPtr; bitC->endPtr = bitC->startPtr + maxSize - sizeof(bitC->ptr); if (maxSize < sizeof(bitC->ptr)) return ERROR(dstSize_tooSmall); return 0; } MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC, size_t value, unsigned nbBits) { static const unsigned mask[] = { 0, 1, 3, 7, 0xF, 0x1F, 0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF, 0x1FFFF, 0x3FFFF, 0x7FFFF, 0xFFFFF, 0x1FFFFF, 0x3FFFFF, 0x7FFFFF, 0xFFFFFF, 0x1FFFFFF }; /* up to 25 bits */ bitC->bitContainer |= (value & mask[nbBits]) << bitC->bitPos; bitC->bitPos += nbBits; } /*! BIT_addBitsFast * works only if `value` is _clean_, meaning all high bits above nbBits are 0 */ MEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC, size_t value, unsigned nbBits) { bitC->bitContainer |= value << bitC->bitPos; bitC->bitPos += nbBits; } /*! BIT_flushBitsFast * unsafe version; does not check buffer overflow */ MEM_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC) { size_t nbBytes = bitC->bitPos >> 3; MEM_writeLEST(bitC->ptr, bitC->bitContainer); bitC->ptr += nbBytes; bitC->bitPos &= 7; bitC->bitContainer >>= nbBytes*8; /* if bitPos >= sizeof(bitContainer)*8 --> undefined behavior */ } MEM_STATIC void BIT_flushBits(BIT_CStream_t* bitC) { size_t nbBytes = bitC->bitPos >> 3; MEM_writeLEST(bitC->ptr, bitC->bitContainer); bitC->ptr += nbBytes; if (bitC->ptr > bitC->endPtr) bitC->ptr = bitC->endPtr; bitC->bitPos &= 7; bitC->bitContainer >>= nbBytes*8; /* if bitPos >= sizeof(bitContainer)*8 --> undefined behavior */ } /*! BIT_closeCStream * @result : size of CStream, in bytes, or 0 if it cannot fit into dstBuffer */ MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC) { char* endPtr; BIT_addBitsFast(bitC, 1, 1); /* endMark */ BIT_flushBits(bitC); if (bitC->ptr >= bitC->endPtr) /* too close to buffer's end */ return 0; /* not storable */ endPtr = bitC->ptr; endPtr += bitC->bitPos > 0; /* remaining bits (incomplete byte) */ return (endPtr - bitC->startPtr); } /*-******************************************************** * bitStream decoding **********************************************************/ /*!BIT_initDStream * Initialize a BIT_DStream_t. * @bitD : a pointer to an already allocated BIT_DStream_t structure * @srcBuffer must point at the beginning of a bitStream * @srcSize must be the exact size of the bitStream * @result : size of stream (== srcSize) or an errorCode if a problem is detected */ MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize) { if (srcSize < 1) { memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); } if (srcSize >= sizeof(size_t)) { /* normal case */ U32 contain32; bitD->start = (const char*)srcBuffer; bitD->ptr = (const char*)srcBuffer + srcSize - sizeof(size_t); bitD->bitContainer = MEM_readLEST(bitD->ptr); contain32 = ((const BYTE*)srcBuffer)[srcSize-1]; if (contain32 == 0) return ERROR(GENERIC); /* endMark not present */ bitD->bitsConsumed = 8 - BIT_highbit32(contain32); } else { U32 contain32; bitD->start = (const char*)srcBuffer; bitD->ptr = bitD->start; bitD->bitContainer = *(const BYTE*)(bitD->start); switch(srcSize) { case 7: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[6]) << (sizeof(size_t)*8 - 16); case 6: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[5]) << (sizeof(size_t)*8 - 24); case 5: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[4]) << (sizeof(size_t)*8 - 32); case 4: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[3]) << 24; case 3: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[2]) << 16; case 2: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[1]) << 8; default:; } contain32 = ((const BYTE*)srcBuffer)[srcSize-1]; if (contain32 == 0) return ERROR(GENERIC); /* endMark not present */ bitD->bitsConsumed = 8 - BIT_highbit32(contain32); bitD->bitsConsumed += (U32)(sizeof(size_t) - srcSize)*8; } return srcSize; } /*!BIT_lookBits * Provides next n bits from local register * local register is not modified (bits are still present for next read/look) * On 32-bits, maxNbBits==25 * On 64-bits, maxNbBits==57 * @return : value extracted */ MEM_STATIC size_t BIT_lookBits(BIT_DStream_t* bitD, U32 nbBits) { const U32 bitMask = sizeof(bitD->bitContainer)*8 - 1; return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask-nbBits) & bitMask); } /*! BIT_lookBitsFast : * unsafe version; only works only if nbBits >= 1 */ MEM_STATIC size_t BIT_lookBitsFast(BIT_DStream_t* bitD, U32 nbBits) { const U32 bitMask = sizeof(bitD->bitContainer)*8 - 1; return (bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> (((bitMask+1)-nbBits) & bitMask); } MEM_STATIC void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits) { bitD->bitsConsumed += nbBits; } /*!BIT_readBits * Read next n bits from local register. * pay attention to not read more than nbBits contained into local register. * @return : extracted value. */ MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, U32 nbBits) { size_t value = BIT_lookBits(bitD, nbBits); BIT_skipBits(bitD, nbBits); return value; } /*!BIT_readBitsFast : * unsafe version; only works only if nbBits >= 1 */ MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, U32 nbBits) { size_t value = BIT_lookBitsFast(bitD, nbBits); BIT_skipBits(bitD, nbBits); return value; } MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD) { if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8)) /* should never happen */ return BIT_DStream_overflow; if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer)) { bitD->ptr -= bitD->bitsConsumed >> 3; bitD->bitsConsumed &= 7; bitD->bitContainer = MEM_readLEST(bitD->ptr); return BIT_DStream_unfinished; } if (bitD->ptr == bitD->start) { if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BIT_DStream_endOfBuffer; return BIT_DStream_completed; } { U32 nbBytes = bitD->bitsConsumed >> 3; BIT_DStream_status result = BIT_DStream_unfinished; if (bitD->ptr - nbBytes < bitD->start) { nbBytes = (U32)(bitD->ptr - bitD->start); /* ptr > start */ result = BIT_DStream_endOfBuffer; } bitD->ptr -= nbBytes; bitD->bitsConsumed -= nbBytes*8; bitD->bitContainer = MEM_readLEST(bitD->ptr); /* reminder : srcSize > sizeof(bitD) */ return result; } } /*! BIT_endOfDStream * @return Tells if DStream has reached its exact end */ MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* DStream) { return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer)*8)); } #if defined (__cplusplus) } #endif #endif /* BITSTREAM_H_MODULE */ zstd-0.5.1/lib/divsufsort.c000066400000000000000000001525001266132244200156300ustar00rootroot00000000000000/* * divsufsort.c for libdivsufsort-lite * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ /*- Compiler specifics -*/ #ifdef __clang__ #pragma clang diagnostic ignored "-Wshorten-64-to-32" #endif #if defined(_MSC_VER) # pragma warning(disable : 4244) # pragma warning(disable : 4127) /* C4127 : Condition expression is constant */ #endif /*- Dependencies -*/ #include #include #include #include "divsufsort.h" /*- Constants -*/ #if defined(INLINE) # undef INLINE #endif #if !defined(INLINE) # define INLINE __inline #endif #if defined(ALPHABET_SIZE) && (ALPHABET_SIZE < 1) # undef ALPHABET_SIZE #endif #if !defined(ALPHABET_SIZE) # define ALPHABET_SIZE (256) #endif #define BUCKET_A_SIZE (ALPHABET_SIZE) #define BUCKET_B_SIZE (ALPHABET_SIZE * ALPHABET_SIZE) #if defined(SS_INSERTIONSORT_THRESHOLD) # if SS_INSERTIONSORT_THRESHOLD < 1 # undef SS_INSERTIONSORT_THRESHOLD # define SS_INSERTIONSORT_THRESHOLD (1) # endif #else # define SS_INSERTIONSORT_THRESHOLD (8) #endif #if defined(SS_BLOCKSIZE) # if SS_BLOCKSIZE < 0 # undef SS_BLOCKSIZE # define SS_BLOCKSIZE (0) # elif 32768 <= SS_BLOCKSIZE # undef SS_BLOCKSIZE # define SS_BLOCKSIZE (32767) # endif #else # define SS_BLOCKSIZE (1024) #endif /* minstacksize = log(SS_BLOCKSIZE) / log(3) * 2 */ #if SS_BLOCKSIZE == 0 # define SS_MISORT_STACKSIZE (96) #elif SS_BLOCKSIZE <= 4096 # define SS_MISORT_STACKSIZE (16) #else # define SS_MISORT_STACKSIZE (24) #endif #define SS_SMERGE_STACKSIZE (32) #define TR_INSERTIONSORT_THRESHOLD (8) #define TR_STACKSIZE (64) /*- Macros -*/ #ifndef SWAP # define SWAP(_a, _b) do { t = (_a); (_a) = (_b); (_b) = t; } while(0) #endif /* SWAP */ #ifndef MIN # define MIN(_a, _b) (((_a) < (_b)) ? (_a) : (_b)) #endif /* MIN */ #ifndef MAX # define MAX(_a, _b) (((_a) > (_b)) ? (_a) : (_b)) #endif /* MAX */ #define STACK_PUSH(_a, _b, _c, _d)\ do {\ assert(ssize < STACK_SIZE);\ stack[ssize].a = (_a), stack[ssize].b = (_b),\ stack[ssize].c = (_c), stack[ssize++].d = (_d);\ } while(0) #define STACK_PUSH5(_a, _b, _c, _d, _e)\ do {\ assert(ssize < STACK_SIZE);\ stack[ssize].a = (_a), stack[ssize].b = (_b),\ stack[ssize].c = (_c), stack[ssize].d = (_d), stack[ssize++].e = (_e);\ } while(0) #define STACK_POP(_a, _b, _c, _d)\ do {\ assert(0 <= ssize);\ if(ssize == 0) { return; }\ (_a) = stack[--ssize].a, (_b) = stack[ssize].b,\ (_c) = stack[ssize].c, (_d) = stack[ssize].d;\ } while(0) #define STACK_POP5(_a, _b, _c, _d, _e)\ do {\ assert(0 <= ssize);\ if(ssize == 0) { return; }\ (_a) = stack[--ssize].a, (_b) = stack[ssize].b,\ (_c) = stack[ssize].c, (_d) = stack[ssize].d, (_e) = stack[ssize].e;\ } while(0) #define BUCKET_A(_c0) bucket_A[(_c0)] #if ALPHABET_SIZE == 256 #define BUCKET_B(_c0, _c1) (bucket_B[((_c1) << 8) | (_c0)]) #define BUCKET_BSTAR(_c0, _c1) (bucket_B[((_c0) << 8) | (_c1)]) #else #define BUCKET_B(_c0, _c1) (bucket_B[(_c1) * ALPHABET_SIZE + (_c0)]) #define BUCKET_BSTAR(_c0, _c1) (bucket_B[(_c0) * ALPHABET_SIZE + (_c1)]) #endif /*- Private Functions -*/ static const int lg_table[256]= { -1,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 }; #if (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE) static INLINE int ss_ilg(int n) { #if SS_BLOCKSIZE == 0 return (n & 0xffff0000) ? ((n & 0xff000000) ? 24 + lg_table[(n >> 24) & 0xff] : 16 + lg_table[(n >> 16) & 0xff]) : ((n & 0x0000ff00) ? 8 + lg_table[(n >> 8) & 0xff] : 0 + lg_table[(n >> 0) & 0xff]); #elif SS_BLOCKSIZE < 256 return lg_table[n]; #else return (n & 0xff00) ? 8 + lg_table[(n >> 8) & 0xff] : 0 + lg_table[(n >> 0) & 0xff]; #endif } #endif /* (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE) */ #if SS_BLOCKSIZE != 0 static const int sqq_table[256] = { 0, 16, 22, 27, 32, 35, 39, 42, 45, 48, 50, 53, 55, 57, 59, 61, 64, 65, 67, 69, 71, 73, 75, 76, 78, 80, 81, 83, 84, 86, 87, 89, 90, 91, 93, 94, 96, 97, 98, 99, 101, 102, 103, 104, 106, 107, 108, 109, 110, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 128, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 144, 145, 146, 147, 148, 149, 150, 150, 151, 152, 153, 154, 155, 155, 156, 157, 158, 159, 160, 160, 161, 162, 163, 163, 164, 165, 166, 167, 167, 168, 169, 170, 170, 171, 172, 173, 173, 174, 175, 176, 176, 177, 178, 178, 179, 180, 181, 181, 182, 183, 183, 184, 185, 185, 186, 187, 187, 188, 189, 189, 190, 191, 192, 192, 193, 193, 194, 195, 195, 196, 197, 197, 198, 199, 199, 200, 201, 201, 202, 203, 203, 204, 204, 205, 206, 206, 207, 208, 208, 209, 209, 210, 211, 211, 212, 212, 213, 214, 214, 215, 215, 216, 217, 217, 218, 218, 219, 219, 220, 221, 221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227, 227, 228, 229, 229, 230, 230, 231, 231, 232, 232, 233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238, 239, 240, 240, 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 246, 246, 247, 247, 248, 248, 249, 249, 250, 250, 251, 251, 252, 252, 253, 253, 254, 254, 255 }; static INLINE int ss_isqrt(int x) { int y, e; if(x >= (SS_BLOCKSIZE * SS_BLOCKSIZE)) { return SS_BLOCKSIZE; } e = (x & 0xffff0000) ? ((x & 0xff000000) ? 24 + lg_table[(x >> 24) & 0xff] : 16 + lg_table[(x >> 16) & 0xff]) : ((x & 0x0000ff00) ? 8 + lg_table[(x >> 8) & 0xff] : 0 + lg_table[(x >> 0) & 0xff]); if(e >= 16) { y = sqq_table[x >> ((e - 6) - (e & 1))] << ((e >> 1) - 7); if(e >= 24) { y = (y + 1 + x / y) >> 1; } y = (y + 1 + x / y) >> 1; } else if(e >= 8) { y = (sqq_table[x >> ((e - 6) - (e & 1))] >> (7 - (e >> 1))) + 1; } else { return sqq_table[x] >> 4; } return (x < (y * y)) ? y - 1 : y; } #endif /* SS_BLOCKSIZE != 0 */ /*---------------------------------------------------------------------------*/ /* Compares two suffixes. */ static INLINE int ss_compare(const unsigned char *T, const int *p1, const int *p2, int depth) { const unsigned char *U1, *U2, *U1n, *U2n; for(U1 = T + depth + *p1, U2 = T + depth + *p2, U1n = T + *(p1 + 1) + 2, U2n = T + *(p2 + 1) + 2; (U1 < U1n) && (U2 < U2n) && (*U1 == *U2); ++U1, ++U2) { } return U1 < U1n ? (U2 < U2n ? *U1 - *U2 : 1) : (U2 < U2n ? -1 : 0); } /*---------------------------------------------------------------------------*/ #if (SS_BLOCKSIZE != 1) && (SS_INSERTIONSORT_THRESHOLD != 1) /* Insertionsort for small size groups */ static void ss_insertionsort(const unsigned char *T, const int *PA, int *first, int *last, int depth) { int *i, *j; int t; int r; for(i = last - 2; first <= i; --i) { for(t = *i, j = i + 1; 0 < (r = ss_compare(T, PA + t, PA + *j, depth));) { do { *(j - 1) = *j; } while((++j < last) && (*j < 0)); if(last <= j) { break; } } if(r == 0) { *j = ~*j; } *(j - 1) = t; } } #endif /* (SS_BLOCKSIZE != 1) && (SS_INSERTIONSORT_THRESHOLD != 1) */ /*---------------------------------------------------------------------------*/ #if (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE) static INLINE void ss_fixdown(const unsigned char *Td, const int *PA, int *SA, int i, int size) { int j, k; int v; int c, d, e; for(v = SA[i], c = Td[PA[v]]; (j = 2 * i + 1) < size; SA[i] = SA[k], i = k) { d = Td[PA[SA[k = j++]]]; if(d < (e = Td[PA[SA[j]]])) { k = j; d = e; } if(d <= c) { break; } } SA[i] = v; } /* Simple top-down heapsort. */ static void ss_heapsort(const unsigned char *Td, const int *PA, int *SA, int size) { int i, m; int t; m = size; if((size % 2) == 0) { m--; if(Td[PA[SA[m / 2]]] < Td[PA[SA[m]]]) { SWAP(SA[m], SA[m / 2]); } } for(i = m / 2 - 1; 0 <= i; --i) { ss_fixdown(Td, PA, SA, i, m); } if((size % 2) == 0) { SWAP(SA[0], SA[m]); ss_fixdown(Td, PA, SA, 0, m); } for(i = m - 1; 0 < i; --i) { t = SA[0], SA[0] = SA[i]; ss_fixdown(Td, PA, SA, 0, i); SA[i] = t; } } /*---------------------------------------------------------------------------*/ /* Returns the median of three elements. */ static INLINE int * ss_median3(const unsigned char *Td, const int *PA, int *v1, int *v2, int *v3) { int *t; if(Td[PA[*v1]] > Td[PA[*v2]]) { SWAP(v1, v2); } if(Td[PA[*v2]] > Td[PA[*v3]]) { if(Td[PA[*v1]] > Td[PA[*v3]]) { return v1; } else { return v3; } } return v2; } /* Returns the median of five elements. */ static INLINE int * ss_median5(const unsigned char *Td, const int *PA, int *v1, int *v2, int *v3, int *v4, int *v5) { int *t; if(Td[PA[*v2]] > Td[PA[*v3]]) { SWAP(v2, v3); } if(Td[PA[*v4]] > Td[PA[*v5]]) { SWAP(v4, v5); } if(Td[PA[*v2]] > Td[PA[*v4]]) { SWAP(v2, v4); SWAP(v3, v5); } if(Td[PA[*v1]] > Td[PA[*v3]]) { SWAP(v1, v3); } if(Td[PA[*v1]] > Td[PA[*v4]]) { SWAP(v1, v4); SWAP(v3, v5); } if(Td[PA[*v3]] > Td[PA[*v4]]) { return v4; } return v3; } /* Returns the pivot element. */ static INLINE int * ss_pivot(const unsigned char *Td, const int *PA, int *first, int *last) { int *middle; int t; t = last - first; middle = first + t / 2; if(t <= 512) { if(t <= 32) { return ss_median3(Td, PA, first, middle, last - 1); } else { t >>= 2; return ss_median5(Td, PA, first, first + t, middle, last - 1 - t, last - 1); } } t >>= 3; first = ss_median3(Td, PA, first, first + t, first + (t << 1)); middle = ss_median3(Td, PA, middle - t, middle, middle + t); last = ss_median3(Td, PA, last - 1 - (t << 1), last - 1 - t, last - 1); return ss_median3(Td, PA, first, middle, last); } /*---------------------------------------------------------------------------*/ /* Binary partition for substrings. */ static INLINE int * ss_partition(const int *PA, int *first, int *last, int depth) { int *a, *b; int t; for(a = first - 1, b = last;;) { for(; (++a < b) && ((PA[*a] + depth) >= (PA[*a + 1] + 1));) { *a = ~*a; } for(; (a < --b) && ((PA[*b] + depth) < (PA[*b + 1] + 1));) { } if(b <= a) { break; } t = ~*b; *b = *a; *a = t; } if(first < a) { *first = ~*first; } return a; } /* Multikey introsort for medium size groups. */ static void ss_mintrosort(const unsigned char *T, const int *PA, int *first, int *last, int depth) { #define STACK_SIZE SS_MISORT_STACKSIZE struct { int *a, *b, c; int d; } stack[STACK_SIZE]; const unsigned char *Td; int *a, *b, *c, *d, *e, *f; int s, t; int ssize; int limit; int v, x = 0; for(ssize = 0, limit = ss_ilg(last - first);;) { if((last - first) <= SS_INSERTIONSORT_THRESHOLD) { #if 1 < SS_INSERTIONSORT_THRESHOLD if(1 < (last - first)) { ss_insertionsort(T, PA, first, last, depth); } #endif STACK_POP(first, last, depth, limit); continue; } Td = T + depth; if(limit-- == 0) { ss_heapsort(Td, PA, first, last - first); } if(limit < 0) { for(a = first + 1, v = Td[PA[*first]]; a < last; ++a) { if((x = Td[PA[*a]]) != v) { if(1 < (a - first)) { break; } v = x; first = a; } } if(Td[PA[*first] - 1] < v) { first = ss_partition(PA, first, a, depth); } if((a - first) <= (last - a)) { if(1 < (a - first)) { STACK_PUSH(a, last, depth, -1); last = a, depth += 1, limit = ss_ilg(a - first); } else { first = a, limit = -1; } } else { if(1 < (last - a)) { STACK_PUSH(first, a, depth + 1, ss_ilg(a - first)); first = a, limit = -1; } else { last = a, depth += 1, limit = ss_ilg(a - first); } } continue; } /* choose pivot */ a = ss_pivot(Td, PA, first, last); v = Td[PA[*a]]; SWAP(*first, *a); /* partition */ for(b = first; (++b < last) && ((x = Td[PA[*b]]) == v);) { } if(((a = b) < last) && (x < v)) { for(; (++b < last) && ((x = Td[PA[*b]]) <= v);) { if(x == v) { SWAP(*b, *a); ++a; } } } for(c = last; (b < --c) && ((x = Td[PA[*c]]) == v);) { } if((b < (d = c)) && (x > v)) { for(; (b < --c) && ((x = Td[PA[*c]]) >= v);) { if(x == v) { SWAP(*c, *d); --d; } } } for(; b < c;) { SWAP(*b, *c); for(; (++b < c) && ((x = Td[PA[*b]]) <= v);) { if(x == v) { SWAP(*b, *a); ++a; } } for(; (b < --c) && ((x = Td[PA[*c]]) >= v);) { if(x == v) { SWAP(*c, *d); --d; } } } if(a <= d) { c = b - 1; if((s = a - first) > (t = b - a)) { s = t; } for(e = first, f = b - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); } if((s = d - c) > (t = last - d - 1)) { s = t; } for(e = b, f = last - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); } a = first + (b - a), c = last - (d - c); b = (v <= Td[PA[*a] - 1]) ? a : ss_partition(PA, a, c, depth); if((a - first) <= (last - c)) { if((last - c) <= (c - b)) { STACK_PUSH(b, c, depth + 1, ss_ilg(c - b)); STACK_PUSH(c, last, depth, limit); last = a; } else if((a - first) <= (c - b)) { STACK_PUSH(c, last, depth, limit); STACK_PUSH(b, c, depth + 1, ss_ilg(c - b)); last = a; } else { STACK_PUSH(c, last, depth, limit); STACK_PUSH(first, a, depth, limit); first = b, last = c, depth += 1, limit = ss_ilg(c - b); } } else { if((a - first) <= (c - b)) { STACK_PUSH(b, c, depth + 1, ss_ilg(c - b)); STACK_PUSH(first, a, depth, limit); first = c; } else if((last - c) <= (c - b)) { STACK_PUSH(first, a, depth, limit); STACK_PUSH(b, c, depth + 1, ss_ilg(c - b)); first = c; } else { STACK_PUSH(first, a, depth, limit); STACK_PUSH(c, last, depth, limit); first = b, last = c, depth += 1, limit = ss_ilg(c - b); } } } else { limit += 1; if(Td[PA[*first] - 1] < v) { first = ss_partition(PA, first, last, depth); limit = ss_ilg(last - first); } depth += 1; } } #undef STACK_SIZE } #endif /* (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE) */ /*---------------------------------------------------------------------------*/ #if SS_BLOCKSIZE != 0 static INLINE void ss_blockswap(int *a, int *b, int n) { int t; for(; 0 < n; --n, ++a, ++b) { t = *a, *a = *b, *b = t; } } static INLINE void ss_rotate(int *first, int *middle, int *last) { int *a, *b, t; int l, r; l = middle - first, r = last - middle; for(; (0 < l) && (0 < r);) { if(l == r) { ss_blockswap(first, middle, l); break; } if(l < r) { a = last - 1, b = middle - 1; t = *a; do { *a-- = *b, *b-- = *a; if(b < first) { *a = t; last = a; if((r -= l + 1) <= l) { break; } a -= 1, b = middle - 1; t = *a; } } while(1); } else { a = first, b = middle; t = *a; do { *a++ = *b, *b++ = *a; if(last <= b) { *a = t; first = a + 1; if((l -= r + 1) <= r) { break; } a += 1, b = middle; t = *a; } } while(1); } } } /*---------------------------------------------------------------------------*/ static void ss_inplacemerge(const unsigned char *T, const int *PA, int *first, int *middle, int *last, int depth) { const int *p; int *a, *b; int len, half; int q, r; int x; for(;;) { if(*(last - 1) < 0) { x = 1; p = PA + ~*(last - 1); } else { x = 0; p = PA + *(last - 1); } for(a = first, len = middle - first, half = len >> 1, r = -1; 0 < len; len = half, half >>= 1) { b = a + half; q = ss_compare(T, PA + ((0 <= *b) ? *b : ~*b), p, depth); if(q < 0) { a = b + 1; half -= (len & 1) ^ 1; } else { r = q; } } if(a < middle) { if(r == 0) { *a = ~*a; } ss_rotate(a, middle, last); last -= middle - a; middle = a; if(first == middle) { break; } } --last; if(x != 0) { while(*--last < 0) { } } if(middle == last) { break; } } } /*---------------------------------------------------------------------------*/ /* Merge-forward with internal buffer. */ static void ss_mergeforward(const unsigned char *T, const int *PA, int *first, int *middle, int *last, int *buf, int depth) { int *a, *b, *c, *bufend; int t; int r; bufend = buf + (middle - first) - 1; ss_blockswap(buf, first, middle - first); for(t = *(a = first), b = buf, c = middle;;) { r = ss_compare(T, PA + *b, PA + *c, depth); if(r < 0) { do { *a++ = *b; if(bufend <= b) { *bufend = t; return; } *b++ = *a; } while(*b < 0); } else if(r > 0) { do { *a++ = *c, *c++ = *a; if(last <= c) { while(b < bufend) { *a++ = *b, *b++ = *a; } *a = *b, *b = t; return; } } while(*c < 0); } else { *c = ~*c; do { *a++ = *b; if(bufend <= b) { *bufend = t; return; } *b++ = *a; } while(*b < 0); do { *a++ = *c, *c++ = *a; if(last <= c) { while(b < bufend) { *a++ = *b, *b++ = *a; } *a = *b, *b = t; return; } } while(*c < 0); } } } /* Merge-backward with internal buffer. */ static void ss_mergebackward(const unsigned char *T, const int *PA, int *first, int *middle, int *last, int *buf, int depth) { const int *p1, *p2; int *a, *b, *c, *bufend; int t; int r; int x; bufend = buf + (last - middle) - 1; ss_blockswap(buf, middle, last - middle); x = 0; if(*bufend < 0) { p1 = PA + ~*bufend; x |= 1; } else { p1 = PA + *bufend; } if(*(middle - 1) < 0) { p2 = PA + ~*(middle - 1); x |= 2; } else { p2 = PA + *(middle - 1); } for(t = *(a = last - 1), b = bufend, c = middle - 1;;) { r = ss_compare(T, p1, p2, depth); if(0 < r) { if(x & 1) { do { *a-- = *b, *b-- = *a; } while(*b < 0); x ^= 1; } *a-- = *b; if(b <= buf) { *buf = t; break; } *b-- = *a; if(*b < 0) { p1 = PA + ~*b; x |= 1; } else { p1 = PA + *b; } } else if(r < 0) { if(x & 2) { do { *a-- = *c, *c-- = *a; } while(*c < 0); x ^= 2; } *a-- = *c, *c-- = *a; if(c < first) { while(buf < b) { *a-- = *b, *b-- = *a; } *a = *b, *b = t; break; } if(*c < 0) { p2 = PA + ~*c; x |= 2; } else { p2 = PA + *c; } } else { if(x & 1) { do { *a-- = *b, *b-- = *a; } while(*b < 0); x ^= 1; } *a-- = ~*b; if(b <= buf) { *buf = t; break; } *b-- = *a; if(x & 2) { do { *a-- = *c, *c-- = *a; } while(*c < 0); x ^= 2; } *a-- = *c, *c-- = *a; if(c < first) { while(buf < b) { *a-- = *b, *b-- = *a; } *a = *b, *b = t; break; } if(*b < 0) { p1 = PA + ~*b; x |= 1; } else { p1 = PA + *b; } if(*c < 0) { p2 = PA + ~*c; x |= 2; } else { p2 = PA + *c; } } } } /* D&C based merge. */ static void ss_swapmerge(const unsigned char *T, const int *PA, int *first, int *middle, int *last, int *buf, int bufsize, int depth) { #define STACK_SIZE SS_SMERGE_STACKSIZE #define GETIDX(a) ((0 <= (a)) ? (a) : (~(a))) #define MERGE_CHECK(a, b, c)\ do {\ if(((c) & 1) ||\ (((c) & 2) && (ss_compare(T, PA + GETIDX(*((a) - 1)), PA + *(a), depth) == 0))) {\ *(a) = ~*(a);\ }\ if(((c) & 4) && ((ss_compare(T, PA + GETIDX(*((b) - 1)), PA + *(b), depth) == 0))) {\ *(b) = ~*(b);\ }\ } while(0) struct { int *a, *b, *c; int d; } stack[STACK_SIZE]; int *l, *r, *lm, *rm; int m, len, half; int ssize; int check, next; for(check = 0, ssize = 0;;) { if((last - middle) <= bufsize) { if((first < middle) && (middle < last)) { ss_mergebackward(T, PA, first, middle, last, buf, depth); } MERGE_CHECK(first, last, check); STACK_POP(first, middle, last, check); continue; } if((middle - first) <= bufsize) { if(first < middle) { ss_mergeforward(T, PA, first, middle, last, buf, depth); } MERGE_CHECK(first, last, check); STACK_POP(first, middle, last, check); continue; } for(m = 0, len = MIN(middle - first, last - middle), half = len >> 1; 0 < len; len = half, half >>= 1) { if(ss_compare(T, PA + GETIDX(*(middle + m + half)), PA + GETIDX(*(middle - m - half - 1)), depth) < 0) { m += half + 1; half -= (len & 1) ^ 1; } } if(0 < m) { lm = middle - m, rm = middle + m; ss_blockswap(lm, middle, m); l = r = middle, next = 0; if(rm < last) { if(*rm < 0) { *rm = ~*rm; if(first < lm) { for(; *--l < 0;) { } next |= 4; } next |= 1; } else if(first < lm) { for(; *r < 0; ++r) { } next |= 2; } } if((l - first) <= (last - r)) { STACK_PUSH(r, rm, last, (next & 3) | (check & 4)); middle = lm, last = l, check = (check & 3) | (next & 4); } else { if((next & 2) && (r == middle)) { next ^= 6; } STACK_PUSH(first, lm, l, (check & 3) | (next & 4)); first = r, middle = rm, check = (next & 3) | (check & 4); } } else { if(ss_compare(T, PA + GETIDX(*(middle - 1)), PA + *middle, depth) == 0) { *middle = ~*middle; } MERGE_CHECK(first, last, check); STACK_POP(first, middle, last, check); } } #undef STACK_SIZE } #endif /* SS_BLOCKSIZE != 0 */ /*---------------------------------------------------------------------------*/ /* Substring sort */ static void sssort(const unsigned char *T, const int *PA, int *first, int *last, int *buf, int bufsize, int depth, int n, int lastsuffix) { int *a; #if SS_BLOCKSIZE != 0 int *b, *middle, *curbuf; int j, k, curbufsize, limit; #endif int i; if(lastsuffix != 0) { ++first; } #if SS_BLOCKSIZE == 0 ss_mintrosort(T, PA, first, last, depth); #else if((bufsize < SS_BLOCKSIZE) && (bufsize < (last - first)) && (bufsize < (limit = ss_isqrt(last - first)))) { if(SS_BLOCKSIZE < limit) { limit = SS_BLOCKSIZE; } buf = middle = last - limit, bufsize = limit; } else { middle = last, limit = 0; } for(a = first, i = 0; SS_BLOCKSIZE < (middle - a); a += SS_BLOCKSIZE, ++i) { #if SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE ss_mintrosort(T, PA, a, a + SS_BLOCKSIZE, depth); #elif 1 < SS_BLOCKSIZE ss_insertionsort(T, PA, a, a + SS_BLOCKSIZE, depth); #endif curbufsize = last - (a + SS_BLOCKSIZE); curbuf = a + SS_BLOCKSIZE; if(curbufsize <= bufsize) { curbufsize = bufsize, curbuf = buf; } for(b = a, k = SS_BLOCKSIZE, j = i; j & 1; b -= k, k <<= 1, j >>= 1) { ss_swapmerge(T, PA, b - k, b, b + k, curbuf, curbufsize, depth); } } #if SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE ss_mintrosort(T, PA, a, middle, depth); #elif 1 < SS_BLOCKSIZE ss_insertionsort(T, PA, a, middle, depth); #endif for(k = SS_BLOCKSIZE; i != 0; k <<= 1, i >>= 1) { if(i & 1) { ss_swapmerge(T, PA, a - k, a, middle, buf, bufsize, depth); a -= k; } } if(limit != 0) { #if SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE ss_mintrosort(T, PA, middle, last, depth); #elif 1 < SS_BLOCKSIZE ss_insertionsort(T, PA, middle, last, depth); #endif ss_inplacemerge(T, PA, first, middle, last, depth); } #endif if(lastsuffix != 0) { /* Insert last type B* suffix. */ int PAi[2]; PAi[0] = PA[*(first - 1)], PAi[1] = n - 2; for(a = first, i = *(first - 1); (a < last) && ((*a < 0) || (0 < ss_compare(T, &(PAi[0]), PA + *a, depth))); ++a) { *(a - 1) = *a; } *(a - 1) = i; } } /*---------------------------------------------------------------------------*/ static INLINE int tr_ilg(int n) { return (n & 0xffff0000) ? ((n & 0xff000000) ? 24 + lg_table[(n >> 24) & 0xff] : 16 + lg_table[(n >> 16) & 0xff]) : ((n & 0x0000ff00) ? 8 + lg_table[(n >> 8) & 0xff] : 0 + lg_table[(n >> 0) & 0xff]); } /*---------------------------------------------------------------------------*/ /* Simple insertionsort for small size groups. */ static void tr_insertionsort(const int *ISAd, int *first, int *last) { int *a, *b; int t, r; for(a = first + 1; a < last; ++a) { for(t = *a, b = a - 1; 0 > (r = ISAd[t] - ISAd[*b]);) { do { *(b + 1) = *b; } while((first <= --b) && (*b < 0)); if(b < first) { break; } } if(r == 0) { *b = ~*b; } *(b + 1) = t; } } /*---------------------------------------------------------------------------*/ static INLINE void tr_fixdown(const int *ISAd, int *SA, int i, int size) { int j, k; int v; int c, d, e; for(v = SA[i], c = ISAd[v]; (j = 2 * i + 1) < size; SA[i] = SA[k], i = k) { d = ISAd[SA[k = j++]]; if(d < (e = ISAd[SA[j]])) { k = j; d = e; } if(d <= c) { break; } } SA[i] = v; } /* Simple top-down heapsort. */ static void tr_heapsort(const int *ISAd, int *SA, int size) { int i, m; int t; m = size; if((size % 2) == 0) { m--; if(ISAd[SA[m / 2]] < ISAd[SA[m]]) { SWAP(SA[m], SA[m / 2]); } } for(i = m / 2 - 1; 0 <= i; --i) { tr_fixdown(ISAd, SA, i, m); } if((size % 2) == 0) { SWAP(SA[0], SA[m]); tr_fixdown(ISAd, SA, 0, m); } for(i = m - 1; 0 < i; --i) { t = SA[0], SA[0] = SA[i]; tr_fixdown(ISAd, SA, 0, i); SA[i] = t; } } /*---------------------------------------------------------------------------*/ /* Returns the median of three elements. */ static INLINE int * tr_median3(const int *ISAd, int *v1, int *v2, int *v3) { int *t; if(ISAd[*v1] > ISAd[*v2]) { SWAP(v1, v2); } if(ISAd[*v2] > ISAd[*v3]) { if(ISAd[*v1] > ISAd[*v3]) { return v1; } else { return v3; } } return v2; } /* Returns the median of five elements. */ static INLINE int * tr_median5(const int *ISAd, int *v1, int *v2, int *v3, int *v4, int *v5) { int *t; if(ISAd[*v2] > ISAd[*v3]) { SWAP(v2, v3); } if(ISAd[*v4] > ISAd[*v5]) { SWAP(v4, v5); } if(ISAd[*v2] > ISAd[*v4]) { SWAP(v2, v4); SWAP(v3, v5); } if(ISAd[*v1] > ISAd[*v3]) { SWAP(v1, v3); } if(ISAd[*v1] > ISAd[*v4]) { SWAP(v1, v4); SWAP(v3, v5); } if(ISAd[*v3] > ISAd[*v4]) { return v4; } return v3; } /* Returns the pivot element. */ static INLINE int * tr_pivot(const int *ISAd, int *first, int *last) { int *middle; int t; t = last - first; middle = first + t / 2; if(t <= 512) { if(t <= 32) { return tr_median3(ISAd, first, middle, last - 1); } else { t >>= 2; return tr_median5(ISAd, first, first + t, middle, last - 1 - t, last - 1); } } t >>= 3; first = tr_median3(ISAd, first, first + t, first + (t << 1)); middle = tr_median3(ISAd, middle - t, middle, middle + t); last = tr_median3(ISAd, last - 1 - (t << 1), last - 1 - t, last - 1); return tr_median3(ISAd, first, middle, last); } /*---------------------------------------------------------------------------*/ typedef struct _trbudget_t trbudget_t; struct _trbudget_t { int chance; int remain; int incval; int count; }; static INLINE void trbudget_init(trbudget_t *budget, int chance, int incval) { budget->chance = chance; budget->remain = budget->incval = incval; } static INLINE int trbudget_check(trbudget_t *budget, int size) { if(size <= budget->remain) { budget->remain -= size; return 1; } if(budget->chance == 0) { budget->count += size; return 0; } budget->remain += budget->incval - size; budget->chance -= 1; return 1; } /*---------------------------------------------------------------------------*/ static INLINE void tr_partition(const int *ISAd, int *first, int *middle, int *last, int **pa, int **pb, int v) { int *a, *b, *c, *d, *e, *f; int t, s; int x = 0; for(b = middle - 1; (++b < last) && ((x = ISAd[*b]) == v);) { } if(((a = b) < last) && (x < v)) { for(; (++b < last) && ((x = ISAd[*b]) <= v);) { if(x == v) { SWAP(*b, *a); ++a; } } } for(c = last; (b < --c) && ((x = ISAd[*c]) == v);) { } if((b < (d = c)) && (x > v)) { for(; (b < --c) && ((x = ISAd[*c]) >= v);) { if(x == v) { SWAP(*c, *d); --d; } } } for(; b < c;) { SWAP(*b, *c); for(; (++b < c) && ((x = ISAd[*b]) <= v);) { if(x == v) { SWAP(*b, *a); ++a; } } for(; (b < --c) && ((x = ISAd[*c]) >= v);) { if(x == v) { SWAP(*c, *d); --d; } } } if(a <= d) { c = b - 1; if((s = a - first) > (t = b - a)) { s = t; } for(e = first, f = b - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); } if((s = d - c) > (t = last - d - 1)) { s = t; } for(e = b, f = last - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); } first += (b - a), last -= (d - c); } *pa = first, *pb = last; } static void tr_copy(int *ISA, const int *SA, int *first, int *a, int *b, int *last, int depth) { /* sort suffixes of middle partition by using sorted order of suffixes of left and right partition. */ int *c, *d, *e; int s, v; v = b - SA - 1; for(c = first, d = a - 1; c <= d; ++c) { if((0 <= (s = *c - depth)) && (ISA[s] == v)) { *++d = s; ISA[s] = d - SA; } } for(c = last - 1, e = d + 1, d = b; e < d; --c) { if((0 <= (s = *c - depth)) && (ISA[s] == v)) { *--d = s; ISA[s] = d - SA; } } } static void tr_partialcopy(int *ISA, const int *SA, int *first, int *a, int *b, int *last, int depth) { int *c, *d, *e; int s, v; int rank, lastrank, newrank = -1; v = b - SA - 1; lastrank = -1; for(c = first, d = a - 1; c <= d; ++c) { if((0 <= (s = *c - depth)) && (ISA[s] == v)) { *++d = s; rank = ISA[s + depth]; if(lastrank != rank) { lastrank = rank; newrank = d - SA; } ISA[s] = newrank; } } lastrank = -1; for(e = d; first <= e; --e) { rank = ISA[*e]; if(lastrank != rank) { lastrank = rank; newrank = e - SA; } if(newrank != rank) { ISA[*e] = newrank; } } lastrank = -1; for(c = last - 1, e = d + 1, d = b; e < d; --c) { if((0 <= (s = *c - depth)) && (ISA[s] == v)) { *--d = s; rank = ISA[s + depth]; if(lastrank != rank) { lastrank = rank; newrank = d - SA; } ISA[s] = newrank; } } } static void tr_introsort(int *ISA, const int *ISAd, int *SA, int *first, int *last, trbudget_t *budget) { #define STACK_SIZE TR_STACKSIZE struct { const int *a; int *b, *c; int d, e; }stack[STACK_SIZE]; int *a, *b, *c; int t; int v, x = 0; int incr = ISAd - ISA; int limit, next; int ssize, trlink = -1; for(ssize = 0, limit = tr_ilg(last - first);;) { if(limit < 0) { if(limit == -1) { /* tandem repeat partition */ tr_partition(ISAd - incr, first, first, last, &a, &b, last - SA - 1); /* update ranks */ if(a < last) { for(c = first, v = a - SA - 1; c < a; ++c) { ISA[*c] = v; } } if(b < last) { for(c = a, v = b - SA - 1; c < b; ++c) { ISA[*c] = v; } } /* push */ if(1 < (b - a)) { STACK_PUSH5(NULL, a, b, 0, 0); STACK_PUSH5(ISAd - incr, first, last, -2, trlink); trlink = ssize - 2; } if((a - first) <= (last - b)) { if(1 < (a - first)) { STACK_PUSH5(ISAd, b, last, tr_ilg(last - b), trlink); last = a, limit = tr_ilg(a - first); } else if(1 < (last - b)) { first = b, limit = tr_ilg(last - b); } else { STACK_POP5(ISAd, first, last, limit, trlink); } } else { if(1 < (last - b)) { STACK_PUSH5(ISAd, first, a, tr_ilg(a - first), trlink); first = b, limit = tr_ilg(last - b); } else if(1 < (a - first)) { last = a, limit = tr_ilg(a - first); } else { STACK_POP5(ISAd, first, last, limit, trlink); } } } else if(limit == -2) { /* tandem repeat copy */ a = stack[--ssize].b, b = stack[ssize].c; if(stack[ssize].d == 0) { tr_copy(ISA, SA, first, a, b, last, ISAd - ISA); } else { if(0 <= trlink) { stack[trlink].d = -1; } tr_partialcopy(ISA, SA, first, a, b, last, ISAd - ISA); } STACK_POP5(ISAd, first, last, limit, trlink); } else { /* sorted partition */ if(0 <= *first) { a = first; do { ISA[*a] = a - SA; } while((++a < last) && (0 <= *a)); first = a; } if(first < last) { a = first; do { *a = ~*a; } while(*++a < 0); next = (ISA[*a] != ISAd[*a]) ? tr_ilg(a - first + 1) : -1; if(++a < last) { for(b = first, v = a - SA - 1; b < a; ++b) { ISA[*b] = v; } } /* push */ if(trbudget_check(budget, a - first)) { if((a - first) <= (last - a)) { STACK_PUSH5(ISAd, a, last, -3, trlink); ISAd += incr, last = a, limit = next; } else { if(1 < (last - a)) { STACK_PUSH5(ISAd + incr, first, a, next, trlink); first = a, limit = -3; } else { ISAd += incr, last = a, limit = next; } } } else { if(0 <= trlink) { stack[trlink].d = -1; } if(1 < (last - a)) { first = a, limit = -3; } else { STACK_POP5(ISAd, first, last, limit, trlink); } } } else { STACK_POP5(ISAd, first, last, limit, trlink); } } continue; } if((last - first) <= TR_INSERTIONSORT_THRESHOLD) { tr_insertionsort(ISAd, first, last); limit = -3; continue; } if(limit-- == 0) { tr_heapsort(ISAd, first, last - first); for(a = last - 1; first < a; a = b) { for(x = ISAd[*a], b = a - 1; (first <= b) && (ISAd[*b] == x); --b) { *b = ~*b; } } limit = -3; continue; } /* choose pivot */ a = tr_pivot(ISAd, first, last); SWAP(*first, *a); v = ISAd[*first]; /* partition */ tr_partition(ISAd, first, first + 1, last, &a, &b, v); if((last - first) != (b - a)) { next = (ISA[*a] != v) ? tr_ilg(b - a) : -1; /* update ranks */ for(c = first, v = a - SA - 1; c < a; ++c) { ISA[*c] = v; } if(b < last) { for(c = a, v = b - SA - 1; c < b; ++c) { ISA[*c] = v; } } /* push */ if((1 < (b - a)) && (trbudget_check(budget, b - a))) { if((a - first) <= (last - b)) { if((last - b) <= (b - a)) { if(1 < (a - first)) { STACK_PUSH5(ISAd + incr, a, b, next, trlink); STACK_PUSH5(ISAd, b, last, limit, trlink); last = a; } else if(1 < (last - b)) { STACK_PUSH5(ISAd + incr, a, b, next, trlink); first = b; } else { ISAd += incr, first = a, last = b, limit = next; } } else if((a - first) <= (b - a)) { if(1 < (a - first)) { STACK_PUSH5(ISAd, b, last, limit, trlink); STACK_PUSH5(ISAd + incr, a, b, next, trlink); last = a; } else { STACK_PUSH5(ISAd, b, last, limit, trlink); ISAd += incr, first = a, last = b, limit = next; } } else { STACK_PUSH5(ISAd, b, last, limit, trlink); STACK_PUSH5(ISAd, first, a, limit, trlink); ISAd += incr, first = a, last = b, limit = next; } } else { if((a - first) <= (b - a)) { if(1 < (last - b)) { STACK_PUSH5(ISAd + incr, a, b, next, trlink); STACK_PUSH5(ISAd, first, a, limit, trlink); first = b; } else if(1 < (a - first)) { STACK_PUSH5(ISAd + incr, a, b, next, trlink); last = a; } else { ISAd += incr, first = a, last = b, limit = next; } } else if((last - b) <= (b - a)) { if(1 < (last - b)) { STACK_PUSH5(ISAd, first, a, limit, trlink); STACK_PUSH5(ISAd + incr, a, b, next, trlink); first = b; } else { STACK_PUSH5(ISAd, first, a, limit, trlink); ISAd += incr, first = a, last = b, limit = next; } } else { STACK_PUSH5(ISAd, first, a, limit, trlink); STACK_PUSH5(ISAd, b, last, limit, trlink); ISAd += incr, first = a, last = b, limit = next; } } } else { if((1 < (b - a)) && (0 <= trlink)) { stack[trlink].d = -1; } if((a - first) <= (last - b)) { if(1 < (a - first)) { STACK_PUSH5(ISAd, b, last, limit, trlink); last = a; } else if(1 < (last - b)) { first = b; } else { STACK_POP5(ISAd, first, last, limit, trlink); } } else { if(1 < (last - b)) { STACK_PUSH5(ISAd, first, a, limit, trlink); first = b; } else if(1 < (a - first)) { last = a; } else { STACK_POP5(ISAd, first, last, limit, trlink); } } } } else { if(trbudget_check(budget, last - first)) { limit = tr_ilg(last - first), ISAd += incr; } else { if(0 <= trlink) { stack[trlink].d = -1; } STACK_POP5(ISAd, first, last, limit, trlink); } } } #undef STACK_SIZE } /*---------------------------------------------------------------------------*/ /* Tandem repeat sort */ static void trsort(int *ISA, int *SA, int n, int depth) { int *ISAd; int *first, *last; trbudget_t budget; int t, skip, unsorted; trbudget_init(&budget, tr_ilg(n) * 2 / 3, n); /* trbudget_init(&budget, tr_ilg(n) * 3 / 4, n); */ for(ISAd = ISA + depth; -n < *SA; ISAd += ISAd - ISA) { first = SA; skip = 0; unsorted = 0; do { if((t = *first) < 0) { first -= t; skip += t; } else { if(skip != 0) { *(first + skip) = skip; skip = 0; } last = SA + ISA[t] + 1; if(1 < (last - first)) { budget.count = 0; tr_introsort(ISA, ISAd, SA, first, last, &budget); if(budget.count != 0) { unsorted += budget.count; } else { skip = first - last; } } else if((last - first) == 1) { skip = -1; } first = last; } } while(first < (SA + n)); if(skip != 0) { *(first + skip) = skip; } if(unsorted == 0) { break; } } } /*---------------------------------------------------------------------------*/ /* Sorts suffixes of type B*. */ static int sort_typeBstar(const unsigned char *T, int *SA, int *bucket_A, int *bucket_B, int n, int openMP) { int *PAb, *ISAb, *buf; #ifdef LIBBSC_OPENMP int *curbuf; int l; #endif int i, j, k, t, m, bufsize; int c0, c1; #ifdef LIBBSC_OPENMP int d0, d1; #endif (void)openMP; /* Initialize bucket arrays. */ for(i = 0; i < BUCKET_A_SIZE; ++i) { bucket_A[i] = 0; } for(i = 0; i < BUCKET_B_SIZE; ++i) { bucket_B[i] = 0; } /* Count the number of occurrences of the first one or two characters of each type A, B and B* suffix. Moreover, store the beginning position of all type B* suffixes into the array SA. */ for(i = n - 1, m = n, c0 = T[n - 1]; 0 <= i;) { /* type A suffix. */ do { ++BUCKET_A(c1 = c0); } while((0 <= --i) && ((c0 = T[i]) >= c1)); if(0 <= i) { /* type B* suffix. */ ++BUCKET_BSTAR(c0, c1); SA[--m] = i; /* type B suffix. */ for(--i, c1 = c0; (0 <= i) && ((c0 = T[i]) <= c1); --i, c1 = c0) { ++BUCKET_B(c0, c1); } } } m = n - m; /* note: A type B* suffix is lexicographically smaller than a type B suffix that begins with the same first two characters. */ /* Calculate the index of start/end point of each bucket. */ for(c0 = 0, i = 0, j = 0; c0 < ALPHABET_SIZE; ++c0) { t = i + BUCKET_A(c0); BUCKET_A(c0) = i + j; /* start point */ i = t + BUCKET_B(c0, c0); for(c1 = c0 + 1; c1 < ALPHABET_SIZE; ++c1) { j += BUCKET_BSTAR(c0, c1); BUCKET_BSTAR(c0, c1) = j; /* end point */ i += BUCKET_B(c0, c1); } } if(0 < m) { /* Sort the type B* suffixes by their first two characters. */ PAb = SA + n - m; ISAb = SA + m; for(i = m - 2; 0 <= i; --i) { t = PAb[i], c0 = T[t], c1 = T[t + 1]; SA[--BUCKET_BSTAR(c0, c1)] = i; } t = PAb[m - 1], c0 = T[t], c1 = T[t + 1]; SA[--BUCKET_BSTAR(c0, c1)] = m - 1; /* Sort the type B* substrings using sssort. */ #ifdef LIBBSC_OPENMP if (openMP) { buf = SA + m; c0 = ALPHABET_SIZE - 2, c1 = ALPHABET_SIZE - 1, j = m; #pragma omp parallel default(shared) private(bufsize, curbuf, k, l, d0, d1) { bufsize = (n - (2 * m)) / omp_get_num_threads(); curbuf = buf + omp_get_thread_num() * bufsize; k = 0; for(;;) { #pragma omp critical(sssort_lock) { if(0 < (l = j)) { d0 = c0, d1 = c1; do { k = BUCKET_BSTAR(d0, d1); if(--d1 <= d0) { d1 = ALPHABET_SIZE - 1; if(--d0 < 0) { break; } } } while(((l - k) <= 1) && (0 < (l = k))); c0 = d0, c1 = d1, j = k; } } if(l == 0) { break; } sssort(T, PAb, SA + k, SA + l, curbuf, bufsize, 2, n, *(SA + k) == (m - 1)); } } } else { buf = SA + m, bufsize = n - (2 * m); for(c0 = ALPHABET_SIZE - 2, j = m; 0 < j; --c0) { for(c1 = ALPHABET_SIZE - 1; c0 < c1; j = i, --c1) { i = BUCKET_BSTAR(c0, c1); if(1 < (j - i)) { sssort(T, PAb, SA + i, SA + j, buf, bufsize, 2, n, *(SA + i) == (m - 1)); } } } } #else buf = SA + m, bufsize = n - (2 * m); for(c0 = ALPHABET_SIZE - 2, j = m; 0 < j; --c0) { for(c1 = ALPHABET_SIZE - 1; c0 < c1; j = i, --c1) { i = BUCKET_BSTAR(c0, c1); if(1 < (j - i)) { sssort(T, PAb, SA + i, SA + j, buf, bufsize, 2, n, *(SA + i) == (m - 1)); } } } #endif /* Compute ranks of type B* substrings. */ for(i = m - 1; 0 <= i; --i) { if(0 <= SA[i]) { j = i; do { ISAb[SA[i]] = i; } while((0 <= --i) && (0 <= SA[i])); SA[i + 1] = i - j; if(i <= 0) { break; } } j = i; do { ISAb[SA[i] = ~SA[i]] = j; } while(SA[--i] < 0); ISAb[SA[i]] = j; } /* Construct the inverse suffix array of type B* suffixes using trsort. */ trsort(ISAb, SA, m, 1); /* Set the sorted order of tyoe B* suffixes. */ for(i = n - 1, j = m, c0 = T[n - 1]; 0 <= i;) { for(--i, c1 = c0; (0 <= i) && ((c0 = T[i]) >= c1); --i, c1 = c0) { } if(0 <= i) { t = i; for(--i, c1 = c0; (0 <= i) && ((c0 = T[i]) <= c1); --i, c1 = c0) { } SA[ISAb[--j]] = ((t == 0) || (1 < (t - i))) ? t : ~t; } } /* Calculate the index of start/end point of each bucket. */ BUCKET_B(ALPHABET_SIZE - 1, ALPHABET_SIZE - 1) = n; /* end point */ for(c0 = ALPHABET_SIZE - 2, k = m - 1; 0 <= c0; --c0) { i = BUCKET_A(c0 + 1) - 1; for(c1 = ALPHABET_SIZE - 1; c0 < c1; --c1) { t = i - BUCKET_B(c0, c1); BUCKET_B(c0, c1) = i; /* end point */ /* Move all type B* suffixes to the correct position. */ for(i = t, j = BUCKET_BSTAR(c0, c1); j <= k; --i, --k) { SA[i] = SA[k]; } } BUCKET_BSTAR(c0, c0 + 1) = i - BUCKET_B(c0, c0) + 1; /* start point */ BUCKET_B(c0, c0) = i; /* end point */ } } return m; } /* Constructs the suffix array by using the sorted order of type B* suffixes. */ static void construct_SA(const unsigned char *T, int *SA, int *bucket_A, int *bucket_B, int n, int m) { int *i, *j, *k; int s; int c0, c1, c2; if(0 < m) { /* Construct the sorted order of type B suffixes by using the sorted order of type B* suffixes. */ for(c1 = ALPHABET_SIZE - 2; 0 <= c1; --c1) { /* Scan the suffix array from right to left. */ for(i = SA + BUCKET_BSTAR(c1, c1 + 1), j = SA + BUCKET_A(c1 + 1) - 1, k = NULL, c2 = -1; i <= j; --j) { if(0 < (s = *j)) { assert(T[s] == c1); assert(((s + 1) < n) && (T[s] <= T[s + 1])); assert(T[s - 1] <= T[s]); *j = ~s; c0 = T[--s]; if((0 < s) && (T[s - 1] > c0)) { s = ~s; } if(c0 != c2) { if(0 <= c2) { BUCKET_B(c2, c1) = k - SA; } k = SA + BUCKET_B(c2 = c0, c1); } assert(k < j); *k-- = s; } else { assert(((s == 0) && (T[s] == c1)) || (s < 0)); *j = ~s; } } } } /* Construct the suffix array by using the sorted order of type B suffixes. */ k = SA + BUCKET_A(c2 = T[n - 1]); *k++ = (T[n - 2] < c2) ? ~(n - 1) : (n - 1); /* Scan the suffix array from left to right. */ for(i = SA, j = SA + n; i < j; ++i) { if(0 < (s = *i)) { assert(T[s - 1] >= T[s]); c0 = T[--s]; if((s == 0) || (T[s - 1] < c0)) { s = ~s; } if(c0 != c2) { BUCKET_A(c2) = k - SA; k = SA + BUCKET_A(c2 = c0); } assert(i < k); *k++ = s; } else { assert(s < 0); *i = ~s; } } } /* Constructs the burrows-wheeler transformed string directly by using the sorted order of type B* suffixes. */ static int construct_BWT(const unsigned char *T, int *SA, int *bucket_A, int *bucket_B, int n, int m) { int *i, *j, *k, *orig; int s; int c0, c1, c2; if(0 < m) { /* Construct the sorted order of type B suffixes by using the sorted order of type B* suffixes. */ for(c1 = ALPHABET_SIZE - 2; 0 <= c1; --c1) { /* Scan the suffix array from right to left. */ for(i = SA + BUCKET_BSTAR(c1, c1 + 1), j = SA + BUCKET_A(c1 + 1) - 1, k = NULL, c2 = -1; i <= j; --j) { if(0 < (s = *j)) { assert(T[s] == c1); assert(((s + 1) < n) && (T[s] <= T[s + 1])); assert(T[s - 1] <= T[s]); c0 = T[--s]; *j = ~((int)c0); if((0 < s) && (T[s - 1] > c0)) { s = ~s; } if(c0 != c2) { if(0 <= c2) { BUCKET_B(c2, c1) = k - SA; } k = SA + BUCKET_B(c2 = c0, c1); } assert(k < j); *k-- = s; } else if(s != 0) { *j = ~s; #ifndef NDEBUG } else { assert(T[s] == c1); #endif } } } } /* Construct the BWTed string by using the sorted order of type B suffixes. */ k = SA + BUCKET_A(c2 = T[n - 1]); *k++ = (T[n - 2] < c2) ? ~((int)T[n - 2]) : (n - 1); /* Scan the suffix array from left to right. */ for(i = SA, j = SA + n, orig = SA; i < j; ++i) { if(0 < (s = *i)) { assert(T[s - 1] >= T[s]); c0 = T[--s]; *i = c0; if((0 < s) && (T[s - 1] < c0)) { s = ~((int)T[s - 1]); } if(c0 != c2) { BUCKET_A(c2) = k - SA; k = SA + BUCKET_A(c2 = c0); } assert(i < k); *k++ = s; } else if(s != 0) { *i = ~s; } else { orig = i; } } return orig - SA; } /* Constructs the burrows-wheeler transformed string directly by using the sorted order of type B* suffixes. */ static int construct_BWT_indexes(const unsigned char *T, int *SA, int *bucket_A, int *bucket_B, int n, int m, unsigned char * num_indexes, int * indexes) { int *i, *j, *k, *orig; int s; int c0, c1, c2; int mod = n / 8; { mod |= mod >> 1; mod |= mod >> 2; mod |= mod >> 4; mod |= mod >> 8; mod |= mod >> 16; mod >>= 1; *num_indexes = (unsigned char)((n - 1) / (mod + 1)); } if(0 < m) { /* Construct the sorted order of type B suffixes by using the sorted order of type B* suffixes. */ for(c1 = ALPHABET_SIZE - 2; 0 <= c1; --c1) { /* Scan the suffix array from right to left. */ for(i = SA + BUCKET_BSTAR(c1, c1 + 1), j = SA + BUCKET_A(c1 + 1) - 1, k = NULL, c2 = -1; i <= j; --j) { if(0 < (s = *j)) { assert(T[s] == c1); assert(((s + 1) < n) && (T[s] <= T[s + 1])); assert(T[s - 1] <= T[s]); if ((s & mod) == 0) indexes[s / (mod + 1) - 1] = j - SA; c0 = T[--s]; *j = ~((int)c0); if((0 < s) && (T[s - 1] > c0)) { s = ~s; } if(c0 != c2) { if(0 <= c2) { BUCKET_B(c2, c1) = k - SA; } k = SA + BUCKET_B(c2 = c0, c1); } assert(k < j); *k-- = s; } else if(s != 0) { *j = ~s; #ifndef NDEBUG } else { assert(T[s] == c1); #endif } } } } /* Construct the BWTed string by using the sorted order of type B suffixes. */ k = SA + BUCKET_A(c2 = T[n - 1]); if (T[n - 2] < c2) { if (((n - 1) & mod) == 0) indexes[(n - 1) / (mod + 1) - 1] = k - SA; *k++ = ~((int)T[n - 2]); } else { *k++ = n - 1; } /* Scan the suffix array from left to right. */ for(i = SA, j = SA + n, orig = SA; i < j; ++i) { if(0 < (s = *i)) { assert(T[s - 1] >= T[s]); if ((s & mod) == 0) indexes[s / (mod + 1) - 1] = i - SA; c0 = T[--s]; *i = c0; if(c0 != c2) { BUCKET_A(c2) = k - SA; k = SA + BUCKET_A(c2 = c0); } assert(i < k); if((0 < s) && (T[s - 1] < c0)) { if ((s & mod) == 0) indexes[s / (mod + 1) - 1] = k - SA; *k++ = ~((int)T[s - 1]); } else *k++ = s; } else if(s != 0) { *i = ~s; } else { orig = i; } } return orig - SA; } /*---------------------------------------------------------------------------*/ /*- Function -*/ int divsufsort(const unsigned char *T, int *SA, int n, int openMP) { int *bucket_A, *bucket_B; int m; int err = 0; /* Check arguments. */ if((T == NULL) || (SA == NULL) || (n < 0)) { return -1; } else if(n == 0) { return 0; } else if(n == 1) { SA[0] = 0; return 0; } else if(n == 2) { m = (T[0] < T[1]); SA[m ^ 1] = 0, SA[m] = 1; return 0; } bucket_A = (int *)malloc(BUCKET_A_SIZE * sizeof(int)); bucket_B = (int *)malloc(BUCKET_B_SIZE * sizeof(int)); /* Suffixsort. */ if((bucket_A != NULL) && (bucket_B != NULL)) { m = sort_typeBstar(T, SA, bucket_A, bucket_B, n, openMP); construct_SA(T, SA, bucket_A, bucket_B, n, m); } else { err = -2; } free(bucket_B); free(bucket_A); return err; } int divbwt(const unsigned char *T, unsigned char *U, int *A, int n, unsigned char * num_indexes, int * indexes, int openMP) { int *B; int *bucket_A, *bucket_B; int m, pidx, i; /* Check arguments. */ if((T == NULL) || (U == NULL) || (n < 0)) { return -1; } else if(n <= 1) { if(n == 1) { U[0] = T[0]; } return n; } if((B = A) == NULL) { B = (int *)malloc((size_t)(n + 1) * sizeof(int)); } bucket_A = (int *)malloc(BUCKET_A_SIZE * sizeof(int)); bucket_B = (int *)malloc(BUCKET_B_SIZE * sizeof(int)); /* Burrows-Wheeler Transform. */ if((B != NULL) && (bucket_A != NULL) && (bucket_B != NULL)) { m = sort_typeBstar(T, B, bucket_A, bucket_B, n, openMP); if (num_indexes == NULL || indexes == NULL) { pidx = construct_BWT(T, B, bucket_A, bucket_B, n, m); } else { pidx = construct_BWT_indexes(T, B, bucket_A, bucket_B, n, m, num_indexes, indexes); } /* Copy to output string. */ U[0] = T[n - 1]; for(i = 0; i < pidx; ++i) { U[i + 1] = (unsigned char)B[i]; } for(i += 1; i < n; ++i) { U[i] = (unsigned char)B[i]; } pidx += 1; } else { pidx = -2; } free(bucket_B); free(bucket_A); if(A == NULL) { free(B); } return pidx; } zstd-0.5.1/lib/divsufsort.h000066400000000000000000000045561266132244200156440ustar00rootroot00000000000000/* * divsufsort.h for libdivsufsort-lite * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ #ifndef _DIVSUFSORT_H #define _DIVSUFSORT_H 1 #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /*- Prototypes -*/ /** * Constructs the suffix array of a given string. * @param T[0..n-1] The input string. * @param SA[0..n-1] The output array of suffixes. * @param n The length of the given string. * @param openMP enables OpenMP optimization. * @return 0 if no error occurred, -1 or -2 otherwise. */ int divsufsort(const unsigned char *T, int *SA, int n, int openMP); /** * Constructs the burrows-wheeler transformed string of a given string. * @param T[0..n-1] The input string. * @param U[0..n-1] The output string. (can be T) * @param A[0..n-1] The temporary array. (can be NULL) * @param n The length of the given string. * @param num_indexes The length of secondary indexes array. (can be NULL) * @param indexes The secondary indexes array. (can be NULL) * @param openMP enables OpenMP optimization. * @return The primary index if no error occurred, -1 or -2 otherwise. */ int divbwt(const unsigned char *T, unsigned char *U, int *A, int n, unsigned char * num_indexes, int * indexes, int openMP); #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ #endif /* _DIVSUFSORT_H */ zstd-0.5.1/lib/error_private.h000066400000000000000000000113221266132244200163040ustar00rootroot00000000000000/* ****************************************************************** Error codes and messages Copyright (C) 2013-2016, Yann Collet BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. You can contact the author at : - Source repository : https://github.com/Cyan4973/zstd ****************************************************************** */ /* Note : this module is expected to remain private, do not expose it */ #ifndef ERROR_H_MODULE #define ERROR_H_MODULE #if defined (__cplusplus) extern "C" { #endif /* **************************************** * Dependencies ******************************************/ #include /* size_t */ #include "error_public.h" /* enum list */ /* **************************************** * Compiler-specific ******************************************/ #if defined(__GNUC__) # define ERR_STATIC static __attribute__((unused)) #elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) # define ERR_STATIC static inline #elif defined(_MSC_VER) # define ERR_STATIC static __inline #else # define ERR_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */ #endif /*-**************************************** * Customization ******************************************/ typedef ZSTD_ErrorCode ERR_enum; #define PREFIX(name) ZSTD_error_##name /*-**************************************** * Error codes handling ******************************************/ #ifdef ERROR # undef ERROR /* reported already defined on VS 2015 (Rich Geldreich) */ #endif #define ERROR(name) (size_t)-PREFIX(name) ERR_STATIC unsigned ERR_isError(size_t code) { return (code > ERROR(maxCode)); } ERR_STATIC ERR_enum ERR_getError(size_t code) { if (!ERR_isError(code)) return (ERR_enum)0; return (ERR_enum) (0-code); } /*-**************************************** * Error Strings ******************************************/ ERR_STATIC const char* ERR_getErrorName(size_t code) { static const char* notErrorCode = "Unspecified error code"; switch( ERR_getError(code) ) { case PREFIX(no_error): return "No error detected"; case PREFIX(GENERIC): return "Error (generic)"; case PREFIX(prefix_unknown): return "Unknown frame descriptor"; case PREFIX(frameParameter_unsupported): return "Unsupported frame parameter"; case PREFIX(frameParameter_unsupportedBy32bits): return "Frame parameter unsupported in 32-bits mode"; case PREFIX(init_missing): return "Context should be init first"; case PREFIX(memory_allocation): return "Allocation error : not enough memory"; case PREFIX(stage_wrong): return "Operation not authorized at current processing stage"; case PREFIX(dstSize_tooSmall): return "Destination buffer is too small"; case PREFIX(srcSize_wrong): return "Src size incorrect"; case PREFIX(corruption_detected): return "Corrupted block detected"; case PREFIX(tableLog_tooLarge): return "tableLog requires too much memory"; case PREFIX(maxSymbolValue_tooLarge): return "Unsupported max possible Symbol Value : too large"; case PREFIX(maxSymbolValue_tooSmall): return "Specified maxSymbolValue is too small"; case PREFIX(dictionary_corrupted): return "Dictionary is corrupted"; case PREFIX(maxCode): default: return notErrorCode; /* should be impossible, due to ERR_getError() */ } } #if defined (__cplusplus) } #endif #endif /* ERROR_H_MODULE */ zstd-0.5.1/lib/error_public.h000066400000000000000000000050631266132244200161150ustar00rootroot00000000000000/* ****************************************************************** Error codes list Copyright (C) 2016, Yann Collet BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. You can contact the author at : - Source repository : https://github.com/Cyan4973/zstd ****************************************************************** */ #ifndef ERROR_PUBLIC_H_MODULE #define ERROR_PUBLIC_H_MODULE #if defined (__cplusplus) extern "C" { #endif /* **************************************** * error codes list ******************************************/ typedef enum { ZSTD_error_no_error, ZSTD_error_GENERIC, ZSTD_error_prefix_unknown, ZSTD_error_frameParameter_unsupported, ZSTD_error_frameParameter_unsupportedBy32bits, ZSTD_error_init_missing, ZSTD_error_memory_allocation, ZSTD_error_stage_wrong, ZSTD_error_dstSize_tooSmall, ZSTD_error_srcSize_wrong, ZSTD_error_corruption_detected, ZSTD_error_tableLog_tooLarge, ZSTD_error_maxSymbolValue_tooLarge, ZSTD_error_maxSymbolValue_tooSmall, ZSTD_error_dictionary_corrupted, ZSTD_error_maxCode } ZSTD_ErrorCode; /* note : functions provide error codes in reverse negative order, so compare with (size_t)(0-enum) */ #if defined (__cplusplus) } #endif #endif /* ERROR_PUBLIC_H_MODULE */ zstd-0.5.1/lib/fse.c000066400000000000000000001217151266132244200142010ustar00rootroot00000000000000/* ****************************************************************** FSE : Finite State Entropy coder Copyright (C) 2013-2015, Yann Collet. BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. You can contact the author at : - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy - Public forum : https://groups.google.com/forum/#!forum/lz4c ****************************************************************** */ #ifndef FSE_COMMONDEFS_ONLY /* ************************************************************** * Tuning parameters ****************************************************************/ /*!MEMORY_USAGE : * Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.) * Increasing memory usage improves compression ratio * Reduced memory usage can improve speed, due to cache effect * Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */ #define FSE_MAX_MEMORY_USAGE 14 #define FSE_DEFAULT_MEMORY_USAGE 13 /*!FSE_MAX_SYMBOL_VALUE : * Maximum symbol value authorized. * Required for proper stack allocation */ #define FSE_MAX_SYMBOL_VALUE 255 /* ************************************************************** * template functions type & suffix ****************************************************************/ #define FSE_FUNCTION_TYPE BYTE #define FSE_FUNCTION_EXTENSION #define FSE_DECODE_TYPE FSE_decode_t #endif /* !FSE_COMMONDEFS_ONLY */ /* ************************************************************** * Compiler specifics ****************************************************************/ #ifdef _MSC_VER /* Visual Studio */ # define FORCE_INLINE static __forceinline # include /* For Visual 2005 */ # pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ # pragma warning(disable : 4214) /* disable: C4214: non-int bitfields */ #else # ifdef __GNUC__ # define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) # define FORCE_INLINE static inline __attribute__((always_inline)) # else # define FORCE_INLINE static inline # endif #endif /* ************************************************************** * Includes ****************************************************************/ #include /* malloc, free, qsort */ #include /* memcpy, memset */ #include /* printf (debug) */ #include "bitstream.h" #include "fse_static.h" /* *************************************************************** * Constants *****************************************************************/ #define FSE_MAX_TABLELOG (FSE_MAX_MEMORY_USAGE-2) #define FSE_MAX_TABLESIZE (1U< FSE_TABLELOG_ABSOLUTE_MAX #error "FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX is not supported" #endif /* ************************************************************** * Error Management ****************************************************************/ #define FSE_STATIC_ASSERT(c) { enum { FSE_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */ /* ************************************************************** * Complex types ****************************************************************/ typedef U32 CTable_max_t[FSE_CTABLE_SIZE_U32(FSE_MAX_TABLELOG, FSE_MAX_SYMBOL_VALUE)]; typedef U32 DTable_max_t[FSE_DTABLE_SIZE_U32(FSE_MAX_TABLELOG)]; /* ************************************************************** * Templates ****************************************************************/ /* designed to be included for type-specific functions (template emulation in C) Objective is to write these functions only once, for improved maintenance */ /* safety checks */ #ifndef FSE_FUNCTION_EXTENSION # error "FSE_FUNCTION_EXTENSION must be defined" #endif #ifndef FSE_FUNCTION_TYPE # error "FSE_FUNCTION_TYPE must be defined" #endif /* Function names */ #define FSE_CAT(X,Y) X##Y #define FSE_FUNCTION_NAME(X,Y) FSE_CAT(X,Y) #define FSE_TYPE_NAME(X,Y) FSE_CAT(X,Y) /* Function templates */ static U32 FSE_tableStep(U32 tableSize) { return (tableSize>>1) + (tableSize>>3) + 3; } size_t FSE_buildCTable(FSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog) { const unsigned tableSize = 1 << tableLog; const unsigned tableMask = tableSize - 1; void* const ptr = ct; U16* const tableU16 = ( (U16*) ptr) + 2; void* const FSCT = ((U32*)ptr) + 1 /* header */ + (tableLog ? tableSize>>1 : 1) ; FSE_symbolCompressionTransform* const symbolTT = (FSE_symbolCompressionTransform*) (FSCT); const unsigned step = FSE_tableStep(tableSize); unsigned cumul[FSE_MAX_SYMBOL_VALUE+2]; U32 position = 0; FSE_FUNCTION_TYPE tableSymbol[FSE_MAX_TABLESIZE]; /* memset() is not necessary, even if static analyzer complain about it */ U32 highThreshold = tableSize-1; unsigned symbol; unsigned i; /* header */ tableU16[-2] = (U16) tableLog; tableU16[-1] = (U16) maxSymbolValue; /* For explanations on how to distribute symbol values over the table : * http://fastcompression.blogspot.fr/2014/02/fse-distributing-symbol-values.html */ /* symbol start positions */ cumul[0] = 0; for (i=1; i<=maxSymbolValue+1; i++) { if (normalizedCounter[i-1]==-1) { /* Low proba symbol */ cumul[i] = cumul[i-1] + 1; tableSymbol[highThreshold--] = (FSE_FUNCTION_TYPE)(i-1); } else { cumul[i] = cumul[i-1] + normalizedCounter[i-1]; } } cumul[maxSymbolValue+1] = tableSize+1; /* Spread symbols */ for (symbol=0; symbol<=maxSymbolValue; symbol++) { int nbOccurences; for (nbOccurences=0; nbOccurences highThreshold) position = (position + step) & tableMask; /* Low proba area */ } } if (position!=0) return ERROR(GENERIC); /* Must have gone through all positions */ /* Build table */ for (i=0; i FSE_TABLELOG_ABSOLUTE_MAX) tableLog = FSE_TABLELOG_ABSOLUTE_MAX; return (FSE_DTable*)malloc( FSE_DTABLE_SIZE_U32(tableLog) * sizeof (U32) ); } void FSE_freeDTable (FSE_DTable* dt) { free(dt); } size_t FSE_buildDTable(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog) { FSE_DTableHeader DTableH; void* const tdPtr = dt+1; /* because dt is unsigned, 32-bits aligned on 32-bits */ FSE_DECODE_TYPE* const tableDecode = (FSE_DECODE_TYPE*) (tdPtr); const U32 tableSize = 1 << tableLog; const U32 tableMask = tableSize-1; const U32 step = FSE_tableStep(tableSize); U16 symbolNext[FSE_MAX_SYMBOL_VALUE+1]; U32 position = 0; U32 highThreshold = tableSize-1; const S16 largeLimit= (S16)(1 << (tableLog-1)); U32 noLarge = 1; U32 s; /* Sanity Checks */ if (maxSymbolValue > FSE_MAX_SYMBOL_VALUE) return ERROR(maxSymbolValue_tooLarge); if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge); /* Init, lay down lowprob symbols */ DTableH.tableLog = (U16)tableLog; for (s=0; s<=maxSymbolValue; s++) { if (normalizedCounter[s]==-1) { tableDecode[highThreshold--].symbol = (FSE_FUNCTION_TYPE)s; symbolNext[s] = 1; } else { if (normalizedCounter[s] >= largeLimit) noLarge=0; symbolNext[s] = normalizedCounter[s]; } } /* Spread symbols */ for (s=0; s<=maxSymbolValue; s++) { int i; for (i=0; i highThreshold) position = (position + step) & tableMask; /* lowprob area */ } } if (position!=0) return ERROR(GENERIC); /* position must reach all cells once, otherwise normalizedCounter is incorrect */ /* Build Decoding table */ { U32 i; for (i=0; i> 3) + 3; return maxSymbolValue ? maxHeaderSize : FSE_NCOUNTBOUND; /* maxSymbolValue==0 ? use default */ } static short FSE_abs(short a) { return a<0 ? -a : a; } static size_t FSE_writeNCount_generic (void* header, size_t headerBufferSize, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, unsigned writeIsSafe) { BYTE* const ostart = (BYTE*) header; BYTE* out = ostart; BYTE* const oend = ostart + headerBufferSize; int nbBits; const int tableSize = 1 << tableLog; int remaining; int threshold; U32 bitStream; int bitCount; unsigned charnum = 0; int previous0 = 0; bitStream = 0; bitCount = 0; /* Table Size */ bitStream += (tableLog-FSE_MIN_TABLELOG) << bitCount; bitCount += 4; /* Init */ remaining = tableSize+1; /* +1 for extra accuracy */ threshold = tableSize; nbBits = tableLog+1; while (remaining>1) { /* stops at 1 */ if (previous0) { unsigned start = charnum; while (!normalizedCounter[charnum]) charnum++; while (charnum >= start+24) { start+=24; bitStream += 0xFFFFU << bitCount; if ((!writeIsSafe) && (out > oend-2)) return ERROR(dstSize_tooSmall); /* Buffer overflow */ out[0] = (BYTE) bitStream; out[1] = (BYTE)(bitStream>>8); out+=2; bitStream>>=16; } while (charnum >= start+3) { start+=3; bitStream += 3 << bitCount; bitCount += 2; } bitStream += (charnum-start) << bitCount; bitCount += 2; if (bitCount>16) { if ((!writeIsSafe) && (out > oend - 2)) return ERROR(dstSize_tooSmall); /* Buffer overflow */ out[0] = (BYTE)bitStream; out[1] = (BYTE)(bitStream>>8); out += 2; bitStream >>= 16; bitCount -= 16; } } { short count = normalizedCounter[charnum++]; const short max = (short)((2*threshold-1)-remaining); remaining -= FSE_abs(count); if (remaining<1) return ERROR(GENERIC); count++; /* +1 for extra accuracy */ if (count>=threshold) count += max; /* [0..max[ [max..threshold[ (...) [threshold+max 2*threshold[ */ bitStream += count << bitCount; bitCount += nbBits; bitCount -= (count>=1; } if (bitCount>16) { if ((!writeIsSafe) && (out > oend - 2)) return ERROR(dstSize_tooSmall); /* Buffer overflow */ out[0] = (BYTE)bitStream; out[1] = (BYTE)(bitStream>>8); out += 2; bitStream >>= 16; bitCount -= 16; } } /* flush remaining bitStream */ if ((!writeIsSafe) && (out > oend - 2)) return ERROR(dstSize_tooSmall); /* Buffer overflow */ out[0] = (BYTE)bitStream; out[1] = (BYTE)(bitStream>>8); out+= (bitCount+7) /8; if (charnum > maxSymbolValue + 1) return ERROR(GENERIC); return (out-ostart); } size_t FSE_writeNCount (void* buffer, size_t bufferSize, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog) { if (tableLog > FSE_MAX_TABLELOG) return ERROR(GENERIC); /* Unsupported */ if (tableLog < FSE_MIN_TABLELOG) return ERROR(GENERIC); /* Unsupported */ if (bufferSize < FSE_NCountWriteBound(maxSymbolValue, tableLog)) return FSE_writeNCount_generic(buffer, bufferSize, normalizedCounter, maxSymbolValue, tableLog, 0); return FSE_writeNCount_generic(buffer, bufferSize, normalizedCounter, maxSymbolValue, tableLog, 1); } size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr, const void* headerBuffer, size_t hbSize) { const BYTE* const istart = (const BYTE*) headerBuffer; const BYTE* const iend = istart + hbSize; const BYTE* ip = istart; int nbBits; int remaining; int threshold; U32 bitStream; int bitCount; unsigned charnum = 0; int previous0 = 0; if (hbSize < 4) return ERROR(srcSize_wrong); bitStream = MEM_readLE32(ip); nbBits = (bitStream & 0xF) + FSE_MIN_TABLELOG; /* extract tableLog */ if (nbBits > FSE_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge); bitStream >>= 4; bitCount = 4; *tableLogPtr = nbBits; remaining = (1<1) && (charnum<=*maxSVPtr)) { if (previous0) { unsigned n0 = charnum; while ((bitStream & 0xFFFF) == 0xFFFF) { n0+=24; if (ip < iend-5) { ip+=2; bitStream = MEM_readLE32(ip) >> bitCount; } else { bitStream >>= 16; bitCount+=16; } } while ((bitStream & 3) == 3) { n0+=3; bitStream>>=2; bitCount+=2; } n0 += bitStream & 3; bitCount += 2; if (n0 > *maxSVPtr) return ERROR(maxSymbolValue_tooSmall); while (charnum < n0) normalizedCounter[charnum++] = 0; if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) { ip += bitCount>>3; bitCount &= 7; bitStream = MEM_readLE32(ip) >> bitCount; } else bitStream >>= 2; } { const short max = (short)((2*threshold-1)-remaining); short count; if ((bitStream & (threshold-1)) < (U32)max) { count = (short)(bitStream & (threshold-1)); bitCount += nbBits-1; } else { count = (short)(bitStream & (2*threshold-1)); if (count >= threshold) count -= max; bitCount += nbBits; } count--; /* extra accuracy */ remaining -= FSE_abs(count); normalizedCounter[charnum++] = count; previous0 = !count; while (remaining < threshold) { nbBits--; threshold >>= 1; } if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) { ip += bitCount>>3; bitCount &= 7; } else { bitCount -= (int)(8 * (iend - 4 - ip)); ip = iend - 4; } bitStream = MEM_readLE32(ip) >> (bitCount & 31); } } if (remaining != 1) return ERROR(GENERIC); *maxSVPtr = charnum-1; ip += (bitCount+7)>>3; if ((size_t)(ip-istart) > hbSize) return ERROR(srcSize_wrong); return ip-istart; } /*-************************************************************** * Counting histogram ****************************************************************/ /*! FSE_count_simple This function just counts byte values within @src, and store the histogram into @count. This function is unsafe : it doesn't check that all values within @src can fit into @count. For this reason, prefer using a table @count with 256 elements. @return : highest count for a single element */ static size_t FSE_count_simple(unsigned* count, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize) { const BYTE* ip = (const BYTE*)src; const BYTE* const end = ip + srcSize; unsigned maxSymbolValue = *maxSymbolValuePtr; unsigned max=0; U32 s; memset(count, 0, (maxSymbolValue+1)*sizeof(*count)); if (srcSize==0) { *maxSymbolValuePtr = 0; return 0; } while (ip max) max = count[s]; return (size_t)max; } static size_t FSE_count_parallel(unsigned* count, unsigned* maxSymbolValuePtr, const void* source, size_t sourceSize, unsigned checkMax) { const BYTE* ip = (const BYTE*)source; const BYTE* const iend = ip+sourceSize; unsigned maxSymbolValue = *maxSymbolValuePtr; unsigned max=0; U32 s; U32 Counting1[256] = { 0 }; U32 Counting2[256] = { 0 }; U32 Counting3[256] = { 0 }; U32 Counting4[256] = { 0 }; /* safety checks */ if (!sourceSize) { memset(count, 0, maxSymbolValue + 1); *maxSymbolValuePtr = 0; return 0; } if (!maxSymbolValue) maxSymbolValue = 255; /* 0 == default */ { /* by stripes of 16 bytes */ U32 cached = MEM_read32(ip); ip += 4; while (ip < iend-15) { U32 c = cached; cached = MEM_read32(ip); ip += 4; Counting1[(BYTE) c ]++; Counting2[(BYTE)(c>>8) ]++; Counting3[(BYTE)(c>>16)]++; Counting4[ c>>24 ]++; c = cached; cached = MEM_read32(ip); ip += 4; Counting1[(BYTE) c ]++; Counting2[(BYTE)(c>>8) ]++; Counting3[(BYTE)(c>>16)]++; Counting4[ c>>24 ]++; c = cached; cached = MEM_read32(ip); ip += 4; Counting1[(BYTE) c ]++; Counting2[(BYTE)(c>>8) ]++; Counting3[(BYTE)(c>>16)]++; Counting4[ c>>24 ]++; c = cached; cached = MEM_read32(ip); ip += 4; Counting1[(BYTE) c ]++; Counting2[(BYTE)(c>>8) ]++; Counting3[(BYTE)(c>>16)]++; Counting4[ c>>24 ]++; } ip-=4; } /* finish last symbols */ while (ipmaxSymbolValue; s--) { Counting1[s] += Counting2[s] + Counting3[s] + Counting4[s]; if (Counting1[s]) return ERROR(maxSymbolValue_tooSmall); } } for (s=0; s<=maxSymbolValue; s++) { count[s] = Counting1[s] + Counting2[s] + Counting3[s] + Counting4[s]; if (count[s] > max) max = count[s]; } while (!count[maxSymbolValue]) maxSymbolValue--; *maxSymbolValuePtr = maxSymbolValue; return (size_t)max; } /* fast variant (unsafe : won't check if src contains values beyond count[] limit) */ size_t FSE_countFast(unsigned* count, unsigned* maxSymbolValuePtr, const void* source, size_t sourceSize) { if (sourceSize < 1500) return FSE_count_simple(count, maxSymbolValuePtr, source, sourceSize); return FSE_count_parallel(count, maxSymbolValuePtr, source, sourceSize, 0); } size_t FSE_count(unsigned* count, unsigned* maxSymbolValuePtr, const void* source, size_t sourceSize) { if (*maxSymbolValuePtr <255) return FSE_count_parallel(count, maxSymbolValuePtr, source, sourceSize, 1); *maxSymbolValuePtr = 255; return FSE_countFast(count, maxSymbolValuePtr, source, sourceSize); } /*-************************************************************** * FSE Compression Code ****************************************************************/ /*! FSE_CTable is a variable size structure which contains : U16 tableLog; U16 maxSymbolValue; U16 nextStateNumber[1 << tableLog]; // This size is variable FSE_symbolCompressionTransform symbolTT[maxSymbolValue+1]; // This size is variable Allocation is manual, since C standard does not support variable-size structures. */ size_t FSE_sizeof_CTable (unsigned maxSymbolValue, unsigned tableLog) { size_t size; FSE_STATIC_ASSERT((size_t)FSE_CTABLE_SIZE_U32(FSE_MAX_TABLELOG, FSE_MAX_SYMBOL_VALUE)*4 >= sizeof(CTable_max_t)); /* A compilation error here means FSE_CTABLE_SIZE_U32 is not large enough */ if (tableLog > FSE_MAX_TABLELOG) return ERROR(GENERIC); size = FSE_CTABLE_SIZE_U32 (tableLog, maxSymbolValue) * sizeof(U32); return size; } FSE_CTable* FSE_createCTable (unsigned maxSymbolValue, unsigned tableLog) { size_t size; if (tableLog > FSE_TABLELOG_ABSOLUTE_MAX) tableLog = FSE_TABLELOG_ABSOLUTE_MAX; size = FSE_CTABLE_SIZE_U32 (tableLog, maxSymbolValue) * sizeof(U32); return (FSE_CTable*)malloc(size); } void FSE_freeCTable (FSE_CTable* ct) { free(ct); } /* provides the minimum logSize to safely represent a distribution */ static unsigned FSE_minTableLog(size_t srcSize, unsigned maxSymbolValue) { U32 minBitsSrc = BIT_highbit32((U32)(srcSize - 1)) + 1; U32 minBitsSymbols = BIT_highbit32(maxSymbolValue) + 2; U32 minBits = minBitsSrc < minBitsSymbols ? minBitsSrc : minBitsSymbols; return minBits; } unsigned FSE_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue) { U32 maxBitsSrc = BIT_highbit32((U32)(srcSize - 1)) - 2; U32 tableLog = maxTableLog; U32 minBits = FSE_minTableLog(srcSize, maxSymbolValue); if (tableLog==0) tableLog = FSE_DEFAULT_TABLELOG; if (maxBitsSrc < tableLog) tableLog = maxBitsSrc; /* Accuracy can be reduced */ if (minBits > tableLog) tableLog = minBits; /* Need a minimum to safely represent all symbol values */ if (tableLog < FSE_MIN_TABLELOG) tableLog = FSE_MIN_TABLELOG; if (tableLog > FSE_MAX_TABLELOG) tableLog = FSE_MAX_TABLELOG; return tableLog; } /* Secondary normalization method. To be used when primary method fails. */ static size_t FSE_normalizeM2(short* norm, U32 tableLog, const unsigned* count, size_t total, U32 maxSymbolValue) { U32 s; U32 distributed = 0; U32 ToDistribute; /* Init */ U32 lowThreshold = (U32)(total >> tableLog); U32 lowOne = (U32)((total * 3) >> (tableLog + 1)); for (s=0; s<=maxSymbolValue; s++) { if (count[s] == 0) { norm[s]=0; continue; } if (count[s] <= lowThreshold) { norm[s] = -1; distributed++; total -= count[s]; continue; } if (count[s] <= lowOne) { norm[s] = 1; distributed++; total -= count[s]; continue; } norm[s]=-2; } ToDistribute = (1 << tableLog) - distributed; if ((total / ToDistribute) > lowOne) { /* risk of rounding to zero */ lowOne = (U32)((total * 3) / (ToDistribute * 2)); for (s=0; s<=maxSymbolValue; s++) { if ((norm[s] == -2) && (count[s] <= lowOne)) { norm[s] = 1; distributed++; total -= count[s]; continue; } } ToDistribute = (1 << tableLog) - distributed; } if (distributed == maxSymbolValue+1) { /* all values are pretty poor; probably incompressible data (should have already been detected); find max, then give all remaining points to max */ U32 maxV = 0, maxC =0; for (s=0; s<=maxSymbolValue; s++) if (count[s] > maxC) maxV=s, maxC=count[s]; norm[maxV] += (short)ToDistribute; return 0; } { U64 const vStepLog = 62 - tableLog; U64 const mid = (1ULL << (vStepLog-1)) - 1; U64 const rStep = ((((U64)1<> vStepLog); U32 sEnd = (U32)(end >> vStepLog); U32 weight = sEnd - sStart; if (weight < 1) return ERROR(GENERIC); norm[s] = (short)weight; tmpTotal = end; } } } return 0; } size_t FSE_normalizeCount (short* normalizedCounter, unsigned tableLog, const unsigned* count, size_t total, unsigned maxSymbolValue) { /* Sanity checks */ if (tableLog==0) tableLog = FSE_DEFAULT_TABLELOG; if (tableLog < FSE_MIN_TABLELOG) return ERROR(GENERIC); /* Unsupported size */ if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge); /* Unsupported size */ if (tableLog < FSE_minTableLog(total, maxSymbolValue)) return ERROR(GENERIC); /* Too small tableLog, compression potentially impossible */ { U32 const rtbTable[] = { 0, 473195, 504333, 520860, 550000, 700000, 750000, 830000 }; U64 const scale = 62 - tableLog; U64 const step = ((U64)1<<62) / total; /* <== here, one division ! */ U64 const vStep = 1ULL<<(scale-20); int stillToDistribute = 1<> tableLog); for (s=0; s<=maxSymbolValue; s++) { if (count[s] == total) return 0; /* rle special case */ if (count[s] == 0) { normalizedCounter[s]=0; continue; } if (count[s] <= lowThreshold) { normalizedCounter[s] = -1; stillToDistribute--; } else { short proba = (short)((count[s]*step) >> scale); if (proba<8) { U64 restToBeat = vStep * rtbTable[proba]; proba += (count[s]*step) - ((U64)proba< restToBeat; } if (proba > largestP) largestP=proba, largest=s; normalizedCounter[s] = proba; stillToDistribute -= proba; } } if (-stillToDistribute >= (normalizedCounter[largest] >> 1)) { /* corner case, need another normalization method */ size_t errorCode = FSE_normalizeM2(normalizedCounter, tableLog, count, total, maxSymbolValue); if (FSE_isError(errorCode)) return errorCode; } else normalizedCounter[largest] += (short)stillToDistribute; } #if 0 { /* Print Table (debug) */ U32 s; U32 nTotal = 0; for (s=0; s<=maxSymbolValue; s++) printf("%3i: %4i \n", s, normalizedCounter[s]); for (s=0; s<=maxSymbolValue; s++) nTotal += abs(normalizedCounter[s]); if (nTotal != (1U<>1); /* assumption : tableLog >= 1 */ FSE_symbolCompressionTransform* const symbolTT = (FSE_symbolCompressionTransform*) (FSCT); unsigned s; /* Sanity checks */ if (nbBits < 1) return ERROR(GENERIC); /* min size */ /* header */ tableU16[-2] = (U16) nbBits; tableU16[-1] = (U16) maxSymbolValue; /* Build table */ for (s=0; s FSE_MAX_TABLELOG*4+7 ) && (srcSize & 2)) { /* test bit 2 */ FSE_encodeSymbol(&bitC, &CState2, *--ip); FSE_encodeSymbol(&bitC, &CState1, *--ip); FSE_FLUSHBITS(&bitC); } /* 2 or 4 encoding per loop */ for ( ; ip>istart ; ) { FSE_encodeSymbol(&bitC, &CState2, *--ip); if (sizeof(bitC.bitContainer)*8 < FSE_MAX_TABLELOG*2+7 ) /* this test must be static */ FSE_FLUSHBITS(&bitC); FSE_encodeSymbol(&bitC, &CState1, *--ip); if (sizeof(bitC.bitContainer)*8 > FSE_MAX_TABLELOG*4+7 ) { /* this test must be static */ FSE_encodeSymbol(&bitC, &CState2, *--ip); FSE_encodeSymbol(&bitC, &CState1, *--ip); } FSE_FLUSHBITS(&bitC); } FSE_flushCState(&bitC, &CState2); FSE_flushCState(&bitC, &CState1); return BIT_closeCStream(&bitC); } size_t FSE_compress_usingCTable (void* dst, size_t dstSize, const void* src, size_t srcSize, const FSE_CTable* ct) { const unsigned fast = (dstSize >= FSE_BLOCKBOUND(srcSize)); if (fast) return FSE_compress_usingCTable_generic(dst, dstSize, src, srcSize, ct, 1); else return FSE_compress_usingCTable_generic(dst, dstSize, src, srcSize, ct, 0); } size_t FSE_compressBound(size_t size) { return FSE_COMPRESSBOUND(size); } size_t FSE_compress2 (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog) { const BYTE* const istart = (const BYTE*) src; const BYTE* ip = istart; BYTE* const ostart = (BYTE*) dst; BYTE* op = ostart; BYTE* const oend = ostart + dstSize; U32 count[FSE_MAX_SYMBOL_VALUE+1]; S16 norm[FSE_MAX_SYMBOL_VALUE+1]; CTable_max_t ct; size_t errorCode; /* init conditions */ if (srcSize <= 1) return 0; /* Uncompressible */ if (!maxSymbolValue) maxSymbolValue = FSE_MAX_SYMBOL_VALUE; if (!tableLog) tableLog = FSE_DEFAULT_TABLELOG; /* Scan input and build symbol stats */ errorCode = FSE_count (count, &maxSymbolValue, ip, srcSize); if (FSE_isError(errorCode)) return errorCode; if (errorCode == srcSize) return 1; if (errorCode == 1) return 0; /* each symbol only present once */ if (errorCode < (srcSize >> 7)) return 0; /* Heuristic : not compressible enough */ tableLog = FSE_optimalTableLog(tableLog, srcSize, maxSymbolValue); errorCode = FSE_normalizeCount (norm, tableLog, count, srcSize, maxSymbolValue); if (FSE_isError(errorCode)) return errorCode; /* Write table description header */ errorCode = FSE_writeNCount (op, oend-op, norm, maxSymbolValue, tableLog); if (FSE_isError(errorCode)) return errorCode; op += errorCode; /* Compress */ errorCode = FSE_buildCTable (ct, norm, maxSymbolValue, tableLog); if (FSE_isError(errorCode)) return errorCode; errorCode = FSE_compress_usingCTable(op, oend - op, ip, srcSize, ct); if (errorCode == 0) return 0; /* not enough space for compressed data */ op += errorCode; /* check compressibility */ if ( (size_t)(op-ostart) >= srcSize-1 ) return 0; return op-ostart; } size_t FSE_compress (void* dst, size_t dstSize, const void* src, size_t srcSize) { return FSE_compress2(dst, dstSize, src, (U32)srcSize, FSE_MAX_SYMBOL_VALUE, FSE_DEFAULT_TABLELOG); } /*-******************************************************* * Decompression (Byte symbols) *********************************************************/ size_t FSE_buildDTable_rle (FSE_DTable* dt, BYTE symbolValue) { void* ptr = dt; FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr; void* dPtr = dt + 1; FSE_decode_t* const cell = (FSE_decode_t*)dPtr; DTableH->tableLog = 0; DTableH->fastMode = 0; cell->newState = 0; cell->symbol = symbolValue; cell->nbBits = 0; return 0; } size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits) { void* ptr = dt; FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr; void* dPtr = dt + 1; FSE_decode_t* const dinfo = (FSE_decode_t*)dPtr; const unsigned tableSize = 1 << nbBits; const unsigned tableMask = tableSize - 1; const unsigned maxSymbolValue = tableMask; unsigned s; /* Sanity checks */ if (nbBits < 1) return ERROR(GENERIC); /* min size */ /* Build Decoding Table */ DTableH->tableLog = (U16)nbBits; DTableH->fastMode = 1; for (s=0; s<=maxSymbolValue; s++) { dinfo[s].newState = 0; dinfo[s].symbol = (BYTE)s; dinfo[s].nbBits = (BYTE)nbBits; } return 0; } FORCE_INLINE size_t FSE_decompress_usingDTable_generic( void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const FSE_DTable* dt, const unsigned fast) { BYTE* const ostart = (BYTE*) dst; BYTE* op = ostart; BYTE* const omax = op + maxDstSize; BYTE* const olimit = omax-3; BIT_DStream_t bitD; FSE_DState_t state1; FSE_DState_t state2; size_t errorCode; /* Init */ errorCode = BIT_initDStream(&bitD, cSrc, cSrcSize); /* replaced last arg by maxCompressed Size */ if (FSE_isError(errorCode)) return errorCode; FSE_initDState(&state1, &bitD, dt); FSE_initDState(&state2, &bitD, dt); #define FSE_GETSYMBOL(statePtr) fast ? FSE_decodeSymbolFast(statePtr, &bitD) : FSE_decodeSymbol(statePtr, &bitD) /* 4 symbols per loop */ for ( ; (BIT_reloadDStream(&bitD)==BIT_DStream_unfinished) && (op sizeof(bitD.bitContainer)*8) /* This test must be static */ BIT_reloadDStream(&bitD); op[1] = FSE_GETSYMBOL(&state2); if (FSE_MAX_TABLELOG*4+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */ { if (BIT_reloadDStream(&bitD) > BIT_DStream_unfinished) { op+=2; break; } } op[2] = FSE_GETSYMBOL(&state1); if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */ BIT_reloadDStream(&bitD); op[3] = FSE_GETSYMBOL(&state2); } /* tail */ /* note : BIT_reloadDStream(&bitD) >= FSE_DStream_partiallyFilled; Ends at exactly BIT_DStream_completed */ while (1) { if ( (BIT_reloadDStream(&bitD)>BIT_DStream_completed) || (op==omax) || (BIT_endOfDStream(&bitD) && (fast || FSE_endOfDState(&state1))) ) break; *op++ = FSE_GETSYMBOL(&state1); if ( (BIT_reloadDStream(&bitD)>BIT_DStream_completed) || (op==omax) || (BIT_endOfDStream(&bitD) && (fast || FSE_endOfDState(&state2))) ) break; *op++ = FSE_GETSYMBOL(&state2); } /* end ? */ if (BIT_endOfDStream(&bitD) && FSE_endOfDState(&state1) && FSE_endOfDState(&state2)) return op-ostart; if (op==omax) return ERROR(dstSize_tooSmall); /* dst buffer is full, but cSrc unfinished */ return ERROR(corruption_detected); } size_t FSE_decompress_usingDTable(void* dst, size_t originalSize, const void* cSrc, size_t cSrcSize, const FSE_DTable* dt) { const void* ptr = dt; const FSE_DTableHeader* DTableH = (const FSE_DTableHeader*)ptr; const U32 fastMode = DTableH->fastMode; /* select fast mode (static) */ if (fastMode) return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1); return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0); } size_t FSE_decompress(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize) { const BYTE* const istart = (const BYTE*)cSrc; const BYTE* ip = istart; short counting[FSE_MAX_SYMBOL_VALUE+1]; DTable_max_t dt; /* Static analyzer seems unable to understand this table will be properly initialized later */ unsigned tableLog; unsigned maxSymbolValue = FSE_MAX_SYMBOL_VALUE; size_t errorCode; if (cSrcSize<2) return ERROR(srcSize_wrong); /* too small input size */ /* normal FSE decoding mode */ errorCode = FSE_readNCount (counting, &maxSymbolValue, &tableLog, istart, cSrcSize); if (FSE_isError(errorCode)) return errorCode; if (errorCode >= cSrcSize) return ERROR(srcSize_wrong); /* too small input size */ ip += errorCode; cSrcSize -= errorCode; errorCode = FSE_buildDTable (dt, counting, maxSymbolValue, tableLog); if (FSE_isError(errorCode)) return errorCode; /* always return, even if it is an error code */ return FSE_decompress_usingDTable (dst, maxDstSize, ip, cSrcSize, dt); } #endif /* FSE_COMMONDEFS_ONLY */ zstd-0.5.1/lib/fse.h000066400000000000000000000342511266132244200142040ustar00rootroot00000000000000/* ****************************************************************** FSE : Finite State Entropy coder header file Copyright (C) 2013-2015, Yann Collet. BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. You can contact the author at : - Source repository : https://github.com/Cyan4973/FiniteStateEntropy - Public forum : https://groups.google.com/forum/#!forum/lz4c ****************************************************************** */ #ifndef FSE_H #define FSE_H #if defined (__cplusplus) extern "C" { #endif /* ***************************************** * Includes ******************************************/ #include /* size_t, ptrdiff_t */ /*-**************************************** * FSE simple functions ******************************************/ size_t FSE_compress(void* dst, size_t maxDstSize, const void* src, size_t srcSize); size_t FSE_decompress(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize); /*! FSE_compress(): Compress content of buffer 'src', of size 'srcSize', into destination buffer 'dst'. 'dst' buffer must be already allocated. Compression runs faster is maxDstSize >= FSE_compressBound(srcSize) return : size of compressed data (<= maxDstSize) Special values : if return == 0, srcData is not compressible => Nothing is stored within dst !!! if return == 1, srcData is a single byte symbol * srcSize times. Use RLE compression instead. if FSE_isError(return), compression failed (more details using FSE_getErrorName()) FSE_decompress(): Decompress FSE data from buffer 'cSrc', of size 'cSrcSize', into already allocated destination buffer 'dst', of size 'maxDstSize'. return : size of regenerated data (<= maxDstSize) or an error code, which can be tested using FSE_isError() ** Important ** : FSE_decompress() doesn't decompress non-compressible nor RLE data !!! Why ? : making this distinction requires a header. Header management is intentionally delegated to the user layer, which can better manage special cases. */ /* ***************************************** * Tool functions ******************************************/ size_t FSE_compressBound(size_t size); /* maximum compressed size */ /* Error Management */ unsigned FSE_isError(size_t code); /* tells if a return value is an error code */ const char* FSE_getErrorName(size_t code); /* provides error code string (useful for debugging) */ /* ***************************************** * FSE advanced functions ******************************************/ /*! FSE_compress2(): Same as FSE_compress(), but allows the selection of 'maxSymbolValue' and 'tableLog' Both parameters can be defined as '0' to mean : use default value return : size of compressed data Special values : if return == 0, srcData is not compressible => Nothing is stored within cSrc !!! if return == 1, srcData is a single byte symbol * srcSize times. Use RLE compression. if FSE_isError(return), it's an error code. */ size_t FSE_compress2 (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog); /* ***************************************** * FSE detailed API ******************************************/ /*! FSE_compress() does the following: 1. count symbol occurrence from source[] into table count[] 2. normalize counters so that sum(count[]) == Power_of_2 (2^tableLog) 3. save normalized counters to memory buffer using writeNCount() 4. build encoding table 'CTable' from normalized counters 5. encode the data stream using encoding table 'CTable' FSE_decompress() does the following: 1. read normalized counters with readNCount() 2. build decoding table 'DTable' from normalized counters 3. decode the data stream using decoding table 'DTable' The following API allows targeting specific sub-functions for advanced tasks. For example, it's possible to compress several blocks using the same 'CTable', or to save and provide normalized distribution using external method. */ /* *** COMPRESSION *** */ /*! FSE_count(): Provides the precise count of each byte within a table 'count' 'count' is a table of unsigned int, of minimum size (*maxSymbolValuePtr+1). *maxSymbolValuePtr will be updated if detected smaller than initial value. @return : the count of the most frequent symbol (which is not identified) if return == srcSize, there is only one symbol. Can also return an error code, which can be tested with FSE_isError() */ size_t FSE_count(unsigned* count, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize); /*! FSE_optimalTableLog(): dynamically downsize 'tableLog' when conditions are met. It saves CPU time, by using smaller tables, while preserving or even improving compression ratio. return : recommended tableLog (necessarily <= initial 'tableLog') */ unsigned FSE_optimalTableLog(unsigned tableLog, size_t srcSize, unsigned maxSymbolValue); /*! FSE_normalizeCount(): normalize counters so that sum(count[]) == Power_of_2 (2^tableLog) 'normalizedCounter' is a table of short, of minimum size (maxSymbolValue+1). return : tableLog, or an errorCode, which can be tested using FSE_isError() */ size_t FSE_normalizeCount(short* normalizedCounter, unsigned tableLog, const unsigned* count, size_t srcSize, unsigned maxSymbolValue); /*! FSE_NCountWriteBound(): Provides the maximum possible size of an FSE normalized table, given 'maxSymbolValue' and 'tableLog' Typically useful for allocation purpose. */ size_t FSE_NCountWriteBound(unsigned maxSymbolValue, unsigned tableLog); /*! FSE_writeNCount(): Compactly save 'normalizedCounter' into 'buffer'. return : size of the compressed table or an errorCode, which can be tested using FSE_isError() */ size_t FSE_writeNCount (void* buffer, size_t bufferSize, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog); /*! Constructor and Destructor of type FSE_CTable Note that its size depends on 'tableLog' and 'maxSymbolValue' */ typedef unsigned FSE_CTable; /* don't allocate that. It's only meant to be more restrictive than void* */ FSE_CTable* FSE_createCTable (unsigned tableLog, unsigned maxSymbolValue); void FSE_freeCTable (FSE_CTable* ct); /*! FSE_buildCTable(): Builds @ct, which must be already allocated, using FSE_createCTable() return : 0 or an errorCode, which can be tested using FSE_isError() */ size_t FSE_buildCTable(FSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog); /*! FSE_compress_usingCTable(): Compress @src using @ct into @dst which must be already allocated return : size of compressed data (<= @dstCapacity) or 0 if compressed data could not fit into @dst or an errorCode, which can be tested using FSE_isError() */ size_t FSE_compress_usingCTable (void* dst, size_t dstCapacity, const void* src, size_t srcSize, const FSE_CTable* ct); /*! Tutorial : ---------- The first step is to count all symbols. FSE_count() does this job very fast. Result will be saved into 'count', a table of unsigned int, which must be already allocated, and have 'maxSymbolValuePtr[0]+1' cells. 'src' is a table of bytes of size 'srcSize'. All values within 'src' MUST be <= maxSymbolValuePtr[0] maxSymbolValuePtr[0] will be updated, with its real value (necessarily <= original value) FSE_count() will return the number of occurrence of the most frequent symbol. This can be used to know if there is a single symbol within 'src', and to quickly evaluate its compressibility. If there is an error, the function will return an ErrorCode (which can be tested using FSE_isError()). The next step is to normalize the frequencies. FSE_normalizeCount() will ensure that sum of frequencies is == 2 ^'tableLog'. It also guarantees a minimum of 1 to any Symbol with frequency >= 1. You can use 'tableLog'==0 to mean "use default tableLog value". If you are unsure of which tableLog value to use, you can ask FSE_optimalTableLog(), which will provide the optimal valid tableLog given sourceSize, maxSymbolValue, and a user-defined maximum (0 means "default"). The result of FSE_normalizeCount() will be saved into a table, called 'normalizedCounter', which is a table of signed short. 'normalizedCounter' must be already allocated, and have at least 'maxSymbolValue+1' cells. The return value is tableLog if everything proceeded as expected. It is 0 if there is a single symbol within distribution. If there is an error (ex: invalid tableLog value), the function will return an ErrorCode (which can be tested using FSE_isError()). 'normalizedCounter' can be saved in a compact manner to a memory area using FSE_writeNCount(). 'buffer' must be already allocated. For guaranteed success, buffer size must be at least FSE_headerBound(). The result of the function is the number of bytes written into 'buffer'. If there is an error, the function will return an ErrorCode (which can be tested using FSE_isError(); ex : buffer size too small). 'normalizedCounter' can then be used to create the compression table 'CTable'. The space required by 'CTable' must be already allocated, using FSE_createCTable(). You can then use FSE_buildCTable() to fill 'CTable'. If there is an error, both functions will return an ErrorCode (which can be tested using FSE_isError()). 'CTable' can then be used to compress 'src', with FSE_compress_usingCTable(). Similar to FSE_count(), the convention is that 'src' is assumed to be a table of char of size 'srcSize' The function returns the size of compressed data (without header), necessarily <= @dstCapacity. If it returns '0', compressed data could not fit into 'dst'. If there is an error, the function will return an ErrorCode (which can be tested using FSE_isError()). */ /* *** DECOMPRESSION *** */ /*! FSE_readNCount(): Read compactly saved 'normalizedCounter' from 'rBuffer'. return : size read from 'rBuffer' or an errorCode, which can be tested using FSE_isError() maxSymbolValuePtr[0] and tableLogPtr[0] will also be updated with their respective values */ size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSymbolValuePtr, unsigned* tableLogPtr, const void* rBuffer, size_t rBuffSize); /*! Constructor and Destructor of type FSE_DTable Note that its size depends on 'tableLog' */ typedef unsigned FSE_DTable; /* don't allocate that. It's just a way to be more restrictive than void* */ FSE_DTable* FSE_createDTable(unsigned tableLog); void FSE_freeDTable(FSE_DTable* dt); /*! FSE_buildDTable(): Builds 'dt', which must be already allocated, using FSE_createDTable() return : 0, or an errorCode, which can be tested using FSE_isError() */ size_t FSE_buildDTable (FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog); /*! FSE_decompress_usingDTable(): Decompress compressed source @cSrc of size @cSrcSize using @dt into @dst which must be already allocated. return : size of regenerated data (necessarily <= @dstCapacity) or an errorCode, which can be tested using FSE_isError() */ size_t FSE_decompress_usingDTable(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, const FSE_DTable* dt); /*! Tutorial : ---------- (Note : these functions only decompress FSE-compressed blocks. If block is uncompressed, use memcpy() instead If block is a single repeated byte, use memset() instead ) The first step is to obtain the normalized frequencies of symbols. This can be performed by FSE_readNCount() if it was saved using FSE_writeNCount(). 'normalizedCounter' must be already allocated, and have at least 'maxSymbolValuePtr[0]+1' cells of signed short. In practice, that means it's necessary to know 'maxSymbolValue' beforehand, or size the table to handle worst case situations (typically 256). FSE_readNCount() will provide 'tableLog' and 'maxSymbolValue'. The result of FSE_readNCount() is the number of bytes read from 'rBuffer'. Note that 'rBufferSize' must be at least 4 bytes, even if useful information is less than that. If there is an error, the function will return an error code, which can be tested using FSE_isError(). The next step is to build the decompression tables 'FSE_DTable' from 'normalizedCounter'. This is performed by the function FSE_buildDTable(). The space required by 'FSE_DTable' must be already allocated using FSE_createDTable(). If there is an error, the function will return an error code, which can be tested using FSE_isError(). 'FSE_DTable' can then be used to decompress 'cSrc', with FSE_decompress_usingDTable(). 'cSrcSize' must be strictly correct, otherwise decompression will fail. FSE_decompress_usingDTable() result will tell how many bytes were regenerated (<=maxDstSize). If there is an error, the function will return an error code, which can be tested using FSE_isError(). (ex: dst buffer too small) */ #if defined (__cplusplus) } #endif #endif /* FSE_H */ zstd-0.5.1/lib/fse_static.h000066400000000000000000000323521266132244200155530ustar00rootroot00000000000000/* ****************************************************************** FSE : Finite State Entropy coder header file for static linking (only) Copyright (C) 2013-2015, Yann Collet BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. You can contact the author at : - Source repository : https://github.com/Cyan4973/FiniteStateEntropy - Public forum : https://groups.google.com/forum/#!forum/lz4c ****************************************************************** */ #ifndef FSE_STATIC_H #define FSE_STATIC_H #if defined (__cplusplus) extern "C" { #endif /* ***************************************** * Dependencies *******************************************/ #include "fse.h" #include "bitstream.h" /* ***************************************** * Static allocation *******************************************/ /* FSE buffer bounds */ #define FSE_NCOUNTBOUND 512 #define FSE_BLOCKBOUND(size) (size + (size>>7)) #define FSE_COMPRESSBOUND(size) (FSE_NCOUNTBOUND + FSE_BLOCKBOUND(size)) /* Macro version, useful for static allocation */ /* It is possible to statically allocate FSE CTable/DTable as a table of unsigned using below macros */ #define FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) (1 + (1<<(maxTableLog-1)) + ((maxSymbolValue+1)*2)) #define FSE_DTABLE_SIZE_U32(maxTableLog) (1 + (1<= BIT_DStream_completed When it's done, verify decompression is fully completed, by checking both DStream and the relevant states. Checking if DStream has reached its end is performed by : BIT_endOfDStream(&DStream); Check also the states. There might be some symbols left there, if some high probability ones (>50%) are possible. FSE_endOfDState(&DState); */ /* ***************************************** * FSE unsafe API *******************************************/ static unsigned char FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD); /* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */ /* ***************************************** * Implementation of inlined functions *******************************************/ typedef struct { int deltaFindState; U32 deltaNbBits; } FSE_symbolCompressionTransform; /* total 8 bytes */ MEM_STATIC void FSE_initCState(FSE_CState_t* statePtr, const FSE_CTable* ct) { const void* ptr = ct; const U16* u16ptr = (const U16*) ptr; const U32 tableLog = MEM_read16(ptr); statePtr->value = (ptrdiff_t)1<stateTable = u16ptr+2; statePtr->symbolTT = ((const U32*)ct + 1 + (tableLog ? (1<<(tableLog-1)) : 1)); statePtr->stateLog = tableLog; } MEM_STATIC void FSE_initCState2(FSE_CState_t* statePtr, const FSE_CTable* ct, U32 symbol) { FSE_initCState(statePtr, ct); { const FSE_symbolCompressionTransform symbolTT = ((const FSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol]; const U16* stateTable = (const U16*)(statePtr->stateTable); U32 nbBitsOut = (U32)((symbolTT.deltaNbBits + (1<<15)) >> 16); statePtr->value = (nbBitsOut << 16) - symbolTT.deltaNbBits; statePtr->value = stateTable[(statePtr->value >> nbBitsOut) + symbolTT.deltaFindState]; } } MEM_STATIC void FSE_encodeSymbol(BIT_CStream_t* bitC, FSE_CState_t* statePtr, U32 symbol) { const FSE_symbolCompressionTransform symbolTT = ((const FSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol]; const U16* const stateTable = (const U16*)(statePtr->stateTable); U32 nbBitsOut = (U32)((statePtr->value + symbolTT.deltaNbBits) >> 16); BIT_addBits(bitC, statePtr->value, nbBitsOut); statePtr->value = stateTable[ (statePtr->value >> nbBitsOut) + symbolTT.deltaFindState]; } MEM_STATIC void FSE_flushCState(BIT_CStream_t* bitC, const FSE_CState_t* statePtr) { BIT_addBits(bitC, statePtr->value, statePtr->stateLog); BIT_flushBits(bitC); } /* decompression */ typedef struct { U16 tableLog; U16 fastMode; } FSE_DTableHeader; /* sizeof U32 */ typedef struct { unsigned short newState; unsigned char symbol; unsigned char nbBits; } FSE_decode_t; /* size == U32 */ MEM_STATIC void FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt) { const void* ptr = dt; const FSE_DTableHeader* const DTableH = (const FSE_DTableHeader*)ptr; DStatePtr->state = BIT_readBits(bitD, DTableH->tableLog); BIT_reloadDStream(bitD); DStatePtr->table = dt + 1; } MEM_STATIC size_t FSE_getStateValue(FSE_DState_t* DStatePtr) { return DStatePtr->state; } MEM_STATIC BYTE FSE_peakSymbol(FSE_DState_t* DStatePtr) { const FSE_decode_t DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state]; return DInfo.symbol; } MEM_STATIC BYTE FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD) { const FSE_decode_t DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state]; const U32 nbBits = DInfo.nbBits; BYTE symbol = DInfo.symbol; size_t lowBits = BIT_readBits(bitD, nbBits); DStatePtr->state = DInfo.newState + lowBits; return symbol; } MEM_STATIC BYTE FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD) { const FSE_decode_t DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state]; const U32 nbBits = DInfo.nbBits; BYTE symbol = DInfo.symbol; size_t lowBits = BIT_readBitsFast(bitD, nbBits); DStatePtr->state = DInfo.newState + lowBits; return symbol; } MEM_STATIC unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr) { return DStatePtr->state == 0; } #if defined (__cplusplus) } #endif #endif /* FSE_STATIC_H */ zstd-0.5.1/lib/huff0.c000066400000000000000000002015101266132244200144240ustar00rootroot00000000000000/* ****************************************************************** Huff0 : Huffman coder, part of New Generation Entropy library Copyright (C) 2013-2015, Yann Collet. BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. You can contact the author at : - FSE+Huff0 source repository : https://github.com/Cyan4973/FiniteStateEntropy - Public forum : https://groups.google.com/forum/#!forum/lz4c ****************************************************************** */ /* ************************************************************** * Compiler specifics ****************************************************************/ #if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) /* inline is defined */ #elif defined(_MSC_VER) # define inline __inline #else # define inline /* disable inline */ #endif #ifdef _MSC_VER /* Visual Studio */ # define FORCE_INLINE static __forceinline # pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ #else # ifdef __GNUC__ # define FORCE_INLINE static inline __attribute__((always_inline)) # else # define FORCE_INLINE static inline # endif #endif /* ************************************************************** * Includes ****************************************************************/ #include /* malloc, free, qsort */ #include /* memcpy, memset */ #include /* printf (debug) */ #include "huff0_static.h" #include "bitstream.h" #include "fse.h" /* header compression */ /* ************************************************************** * Constants ****************************************************************/ #define HUF_ABSOLUTEMAX_TABLELOG 16 /* absolute limit of HUF_MAX_TABLELOG. Beyond that value, code does not work */ #define HUF_MAX_TABLELOG 12 /* max configured tableLog (for static allocation); can be modified up to HUF_ABSOLUTEMAX_TABLELOG */ #define HUF_DEFAULT_TABLELOG HUF_MAX_TABLELOG /* tableLog by default, when not specified */ #define HUF_MAX_SYMBOL_VALUE 255 #if (HUF_MAX_TABLELOG > HUF_ABSOLUTEMAX_TABLELOG) # error "HUF_MAX_TABLELOG is too large !" #endif /* ************************************************************** * Error Management ****************************************************************/ unsigned HUF_isError(size_t code) { return ERR_isError(code); } const char* HUF_getErrorName(size_t code) { return ERR_getErrorName(code); } #define HUF_STATIC_ASSERT(c) { enum { HUF_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */ /* ******************************************************* * Huff0 : Huffman block compression *********************************************************/ struct HUF_CElt_s { U16 val; BYTE nbBits; }; /* typedef'd to HUF_CElt within huff0_static.h */ typedef struct nodeElt_s { U32 count; U16 parent; BYTE byte; BYTE nbBits; } nodeElt; /*! HUF_writeCTable() : @dst : destination buffer @CTable : huffman tree to save, using huff0 representation @return : size of saved CTable */ size_t HUF_writeCTable (void* dst, size_t maxDstSize, const HUF_CElt* CTable, U32 maxSymbolValue, U32 huffLog) { BYTE bitsToWeight[HUF_MAX_TABLELOG + 1]; BYTE huffWeight[HUF_MAX_SYMBOL_VALUE + 1]; U32 n; BYTE* op = (BYTE*)dst; size_t size; /* check conditions */ if (maxSymbolValue > HUF_MAX_SYMBOL_VALUE + 1) return ERROR(GENERIC); /* convert to weight */ bitsToWeight[0] = 0; for (n=1; n<=huffLog; n++) bitsToWeight[n] = (BYTE)(huffLog + 1 - n); for (n=0; n= 128) return ERROR(GENERIC); /* should never happen, since maxSymbolValue <= 255 */ if ((size <= 1) || (size >= maxSymbolValue/2)) { if (size==1) { /* RLE */ /* only possible case : serie of 1 (because there are at least 2) */ /* can only be 2^n or (2^n-1), otherwise not an huffman tree */ BYTE code; switch(maxSymbolValue) { case 1: code = 0; break; case 2: code = 1; break; case 3: code = 2; break; case 4: code = 3; break; case 7: code = 4; break; case 8: code = 5; break; case 15: code = 6; break; case 16: code = 7; break; case 31: code = 8; break; case 32: code = 9; break; case 63: code = 10; break; case 64: code = 11; break; case 127: code = 12; break; case 128: code = 13; break; default : return ERROR(corruption_detected); } op[0] = (BYTE)(255-13 + code); return 1; } /* Not compressible */ if (maxSymbolValue > (241-128)) return ERROR(GENERIC); /* not implemented (not possible with current format) */ if (((maxSymbolValue+1)/2) + 1 > maxDstSize) return ERROR(dstSize_tooSmall); /* not enough space within dst buffer */ op[0] = (BYTE)(128 /*special case*/ + 0 /* Not Compressible */ + (maxSymbolValue-1)); huffWeight[maxSymbolValue] = 0; /* to be sure it doesn't cause issue in final combination */ for (n=0; n HUF_MAX_TABLELOG) return ERROR(tableLog_tooLarge); if (nbSymbols > maxSymbolValue+1) return ERROR(maxSymbolValue_tooSmall); /* Prepare base value per rank */ nextRankStart = 0; for (n=1; n<=tableLog; n++) { U32 current = nextRankStart; nextRankStart += (rankVal[n] << (n-1)); rankVal[n] = current; } /* fill nbBits */ for (n=0; n0; n--) { valPerRank[n] = min; /* get starting value within each rank */ min += nbPerRank[n]; min >>= 1; } } for (n=0; n<=maxSymbolValue; n++) CTable[n].val = valPerRank[CTable[n].nbBits]++; /* assign value within rank, symbol order */ } return iSize; } static U32 HUF_setMaxHeight(nodeElt* huffNode, U32 lastNonNull, U32 maxNbBits) { int totalCost = 0; const U32 largestBits = huffNode[lastNonNull].nbBits; /* early exit : all is fine */ if (largestBits <= maxNbBits) return largestBits; /* there are several too large elements (at least >= 2) */ { const U32 baseCost = 1 << (largestBits - maxNbBits); U32 n = lastNonNull; while (huffNode[n].nbBits > maxNbBits) { totalCost += baseCost - (1 << (largestBits - huffNode[n].nbBits)); huffNode[n].nbBits = (BYTE)maxNbBits; n --; } /* n stops at huffNode[n].nbBits <= maxNbBits */ while (huffNode[n].nbBits == maxNbBits) n--; /* n end at index of smallest symbol using (maxNbBits-1) */ /* renorm totalCost */ totalCost >>= (largestBits - maxNbBits); /* note : totalCost is necessarily a multiple of baseCost */ /* repay normalized cost */ { const U32 noSymbol = 0xF0F0F0F0; U32 rankLast[HUF_MAX_TABLELOG+1]; U32 currentNbBits = maxNbBits; int pos; /* Get pos of last (smallest) symbol per rank */ memset(rankLast, 0xF0, sizeof(rankLast)); for (pos=n ; pos >= 0; pos--) { if (huffNode[pos].nbBits >= currentNbBits) continue; currentNbBits = huffNode[pos].nbBits; /* < maxNbBits */ rankLast[maxNbBits-currentNbBits] = pos; } while (totalCost > 0) { U32 nBitsToDecrease = BIT_highbit32(totalCost) + 1; for ( ; nBitsToDecrease > 1; nBitsToDecrease--) { U32 highPos = rankLast[nBitsToDecrease]; U32 lowPos = rankLast[nBitsToDecrease-1]; if (highPos == noSymbol) continue; if (lowPos == noSymbol) break; { U32 highTotal = huffNode[highPos].count; U32 lowTotal = 2 * huffNode[lowPos].count; if (highTotal <= lowTotal) break; } } /* only triggered when no more rank 1 symbol left => find closest one (note : there is necessarily at least one !) */ while ((nBitsToDecrease<=HUF_MAX_TABLELOG) && (rankLast[nBitsToDecrease] == noSymbol)) /* HUF_MAX_TABLELOG test just to please gcc 5+; but it should not be necessary */ nBitsToDecrease ++; totalCost -= 1 << (nBitsToDecrease-1); if (rankLast[nBitsToDecrease-1] == noSymbol) rankLast[nBitsToDecrease-1] = rankLast[nBitsToDecrease]; /* this rank is no longer empty */ huffNode[rankLast[nBitsToDecrease]].nbBits ++; if (rankLast[nBitsToDecrease] == 0) /* special case, reached largest symbol */ rankLast[nBitsToDecrease] = noSymbol; else { rankLast[nBitsToDecrease]--; if (huffNode[rankLast[nBitsToDecrease]].nbBits != maxNbBits-nBitsToDecrease) rankLast[nBitsToDecrease] = noSymbol; /* this rank is now empty */ } } while (totalCost < 0) { /* Sometimes, cost correction overshoot */ if (rankLast[1] == noSymbol) { /* special case : no rank 1 symbol (using maxNbBits-1); let's create one from largest rank 0 (using maxNbBits) */ while (huffNode[n].nbBits == maxNbBits) n--; huffNode[n+1].nbBits--; rankLast[1] = n+1; totalCost++; continue; } huffNode[ rankLast[1] + 1 ].nbBits--; rankLast[1]++; totalCost ++; } } } return maxNbBits; } typedef struct { U32 base; U32 current; } rankPos; static void HUF_sort(nodeElt* huffNode, const U32* count, U32 maxSymbolValue) { rankPos rank[32]; U32 n; memset(rank, 0, sizeof(rank)); for (n=0; n<=maxSymbolValue; n++) { U32 r = BIT_highbit32(count[n] + 1); rank[r].base ++; } for (n=30; n>0; n--) rank[n-1].base += rank[n].base; for (n=0; n<32; n++) rank[n].current = rank[n].base; for (n=0; n<=maxSymbolValue; n++) { U32 c = count[n]; U32 r = BIT_highbit32(c+1) + 1; U32 pos = rank[r].current++; while ((pos > rank[r].base) && (c > huffNode[pos-1].count)) huffNode[pos]=huffNode[pos-1], pos--; huffNode[pos].count = c; huffNode[pos].byte = (BYTE)n; } } #define STARTNODE (HUF_MAX_SYMBOL_VALUE+1) size_t HUF_buildCTable (HUF_CElt* tree, const U32* count, U32 maxSymbolValue, U32 maxNbBits) { nodeElt huffNode0[2*HUF_MAX_SYMBOL_VALUE+1 +1]; nodeElt* huffNode = huffNode0 + 1; U32 n, nonNullRank; int lowS, lowN; U16 nodeNb = STARTNODE; U32 nodeRoot; /* safety checks */ if (maxNbBits == 0) maxNbBits = HUF_DEFAULT_TABLELOG; if (maxSymbolValue > HUF_MAX_SYMBOL_VALUE) return ERROR(GENERIC); memset(huffNode0, 0, sizeof(huffNode0)); /* sort, decreasing order */ HUF_sort(huffNode, count, maxSymbolValue); /* init for parents */ nonNullRank = maxSymbolValue; while(huffNode[nonNullRank].count == 0) nonNullRank--; lowS = nonNullRank; nodeRoot = nodeNb + lowS - 1; lowN = nodeNb; huffNode[nodeNb].count = huffNode[lowS].count + huffNode[lowS-1].count; huffNode[lowS].parent = huffNode[lowS-1].parent = nodeNb; nodeNb++; lowS-=2; for (n=nodeNb; n<=nodeRoot; n++) huffNode[n].count = (U32)(1U<<30); huffNode0[0].count = (U32)(1U<<31); /* create parents */ while (nodeNb <= nodeRoot) { U32 n1 = (huffNode[lowS].count < huffNode[lowN].count) ? lowS-- : lowN++; U32 n2 = (huffNode[lowS].count < huffNode[lowN].count) ? lowS-- : lowN++; huffNode[nodeNb].count = huffNode[n1].count + huffNode[n2].count; huffNode[n1].parent = huffNode[n2].parent = nodeNb; nodeNb++; } /* distribute weights (unlimited tree height) */ huffNode[nodeRoot].nbBits = 0; for (n=nodeRoot-1; n>=STARTNODE; n--) huffNode[n].nbBits = huffNode[ huffNode[n].parent ].nbBits + 1; for (n=0; n<=nonNullRank; n++) huffNode[n].nbBits = huffNode[ huffNode[n].parent ].nbBits + 1; /* enforce maxTableLog */ maxNbBits = HUF_setMaxHeight(huffNode, nonNullRank, maxNbBits); /* fill result into tree (val, nbBits) */ { U16 nbPerRank[HUF_MAX_TABLELOG+1] = {0}; U16 valPerRank[HUF_MAX_TABLELOG+1] = {0}; if (maxNbBits > HUF_MAX_TABLELOG) return ERROR(GENERIC); /* check fit into table */ for (n=0; n<=nonNullRank; n++) nbPerRank[huffNode[n].nbBits]++; { /* determine stating value per rank */ U16 min = 0; for (n=maxNbBits; n>0; n--) { valPerRank[n] = min; /* get starting value within each rank */ min += nbPerRank[n]; min >>= 1; } } for (n=0; n<=maxSymbolValue; n++) tree[huffNode[n].byte].nbBits = huffNode[n].nbBits; /* push nbBits per symbol, symbol order */ for (n=0; n<=maxSymbolValue; n++) tree[n].val = valPerRank[tree[n].nbBits]++; /* assign value within rank, symbol order */ } return maxNbBits; } static void HUF_encodeSymbol(BIT_CStream_t* bitCPtr, U32 symbol, const HUF_CElt* CTable) { BIT_addBitsFast(bitCPtr, CTable[symbol].val, CTable[symbol].nbBits); } size_t HUF_compressBound(size_t size) { return HUF_COMPRESSBOUND(size); } #define HUF_FLUSHBITS(s) (fast ? BIT_flushBitsFast(s) : BIT_flushBits(s)) #define HUF_FLUSHBITS_1(stream) \ if (sizeof((stream)->bitContainer)*8 < HUF_MAX_TABLELOG*2+7) HUF_FLUSHBITS(stream) #define HUF_FLUSHBITS_2(stream) \ if (sizeof((stream)->bitContainer)*8 < HUF_MAX_TABLELOG*4+7) HUF_FLUSHBITS(stream) size_t HUF_compress1X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable) { const BYTE* ip = (const BYTE*) src; BYTE* const ostart = (BYTE*)dst; BYTE* op = ostart; BYTE* const oend = ostart + dstSize; size_t n; const unsigned fast = (dstSize >= HUF_BLOCKBOUND(srcSize)); size_t errorCode; BIT_CStream_t bitC; /* init */ if (dstSize < 8) return 0; /* not enough space to compress */ errorCode = BIT_initCStream(&bitC, op, oend-op); if (HUF_isError(errorCode)) return 0; n = srcSize & ~3; /* join to mod 4 */ switch (srcSize & 3) { case 3 : HUF_encodeSymbol(&bitC, ip[n+ 2], CTable); HUF_FLUSHBITS_2(&bitC); case 2 : HUF_encodeSymbol(&bitC, ip[n+ 1], CTable); HUF_FLUSHBITS_1(&bitC); case 1 : HUF_encodeSymbol(&bitC, ip[n+ 0], CTable); HUF_FLUSHBITS(&bitC); case 0 : default: ; } for (; n>0; n-=4) { /* note : n&3==0 at this stage */ HUF_encodeSymbol(&bitC, ip[n- 1], CTable); HUF_FLUSHBITS_1(&bitC); HUF_encodeSymbol(&bitC, ip[n- 2], CTable); HUF_FLUSHBITS_2(&bitC); HUF_encodeSymbol(&bitC, ip[n- 3], CTable); HUF_FLUSHBITS_1(&bitC); HUF_encodeSymbol(&bitC, ip[n- 4], CTable); HUF_FLUSHBITS(&bitC); } return BIT_closeCStream(&bitC); } size_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable) { size_t segmentSize = (srcSize+3)/4; /* first 3 segments */ size_t errorCode; const BYTE* ip = (const BYTE*) src; const BYTE* const iend = ip + srcSize; BYTE* const ostart = (BYTE*) dst; BYTE* op = ostart; BYTE* const oend = ostart + dstSize; if (dstSize < 6 + 1 + 1 + 1 + 8) return 0; /* minimum space to compress successfully */ if (srcSize < 12) return 0; /* no saving possible : too small input */ op += 6; /* jumpTable */ errorCode = HUF_compress1X_usingCTable(op, oend-op, ip, segmentSize, CTable); if (HUF_isError(errorCode)) return errorCode; if (errorCode==0) return 0; MEM_writeLE16(ostart, (U16)errorCode); ip += segmentSize; op += errorCode; errorCode = HUF_compress1X_usingCTable(op, oend-op, ip, segmentSize, CTable); if (HUF_isError(errorCode)) return errorCode; if (errorCode==0) return 0; MEM_writeLE16(ostart+2, (U16)errorCode); ip += segmentSize; op += errorCode; errorCode = HUF_compress1X_usingCTable(op, oend-op, ip, segmentSize, CTable); if (HUF_isError(errorCode)) return errorCode; if (errorCode==0) return 0; MEM_writeLE16(ostart+4, (U16)errorCode); ip += segmentSize; op += errorCode; errorCode = HUF_compress1X_usingCTable(op, oend-op, ip, iend-ip, CTable); if (HUF_isError(errorCode)) return errorCode; if (errorCode==0) return 0; op += errorCode; return op-ostart; } static size_t HUF_compress_internal ( void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned huffLog, unsigned singleStream) { BYTE* const ostart = (BYTE*)dst; BYTE* op = ostart; BYTE* const oend = ostart + dstSize; U32 count[HUF_MAX_SYMBOL_VALUE+1]; HUF_CElt CTable[HUF_MAX_SYMBOL_VALUE+1]; size_t errorCode; /* checks & inits */ if (srcSize < 1) return 0; /* Uncompressed - note : 1 means rle, so first byte must be correct */ if (dstSize < 1) return 0; /* not compressible within dst budget */ if (srcSize > 128 * 1024) return ERROR(srcSize_wrong); /* current block size limit */ if (huffLog > HUF_MAX_TABLELOG) return ERROR(tableLog_tooLarge); if (!maxSymbolValue) maxSymbolValue = HUF_MAX_SYMBOL_VALUE; if (!huffLog) huffLog = HUF_DEFAULT_TABLELOG; /* Scan input and build symbol stats */ errorCode = FSE_count (count, &maxSymbolValue, (const BYTE*)src, srcSize); if (HUF_isError(errorCode)) return errorCode; if (errorCode == srcSize) { *ostart = ((const BYTE*)src)[0]; return 1; } if (errorCode <= (srcSize >> 7)+1) return 0; /* Heuristic : not compressible enough */ /* Build Huffman Tree */ errorCode = HUF_buildCTable (CTable, count, maxSymbolValue, huffLog); if (HUF_isError(errorCode)) return errorCode; huffLog = (U32)errorCode; /* Write table description header */ errorCode = HUF_writeCTable (op, dstSize, CTable, maxSymbolValue, huffLog); if (HUF_isError(errorCode)) return errorCode; if (errorCode + 12 >= srcSize) return 0; /* not useful to try compression */ op += errorCode; /* Compress */ if (singleStream) errorCode = HUF_compress1X_usingCTable(op, oend - op, src, srcSize, CTable); /* single segment */ else errorCode = HUF_compress4X_usingCTable(op, oend - op, src, srcSize, CTable); if (HUF_isError(errorCode)) return errorCode; if (errorCode==0) return 0; op += errorCode; /* check compressibility */ if ((size_t)(op-ostart) >= srcSize-1) return 0; return op-ostart; } size_t HUF_compress1X (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned huffLog) { return HUF_compress_internal(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, 1); } size_t HUF_compress2 (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned huffLog) { return HUF_compress_internal(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, 0); } size_t HUF_compress (void* dst, size_t maxDstSize, const void* src, size_t srcSize) { return HUF_compress2(dst, maxDstSize, src, (U32)srcSize, 255, HUF_DEFAULT_TABLELOG); } /* ******************************************************* * Huff0 : Huffman block decompression *********************************************************/ typedef struct { BYTE byte; BYTE nbBits; } HUF_DEltX2; /* single-symbol decoding */ typedef struct { U16 sequence; BYTE nbBits; BYTE length; } HUF_DEltX4; /* double-symbols decoding */ typedef struct { BYTE symbol; BYTE weight; } sortedSymbol_t; /*! HUF_readStats Read compact Huffman tree, saved by HUF_writeCTable @huffWeight : destination buffer @return : size read from `src` */ static size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats, U32* nbSymbolsPtr, U32* tableLogPtr, const void* src, size_t srcSize) { U32 weightTotal; U32 tableLog; const BYTE* ip = (const BYTE*) src; size_t iSize = ip[0]; size_t oSize; U32 n; //memset(huffWeight, 0, hwSize); /* is not necessary, even though some analyzer complain ... */ if (iSize >= 128) { /* special header */ if (iSize >= (242)) { /* RLE */ static int l[14] = { 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 127, 128 }; oSize = l[iSize-242]; memset(huffWeight, 1, hwSize); iSize = 0; } else { /* Incompressible */ oSize = iSize - 127; iSize = ((oSize+1)/2); if (iSize+1 > srcSize) return ERROR(srcSize_wrong); if (oSize >= hwSize) return ERROR(corruption_detected); ip += 1; for (n=0; n> 4; huffWeight[n+1] = ip[n/2] & 15; } } } else { /* header compressed with FSE (normal case) */ if (iSize+1 > srcSize) return ERROR(srcSize_wrong); oSize = FSE_decompress(huffWeight, hwSize-1, ip+1, iSize); /* max (hwSize-1) values decoded, as last one is implied */ if (FSE_isError(oSize)) return oSize; } /* collect weight stats */ memset(rankStats, 0, (HUF_ABSOLUTEMAX_TABLELOG + 1) * sizeof(U32)); weightTotal = 0; for (n=0; n= HUF_ABSOLUTEMAX_TABLELOG) return ERROR(corruption_detected); rankStats[huffWeight[n]]++; weightTotal += (1 << huffWeight[n]) >> 1; } /* get last non-null symbol weight (implied, total must be 2^n) */ tableLog = BIT_highbit32(weightTotal) + 1; if (tableLog > HUF_ABSOLUTEMAX_TABLELOG) return ERROR(corruption_detected); { /* determine last weight */ U32 total = 1 << tableLog; U32 rest = total - weightTotal; U32 verif = 1 << BIT_highbit32(rest); U32 lastWeight = BIT_highbit32(rest) + 1; if (verif != rest) return ERROR(corruption_detected); /* last value must be a clean power of 2 */ huffWeight[oSize] = (BYTE)lastWeight; rankStats[lastWeight]++; } /* check tree construction validity */ if ((rankStats[1] < 2) || (rankStats[1] & 1)) return ERROR(corruption_detected); /* by construction : at least 2 elts of rank 1, must be even */ /* results */ *nbSymbolsPtr = (U32)(oSize+1); *tableLogPtr = tableLog; return iSize+1; } /*-***************************/ /* single-symbol decoding */ /*-***************************/ size_t HUF_readDTableX2 (U16* DTable, const void* src, size_t srcSize) { BYTE huffWeight[HUF_MAX_SYMBOL_VALUE + 1]; U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1]; /* large enough for values from 0 to 16 */ U32 tableLog = 0; size_t iSize; U32 nbSymbols = 0; U32 n; U32 nextRankStart; void* const dtPtr = DTable + 1; HUF_DEltX2* const dt = (HUF_DEltX2*)dtPtr; HUF_STATIC_ASSERT(sizeof(HUF_DEltX2) == sizeof(U16)); /* if compilation fails here, assertion is false */ //memset(huffWeight, 0, sizeof(huffWeight)); /* is not necessary, even though some analyzer complain ... */ iSize = HUF_readStats(huffWeight, HUF_MAX_SYMBOL_VALUE + 1, rankVal, &nbSymbols, &tableLog, src, srcSize); if (HUF_isError(iSize)) return iSize; /* check result */ if (tableLog > DTable[0]) return ERROR(tableLog_tooLarge); /* DTable is too small */ DTable[0] = (U16)tableLog; /* maybe should separate sizeof allocated DTable, from used size of DTable, in case of re-use */ /* Prepare ranks */ nextRankStart = 0; for (n=1; n<=tableLog; n++) { U32 current = nextRankStart; nextRankStart += (rankVal[n] << (n-1)); rankVal[n] = current; } /* fill DTable */ for (n=0; n> 1; U32 i; HUF_DEltX2 D; D.byte = (BYTE)n; D.nbBits = (BYTE)(tableLog + 1 - w); for (i = rankVal[w]; i < rankVal[w] + length; i++) dt[i] = D; rankVal[w] += length; } return iSize; } static BYTE HUF_decodeSymbolX2(BIT_DStream_t* Dstream, const HUF_DEltX2* dt, const U32 dtLog) { const size_t val = BIT_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */ const BYTE c = dt[val].byte; BIT_skipBits(Dstream, dt[val].nbBits); return c; } #define HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \ *ptr++ = HUF_decodeSymbolX2(DStreamPtr, dt, dtLog) #define HUF_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \ if (MEM_64bits() || (HUF_MAX_TABLELOG<=12)) \ HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) #define HUF_DECODE_SYMBOLX2_2(ptr, DStreamPtr) \ if (MEM_64bits()) \ HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) static inline size_t HUF_decodeStreamX2(BYTE* p, BIT_DStream_t* const bitDPtr, BYTE* const pEnd, const HUF_DEltX2* const dt, const U32 dtLog) { BYTE* const pStart = p; /* up to 4 symbols at a time */ while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p <= pEnd-4)) { HUF_DECODE_SYMBOLX2_2(p, bitDPtr); HUF_DECODE_SYMBOLX2_1(p, bitDPtr); HUF_DECODE_SYMBOLX2_2(p, bitDPtr); HUF_DECODE_SYMBOLX2_0(p, bitDPtr); } /* closer to the end */ while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p < pEnd)) HUF_DECODE_SYMBOLX2_0(p, bitDPtr); /* no more data to retrieve from bitstream, hence no need to reload */ while (p < pEnd) HUF_DECODE_SYMBOLX2_0(p, bitDPtr); return pEnd-pStart; } size_t HUF_decompress1X2_usingDTable( void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, const U16* DTable) { BYTE* op = (BYTE*)dst; BYTE* const oend = op + dstSize; size_t errorCode; const U32 dtLog = DTable[0]; const void* dtPtr = DTable; const HUF_DEltX2* const dt = ((const HUF_DEltX2*)dtPtr)+1; BIT_DStream_t bitD; errorCode = BIT_initDStream(&bitD, cSrc, cSrcSize); if (HUF_isError(errorCode)) return errorCode; HUF_decodeStreamX2(op, &bitD, oend, dt, dtLog); /* check */ if (!BIT_endOfDStream(&bitD)) return ERROR(corruption_detected); return dstSize; } size_t HUF_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) { HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_MAX_TABLELOG); const BYTE* ip = (const BYTE*) cSrc; size_t errorCode; errorCode = HUF_readDTableX2 (DTable, cSrc, cSrcSize); if (HUF_isError(errorCode)) return errorCode; if (errorCode >= cSrcSize) return ERROR(srcSize_wrong); ip += errorCode; cSrcSize -= errorCode; return HUF_decompress1X2_usingDTable (dst, dstSize, ip, cSrcSize, DTable); } size_t HUF_decompress4X2_usingDTable( void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, const U16* DTable) { const BYTE* const istart = (const BYTE*) cSrc; BYTE* const ostart = (BYTE*) dst; BYTE* const oend = ostart + dstSize; const void* const dtPtr = DTable; const HUF_DEltX2* const dt = ((const HUF_DEltX2*)dtPtr) +1; const U32 dtLog = DTable[0]; size_t errorCode; /* Check */ if (cSrcSize < 10) return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */ /* Init */ BIT_DStream_t bitD1; BIT_DStream_t bitD2; BIT_DStream_t bitD3; BIT_DStream_t bitD4; const size_t length1 = MEM_readLE16(istart); const size_t length2 = MEM_readLE16(istart+2); const size_t length3 = MEM_readLE16(istart+4); size_t length4; const BYTE* const istart1 = istart + 6; /* jumpTable */ const BYTE* const istart2 = istart1 + length1; const BYTE* const istart3 = istart2 + length2; const BYTE* const istart4 = istart3 + length3; const size_t segmentSize = (dstSize+3) / 4; BYTE* const opStart2 = ostart + segmentSize; BYTE* const opStart3 = opStart2 + segmentSize; BYTE* const opStart4 = opStart3 + segmentSize; BYTE* op1 = ostart; BYTE* op2 = opStart2; BYTE* op3 = opStart3; BYTE* op4 = opStart4; U32 endSignal; length4 = cSrcSize - (length1 + length2 + length3 + 6); if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */ errorCode = BIT_initDStream(&bitD1, istart1, length1); if (HUF_isError(errorCode)) return errorCode; errorCode = BIT_initDStream(&bitD2, istart2, length2); if (HUF_isError(errorCode)) return errorCode; errorCode = BIT_initDStream(&bitD3, istart3, length3); if (HUF_isError(errorCode)) return errorCode; errorCode = BIT_initDStream(&bitD4, istart4, length4); if (HUF_isError(errorCode)) return errorCode; /* 16-32 symbols per loop (4-8 symbols per stream) */ endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4); for ( ; (endSignal==BIT_DStream_unfinished) && (op4<(oend-7)) ; ) { HUF_DECODE_SYMBOLX2_2(op1, &bitD1); HUF_DECODE_SYMBOLX2_2(op2, &bitD2); HUF_DECODE_SYMBOLX2_2(op3, &bitD3); HUF_DECODE_SYMBOLX2_2(op4, &bitD4); HUF_DECODE_SYMBOLX2_1(op1, &bitD1); HUF_DECODE_SYMBOLX2_1(op2, &bitD2); HUF_DECODE_SYMBOLX2_1(op3, &bitD3); HUF_DECODE_SYMBOLX2_1(op4, &bitD4); HUF_DECODE_SYMBOLX2_2(op1, &bitD1); HUF_DECODE_SYMBOLX2_2(op2, &bitD2); HUF_DECODE_SYMBOLX2_2(op3, &bitD3); HUF_DECODE_SYMBOLX2_2(op4, &bitD4); HUF_DECODE_SYMBOLX2_0(op1, &bitD1); HUF_DECODE_SYMBOLX2_0(op2, &bitD2); HUF_DECODE_SYMBOLX2_0(op3, &bitD3); HUF_DECODE_SYMBOLX2_0(op4, &bitD4); endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4); } /* check corruption */ if (op1 > opStart2) return ERROR(corruption_detected); if (op2 > opStart3) return ERROR(corruption_detected); if (op3 > opStart4) return ERROR(corruption_detected); /* note : op4 supposed already verified within main loop */ /* finish bitStreams one by one */ HUF_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog); HUF_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog); HUF_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog); HUF_decodeStreamX2(op4, &bitD4, oend, dt, dtLog); /* check */ endSignal = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4); if (!endSignal) return ERROR(corruption_detected); /* decoded size */ return dstSize; } size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) { HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_MAX_TABLELOG); const BYTE* ip = (const BYTE*) cSrc; size_t errorCode; errorCode = HUF_readDTableX2 (DTable, cSrc, cSrcSize); if (HUF_isError(errorCode)) return errorCode; if (errorCode >= cSrcSize) return ERROR(srcSize_wrong); ip += errorCode; cSrcSize -= errorCode; return HUF_decompress4X2_usingDTable (dst, dstSize, ip, cSrcSize, DTable); } /* *************************/ /* double-symbols decoding */ /* *************************/ static void HUF_fillDTableX4Level2(HUF_DEltX4* DTable, U32 sizeLog, const U32 consumed, const U32* rankValOrigin, const int minWeight, const sortedSymbol_t* sortedSymbols, const U32 sortedListSize, U32 nbBitsBaseline, U16 baseSeq) { HUF_DEltX4 DElt; U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1]; U32 s; /* get pre-calculated rankVal */ memcpy(rankVal, rankValOrigin, sizeof(rankVal)); /* fill skipped values */ if (minWeight>1) { U32 i, skipSize = rankVal[minWeight]; MEM_writeLE16(&(DElt.sequence), baseSeq); DElt.nbBits = (BYTE)(consumed); DElt.length = 1; for (i = 0; i < skipSize; i++) DTable[i] = DElt; } /* fill DTable */ for (s=0; s= 1 */ rankVal[weight] += length; } } typedef U32 rankVal_t[HUF_ABSOLUTEMAX_TABLELOG][HUF_ABSOLUTEMAX_TABLELOG + 1]; static void HUF_fillDTableX4(HUF_DEltX4* DTable, const U32 targetLog, const sortedSymbol_t* sortedList, const U32 sortedListSize, const U32* rankStart, rankVal_t rankValOrigin, const U32 maxWeight, const U32 nbBitsBaseline) { U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1]; const int scaleLog = nbBitsBaseline - targetLog; /* note : targetLog >= srcLog, hence scaleLog <= 1 */ const U32 minBits = nbBitsBaseline - maxWeight; U32 s; memcpy(rankVal, rankValOrigin, sizeof(rankVal)); /* fill DTable */ for (s=0; s= minBits) { /* enough room for a second symbol */ U32 sortedRank; int minWeight = nbBits + scaleLog; if (minWeight < 1) minWeight = 1; sortedRank = rankStart[minWeight]; HUF_fillDTableX4Level2(DTable+start, targetLog-nbBits, nbBits, rankValOrigin[nbBits], minWeight, sortedList+sortedRank, sortedListSize-sortedRank, nbBitsBaseline, symbol); } else { U32 i; const U32 end = start + length; HUF_DEltX4 DElt; MEM_writeLE16(&(DElt.sequence), symbol); DElt.nbBits = (BYTE)(nbBits); DElt.length = 1; for (i = start; i < end; i++) DTable[i] = DElt; } rankVal[weight] += length; } } size_t HUF_readDTableX4 (U32* DTable, const void* src, size_t srcSize) { BYTE weightList[HUF_MAX_SYMBOL_VALUE + 1]; sortedSymbol_t sortedSymbol[HUF_MAX_SYMBOL_VALUE + 1]; U32 rankStats[HUF_ABSOLUTEMAX_TABLELOG + 1] = { 0 }; U32 rankStart0[HUF_ABSOLUTEMAX_TABLELOG + 2] = { 0 }; U32* const rankStart = rankStart0+1; rankVal_t rankVal; U32 tableLog, maxW, sizeOfSort, nbSymbols; const U32 memLog = DTable[0]; size_t iSize; void* dtPtr = DTable; HUF_DEltX4* const dt = ((HUF_DEltX4*)dtPtr) + 1; HUF_STATIC_ASSERT(sizeof(HUF_DEltX4) == sizeof(U32)); /* if compilation fails here, assertion is false */ if (memLog > HUF_ABSOLUTEMAX_TABLELOG) return ERROR(tableLog_tooLarge); //memset(weightList, 0, sizeof(weightList)); /* is not necessary, even though some analyzer complain ... */ iSize = HUF_readStats(weightList, HUF_MAX_SYMBOL_VALUE + 1, rankStats, &nbSymbols, &tableLog, src, srcSize); if (HUF_isError(iSize)) return iSize; /* check result */ if (tableLog > memLog) return ERROR(tableLog_tooLarge); /* DTable can't fit code depth */ /* find maxWeight */ for (maxW = tableLog; rankStats[maxW]==0; maxW--) {} /* necessarily finds a solution before 0 */ /* Get start index of each weight */ { U32 w, nextRankStart = 0; for (w=1; w<=maxW; w++) { U32 current = nextRankStart; nextRankStart += rankStats[w]; rankStart[w] = current; } rankStart[0] = nextRankStart; /* put all 0w symbols at the end of sorted list*/ sizeOfSort = nextRankStart; } /* sort symbols by weight */ { U32 s; for (s=0; s> consumed; } } } HUF_fillDTableX4(dt, memLog, sortedSymbol, sizeOfSort, rankStart0, rankVal, maxW, tableLog+1); return iSize; } static U32 HUF_decodeSymbolX4(void* op, BIT_DStream_t* DStream, const HUF_DEltX4* dt, const U32 dtLog) { const size_t val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */ memcpy(op, dt+val, 2); BIT_skipBits(DStream, dt[val].nbBits); return dt[val].length; } static U32 HUF_decodeLastSymbolX4(void* op, BIT_DStream_t* DStream, const HUF_DEltX4* dt, const U32 dtLog) { const size_t val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */ memcpy(op, dt+val, 1); if (dt[val].length==1) BIT_skipBits(DStream, dt[val].nbBits); else { if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8)) { BIT_skipBits(DStream, dt[val].nbBits); if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8)) DStream->bitsConsumed = (sizeof(DStream->bitContainer)*8); /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */ } } return 1; } #define HUF_DECODE_SYMBOLX4_0(ptr, DStreamPtr) \ ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog) #define HUF_DECODE_SYMBOLX4_1(ptr, DStreamPtr) \ if (MEM_64bits() || (HUF_MAX_TABLELOG<=12)) \ ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog) #define HUF_DECODE_SYMBOLX4_2(ptr, DStreamPtr) \ if (MEM_64bits()) \ ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog) static inline size_t HUF_decodeStreamX4(BYTE* p, BIT_DStream_t* bitDPtr, BYTE* const pEnd, const HUF_DEltX4* const dt, const U32 dtLog) { BYTE* const pStart = p; /* up to 8 symbols at a time */ while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p < pEnd-7)) { HUF_DECODE_SYMBOLX4_2(p, bitDPtr); HUF_DECODE_SYMBOLX4_1(p, bitDPtr); HUF_DECODE_SYMBOLX4_2(p, bitDPtr); HUF_DECODE_SYMBOLX4_0(p, bitDPtr); } /* closer to the end */ while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p <= pEnd-2)) HUF_DECODE_SYMBOLX4_0(p, bitDPtr); while (p <= pEnd-2) HUF_DECODE_SYMBOLX4_0(p, bitDPtr); /* no need to reload : reached the end of DStream */ if (p < pEnd) p += HUF_decodeLastSymbolX4(p, bitDPtr, dt, dtLog); return p-pStart; } size_t HUF_decompress1X4_usingDTable( void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, const U32* DTable) { const BYTE* const istart = (const BYTE*) cSrc; BYTE* const ostart = (BYTE*) dst; BYTE* const oend = ostart + dstSize; const U32 dtLog = DTable[0]; const void* const dtPtr = DTable; const HUF_DEltX4* const dt = ((const HUF_DEltX4*)dtPtr) +1; size_t errorCode; /* Init */ BIT_DStream_t bitD; errorCode = BIT_initDStream(&bitD, istart, cSrcSize); if (HUF_isError(errorCode)) return errorCode; /* finish bitStreams one by one */ HUF_decodeStreamX4(ostart, &bitD, oend, dt, dtLog); /* check */ if (!BIT_endOfDStream(&bitD)) return ERROR(corruption_detected); /* decoded size */ return dstSize; } size_t HUF_decompress1X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) { HUF_CREATE_STATIC_DTABLEX4(DTable, HUF_MAX_TABLELOG); const BYTE* ip = (const BYTE*) cSrc; size_t hSize = HUF_readDTableX4 (DTable, cSrc, cSrcSize); if (HUF_isError(hSize)) return hSize; if (hSize >= cSrcSize) return ERROR(srcSize_wrong); ip += hSize; cSrcSize -= hSize; return HUF_decompress1X4_usingDTable (dst, dstSize, ip, cSrcSize, DTable); } size_t HUF_decompress4X4_usingDTable( void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, const U32* DTable) { if (cSrcSize < 10) return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */ { const BYTE* const istart = (const BYTE*) cSrc; BYTE* const ostart = (BYTE*) dst; BYTE* const oend = ostart + dstSize; const void* const dtPtr = DTable; const HUF_DEltX4* const dt = ((const HUF_DEltX4*)dtPtr) +1; const U32 dtLog = DTable[0]; size_t errorCode; /* Init */ BIT_DStream_t bitD1; BIT_DStream_t bitD2; BIT_DStream_t bitD3; BIT_DStream_t bitD4; const size_t length1 = MEM_readLE16(istart); const size_t length2 = MEM_readLE16(istart+2); const size_t length3 = MEM_readLE16(istart+4); size_t length4; const BYTE* const istart1 = istart + 6; /* jumpTable */ const BYTE* const istart2 = istart1 + length1; const BYTE* const istart3 = istart2 + length2; const BYTE* const istart4 = istart3 + length3; const size_t segmentSize = (dstSize+3) / 4; BYTE* const opStart2 = ostart + segmentSize; BYTE* const opStart3 = opStart2 + segmentSize; BYTE* const opStart4 = opStart3 + segmentSize; BYTE* op1 = ostart; BYTE* op2 = opStart2; BYTE* op3 = opStart3; BYTE* op4 = opStart4; U32 endSignal; length4 = cSrcSize - (length1 + length2 + length3 + 6); if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */ errorCode = BIT_initDStream(&bitD1, istart1, length1); if (HUF_isError(errorCode)) return errorCode; errorCode = BIT_initDStream(&bitD2, istart2, length2); if (HUF_isError(errorCode)) return errorCode; errorCode = BIT_initDStream(&bitD3, istart3, length3); if (HUF_isError(errorCode)) return errorCode; errorCode = BIT_initDStream(&bitD4, istart4, length4); if (HUF_isError(errorCode)) return errorCode; /* 16-32 symbols per loop (4-8 symbols per stream) */ endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4); for ( ; (endSignal==BIT_DStream_unfinished) && (op4<(oend-7)) ; ) { HUF_DECODE_SYMBOLX4_2(op1, &bitD1); HUF_DECODE_SYMBOLX4_2(op2, &bitD2); HUF_DECODE_SYMBOLX4_2(op3, &bitD3); HUF_DECODE_SYMBOLX4_2(op4, &bitD4); HUF_DECODE_SYMBOLX4_1(op1, &bitD1); HUF_DECODE_SYMBOLX4_1(op2, &bitD2); HUF_DECODE_SYMBOLX4_1(op3, &bitD3); HUF_DECODE_SYMBOLX4_1(op4, &bitD4); HUF_DECODE_SYMBOLX4_2(op1, &bitD1); HUF_DECODE_SYMBOLX4_2(op2, &bitD2); HUF_DECODE_SYMBOLX4_2(op3, &bitD3); HUF_DECODE_SYMBOLX4_2(op4, &bitD4); HUF_DECODE_SYMBOLX4_0(op1, &bitD1); HUF_DECODE_SYMBOLX4_0(op2, &bitD2); HUF_DECODE_SYMBOLX4_0(op3, &bitD3); HUF_DECODE_SYMBOLX4_0(op4, &bitD4); endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4); } /* check corruption */ if (op1 > opStart2) return ERROR(corruption_detected); if (op2 > opStart3) return ERROR(corruption_detected); if (op3 > opStart4) return ERROR(corruption_detected); /* note : op4 supposed already verified within main loop */ /* finish bitStreams one by one */ HUF_decodeStreamX4(op1, &bitD1, opStart2, dt, dtLog); HUF_decodeStreamX4(op2, &bitD2, opStart3, dt, dtLog); HUF_decodeStreamX4(op3, &bitD3, opStart4, dt, dtLog); HUF_decodeStreamX4(op4, &bitD4, oend, dt, dtLog); /* check */ endSignal = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4); if (!endSignal) return ERROR(corruption_detected); /* decoded size */ return dstSize; } } size_t HUF_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) { HUF_CREATE_STATIC_DTABLEX4(DTable, HUF_MAX_TABLELOG); const BYTE* ip = (const BYTE*) cSrc; size_t hSize = HUF_readDTableX4 (DTable, cSrc, cSrcSize); if (HUF_isError(hSize)) return hSize; if (hSize >= cSrcSize) return ERROR(srcSize_wrong); ip += hSize; cSrcSize -= hSize; return HUF_decompress4X4_usingDTable (dst, dstSize, ip, cSrcSize, DTable); } /* ********************************/ /* quad-symbol decoding */ /* ********************************/ typedef struct { BYTE nbBits; BYTE nbBytes; } HUF_DDescX6; typedef union { BYTE byte[4]; U32 sequence; } HUF_DSeqX6; /* recursive, up to level 3; may benefit from