From 6b7c844df0b70ce20ff4bba73334d1bd7173727f Mon Sep 17 00:00:00 2001 From: Peter Osterlund Date: Fri, 20 Jan 2012 19:14:25 +0000 Subject: [PATCH] DroidFish: Added support for Gaviota endgame tablebases. --- DroidFish/jni/Android.mk | 4 +- DroidFish/jni/gtb/Android.mk | 25 + DroidFish/jni/gtb/GtbProbe.cpp | 130 + DroidFish/jni/gtb/GtbProbe.h | 63 + .../jni/gtb/compression/huffman/ChangeLog | 0 DroidFish/jni/gtb/compression/huffman/hzip.c | 973 ++ DroidFish/jni/gtb/compression/huffman/hzip.h | 51 + DroidFish/jni/gtb/compression/liblzf/LICENSE | 27 + DroidFish/jni/gtb/compression/liblzf/lzf.h | 100 + DroidFish/jni/gtb/compression/liblzf/lzfP.h | 159 + DroidFish/jni/gtb/compression/liblzf/lzf_c.c | 302 + DroidFish/jni/gtb/compression/liblzf/lzf_d.c | 157 + DroidFish/jni/gtb/compression/lzma/Alloc.c | 127 + DroidFish/jni/gtb/compression/lzma/Alloc.h | 32 + DroidFish/jni/gtb/compression/lzma/Bra.h | 60 + DroidFish/jni/gtb/compression/lzma/Bra86.c | 85 + DroidFish/jni/gtb/compression/lzma/LzFind.c | 758 ++ DroidFish/jni/gtb/compression/lzma/LzFind.h | 107 + DroidFish/jni/gtb/compression/lzma/LzFindMt.h | 97 + DroidFish/jni/gtb/compression/lzma/LzHash.h | 54 + .../jni/gtb/compression/lzma/Lzma86Dec.c | 61 + .../jni/gtb/compression/lzma/Lzma86Dec.h | 45 + .../jni/gtb/compression/lzma/Lzma86Enc.c | 113 + .../jni/gtb/compression/lzma/Lzma86Enc.h | 72 + DroidFish/jni/gtb/compression/lzma/LzmaDec.c | 1012 +++ DroidFish/jni/gtb/compression/lzma/LzmaDec.h | 223 + DroidFish/jni/gtb/compression/lzma/LzmaEnc.c | 2330 +++++ DroidFish/jni/gtb/compression/lzma/LzmaEnc.h | 72 + DroidFish/jni/gtb/compression/lzma/Types.h | 208 + DroidFish/jni/gtb/compression/wrap.c | 338 + DroidFish/jni/gtb/compression/wrap.h | 58 + DroidFish/jni/gtb/compression/zlib/adler32.c | 143 + DroidFish/jni/gtb/compression/zlib/crc32.c | 439 + DroidFish/jni/gtb/compression/zlib/crc32.h | 441 + DroidFish/jni/gtb/compression/zlib/deflate.c | 1725 ++++ DroidFish/jni/gtb/compression/zlib/deflate.h | 350 + DroidFish/jni/gtb/compression/zlib/infback.c | 620 ++ DroidFish/jni/gtb/compression/zlib/inffast.c | 318 + DroidFish/jni/gtb/compression/zlib/inffast.h | 11 + DroidFish/jni/gtb/compression/zlib/inffixed.h | 94 + DroidFish/jni/gtb/compression/zlib/inflate.c | 1348 +++ DroidFish/jni/gtb/compression/zlib/inflate.h | 115 + DroidFish/jni/gtb/compression/zlib/inftrees.c | 323 + DroidFish/jni/gtb/compression/zlib/inftrees.h | 55 + DroidFish/jni/gtb/compression/zlib/trees.c | 1267 +++ DroidFish/jni/gtb/compression/zlib/trees.h | 128 + DroidFish/jni/gtb/compression/zlib/uncompr.c | 57 + .../jni/gtb/compression/zlib/zcompress.c | 69 + DroidFish/jni/gtb/compression/zlib/zconf.h | 332 + DroidFish/jni/gtb/compression/zlib/zconf.in.h | 332 + DroidFish/jni/gtb/compression/zlib/zlib.h | 1357 +++ DroidFish/jni/gtb/compression/zlib/zutil.c | 354 + DroidFish/jni/gtb/compression/zlib/zutil.h | 269 + DroidFish/jni/gtb/gtb-att.c | 390 + DroidFish/jni/gtb/gtb-att.h | 43 + DroidFish/jni/gtb/gtb-dec.c | 133 + DroidFish/jni/gtb/gtb-dec.h | 50 + DroidFish/jni/gtb/gtb-probe.c | 8039 +++++++++++++++++ DroidFish/jni/gtb/gtb-probe.h | 234 + DroidFish/jni/gtb/gtb-types.h | 25 + DroidFish/jni/gtb/license.txt | 100 + DroidFish/jni/gtb/progname.h | 1 + DroidFish/jni/gtb/readme.txt | 147 + DroidFish/jni/gtb/sysport/sysport.c | 274 + DroidFish/jni/gtb/sysport/sysport.h | 237 + DroidFish/jni/gtb/version.h | 2 + DroidFish/jni/gtb/version.txt | 1 + DroidFish/res/values/strings.xml | 23 + DroidFish/res/xml/preferences.xml | 41 +- .../src/org/petero/droidfish/ChessBoard.java | 76 +- .../src/org/petero/droidfish/ColorTheme.java | 17 +- .../src/org/petero/droidfish/DroidFish.java | 58 +- .../src/org/petero/droidfish/EGTBOptions.java | 44 + .../org/petero/droidfish/GUIInterface.java | 5 +- .../droidfish/activities/ChessBoardEdit.java | 2 +- .../droidfish/activities/EditBoard.java | 65 +- .../petero/droidfish/book/BookOptions.java | 2 +- .../droidfish/engine/DroidComputerPlayer.java | 63 +- .../droidfish/engine/ExternalEngine.java | 9 +- .../petero/droidfish/engine/UCIEngine.java | 4 +- .../droidfish/engine/UCIEngineBase.java | 3 +- .../engine/cuckoochess/CuckooChessEngine.java | 5 +- .../gamelogic/DroidChessController.java | 17 +- .../petero/droidfish/gamelogic/GameTree.java | 4 +- .../droidfish/gamelogic/SearchListener.java | 3 +- .../org/petero/droidfish/gtb/GtbProbe.java | 83 + .../src/org/petero/droidfish/gtb/Probe.java | 278 + 87 files changed, 28407 insertions(+), 61 deletions(-) create mode 100644 DroidFish/jni/gtb/Android.mk create mode 100644 DroidFish/jni/gtb/GtbProbe.cpp create mode 100644 DroidFish/jni/gtb/GtbProbe.h create mode 100644 DroidFish/jni/gtb/compression/huffman/ChangeLog create mode 100644 DroidFish/jni/gtb/compression/huffman/hzip.c create mode 100644 DroidFish/jni/gtb/compression/huffman/hzip.h create mode 100644 DroidFish/jni/gtb/compression/liblzf/LICENSE create mode 100644 DroidFish/jni/gtb/compression/liblzf/lzf.h create mode 100644 DroidFish/jni/gtb/compression/liblzf/lzfP.h create mode 100644 DroidFish/jni/gtb/compression/liblzf/lzf_c.c create mode 100644 DroidFish/jni/gtb/compression/liblzf/lzf_d.c create mode 100755 DroidFish/jni/gtb/compression/lzma/Alloc.c create mode 100755 DroidFish/jni/gtb/compression/lzma/Alloc.h create mode 100755 DroidFish/jni/gtb/compression/lzma/Bra.h create mode 100755 DroidFish/jni/gtb/compression/lzma/Bra86.c create mode 100755 DroidFish/jni/gtb/compression/lzma/LzFind.c create mode 100755 DroidFish/jni/gtb/compression/lzma/LzFind.h create mode 100755 DroidFish/jni/gtb/compression/lzma/LzFindMt.h create mode 100755 DroidFish/jni/gtb/compression/lzma/LzHash.h create mode 100755 DroidFish/jni/gtb/compression/lzma/Lzma86Dec.c create mode 100755 DroidFish/jni/gtb/compression/lzma/Lzma86Dec.h create mode 100755 DroidFish/jni/gtb/compression/lzma/Lzma86Enc.c create mode 100755 DroidFish/jni/gtb/compression/lzma/Lzma86Enc.h create mode 100755 DroidFish/jni/gtb/compression/lzma/LzmaDec.c create mode 100755 DroidFish/jni/gtb/compression/lzma/LzmaDec.h create mode 100755 DroidFish/jni/gtb/compression/lzma/LzmaEnc.c create mode 100755 DroidFish/jni/gtb/compression/lzma/LzmaEnc.h create mode 100755 DroidFish/jni/gtb/compression/lzma/Types.h create mode 100644 DroidFish/jni/gtb/compression/wrap.c create mode 100644 DroidFish/jni/gtb/compression/wrap.h create mode 100644 DroidFish/jni/gtb/compression/zlib/adler32.c create mode 100644 DroidFish/jni/gtb/compression/zlib/crc32.c create mode 100644 DroidFish/jni/gtb/compression/zlib/crc32.h create mode 100644 DroidFish/jni/gtb/compression/zlib/deflate.c create mode 100644 DroidFish/jni/gtb/compression/zlib/deflate.h create mode 100644 DroidFish/jni/gtb/compression/zlib/infback.c create mode 100644 DroidFish/jni/gtb/compression/zlib/inffast.c create mode 100644 DroidFish/jni/gtb/compression/zlib/inffast.h create mode 100644 DroidFish/jni/gtb/compression/zlib/inffixed.h create mode 100644 DroidFish/jni/gtb/compression/zlib/inflate.c create mode 100644 DroidFish/jni/gtb/compression/zlib/inflate.h create mode 100644 DroidFish/jni/gtb/compression/zlib/inftrees.c create mode 100644 DroidFish/jni/gtb/compression/zlib/inftrees.h create mode 100644 DroidFish/jni/gtb/compression/zlib/trees.c create mode 100644 DroidFish/jni/gtb/compression/zlib/trees.h create mode 100644 DroidFish/jni/gtb/compression/zlib/uncompr.c create mode 100644 DroidFish/jni/gtb/compression/zlib/zcompress.c create mode 100644 DroidFish/jni/gtb/compression/zlib/zconf.h create mode 100644 DroidFish/jni/gtb/compression/zlib/zconf.in.h create mode 100644 DroidFish/jni/gtb/compression/zlib/zlib.h create mode 100644 DroidFish/jni/gtb/compression/zlib/zutil.c create mode 100644 DroidFish/jni/gtb/compression/zlib/zutil.h create mode 100644 DroidFish/jni/gtb/gtb-att.c create mode 100644 DroidFish/jni/gtb/gtb-att.h create mode 100644 DroidFish/jni/gtb/gtb-dec.c create mode 100644 DroidFish/jni/gtb/gtb-dec.h create mode 100644 DroidFish/jni/gtb/gtb-probe.c create mode 100644 DroidFish/jni/gtb/gtb-probe.h create mode 100644 DroidFish/jni/gtb/gtb-types.h create mode 100644 DroidFish/jni/gtb/license.txt create mode 100644 DroidFish/jni/gtb/progname.h create mode 100644 DroidFish/jni/gtb/readme.txt create mode 100644 DroidFish/jni/gtb/sysport/sysport.c create mode 100644 DroidFish/jni/gtb/sysport/sysport.h create mode 100644 DroidFish/jni/gtb/version.h create mode 100644 DroidFish/jni/gtb/version.txt create mode 100644 DroidFish/src/org/petero/droidfish/EGTBOptions.java create mode 100644 DroidFish/src/org/petero/droidfish/gtb/GtbProbe.java create mode 100644 DroidFish/src/org/petero/droidfish/gtb/Probe.java diff --git a/DroidFish/jni/Android.mk b/DroidFish/jni/Android.mk index 62b2b0d..cb62fcc 100644 --- a/DroidFish/jni/Android.mk +++ b/DroidFish/jni/Android.mk @@ -6,10 +6,12 @@ LOCAL_MODULE := nativeutil LOCAL_SRC_FILES := nativeutil.cpp LOCAL_CFLAGS := \ - -mandroid \ + -mandroid \ -DTARGET_OS=android -D__ANDROID__ \ -isystem $(SYSROOT)/usr/include include $(BUILD_SHARED_LIBRARY) include jni/stockfish/Android.mk + +include jni/gtb/Android.mk diff --git a/DroidFish/jni/gtb/Android.mk b/DroidFish/jni/gtb/Android.mk new file mode 100644 index 0000000..34e86a8 --- /dev/null +++ b/DroidFish/jni/gtb/Android.mk @@ -0,0 +1,25 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := gtb +LOCAL_SRC_FILES := \ + gtb-probe.c gtb-dec.c gtb-att.c sysport/sysport.c compression/wrap.c \ + compression/huffman/hzip.c compression/lzma/LzmaEnc.c compression/lzma/LzmaDec.c \ + compression/lzma/Alloc.c compression/lzma/LzFind.c compression/lzma/Lzma86Enc.c \ + compression/lzma/Lzma86Dec.c compression/lzma/Bra86.c compression/zlib/zcompress.c \ + compression/zlib/uncompr.c compression/zlib/inflate.c compression/zlib/deflate.c \ + compression/zlib/adler32.c compression/zlib/crc32.c compression/zlib/infback.c \ + compression/zlib/inffast.c compression/zlib/inftrees.c compression/zlib/trees.c \ + compression/zlib/zutil.c compression/liblzf/lzf_c.c compression/liblzf/lzf_d.c \ + GtbProbe.cpp + +LOCAL_CFLAGS := \ + -I $(LOCAL_PATH)/sysport/ -I $(LOCAL_PATH)/compression/ \ + -I $(LOCAL_PATH)/compression/liblzf/ -I $(LOCAL_PATH)/compression/zlib/ \ + -I $(LOCAL_PATH)/compression/lzma/ -I $(LOCAL_PATH)/compression/huffman/ \ + -D Z_PREFIX -D NDEBUG -Wall\ + -mandroid -DTARGET_OS=android -D__ANDROID__ \ + -isystem $(SYSROOT)/usr/include + +include $(BUILD_SHARED_LIBRARY) diff --git a/DroidFish/jni/gtb/GtbProbe.cpp b/DroidFish/jni/gtb/GtbProbe.cpp new file mode 100644 index 0000000..cbfbf73 --- /dev/null +++ b/DroidFish/jni/gtb/GtbProbe.cpp @@ -0,0 +1,130 @@ +/* + DroidFish - An Android chess program. + Copyright (C) 2011-2012 Peter Österlund, peterosterlund2@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +#include "GtbProbe.h" +#include "gtb-probe.h" +#include + +using namespace std; + +static bool isInitialized = false; +static bool initOk = false; +static const char** paths = NULL; + + +JNIEXPORT jboolean +JNICALL Java_org_petero_droidfish_gtb_GtbProbe_init( + JNIEnv* env, jclass cls, jstring jTbPath) +{ + initOk = false; + const char* tbPath = (*env).GetStringUTFChars(jTbPath, NULL); + if (!tbPath) + return false; + + if (isInitialized && paths) + tbpaths_done(paths); + paths = tbpaths_init(); + if (paths == NULL) { + (*env).ReleaseStringUTFChars(jTbPath, tbPath); + return false; + } + paths = tbpaths_add(paths, tbPath); + if (paths == NULL) { + (*env).ReleaseStringUTFChars(jTbPath, tbPath); + return false; + } + + TB_compression_scheme scheme = tb_CP4; + int verbose = 0; + int cacheSize = 4*1024*1024; + int wdlFraction = 8; + if (isInitialized) { + tb_restart (verbose, scheme, paths); + tbcache_restart(cacheSize, wdlFraction); + } else { + tb_init(verbose, scheme, paths); + tbcache_init(cacheSize, wdlFraction); + } + isInitialized = true; + + (*env).ReleaseStringUTFChars(jTbPath, tbPath); + initOk = true; + return true; +} + +#define WHITE_TO_MOVE 0 +#define BLACK_TO_MOVE 1 + +JNIEXPORT jboolean +JNICALL Java_org_petero_droidfish_gtb_GtbProbe_probeHard( + JNIEnv* env, jobject ths, + jboolean wtm, jint epSq, jint castleMask, + jintArray whiteSquares, jintArray blackSquares, + jbyteArray whitePieces, jbyteArray blackPieces, + jintArray result) +{ + if (!initOk) + return false; + if ((*env).GetArrayLength(result) < 2) + return false; + + const int MAXLEN = 17; + unsigned char wp[MAXLEN]; + unsigned int ws[MAXLEN]; + unsigned char bp[MAXLEN]; + unsigned int bs[MAXLEN]; + + int len = (*env).GetArrayLength(whiteSquares); + jint* jiPtr = (*env).GetIntArrayElements(whiteSquares, NULL); + for (int i = 0; i < min(len, MAXLEN); i++) + ws[i] = jiPtr[i]; + (*env).ReleaseIntArrayElements(whiteSquares, jiPtr, 0); + + len = (*env).GetArrayLength(blackSquares); + jiPtr = (*env).GetIntArrayElements(blackSquares, NULL); + for (int i = 0; i < min(len, MAXLEN); i++) + bs[i] = jiPtr[i]; + (*env).ReleaseIntArrayElements(blackSquares, jiPtr, 0); + + len = (*env).GetArrayLength(whitePieces); + jbyte* jcPtr = (*env).GetByteArrayElements(whitePieces, NULL); + for (int i = 0; i < min(len, MAXLEN); i++) + wp[i] = jcPtr[i]; + (*env).ReleaseByteArrayElements(whitePieces, jcPtr, 0); + + len = (*env).GetArrayLength(blackPieces); + jcPtr = (*env).GetByteArrayElements(blackPieces, NULL); + for (int i = 0; i < min(len, MAXLEN); i++) + bp[i] = jcPtr[i]; + (*env).ReleaseByteArrayElements(blackPieces, jcPtr, 0); + + unsigned int tbInfo; + unsigned int plies; + int ret = tb_probe_hard(wtm ? WHITE_TO_MOVE : BLACK_TO_MOVE, + epSq, castleMask, + ws, + bs, + wp, + bp, + &tbInfo, &plies); + jint res[2]; + res[0] = tbInfo; + res[1] = plies; + + (*env).SetIntArrayRegion(result, 0, 2, res); + return ret != 0; +} diff --git a/DroidFish/jni/gtb/GtbProbe.h b/DroidFish/jni/gtb/GtbProbe.h new file mode 100644 index 0000000..3137625 --- /dev/null +++ b/DroidFish/jni/gtb/GtbProbe.h @@ -0,0 +1,63 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_petero_droidfish_gtb_GtbProbe */ + +#ifndef _Included_org_petero_droidfish_gtb_GtbProbe +#define _Included_org_petero_droidfish_gtb_GtbProbe +#ifdef __cplusplus +extern "C" { +#endif +#undef org_petero_droidfish_gtb_GtbProbe_NOPIECE +#define org_petero_droidfish_gtb_GtbProbe_NOPIECE 0L +#undef org_petero_droidfish_gtb_GtbProbe_PAWN +#define org_petero_droidfish_gtb_GtbProbe_PAWN 1L +#undef org_petero_droidfish_gtb_GtbProbe_KNIGHT +#define org_petero_droidfish_gtb_GtbProbe_KNIGHT 2L +#undef org_petero_droidfish_gtb_GtbProbe_BISHOP +#define org_petero_droidfish_gtb_GtbProbe_BISHOP 3L +#undef org_petero_droidfish_gtb_GtbProbe_ROOK +#define org_petero_droidfish_gtb_GtbProbe_ROOK 4L +#undef org_petero_droidfish_gtb_GtbProbe_QUEEN +#define org_petero_droidfish_gtb_GtbProbe_QUEEN 5L +#undef org_petero_droidfish_gtb_GtbProbe_KING +#define org_petero_droidfish_gtb_GtbProbe_KING 6L +#undef org_petero_droidfish_gtb_GtbProbe_NOSQUARE +#define org_petero_droidfish_gtb_GtbProbe_NOSQUARE 64L +#undef org_petero_droidfish_gtb_GtbProbe_H1_CASTLE +#define org_petero_droidfish_gtb_GtbProbe_H1_CASTLE 8L +#undef org_petero_droidfish_gtb_GtbProbe_A1_CASTLE +#define org_petero_droidfish_gtb_GtbProbe_A1_CASTLE 4L +#undef org_petero_droidfish_gtb_GtbProbe_H8_CASTLE +#define org_petero_droidfish_gtb_GtbProbe_H8_CASTLE 2L +#undef org_petero_droidfish_gtb_GtbProbe_A8_CASTLE +#define org_petero_droidfish_gtb_GtbProbe_A8_CASTLE 1L +#undef org_petero_droidfish_gtb_GtbProbe_DRAW +#define org_petero_droidfish_gtb_GtbProbe_DRAW 0L +#undef org_petero_droidfish_gtb_GtbProbe_WMATE +#define org_petero_droidfish_gtb_GtbProbe_WMATE 1L +#undef org_petero_droidfish_gtb_GtbProbe_BMATE +#define org_petero_droidfish_gtb_GtbProbe_BMATE 2L +#undef org_petero_droidfish_gtb_GtbProbe_FORBID +#define org_petero_droidfish_gtb_GtbProbe_FORBID 3L +#undef org_petero_droidfish_gtb_GtbProbe_UNKNOWN +#define org_petero_droidfish_gtb_GtbProbe_UNKNOWN 7L +/* + * Class: org_petero_droidfish_gtb_GtbProbe + * Method: probeHard + * Signature: (ZII[I[I[B[B[I)Z + */ +JNIEXPORT jboolean JNICALL Java_org_petero_droidfish_gtb_GtbProbe_probeHard + (JNIEnv *, jobject, jboolean, jint, jint, jintArray, jintArray, jbyteArray, jbyteArray, jintArray); + +/* + * Class: org_petero_droidfish_gtb_GtbProbe + * Method: init + * Signature: (Ljava/lang/String;)Z + */ +JNIEXPORT jboolean JNICALL Java_org_petero_droidfish_gtb_GtbProbe_init + (JNIEnv *, jclass, jstring); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/DroidFish/jni/gtb/compression/huffman/ChangeLog b/DroidFish/jni/gtb/compression/huffman/ChangeLog new file mode 100644 index 0000000..e69de29 diff --git a/DroidFish/jni/gtb/compression/huffman/hzip.c b/DroidFish/jni/gtb/compression/huffman/hzip.c new file mode 100644 index 0000000..7419d0e --- /dev/null +++ b/DroidFish/jni/gtb/compression/huffman/hzip.c @@ -0,0 +1,973 @@ +/* hzip.c */ +/* +| Routines designed to be used as a pilot experiment for compression +| of tablebases. Not really optimized, but they are supposed to work +| --Miguel A. Ballicora +*/ + +/* +This Software is distributed with the following X11 License, +sometimes also known as MIT license. + +Copyright (c) 2010 Miguel A. Ballicora + + 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. +*/ + +#include "hzip.h" + +/*-------------------------------------------------------------------*\ +| +| Huffman coding compression +| +\*-------------------------------------------------------------------*/ + +#include +#include +#include +#include + +#define MAXDIVERSITY (256) +#define MAXHEAP (MAXDIVERSITY+1) +#define MAXSTREAM (1<<18) +#define MAXHUFF (2*MAXDIVERSITY) + +typedef int bool_t; + +#define TRUE 1 +#define FALSE 0; + +/* huffman tree */ +struct huff { + int freq; + int value; + int pleft; + int pright; + bool_t isleaf; +}; + +static int huff_end; +static struct huff hufftree[MAXHUFF]; + +/* heap */ +struct element { + int freq; + int huffidx; +}; + +static int heap_end; +static struct element heap[MAXHEAP]; + +unsigned char streambuffer[MAXSTREAM]; + +/* stream */ +struct STREAM { + unsigned long pbit; + unsigned char *x; +}; + +typedef struct STREAM stream_t; + +/* read only */ +struct RO_STREAM { + unsigned long pbit; + const unsigned char *x; +}; + +typedef struct RO_STREAM ro_stream_t; + +/* +| +| VARIABLES +| +\*---------------------------*/ + +static int freq[MAXDIVERSITY]; +static unsigned code_table[MAXDIVERSITY]; +static unsigned size_table[MAXDIVERSITY]; +static stream_t Stream = {0, NULL}; +static ro_stream_t RO_Stream = {0, NULL}; +static const unsigned int VALUEBITS = 8u; + +/*==== PROTOTYPES======================================*/ + + +/* heap */ + +static void freq_init (const unsigned char *in, size_t max); +static void heap_init (void); +static void heap_append (struct element e); +static void heap_sift_up (int x); +static void heap_adjust_down (int top, int last); + + +/* hufftree */ + +static int hufftree_from_freq (void); +static int hufftree_from_heap (void); +static void hufftree_to_codes (int start, int n, unsigned code); +static void hufftree_reset (void); +static int hufftree_frombits (ro_stream_t *stream, bool_t *pok); +static void hufftree_tobits (int thisnode, stream_t *stream); +static unsigned int hufftree_readstream (int root, ro_stream_t *s); + +/* stream */ + +/* read only */ +static void ro_stream_rewind (ro_stream_t *s); +static void ro_stream_init (ro_stream_t *s, const unsigned char *buffer); +static void ro_stream_done (ro_stream_t *s); + +/* read and write */ +static void stream_clear (stream_t *s); +static void stream_init (stream_t *s, unsigned char *buffer); +static void stream_done (stream_t *s); +static size_t stream_len (stream_t *s); + +static void stream_rewind (stream_t *s); +static unsigned int stream_nextbit (ro_stream_t *s); +static unsigned int stream_nextbit_n (ro_stream_t *s, unsigned int width); +static void stream_writebit (stream_t *s, unsigned z); +static void stream_write_n (unsigned code, unsigned width, stream_t *s); + + +static bool_t decode_from_stream (ro_stream_t *stream, size_t n, unsigned char *out); +static void encode_to_stream (const unsigned char *in, size_t inlen, stream_t *stream); + +/*static unsigned int stream_next8 (stream_t *s);*/ +/*static void stream_write8 (stream_t *s, unsigned z);*/ + +/* supporting functions */ + +/* +static void heap_plot (void); +static int fill_block(unsigned char *out); +static char *binstream(unsigned int x, int n); +static void stream_print(stream_t *s, int n); +static void stream_printnext (stream_t *s, int n); +static void stream_dump (stream_t *s, int ori, int n); +static void freq_report (void); +*/ + +/*=== ENCODE/DECODE=================================================*/ + +size_t TB_hzip_unused; + +static int +huffman_decode (size_t z, const unsigned char *bz, size_t n, unsigned char *bp) +/* bz:buffer huffman zipped to bp:buffer decoded */ +{ + bool_t ok; + TB_hzip_unused = z; /* to silence compiler */ + ro_stream_init (&RO_Stream, bz); + ok = decode_from_stream (&RO_Stream, n, bp); + ro_stream_done (&RO_Stream); + return ok; +} + +static int +huffman_encode (size_t n, const unsigned char *bp, size_t *z, unsigned char *bz) +/* bz:buffer huffman zipped to bp:buffer decoded */ +{ + size_t i, zz; + stream_init (&Stream, streambuffer); + encode_to_stream (bp, n, &Stream); + zz = stream_len (&Stream); + for (i = 0; i < zz; i++) { + bz[i] = Stream.x[i]; + } + *z = zz; + stream_done (&Stream); + return TRUE; +} + +extern int +huff_decode +(const unsigned char *in_start, size_t in_len, unsigned char *out_start, size_t *pout_len, size_t out_max) +{ + size_t n = (size_t)in_start[0] + | ((size_t)in_start[1] << 8) + | ((size_t)in_start[2] << 16) + | ((size_t)in_start[3] << 24); + TB_hzip_unused = out_max; + *pout_len = n; + return huffman_decode (in_len-4, in_start+4, n, out_start); +} + + +extern int +huff_encode +(const unsigned char *in_start, size_t in_len, unsigned char *out_start, size_t *pout_len, size_t out_max) +{ + bool_t ok; + size_t hlen = 0; + TB_hzip_unused = out_max; + out_start[0] = (unsigned char) ((in_len ) & 0xffu); + out_start[1] = (unsigned char) ((in_len >> 8) & 0xffu); + out_start[2] = (unsigned char) ((in_len >> 16) & 0xffu); + out_start[3] = (unsigned char) ((in_len >> 24) & 0xffu); + ok = huffman_encode (in_len, in_start, &hlen, out_start+4); + *pout_len = hlen + 4; + return ok; +} + + +static bool_t +decode_from_stream (ro_stream_t *s, size_t n, unsigned char *out) +{ + int root; + bool_t ok = TRUE; /* default */ + + hufftree_reset (); + ro_stream_rewind (s); + root = hufftree_frombits (s, &ok); + + if (ok) { + while (n-->0) { + *out++ = (unsigned char) hufftree_readstream (root, s); /* cast to silence compiler */ + } + } + return ok; +} + + +static void +encode_to_stream (const unsigned char *in, size_t inlen, stream_t *stream) +{ + size_t i; + unsigned x, c, s; + int root; + + stream_clear (&Stream); + stream_rewind(&Stream); + + /* pass to collect frequencies */ + freq_init (in, inlen); + + /* frequency --> heap --> hufftrees */ + root = hufftree_from_freq(); + + /* hufftree --> codes */ + hufftree_to_codes (root, 0, 0); + + /* hufftrees --> stored in bits (stream) */ + hufftree_tobits (root, stream) ; + + /* input + codes --> stored in bits (stream) */ + for (i = 0; i < inlen; i++) { + x = in[i]; + c = code_table[x]; + s = size_table[x]; + stream_write_n (c, s, stream); + } + return; +} + +/*=== STREAM =================================================*/ +/* +static char buffer[256]; +*/ +/* +static char * +binstream(unsigned int x, int n) +{ + char *s = buffer; + int i; + + for (i = 0; i < n; i++) { + if (0!=(x&(1<pbit = 0; return;} + +static void +ro_stream_init (ro_stream_t *s, const unsigned char *buffer) +{ + s->x = buffer; + s->pbit = 0; + return; +} + +static void +ro_stream_done (ro_stream_t *s) +{ + s->x = NULL; + s->pbit = 0; + return; +} + + +/* READ AND WRITE */ +static void stream_rewind (stream_t *s) {s->pbit = 0; return;} + +static void +stream_init (stream_t *s, unsigned char *buffer) +{ + s->x = buffer; + s->pbit = 0; + return; +} + +static void +stream_done (stream_t *s) +{ + s->x = NULL; + s->pbit = 0; + return; +} + +static void +stream_clear (stream_t *s) +{ int i; + for (i = 0; i < MAXSTREAM; i++) { + s->x[i] = 0; + } + s->pbit = 0; + return; +} + +static size_t +stream_len (stream_t *s) +{ + return 1 + s->pbit/8; +} + +static unsigned int +stream_nextbit (ro_stream_t *s) +{ + unsigned long y, byte, bit; + y = s->pbit++; + byte = y / 8; + bit = y & 7; + return 1u & (((unsigned)s->x[byte]) >> bit); +} + +static unsigned int +stream_nextbit_n (ro_stream_t *s, unsigned int width) +{ + unsigned i; + unsigned x; + unsigned r = 0; + for (i = 0; i < width; i++) { + x = stream_nextbit (s); + r |= (x << i); + } + return r; +} + +/* +static unsigned int +stream_next8 (stream_t *s) +{ + unsigned a,b,y,byte,bit; + y = s->pbit; + s->pbit += 8; + byte = y / 8; + bit = y & 7; + a = 0xff & s->x[byte]; + b = 0xff & s->x[byte+1]; + return 0xff & ((a >> bit) | (b << (8-bit))); +} +*/ + +#if 1 +static void +stream_writebit (stream_t *s, unsigned z) +{ + unsigned long y,byte,bit; + y = s->pbit++; + + byte = y / 8; + bit = y & 7; + + /* s->x[byte] &= ~(1u << bit);*/ + s->x[byte] = (unsigned char) (s->x[byte] | ((z&1u) << bit)); /* cast to silence compiler */ + return; +} + +#else +static void +stream_writebit (stream_t *s, unsigned z) +{ + /* This function will write the next bit, 0 or 1 depending on z, and will clear + | the following bits (when bit == 0) or some future bytes + | Do not use for writing after random access + | It is only useful when this function is use for sequential writing on a + | empty buffer. + */ + unsigned long y, byte, bit; + unsigned char *p; + y = s->pbit++; + + byte = y / 8; + bit = y & 7; + + p = &(s->x[byte]); + + /* hack to clear the byte only when bit == 0, otherwise, it clears future bytes + | This will avoid clearing the whole buffer beforehand or doing + | *p &= (unsigned char)(~(1u << bit)); + */ + p[bit] = 0; + + *p |= (unsigned char)(z&1u) << bit); + + return; +} +#endif + + +/* +static void +stream_write8 (stream_t *s, unsigned z) +{ + unsigned a,b,c,y,byte,bit; + y = s->pbit; + s->pbit += 8; + byte = y / 8; + bit = y & 7; + a = 0xff & s->x[byte]; + b = 0xff & s->x[byte+1]; + c = a | (b << 8); + + c &= ~(0xff << bit); + c |= z << bit; + + s->x[byte] = c & 0xff; + s->x[byte+1] = 0xff & (c >> 8); + + return; +} +*/ + +static void +stream_write_n (unsigned code, unsigned width, stream_t *s) +{ + unsigned i; + for (i = 0; i < width; i++) { + stream_writebit (s, 1u & (code >> i)); + } + return; +} + +/* +static void +stream_printnext (stream_t *s, int n) +{ + int i; unsigned int x; + unsigned long int oldpos = s->pbit; + + printf("\n"); + for (i = 0; i < n; i++) { + if ((i & 7) == 0) + printf ("\n"); + x = stream_next8 (s); + printf ("%s ", binstream(x,8) ); + } + printf("\n"); + + s->pbit = oldpos; + return; +} +*/ + +/* +static void +stream_dump (stream_t *s, int ori, int n) +{ + int i; unsigned int x; + unsigned long int oldpos = s->pbit; + + s->pbit = ori; + + printf("\n"); + for (i = 0; i < n; i++) { + if ((i & 7) == 0) + printf ("\n"); + x = stream_next8 (s); + printf ("%s ", binstream(x,8) ); + } + printf("\n"); + + s->pbit = oldpos; + return; +} +*/ + +/*=== HUFFTREE=================================================*/ + +#define LEFTCODE 0u +#define RIGHTCODE 1u +#define BITLEAF 1 +#define BITNODE 0 + +static void +hufftree_reset (void) +{ + struct huff h; + int i; + for (i = 0; i < 2*MAXDIVERSITY; i++) { + h.isleaf = FALSE; + h.value = 0; + h.freq = 0; + h.pleft = 0; + h.pright = 0; + hufftree[i] = h; + } + huff_end = 0; +} + +static int +hufftree_from_heap (void) +{ + int top, newidx /*, left, right, lesser */ ; + struct huff h; + + for (;;) + { + if (heap_end == 2) { /* at least top element */ + /* done */ + break; + } + + /* work at the top */ + top = 1; +/* + left = 2*top; + right = left + 1; + + lesser = left; + if (right < heap_end && (heap[right].freq < heap[left].freq)) + lesser = right; +*/ + /* new huff node */ + newidx = huff_end++; + + h.isleaf = FALSE; + h.value = -1; + h.freq = heap[top].freq; /* will be incremented later when in 'combine' */ + h.pleft = heap[top].huffidx; + h.pright = -1; /* will be attached the next element */ + + + #ifdef TRACE + printf ("\n\nBefore Eliminate Top\n"); + heap_plot(); + #endif + + /* eliminate top */ + heap[top] = heap[--heap_end]; + + /* next 'lesser' element at 'top' */ + heap_adjust_down (1, heap_end-1); + + #ifdef TRACE + printf ("\n\nEliminate Top\n"); + heap_plot (); + #endif + + /* combine */ + h.pright = heap[1].huffidx; + h.freq += heap[1].freq; /* combine frequencies */ + hufftree[newidx] = h; + + heap[1].freq = h.freq; + heap[1].huffidx = newidx; + + /* adjust the combined elements */ + heap_adjust_down (1, heap_end-1); + + #ifdef TRACE + printf ("\n\nAfter Combine\n"); + heap_plot (); + #endif + + } + + return heap[1].huffidx; +} + + +static void +hufftree_to_codes (int start, int n, unsigned code) +{ + int x, m; + unsigned c; + int value; + + #ifdef TRACK + if (n == 0) + printf ("\nHufftree to codes\n"); + #endif + + assert (n >= 0); + + x = hufftree[start].pleft; + c = code | (LEFTCODE << n); + m = n + 1; + + /* LEFT */ + if (hufftree[x].isleaf) { + value = hufftree[x].value; + code_table[value] = c; + size_table[value] = (unsigned)m; + + #ifdef TRACK + printf ("value=%c:%d, code=%d \"%s\", size=%d\n", value,value, c, binstream(c,m), m); + #endif + + } else { + hufftree_to_codes(x, m, c); + } + + + /* RIGHT */ + x = hufftree[start].pright; + c = code | (RIGHTCODE << n); + m = n + 1; + + if (hufftree[x].isleaf) { + value = hufftree[x].value; + code_table[value] = c; + size_table[value] = (unsigned)m; + + #ifdef TRACK + printf ("value=%c:%d, code=%d \"%s\", size=%d\n", value,value, c, binstream(c,m), m); + #endif + + } else { + hufftree_to_codes(x, m, c); + } + + return; +} + + +static int +hufftree_frombits (ro_stream_t *stream, bool_t *pok) +{ + unsigned bit; + unsigned value; + int thisnode; + struct huff h; + + if (!*pok) + return 0; + + bit = stream_nextbit(stream); + if (bit == BITLEAF) { + /* leaf */ + value = stream_nextbit_n (stream, VALUEBITS); + thisnode = huff_end++; + h.isleaf = TRUE; + h.value = (int)value; + h.freq = 0; + h.pleft = 0; + h.pright = 0; + + if (thisnode >= MAXHUFF) { + *pok = FALSE; + return 0; + } + + hufftree[thisnode] = h; + + #ifdef TRACK + printf ("Huff leaf, %d=%c\n", value, value); + #endif + + return thisnode; + + } else { + /* node */ + thisnode = huff_end++; + + if (thisnode >= MAXHUFF) { + *pok = FALSE; + return 0; + } + + h.isleaf = FALSE; + h.value = -1; + h.freq = 0; + h.pleft = hufftree_frombits (stream, pok); + h.pright = hufftree_frombits (stream, pok); + hufftree[thisnode] = h; + return thisnode; + } +} + + +static void +hufftree_tobits (int thisnode, stream_t *stream) +{ + + if (hufftree[thisnode].isleaf) { + + #ifdef TRACK + {int c = hufftree[thisnode].value; printf ("[leaf=1][%c:%d=%s]", c, c, binstream(c,8));} + #endif + + assert (0 <= hufftree[thisnode].value); + + stream_writebit (stream, BITLEAF); + stream_write_n ((unsigned)hufftree[thisnode].value, VALUEBITS, stream); + + } else { + stream_writebit (stream, BITNODE); + + #ifdef TRACK + printf ("[node=0]"); + #endif + + hufftree_tobits (hufftree[thisnode].pleft, stream); + hufftree_tobits (hufftree[thisnode].pright, stream); + + } + return; +} + + +static unsigned int +hufftree_readstream (int root, ro_stream_t *s) +{ + unsigned bit; + int next; + + bit = stream_nextbit(s); + if (bit == RIGHTCODE) { + /* right */ + next = hufftree[root].pright; + } else { + /*ASSERT (bit == LEFTCODE */ + /* left */ + next = hufftree[root].pleft; + } + + if (hufftree[next].isleaf) { + assert (0 <= hufftree[next].value); + return (unsigned)hufftree[next].value; + } else { + return hufftree_readstream (next, s); + } +} + +/*==== HEAP ==========================================*/ + +static void +heap_init (void) +{ + heap_end = 1; + return; +} + +static void +heap_append (struct element e) +{ + /*ASSERT (heap_end < MAXHEAP);*/ + heap[heap_end++] = e; + return; +} + +static void +heap_sift_up (int x) +{ + struct element t; + int p; + int c = x; + while (c > 1) { + p = c / 2; + if (heap[c].freq < heap[p].freq) { + t = heap[c]; heap[c] = heap[p]; heap[p] = t; + } else { + break; + } + c = p; + } + return; +} + + + +static void +heap_adjust_down (int top, int last) +{ + struct element t; + int p; + int c; + int left, right; + + if (last == top) { /* at least top element */ + /* done */ + return; + } + + /* starts at the top */ + p = top; + + while (p <= last) + { + left = 2*p; + right = left + 1; + + if (left > last) + break; + + if (right <= last && (heap[right].freq < heap[left].freq)) + c = right; + else + c = left; + + if (c > last) + break; + + if (heap[c].freq < heap[p].freq) { + t = heap[c]; heap[c] = heap[p]; heap[p] = t; + } else { + break; + } + p = c; + } + return; +} + + +/* +static void +heap_plot (void) +{ + unsigned int line, limit, j; + int n = heap_end; + printf("===========================\n"); + line = 1; + j = 1; + while (j < n) { + limit = 1 << line; + while (j < limit && j < n) { + printf("%3d:%c ",heap[j].freq, hufftree[heap[j].huffidx].value); + j++; + } + while (j < limit) { + printf("%3s ","--"); + j++; + } + line++; printf("\n"); + } + printf("===========================\n"); + return; +} +*/ + +/* +static void +freq_report (void) +{ + int i; + printf ("\nFREQUENCIES\n"); + for (i = 0; i < MAXDIVERSITY; i++) { + if (freq[i] > 0) { + printf ("%c: %2d: %d: %d\n", i, i, freq[i], code_table[i]); + } + } + printf ("\n"); + return; +} +*/ + +static void +freq_init (const unsigned char *in, size_t max) +{ + size_t i; + + /* clean up frequencies */ + for (i = 0; i < MAXDIVERSITY; i++) { + freq [i] = 0; + code_table[i] = 0; + size_table[i] = 0; + } + + /* build frequencies */ + for (i = 0; i < max; i++) { + freq [in[i]]++; + } + + #ifdef TRACK + freq_report(); + #endif + + return; +} + +static int +hufftree_from_freq (void) +{ + int i; + struct huff h; + struct element e; + int root; + + hufftree_reset (); + + /* build huff tree elements */ + huff_end = 0; + for (i = 0; i < MAXDIVERSITY; i++) { + if (freq[i] > 0) { + h.isleaf = TRUE; + h.value = i; + h.freq = freq[i]; + h.pleft = 0; + h.pright = 0; + hufftree[huff_end++] = h; + } + } + + /* build heap */ + heap_init(); + for (i = 0; i < huff_end; i++) { + e.freq = hufftree[i].freq; + e.huffidx = i; + heap_append(e); + heap_sift_up(heap_end-1); + } + + #ifdef TRACE + heap_plot (); + #endif + + root = hufftree_from_heap(); + + /*hufftree_to_codes (root, 0, 0);*/ + + return root; +} + + + diff --git a/DroidFish/jni/gtb/compression/huffman/hzip.h b/DroidFish/jni/gtb/compression/huffman/hzip.h new file mode 100644 index 0000000..4382496 --- /dev/null +++ b/DroidFish/jni/gtb/compression/huffman/hzip.h @@ -0,0 +1,51 @@ +/* hzip.h */ +/* +| Routines designed to be used as a pilot experiment for compression +| of tablebases. Not really optimized, but they are supposed to work +| --Miguel A. Ballicora +*/ + +/* +This Software is distributed with the following X11 License, +sometimes also known as MIT license. + +Copyright (c) 2010 Miguel A. Ballicora + + 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. +*/ + +#if !defined(H_HZIP) +#define H_HZIP + +/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ +#include + +extern int +huff_decode +(const unsigned char *in_start, size_t in_len, unsigned char *out_start, size_t *pout_len, size_t out_max); + +extern int +huff_encode +(const unsigned char *in_start, size_t in_len, unsigned char *out_start, size_t *pout_len, size_t out_max); + +/*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ +#endif diff --git a/DroidFish/jni/gtb/compression/liblzf/LICENSE b/DroidFish/jni/gtb/compression/liblzf/LICENSE new file mode 100644 index 0000000..9d8e6ec --- /dev/null +++ b/DroidFish/jni/gtb/compression/liblzf/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2000-2007 Marc Alexander Lehmann + +Redistribution and use in source and binary forms, with or without modifica- +tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. 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 AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- +CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- +CIAL, 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 OTH- +ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +OF THE POSSIBILITY OF SUCH DAMAGE. + +Alternatively, the following files carry an additional notice that +explicitly allows relicensing under the GPLv2: lzf.c lzf.h lzfP.h lzf_c.c +lzf_d.c + diff --git a/DroidFish/jni/gtb/compression/liblzf/lzf.h b/DroidFish/jni/gtb/compression/liblzf/lzf.h new file mode 100644 index 0000000..919b6e6 --- /dev/null +++ b/DroidFish/jni/gtb/compression/liblzf/lzf.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2000-2008 Marc Alexander Lehmann + * + * Redistribution and use in source and binary forms, with or without modifica- + * tion, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. 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 AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- + * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- + * CIAL, 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 OTH- + * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Alternatively, the contents of this file may be used under the terms of + * the GNU General Public License ("GPL") version 2 or any later version, + * in which case the provisions of the GPL are applicable instead of + * the above. If you wish to allow the use of your version of this file + * only under the terms of the GPL and not to allow others to use your + * version of this file under the BSD license, indicate your decision + * by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL. If you do not delete the + * provisions above, a recipient may use your version of this file under + * either the BSD or the GPL. + */ + +#ifndef LZF_H +#define LZF_H + +/*********************************************************************** +** +** lzf -- an extremely fast/free compression/decompression-method +** http://liblzf.plan9.de/ +** +** This algorithm is believed to be patent-free. +** +***********************************************************************/ + +#define LZF_VERSION 0x0105 /* 1.5, API version */ + +/* + * Compress in_len bytes stored at the memory block starting at + * in_data and write the result to out_data, up to a maximum length + * of out_len bytes. + * + * If the output buffer is not large enough or any error occurs return 0, + * otherwise return the number of bytes used, which might be considerably + * more than in_len (but less than 104% of the original size), so it + * makes sense to always use out_len == in_len - 1), to ensure _some_ + * compression, and store the data uncompressed otherwise (with a flag, of + * course. + * + * lzf_compress might use different algorithms on different systems and + * even different runs, thus might result in different compressed strings + * depending on the phase of the moon or similar factors. However, all + * these strings are architecture-independent and will result in the + * original data when decompressed using lzf_decompress. + * + * The buffers must not be overlapping. + * + * If the option LZF_STATE_ARG is enabled, an extra argument must be + * supplied which is not reflected in this header file. Refer to lzfP.h + * and lzf_c.c. + * + */ +unsigned int +lzf_compress (const void *const in_data, unsigned int in_len, + void *out_data, unsigned int out_len); + +/* + * Decompress data compressed with some version of the lzf_compress + * function and stored at location in_data and length in_len. The result + * will be stored at out_data up to a maximum of out_len characters. + * + * If the output buffer is not large enough to hold the decompressed + * data, a 0 is returned and errno is set to E2BIG. Otherwise the number + * of decompressed bytes (i.e. the original length of the data) is + * returned. + * + * If an error in the compressed data is detected, a zero is returned and + * errno is set to EINVAL. + * + * This function is very fast, about as fast as a copying loop. + */ +unsigned int +lzf_decompress (const void *const in_data, unsigned int in_len, + void *out_data, unsigned int out_len); + +#endif + diff --git a/DroidFish/jni/gtb/compression/liblzf/lzfP.h b/DroidFish/jni/gtb/compression/liblzf/lzfP.h new file mode 100644 index 0000000..d533f18 --- /dev/null +++ b/DroidFish/jni/gtb/compression/liblzf/lzfP.h @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2000-2007 Marc Alexander Lehmann + * + * Redistribution and use in source and binary forms, with or without modifica- + * tion, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. 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 AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- + * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- + * CIAL, 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 OTH- + * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Alternatively, the contents of this file may be used under the terms of + * the GNU General Public License ("GPL") version 2 or any later version, + * in which case the provisions of the GPL are applicable instead of + * the above. If you wish to allow the use of your version of this file + * only under the terms of the GPL and not to allow others to use your + * version of this file under the BSD license, indicate your decision + * by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL. If you do not delete the + * provisions above, a recipient may use your version of this file under + * either the BSD or the GPL. + */ + +#ifndef LZFP_h +#define LZFP_h + +#define STANDALONE 1 /* at the moment, this is ok. */ + +#ifndef STANDALONE +# include "lzf.h" +#endif + +/* + * Size of hashtable is (1 << HLOG) * sizeof (char *) + * decompression is independent of the hash table size + * the difference between 15 and 14 is very small + * for small blocks (and 14 is usually a bit faster). + * For a low-memory/faster configuration, use HLOG == 13; + * For best compression, use 15 or 16 (or more, up to 23). + */ +#ifndef HLOG +# define HLOG 16 +#endif + +/* + * Sacrifice very little compression quality in favour of compression speed. + * This gives almost the same compression as the default code, and is + * (very roughly) 15% faster. This is the preferred mode of operation. + */ +#ifndef VERY_FAST +# define VERY_FAST 1 +#endif + +/* + * Sacrifice some more compression quality in favour of compression speed. + * (roughly 1-2% worse compression for large blocks and + * 9-10% for small, redundant, blocks and >>20% better speed in both cases) + * In short: when in need for speed, enable this for binary data, + * possibly disable this for text data. + */ +#ifndef ULTRA_FAST +# define ULTRA_FAST 0 +#endif + +/* + * Unconditionally aligning does not cost very much, so do it if unsure + */ +#ifndef STRICT_ALIGN +# define STRICT_ALIGN !(defined(__i386) || defined (__amd64)) +#endif + +/* + * You may choose to pre-set the hash table (might be faster on some + * modern cpus and large (>>64k) blocks, and also makes compression + * deterministic/repeatable when the configuration otherwise is the same). + */ +#ifndef INIT_HTAB +# define INIT_HTAB 0 +#endif + +/* + * Avoid assigning values to errno variable? for some embedding purposes + * (linux kernel for example), this is neccessary. NOTE: this breaks + * the documentation in lzf.h. + */ +#ifndef AVOID_ERRNO +# define AVOID_ERRNO 0 +#endif + +/* + * Wether to pass the LZF_STATE variable as argument, or allocate it + * on the stack. For small-stack environments, define this to 1. + * NOTE: this breaks the prototype in lzf.h. + */ +#ifndef LZF_STATE_ARG +# define LZF_STATE_ARG 0 +#endif + +/* + * Wether to add extra checks for input validity in lzf_decompress + * and return EINVAL if the input stream has been corrupted. This + * only shields against overflowing the input buffer and will not + * detect most corrupted streams. + * This check is not normally noticable on modern hardware + * (<1% slowdown), but might slow down older cpus considerably. + */ +#ifndef CHECK_INPUT +# define CHECK_INPUT 1 +#endif + +/*****************************************************************************/ +/* nothing should be changed below */ + +typedef unsigned char u8; + +typedef const u8 *LZF_STATE[1 << (HLOG)]; + +#if !STRICT_ALIGN +/* for unaligned accesses we need a 16 bit datatype. */ +# include +# if USHRT_MAX == 65535 + typedef unsigned short u16; +# elif UINT_MAX == 65535 + typedef unsigned int u16; +# else +# undef STRICT_ALIGN +# define STRICT_ALIGN 1 +# endif +#endif + +#if ULTRA_FAST +# if defined(VERY_FAST) +# undef VERY_FAST +# endif +#endif + +#if INIT_HTAB +# ifdef __cplusplus +# include +# else +# include +# endif +#endif + +#endif + diff --git a/DroidFish/jni/gtb/compression/liblzf/lzf_c.c b/DroidFish/jni/gtb/compression/liblzf/lzf_c.c new file mode 100644 index 0000000..a6d98e1 --- /dev/null +++ b/DroidFish/jni/gtb/compression/liblzf/lzf_c.c @@ -0,0 +1,302 @@ +/* + * Copyright (c) 2000-2008 Marc Alexander Lehmann + * + * Redistribution and use in source and binary forms, with or without modifica- + * tion, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. 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 AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- + * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- + * CIAL, 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 OTH- + * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Alternatively, the contents of this file may be used under the terms of + * the GNU General Public License ("GPL") version 2 or any later version, + * in which case the provisions of the GPL are applicable instead of + * the above. If you wish to allow the use of your version of this file + * only under the terms of the GPL and not to allow others to use your + * version of this file under the BSD license, indicate your decision + * by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL. If you do not delete the + * provisions above, a recipient may use your version of this file under + * either the BSD or the GPL. + */ + +/*MAB: added this include to silence compiler */ +#include "lzf.h" + +#include "lzfP.h" + +#define HSIZE (1 << (HLOG)) + +/* + * don't play with this unless you benchmark! + * decompression is not dependent on the hash function + * the hashing function might seem strange, just believe me + * it works ;) + */ +#ifndef FRST +# define FRST(p) (((p[0]) << 8) | p[1]) +# define NEXT(v,p) (((v) << 8) | p[2]) +# if ULTRA_FAST +# define IDX(h) ((( h >> (3*8 - HLOG)) - h ) & (HSIZE - 1)) +# elif VERY_FAST +# define IDX(h) ((( h >> (3*8 - HLOG)) - h*5) & (HSIZE - 1)) +# else +# define IDX(h) ((((h ^ (h << 5)) >> (3*8 - HLOG)) - h*5) & (HSIZE - 1)) +# endif +#endif +/* + * IDX works because it is very similar to a multiplicative hash, e.g. + * ((h * 57321 >> (3*8 - HLOG)) & (HSIZE - 1)) + * the latter is also quite fast on newer CPUs, and compresses similarly. + * + * the next one is also quite good, albeit slow ;) + * (int)(cos(h & 0xffffff) * 1e6) + */ + +#if 0 +/* original lzv-like hash function, much worse and thus slower */ +# define FRST(p) (p[0] << 5) ^ p[1] +# define NEXT(v,p) ((v) << 5) ^ p[2] +# define IDX(h) ((h) & (HSIZE - 1)) +#endif + +#define MAX_LIT (1 << 5) +#define MAX_OFF (1 << 13) +#define MAX_REF ((1 << 8) + (1 << 3)) + +#if __GNUC__ >= 3 +# define expect(expr,value) __builtin_expect ((expr),(value)) +# define inline inline +#else +# define expect(expr,value) (expr) +# define inline static +#endif + +#define expect_false(expr) expect ((expr) != 0, 0) +#define expect_true(expr) expect ((expr) != 0, 1) + +/* + * compressed format + * + * 000LLLLL ; literal + * LLLooooo oooooooo ; backref L + * 111ooooo LLLLLLLL oooooooo ; backref L+7 + * + */ + +unsigned int +lzf_compress (const void *const in_data, unsigned int in_len, + void *out_data, unsigned int out_len +#if LZF_STATE_ARG + , LZF_STATE htab +#endif + ) +{ +#if !LZF_STATE_ARG + LZF_STATE htab; +#endif + const u8 **hslot; + const u8 *ip = (const u8 *)in_data; + u8 *op = (u8 *)out_data; + const u8 *in_end = ip + in_len; + u8 *out_end = op + out_len; + const u8 *ref; + + /* off requires a type wide enough to hold a general pointer difference. + * ISO C doesn't have that (size_t might not be enough and ptrdiff_t only + * works for differences within a single object). We also assume that no + * no bit pattern traps. Since the only platform that is both non-POSIX + * and fails to support both assumptions is windows 64 bit, we make a + * special workaround for it. + */ +#if defined (WIN32) && defined (_M_X64) + /*MAB fix bug, it is __int64 rather than _int64 */ + unsigned __int64 off; /* workaround for missing POSIX compliance */ +#else + unsigned long off; +#endif + unsigned int hval; + int lit; + + if (!in_len || !out_len) + return 0; + +#if INIT_HTAB + memset (htab, 0, sizeof (htab)); +# if 0 + for (hslot = htab; hslot < htab + HSIZE; hslot++) + *hslot++ = ip; +# endif +#endif + + lit = 0; op++; /* start run */ + + hval = (unsigned)(FRST (ip)); /*MAB silence warning with cast*/ + while (ip < in_end - 2) + { + hval = NEXT (hval, ip); + hslot = htab + IDX (hval); + ref = *hslot; *hslot = ip; + + if ( +/*MAB: Remove 1, it was a constant, to silence compiler */ +#if INIT_HTAB + ref < ip /* the next test will actually take care of this, but this is faster */ + && +#endif + (off = (unsigned long)(ip - ref - 1)) < MAX_OFF /*MAB silence warning with cast */ + && ip + 4 < in_end + && ref > (u8 *)in_data +#if STRICT_ALIGN + && ref[0] == ip[0] + && ref[1] == ip[1] + && ref[2] == ip[2] +#else + && *(u16 *)ref == *(u16 *)ip + && ref[2] == ip[2] +#endif + ) + { + /* match found at *ref++ */ + unsigned int len = 2; + unsigned int maxlen = (unsigned)(in_end - ip - (int)len); /* MAB silence warning with casting */ + maxlen = maxlen > MAX_REF ? MAX_REF : maxlen; + + if (expect_false (op + 3 + 1 >= out_end)) /* first a faster conservative test */ + if (op - !lit + 3 + 1 >= out_end) /* second the exact but rare test */ + return 0; + + op [- lit - 1] = (u8) (lit - 1); /* stop run */ /*MAB: Casting to u8 to silence compiler */ + op -= !lit; /* undo run if length is zero */ + + for (;;) + { + if (expect_true (maxlen > 16)) + { + len++; if (ref [len] != ip [len]) break; + len++; if (ref [len] != ip [len]) break; + len++; if (ref [len] != ip [len]) break; + len++; if (ref [len] != ip [len]) break; + + len++; if (ref [len] != ip [len]) break; + len++; if (ref [len] != ip [len]) break; + len++; if (ref [len] != ip [len]) break; + len++; if (ref [len] != ip [len]) break; + + len++; if (ref [len] != ip [len]) break; + len++; if (ref [len] != ip [len]) break; + len++; if (ref [len] != ip [len]) break; + len++; if (ref [len] != ip [len]) break; + + len++; if (ref [len] != ip [len]) break; + len++; if (ref [len] != ip [len]) break; + len++; if (ref [len] != ip [len]) break; + len++; if (ref [len] != ip [len]) break; + } + + do + len++; + while (len < maxlen && ref[len] == ip[len]); + + break; + } + + len -= 2; /* len is now #octets - 1 */ + ip++; + + if (len < 7) + { + *op++ = (u8) ((off >> 8) + (len << 5)); /*MAB: Casting to u8 to silence compiler */ + } + else + { + *op++ = (u8) ((off >> 8) + ( 7 << 5)); /*MAB: Casting to u8 to silence compiler */ + *op++ = (u8) (len - 7); /*MAB: Casting to u8 to silence compiler */ + } + + *op++ = (u8) off; /*MAB: Casting to u8 to silence compiler */ + lit = 0; op++; /* start run */ + + ip += len + 1; + + if (expect_false (ip >= in_end - 2)) + break; + +#if ULTRA_FAST || VERY_FAST + --ip; +# if VERY_FAST && !ULTRA_FAST + --ip; +# endif + hval = (unsigned)(FRST (ip)); /*MAB silence warning with cast*/ + + hval = NEXT (hval, ip); + htab[IDX (hval)] = ip; + ip++; + +# if VERY_FAST && !ULTRA_FAST + hval = NEXT (hval, ip); + htab[IDX (hval)] = ip; + ip++; +# endif +#else + ip -= len + 1; + + do + { + hval = NEXT (hval, ip); + htab[IDX (hval)] = ip; + ip++; + } + while (len--); +#endif + } + else + { + /* one more literal byte we must copy */ + if (expect_false (op >= out_end)) + return 0; + + lit++; *op++ = *ip++; + + if (expect_false (lit == MAX_LIT)) + { + op [- lit - 1] = (u8) (lit - 1); /* stop run */ /*MAB: Casting to u8 to silence compiler */ + lit = 0; op++; /* start run */ + } + } + } + + if (op + 3 > out_end) /* at most 3 bytes can be missing here */ + return 0; + + while (ip < in_end) + { + lit++; *op++ = *ip++; + + if (expect_false (lit == MAX_LIT)) + { + op [- lit - 1] = (u8) (lit - 1); /* stop run */ /*MAB: Casting to u8 to silence compiler */ + lit = 0; op++; /* start run */ + } + } + + op [- lit - 1] = (u8) (lit - 1); /* end run */ /*MAB: Casting to u8 to silence compiler */ + op -= !lit; /* undo run if length is zero */ + + return (unsigned)(op - (u8 *)out_data); /*MAB: Casting to unsigned to silence compiler */ +} + diff --git a/DroidFish/jni/gtb/compression/liblzf/lzf_d.c b/DroidFish/jni/gtb/compression/liblzf/lzf_d.c new file mode 100644 index 0000000..3bb91ab --- /dev/null +++ b/DroidFish/jni/gtb/compression/liblzf/lzf_d.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2000-2007 Marc Alexander Lehmann + * + * Redistribution and use in source and binary forms, with or without modifica- + * tion, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. 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 AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- + * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- + * CIAL, 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 OTH- + * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Alternatively, the contents of this file may be used under the terms of + * the GNU General Public License ("GPL") version 2 or any later version, + * in which case the provisions of the GPL are applicable instead of + * the above. If you wish to allow the use of your version of this file + * only under the terms of the GPL and not to allow others to use your + * version of this file under the BSD license, indicate your decision + * by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL. If you do not delete the + * provisions above, a recipient may use your version of this file under + * either the BSD or the GPL. + */ + +/*MAB: added this include to silence compiler */ +#include "lzf.h" + +#include "lzfP.h" + +#if AVOID_ERRNO +# define SET_ERRNO(n) +#else +# include +# define SET_ERRNO(n) errno = (n) +#endif + +/*MAB: __i386 and __amd64 surrounded by defined() to silence intel compiler */ +/*MAB: added __STRICT_ANSI__ flag so it could be checked with -ansi -pedantic */ +#if (defined(__i386) || defined(__amd64)) && __GNUC__ >= 3 && !defined(__STRICT_ANSI__) +# define lzf_movsb(dst, src, len) \ + asm ("rep movsb" \ + : "=D" (dst), "=S" (src), "=c" (len) \ + : "0" (dst), "1" (src), "2" (len)); +#endif + +unsigned int +lzf_decompress (const void *const in_data, unsigned int in_len, + void *out_data, unsigned int out_len) +{ + u8 const *ip = (const u8 *)in_data; + u8 *op = (u8 *)out_data; + u8 const *const in_end = ip + in_len; + u8 *const out_end = op + out_len; + + do + { + unsigned int ctrl = *ip++; + + if (ctrl < (1 << 5)) /* literal run */ + { + ctrl++; + + if (op + ctrl > out_end) + { + SET_ERRNO (E2BIG); + return 0; + } + +#if CHECK_INPUT + if (ip + ctrl > in_end) + { + SET_ERRNO (EINVAL); + return 0; + } +#endif + +#ifdef lzf_movsb + lzf_movsb (op, ip, ctrl); +#else + do + *op++ = *ip++; + while (--ctrl); +#endif + } + else /* back reference */ + { + unsigned int len = ctrl >> 5; + + u8 *ref = op - ((ctrl & 0x1f) << 8) - 1; + +#if CHECK_INPUT + if (ip >= in_end) + { + SET_ERRNO (EINVAL); + return 0; + } +#endif + if (len == 7) + { + len += *ip++; +#if CHECK_INPUT + if (ip >= in_end) + { + SET_ERRNO (EINVAL); + return 0; + } +#endif + } + + ref -= *ip++; + + if (op + len + 2 > out_end) + { + SET_ERRNO (E2BIG); + return 0; + } + + if (ref < (u8 *)out_data) + { + SET_ERRNO (EINVAL); + return 0; + } + +#ifdef lzf_movsb + len += 2; + lzf_movsb (op, ref, len); +#else + *op++ = *ref++; + *op++ = *ref++; + + do + *op++ = *ref++; + while (--len); +#endif + } + } + while (ip < in_end); + +#if 0 + return op - (u8 *)out_data; +#else + return (unsigned int)(op - (u8 *)out_data); /*MAB: cast to silence warning */ +#endif +} + diff --git a/DroidFish/jni/gtb/compression/lzma/Alloc.c b/DroidFish/jni/gtb/compression/lzma/Alloc.c new file mode 100755 index 0000000..eb5196b --- /dev/null +++ b/DroidFish/jni/gtb/compression/lzma/Alloc.c @@ -0,0 +1,127 @@ +/* Alloc.c -- Memory allocation functions +2008-09-24 +Igor Pavlov +Public domain */ + +#ifdef _WIN32 +#include +#endif +#include + +#include "Alloc.h" + +/* #define _SZ_ALLOC_DEBUG */ + +/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ +#ifdef _SZ_ALLOC_DEBUG +#include +int g_allocCount = 0; +int g_allocCountMid = 0; +int g_allocCountBig = 0; +#endif + +void *MyAlloc(size_t size) +{ + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + { + void *p = malloc(size); + fprintf(stderr, "\nAlloc %10d bytes, count = %10d, addr = %8X", size, g_allocCount++, (unsigned)p); + return p; + } + #else + return malloc(size); + #endif +} + +void MyFree(void *address) +{ + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + fprintf(stderr, "\nFree; count = %10d, addr = %8X", --g_allocCount, (unsigned)address); + #endif + free(address); +} + +#ifdef _WIN32 + +void *MidAlloc(size_t size) +{ + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + fprintf(stderr, "\nAlloc_Mid %10d bytes; count = %10d", size, g_allocCountMid++); + #endif + return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); +} + +void MidFree(void *address) +{ + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid); + #endif + if (address == 0) + return; + VirtualFree(address, 0, MEM_RELEASE); +} + +#ifndef MEM_LARGE_PAGES +#undef _7ZIP_LARGE_PAGES +#endif + +#ifdef _7ZIP_LARGE_PAGES +SIZE_T g_LargePageSize = 0; +typedef SIZE_T (WINAPI *GetLargePageMinimumP)(); +#endif + +void SetLargePageSize(void) +{ + #ifdef _7ZIP_LARGE_PAGES + SIZE_T size = 0; + GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP) + GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum"); + if (largePageMinimum == 0) + return; + size = largePageMinimum(); + if (size == 0 || (size & (size - 1)) != 0) + return; + g_LargePageSize = size; + #endif +} + + +void *BigAlloc(size_t size) +{ + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + fprintf(stderr, "\nAlloc_Big %10d bytes; count = %10d", size, g_allocCountBig++); + #endif + + #ifdef _7ZIP_LARGE_PAGES + if (g_LargePageSize != 0 && g_LargePageSize <= (1 << 30) && size >= (1 << 18)) + { + void *res = VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)), + MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); + if (res != 0) + return res; + } + #endif + return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); +} + +void BigFree(void *address) +{ + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig); + #endif + + if (address == 0) + return; + VirtualFree(address, 0, MEM_RELEASE); +} + +#endif diff --git a/DroidFish/jni/gtb/compression/lzma/Alloc.h b/DroidFish/jni/gtb/compression/lzma/Alloc.h new file mode 100755 index 0000000..9d81f1f --- /dev/null +++ b/DroidFish/jni/gtb/compression/lzma/Alloc.h @@ -0,0 +1,32 @@ +/* Alloc.h -- Memory allocation functions +2008-03-13 +Igor Pavlov +Public domain */ + +#ifndef __COMMON_ALLOC_H +#define __COMMON_ALLOC_H + +#include + +void *MyAlloc(size_t size); +void MyFree(void *address); + +#ifdef _WIN32 + +void SetLargePageSize(void); + +void *MidAlloc(size_t size); +void MidFree(void *address); +void *BigAlloc(size_t size); +void BigFree(void *address); + +#else + +#define MidAlloc(size) MyAlloc(size) +#define MidFree(address) MyFree(address) +#define BigAlloc(size) MyAlloc(size) +#define BigFree(address) MyFree(address) + +#endif + +#endif diff --git a/DroidFish/jni/gtb/compression/lzma/Bra.h b/DroidFish/jni/gtb/compression/lzma/Bra.h new file mode 100755 index 0000000..b9018eb --- /dev/null +++ b/DroidFish/jni/gtb/compression/lzma/Bra.h @@ -0,0 +1,60 @@ +/* Bra.h -- Branch converters for executables +2008-10-04 : Igor Pavlov : Public domain */ + +#ifndef __BRA_H +#define __BRA_H + +#include "Types.h" + +/* +These functions convert relative addresses to absolute addresses +in CALL instructions to increase the compression ratio. + + In: + data - data buffer + size - size of data + ip - current virtual Instruction Pinter (IP) value + state - state variable for x86 converter + encoding - 0 (for decoding), 1 (for encoding) + + Out: + state - state variable for x86 converter + + Returns: + The number of processed bytes. If you call these functions with multiple calls, + you must start next call with first byte after block of processed bytes. + + Type Endian Alignment LookAhead + + x86 little 1 4 + ARMT little 2 2 + ARM little 4 0 + PPC big 4 0 + SPARC big 4 0 + IA64 little 16 0 + + size must be >= Alignment + LookAhead, if it's not last block. + If (size < Alignment + LookAhead), converter returns 0. + + Example: + + UInt32 ip = 0; + for () + { + ; size must be >= Alignment + LookAhead, if it's not last block + SizeT processed = Convert(data, size, ip, 1); + data += processed; + size -= processed; + ip += processed; + } +*/ + +#define x86_Convert_Init(state) { state = 0; } +SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding); +SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); +SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); +SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); +SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); +SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); + +#endif diff --git a/DroidFish/jni/gtb/compression/lzma/Bra86.c b/DroidFish/jni/gtb/compression/lzma/Bra86.c new file mode 100755 index 0000000..5bec666 --- /dev/null +++ b/DroidFish/jni/gtb/compression/lzma/Bra86.c @@ -0,0 +1,85 @@ +/* Bra86.c -- Converter for x86 code (BCJ) +2008-10-04 : Igor Pavlov : Public domain */ + +#include "Bra.h" + +#define Test86MSByte(b) ((b) == 0 || (b) == 0xFF) + +const Byte kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0}; +const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3}; + +SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding) +{ + SizeT bufferPos = 0, prevPosT; + UInt32 prevMask = *state & 0x7; + if (size < 5) + return 0; + ip += 5; + prevPosT = (SizeT)0 - 1; + + for (;;) + { + Byte *p = data + bufferPos; + Byte *limit = data + size - 4; + for (; p < limit; p++) + if ((*p & 0xFE) == 0xE8) + break; + bufferPos = (SizeT)(p - data); + if (p >= limit) + break; + prevPosT = bufferPos - prevPosT; + if (prevPosT > 3) + prevMask = 0; + else + { + prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7; + if (prevMask != 0) + { + Byte b = p[4 - kMaskToBitNumber[prevMask]]; + if (!kMaskToAllowedStatus[prevMask] || Test86MSByte(b)) + { + prevPosT = bufferPos; + prevMask = ((prevMask << 1) & 0x7) | 1; + bufferPos++; + continue; + } + } + } + prevPosT = bufferPos; + + if (Test86MSByte(p[4])) + { + UInt32 src = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]); + UInt32 dest; + for (;;) + { + Byte b; + int index; + if (encoding) + dest = (ip + (UInt32)bufferPos) + src; + else + dest = src - (ip + (UInt32)bufferPos); + if (prevMask == 0) + break; + index = kMaskToBitNumber[prevMask] * 8; + b = (Byte)(dest >> (24 - index)); + if (!Test86MSByte(b)) + break; + src = dest ^ (((UInt32)1 << (32 - index)) - (UInt32)1); + } + p[4] = (Byte)(~(((dest >> 24) & 1) - 1)); + p[3] = (Byte)(dest >> 16); + p[2] = (Byte)(dest >> 8); + p[1] = (Byte)dest; + bufferPos += 5; + } + else + { + prevMask = ((prevMask << 1) & 0x7) | 1; + bufferPos++; + } + } + prevPosT = bufferPos - prevPosT; + *state = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7)); + return bufferPos; +} diff --git a/DroidFish/jni/gtb/compression/lzma/LzFind.c b/DroidFish/jni/gtb/compression/lzma/LzFind.c new file mode 100755 index 0000000..51ae22e --- /dev/null +++ b/DroidFish/jni/gtb/compression/lzma/LzFind.c @@ -0,0 +1,758 @@ +/* LzFind.c -- Match finder for LZ algorithms +2008-10-04 : Igor Pavlov : Public domain */ + +#include + +#include "LzFind.h" +#include "LzHash.h" + +#define kEmptyHashValue 0 +#define kMaxValForNormalize ((UInt32)0xFFFFFFFF) +#define kNormalizeStepMin (1u << 10) /* it must be power of 2 */ /*MAB 1u */ +#define kNormalizeMask (~(kNormalizeStepMin - 1)) +#define kMaxHistorySize ((UInt32)3 << 30) + +#define kStartMaxLen 3 + +static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc) +{ + if (!p->directInput) + { + alloc->Free(alloc, p->bufferBase); + p->bufferBase = 0; + } +} + +/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */ + +static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc) +{ + UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv; + if (p->directInput) + { + p->blockSize = blockSize; + return 1; + } + if (p->bufferBase == 0 || p->blockSize != blockSize) + { + LzInWindow_Free(p, alloc); + p->blockSize = blockSize; + p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize); + } + return (p->bufferBase != 0); +} + +Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } + +/*MAB: static added, index replaced by idx to avoid shadowing a global variable */ +static +Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 idx) { return p->buffer[idx]; } + +/*MAB: static added */ +static +UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; } + +void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue) +{ + p->posLimit -= subValue; + p->pos -= subValue; + p->streamPos -= subValue; +} + +static void MatchFinder_ReadBlock(CMatchFinder *p) +{ + if (p->streamEndWasReached || p->result != SZ_OK) + return; + for (;;) + { + Byte *dest = p->buffer + (p->streamPos - p->pos); + size_t size = (size_t)(p->bufferBase + p->blockSize - dest); + if (size == 0) + return; + p->result = p->stream->Read(p->stream, dest, &size); + if (p->result != SZ_OK) + return; + if (size == 0) + { + p->streamEndWasReached = 1; + return; + } + p->streamPos += (UInt32)size; + if (p->streamPos - p->pos > p->keepSizeAfter) + return; + } +} + +void MatchFinder_MoveBlock(CMatchFinder *p) +{ + memmove(p->bufferBase, + p->buffer - p->keepSizeBefore, + (size_t)(p->streamPos - p->pos + p->keepSizeBefore)); + p->buffer = p->bufferBase + p->keepSizeBefore; +} + +int MatchFinder_NeedMove(CMatchFinder *p) +{ + /* if (p->streamEndWasReached) return 0; */ + return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter); +} + +void MatchFinder_ReadIfRequired(CMatchFinder *p) +{ + if (p->streamEndWasReached) + return; + if (p->keepSizeAfter >= p->streamPos - p->pos) + MatchFinder_ReadBlock(p); +} + +static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p) +{ + if (MatchFinder_NeedMove(p)) + MatchFinder_MoveBlock(p); + MatchFinder_ReadBlock(p); +} + +static void MatchFinder_SetDefaultSettings(CMatchFinder *p) +{ + p->cutValue = 32; + p->btMode = 1; + p->numHashBytes = 4; + /* p->skipModeBits = 0; */ + p->directInput = 0; + p->bigHash = 0; +} + +#define kCrcPoly 0xEDB88320 + +void MatchFinder_Construct(CMatchFinder *p) +{ + UInt32 i; + p->bufferBase = 0; + p->directInput = 0; + p->hash = 0; + MatchFinder_SetDefaultSettings(p); + + for (i = 0; i < 256; i++) + { + UInt32 r = i; + int j; + for (j = 0; j < 8; j++) + r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); + p->crc[i] = r; + } +} + +static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->hash); + p->hash = 0; +} + +void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc) +{ + MatchFinder_FreeThisClassMemory(p, alloc); + LzInWindow_Free(p, alloc); +} + +static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc) +{ + size_t sizeInBytes = (size_t)num * sizeof(CLzRef); + if (sizeInBytes / sizeof(CLzRef) != num) + return 0; + return (CLzRef *)alloc->Alloc(alloc, sizeInBytes); +} + +int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, + UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, + ISzAlloc *alloc) +{ + UInt32 sizeReserv; + if (historySize > kMaxHistorySize) + { + MatchFinder_Free(p, alloc); + return 0; + } + sizeReserv = historySize >> 1; + if (historySize > ((UInt32)2 << 30)) + sizeReserv = historySize >> 2; + sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19); + + p->keepSizeBefore = historySize + keepAddBufferBefore + 1; + p->keepSizeAfter = matchMaxLen + keepAddBufferAfter; + /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */ + if (LzInWindow_Create(p, sizeReserv, alloc)) + { + UInt32 newCyclicBufferSize = (historySize /* >> p->skipModeBits */) + 1; + UInt32 hs; + p->matchMaxLen = matchMaxLen; + { + p->fixedHashSize = 0; + if (p->numHashBytes == 2) + hs = (1 << 16) - 1; + else + { + hs = historySize - 1; + hs |= (hs >> 1); + hs |= (hs >> 2); + hs |= (hs >> 4); + hs |= (hs >> 8); + hs >>= 1; + /* hs >>= p->skipModeBits; */ + hs |= 0xFFFF; /* don't change it! It's required for Deflate */ + if (hs > (1 << 24)) + { + if (p->numHashBytes == 3) + hs = (1 << 24) - 1; + else + hs >>= 1; + } + } + p->hashMask = hs; + hs++; + if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size; + if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size; + if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size; + hs += p->fixedHashSize; + } + + { + UInt32 prevSize = p->hashSizeSum + p->numSons; + UInt32 newSize; + p->historySize = historySize; + p->hashSizeSum = hs; + p->cyclicBufferSize = newCyclicBufferSize; + p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize); + newSize = p->hashSizeSum + p->numSons; + if (p->hash != 0 && prevSize == newSize) + return 1; + MatchFinder_FreeThisClassMemory(p, alloc); + p->hash = AllocRefs(newSize, alloc); + if (p->hash != 0) + { + p->son = p->hash + p->hashSizeSum; + return 1; + } + } + } + MatchFinder_Free(p, alloc); + return 0; +} + +static void MatchFinder_SetLimits(CMatchFinder *p) +{ + UInt32 limit = kMaxValForNormalize - p->pos; + UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos; + if (limit2 < limit) + limit = limit2; + limit2 = p->streamPos - p->pos; + if (limit2 <= p->keepSizeAfter) + { + if (limit2 > 0) + limit2 = 1; + } + else + limit2 -= p->keepSizeAfter; + if (limit2 < limit) + limit = limit2; + { + UInt32 lenLimit = p->streamPos - p->pos; + if (lenLimit > p->matchMaxLen) + lenLimit = p->matchMaxLen; + p->lenLimit = lenLimit; + } + p->posLimit = p->pos + limit; +} + +void MatchFinder_Init(CMatchFinder *p) +{ + UInt32 i; + for (i = 0; i < p->hashSizeSum; i++) + p->hash[i] = kEmptyHashValue; + p->cyclicBufferPos = 0; + p->buffer = p->bufferBase; + p->pos = p->streamPos = p->cyclicBufferSize; + p->result = SZ_OK; + p->streamEndWasReached = 0; + MatchFinder_ReadBlock(p); + MatchFinder_SetLimits(p); +} + +static UInt32 MatchFinder_GetSubValue(CMatchFinder *p) +{ + return (p->pos - p->historySize - 1) & kNormalizeMask; +} + +void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems) +{ + UInt32 i; + for (i = 0; i < numItems; i++) + { + UInt32 value = items[i]; + if (value <= subValue) + value = kEmptyHashValue; + else + value -= subValue; + items[i] = value; + } +} + +static void MatchFinder_Normalize(CMatchFinder *p) +{ + UInt32 subValue = MatchFinder_GetSubValue(p); + MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons); + MatchFinder_ReduceOffsets(p, subValue); +} + +static void MatchFinder_CheckLimits(CMatchFinder *p) +{ + if (p->pos == kMaxValForNormalize) + MatchFinder_Normalize(p); + + if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos) + MatchFinder_CheckAndMoveAndRead(p); + if (p->cyclicBufferPos == p->cyclicBufferSize) + p->cyclicBufferPos = 0; + MatchFinder_SetLimits(p); +} + +static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, + UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, + UInt32 *distances, UInt32 maxLen) +{ + son[_cyclicBufferPos] = curMatch; + for (;;) + { + UInt32 delta = pos - curMatch; + if (cutValue-- == 0 || delta >= _cyclicBufferSize) + return distances; + { + const Byte *pb = cur - delta; + curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)]; + if (pb[maxLen] == cur[maxLen] && *pb == *cur) + { + UInt32 len = 0; + while (++len != lenLimit) + if (pb[len] != cur[len]) + break; + if (maxLen < len) + { + *distances++ = maxLen = len; + *distances++ = delta - 1; + if (len == lenLimit) + return distances; + } + } + } + } +} + +UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, + UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, + UInt32 *distances, UInt32 maxLen) +{ + CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; + CLzRef *ptr1 = son + (_cyclicBufferPos << 1); + UInt32 len0 = 0, len1 = 0; + for (;;) + { + UInt32 delta = pos - curMatch; + if (cutValue-- == 0 || delta >= _cyclicBufferSize) + { + *ptr0 = *ptr1 = kEmptyHashValue; + return distances; + } + { + CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); + const Byte *pb = cur - delta; + UInt32 len = (len0 < len1 ? len0 : len1); + if (pb[len] == cur[len]) + { + if (++len != lenLimit && pb[len] == cur[len]) + while (++len != lenLimit) + if (pb[len] != cur[len]) + break; + if (maxLen < len) + { + *distances++ = maxLen = len; + *distances++ = delta - 1; + if (len == lenLimit) + { + *ptr1 = pair[0]; + *ptr0 = pair[1]; + return distances; + } + } + } + if (pb[len] < cur[len]) + { + *ptr1 = curMatch; + ptr1 = pair + 1; + curMatch = *ptr1; + len1 = len; + } + else + { + *ptr0 = curMatch; + ptr0 = pair; + curMatch = *ptr0; + len0 = len; + } + } + } +} + +static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, + UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue) +{ + CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; + CLzRef *ptr1 = son + (_cyclicBufferPos << 1); + UInt32 len0 = 0, len1 = 0; + for (;;) + { + UInt32 delta = pos - curMatch; + if (cutValue-- == 0 || delta >= _cyclicBufferSize) + { + *ptr0 = *ptr1 = kEmptyHashValue; + return; + } + { + CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); + const Byte *pb = cur - delta; + UInt32 len = (len0 < len1 ? len0 : len1); + if (pb[len] == cur[len]) + { + while (++len != lenLimit) + if (pb[len] != cur[len]) + break; + { + if (len == lenLimit) + { + *ptr1 = pair[0]; + *ptr0 = pair[1]; + return; + } + } + } + if (pb[len] < cur[len]) + { + *ptr1 = curMatch; + ptr1 = pair + 1; + curMatch = *ptr1; + len1 = len; + } + else + { + *ptr0 = curMatch; + ptr0 = pair; + curMatch = *ptr0; + len0 = len; + } + } + } +} + +#define MOVE_POS \ + ++p->cyclicBufferPos; \ + p->buffer++; \ + if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p); + +#define MOVE_POS_RET MOVE_POS return offset; + +static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; } + +#define GET_MATCHES_HEADER2(minLen, ret_op) \ + UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \ + lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \ + cur = p->buffer; + +#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0) +#define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue) + +#define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue + +#define GET_MATCHES_FOOTER(offset, maxLen) \ + offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \ + distances + offset, maxLen) - distances); MOVE_POS_RET; + +#define SKIP_FOOTER \ + SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS; + +static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 offset; + GET_MATCHES_HEADER(2) + HASH2_CALC; + curMatch = p->hash[hashValue]; + p->hash[hashValue] = p->pos; + offset = 0; + GET_MATCHES_FOOTER(offset, 1) +} + +UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 offset; + GET_MATCHES_HEADER(3) + HASH_ZIP_CALC; + curMatch = p->hash[hashValue]; + p->hash[hashValue] = p->pos; + offset = 0; + GET_MATCHES_FOOTER(offset, 2) +} + +static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 hash2Value, delta2, maxLen, offset; + GET_MATCHES_HEADER(3) + + HASH3_CALC; + + delta2 = p->pos - p->hash[hash2Value]; + curMatch = p->hash[kFix3HashSize + hashValue]; + + p->hash[hash2Value] = + p->hash[kFix3HashSize + hashValue] = p->pos; + + + maxLen = 2; + offset = 0; + if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) + { + for (; maxLen != lenLimit; maxLen++) + if (cur[(ptrdiff_t)maxLen - (ptrdiff_t)delta2] != cur[maxLen]) /*MAB second casts (ptrdiff_t)*/ + break; + distances[0] = maxLen; + distances[1] = delta2 - 1; + offset = 2; + if (maxLen == lenLimit) + { + SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); + MOVE_POS_RET; + } + } + GET_MATCHES_FOOTER(offset, maxLen) +} + +static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; + GET_MATCHES_HEADER(4) + + HASH4_CALC; + + delta2 = p->pos - p->hash[ hash2Value]; + delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; + curMatch = p->hash[kFix4HashSize + hashValue]; + + p->hash[ hash2Value] = + p->hash[kFix3HashSize + hash3Value] = + p->hash[kFix4HashSize + hashValue] = p->pos; + + maxLen = 1; + offset = 0; + if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) + { + distances[0] = maxLen = 2; + distances[1] = delta2 - 1; + offset = 2; + } + if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) + { + maxLen = 3; + distances[offset + 1] = delta3 - 1; + offset += 2; + delta2 = delta3; + } + if (offset != 0) + { + for (; maxLen != lenLimit; maxLen++) + if (cur[(ptrdiff_t)maxLen - (ptrdiff_t)delta2] != cur[maxLen]) /*MAB casts second (ptrdiff_t)*/ + break; + distances[offset - 2] = maxLen; + if (maxLen == lenLimit) + { + SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); + MOVE_POS_RET; + } + } + if (maxLen < 3) + maxLen = 3; + GET_MATCHES_FOOTER(offset, maxLen) +} + +static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; + GET_MATCHES_HEADER(4) + + HASH4_CALC; + + delta2 = p->pos - p->hash[ hash2Value]; + delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; + curMatch = p->hash[kFix4HashSize + hashValue]; + + p->hash[ hash2Value] = + p->hash[kFix3HashSize + hash3Value] = + p->hash[kFix4HashSize + hashValue] = p->pos; + + maxLen = 1; + offset = 0; + if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) + { + distances[0] = maxLen = 2; + distances[1] = delta2 - 1; + offset = 2; + } + if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) + { + maxLen = 3; + distances[offset + 1] = delta3 - 1; + offset += 2; + delta2 = delta3; + } + if (offset != 0) + { + for (; maxLen != lenLimit; maxLen++) + if (cur[(ptrdiff_t)maxLen - (ptrdiff_t)delta2] != cur[maxLen]) /*MAB casts second (ptrdiff_t) */ + break; + + distances[offset - 2] = maxLen; + if (maxLen == lenLimit) + { + p->son[p->cyclicBufferPos] = curMatch; + MOVE_POS_RET; + } + } + if (maxLen < 3) + maxLen = 3; + offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), + distances + offset, maxLen) - (distances)); + MOVE_POS_RET +} + +UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 offset; + GET_MATCHES_HEADER(3) + HASH_ZIP_CALC; + curMatch = p->hash[hashValue]; + p->hash[hashValue] = p->pos; + offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), + distances, 2) - (distances)); + MOVE_POS_RET +} + +static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + SKIP_HEADER(2) + HASH2_CALC; + curMatch = p->hash[hashValue]; + p->hash[hashValue] = p->pos; + SKIP_FOOTER + } + while (--num != 0); +} + +void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + SKIP_HEADER(3) + HASH_ZIP_CALC; + curMatch = p->hash[hashValue]; + p->hash[hashValue] = p->pos; + SKIP_FOOTER + } + while (--num != 0); +} + +static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + UInt32 hash2Value; + SKIP_HEADER(3) + HASH3_CALC; + curMatch = p->hash[kFix3HashSize + hashValue]; + p->hash[hash2Value] = + p->hash[kFix3HashSize + hashValue] = p->pos; + SKIP_FOOTER + } + while (--num != 0); +} + +static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + UInt32 hash2Value, hash3Value; + SKIP_HEADER(4) + HASH4_CALC; + curMatch = p->hash[kFix4HashSize + hashValue]; + p->hash[ hash2Value] = + p->hash[kFix3HashSize + hash3Value] = p->pos; + p->hash[kFix4HashSize + hashValue] = p->pos; + SKIP_FOOTER + } + while (--num != 0); +} + +static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + UInt32 hash2Value, hash3Value; + SKIP_HEADER(4) + HASH4_CALC; + curMatch = p->hash[kFix4HashSize + hashValue]; + p->hash[ hash2Value] = + p->hash[kFix3HashSize + hash3Value] = + p->hash[kFix4HashSize + hashValue] = p->pos; + p->son[p->cyclicBufferPos] = curMatch; + MOVE_POS + } + while (--num != 0); +} + +void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + SKIP_HEADER(3) + HASH_ZIP_CALC; + curMatch = p->hash[hashValue]; + p->hash[hashValue] = p->pos; + p->son[p->cyclicBufferPos] = curMatch; + MOVE_POS + } + while (--num != 0); +} + +void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable) +{ + vTable->Init = (Mf_Init_Func)MatchFinder_Init; + vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte; + vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes; + vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos; + if (!p->btMode) + { + vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip; + } + else if (p->numHashBytes == 2) + { + vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip; + } + else if (p->numHashBytes == 3) + { + vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip; + } + else + { + vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip; + } +} diff --git a/DroidFish/jni/gtb/compression/lzma/LzFind.h b/DroidFish/jni/gtb/compression/lzma/LzFind.h new file mode 100755 index 0000000..423d67e --- /dev/null +++ b/DroidFish/jni/gtb/compression/lzma/LzFind.h @@ -0,0 +1,107 @@ +/* LzFind.h -- Match finder for LZ algorithms +2008-10-04 : Igor Pavlov : Public domain */ + +#ifndef __LZFIND_H +#define __LZFIND_H + +#include "Types.h" + +typedef UInt32 CLzRef; + +typedef struct _CMatchFinder +{ + Byte *buffer; + UInt32 pos; + UInt32 posLimit; + UInt32 streamPos; + UInt32 lenLimit; + + UInt32 cyclicBufferPos; + UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */ + + UInt32 matchMaxLen; + CLzRef *hash; + CLzRef *son; + UInt32 hashMask; + UInt32 cutValue; + + Byte *bufferBase; + ISeqInStream *stream; + int streamEndWasReached; + + UInt32 blockSize; + UInt32 keepSizeBefore; + UInt32 keepSizeAfter; + + UInt32 numHashBytes; + int directInput; + int btMode; + /* int skipModeBits; */ + int bigHash; + UInt32 historySize; + UInt32 fixedHashSize; + UInt32 hashSizeSum; + UInt32 numSons; + SRes result; + UInt32 crc[256]; +} CMatchFinder; + +#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer) +#define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)]) + +#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos) + +int MatchFinder_NeedMove(CMatchFinder *p); +Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p); +void MatchFinder_MoveBlock(CMatchFinder *p); +void MatchFinder_ReadIfRequired(CMatchFinder *p); + +void MatchFinder_Construct(CMatchFinder *p); + +/* Conditions: + historySize <= 3 GB + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB +*/ +int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, + UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, + ISzAlloc *alloc); +void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc); +void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems); +void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue); + +UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son, + UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, + UInt32 *distances, UInt32 maxLen); + +/* +Conditions: + Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func. + Mf_GetPointerToCurrentPos_Func's result must be used only before any other function +*/ + +typedef void (*Mf_Init_Func)(void *object); +typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index); +typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object); +typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object); +typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances); +typedef void (*Mf_Skip_Func)(void *object, UInt32); + +typedef struct _IMatchFinder +{ + Mf_Init_Func Init; + Mf_GetIndexByte_Func GetIndexByte; + Mf_GetNumAvailableBytes_Func GetNumAvailableBytes; + Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos; + Mf_GetMatches_Func GetMatches; + Mf_Skip_Func Skip; +} IMatchFinder; + +void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable); + +void MatchFinder_Init(CMatchFinder *p); +UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); +UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); +void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); +void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); + +#endif diff --git a/DroidFish/jni/gtb/compression/lzma/LzFindMt.h b/DroidFish/jni/gtb/compression/lzma/LzFindMt.h new file mode 100755 index 0000000..b7ead2d --- /dev/null +++ b/DroidFish/jni/gtb/compression/lzma/LzFindMt.h @@ -0,0 +1,97 @@ +/* LzFindMt.h -- multithreaded Match finder for LZ algorithms +2008-10-04 : Igor Pavlov : Public domain */ + +#ifndef __LZFINDMT_H +#define __LZFINDMT_H + +#include "Threads.h" +#include "LzFind.h" + +#define kMtHashBlockSize (1 << 13) +#define kMtHashNumBlocks (1 << 3) +#define kMtHashNumBlocksMask (kMtHashNumBlocks - 1) + +#define kMtBtBlockSize (1 << 14) +#define kMtBtNumBlocks (1 << 6) +#define kMtBtNumBlocksMask (kMtBtNumBlocks - 1) + +typedef struct _CMtSync +{ + Bool wasCreated; + Bool needStart; + Bool exit; + Bool stopWriting; + + CThread thread; + CAutoResetEvent canStart; + CAutoResetEvent wasStarted; + CAutoResetEvent wasStopped; + CSemaphore freeSemaphore; + CSemaphore filledSemaphore; + Bool csWasInitialized; + Bool csWasEntered; + CCriticalSection cs; + UInt32 numProcessedBlocks; +} CMtSync; + +typedef UInt32 * (*Mf_Mix_Matches)(void *p, UInt32 matchMinPos, UInt32 *distances); + +/* kMtCacheLineDummy must be >= size_of_CPU_cache_line */ +#define kMtCacheLineDummy 128 + +typedef void (*Mf_GetHeads)(const Byte *buffer, UInt32 pos, + UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc); + +typedef struct _CMatchFinderMt +{ + /* LZ */ + const Byte *pointerToCurPos; + UInt32 *btBuf; + UInt32 btBufPos; + UInt32 btBufPosLimit; + UInt32 lzPos; + UInt32 btNumAvailBytes; + + UInt32 *hash; + UInt32 fixedHashSize; + UInt32 historySize; + const UInt32 *crc; + + Mf_Mix_Matches MixMatchesFunc; + + /* LZ + BT */ + CMtSync btSync; + Byte btDummy[kMtCacheLineDummy]; + + /* BT */ + UInt32 *hashBuf; + UInt32 hashBufPos; + UInt32 hashBufPosLimit; + UInt32 hashNumAvail; + + CLzRef *son; + UInt32 matchMaxLen; + UInt32 numHashBytes; + UInt32 pos; + Byte *buffer; + UInt32 cyclicBufferPos; + UInt32 cyclicBufferSize; /* it must be historySize + 1 */ + UInt32 cutValue; + + /* BT + Hash */ + CMtSync hashSync; + /* Byte hashDummy[kMtCacheLineDummy]; */ + + /* Hash */ + Mf_GetHeads GetHeadsFunc; + CMatchFinder *MatchFinder; +} CMatchFinderMt; + +void MatchFinderMt_Construct(CMatchFinderMt *p); +void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc); +SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore, + UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc); +void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable); +void MatchFinderMt_ReleaseStream(CMatchFinderMt *p); + +#endif diff --git a/DroidFish/jni/gtb/compression/lzma/LzHash.h b/DroidFish/jni/gtb/compression/lzma/LzHash.h new file mode 100755 index 0000000..c923417 --- /dev/null +++ b/DroidFish/jni/gtb/compression/lzma/LzHash.h @@ -0,0 +1,54 @@ +/* LzHash.h -- HASH functions for LZ algorithms +2008-10-04 : Igor Pavlov : Public domain */ + +#ifndef __LZHASH_H +#define __LZHASH_H + +#define kHash2Size (1 << 10) +#define kHash3Size (1 << 16) +#define kHash4Size (1 << 20) + +#define kFix3HashSize (kHash2Size) +#define kFix4HashSize (kHash2Size + kHash3Size) +#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size) + +#define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8); + +#define HASH3_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + hash2Value = temp & (kHash2Size - 1); \ + hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; } + +#define HASH4_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + hash2Value = temp & (kHash2Size - 1); \ + hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ + hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; } + +#define HASH5_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + hash2Value = temp & (kHash2Size - 1); \ + hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ + hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \ + hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \ + hash4Value &= (kHash4Size - 1); } + +/* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */ +#define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF; + + +#define MT_HASH2_CALC \ + hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1); + +#define MT_HASH3_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + hash2Value = temp & (kHash2Size - 1); \ + hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); } + +#define MT_HASH4_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + hash2Value = temp & (kHash2Size - 1); \ + hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ + hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); } + +#endif diff --git a/DroidFish/jni/gtb/compression/lzma/Lzma86Dec.c b/DroidFish/jni/gtb/compression/lzma/Lzma86Dec.c new file mode 100755 index 0000000..c3f1dff --- /dev/null +++ b/DroidFish/jni/gtb/compression/lzma/Lzma86Dec.c @@ -0,0 +1,61 @@ +/* Lzma86Dec.c -- LZMA + x86 (BCJ) Filter Decoder +2008-04-07 +Igor Pavlov +Public domain */ + +#include "Lzma86Dec.h" + +#include "Alloc.h" +#include "Bra.h" +#include "LzmaDec.h" + +#define LZMA86_SIZE_OFFSET (1 + LZMA_PROPS_SIZE) +#define LZMA86_HEADER_SIZE (LZMA86_SIZE_OFFSET + 8) + +static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } +static void SzFree(void *p, void *address) { p = p; MyFree(address); } +static ISzAlloc g_Alloc = { SzAlloc, SzFree }; + +SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize) +{ + unsigned i; + if (srcLen < LZMA86_HEADER_SIZE) + return SZ_ERROR_INPUT_EOF; + *unpackSize = 0; + for (i = 0; i < sizeof(UInt64); i++) + *unpackSize += ((UInt64)src[LZMA86_SIZE_OFFSET + i]) << (8 * i); + return SZ_OK; +} + +SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen) +{ + SRes res; + int useFilter; + SizeT inSizePure; + ELzmaStatus status; + + if (*srcLen < LZMA86_HEADER_SIZE) + return SZ_ERROR_INPUT_EOF; + + useFilter = src[0]; + + if (useFilter > 1) + { + *destLen = 0; + return SZ_ERROR_UNSUPPORTED; + } + + inSizePure = *srcLen - LZMA86_HEADER_SIZE; + res = LzmaDecode(dest, destLen, src + LZMA86_HEADER_SIZE, &inSizePure, + src + 1, LZMA_PROPS_SIZE, LZMA_FINISH_ANY, &status, &g_Alloc); + *srcLen = inSizePure + LZMA86_HEADER_SIZE; + if (res != SZ_OK) + return res; + if (useFilter == 1) + { + UInt32 x86State; + x86_Convert_Init(x86State); + x86_Convert(dest, *destLen, 0, &x86State, 0); + } + return SZ_OK; +} diff --git a/DroidFish/jni/gtb/compression/lzma/Lzma86Dec.h b/DroidFish/jni/gtb/compression/lzma/Lzma86Dec.h new file mode 100755 index 0000000..3ddb227 --- /dev/null +++ b/DroidFish/jni/gtb/compression/lzma/Lzma86Dec.h @@ -0,0 +1,45 @@ +/* Lzma86Dec.h -- LZMA + x86 (BCJ) Filter Decoder +2008-08-05 +Igor Pavlov +Public domain */ + +#ifndef __LZMA86DEC_H +#define __LZMA86DEC_H + +#include "Types.h" + +/* +Lzma86_GetUnpackSize: + In: + src - input data + srcLen - input data size + Out: + unpackSize - size of uncompressed stream + Return code: + SZ_OK - OK + SZ_ERROR_INPUT_EOF - Error in headers +*/ + +SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize); + +/* +Lzma86_Decode: + In: + dest - output data + destLen - output data size + src - input data + srcLen - input data size + Out: + destLen - processed output size + srcLen - processed input size + Return code: + SZ_OK - OK + SZ_ERROR_DATA - Data error + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_UNSUPPORTED - unsupported file + SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer +*/ + +SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen); + +#endif diff --git a/DroidFish/jni/gtb/compression/lzma/Lzma86Enc.c b/DroidFish/jni/gtb/compression/lzma/Lzma86Enc.c new file mode 100755 index 0000000..4cd30e6 --- /dev/null +++ b/DroidFish/jni/gtb/compression/lzma/Lzma86Enc.c @@ -0,0 +1,113 @@ +/* Lzma86Enc.c -- LZMA + x86 (BCJ) Filter Encoder +2008-08-05 +Igor Pavlov +Public domain */ + +#include + +#include "Lzma86Enc.h" + +#include "Alloc.h" +#include "Bra.h" +#include "LzmaEnc.h" + +#define SZE_OUT_OVERFLOW SZE_DATA_ERROR + +static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } +static void SzFree(void *p, void *address) { p = p; MyFree(address); } +static ISzAlloc g_Alloc = { SzAlloc, SzFree }; + +#define LZMA86_SIZE_OFFSET (1 + LZMA_PROPS_SIZE) +#define LZMA86_HEADER_SIZE (LZMA86_SIZE_OFFSET + 8) + +int Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen, + int level, UInt32 dictSize, int filterMode) +{ + size_t outSize2 = *destLen; + Byte *filteredStream; + Bool useFilter; + int mainResult = SZ_ERROR_OUTPUT_EOF; + CLzmaEncProps props; + LzmaEncProps_Init(&props); + props.level = level; + props.dictSize = dictSize; + + *destLen = 0; + if (outSize2 < LZMA86_HEADER_SIZE) + return SZ_ERROR_OUTPUT_EOF; + + { + int i; + UInt64 t = srcLen; + for (i = 0; i < 8; i++, t >>= 8) + dest[LZMA86_SIZE_OFFSET + i] = (Byte)t; + } + + filteredStream = 0; + useFilter = (filterMode != SZ_FILTER_NO); + if (useFilter) + { + if (srcLen != 0) + { + filteredStream = (Byte *)MyAlloc(srcLen); + if (filteredStream == 0) + return SZ_ERROR_MEM; + memcpy(filteredStream, src, srcLen); + } + { + UInt32 x86State; + x86_Convert_Init(x86State); + x86_Convert(filteredStream, srcLen, 0, &x86State, 1); + } + } + + { + size_t minSize = 0; + Bool bestIsFiltered = False; + + /* passes for SZ_FILTER_AUTO: + 0 - BCJ + LZMA + 1 - LZMA + 2 - BCJ + LZMA agaian, if pass 0 (BCJ + LZMA) is better. + */ + int numPasses = (filterMode == SZ_FILTER_AUTO) ? 3 : 1; + + int i; + for (i = 0; i < numPasses; i++) + { + size_t outSizeProcessed = outSize2 - LZMA86_HEADER_SIZE; + size_t outPropsSize = 5; + SRes curRes; + Bool curModeIsFiltered = (numPasses > 1 && i == numPasses - 1); + if (curModeIsFiltered && !bestIsFiltered) + break; + if (useFilter && i == 0) + curModeIsFiltered = True; + + curRes = LzmaEncode(dest + LZMA86_HEADER_SIZE, &outSizeProcessed, + curModeIsFiltered ? filteredStream : src, srcLen, + &props, dest + 1, &outPropsSize, 0, + NULL, &g_Alloc, &g_Alloc); + + if (curRes != SZ_ERROR_OUTPUT_EOF) + { + if (curRes != SZ_OK) + { + mainResult = curRes; + break; + } + if (outSizeProcessed <= minSize || mainResult != SZ_OK) + { + minSize = outSizeProcessed; + bestIsFiltered = curModeIsFiltered; + mainResult = SZ_OK; + } + } + } + dest[0] = (unsigned char) (bestIsFiltered ? 1 : 0); /*MAB: Cast to silence compiler */ + *destLen = LZMA86_HEADER_SIZE + minSize; + } + if (useFilter) + MyFree(filteredStream); + return mainResult; +} diff --git a/DroidFish/jni/gtb/compression/lzma/Lzma86Enc.h b/DroidFish/jni/gtb/compression/lzma/Lzma86Enc.h new file mode 100755 index 0000000..eb7ba7d --- /dev/null +++ b/DroidFish/jni/gtb/compression/lzma/Lzma86Enc.h @@ -0,0 +1,72 @@ +/* Lzma86Enc.h -- LZMA + x86 (BCJ) Filter Encoder +2008-08-05 +Igor Pavlov +Public domain */ + +#ifndef __LZMA86ENC_H +#define __LZMA86ENC_H + +#include "Types.h" + +/* +It's an example for LZMA + x86 Filter use. +You can use .lzma86 extension, if you write that stream to file. +.lzma86 header adds one additional byte to standard .lzma header. +.lzma86 header (14 bytes): + Offset Size Description + 0 1 = 0 - no filter, + = 1 - x86 filter + 1 1 lc, lp and pb in encoded form + 2 4 dictSize (little endian) + 6 8 uncompressed size (little endian) + + +Lzma86_Encode +------------- +level - compression level: 0 <= level <= 9, the default value for "level" is 5. + + +dictSize - The dictionary size in bytes. The maximum value is + 128 MB = (1 << 27) bytes for 32-bit version + 1 GB = (1 << 30) bytes for 64-bit version + The default value is 16 MB = (1 << 24) bytes, for level = 5. + It's recommended to use the dictionary that is larger than 4 KB and + that can be calculated as (1 << N) or (3 << N) sizes. + For better compression ratio dictSize must be >= inSize. + +filterMode: + SZ_FILTER_NO - no Filter + SZ_FILTER_YES - x86 Filter + SZ_FILTER_AUTO - it tries both alternatives to select best. + Encoder will use 2 or 3 passes: + 2 passes when FILTER_NO provides better compression. + 3 passes when FILTER_YES provides better compression. + +Lzma86Encode allocates Data with MyAlloc functions. +RAM Requirements for compressing: + RamSize = dictionarySize * 11.5 + 6MB + FilterBlockSize + filterMode FilterBlockSize + SZ_FILTER_NO 0 + SZ_FILTER_YES inSize + SZ_FILTER_AUTO inSize + + +Return code: + SZ_OK - OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_PARAM - Incorrect paramater + SZ_ERROR_OUTPUT_EOF - output buffer overflow + SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) +*/ + +enum ESzFilterMode +{ + SZ_FILTER_NO, + SZ_FILTER_YES, + SZ_FILTER_AUTO +}; + +SRes Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen, + int level, UInt32 dictSize, int filterMode); + +#endif diff --git a/DroidFish/jni/gtb/compression/lzma/LzmaDec.c b/DroidFish/jni/gtb/compression/lzma/LzmaDec.c new file mode 100755 index 0000000..00f93aa --- /dev/null +++ b/DroidFish/jni/gtb/compression/lzma/LzmaDec.c @@ -0,0 +1,1012 @@ +/* LzmaDec.c -- LZMA Decoder +2008-11-06 : Igor Pavlov : Public domain */ + +#include "LzmaDec.h" + +#include + +#define kNumTopBits 24 +#define kTopValue ((UInt32)1 << kNumTopBits) + +#define kNumBitModelTotalBits 11 +#define kBitModelTotal (1 << kNumBitModelTotalBits) +#define kNumMoveBits 5 + +#define RC_INIT_SIZE 5 + +#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } + +#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) +#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); +#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); +#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \ + { UPDATE_0(p); i = (i + i); A0; } else \ + { UPDATE_1(p); i = (i + i) + 1; A1; } +#define GET_BIT(p, i) GET_BIT2(p, i, ; , ;) + +#define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); } +#define TREE_DECODE(probs, limit, i) \ + { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; } + +/* #define _LZMA_SIZE_OPT */ + +#ifdef _LZMA_SIZE_OPT +#define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i) +#else +#define TREE_6_DECODE(probs, i) \ + { i = 1; \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + i -= 0x40; } +#endif + +#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); } + +#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) +#define UPDATE_0_CHECK range = bound; +#define UPDATE_1_CHECK range -= bound; code -= bound; +#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \ + { UPDATE_0_CHECK; i = (i + i); A0; } else \ + { UPDATE_1_CHECK; i = (i + i) + 1; A1; } +#define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;) +#define TREE_DECODE_CHECK(probs, limit, i) \ + { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; } + + +#define kNumPosBitsMax 4 +#define kNumPosStatesMax (1 << kNumPosBitsMax) + +#define kLenNumLowBits 3 +#define kLenNumLowSymbols (1 << kLenNumLowBits) +#define kLenNumMidBits 3 +#define kLenNumMidSymbols (1 << kLenNumMidBits) +#define kLenNumHighBits 8 +#define kLenNumHighSymbols (1 << kLenNumHighBits) + +#define LenChoice 0 +#define LenChoice2 (LenChoice + 1) +#define LenLow (LenChoice2 + 1) +#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits)) +#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits)) +#define kNumLenProbs (LenHigh + kLenNumHighSymbols) + + +#define kNumStates 12 +#define kNumLitStates 7 + +#define kStartPosModelIndex 4 +#define kEndPosModelIndex 14 +#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) + +#define kNumPosSlotBits 6 +#define kNumLenToPosStates 4 + +#define kNumAlignBits 4 +#define kAlignTableSize (1 << kNumAlignBits) + +#define kMatchMinLen 2 +#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) + +#define IsMatch 0 +#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax)) +#define IsRepG0 (IsRep + kNumStates) +#define IsRepG1 (IsRepG0 + kNumStates) +#define IsRepG2 (IsRepG1 + kNumStates) +#define IsRep0Long (IsRepG2 + kNumStates) +#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax)) +#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) +#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex) +#define LenCoder (Align + kAlignTableSize) +#define RepLenCoder (LenCoder + kNumLenProbs) +#define Literal (RepLenCoder + kNumLenProbs) + +#define LZMA_BASE_SIZE 1846 +#define LZMA_LIT_SIZE 768 +/*MAB casts next... */ +#define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + ((unsigned)LZMA_LIT_SIZE << ((p)->lc + (p)->lp))) + +#if Literal != LZMA_BASE_SIZE +StopCompilingDueBUG +#endif + +static const Byte kLiteralNextStates[kNumStates * 2] = +{ + 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5, + 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10 +}; + +#define LZMA_DIC_MIN (1 << 12) + +/* First LZMA-symbol is always decoded. +And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization +Out: + Result: + SZ_OK - OK + SZ_ERROR_DATA - Error + p->remainLen: + < kMatchSpecLenStart : normal remain + = kMatchSpecLenStart : finished + = kMatchSpecLenStart + 1 : Flush marker + = kMatchSpecLenStart + 2 : State Init Marker +*/ + +static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit) +{ + CLzmaProb *probs = p->probs; + + unsigned state = p->state; + UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3]; + unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1; + unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1; + unsigned lc = p->prop.lc; + + Byte *dic = p->dic; + SizeT dicBufSize = p->dicBufSize; + SizeT dicPos = p->dicPos; + + UInt32 processedPos = p->processedPos; + UInt32 checkDicSize = p->checkDicSize; + unsigned len = 0; + + const Byte *buf = p->buf; + UInt32 range = p->range; + UInt32 code = p->code; + + do + { + CLzmaProb *prob; + UInt32 bound; + unsigned ttt; + unsigned posState = processedPos & pbMask; + + prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; + IF_BIT_0(prob) + { + unsigned symbol; + UPDATE_0(prob); + prob = probs + Literal; + if (checkDicSize != 0 || processedPos != 0) + prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) + (UInt32) ( /*MAB casts */ + (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc)))) ) + ; + if (state < kNumLitStates) + { + symbol = 1; + do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100); + } + else + { + unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; + unsigned offs = 0x100; + symbol = 1; + do + { + unsigned bit; + CLzmaProb *probLit; + matchByte <<= 1; + bit = (matchByte & offs); + probLit = prob + offs + bit + symbol; + GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit) + } + while (symbol < 0x100); + } + dic[dicPos++] = (Byte)symbol; + processedPos++; + + state = kLiteralNextStates[state]; + /* if (state < 4) state = 0; else if (state < 10) state -= 3; else state -= 6; */ + continue; + } + else + { + UPDATE_1(prob); + prob = probs + IsRep + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + state += kNumStates; + prob = probs + LenCoder; + } + else + { + UPDATE_1(prob); + if (checkDicSize == 0 && processedPos == 0) + return SZ_ERROR_DATA; + prob = probs + IsRepG0 + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; + IF_BIT_0(prob) + { + UPDATE_0(prob); + dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; + dicPos++; + processedPos++; + state = state < kNumLitStates ? 9 : 11; + continue; + } + UPDATE_1(prob); + } + else + { + UInt32 distance; + UPDATE_1(prob); + prob = probs + IsRepG1 + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + distance = rep1; + } + else + { + UPDATE_1(prob); + prob = probs + IsRepG2 + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + distance = rep2; + } + else + { + UPDATE_1(prob); + distance = rep3; + rep3 = rep2; + } + rep2 = rep1; + } + rep1 = rep0; + rep0 = distance; + } + state = state < kNumLitStates ? 8 : 11; + prob = probs + RepLenCoder; + } + { + /*MAB: limit changed to limit__ because it was hiding a variable limit */ + unsigned limit__, offset; + CLzmaProb *probLen = prob + LenChoice; + IF_BIT_0(probLen) + { + UPDATE_0(probLen); + probLen = prob + LenLow + (posState << kLenNumLowBits); + offset = 0; + limit__ = (1 << kLenNumLowBits); + } + else + { + UPDATE_1(probLen); + probLen = prob + LenChoice2; + IF_BIT_0(probLen) + { + UPDATE_0(probLen); + probLen = prob + LenMid + (posState << kLenNumMidBits); + offset = kLenNumLowSymbols; + limit__ = (1 << kLenNumMidBits); + } + else + { + UPDATE_1(probLen); + probLen = prob + LenHigh; + offset = kLenNumLowSymbols + kLenNumMidSymbols; + limit__ = (1 << kLenNumHighBits); + } + } + TREE_DECODE(probLen, limit__, len); + len += offset; + } + + if (state >= kNumStates) + { + UInt32 distance; + prob = probs + PosSlot + + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); + TREE_6_DECODE(prob, distance); + if (distance >= kStartPosModelIndex) + { + unsigned posSlot = (unsigned)distance; + int numDirectBits = (int)(((distance >> 1) - 1)); + distance = (2 | (distance & 1)); + if (posSlot < kEndPosModelIndex) + { + distance <<= numDirectBits; + prob = probs + SpecPos + distance - posSlot - 1; + { + UInt32 mask = 1; + unsigned i = 1; + do + { + GET_BIT2(prob + i, i, ; , distance |= mask); + mask <<= 1; + } + while (--numDirectBits != 0); + } + } + else + { + numDirectBits -= kNumAlignBits; + do + { + NORMALIZE + range >>= 1; + + { + UInt32 t; + code -= range; + t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */ + distance = (distance << 1) + (t + 1); + code += range & t; + } + /* + distance <<= 1; + if (code >= range) + { + code -= range; + distance |= 1; + } + */ + } + while (--numDirectBits != 0); + prob = probs + Align; + distance <<= kNumAlignBits; + { + unsigned i = 1; + GET_BIT2(prob + i, i, ; , distance |= 1); + GET_BIT2(prob + i, i, ; , distance |= 2); + GET_BIT2(prob + i, i, ; , distance |= 4); + GET_BIT2(prob + i, i, ; , distance |= 8); + } + if (distance == (UInt32)0xFFFFFFFF) + { + len += kMatchSpecLenStart; + state -= kNumStates; + break; + } + } + } + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + rep0 = distance + 1; + if (checkDicSize == 0) + { + if (distance >= processedPos) + return SZ_ERROR_DATA; + } + else if (distance >= checkDicSize) + return SZ_ERROR_DATA; + state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; + /* state = kLiteralNextStates[state]; */ + } + + len += kMatchMinLen; + + if (limit == dicPos) + return SZ_ERROR_DATA; + { + SizeT rem = limit - dicPos; + unsigned curLen = ((rem < len) ? (unsigned)rem : len); + SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0); + + processedPos += curLen; + + len -= curLen; + if (pos + curLen <= dicBufSize) + { + Byte *dest = dic + dicPos; + ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos; + const Byte *lim = dest + curLen; + dicPos += curLen; + do + *(dest) = (Byte)*(dest + src); + while (++dest != lim); + } + else + { + do + { + dic[dicPos++] = dic[pos]; + if (++pos == dicBufSize) + pos = 0; + } + while (--curLen != 0); + } + } + } + } + while (dicPos < limit && buf < bufLimit); + NORMALIZE; + p->buf = buf; + p->range = range; + p->code = code; + p->remainLen = len; + p->dicPos = dicPos; + p->processedPos = processedPos; + p->reps[0] = rep0; + p->reps[1] = rep1; + p->reps[2] = rep2; + p->reps[3] = rep3; + p->state = state; + + return SZ_OK; +} + +static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit) +{ + if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart) + { + Byte *dic = p->dic; + SizeT dicPos = p->dicPos; + SizeT dicBufSize = p->dicBufSize; + unsigned len = p->remainLen; + UInt32 rep0 = p->reps[0]; + if (limit - dicPos < len) + len = (unsigned)(limit - dicPos); + + if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len) + p->checkDicSize = p->prop.dicSize; + + p->processedPos += len; + p->remainLen -= len; + while (len-- != 0) + { + dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; + dicPos++; + } + p->dicPos = dicPos; + } +} + +static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit) +{ + do + { + SizeT limit2 = limit; + if (p->checkDicSize == 0) + { + UInt32 rem = p->prop.dicSize - p->processedPos; + if (limit - p->dicPos > rem) + limit2 = p->dicPos + rem; + } + RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit)); + if (p->processedPos >= p->prop.dicSize) + p->checkDicSize = p->prop.dicSize; + LzmaDec_WriteRem(p, limit); + } + while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart); + + if (p->remainLen > kMatchSpecLenStart) + { + p->remainLen = kMatchSpecLenStart; + } + return 0; +} + +typedef enum ELzmaDummy +{ + DUMMY_ERROR, /* unexpected end of input stream */ + DUMMY_LIT, + DUMMY_MATCH, + DUMMY_REP +} ELzmaDummy; + +static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize) +{ + UInt32 range = p->range; + UInt32 code = p->code; + const Byte *bufLimit = buf + inSize; + CLzmaProb *probs = p->probs; + unsigned state = p->state; + ELzmaDummy res; + + { + CLzmaProb *prob; + UInt32 bound; + unsigned ttt; + unsigned posState = (p->processedPos) & ((1u << p->prop.pb) - 1u); /*MAB 1u */ + + prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK + + /* if (bufLimit - buf >= 7) return DUMMY_LIT; */ + + prob = probs + Literal; + if (p->checkDicSize != 0 || p->processedPos != 0) + prob += (LZMA_LIT_SIZE * + ( (unsigned) /*MAB casts */ + (((p->processedPos) & ((1u << (p->prop.lp)) - 1u)) << p->prop.lc) + + (unsigned) /*MAB casts */ + (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc)))); + + if (state < kNumLitStates) + { + unsigned symbol = 1; + do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100); + } + else + { + unsigned matchByte = p->dic[p->dicPos - p->reps[0] + + ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)]; + unsigned offs = 0x100; + unsigned symbol = 1; + do + { + unsigned bit; + CLzmaProb *probLit; + matchByte <<= 1; + bit = (matchByte & offs); + probLit = prob + offs + bit + symbol; + GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit) + } + while (symbol < 0x100); + } + res = DUMMY_LIT; + } + else + { + unsigned len; + UPDATE_1_CHECK; + + prob = probs + IsRep + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + state = 0; + prob = probs + LenCoder; + res = DUMMY_MATCH; + } + else + { + UPDATE_1_CHECK; + res = DUMMY_REP; + prob = probs + IsRepG0 + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + NORMALIZE_CHECK; + return DUMMY_REP; + } + else + { + UPDATE_1_CHECK; + } + } + else + { + UPDATE_1_CHECK; + prob = probs + IsRepG1 + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + } + else + { + UPDATE_1_CHECK; + prob = probs + IsRepG2 + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + } + else + { + UPDATE_1_CHECK; + } + } + } + state = kNumStates; + prob = probs + RepLenCoder; + } + { + unsigned limit, offset; + CLzmaProb *probLen = prob + LenChoice; + IF_BIT_0_CHECK(probLen) + { + UPDATE_0_CHECK; + probLen = prob + LenLow + (posState << kLenNumLowBits); + offset = 0; + limit = 1 << kLenNumLowBits; + } + else + { + UPDATE_1_CHECK; + probLen = prob + LenChoice2; + IF_BIT_0_CHECK(probLen) + { + UPDATE_0_CHECK; + probLen = prob + LenMid + (posState << kLenNumMidBits); + offset = kLenNumLowSymbols; + limit = 1 << kLenNumMidBits; + } + else + { + UPDATE_1_CHECK; + probLen = prob + LenHigh; + offset = kLenNumLowSymbols + kLenNumMidSymbols; + limit = 1 << kLenNumHighBits; + } + } + TREE_DECODE_CHECK(probLen, limit, len); + len += offset; + } + + if (state < 4) + { + unsigned posSlot; + prob = probs + PosSlot + + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << + kNumPosSlotBits); + TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot); + if (posSlot >= kStartPosModelIndex) + { + int numDirectBits = (int)((posSlot >> 1) - 1); /*MAB casts */ + + /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */ + + if (posSlot < kEndPosModelIndex) + { + prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1; + } + else + { + numDirectBits -= kNumAlignBits; + do + { + NORMALIZE_CHECK + range >>= 1; + code -= range & (((code - range) >> 31) - 1); + /* if (code >= range) code -= range; */ + } + while (--numDirectBits != 0); + prob = probs + Align; + numDirectBits = kNumAlignBits; + } + { + unsigned i = 1; + do + { + GET_BIT_CHECK(prob + i, i); + } + while (--numDirectBits != 0); + } + } + } + } + } + NORMALIZE_CHECK; + return res; +} + + +static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data) +{ + p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]); + p->range = 0xFFFFFFFF; + p->needFlush = 0; +} + +/*MAB: static added because it is not used externally */ +static +void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) +{ + p->needFlush = 1; + p->remainLen = 0; + p->tempBufSize = 0; + + if (initDic) + { + p->processedPos = 0; + p->checkDicSize = 0; + p->needInitState = 1; + } + if (initState) + p->needInitState = 1; +} + +void LzmaDec_Init(CLzmaDec *p) +{ + p->dicPos = 0; + LzmaDec_InitDicAndState(p, True, True); +} + +static void LzmaDec_InitStateReal(CLzmaDec *p) +{ + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp)); + UInt32 i; + CLzmaProb *probs = p->probs; + for (i = 0; i < numProbs; i++) + probs[i] = kBitModelTotal >> 1; + p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1; + p->state = 0; + p->needInitState = 0; +} + +SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, + ELzmaFinishMode finishMode, ELzmaStatus *status) +{ + SizeT inSize = *srcLen; + (*srcLen) = 0; + LzmaDec_WriteRem(p, dicLimit); + + *status = LZMA_STATUS_NOT_SPECIFIED; + + while (p->remainLen != kMatchSpecLenStart) + { + int checkEndMarkNow; + + if (p->needFlush != 0) + { + for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--) + p->tempBuf[p->tempBufSize++] = *src++; + if (p->tempBufSize < RC_INIT_SIZE) + { + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + if (p->tempBuf[0] != 0) + return SZ_ERROR_DATA; + + LzmaDec_InitRc(p, p->tempBuf); + p->tempBufSize = 0; + } + + checkEndMarkNow = 0; + if (p->dicPos >= dicLimit) + { + if (p->remainLen == 0 && p->code == 0) + { + *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK; + return SZ_OK; + } + if (finishMode == LZMA_FINISH_ANY) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_OK; + } + if (p->remainLen != 0) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_ERROR_DATA; + } + checkEndMarkNow = 1; + } + + if (p->needInitState) + LzmaDec_InitStateReal(p); + + if (p->tempBufSize == 0) + { + SizeT processed; + const Byte *bufLimit; + if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) + { + int dummyRes = LzmaDec_TryDummy(p, src, inSize); + if (dummyRes == DUMMY_ERROR) + { + memcpy(p->tempBuf, src, inSize); + p->tempBufSize = (unsigned)inSize; + (*srcLen) += inSize; + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + if (checkEndMarkNow && dummyRes != DUMMY_MATCH) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_ERROR_DATA; + } + bufLimit = src; + } + else + bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX; + p->buf = src; + if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0) + return SZ_ERROR_DATA; + processed = (SizeT)(p->buf - src); + (*srcLen) += processed; + src += processed; + inSize -= processed; + } + else + { + unsigned rem = p->tempBufSize, lookAhead = 0; + while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize) + p->tempBuf[rem++] = src[lookAhead++]; + p->tempBufSize = rem; + if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) + { + int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem); + if (dummyRes == DUMMY_ERROR) + { + (*srcLen) += lookAhead; + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + if (checkEndMarkNow && dummyRes != DUMMY_MATCH) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_ERROR_DATA; + } + } + p->buf = p->tempBuf; + if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0) + return SZ_ERROR_DATA; + lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf)); + (*srcLen) += lookAhead; + src += lookAhead; + inSize -= lookAhead; + p->tempBufSize = 0; + } + } + if (p->code == 0) + *status = LZMA_STATUS_FINISHED_WITH_MARK; + return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA; +} + +SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) +{ + SizeT outSize = *destLen; + SizeT inSize = *srcLen; + *srcLen = *destLen = 0; + for (;;) + { + SizeT inSizeCur = inSize, outSizeCur, dicPos; + ELzmaFinishMode curFinishMode; + SRes res; + if (p->dicPos == p->dicBufSize) + p->dicPos = 0; + dicPos = p->dicPos; + if (outSize > p->dicBufSize - dicPos) + { + outSizeCur = p->dicBufSize; + curFinishMode = LZMA_FINISH_ANY; + } + else + { + outSizeCur = dicPos + outSize; + curFinishMode = finishMode; + } + + res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status); + src += inSizeCur; + inSize -= inSizeCur; + *srcLen += inSizeCur; + outSizeCur = p->dicPos - dicPos; + memcpy(dest, p->dic + dicPos, outSizeCur); + dest += outSizeCur; + outSize -= outSizeCur; + *destLen += outSizeCur; + if (res != 0) + return res; + if (outSizeCur == 0 || outSize == 0) + return SZ_OK; + } +} + +void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->probs); + p->probs = 0; +} + +static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->dic); + p->dic = 0; +} + +void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc) +{ + LzmaDec_FreeProbs(p, alloc); + LzmaDec_FreeDict(p, alloc); +} + +SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size) +{ + UInt32 dicSize; + Byte d; + + if (size < LZMA_PROPS_SIZE) + return SZ_ERROR_UNSUPPORTED; + else + dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24); + + if (dicSize < LZMA_DIC_MIN) + dicSize = LZMA_DIC_MIN; + p->dicSize = dicSize; + + d = data[0]; + if (d >= (9 * 5 * 5)) + return SZ_ERROR_UNSUPPORTED; + + p->lc = d % 9; + d /= 9; + p->pb = d / 5; + p->lp = d % 5; + + return SZ_OK; +} + +static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc) +{ + UInt32 numProbs = (UInt32) (LzmaProps_GetNumProbs(propNew)); /*MAB casts */ + if (p->probs == 0 || numProbs != p->numProbs) + { + LzmaDec_FreeProbs(p, alloc); + p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb)); + p->numProbs = numProbs; + if (p->probs == 0) + return SZ_ERROR_MEM; + } + return SZ_OK; +} + +SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) +{ + CLzmaProps propNew; + RINOK(LzmaProps_Decode(&propNew, props, propsSize)); + RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); + p->prop = propNew; + return SZ_OK; +} + +SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) +{ + CLzmaProps propNew; + SizeT dicBufSize; + RINOK(LzmaProps_Decode(&propNew, props, propsSize)); + RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); + dicBufSize = propNew.dicSize; + if (p->dic == 0 || dicBufSize != p->dicBufSize) + { + LzmaDec_FreeDict(p, alloc); + p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize); + if (p->dic == 0) + { + LzmaDec_FreeProbs(p, alloc); + return SZ_ERROR_MEM; + } + } + p->dicBufSize = dicBufSize; + p->prop = propNew; + return SZ_OK; +} + +SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, + ELzmaStatus *status, ISzAlloc *alloc) +{ + CLzmaDec p; + SRes res; + SizeT inSize = *srcLen; + SizeT outSize = *destLen; + *srcLen = *destLen = 0; + if (inSize < RC_INIT_SIZE) + return SZ_ERROR_INPUT_EOF; + + LzmaDec_Construct(&p); + res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc); + if (res != 0) + return res; + p.dic = dest; + p.dicBufSize = outSize; + + LzmaDec_Init(&p); + + *srcLen = inSize; + res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); + + if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) + res = SZ_ERROR_INPUT_EOF; + + (*destLen) = p.dicPos; + LzmaDec_FreeProbs(&p, alloc); + return res; +} diff --git a/DroidFish/jni/gtb/compression/lzma/LzmaDec.h b/DroidFish/jni/gtb/compression/lzma/LzmaDec.h new file mode 100755 index 0000000..00d8398 --- /dev/null +++ b/DroidFish/jni/gtb/compression/lzma/LzmaDec.h @@ -0,0 +1,223 @@ +/* LzmaDec.h -- LZMA Decoder +2008-10-04 : Igor Pavlov : Public domain */ + +#ifndef __LZMADEC_H +#define __LZMADEC_H + +#include "Types.h" + +/* #define _LZMA_PROB32 */ +/* _LZMA_PROB32 can increase the speed on some CPUs, + but memory usage for CLzmaDec::probs will be doubled in that case */ + +#ifdef _LZMA_PROB32 +#define CLzmaProb UInt32 +#else +#define CLzmaProb UInt16 +#endif + + +/* ---------- LZMA Properties ---------- */ + +#define LZMA_PROPS_SIZE 5 + +typedef struct _CLzmaProps +{ + unsigned lc, lp, pb; + UInt32 dicSize; +} CLzmaProps; + +/* LzmaProps_Decode - decodes properties +Returns: + SZ_OK + SZ_ERROR_UNSUPPORTED - Unsupported properties +*/ + +SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size); + + +/* ---------- LZMA Decoder state ---------- */ + +/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case. + Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */ + +#define LZMA_REQUIRED_INPUT_MAX 20 + +typedef struct CLzmaDec +{ + CLzmaProps prop; + CLzmaProb *probs; + Byte *dic; + const Byte *buf; + UInt32 range, code; + SizeT dicPos; + SizeT dicBufSize; + UInt32 processedPos; + UInt32 checkDicSize; + unsigned state; + UInt32 reps[4]; + unsigned remainLen; + int needFlush; + int needInitState; + UInt32 numProbs; + unsigned tempBufSize; + Byte tempBuf[LZMA_REQUIRED_INPUT_MAX]; +} CLzmaDec; + +#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; } + +void LzmaDec_Init(CLzmaDec *p); + +/* There are two types of LZMA streams: + 0) Stream with end mark. That end mark adds about 6 bytes to compressed size. + 1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */ + +typedef enum ELzmaFinishMode +{ + LZMA_FINISH_ANY, /* finish at any point */ + LZMA_FINISH_END /* block must be finished at the end */ +} ELzmaFinishMode; + +/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!! + + You must use LZMA_FINISH_END, when you know that current output buffer + covers last bytes of block. In other cases you must use LZMA_FINISH_ANY. + + If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK, + and output value of destLen will be less than output buffer size limit. + You can check status result also. + + You can use multiple checks to test data integrity after full decompression: + 1) Check Result and "status" variable. + 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. + 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. + You must use correct finish mode in that case. */ + +typedef enum ELzmaStatus +{ + LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */ + LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */ + LZMA_STATUS_NOT_FINISHED, /* stream was not finished */ + LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */ + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */ +} ELzmaStatus; + +/* ELzmaStatus is used only as output value for function call */ + + +/* ---------- Interfaces ---------- */ + +/* There are 3 levels of interfaces: + 1) Dictionary Interface + 2) Buffer Interface + 3) One Call Interface + You can select any of these interfaces, but don't mix functions from different + groups for same object. */ + + +/* There are two variants to allocate state for Dictionary Interface: + 1) LzmaDec_Allocate / LzmaDec_Free + 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs + You can use variant 2, if you set dictionary buffer manually. + For Buffer Interface you must always use variant 1. + +LzmaDec_Allocate* can return: + SZ_OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_UNSUPPORTED - Unsupported properties +*/ + +SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc); +void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc); + +SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc); +void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc); + +/* ---------- Dictionary Interface ---------- */ + +/* You can use it, if you want to eliminate the overhead for data copying from + dictionary to some other external buffer. + You must work with CLzmaDec variables directly in this interface. + + STEPS: + LzmaDec_Constr() + LzmaDec_Allocate() + for (each new stream) + { + LzmaDec_Init() + while (it needs more decompression) + { + LzmaDec_DecodeToDic() + use data from CLzmaDec::dic and update CLzmaDec::dicPos + } + } + LzmaDec_Free() +*/ + +/* LzmaDec_DecodeToDic + + The decoding to internal dictionary buffer (CLzmaDec::dic). + You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!! + +finishMode: + It has meaning only if the decoding reaches output limit (dicLimit). + LZMA_FINISH_ANY - Decode just dicLimit bytes. + LZMA_FINISH_END - Stream must be finished after dicLimit. + +Returns: + SZ_OK + status: + LZMA_STATUS_FINISHED_WITH_MARK + LZMA_STATUS_NOT_FINISHED + LZMA_STATUS_NEEDS_MORE_INPUT + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + SZ_ERROR_DATA - Data error +*/ + +SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); + + +/* ---------- Buffer Interface ---------- */ + +/* It's zlib-like interface. + See LzmaDec_DecodeToDic description for information about STEPS and return results, + but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need + to work with CLzmaDec variables manually. + +finishMode: + It has meaning only if the decoding reaches output limit (*destLen). + LZMA_FINISH_ANY - Decode just destLen bytes. + LZMA_FINISH_END - Stream must be finished after (*destLen). +*/ + +SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); + + +/* ---------- One Call Interface ---------- */ + +/* LzmaDecode + +finishMode: + It has meaning only if the decoding reaches output limit (*destLen). + LZMA_FINISH_ANY - Decode just destLen bytes. + LZMA_FINISH_END - Stream must be finished after (*destLen). + +Returns: + SZ_OK + status: + LZMA_STATUS_FINISHED_WITH_MARK + LZMA_STATUS_NOT_FINISHED + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + SZ_ERROR_DATA - Data error + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_UNSUPPORTED - Unsupported properties + SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). +*/ + +SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, + ELzmaStatus *status, ISzAlloc *alloc); + +#endif diff --git a/DroidFish/jni/gtb/compression/lzma/LzmaEnc.c b/DroidFish/jni/gtb/compression/lzma/LzmaEnc.c new file mode 100755 index 0000000..fc9153c --- /dev/null +++ b/DroidFish/jni/gtb/compression/lzma/LzmaEnc.c @@ -0,0 +1,2330 @@ +/* LzmaEnc.c -- LZMA Encoder +2009-02-02 : Igor Pavlov : Public domain */ + +#include + +/* #define SHOW_STAT */ +/* #define SHOW_STAT2 */ + +#if defined(SHOW_STAT) || defined(SHOW_STAT2) +#include +#endif + +#include "LzmaEnc.h" + +#include "LzFind.h" +#ifdef COMPRESS_MF_MT +#include "LzFindMt.h" +#endif + +#ifdef SHOW_STAT +static int ttt = 0; +#endif + +#define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1) + +#define kBlockSize (9 << 10) +#define kUnpackBlockSize (1 << 18) +#define kMatchArraySize (1 << 21) +#define kMatchRecordMaxSize ((LZMA_MATCH_LEN_MAX * 2 + 3) * LZMA_MATCH_LEN_MAX) + +#define kNumMaxDirectBits (31) + +#define kNumTopBits 24 +#define kTopValue ((UInt32)1 << kNumTopBits) + +#define kNumBitModelTotalBits 11 +#define kBitModelTotal (1 << kNumBitModelTotalBits) +#define kNumMoveBits 5 +#define kProbInitValue (kBitModelTotal >> 1) + +#define kNumMoveReducingBits 4 +#define kNumBitPriceShiftBits 4 +#define kBitPrice (1 << kNumBitPriceShiftBits) + +void LzmaEncProps_Init(CLzmaEncProps *p) +{ + p->level = 5; + p->dictSize = p->mc = 0; + p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1; + p->writeEndMark = 0; +} + +void LzmaEncProps_Normalize(CLzmaEncProps *p) +{ + int level = p->level; + if (level < 0) level = 5; + p->level = level; + if (p->dictSize == 0) p->dictSize = (UInt32) ((level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26)))); /*MAB casts UInt32 */ + if (p->lc < 0) p->lc = 3; + if (p->lp < 0) p->lp = 0; + if (p->pb < 0) p->pb = 2; + if (p->algo < 0) p->algo = (level < 5 ? 0 : 1); + if (p->fb < 0) p->fb = (level < 7 ? 32 : 64); + if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1); + if (p->numHashBytes < 0) p->numHashBytes = 4; + if (p->mc == 0) p->mc = (UInt32) ((16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1)); /*MAB casts UInt32 */ + if (p->numThreads < 0) + p->numThreads = + #ifdef COMPRESS_MF_MT + ((p->btMode && p->algo) ? 2 : 1); + #else + 1; + #endif +} + +UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2) +{ + CLzmaEncProps props = *props2; + LzmaEncProps_Normalize(&props); + return props.dictSize; +} + +/* #define LZMA_LOG_BSR */ +/* Define it for Intel's CPU */ + + +#ifdef LZMA_LOG_BSR + +#define kDicLogSizeMaxCompress 30 + +/*MAB: i changed to i__ to avoid possible hiding of a variable */ +#define BSR2_RET(pos, res) { unsigned long i__; _BitScanReverse(&i__, (pos)); res = (i__ + i__) + ((pos >> (i__ - 1)) & 1); } + +UInt32 GetPosSlot1(UInt32 pos) +{ + UInt32 res; + BSR2_RET(pos, res); + return res; +} +#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } +#define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); } + +#else + +#define kNumLogBits (9 + (int)sizeof(size_t) / 2) +#define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7) + +/*MAB: static added */ +static +void LzmaEnc_FastPosInit(Byte *g_FastPos) +{ + int c = 2, slotFast; + g_FastPos[0] = 0; + g_FastPos[1] = 1; + + for (slotFast = 2; slotFast < kNumLogBits * 2; slotFast++) + { + UInt32 k = (UInt32) ((1 << ((slotFast >> 1) - 1))); /*MAB casts */ + UInt32 j; + for (j = 0; j < k; j++, c++) + g_FastPos[c] = (Byte)slotFast; + } +} + +/*MAB: i changed to i__ to avoid hiding a variable */ +#define BSR2_RET(pos, res) { UInt32 i__ = 6 + ((kNumLogBits - 1) & \ + (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \ + res = p->g_FastPos[pos >> i__] + (i__ * 2); } + +/* +#define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \ + p->g_FastPos[pos >> 6] + 12 : \ + p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; } +*/ + +#define GetPosSlot1(pos) p->g_FastPos[pos] +#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } +#define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos]; else BSR2_RET(pos, res); } + +#endif + + +#define LZMA_NUM_REPS 4 + +typedef unsigned CState; + +typedef struct _COptimal +{ + UInt32 price; + + CState state; + int prev1IsChar; + int prev2; + + UInt32 posPrev2; + UInt32 backPrev2; + + UInt32 posPrev; + UInt32 backPrev; + UInt32 backs[LZMA_NUM_REPS]; +} COptimal; + +#define kNumOpts (1 << 12) + +#define kNumLenToPosStates 4 +#define kNumPosSlotBits 6 +#define kDicLogSizeMin 0 +#define kDicLogSizeMax 32 +#define kDistTableSizeMax (kDicLogSizeMax * 2) + + +#define kNumAlignBits 4 +#define kAlignTableSize (1 << kNumAlignBits) +#define kAlignMask (kAlignTableSize - 1) + +#define kStartPosModelIndex 4 +#define kEndPosModelIndex 14 +#define kNumPosModels (kEndPosModelIndex - kStartPosModelIndex) + +#define kNumFullDistances (1 << (kEndPosModelIndex / 2)) + +#ifdef _LZMA_PROB32 +#define CLzmaProb UInt32 +#else +#define CLzmaProb UInt16 +#endif + +#define LZMA_PB_MAX 4 +#define LZMA_LC_MAX 8 +#define LZMA_LP_MAX 4 + +#define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX) + + +#define kLenNumLowBits 3 +#define kLenNumLowSymbols (1 << kLenNumLowBits) +#define kLenNumMidBits 3 +#define kLenNumMidSymbols (1 << kLenNumMidBits) +#define kLenNumHighBits 8 +#define kLenNumHighSymbols (1 << kLenNumHighBits) + +#define kLenNumSymbolsTotal (kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) + +#define LZMA_MATCH_LEN_MIN 2 +#define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1) + +#define kNumStates 12 + +typedef struct CLenEnc +{ + CLzmaProb choice; + CLzmaProb choice2; + CLzmaProb low[LZMA_NUM_PB_STATES_MAX << kLenNumLowBits]; + CLzmaProb mid[LZMA_NUM_PB_STATES_MAX << kLenNumMidBits]; + CLzmaProb high[kLenNumHighSymbols]; +} CLenEnc; + +typedef struct CLenPriceEnc +{ + CLenEnc p; + UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal]; + UInt32 tableSize; + UInt32 counters[LZMA_NUM_PB_STATES_MAX]; +} CLenPriceEnc; + +typedef struct _CRangeEnc +{ + UInt32 range; + Byte cache; + UInt64 low; + UInt64 cacheSize; + Byte *buf; + Byte *bufLim; + Byte *bufBase; + ISeqOutStream *outStream; + UInt64 processed; + SRes res; +} CRangeEnc; + +typedef struct _CSeqInStreamBuf +{ + ISeqInStream funcTable; + const Byte *data; + SizeT rem; +} CSeqInStreamBuf; + +static SRes MyRead(void *pp, void *data, size_t *size) +{ + size_t curSize = *size; + CSeqInStreamBuf *p = (CSeqInStreamBuf *)pp; + if (p->rem < curSize) + curSize = p->rem; + memcpy(data, p->data, curSize); + p->rem -= curSize; + p->data += curSize; + *size = curSize; + return SZ_OK; +} + +typedef struct CSaveState +{ + CLzmaProb *litProbs; + + CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; + CLzmaProb isRep[kNumStates]; + CLzmaProb isRepG0[kNumStates]; + CLzmaProb isRepG1[kNumStates]; + CLzmaProb isRepG2[kNumStates]; + CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; + + CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; + CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex]; + CLzmaProb posAlignEncoder[1 << kNumAlignBits]; + + CLenPriceEnc lenEnc; + CLenPriceEnc repLenEnc; + + UInt32 reps[LZMA_NUM_REPS]; + UInt32 state; +} CSaveState; + +typedef struct _CLzmaEnc +{ + IMatchFinder matchFinder; + void *matchFinderObj; + + #ifdef COMPRESS_MF_MT + Bool mtMode; + CMatchFinderMt matchFinderMt; + #endif + + CMatchFinder matchFinderBase; + + #ifdef COMPRESS_MF_MT + Byte pad[128]; + #endif + + UInt32 optimumEndIndex; + UInt32 optimumCurrentIndex; + + UInt32 longestMatchLength; + UInt32 numPairs; + UInt32 numAvail; + COptimal opt[kNumOpts]; + + #ifndef LZMA_LOG_BSR + Byte g_FastPos[1 << kNumLogBits]; + #endif + + UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; + UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1]; + UInt32 numFastBytes; + UInt32 additionalOffset; + UInt32 reps[LZMA_NUM_REPS]; + UInt32 state; + + UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax]; + UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances]; + UInt32 alignPrices[kAlignTableSize]; + UInt32 alignPriceCount; + + UInt32 distTableSize; + + unsigned lc, lp, pb; + unsigned lpMask, pbMask; + + CLzmaProb *litProbs; + + CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; + CLzmaProb isRep[kNumStates]; + CLzmaProb isRepG0[kNumStates]; + CLzmaProb isRepG1[kNumStates]; + CLzmaProb isRepG2[kNumStates]; + CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; + + CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; + CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex]; + CLzmaProb posAlignEncoder[1 << kNumAlignBits]; + + CLenPriceEnc lenEnc; + CLenPriceEnc repLenEnc; + + unsigned lclp; + + Bool fastMode; + + CRangeEnc rc; + + Bool writeEndMark; + UInt64 nowPos64; + UInt32 matchPriceCount; + Bool finished; + Bool multiThread; + + SRes result; + UInt32 dictSize; + UInt32 matchFinderCycles; + + ISeqInStream *inStream; + CSeqInStreamBuf seqBufInStream; + + CSaveState saveState; +} CLzmaEnc; + + +#if defined(USE_UNUSED_CODE) +/*MAB: static added */ +static +void LzmaEnc_SaveState(CLzmaEncHandle pp) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + CSaveState *dest = &p->saveState; + int i; + dest->lenEnc = p->lenEnc; + dest->repLenEnc = p->repLenEnc; + dest->state = p->state; + + for (i = 0; i < kNumStates; i++) + { + memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); + memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); + } + for (i = 0; i < kNumLenToPosStates; i++) + memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); + memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); + memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); + memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); + memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); + memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); + memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); + memcpy(dest->reps, p->reps, sizeof(p->reps)); + memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb)); +} + +/*MAB: static added */ +static void LzmaEnc_RestoreState(CLzmaEncHandle pp) +{ + CLzmaEnc *dest = (CLzmaEnc *)pp; + const CSaveState *p = &dest->saveState; + int i; + dest->lenEnc = p->lenEnc; + dest->repLenEnc = p->repLenEnc; + dest->state = p->state; + + for (i = 0; i < kNumStates; i++) + { + memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); + memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); + } + for (i = 0; i < kNumLenToPosStates; i++) + memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); + memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); + memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); + memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); + memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); + memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); + memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); + memcpy(dest->reps, p->reps, sizeof(p->reps)); + memcpy(dest->litProbs, p->litProbs, (0x300 << dest->lclp) * sizeof(CLzmaProb)); +} +#endif + +SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + CLzmaEncProps props = *props2; + LzmaEncProps_Normalize(&props); + + if (props.lc > LZMA_LC_MAX || props.lp > LZMA_LP_MAX || props.pb > LZMA_PB_MAX || + props.dictSize > (1u << kDicLogSizeMaxCompress) || props.dictSize > (1u << 30)) /*MAB: 1u to silence warnings */ + return SZ_ERROR_PARAM; + p->dictSize = props.dictSize; + p->matchFinderCycles = props.mc; + { + unsigned fb = (unsigned) props.fb; /*MAB casts */ + if (fb < 5) + fb = 5; + if (fb > LZMA_MATCH_LEN_MAX) + fb = LZMA_MATCH_LEN_MAX; + p->numFastBytes = fb; + } + p->lc = (unsigned) props.lc; + p->lp = (unsigned) props.lp; + p->pb = (unsigned) props.pb; + p->fastMode = (props.algo == 0); + p->matchFinderBase.btMode = props.btMode; + { + UInt32 numHashBytes = 4; + if (props.btMode) + { + if (props.numHashBytes < 2) + numHashBytes = 2; + else if (props.numHashBytes < 4) + numHashBytes = (UInt32) props.numHashBytes; /*MAB casts */ + } + p->matchFinderBase.numHashBytes = numHashBytes; + } + + p->matchFinderBase.cutValue = props.mc; + + p->writeEndMark = (Bool) props.writeEndMark; /*MAB casts */ + + #ifdef COMPRESS_MF_MT + /* + if (newMultiThread != _multiThread) + { + ReleaseMatchFinder(); + _multiThread = newMultiThread; + } + */ + p->multiThread = (props.numThreads > 1); + #endif + + return SZ_OK; +} + +static const int kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; +static const int kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; +static const int kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; +static const int kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; + +#define IsCharState(s) ((s) < 7) + +#define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1) + +#define kInfinityPrice (1 << 30) + +static void RangeEnc_Construct(CRangeEnc *p) +{ + p->outStream = 0; + p->bufBase = 0; +} + +#define RangeEnc_GetProcessed(p) ((p)->processed + (UInt64) ((p)->buf - (p)->bufBase) + (p)->cacheSize) /*MAB casts */ + +#define RC_BUF_SIZE (1 << 16) +static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc) +{ + if (p->bufBase == 0) + { + p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE); + if (p->bufBase == 0) + return 0; + p->bufLim = p->bufBase + RC_BUF_SIZE; + } + return 1; +} + +static void RangeEnc_Free(CRangeEnc *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->bufBase); + p->bufBase = 0; +} + +static void RangeEnc_Init(CRangeEnc *p) +{ + /* Stream.Init(); */ + p->low = 0; + p->range = 0xFFFFFFFF; + p->cacheSize = 1; + p->cache = 0; + + p->buf = p->bufBase; + + p->processed = 0; + p->res = SZ_OK; +} + +static void RangeEnc_FlushStream(CRangeEnc *p) +{ + size_t num; + if (p->res != SZ_OK) + return; + num = (size_t)(p->buf - p->bufBase); /*MAB casts */ + if (num != p->outStream->Write(p->outStream, p->bufBase, num)) + p->res = SZ_ERROR_WRITE; + p->processed += num; + p->buf = p->bufBase; +} + +static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p) +{ + if ((UInt32)p->low < (UInt32)0xFF000000 || (int)(p->low >> 32) != 0) + { + Byte temp = p->cache; + do + { + Byte *buf = p->buf; + *buf++ = (Byte)(temp + (Byte)(p->low >> 32)); + p->buf = buf; + if (buf == p->bufLim) + RangeEnc_FlushStream(p); + temp = 0xFF; + } + while (--p->cacheSize != 0); + p->cache = (Byte)((UInt32)p->low >> 24); + } + p->cacheSize++; + p->low = (UInt32)p->low << 8; +} + +static void RangeEnc_FlushData(CRangeEnc *p) +{ + int i; + for (i = 0; i < 5; i++) + RangeEnc_ShiftLow(p); +} + +static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, int numBits) +{ + do + { + p->range >>= 1; + p->low += p->range & (0 - ((value >> --numBits) & 1)); + if (p->range < kTopValue) + { + p->range <<= 8; + RangeEnc_ShiftLow(p); + } + } + while (numBits != 0); +} + +static void RangeEnc_EncodeBit(CRangeEnc *p, CLzmaProb *prob, UInt32 symbol) +{ + UInt32 ttt = *prob; + UInt32 newBound = (p->range >> kNumBitModelTotalBits) * ttt; + if (symbol == 0) + { + p->range = newBound; + ttt += (kBitModelTotal - ttt) >> kNumMoveBits; + } + else + { + p->low += newBound; + p->range -= newBound; + ttt -= ttt >> kNumMoveBits; + } + *prob = (CLzmaProb)ttt; + if (p->range < kTopValue) + { + p->range <<= 8; + RangeEnc_ShiftLow(p); + } +} + +static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol) +{ + symbol |= 0x100; + do + { + RangeEnc_EncodeBit(p, probs + (symbol >> 8), (symbol >> 7) & 1); + symbol <<= 1; + } + while (symbol < 0x10000); +} + +static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol, UInt32 matchByte) +{ + UInt32 offs = 0x100; + symbol |= 0x100; + do + { + matchByte <<= 1; + RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (symbol >> 8)), (symbol >> 7) & 1); + symbol <<= 1; + offs &= ~(matchByte ^ symbol); + } + while (symbol < 0x10000); +} + +/*MAB: static added */ +static void LzmaEnc_InitPriceTables(UInt32 *ProbPrices) +{ + UInt32 i; + for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits)) + { + const int kCyclesBits = kNumBitPriceShiftBits; + UInt32 w = i; + UInt32 bitCount = 0; + int j; + for (j = 0; j < kCyclesBits; j++) + { + w = w * w; + bitCount <<= 1; + while (w >= ((UInt32)1 << 16)) + { + w >>= 1; + bitCount++; + } + } + ProbPrices[i >> kNumMoveReducingBits] = (/*MAB: cast to silence*/(UInt32)(kNumBitModelTotalBits << kCyclesBits) - /*MAB: cast to silence*/(UInt32)15 - bitCount); + } +} + + +#define GET_PRICE(prob, symbol) \ + p->ProbPrices[((prob) ^ (((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; + +#define GET_PRICEa(prob, symbol) \ + ProbPrices[((prob) ^ ((-((int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; + +#define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits] +#define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] + +#define GET_PRICE_0a(prob) ProbPrices[(prob) >> kNumMoveReducingBits] +#define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] + +static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 *ProbPrices) +{ + UInt32 price = 0; + symbol |= 0x100; + do + { + price += GET_PRICEa(probs[symbol >> 8], (symbol >> 7) & 1); + symbol <<= 1; + } + while (symbol < 0x10000); + return price; +} + +static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, UInt32 *ProbPrices) +{ + UInt32 price = 0; + UInt32 offs = 0x100; + symbol |= 0x100; + do + { + matchByte <<= 1; + price += GET_PRICEa(probs[offs + (matchByte & offs) + (symbol >> 8)], (symbol >> 7) & 1); + symbol <<= 1; + offs &= ~(matchByte ^ symbol); + } + while (symbol < 0x10000); + return price; +} + + +static void RcTree_Encode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol) +{ + UInt32 m = 1; + int i; + for (i = numBitLevels; i != 0;) + { + UInt32 bit; + i--; + bit = (symbol >> i) & 1; + RangeEnc_EncodeBit(rc, probs + m, bit); + m = (m << 1) | bit; + } +} + +static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol) +{ + UInt32 m = 1; + int i; + for (i = 0; i < numBitLevels; i++) + { + UInt32 bit = symbol & 1; + RangeEnc_EncodeBit(rc, probs + m, bit); + m = (m << 1) | bit; + symbol >>= 1; + } +} + +static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices) +{ + UInt32 price = 0; + symbol |= (1u << numBitLevels); /*MAB 1u */ + while (symbol != 1) + { + price += GET_PRICEa(probs[symbol >> 1], symbol & 1); + symbol >>= 1; + } + return price; +} + +static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices) +{ + UInt32 price = 0; + UInt32 m = 1; + int i; + for (i = numBitLevels; i != 0; i--) + { + UInt32 bit = symbol & 1; + symbol >>= 1; + price += GET_PRICEa(probs[m], bit); + m = (m << 1) | bit; + } + return price; +} + + +static void LenEnc_Init(CLenEnc *p) +{ + unsigned i; + p->choice = p->choice2 = kProbInitValue; + for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumLowBits); i++) + p->low[i] = kProbInitValue; + for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumMidBits); i++) + p->mid[i] = kProbInitValue; + for (i = 0; i < kLenNumHighSymbols; i++) + p->high[i] = kProbInitValue; +} + +static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState) +{ + if (symbol < kLenNumLowSymbols) + { + RangeEnc_EncodeBit(rc, &p->choice, 0); + RcTree_Encode(rc, p->low + (posState << kLenNumLowBits), kLenNumLowBits, symbol); + } + else + { + RangeEnc_EncodeBit(rc, &p->choice, 1); + if (symbol < kLenNumLowSymbols + kLenNumMidSymbols) + { + RangeEnc_EncodeBit(rc, &p->choice2, 0); + RcTree_Encode(rc, p->mid + (posState << kLenNumMidBits), kLenNumMidBits, symbol - kLenNumLowSymbols); + } + else + { + RangeEnc_EncodeBit(rc, &p->choice2, 1); + RcTree_Encode(rc, p->high, kLenNumHighBits, symbol - kLenNumLowSymbols - kLenNumMidSymbols); + } + } +} + +static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, UInt32 *ProbPrices) +{ + UInt32 a0 = GET_PRICE_0a(p->choice); + UInt32 a1 = GET_PRICE_1a(p->choice); + UInt32 b0 = a1 + GET_PRICE_0a(p->choice2); + UInt32 b1 = a1 + GET_PRICE_1a(p->choice2); + UInt32 i = 0; + for (i = 0; i < kLenNumLowSymbols; i++) + { + if (i >= numSymbols) + return; + prices[i] = a0 + RcTree_GetPrice(p->low + (posState << kLenNumLowBits), kLenNumLowBits, i, ProbPrices); + } + for (; i < kLenNumLowSymbols + kLenNumMidSymbols; i++) + { + if (i >= numSymbols) + return; + prices[i] = b0 + RcTree_GetPrice(p->mid + (posState << kLenNumMidBits), kLenNumMidBits, i - kLenNumLowSymbols, ProbPrices); + } + for (; i < numSymbols; i++) + prices[i] = b1 + RcTree_GetPrice(p->high, kLenNumHighBits, i - kLenNumLowSymbols - kLenNumMidSymbols, ProbPrices); +} + +static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, UInt32 *ProbPrices) +{ + LenEnc_SetPrices(&p->p, posState, p->tableSize, p->prices[posState], ProbPrices); + p->counters[posState] = p->tableSize; +} + +static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, UInt32 *ProbPrices) +{ + UInt32 posState; + for (posState = 0; posState < numPosStates; posState++) + LenPriceEnc_UpdateTable(p, posState, ProbPrices); +} + +static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, UInt32 *ProbPrices) +{ + LenEnc_Encode(&p->p, rc, symbol, posState); + if (updatePrice) + if (--p->counters[posState] == 0) + LenPriceEnc_UpdateTable(p, posState, ProbPrices); +} + + + + +static void MovePos(CLzmaEnc *p, UInt32 num) +{ + #ifdef SHOW_STAT + ttt += num; + printf("\n MovePos %d", num); + #endif + if (num != 0) + { + p->additionalOffset += num; + p->matchFinder.Skip(p->matchFinderObj, num); + } +} + +static UInt32 ReadMatchDistances(CLzmaEnc *p, UInt32 *numDistancePairsRes) +{ + UInt32 lenRes = 0, numPairs; + p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); + numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches); + #ifdef SHOW_STAT + printf("\n i = %d numPairs = %d ", ttt, numPairs / 2); + ttt++; + { + UInt32 i; + for (i = 0; i < numPairs; i += 2) + printf("%2d %6d | ", p->matches[i], p->matches[i + 1]); + } + #endif + if (numPairs > 0) + { + lenRes = p->matches[numPairs - 2]; + if (lenRes == p->numFastBytes) + { + const Byte *pby = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + UInt32 distance = p->matches[numPairs - 1] + 1; + UInt32 numAvail = p->numAvail; + if (numAvail > LZMA_MATCH_LEN_MAX) + numAvail = LZMA_MATCH_LEN_MAX; + { + const Byte *pby2 = pby - distance; + for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++); + } + } + } + p->additionalOffset++; + *numDistancePairsRes = numPairs; + return lenRes; +} + + +#define MakeAsChar(p) (p)->backPrev = (UInt32)(-1); (p)->prev1IsChar = False; +#define MakeAsShortRep(p) (p)->backPrev = 0; (p)->prev1IsChar = False; +#define IsShortRep(p) ((p)->backPrev == 0) + +static UInt32 GetRepLen1Price(CLzmaEnc *p, UInt32 state, UInt32 posState) +{ + return + GET_PRICE_0(p->isRepG0[state]) + + GET_PRICE_0(p->isRep0Long[state][posState]); +} + +static UInt32 GetPureRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 state, UInt32 posState) +{ + UInt32 price; + if (repIndex == 0) + { + price = GET_PRICE_0(p->isRepG0[state]); + price += GET_PRICE_1(p->isRep0Long[state][posState]); + } + else + { + price = GET_PRICE_1(p->isRepG0[state]); + if (repIndex == 1) + price += GET_PRICE_0(p->isRepG1[state]); + else + { + price += GET_PRICE_1(p->isRepG1[state]); + price += GET_PRICE(p->isRepG2[state], repIndex - 2); + } + } + return price; +} + +static UInt32 GetRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 len, UInt32 state, UInt32 posState) +{ + return p->repLenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN] + + GetPureRepPrice(p, repIndex, state, posState); +} + +static UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur) +{ + UInt32 posMem = p->opt[cur].posPrev; + UInt32 backMem = p->opt[cur].backPrev; + p->optimumEndIndex = cur; + do + { + if (p->opt[cur].prev1IsChar) + { + MakeAsChar(&p->opt[posMem]) + p->opt[posMem].posPrev = posMem - 1; + if (p->opt[cur].prev2) + { + p->opt[posMem - 1].prev1IsChar = False; + p->opt[posMem - 1].posPrev = p->opt[cur].posPrev2; + p->opt[posMem - 1].backPrev = p->opt[cur].backPrev2; + } + } + { + UInt32 posPrev = posMem; + UInt32 backCur = backMem; + + backMem = p->opt[posPrev].backPrev; + posMem = p->opt[posPrev].posPrev; + + p->opt[posPrev].backPrev = backCur; + p->opt[posPrev].posPrev = cur; + cur = posPrev; + } + } + while (cur != 0); + *backRes = p->opt[0].backPrev; + p->optimumCurrentIndex = p->opt[0].posPrev; + return p->optimumCurrentIndex; +} + +#define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + (UInt32) ((prevByte) >> (8 - p->lc))) * 0x300) /*MAB cast UInt32 */ + +static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes) +{ + UInt32 numAvail, mainLen, repMaxIndex, i, lenEnd, len, cur; + /*MAB: Changed numPairs_, posState_ avoid hiding a variable later */ + UInt32 numPairs_, posState_; + /*MAB: Changed matchPrice_, repMatchPrice_ avoid hiding a variable later */ + UInt32 matchPrice_, repMatchPrice_, + normalMatchPrice; + UInt32 reps[LZMA_NUM_REPS], repLens[LZMA_NUM_REPS]; + UInt32 *matches; + /*MAB: Changed from data to avoid hiding a variable later */ + const Byte *data_; + /*MAB: Changed from matchByte to avoid hiding a variable later */ + Byte curByte_, matchByte_; + if (p->optimumEndIndex != p->optimumCurrentIndex) + { + const COptimal *opt = &p->opt[p->optimumCurrentIndex]; + UInt32 lenRes = opt->posPrev - p->optimumCurrentIndex; + *backRes = opt->backPrev; + p->optimumCurrentIndex = opt->posPrev; + return lenRes; + } + p->optimumCurrentIndex = p->optimumEndIndex = 0; + + if (p->additionalOffset == 0) + mainLen = ReadMatchDistances(p, &numPairs_); + else + { + mainLen = p->longestMatchLength; + numPairs_ = p->numPairs; + } + + numAvail = p->numAvail; + if (numAvail < 2) + { + *backRes = (UInt32)(-1); + return 1; + } + if (numAvail > LZMA_MATCH_LEN_MAX) + numAvail = LZMA_MATCH_LEN_MAX; + + data_ = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + repMaxIndex = 0; + for (i = 0; i < LZMA_NUM_REPS; i++) + { + UInt32 lenTest; + const Byte *data2; + reps[i] = p->reps[i]; + data2 = data_ - (reps[i] + 1); + if (data_[0] != data2[0] || data_[1] != data2[1]) + { + repLens[i] = 0; + continue; + } + for (lenTest = 2; lenTest < numAvail && data_[lenTest] == data2[lenTest]; lenTest++); + repLens[i] = lenTest; + if (lenTest > repLens[repMaxIndex]) + repMaxIndex = i; + } + if (repLens[repMaxIndex] >= p->numFastBytes) + { + UInt32 lenRes; + *backRes = repMaxIndex; + lenRes = repLens[repMaxIndex]; + MovePos(p, lenRes - 1); + return lenRes; + } + + matches = p->matches; + if (mainLen >= p->numFastBytes) + { + *backRes = matches[numPairs_ - 1] + LZMA_NUM_REPS; + MovePos(p, mainLen - 1); + return mainLen; + } + curByte_ = *data_; + matchByte_ = *(data_ - (reps[0] + 1)); + + if (mainLen < 2 && curByte_ != matchByte_ && repLens[repMaxIndex] < 2) + { + *backRes = (UInt32)-1; + return 1; + } + + p->opt[0].state = (CState)p->state; + + posState_ = (position & p->pbMask); + + { + const CLzmaProb *probs = LIT_PROBS(position, *(data_ - 1)); + p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState_]) + + (!IsCharState(p->state) ? + LitEnc_GetPriceMatched(probs, curByte_, matchByte_, p->ProbPrices) : + LitEnc_GetPrice(probs, curByte_, p->ProbPrices)); + } + + MakeAsChar(&p->opt[1]); + + matchPrice_ = GET_PRICE_1(p->isMatch[p->state][posState_]); + repMatchPrice_ = matchPrice_ + GET_PRICE_1(p->isRep[p->state]); + + if (matchByte_ == curByte_) + { + UInt32 shortRepPrice = repMatchPrice_ + GetRepLen1Price(p, p->state, posState_); + if (shortRepPrice < p->opt[1].price) + { + p->opt[1].price = shortRepPrice; + MakeAsShortRep(&p->opt[1]); + } + } + lenEnd = ((mainLen >= repLens[repMaxIndex]) ? mainLen : repLens[repMaxIndex]); + + if (lenEnd < 2) + { + *backRes = p->opt[1].backPrev; + return 1; + } + + p->opt[1].posPrev = 0; + for (i = 0; i < LZMA_NUM_REPS; i++) + p->opt[0].backs[i] = reps[i]; + + len = lenEnd; + do + p->opt[len--].price = kInfinityPrice; + while (len >= 2); + + for (i = 0; i < LZMA_NUM_REPS; i++) + { + UInt32 repLen = repLens[i]; + UInt32 price; + if (repLen < 2) + continue; + price = repMatchPrice_ + GetPureRepPrice(p, i, p->state, posState_); + do + { + UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState_][repLen - 2]; + COptimal *opt = &p->opt[repLen]; + if (curAndLenPrice < opt->price) + { + opt->price = curAndLenPrice; + opt->posPrev = 0; + opt->backPrev = i; + opt->prev1IsChar = False; + } + } + while (--repLen >= 2); + } + + normalMatchPrice = matchPrice_ + GET_PRICE_0(p->isRep[p->state]); + + len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); + if (len <= mainLen) + { + UInt32 offs = 0; + while (len > matches[offs]) + offs += 2; + for (; ; len++) + { + COptimal *opt; + UInt32 distance = matches[offs + 1]; + + UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState_][len - LZMA_MATCH_LEN_MIN]; + UInt32 lenToPosState = GetLenToPosState(len); + if (distance < kNumFullDistances) + curAndLenPrice += p->distancesPrices[lenToPosState][distance]; + else + { + UInt32 slot; + GetPosSlot2(distance, slot); + curAndLenPrice += p->alignPrices[distance & kAlignMask] + p->posSlotPrices[lenToPosState][slot]; + } + opt = &p->opt[len]; + if (curAndLenPrice < opt->price) + { + opt->price = curAndLenPrice; + opt->posPrev = 0; + opt->backPrev = distance + LZMA_NUM_REPS; + opt->prev1IsChar = False; + } + if (len == matches[offs]) + { + offs += 2; + if (offs == numPairs_) + break; + } + } + } + + cur = 0; + + #ifdef SHOW_STAT2 + if (position >= 0) + { + unsigned i__; + printf("\n pos = %4X", position); + for (i__ = cur; i__ <= lenEnd; i__++) + printf("\nprice[%4X] = %d", position - cur + i__, p->opt[i__].price); + } + #endif + + for (;;) + { + UInt32 numAvailFull, newLen, numPairs, posPrev, state, posState, startLen; + UInt32 curPrice, curAnd1Price, matchPrice, repMatchPrice; + Bool nextIsChar; + Byte curByte, matchByte; + const Byte *data; + COptimal *curOpt; + COptimal *nextOpt; + + cur++; + if (cur == lenEnd) + return Backward(p, backRes, cur); + + newLen = ReadMatchDistances(p, &numPairs); + if (newLen >= p->numFastBytes) + { + p->numPairs = numPairs; + p->longestMatchLength = newLen; + return Backward(p, backRes, cur); + } + position++; + curOpt = &p->opt[cur]; + posPrev = curOpt->posPrev; + if (curOpt->prev1IsChar) + { + posPrev--; + if (curOpt->prev2) + { + state = p->opt[curOpt->posPrev2].state; + if (curOpt->backPrev2 < LZMA_NUM_REPS) + state = (UInt32) kRepNextStates[state]; /*MAB casts */ + else + state = (UInt32) kMatchNextStates[state]; /*MAB casts */ + } + else + state = p->opt[posPrev].state; + state = (UInt32) kLiteralNextStates[state]; /*MAB casts */ + } + else + state = p->opt[posPrev].state; + if (posPrev == cur - 1) + { + if (IsShortRep(curOpt)) + state = (UInt32) kShortRepNextStates[state]; /*MAB casts */ + else + state = (UInt32) kLiteralNextStates[state]; /*MAB casts */ + } + else + { + UInt32 pos; + const COptimal *prevOpt; + if (curOpt->prev1IsChar && curOpt->prev2) + { + posPrev = curOpt->posPrev2; + pos = curOpt->backPrev2; + state = (UInt32) kRepNextStates[state]; /*MAB casts */ + } + else + { + pos = curOpt->backPrev; + if (pos < LZMA_NUM_REPS) + state = (UInt32) kRepNextStates[state]; /*MAB casts */ + else + state = (UInt32) kMatchNextStates[state]; /*MAB casts */ + } + prevOpt = &p->opt[posPrev]; + if (pos < LZMA_NUM_REPS) + { + /*MAB: i changed to i__ to avoid hiding a variable */ + UInt32 i__; + reps[0] = prevOpt->backs[pos]; + for (i__ = 1; i__ <= pos; i__++) + reps[i__] = prevOpt->backs[i__ - 1]; + for (; i__ < LZMA_NUM_REPS; i__++) + reps[i__] = prevOpt->backs[i__]; + } + else + { + /*MAB: i changed to i__ to avoid hiding a variable */ + UInt32 i__; + reps[0] = (pos - LZMA_NUM_REPS); + for (i__ = 1; i__ < LZMA_NUM_REPS; i__++) + reps[i__] = prevOpt->backs[i__ - 1]; + } + } + curOpt->state = (CState)state; + + curOpt->backs[0] = reps[0]; + curOpt->backs[1] = reps[1]; + curOpt->backs[2] = reps[2]; + curOpt->backs[3] = reps[3]; + + curPrice = curOpt->price; + nextIsChar = False; + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + curByte = *data; + matchByte = *(data - (reps[0] + 1)); + + posState = (position & p->pbMask); + + curAnd1Price = curPrice + GET_PRICE_0(p->isMatch[state][posState]); + { + const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); + curAnd1Price += + (!IsCharState(state) ? + LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) : + LitEnc_GetPrice(probs, curByte, p->ProbPrices)); + } + + nextOpt = &p->opt[cur + 1]; + + if (curAnd1Price < nextOpt->price) + { + nextOpt->price = curAnd1Price; + nextOpt->posPrev = cur; + MakeAsChar(nextOpt); + nextIsChar = True; + } + + matchPrice = curPrice + GET_PRICE_1(p->isMatch[state][posState]); + repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]); + + if (matchByte == curByte && !(nextOpt->posPrev < cur && nextOpt->backPrev == 0)) + { + UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, state, posState); + if (shortRepPrice <= nextOpt->price) + { + nextOpt->price = shortRepPrice; + nextOpt->posPrev = cur; + MakeAsShortRep(nextOpt); + nextIsChar = True; + } + } + numAvailFull = p->numAvail; + { + UInt32 temp = kNumOpts - 1 - cur; + if (temp < numAvailFull) + numAvailFull = temp; + } + + if (numAvailFull < 2) + continue; + numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes); + + if (!nextIsChar && matchByte != curByte) /* speed optimization */ + { + /* try Literal + rep0 */ + UInt32 temp; + UInt32 lenTest2; + const Byte *data2 = data - (reps[0] + 1); + UInt32 limit = p->numFastBytes + 1; + if (limit > numAvailFull) + limit = numAvailFull; + + for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++); + lenTest2 = temp - 1; + if (lenTest2 >= 2) + { + UInt32 state2 = (UInt32) kLiteralNextStates[state]; /*MAB casts */ + UInt32 posStateNext = (position + 1) & p->pbMask; + UInt32 nextRepMatchPrice = curAnd1Price + + GET_PRICE_1(p->isMatch[state2][posStateNext]) + + GET_PRICE_1(p->isRep[state2]); + /* for (; lenTest2 >= 2; lenTest2--) */ + { + UInt32 curAndLenPrice; + COptimal *opt; + UInt32 offset = cur + 1 + lenTest2; + while (lenEnd < offset) + p->opt[++lenEnd].price = kInfinityPrice; + curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); + opt = &p->opt[offset]; + if (curAndLenPrice < opt->price) + { + opt->price = curAndLenPrice; + opt->posPrev = cur + 1; + opt->backPrev = 0; + opt->prev1IsChar = True; + opt->prev2 = False; + } + } + } + } + + startLen = 2; /* speed optimization */ + { + UInt32 repIndex; + for (repIndex = 0; repIndex < LZMA_NUM_REPS; repIndex++) + { + UInt32 lenTest; + UInt32 lenTestTemp; + UInt32 price; + const Byte *data2 = data - (reps[repIndex] + 1); + if (data[0] != data2[0] || data[1] != data2[1]) + continue; + for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++); + while (lenEnd < cur + lenTest) + p->opt[++lenEnd].price = kInfinityPrice; + lenTestTemp = lenTest; + price = repMatchPrice + GetPureRepPrice(p, repIndex, state, posState); + do + { + UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][lenTest - 2]; + COptimal *opt = &p->opt[cur + lenTest]; + if (curAndLenPrice < opt->price) + { + opt->price = curAndLenPrice; + opt->posPrev = cur; + opt->backPrev = repIndex; + opt->prev1IsChar = False; + } + } + while (--lenTest >= 2); + lenTest = lenTestTemp; + + if (repIndex == 0) + startLen = lenTest + 1; + + /* if (_maxMode) */ + { + UInt32 lenTest2 = lenTest + 1; + UInt32 limit = lenTest2 + p->numFastBytes; + UInt32 nextRepMatchPrice; + if (limit > numAvailFull) + limit = numAvailFull; + for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); + lenTest2 -= lenTest + 1; + if (lenTest2 >= 2) + { + UInt32 state2 = (UInt32) kRepNextStates[state]; /*MAB casts */ + UInt32 posStateNext = (position + lenTest) & p->pbMask; + UInt32 curAndLenCharPrice = + price + p->repLenEnc.prices[posState][lenTest - 2] + + GET_PRICE_0(p->isMatch[state2][posStateNext]) + + LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]), + data[lenTest], data2[lenTest], p->ProbPrices); + state2 = (UInt32) kLiteralNextStates[state2]; /*MAB casts */ + posStateNext = (position + lenTest + 1) & p->pbMask; + nextRepMatchPrice = curAndLenCharPrice + + GET_PRICE_1(p->isMatch[state2][posStateNext]) + + GET_PRICE_1(p->isRep[state2]); + + /* for (; lenTest2 >= 2; lenTest2--) */ + { + UInt32 curAndLenPrice; + COptimal *opt; + UInt32 offset = cur + lenTest + 1 + lenTest2; + while (lenEnd < offset) + p->opt[++lenEnd].price = kInfinityPrice; + curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); + opt = &p->opt[offset]; + if (curAndLenPrice < opt->price) + { + opt->price = curAndLenPrice; + opt->posPrev = cur + lenTest + 1; + opt->backPrev = 0; + opt->prev1IsChar = True; + opt->prev2 = True; + opt->posPrev2 = cur; + opt->backPrev2 = repIndex; + } + } + } + } + } + } + /* for (UInt32 lenTest = 2; lenTest <= newLen; lenTest++) */ + if (newLen > numAvail) + { + newLen = numAvail; + for (numPairs = 0; newLen > matches[numPairs]; numPairs += 2); + matches[numPairs] = newLen; + numPairs += 2; + } + if (newLen >= startLen) + { + /*MAB: normalMatchPrice changed to normalMatchPrice__ not to hide a variable later */ + UInt32 normalMatchPrice__ = matchPrice + GET_PRICE_0(p->isRep[state]); + UInt32 offs, curBack, posSlot; + UInt32 lenTest; + while (lenEnd < cur + newLen) + p->opt[++lenEnd].price = kInfinityPrice; + + offs = 0; + while (startLen > matches[offs]) + offs += 2; + curBack = matches[offs + 1]; + GetPosSlot2(curBack, posSlot); + for (lenTest = /*2*/ startLen; ; lenTest++) + { + /*MAB: curAndLenPrice changed to curAndLenPrice__ not to hide a variable later */ + UInt32 curAndLenPrice__ = normalMatchPrice__ + p->lenEnc.prices[posState][lenTest - LZMA_MATCH_LEN_MIN]; + UInt32 lenToPosState = GetLenToPosState(lenTest); + /*MAB: opt changed to opt__ not to hide a variable later */ + COptimal *opt__; + if (curBack < kNumFullDistances) + curAndLenPrice__ += p->distancesPrices[lenToPosState][curBack]; + else + curAndLenPrice__ += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[curBack & kAlignMask]; + + opt__ = &p->opt[cur + lenTest]; + if (curAndLenPrice__ < opt__->price) + { + opt__->price = curAndLenPrice__; + opt__->posPrev = cur; + opt__->backPrev = curBack + LZMA_NUM_REPS; + opt__->prev1IsChar = False; + } + + if (/*_maxMode && */lenTest == matches[offs]) + { + /* Try Match + Literal + Rep0 */ + const Byte *data2 = data - (curBack + 1); + UInt32 lenTest2 = lenTest + 1; + UInt32 limit = lenTest2 + p->numFastBytes; + UInt32 nextRepMatchPrice; + if (limit > numAvailFull) + limit = numAvailFull; + for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); + lenTest2 -= lenTest + 1; + if (lenTest2 >= 2) + { + UInt32 state2 = (UInt32) kMatchNextStates[state]; /*MAB casts */ + UInt32 posStateNext = (position + lenTest) & p->pbMask; + UInt32 curAndLenCharPrice = curAndLenPrice__ + + GET_PRICE_0(p->isMatch[state2][posStateNext]) + + LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]), + data[lenTest], data2[lenTest], p->ProbPrices); + state2 = (UInt32) kLiteralNextStates[state2]; /*MAB casts */ + posStateNext = (posStateNext + 1) & p->pbMask; + nextRepMatchPrice = curAndLenCharPrice + + GET_PRICE_1(p->isMatch[state2][posStateNext]) + + GET_PRICE_1(p->isRep[state2]); + + /* for (; lenTest2 >= 2; lenTest2--) */ + { + UInt32 offset = cur + lenTest + 1 + lenTest2; + UInt32 curAndLenPrice; + COptimal *opt; + while (lenEnd < offset) + p->opt[++lenEnd].price = kInfinityPrice; + curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); + opt = &p->opt[offset]; + if (curAndLenPrice < opt->price) + { + opt->price = curAndLenPrice; + opt->posPrev = cur + lenTest + 1; + opt->backPrev = 0; + opt->prev1IsChar = True; + opt->prev2 = True; + opt->posPrev2 = cur; + opt->backPrev2 = curBack + LZMA_NUM_REPS; + } + } + } + offs += 2; + if (offs == numPairs) + break; + curBack = matches[offs + 1]; + if (curBack >= kNumFullDistances) + GetPosSlot2(curBack, posSlot); + } + } + } + } +} + +#define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist)) + +static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes) +{ + UInt32 numAvail, mainLen, mainDist, numPairs, repIndex, repLen, i; + const Byte *data; + const UInt32 *matches; + + if (p->additionalOffset == 0) + mainLen = ReadMatchDistances(p, &numPairs); + else + { + mainLen = p->longestMatchLength; + numPairs = p->numPairs; + } + + numAvail = p->numAvail; + *backRes = (UInt32)-1; + if (numAvail < 2) + return 1; + if (numAvail > LZMA_MATCH_LEN_MAX) + numAvail = LZMA_MATCH_LEN_MAX; + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + + repLen = repIndex = 0; + for (i = 0; i < LZMA_NUM_REPS; i++) + { + UInt32 len; + const Byte *data2 = data - (p->reps[i] + 1); + if (data[0] != data2[0] || data[1] != data2[1]) + continue; + for (len = 2; len < numAvail && data[len] == data2[len]; len++); + if (len >= p->numFastBytes) + { + *backRes = i; + MovePos(p, len - 1); + return len; + } + if (len > repLen) + { + repIndex = i; + repLen = len; + } + } + + matches = p->matches; + if (mainLen >= p->numFastBytes) + { + *backRes = matches[numPairs - 1] + LZMA_NUM_REPS; + MovePos(p, mainLen - 1); + return mainLen; + } + + mainDist = 0; /* for GCC */ + if (mainLen >= 2) + { + mainDist = matches[numPairs - 1]; + while (numPairs > 2 && mainLen == matches[numPairs - 4] + 1) + { + if (!ChangePair(matches[numPairs - 3], mainDist)) + break; + numPairs -= 2; + mainLen = matches[numPairs - 2]; + mainDist = matches[numPairs - 1]; + } + if (mainLen == 2 && mainDist >= 0x80) + mainLen = 1; + } + + if (repLen >= 2 && ( + (repLen + 1 >= mainLen) || + (repLen + 2 >= mainLen && mainDist >= (1 << 9)) || + (repLen + 3 >= mainLen && mainDist >= (1 << 15)))) + { + *backRes = repIndex; + MovePos(p, repLen - 1); + return repLen; + } + + if (mainLen < 2 || numAvail <= 2) + return 1; + + p->longestMatchLength = ReadMatchDistances(p, &p->numPairs); + if (p->longestMatchLength >= 2) + { + UInt32 newDistance = matches[p->numPairs - 1]; + if ((p->longestMatchLength >= mainLen && newDistance < mainDist) || + (p->longestMatchLength == mainLen + 1 && !ChangePair(mainDist, newDistance)) || + (p->longestMatchLength > mainLen + 1) || + (p->longestMatchLength + 1 >= mainLen && mainLen >= 3 && ChangePair(newDistance, mainDist))) + return 1; + } + + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + for (i = 0; i < LZMA_NUM_REPS; i++) + { + UInt32 len, limit; + const Byte *data2 = data - (p->reps[i] + 1); + if (data[0] != data2[0] || data[1] != data2[1]) + continue; + limit = mainLen - 1; + for (len = 2; len < limit && data[len] == data2[len]; len++); + if (len >= limit) + return 1; + } + *backRes = mainDist + LZMA_NUM_REPS; + MovePos(p, mainLen - 2); + return mainLen; +} + +static void WriteEndMarker(CLzmaEnc *p, UInt32 posState) +{ + UInt32 len; + RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1); + RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0); + p->state = (UInt32) kMatchNextStates[p->state]; /*MAB casts */ + len = LZMA_MATCH_LEN_MIN; + LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); + RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, (1 << kNumPosSlotBits) - 1); + RangeEnc_EncodeDirectBits(&p->rc, (((UInt32)1 << 30) - 1) >> kNumAlignBits, 30 - kNumAlignBits); + RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask); +} + +static SRes CheckErrors(CLzmaEnc *p) +{ + if (p->result != SZ_OK) + return p->result; + if (p->rc.res != SZ_OK) + p->result = SZ_ERROR_WRITE; + if (p->matchFinderBase.result != SZ_OK) + p->result = SZ_ERROR_READ; + if (p->result != SZ_OK) + p->finished = True; + return p->result; +} + +static SRes Flush(CLzmaEnc *p, UInt32 nowPos) +{ + /* ReleaseMFStream(); */ + p->finished = True; + if (p->writeEndMark) + WriteEndMarker(p, nowPos & p->pbMask); + RangeEnc_FlushData(&p->rc); + RangeEnc_FlushStream(&p->rc); + return CheckErrors(p); +} + +static void FillAlignPrices(CLzmaEnc *p) +{ + UInt32 i; + for (i = 0; i < kAlignTableSize; i++) + p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices); + p->alignPriceCount = 0; +} + +static void FillDistancesPrices(CLzmaEnc *p) +{ + UInt32 tempPrices[kNumFullDistances]; + /*MAB: i changed to j to avoid warnings later of hiding i */ + UInt32 j, lenToPosState; + for (j = kStartPosModelIndex; j < kNumFullDistances; j++) + { + UInt32 posSlot = GetPosSlot1(j); + UInt32 footerBits = ((posSlot >> 1) - 1); + UInt32 base = ((2 | (posSlot & 1)) << footerBits); + tempPrices[j] = RcTree_ReverseGetPrice(p->posEncoders + base - posSlot - 1, (int)footerBits, j - base, p->ProbPrices); /*MAB casts */ + } + + for (lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++) + { + UInt32 posSlot; + const CLzmaProb *encoder = p->posSlotEncoder[lenToPosState]; + UInt32 *posSlotPrices = p->posSlotPrices[lenToPosState]; + for (posSlot = 0; posSlot < p->distTableSize; posSlot++) + posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices); + for (posSlot = kEndPosModelIndex; posSlot < p->distTableSize; posSlot++) + posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits); + + { + UInt32 *distancesPrices = p->distancesPrices[lenToPosState]; + /*MAB: i changed to i__ to avoid hiding a variable */ + UInt32 i__; + for (i__ = 0; i__ < kStartPosModelIndex; i__++) + distancesPrices[i__] = posSlotPrices[i__]; + for (; i__ < kNumFullDistances; i__++) + distancesPrices[i__] = posSlotPrices[GetPosSlot1(i__)] + tempPrices[i__]; + } + } + p->matchPriceCount = 0; +} + +/*MAB: static added */ +static void LzmaEnc_Construct(CLzmaEnc *p) +{ + RangeEnc_Construct(&p->rc); + MatchFinder_Construct(&p->matchFinderBase); + #ifdef COMPRESS_MF_MT + MatchFinderMt_Construct(&p->matchFinderMt); + p->matchFinderMt.MatchFinder = &p->matchFinderBase; + #endif + + { + CLzmaEncProps props; + LzmaEncProps_Init(&props); + LzmaEnc_SetProps(p, &props); + } + + #ifndef LZMA_LOG_BSR + LzmaEnc_FastPosInit(p->g_FastPos); + #endif + + LzmaEnc_InitPriceTables(p->ProbPrices); + p->litProbs = 0; + p->saveState.litProbs = 0; +} + +CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc) +{ + void *p; + p = alloc->Alloc(alloc, sizeof(CLzmaEnc)); + if (p != 0) + LzmaEnc_Construct((CLzmaEnc *)p); + return p; +} + +/*MAB: static added */ +static void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->litProbs); + alloc->Free(alloc, p->saveState.litProbs); + p->litProbs = 0; + p->saveState.litProbs = 0; +} + +/*MAB: static added */ +static void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig) +{ + #ifdef COMPRESS_MF_MT + MatchFinderMt_Destruct(&p->matchFinderMt, allocBig); + #endif + MatchFinder_Free(&p->matchFinderBase, allocBig); + LzmaEnc_FreeLits(p, alloc); + RangeEnc_Free(&p->rc, alloc); +} + +void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig) +{ + LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig); + alloc->Free(alloc, p); +} + +static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize, UInt32 maxUnpackSize) +{ + UInt32 nowPos32, startPos32; + if (p->inStream != 0) + { + p->matchFinderBase.stream = p->inStream; + p->matchFinder.Init(p->matchFinderObj); + p->inStream = 0; + } + + if (p->finished) + return p->result; + RINOK(CheckErrors(p)); + + nowPos32 = (UInt32)p->nowPos64; + startPos32 = nowPos32; + + if (p->nowPos64 == 0) + { + UInt32 numPairs; + Byte curByte; + if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) + return Flush(p, nowPos32); + ReadMatchDistances(p, &numPairs); + RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][0], 0); + p->state = (UInt32) kLiteralNextStates[p->state]; /*MAB casts */ + curByte = p->matchFinder.GetIndexByte(p->matchFinderObj, (Int32)(0 - p->additionalOffset)); /*MAB casts */ + LitEnc_Encode(&p->rc, p->litProbs, curByte); + p->additionalOffset--; + nowPos32++; + } + + if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0) + for (;;) + { + UInt32 pos, len, posState; + + if (p->fastMode) + len = GetOptimumFast(p, &pos); + else + len = GetOptimum(p, nowPos32, &pos); + + #ifdef SHOW_STAT2 + printf("\n pos = %4X, len = %d pos = %d", nowPos32, len, pos); + #endif + + posState = nowPos32 & p->pbMask; + if (len == 1 && pos == (UInt32)-1) + { + Byte curByte; + CLzmaProb *probs; + const Byte *data; + + RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 0); + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; + curByte = *data; + probs = LIT_PROBS(nowPos32, *(data - 1)); + if (IsCharState(p->state)) + LitEnc_Encode(&p->rc, probs, curByte); + else + LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0] - 1)); + p->state = (UInt32) kLiteralNextStates[p->state]; /*MAB casts */ + } + else + { + RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1); + if (pos < LZMA_NUM_REPS) + { + RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 1); + if (pos == 0) + { + RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 0); + RangeEnc_EncodeBit(&p->rc, &p->isRep0Long[p->state][posState], ((len == 1) ? 0 : 1)); + } + else + { + UInt32 distance = p->reps[pos]; + RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 1); + if (pos == 1) + RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 0); + else + { + RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 1); + RangeEnc_EncodeBit(&p->rc, &p->isRepG2[p->state], pos - 2); + if (pos == 3) + p->reps[3] = p->reps[2]; + p->reps[2] = p->reps[1]; + } + p->reps[1] = p->reps[0]; + p->reps[0] = distance; + } + if (len == 1) + p->state = (UInt32) kShortRepNextStates[p->state]; /*MAB casts */ + else + { + LenEnc_Encode2(&p->repLenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); + p->state = (UInt32) kRepNextStates[p->state]; /*MAB casts */ + } + } + else + { + UInt32 posSlot; + RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0); + p->state = (UInt32) kMatchNextStates[p->state]; /*MAB casts */ + LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); + pos -= LZMA_NUM_REPS; + GetPosSlot(pos, posSlot); + RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot); + + if (posSlot >= kStartPosModelIndex) + { + UInt32 footerBits = ((posSlot >> 1) - 1); + UInt32 base = ((2 | (posSlot & 1)) << footerBits); + UInt32 posReduced = pos - base; + + if (posSlot < kEndPosModelIndex) + RcTree_ReverseEncode(&p->rc, p->posEncoders + base - posSlot - 1, (int)footerBits, posReduced); /*MAB casts */ + else + { + RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, (int)footerBits - kNumAlignBits); /*MAB casts */ + RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask); + p->alignPriceCount++; + } + } + p->reps[3] = p->reps[2]; + p->reps[2] = p->reps[1]; + p->reps[1] = p->reps[0]; + p->reps[0] = pos; + p->matchPriceCount++; + } + } + p->additionalOffset -= len; + nowPos32 += len; + if (p->additionalOffset == 0) + { + UInt32 processed; + if (!p->fastMode) + { + if (p->matchPriceCount >= (1 << 7)) + FillDistancesPrices(p); + if (p->alignPriceCount >= kAlignTableSize) + FillAlignPrices(p); + } + if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) + break; + processed = nowPos32 - startPos32; + + if (useLimits) + { + if (processed + kNumOpts + 300 >= maxUnpackSize || + RangeEnc_GetProcessed(&p->rc) + kNumOpts * 2 >= maxPackSize) + break; + } + else if (processed >= (1 << 15)) + { + p->nowPos64 += nowPos32 - startPos32; + return CheckErrors(p); + } + } + } + p->nowPos64 += nowPos32 - startPos32; + return Flush(p, nowPos32); +} + +#define kBigHashDicLimit ((UInt32)1 << 24) + +static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) +{ + UInt32 beforeSize = kNumOpts; + #ifdef COMPRESS_MF_MT + Bool btMode; /*MAB: this line wrap inside the compilation ifdef, btMode not used without it */ + #endif + + if (!RangeEnc_Alloc(&p->rc, alloc)) + return SZ_ERROR_MEM; + + #ifdef COMPRESS_MF_MT + btMode = (p->matchFinderBase.btMode != 0); /*MAB: this line moved inside the compilation ifdef, btMode not used without it */ + + p->mtMode = (p->multiThread && !p->fastMode && btMode); + #endif + + { + unsigned lclp = p->lc + p->lp; + if (p->litProbs == 0 || p->saveState.litProbs == 0 || p->lclp != lclp) + { + LzmaEnc_FreeLits(p, alloc); + p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300u << lclp) * sizeof(CLzmaProb)); /*MAB 0x300 vs 0x300u*/ + p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300u << lclp) * sizeof(CLzmaProb)); /*MAB 0x300 vs 0x300u*/ + if (p->litProbs == 0 || p->saveState.litProbs == 0) + { + LzmaEnc_FreeLits(p, alloc); + return SZ_ERROR_MEM; + } + p->lclp = lclp; + } + } + + p->matchFinderBase.bigHash = (p->dictSize > kBigHashDicLimit); + + if (beforeSize + p->dictSize < keepWindowSize) + beforeSize = keepWindowSize - p->dictSize; + + #ifdef COMPRESS_MF_MT + if (p->mtMode) + { + RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)); + p->matchFinderObj = &p->matchFinderMt; + MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder); + } + else + #endif + { + if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)) + return SZ_ERROR_MEM; + p->matchFinderObj = &p->matchFinderBase; + MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder); + } + return SZ_OK; +} + +/*MAB: static added */ +static void LzmaEnc_Init(CLzmaEnc *p) +{ + UInt32 i; + p->state = 0; + for (i = 0 ; i < LZMA_NUM_REPS; i++) + p->reps[i] = 0; + + RangeEnc_Init(&p->rc); + + + for (i = 0; i < kNumStates; i++) + { + UInt32 j; + for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++) + { + p->isMatch[i][j] = kProbInitValue; + p->isRep0Long[i][j] = kProbInitValue; + } + p->isRep[i] = kProbInitValue; + p->isRepG0[i] = kProbInitValue; + p->isRepG1[i] = kProbInitValue; + p->isRepG2[i] = kProbInitValue; + } + + { + UInt32 num = (UInt32) (0x300 << (p->lp + p->lc)); /*MAB casts */ + for (i = 0; i < num; i++) + p->litProbs[i] = kProbInitValue; + } + + { + for (i = 0; i < kNumLenToPosStates; i++) + { + CLzmaProb *probs = p->posSlotEncoder[i]; + UInt32 j; + for (j = 0; j < (1 << kNumPosSlotBits); j++) + probs[j] = kProbInitValue; + } + } + { + for (i = 0; i < kNumFullDistances - kEndPosModelIndex; i++) + p->posEncoders[i] = kProbInitValue; + } + + LenEnc_Init(&p->lenEnc.p); + LenEnc_Init(&p->repLenEnc.p); + + for (i = 0; i < (1 << kNumAlignBits); i++) + p->posAlignEncoder[i] = kProbInitValue; + + p->optimumEndIndex = 0; + p->optimumCurrentIndex = 0; + p->additionalOffset = 0; + + p->pbMask = (1u << p->pb) - 1u; /*MAB 1u */ + p->lpMask = (1u << p->lp) - 1u; /*MAB 1u */ +} + +/*MAB: static added */ +static void LzmaEnc_InitPrices(CLzmaEnc *p) +{ + if (!p->fastMode) + { + FillDistancesPrices(p); + FillAlignPrices(p); + } + + p->lenEnc.tableSize = + p->repLenEnc.tableSize = + p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN; + LenPriceEnc_UpdateTables(&p->lenEnc, 1u << p->pb, p->ProbPrices); /*MAB 1u */ + LenPriceEnc_UpdateTables(&p->repLenEnc, 1u << p->pb, p->ProbPrices); /*MAB 1u */ +} + +static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) +{ + UInt32 i; + for (i = 0; i < (UInt32)kDicLogSizeMaxCompress; i++) + if (p->dictSize <= ((UInt32)1 << i)) + break; + p->distTableSize = i * 2; + + p->finished = False; + p->result = SZ_OK; + RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig)); + LzmaEnc_Init(p); + LzmaEnc_InitPrices(p); + p->nowPos64 = 0; + return SZ_OK; +} + +static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqInStream *inStream, ISeqOutStream *outStream, + ISzAlloc *alloc, ISzAlloc *allocBig) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + p->inStream = inStream; + p->rc.outStream = outStream; + return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig); +} + +#if defined(USE_UNUSED_CODE) +/*MAB: static added */ +static SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, + ISeqInStream *inStream, UInt32 keepWindowSize, + ISzAlloc *alloc, ISzAlloc *allocBig) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + p->inStream = inStream; + return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); +} +#endif + +static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen) +{ + p->seqBufInStream.funcTable.Read = MyRead; + p->seqBufInStream.data = src; + p->seqBufInStream.rem = srcLen; +} + +#if defined(USE_UNUSED_CODE) +/*MAB: static added */ +static SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, + UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + LzmaEnc_SetInputBuf(p, src, srcLen); + p->inStream = &p->seqBufInStream.funcTable; + return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); +} +#endif + +/*MAB: static added */ +static void LzmaEnc_Finish(CLzmaEncHandle pp) +{ + #ifdef COMPRESS_MF_MT + CLzmaEnc *p = (CLzmaEnc *)pp; + if (p->mtMode) + MatchFinderMt_ReleaseStream(&p->matchFinderMt); + #else + pp = pp; + #endif +} + +typedef struct _CSeqOutStreamBuf +{ + ISeqOutStream funcTable; + Byte *data; + SizeT rem; + Bool overflow; +} CSeqOutStreamBuf; + +static size_t MyWrite(void *pp, const void *data, size_t size) +{ + CSeqOutStreamBuf *p = (CSeqOutStreamBuf *)pp; + if (p->rem < size) + { + size = p->rem; + p->overflow = True; + } + memcpy(p->data, data, size); + p->rem -= size; + p->data += size; + return size; +} + +#if defined(USE_UNUSED_CODE) +/*MAB: static added */ +static UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp) +{ + const CLzmaEnc *p = (CLzmaEnc *)pp; + return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); +} + +/*MAB: static added */ +static +const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp) +{ + const CLzmaEnc *p = (CLzmaEnc *)pp; + return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; +} + +/*MAB: static added */ +static +SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit, + Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + UInt64 nowPos64; + SRes res; + CSeqOutStreamBuf outStream; + + outStream.funcTable.Write = MyWrite; + outStream.data = dest; + outStream.rem = *destLen; + outStream.overflow = False; + + p->writeEndMark = False; + p->finished = False; + p->result = SZ_OK; + + if (reInit) + LzmaEnc_Init(p); + LzmaEnc_InitPrices(p); + nowPos64 = p->nowPos64; + RangeEnc_Init(&p->rc); + p->rc.outStream = &outStream.funcTable; + + res = LzmaEnc_CodeOneBlock(p, True, desiredPackSize, *unpackSize); + + *unpackSize = (UInt32)(p->nowPos64 - nowPos64); + *destLen -= outStream.rem; + if (outStream.overflow) + return SZ_ERROR_OUTPUT_EOF; + + return res; +} +#endif + +SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, + ISzAlloc *alloc, ISzAlloc *allocBig) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + SRes res = SZ_OK; + + #ifdef COMPRESS_MF_MT + Byte allocaDummy[0x300]; + int i = 0; + for (i = 0; i < 16; i++) + allocaDummy[i] = (Byte)i; + #endif + + RINOK(LzmaEnc_Prepare(pp, inStream, outStream, alloc, allocBig)); + + for (;;) + { + res = LzmaEnc_CodeOneBlock(p, False, 0, 0); + if (res != SZ_OK || p->finished != 0) + break; + if (progress != 0) + { + res = progress->Progress(progress, p->nowPos64, (UInt64) RangeEnc_GetProcessed(&p->rc)); /*MAB casts */ + if (res != SZ_OK) + { + res = SZ_ERROR_PROGRESS; + break; + } + } + } + LzmaEnc_Finish(pp); + return res; +} + +SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + int i; + UInt32 dictSize = p->dictSize; + if (*size < LZMA_PROPS_SIZE) + return SZ_ERROR_PARAM; + *size = LZMA_PROPS_SIZE; + props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc); + + for (i = 11; i <= 30; i++) + { + if (dictSize <= ((UInt32)2 << i)) + { + dictSize = (UInt32)(2 << i); /*MAB casts */ + break; + } + if (dictSize <= ((UInt32)3 << i)) + { + dictSize = (UInt32)(3 << i); /*MAB casts */ + break; + } + } + + for (i = 0; i < 4; i++) + props[1 + i] = (Byte)(dictSize >> (8 * i)); + return SZ_OK; +} + +SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) +{ + SRes res; + CLzmaEnc *p = (CLzmaEnc *)pp; + + CSeqOutStreamBuf outStream; + + LzmaEnc_SetInputBuf(p, src, srcLen); + + outStream.funcTable.Write = MyWrite; + outStream.data = dest; + outStream.rem = *destLen; + outStream.overflow = False; + + p->writeEndMark = writeEndMark; + res = LzmaEnc_Encode(pp, &outStream.funcTable, &p->seqBufInStream.funcTable, + progress, alloc, allocBig); + + *destLen -= outStream.rem; + if (outStream.overflow) + return SZ_ERROR_OUTPUT_EOF; + return res; +} + +SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, + ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) +{ + CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc); + SRes res; + if (p == 0) + return SZ_ERROR_MEM; + + res = LzmaEnc_SetProps(p, props); + if (res == SZ_OK) + { + res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize); + if (res == SZ_OK) + res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen, + writeEndMark, progress, alloc, allocBig); + } + + LzmaEnc_Destroy(p, alloc, allocBig); + return res; +} diff --git a/DroidFish/jni/gtb/compression/lzma/LzmaEnc.h b/DroidFish/jni/gtb/compression/lzma/LzmaEnc.h new file mode 100755 index 0000000..e3d84fa --- /dev/null +++ b/DroidFish/jni/gtb/compression/lzma/LzmaEnc.h @@ -0,0 +1,72 @@ +/* LzmaEnc.h -- LZMA Encoder +2008-10-04 : Igor Pavlov : Public domain */ + +#ifndef __LZMAENC_H +#define __LZMAENC_H + +#include "Types.h" + +#define LZMA_PROPS_SIZE 5 + +typedef struct _CLzmaEncProps +{ + int level; /* 0 <= level <= 9 */ + UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version + (1 << 12) <= dictSize <= (1 << 30) for 64-bit version + default = (1 << 24) */ + int lc; /* 0 <= lc <= 8, default = 3 */ + int lp; /* 0 <= lp <= 4, default = 0 */ + int pb; /* 0 <= pb <= 4, default = 2 */ + int algo; /* 0 - fast, 1 - normal, default = 1 */ + int fb; /* 5 <= fb <= 273, default = 32 */ + int btMode; /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */ + int numHashBytes; /* 2, 3 or 4, default = 4 */ + UInt32 mc; /* 1 <= mc <= (1 << 30), default = 32 */ + unsigned writeEndMark; /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */ + int numThreads; /* 1 or 2, default = 2 */ +} CLzmaEncProps; + +void LzmaEncProps_Init(CLzmaEncProps *p); +void LzmaEncProps_Normalize(CLzmaEncProps *p); +UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2); + + +/* ---------- CLzmaEncHandle Interface ---------- */ + +/* LzmaEnc_* functions can return the following exit codes: +Returns: + SZ_OK - OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_PARAM - Incorrect paramater in props + SZ_ERROR_WRITE - Write callback error. + SZ_ERROR_PROGRESS - some break from progress callback + SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) +*/ + +typedef void * CLzmaEncHandle; + +CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc); +void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig); +SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props); +SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size); +SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream, + ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); +SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); + +/* ---------- One Call Interface ---------- */ + +/* LzmaEncode +Return code: + SZ_OK - OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_PARAM - Incorrect paramater + SZ_ERROR_OUTPUT_EOF - output buffer overflow + SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) +*/ + +SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, + ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); + +#endif diff --git a/DroidFish/jni/gtb/compression/lzma/Types.h b/DroidFish/jni/gtb/compression/lzma/Types.h new file mode 100755 index 0000000..4e58832 --- /dev/null +++ b/DroidFish/jni/gtb/compression/lzma/Types.h @@ -0,0 +1,208 @@ +/* Types.h -- Basic types +2008-11-23 : Igor Pavlov : Public domain */ + +#ifndef __7Z_TYPES_H +#define __7Z_TYPES_H + +#include + +#ifdef _WIN32 +#include +#endif + +#define SZ_OK 0 + +#define SZ_ERROR_DATA 1 +#define SZ_ERROR_MEM 2 +#define SZ_ERROR_CRC 3 +#define SZ_ERROR_UNSUPPORTED 4 +#define SZ_ERROR_PARAM 5 +#define SZ_ERROR_INPUT_EOF 6 +#define SZ_ERROR_OUTPUT_EOF 7 +#define SZ_ERROR_READ 8 +#define SZ_ERROR_WRITE 9 +#define SZ_ERROR_PROGRESS 10 +#define SZ_ERROR_FAIL 11 +#define SZ_ERROR_THREAD 12 + +#define SZ_ERROR_ARCHIVE 16 +#define SZ_ERROR_NO_ARCHIVE 17 + +typedef int SRes; + +#ifdef _WIN32 +typedef DWORD WRes; +#else +typedef int WRes; +#endif + +#ifndef RINOK +#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } +#endif + +typedef unsigned char Byte; +typedef short Int16; +typedef unsigned short UInt16; + +#ifdef _LZMA_UINT32_IS_ULONG +typedef long Int32; +typedef unsigned long UInt32; +#else +typedef int Int32; +typedef unsigned int UInt32; +#endif + +#ifdef _SZ_NO_INT_64 + +/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers. + NOTES: Some code will work incorrectly in that case! */ + +typedef long Int64; +typedef unsigned long UInt64; + +#else + +#if defined(_MSC_VER) || defined(__BORLANDC__) +typedef __int64 Int64; +typedef unsigned __int64 UInt64; +#else +typedef long long int Int64; +typedef unsigned long long int UInt64; +#endif + +#endif + +#ifdef _LZMA_NO_SYSTEM_SIZE_T +typedef UInt32 SizeT; +#else +typedef size_t SizeT; +#endif + +typedef int Bool; +#define True 1 +#define False 0 + + +#ifdef _MSC_VER + +#if _MSC_VER >= 1300 +#define MY_NO_INLINE __declspec(noinline) +#else +#define MY_NO_INLINE +#endif + +#define MY_CDECL __cdecl +#define MY_STD_CALL __stdcall +#define MY_FAST_CALL MY_NO_INLINE __fastcall + +#else + +#define MY_CDECL +#define MY_STD_CALL +#define MY_FAST_CALL + +#endif + + +/* The following interfaces use first parameter as pointer to structure */ + +typedef struct ISeqInStream +{ + SRes (*Read)(void *p, void *buf, size_t *size); + /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. + (output(*size) < input(*size)) is allowed */ +} ISeqInStream; + +/* it can return SZ_ERROR_INPUT_EOF */ +SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size); +SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType); +SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf); + +typedef struct ISeqOutStream +{ + size_t (*Write)(void *p, const void *buf, size_t size); + /* Returns: result - the number of actually written bytes. + (result < size) means error */ +} ISeqOutStream; + +typedef enum ESzSeek +{ + SZ_SEEK_SET = 0, + SZ_SEEK_CUR = 1, + SZ_SEEK_END = 2 +} ESzSeek; + +typedef struct ISeekInStream +{ + SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */ + SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); +} ISeekInStream; + +typedef struct ILookInStream +{ + SRes (*Look)(void *p, void **buf, size_t *size); + /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. + (output(*size) > input(*size)) is not allowed + (output(*size) < input(*size)) is allowed */ + SRes (*Skip)(void *p, size_t offset); + /* offset must be <= output(*size) of Look */ + + SRes (*Read)(void *p, void *buf, size_t *size); + /* reads directly (without buffer). It's same as ISeqInStream::Read */ + SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); +} ILookInStream; + +SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size); +SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset); + +/* reads via ILookInStream::Read */ +SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType); +SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size); + +#define LookToRead_BUF_SIZE (1 << 14) + +typedef struct CLookToRead +{ + ILookInStream s; + ISeekInStream *realStream; + size_t pos; + size_t size; + Byte buf[LookToRead_BUF_SIZE]; +} CLookToRead; + +void LookToRead_CreateVTable(CLookToRead *p, int lookahead); +void LookToRead_Init(CLookToRead *p); + +typedef struct CSecToLook +{ + ISeqInStream s; + ILookInStream *realStream; +} CSecToLook; + +void SecToLook_CreateVTable(CSecToLook *p); + +typedef struct CSecToRead +{ + ISeqInStream s; + ILookInStream *realStream; +} CSecToRead; + +void SecToRead_CreateVTable(CSecToRead *p); + +typedef struct ICompressProgress +{ + SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize); + /* Returns: result. (result != SZ_OK) means break. + Value (UInt64)(Int64)-1 for size means unknown value. */ +} ICompressProgress; + +typedef struct ISzAlloc +{ + void *(*Alloc)(void *p, size_t size); + void (*Free)(void *p, void *address); /* address can be 0 */ +} ISzAlloc; + +#define IAlloc_Alloc(p, size) (p)->Alloc((p), size) +#define IAlloc_Free(p, a) (p)->Free((p), a) + +#endif diff --git a/DroidFish/jni/gtb/compression/wrap.c b/DroidFish/jni/gtb/compression/wrap.c new file mode 100644 index 0000000..8aae16e --- /dev/null +++ b/DroidFish/jni/gtb/compression/wrap.c @@ -0,0 +1,338 @@ +/* wrap.c */ + +/* +This Software is distributed with the following X11 License, +sometimes also known as MIT license. + +Copyright (c) 2010 Miguel A. Ballicora + + 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. +*/ + +#include "wrap.h" + +#define LZMA86 +#define ZLIB +#define HUFFMAN +#define LIBLZF +/*#define LIBBZIP2*/ + +#if defined(LZMA86) +#include "Lzma86Enc.h" +#include "Lzma86Dec.h" +#endif + +#if defined(ZLIB) +#include "zlib.h" +#endif + +#if defined(HUFFMAN) +#include "hzip.h" +#endif + +#if defined(LIBLZF) +#include "lzf.h" +#endif + +#if defined(LIBBZIP2) +#include "bzlib.h" +#endif + +#if !defined(NDEBUG) +#define NDEBUG +#endif +#ifdef DEBUG +#undef NDEBUG +#endif +#include "assert.h" + +/* external, so the compiler can be silenced */ +size_t TB_DUMMY_unused; + +/***********************************************************************************************************/ + +extern int +zlib_encode +(const unsigned char *in_start, size_t in_len, unsigned char *out_start, size_t *pout_len, size_t out_max) +{ + enum COMPRESSION_LEVELS {ZLIB_MAXIMUM_COMPRESSION = 9}; + int outcome; + unsigned long zz = (unsigned long)out_max; + outcome = compress2 (out_start, &zz, in_start, (z_uLong)in_len, ZLIB_MAXIMUM_COMPRESSION); + *pout_len = (size_t) zz; + return outcome == Z_OK; +} + +extern int +zlib_decode +(const unsigned char *in_start, size_t in_len, unsigned char *out_start, size_t *pout_len, size_t out_max) +{ + int outcome; + unsigned long nn = (unsigned long) out_max /* *pout_len */; + outcome = uncompress (out_start, &nn, in_start, (unsigned long)in_len); + *pout_len = (size_t)nn; + return outcome == Z_OK; +} + +/***********************************************************************************************************/ + +extern int +lzf_encode +(const unsigned char *in_start, size_t in_len, unsigned char *out_start, size_t *pout_len, size_t out_max) +{ + size_t x = lzf_compress (in_start, (unsigned)in_len, out_start, (unsigned)(in_len-1) /* ensures best compression */); + TB_DUMMY_unused = out_max; + if (x != 0) + *pout_len = (size_t) x; + return x != 0; +} + +extern int +lzf_decode +(const unsigned char *in_start, size_t in_len, unsigned char *out_start, size_t *pout_len, size_t out_max) +{ + *pout_len = (size_t)lzf_decompress (in_start, (unsigned)in_len, out_start, (unsigned)out_max); + return *pout_len != 0; +} + +/***********************************************************************************************************/ + +extern int +lzma_encode +(const unsigned char *in_start, size_t in_len, unsigned char *out_start, size_t *pout_len, size_t out_max) +{ + int level = 5; /* 5 => default compression level */ + unsigned int memory = 4096; /* dictionary size */ + int filter = SZ_FILTER_NO; /* => 0, use LZMA, do not try to optimize with x86 filter */ + size_t zz = out_max; /* maximum memory allowed, receives back the actual size */ + int x = Lzma86_Encode(out_start, &zz, in_start, in_len, level, memory, filter); + *pout_len = zz; + return x == 0; +} + +extern int +lzma_decode +(const unsigned char *in_start, size_t in_len, unsigned char *out_start, size_t *pout_len, size_t out_max) +{ + size_t nn = out_max; + int x = Lzma86_Decode(out_start, &nn, in_start, &in_len); + *pout_len = nn; + return x == SZ_OK; +} + +/***********************************************************************************************************/ + +#if defined (LIBBZIP2) + +extern int +bzip2_encode +(const unsigned char *in_start, size_t in_len, unsigned char *out_start, size_t *pout_len, size_t out_max) +{ + int blockSize100k = 9; + int verbosity = 0; + int workFactor = 30; + size_t destlen = out_max; + + int x = BZ2_bzBuffToBuffCompress( (char*)out_start, &destlen, (char*)in_start, in_len, + blockSize100k, verbosity, workFactor); + *pout_len = destlen; + return x == BZ_OK; +} + +extern int +bzip2_decode +(const unsigned char *in_start, size_t in_len, unsigned char *out_start, size_t *pout_len, size_t out_max) +{ + int small = 1; + int verbosity = 0; + size_t destlen = n; + + int x = BZ2_bzBuffToBuffDecompress( (char*)out_start, &destlen, (char*)in_start, in_len, + small, verbosity); + *pout_len = destlen; + return x == BZ_OK; +} + +#endif + +/***********************************************************************************************************/ + +extern int +justcopy_encode +(const unsigned char *in_start, size_t in_len, unsigned char *out_start, size_t *pout_len, size_t out_max) +{ + size_t i; + const unsigned char *in = in_start; + unsigned char *out = out_start; + + if (in_len > out_max) + return 0; + + for (i = 0; i < in_len; i++) { + *out++ = *in++; + } + *pout_len = in_len; + return 1; +} + +extern int +justcopy_decode +(const unsigned char *in_start, size_t in_len, unsigned char *out_start, size_t *pout_len, size_t out_max) +{ + size_t i; + const unsigned char *in = in_start; + unsigned char *out = out_start; + + if (in_len > out_max) + return 0; + + for (i = 0; i < in_len; i++) { + *out++ = *in++; + } + *pout_len = in_len; + return 1; +} + +/***********************************************************************************************************/ + +#define RLE_ESC 253 +#define RLE_TER 254 +#define RLE_MAX 252 +#define TRUE 1 +#define FALSE 0 + +extern int +rle_encode +(const unsigned char *in_start, size_t in_len, unsigned char *out_start, size_t *pout_len, size_t out_max) +{ + const unsigned char *p; + const unsigned char *in = in_start; + const unsigned char *in_end = in + in_len; + unsigned char *out = out_start; + int ok = TRUE; + int ch; + ptrdiff_t out_len; + + while (in < in_end) + { + if (*in == RLE_ESC) { + + *out++ = RLE_ESC; + *out++ = RLE_ESC; + in++; + + } else { + + ch = *in; + + if ( (in_end-in) >= 3 /* enough space for a run */ + && ch == in[1] && ch == in[2] && ch == in[3] /* enough length */) { + + p = in; + while (p < in_end && *p == ch && (p-in) < RLE_MAX) { + p++; + } + + *out++ = RLE_ESC; + assert (RLE_MAX < 256); + *out++ = (unsigned char)(p - in); + *out++ = (unsigned char)ch; + in = p; + + } else { + *out++ = *in++; + } + } + } + + if (ok) { + /* *out++ = RLE_ESC; *out++ = RLE_TER; */ + out_len = out - out_start; + *pout_len = (size_t)out_len; + ok = (size_t)out_len <= out_max; + } + + return ok; +} + +extern int +rle_decode +(const unsigned char *in_start, size_t in_len, unsigned char *out_start, size_t *pout_len, size_t out_max) +{ + const unsigned char *in = in_start; + const unsigned char *in_end = in + in_len; + unsigned char *out = out_start; + unsigned char *out_end = out + *pout_len; + int ok = TRUE; + int ch; + int n; + ptrdiff_t out_len; + + while (in < in_end) + { + if (in >= in_end) { ok = FALSE; break;} + if (out >= out_end) { ok = FALSE; break;} + + if (*in == RLE_ESC) { + ++in; if (in >= in_end) { ok = FALSE; break;} + + if (*in == RLE_ESC) { + *out++ = *in++; + } /*else if (*in == RLE_TER) {ok = TRUE;break;} */ else { + + /* rle */ + n = *in++; if (in >= in_end) { ok = FALSE; break;} + ch = *in++; + while (n-->0) { if (out >= out_end) { ok = FALSE; break;} + *out++ = (unsigned char)ch; + } + } + } else { + *out++ = *in++; + } + } + + out_len = out - out_start; + + if (ok) + *pout_len = (size_t)out_len; + + ok = ok && (out_max >= (size_t)out_len); + + return ok; +} + + + + + + + + + + + + + + + + diff --git a/DroidFish/jni/gtb/compression/wrap.h b/DroidFish/jni/gtb/compression/wrap.h new file mode 100644 index 0000000..d02dcff --- /dev/null +++ b/DroidFish/jni/gtb/compression/wrap.h @@ -0,0 +1,58 @@ +/* wrap.h */ + +/* + X11 License: + + Copyright (c) 2010 Miguel A. Ballicora + + 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. +*/ + +#if !defined(H_WRAP) +#define H_WRAP + +/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ +#include + +extern int zlib_encode (const unsigned char *in_start, size_t in_len, unsigned char *out_start, size_t *pout_len, size_t out_max); +extern int zlib_decode (const unsigned char *in_start, size_t in_len, unsigned char *out_start, size_t *pout_len, size_t out_max); + +extern int lzf_encode (const unsigned char *in_start, size_t in_len, unsigned char *out_start, size_t *pout_len, size_t out_max); +extern int lzf_decode (const unsigned char *in_start, size_t in_len, unsigned char *out_start, size_t *pout_len, size_t out_max); + +extern int lzma_encode (const unsigned char *in_start, size_t in_len, unsigned char *out_start, size_t *pout_len, size_t out_max); +extern int lzma_decode (const unsigned char *in_start, size_t in_len, unsigned char *out_start, size_t *pout_len, size_t out_max); + +#if defined (LIBBZIP2) +extern int bzip2_encode(const unsigned char *in_start, size_t in_len, unsigned char *out_start, size_t *pout_len, size_t out_max); +extern int bzip2_decode(const unsigned char *in_start, size_t in_len, unsigned char *out_start, size_t *pout_len, size_t out_max); +#endif + +extern int rle_encode (const unsigned char *in_start, size_t in_len, unsigned char *out_start, size_t *pout_len, size_t out_max); +extern int rle_decode (const unsigned char *in_start, size_t in_len, unsigned char *out_start, size_t *pout_len, size_t out_max); + +extern int justcopy_encode (const unsigned char *in_start, size_t in_len, unsigned char *out_start, size_t *pout_len, size_t out_max); +extern int justcopy_decode (const unsigned char *in_start, size_t in_len, unsigned char *out_start, size_t *pout_len, size_t out_max); + + +/*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ +#endif diff --git a/DroidFish/jni/gtb/compression/zlib/adler32.c b/DroidFish/jni/gtb/compression/zlib/adler32.c new file mode 100644 index 0000000..e449c32 --- /dev/null +++ b/DroidFish/jni/gtb/compression/zlib/adler32.c @@ -0,0 +1,143 @@ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2004 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +#define BASE 65521UL /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +/* use NO_DIVIDE if your processor does not do division in hardware */ +#ifdef NO_DIVIDE +# define MOD(a) \ + do { \ + if (a >= (BASE << 16)) a -= (BASE << 16); \ + if (a >= (BASE << 15)) a -= (BASE << 15); \ + if (a >= (BASE << 14)) a -= (BASE << 14); \ + if (a >= (BASE << 13)) a -= (BASE << 13); \ + if (a >= (BASE << 12)) a -= (BASE << 12); \ + if (a >= (BASE << 11)) a -= (BASE << 11); \ + if (a >= (BASE << 10)) a -= (BASE << 10); \ + if (a >= (BASE << 9)) a -= (BASE << 9); \ + if (a >= (BASE << 8)) a -= (BASE << 8); \ + if (a >= (BASE << 7)) a -= (BASE << 7); \ + if (a >= (BASE << 6)) a -= (BASE << 6); \ + if (a >= (BASE << 5)) a -= (BASE << 5); \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) +# define MOD4(a) \ + do { \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) +#else +# define MOD(a) a %= BASE +# define MOD4(a) a %= BASE +#endif + +/* ========================================================================= */ +uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len) +{ + unsigned long sum2; + unsigned n; + + /* split Adler-32 into component sums */ + sum2 = (adler >> 16) & 0xffff; + adler &= 0xffff; + + /* in case user likes doing a byte at a time, keep it fast */ + if (len == 1) { + adler += buf[0]; + if (adler >= BASE) + adler -= BASE; + sum2 += adler; + if (sum2 >= BASE) + sum2 -= BASE; + return adler | (sum2 << 16); + } + + /* initial Adler-32 value (deferred check for len == 1 speed) */ + if (buf == Z_NULL) + return 1L; + + /* in case short lengths are provided, keep it somewhat fast */ + if (len < 16) { + while (len--) { + adler += *buf++; + sum2 += adler; + } + if (adler >= BASE) + adler -= BASE; + MOD4(sum2); /* only added so many BASE's */ + return adler | (sum2 << 16); + } + + /* do length NMAX blocks -- requires just one modulo operation */ + while (len >= NMAX) { + len -= NMAX; + n = NMAX / 16; /* NMAX is divisible by 16 */ + do { + DO16(buf); /* 16 sums unrolled */ + buf += 16; + } while (--n); + MOD(adler); + MOD(sum2); + } + + /* do remaining bytes (less than NMAX, still just one modulo) */ + if (len) { /* avoid modulos if none remaining */ + while (len >= 16) { + len -= 16; + DO16(buf); + buf += 16; + } + while (len--) { + adler += *buf++; + sum2 += adler; + } + MOD(adler); + MOD(sum2); + } + + /* return recombined sums */ + return adler | (sum2 << 16); +} + +/* ========================================================================= */ +uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2, long int len2) +{ + unsigned long sum1; + unsigned long sum2; + unsigned rem; + + /* the derivation of this formula is left as an exercise for the reader */ + rem = (unsigned)((long unsigned)len2 % BASE); /*MAB long unsigned casts */ + sum1 = adler1 & 0xffff; + sum2 = rem * sum1; + MOD(sum2); + sum1 += (adler2 & 0xffff) + BASE - 1; + sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; + if (sum1 > BASE) sum1 -= BASE; + if (sum1 > BASE) sum1 -= BASE; + if (sum2 > (BASE << 1)) sum2 -= (BASE << 1); + if (sum2 > BASE) sum2 -= BASE; + return sum1 | (sum2 << 16); +} diff --git a/DroidFish/jni/gtb/compression/zlib/crc32.c b/DroidFish/jni/gtb/compression/zlib/crc32.c new file mode 100644 index 0000000..6fba35f --- /dev/null +++ b/DroidFish/jni/gtb/compression/zlib/crc32.c @@ -0,0 +1,439 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Thanks to Rodney Brown for his contribution of faster + * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing + * tables for updating the shift register in one step with three exclusive-ors + * instead of four steps with four exclusive-ors. This results in about a + * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. + */ + +/* @(#) $Id$ */ + +/* + Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore + protection on the static variables used to control the first-use generation + of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should + first call get_crc_table() to initialize the tables before allowing more than + one thread to use crc32(). + */ + +#ifdef MAKECRCH +# include +# ifndef DYNAMIC_CRC_TABLE +# define DYNAMIC_CRC_TABLE +# endif /* !DYNAMIC_CRC_TABLE */ +#endif /* MAKECRCH */ + +#include "zutil.h" /* for STDC and FAR definitions */ + +#define local static + +/* Find a four-byte integer type for crc32_little() and crc32_big(). */ +#ifndef NOBYFOUR +# ifdef STDC /* need ANSI C limits.h to determine sizes */ +# include +# define BYFOUR +# if (UINT_MAX == 0xffffffffUL) + typedef unsigned int u4; +# else +# if (ULONG_MAX == 0xffffffffUL) + typedef unsigned long u4; +# else +# if (USHRT_MAX == 0xffffffffUL) + typedef unsigned short u4; +# else +# undef BYFOUR /* can't find a four-byte integer type! */ +# endif +# endif +# endif +# endif /* STDC */ +#endif /* !NOBYFOUR */ + +/* Definitions for doing the crc four data bytes at a time. */ +#ifdef BYFOUR +# define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \ + (((w)&0xff00)<<8)+(((w)&0xff)<<24)) + local unsigned long crc32_little OF((unsigned long, + const unsigned char FAR *, unsigned)); + local unsigned long crc32_big OF((unsigned long, + const unsigned char FAR *, unsigned)); +# define TBLS 8 +#else +# define TBLS 1 +#endif /* BYFOUR */ + +/* Local functions for crc concatenation */ +local unsigned long gf2_matrix_times OF((unsigned long *mat, + unsigned long vec)); +local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); + +#ifdef DYNAMIC_CRC_TABLE + +local volatile int crc_table_empty = 1; +local unsigned long FAR crc_table[TBLS][256]; +local void make_crc_table OF((void)); +#ifdef MAKECRCH + local void write_table OF((FILE *, const unsigned long FAR *)); +#endif /* MAKECRCH */ +/* + Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The first table is simply the CRC of all possible eight bit values. This is + all the information needed to generate CRCs on data a byte at a time for all + combinations of CRC register values and incoming bytes. The remaining tables + allow for word-at-a-time CRC calculation for both big-endian and little- + endian machines, where a word is four bytes. +*/ +local void make_crc_table() +{ + unsigned long c; + int n, k; + unsigned long poly; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static volatile int first = 1; /* flag to limit concurrent making */ + static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* See if another task is already doing this (not thread-safe, but better + than nothing -- significantly reduces duration of vulnerability in + case the advice about DYNAMIC_CRC_TABLE is ignored) */ + if (first) { + first = 0; + + /* make exclusive-or pattern from polynomial (0xedb88320UL) */ + poly = 0UL; + for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++) + poly |= 1UL << (31 - p[n]); + + /* generate a crc for every 8-bit value */ + for (n = 0; n < 256; n++) { + c = (unsigned long)n; + for (k = 0; k < 8; k++) + c = c & 1 ? poly ^ (c >> 1) : c >> 1; + crc_table[0][n] = c; + } + +#ifdef BYFOUR + /* generate crc for each value followed by one, two, and three zeros, + and then the byte reversal of those as well as the first table */ + for (n = 0; n < 256; n++) { + c = crc_table[0][n]; + crc_table[4][n] = REV(c); + for (k = 1; k < 4; k++) { + c = crc_table[0][c & 0xff] ^ (c >> 8); + crc_table[k][n] = c; + crc_table[k + 4][n] = REV(c); + } + } +#endif /* BYFOUR */ + + crc_table_empty = 0; + } + else { /* not first */ + /* wait for the other guy to finish (not efficient, but rare) */ + while (crc_table_empty) + ; + } + +#ifdef MAKECRCH + /* write out CRC tables to crc32.h */ + { + FILE *out; + + out = fopen("crc32.h", "w"); + if (out == NULL) return; + fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); + fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); + fprintf(out, "local const unsigned long FAR "); + fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); + write_table(out, crc_table[0]); +# ifdef BYFOUR + fprintf(out, "#ifdef BYFOUR\n"); + for (k = 1; k < 8; k++) { + fprintf(out, " },\n {\n"); + write_table(out, crc_table[k]); + } + fprintf(out, "#endif\n"); +# endif /* BYFOUR */ + fprintf(out, " }\n};\n"); + fclose(out); + } +#endif /* MAKECRCH */ +} + +#ifdef MAKECRCH +local void write_table(out, table) + FILE *out; + const unsigned long FAR *table; +{ + int n; + + for (n = 0; n < 256; n++) + fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n], + n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); +} +#endif /* MAKECRCH */ + +#else /* !DYNAMIC_CRC_TABLE */ +/* ======================================================================== + * Tables of CRC-32s of all single-byte values, made by make_crc_table(). + */ +#include "crc32.h" +#endif /* DYNAMIC_CRC_TABLE */ + +/* ========================================================================= + * This function can be used by asm versions of crc32() + */ +const unsigned long FAR * ZEXPORT get_crc_table(void) +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + return (const unsigned long FAR *)crc_table; +} + +/* ========================================================================= */ +#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) +#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 + +/* ========================================================================= */ +unsigned long ZEXPORT crc32(long unsigned int crc, const unsigned char *buf, unsigned int len) +{ + if (buf == Z_NULL) return 0UL; + +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + +#ifdef BYFOUR + + +#ifdef _MSC_VER +#pragma warning(disable:4127) +#endif + + if (sizeof(void *) == sizeof(ptrdiff_t)) { + +#ifdef _MSC_VER +#pragma warning(default:4127) +#endif + u4 endian; + + endian = 1; + if (*((unsigned char *)(&endian))) + return crc32_little(crc, buf, len); + else + return crc32_big(crc, buf, len); + + } + + /*MAB: begin*/ + else { + + crc = crc ^ 0xffffffffUL; + while (len >= 8) { + DO8; + len -= 8; + } + if (len) do { + DO1; + } while (--len); + return crc ^ 0xffffffffUL; + + } + /*MAB: end addition */ + +#else /*MAB: Changed from endif */ + + crc = crc ^ 0xffffffffUL; + while (len >= 8) { + DO8; + len -= 8; + } + if (len) do { + DO1; + } while (--len); + return crc ^ 0xffffffffUL; + +#endif /*MAB*/ + +} + +#ifdef BYFOUR + +/* ========================================================================= */ +#define DOLIT4 c ^= *buf4++; \ + c = (u4)(crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24]) /*MAB casts */ + +#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 + +/* ========================================================================= */ +local unsigned long crc32_little(long unsigned int crc, const unsigned char *buf, unsigned int len) +{ + register u4 c; + register const u4 FAR *buf4; + + c = (u4)crc; + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = (u4) (crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8)); /*MAB casts */ + len--; + } + + buf4 = (const u4 FAR *)(const void FAR *)buf; + while (len >= 32) { + DOLIT32; + len -= 32; + } + while (len >= 4) { + DOLIT4; + len -= 4; + } + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = (u4)(crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8)); /*MAB casts */ + } while (--len); + c = ~c; + return (unsigned long)c; +} + +/* ========================================================================= */ +#define DOBIG4 c ^= *++buf4; \ + c = (u4) (crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]) /*MAB casts */ + +#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 + +/* ========================================================================= */ +local unsigned long crc32_big(long unsigned int crc, const unsigned char *buf, unsigned int len) +{ + register u4 c; + register const u4 FAR *buf4; + + c = REV((u4)crc); + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = (u4) (crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8)); /*MAB casts */ + len--; + } + + buf4 = (const u4 FAR *)(const void FAR *)buf; + buf4--; + while (len >= 32) { + DOBIG32; + len -= 32; + } + while (len >= 4) { + DOBIG4; + len -= 4; + } + buf4++; + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = (u4) (crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8)); + } while (--len); + c = ~c; + return (unsigned long)(REV(c)); +} + +#endif /* BYFOUR */ + +#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ + +/* ========================================================================= */ +local unsigned long gf2_matrix_times(long unsigned int *mat, long unsigned int vec) +{ + unsigned long sum; + + sum = 0; + while (vec) { + if (vec & 1) + sum ^= *mat; + vec >>= 1; + mat++; + } + return sum; +} + +/* ========================================================================= */ +local void gf2_matrix_square(long unsigned int *square, long unsigned int *mat) +{ + int n; + + for (n = 0; n < GF2_DIM; n++) + square[n] = gf2_matrix_times(mat, mat[n]); +} + +/* ========================================================================= */ +uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, long int len2) +{ + int n; + unsigned long row; + unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ + unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ + + /* degenerate case */ + if (len2 == 0) + return crc1; + + /* put operator for one zero bit in odd */ + odd[0] = 0xedb88320L; /* CRC-32 polynomial */ + row = 1; + for (n = 1; n < GF2_DIM; n++) { + odd[n] = row; + row <<= 1; + } + + /* put operator for two zero bits in even */ + gf2_matrix_square(even, odd); + + /* put operator for four zero bits in odd */ + gf2_matrix_square(odd, even); + + /* apply len2 zeros to crc1 (first square will put the operator for one + zero byte, eight zero bits, in even) */ + do { + /* apply zeros operator for this bit of len2 */ + gf2_matrix_square(even, odd); + if (len2 & 1) + crc1 = gf2_matrix_times(even, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + if (len2 == 0) + break; + + /* another iteration of the loop with odd and even swapped */ + gf2_matrix_square(odd, even); + if (len2 & 1) + crc1 = gf2_matrix_times(odd, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + } while (len2 != 0); + + /* return combined crc */ + crc1 ^= crc2; + return crc1; +} diff --git a/DroidFish/jni/gtb/compression/zlib/crc32.h b/DroidFish/jni/gtb/compression/zlib/crc32.h new file mode 100644 index 0000000..8053b61 --- /dev/null +++ b/DroidFish/jni/gtb/compression/zlib/crc32.h @@ -0,0 +1,441 @@ +/* crc32.h -- tables for rapid CRC calculation + * Generated automatically by crc32.c + */ + +local const unsigned long FAR crc_table[TBLS][256] = +{ + { + 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, + 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, + 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, + 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, + 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, + 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, + 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, + 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, + 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, + 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, + 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, + 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, + 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, + 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, + 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, + 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, + 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, + 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, + 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, + 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, + 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, + 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, + 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, + 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, + 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, + 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, + 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, + 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, + 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, + 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, + 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, + 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, + 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, + 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, + 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, + 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, + 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, + 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, + 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, + 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, + 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, + 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, + 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, + 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, + 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, + 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, + 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, + 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, + 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, + 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, + 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, + 0x2d02ef8dUL +#ifdef BYFOUR + }, + { + 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, + 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, + 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, + 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, + 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, + 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, + 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, + 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, + 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, + 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, + 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, + 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, + 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, + 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, + 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, + 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, + 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, + 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, + 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, + 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, + 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, + 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, + 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, + 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, + 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, + 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, + 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, + 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, + 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, + 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, + 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, + 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, + 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, + 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, + 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, + 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, + 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, + 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, + 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, + 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, + 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, + 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, + 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, + 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, + 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, + 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, + 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, + 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, + 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, + 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, + 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, + 0x9324fd72UL + }, + { + 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, + 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, + 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, + 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, + 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, + 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, + 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, + 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, + 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, + 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, + 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, + 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, + 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, + 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, + 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, + 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, + 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, + 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, + 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, + 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, + 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, + 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, + 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, + 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, + 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, + 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, + 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, + 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, + 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, + 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, + 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, + 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, + 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, + 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, + 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, + 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, + 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, + 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, + 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, + 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, + 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, + 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, + 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, + 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, + 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, + 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, + 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, + 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, + 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, + 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, + 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, + 0xbe9834edUL + }, + { + 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, + 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, + 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, + 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, + 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, + 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, + 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, + 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, + 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, + 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, + 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, + 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, + 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, + 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, + 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, + 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, + 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, + 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, + 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, + 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, + 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, + 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, + 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, + 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, + 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, + 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, + 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, + 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, + 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, + 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, + 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, + 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, + 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, + 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, + 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, + 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, + 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, + 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, + 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, + 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, + 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, + 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, + 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, + 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, + 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, + 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, + 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, + 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, + 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, + 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, + 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, + 0xde0506f1UL + }, + { + 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, + 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, + 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, + 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, + 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, + 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, + 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, + 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, + 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, + 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, + 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, + 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, + 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, + 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, + 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, + 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, + 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, + 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, + 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, + 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, + 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, + 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, + 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, + 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, + 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, + 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, + 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, + 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, + 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, + 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, + 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, + 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, + 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, + 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, + 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, + 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, + 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, + 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, + 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, + 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, + 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, + 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, + 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, + 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, + 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, + 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, + 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, + 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, + 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, + 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, + 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, + 0x8def022dUL + }, + { + 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, + 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, + 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, + 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, + 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, + 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, + 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, + 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, + 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, + 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, + 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, + 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, + 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, + 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, + 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, + 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, + 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, + 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, + 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, + 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, + 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, + 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, + 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, + 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, + 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, + 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, + 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, + 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, + 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, + 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, + 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, + 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, + 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, + 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, + 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, + 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, + 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, + 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, + 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, + 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, + 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, + 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, + 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, + 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, + 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, + 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, + 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, + 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, + 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, + 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, + 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, + 0x72fd2493UL + }, + { + 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, + 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, + 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, + 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, + 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, + 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, + 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, + 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, + 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, + 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, + 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, + 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, + 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, + 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, + 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, + 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, + 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, + 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, + 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, + 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, + 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, + 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, + 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, + 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, + 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, + 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, + 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, + 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, + 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, + 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, + 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, + 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, + 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, + 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, + 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, + 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, + 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, + 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, + 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, + 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, + 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, + 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, + 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, + 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, + 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, + 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, + 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, + 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, + 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, + 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, + 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, + 0xed3498beUL + }, + { + 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, + 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, + 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, + 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, + 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, + 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, + 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, + 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, + 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, + 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, + 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, + 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, + 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, + 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, + 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, + 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, + 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, + 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, + 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, + 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, + 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, + 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, + 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, + 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, + 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, + 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, + 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, + 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, + 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, + 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, + 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, + 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, + 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, + 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, + 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, + 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, + 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, + 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, + 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, + 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, + 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, + 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, + 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, + 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, + 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, + 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, + 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, + 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, + 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, + 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, + 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, + 0xf10605deUL +#endif + } +}; diff --git a/DroidFish/jni/gtb/compression/zlib/deflate.c b/DroidFish/jni/gtb/compression/zlib/deflate.c new file mode 100644 index 0000000..3e81cc0 --- /dev/null +++ b/DroidFish/jni/gtb/compression/zlib/deflate.c @@ -0,0 +1,1725 @@ +/* deflate.c -- compress data using the deflation algorithm + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process depends on being able to identify portions + * of the input text which are identical to earlier input (within a + * sliding window trailing behind the input currently being processed). + * + * The most straightforward technique turns out to be the fastest for + * most input files: try all possible matches and select the longest. + * The key feature of this algorithm is that insertions into the string + * dictionary are very simple and thus fast, and deletions are avoided + * completely. Insertions are performed at each input character, whereas + * string matches are performed only when the previous match ends. So it + * is preferable to spend more time in matches to allow very fast string + * insertions and avoid deletions. The matching algorithm for small + * strings is inspired from that of Rabin & Karp. A brute force approach + * is used to find longer strings when a small match has been found. + * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze + * (by Leonid Broukhis). + * A previous version of this file used a more sophisticated algorithm + * (by Fiala and Greene) which is guaranteed to run in linear amortized + * time, but has a larger average cost, uses more memory and is patented. + * However the F&G algorithm may be faster for some highly redundant + * files if the parameter max_chain_length (described below) is too large. + * + * ACKNOWLEDGEMENTS + * + * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and + * I found it in 'freeze' written by Leonid Broukhis. + * Thanks to many people for bug reports and testing. + * + * REFERENCES + * + * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". + * Available in http://www.ietf.org/rfc/rfc1951.txt + * + * A description of the Rabin and Karp algorithm is given in the book + * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. + * + * Fiala,E.R., and Greene,D.H. + * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 + * + */ + +/* @(#) $Id$ */ + +#include "deflate.h" + +const char deflate_copyright[] = + " deflate 1.2.3 Copyright 1995-2005 Jean-loup Gailly "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* =========================================================================== + * Function prototypes. + */ +typedef enum block_state { + need_more, /* block not completed, need more input or more output */ + block_done, /* block flush performed */ + finish_started, /* finish started, need only more output at next deflate */ + finish_done /* finish done, accept no more input or output */ +} block_state; + +typedef block_state (*compress_func) OF((deflate_state *s, int flush)); +/* Compression function. Returns the block state after the call. */ + +local void fill_window OF((deflate_state *s)); +local block_state deflate_stored OF((deflate_state *s, int flush)); +local block_state deflate_fast OF((deflate_state *s, int flush)); +#ifndef FASTEST +local block_state deflate_slow OF((deflate_state *s, int flush)); +#endif +local void lm_init OF((deflate_state *s)); +local void putShortMSB OF((deflate_state *s, uInt b)); +local void flush_pending OF((z_streamp strm)); +local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); +#ifndef FASTEST +#ifdef ASMV + void match_init OF((void)); /* asm code initialization */ + uInt longest_match OF((deflate_state *s, IPos cur_match)); +#else +local uInt longest_match OF((deflate_state *s, IPos cur_match)); +#endif +#endif +local uInt longest_match_fast OF((deflate_state *s, IPos cur_match)); + +#ifdef DEBUG +local void check_match OF((deflate_state *s, IPos start, IPos match, + int length)); +#endif + +/* =========================================================================== + * Local data + */ + +#define NIL 0 +/* Tail of hash chains */ + +#ifndef TOO_FAR +# define TOO_FAR 4096 +#endif +/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +typedef struct config_s { + ush good_length; /* reduce lazy search above this match length */ + ush max_lazy; /* do not perform lazy search above this match length */ + ush nice_length; /* quit search above this match length */ + ush max_chain; + compress_func func; +} config; + +#ifdef FASTEST +local const config configuration_table[2] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ +#else +local const config configuration_table[10] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ +/* 2 */ {4, 5, 16, 8, deflate_fast}, +/* 3 */ {4, 6, 32, 32, deflate_fast}, + +/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ +/* 5 */ {8, 16, 32, 32, deflate_slow}, +/* 6 */ {8, 16, 128, 128, deflate_slow}, +/* 7 */ {8, 32, 128, 256, deflate_slow}, +/* 8 */ {32, 128, 258, 1024, deflate_slow}, +/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ +#endif + +/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 + * For deflate_fast() (levels <= 3) good is ignored and lazy has a different + * meaning. + */ + +#define EQUAL 0 +/* result of memcmp for equal strings */ + +#ifndef NO_DUMMY_DECL +struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ +#endif + +/* =========================================================================== + * Update a hash value with the given input byte + * IN assertion: all calls to to UPDATE_HASH are made with consecutive + * input characters, so that a running hash key can be computed from the + * previous key instead of complete recalculation each time. + */ +#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) + + +/* =========================================================================== + * Insert string str in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + * If this file is compiled with -DFASTEST, the compression level is forced + * to 1, and no hash chains are maintained. + * IN assertion: all calls to to INSERT_STRING are made with consecutive + * input characters and the first MIN_MATCH bytes of str are valid + * (except for the last MIN_MATCH-1 bytes of the input file). + */ +#ifdef FASTEST +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#else +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#endif + +/* =========================================================================== + * Initialize the hash table (avoiding 64K overflow for 16 bit systems). + * prev[] will be initialized on the fly. + */ +#define CLEAR_HASH(s) \ + s->head[s->hash_size-1] = NIL; \ + zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); + +/* ========================================================================= */ +int ZEXPORT deflateInit_(z_streamp strm, int level, const char *version, int stream_size) +{ + return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, version, stream_size); + /* To do: ignore strm->next_in if we use it as window */ +} + +/* ========================================================================= */ +int ZEXPORT deflateInit2_(z_streamp strm, int level, int method, int windowBits, int memLevel, int strategy, const char *version, int stream_size) +{ + deflate_state *s; + int wrap = 1; + static const char my_version[] = ZLIB_VERSION; + + ushf *overlay; + /* We overlay pending_buf and d_buf+l_buf. This works since the average + * output size for (length,distance) codes is <= 24 bits. + */ + + if (version == Z_NULL || version[0] != my_version[0] || + stream_size != sizeof(z_stream)) { + return Z_VERSION_ERROR; + } + if (strm == Z_NULL) return Z_STREAM_ERROR; + + strm->msg = Z_NULL; + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + + if (windowBits < 0) { /* suppress zlib wrapper */ + wrap = 0; + windowBits = -windowBits; + } +#ifdef GZIP + else if (windowBits > 15) { + wrap = 2; /* write gzip wrapper instead */ + windowBits -= 16; + } +#endif + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || + windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_FIXED) { + return Z_STREAM_ERROR; + } + if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ + s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); + if (s == Z_NULL) return Z_MEM_ERROR; + strm->state = (struct internal_state FAR *)s; + s->strm = strm; + + s->wrap = wrap; + s->gzhead = Z_NULL; + s->w_bits = (z_uInt) windowBits; /*MAB casts */ + s->w_size = (z_uInt) (1 << s->w_bits); /*MAB casts */ + s->w_mask = s->w_size - 1; + + s->hash_bits = (z_uInt) (memLevel + 7); /*MAB casts */ + s->hash_size = (z_uInt) (1 << s->hash_bits); /*MAB casts */ + s->hash_mask = s->hash_size - 1; + s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + + s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); + s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); + s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); + + s->lit_bufsize = (z_uInt)(1 << (memLevel + 6)); /* 16K elements by default */ /*MAB casts */ + + overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + s->pending_buf = (uchf *) overlay; + s->pending_buf_size = (ulg)s->lit_bufsize * (ulg)(sizeof(ush)+2L); /*MAB casts (ulg)(sizeof... */ + + if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || + s->pending_buf == Z_NULL) { + s->status = FINISH_STATE; + strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); + deflateEnd (strm); + return Z_MEM_ERROR; + } + s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + + s->level = level; + s->strategy = strategy; + s->method = (Byte)method; + + return deflateReset(strm); +} + +/* ========================================================================= */ +int ZEXPORT deflateSetDictionary (z_streamp strm, const Bytef *dictionary, uInt dictLength) +{ + deflate_state *s; + uInt length = dictLength; + uInt n; + IPos hash_head = 0; + + if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || + strm->state->wrap == 2 || + (strm->state->wrap == 1 && strm->state->status != INIT_STATE)) + return Z_STREAM_ERROR; + + s = strm->state; + if (s->wrap) + strm->adler = adler32(strm->adler, dictionary, dictLength); + + if (length < MIN_MATCH) return Z_OK; + if (length > MAX_DIST(s)) { + length = MAX_DIST(s); + dictionary += dictLength - length; /* use the tail of the dictionary */ + } + zmemcpy(s->window, dictionary, length); + s->strstart = length; + s->block_start = (long)length; + + /* Insert all strings in the hash table (except for the last two bytes). + * s->lookahead stays null, so s->ins_h will be recomputed at the next + * call of fill_window. + */ + s->ins_h = s->window[0]; + UPDATE_HASH(s, s->ins_h, s->window[1]); + for (n = 0; n <= length - MIN_MATCH; n++) { + INSERT_STRING(s, n, hash_head); + } + if (hash_head) hash_head = 0; /* to make compiler happy */ + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateReset (z_streamp strm) +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { + return Z_STREAM_ERROR; + } + + strm->total_in = strm->total_out = 0; + strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ + strm->data_type = Z_UNKNOWN; + + s = (deflate_state *)strm->state; + s->pending = 0; + s->pending_out = s->pending_buf; + + if (s->wrap < 0) { + s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ + } + s->status = s->wrap ? INIT_STATE : BUSY_STATE; + strm->adler = +#ifdef GZIP + s->wrap == 2 ? crc32(0L, Z_NULL, 0) : +#endif + adler32(0L, Z_NULL, 0); + s->last_flush = Z_NO_FLUSH; + + _tr_init(s); + lm_init(s); + + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateSetHeader (z_streamp strm, gz_headerp head) +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (strm->state->wrap != 2) return Z_STREAM_ERROR; + strm->state->gzhead = head; + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflatePrime (z_streamp strm, int bits, int value) +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + strm->state->bi_valid = bits; + strm->state->bi_buf = (ush)(value & ((1 << bits) - 1)); + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateParams(z_streamp strm, int level, int strategy) +{ + deflate_state *s; + compress_func func; + int err = Z_OK; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { + return Z_STREAM_ERROR; + } + func = configuration_table[s->level].func; + + if (func != configuration_table[level].func && strm->total_in != 0) { + /* Flush the last buffer: */ + err = deflate(strm, Z_PARTIAL_FLUSH); + } + if (s->level != level) { + s->level = level; + s->max_lazy_match = configuration_table[level].max_lazy; + s->good_match = configuration_table[level].good_length; + s->nice_match = configuration_table[level].nice_length; + s->max_chain_length = configuration_table[level].max_chain; + } + s->strategy = strategy; + return err; +} + +/* ========================================================================= */ +int ZEXPORT deflateTune(z_streamp strm, int good_length, int max_lazy, int nice_length, int max_chain) +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + s->good_match = (z_uInt) good_length; /*MAB casts */ + s->max_lazy_match = (z_uInt) max_lazy; /*MAB casts */ + s->nice_match = nice_length; + s->max_chain_length = (z_uInt) max_chain; /*MAB casts */ + return Z_OK; +} + +/* ========================================================================= + * For the default windowBits of 15 and memLevel of 8, this function returns + * a close to exact, as well as small, upper bound on the compressed size. + * They are coded as constants here for a reason--if the #define's are + * changed, then this function needs to be changed as well. The return + * value for 15 and 8 only works for those exact settings. + * + * For any setting other than those defaults for windowBits and memLevel, + * the value returned is a conservative worst case for the maximum expansion + * resulting from using fixed blocks instead of stored blocks, which deflate + * can emit on compressed data for some combinations of the parameters. + * + * This function could be more sophisticated to provide closer upper bounds + * for every combination of windowBits and memLevel, as well as wrap. + * But even the conservative upper bound of about 14% expansion does not + * seem onerous for output buffer allocation. + */ +uLong ZEXPORT deflateBound(z_streamp strm, uLong sourceLen) +{ + deflate_state *s; + uLong destLen; + + /* conservative upper bound */ + destLen = sourceLen + + ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 11; + + /* if can't get parameters, return conservative bound */ + if (strm == Z_NULL || strm->state == Z_NULL) + return destLen; + + /* if not default parameters, return conservative bound */ + s = strm->state; + if (s->w_bits != 15 || s->hash_bits != 8 + 7) + return destLen; + + /* default settings: return tight bound for that case */ + return compressBound(sourceLen); +} + +/* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ +local void putShortMSB (deflate_state *s, uInt b) +{ + put_byte(s, (Byte)(b >> 8)); + put_byte(s, (Byte)(b & 0xff)); +} + +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output goes + * through this function so some applications may wish to modify it + * to avoid allocating a large strm->next_out buffer and copying into it. + * (See also read_buf()). + */ +local void flush_pending(z_streamp strm) +{ + unsigned len = strm->state->pending; + + if (len > strm->avail_out) len = strm->avail_out; + if (len == 0) return; + + zmemcpy(strm->next_out, strm->state->pending_out, len); + strm->next_out += len; + strm->state->pending_out += len; + strm->total_out += len; + strm->avail_out -= len; + strm->state->pending -= len; + if (strm->state->pending == 0) { + strm->state->pending_out = strm->state->pending_buf; + } +} + +/* ========================================================================= */ +int ZEXPORT deflate (z_streamp strm, int flush) +{ + int old_flush; /* value of flush param for previous deflate call */ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + flush > Z_FINISH || flush < 0) { + return Z_STREAM_ERROR; + } + s = strm->state; + + if (strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0) || + (s->status == FINISH_STATE && flush != Z_FINISH)) { + ERR_RETURN(strm, Z_STREAM_ERROR); + } + if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); + + s->strm = strm; /* just in case */ + old_flush = s->last_flush; + s->last_flush = flush; + + /* Write the header */ + if (s->status == INIT_STATE) { +#ifdef GZIP + if (s->wrap == 2) { + strm->adler = crc32(0L, Z_NULL, 0); + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + if (s->gzhead == NULL) { + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, OS_CODE); + s->status = BUSY_STATE; + } + else { + put_byte(s, (s->gzhead->text ? 1 : 0) + + (s->gzhead->hcrc ? 2 : 0) + + (s->gzhead->extra == Z_NULL ? 0 : 4) + + (s->gzhead->name == Z_NULL ? 0 : 8) + + (s->gzhead->comment == Z_NULL ? 0 : 16) + ); + put_byte(s, (Byte)(s->gzhead->time & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, s->gzhead->os & 0xff); + if (s->gzhead->extra != NULL) { + put_byte(s, s->gzhead->extra_len & 0xff); + put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); + } + if (s->gzhead->hcrc) + strm->adler = crc32(strm->adler, s->pending_buf, + s->pending); + s->gzindex = 0; + s->status = EXTRA_STATE; + } + } + else +#endif + { + uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt level_flags; + + if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) + level_flags = 0; + else if (s->level < 6) + level_flags = 1; + else if (s->level == 6) + level_flags = 2; + else + level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) header |= PRESET_DICT; + header += 31 - (header % 31); + + s->status = BUSY_STATE; + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s->strstart != 0) { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + strm->adler = adler32(0L, Z_NULL, 0); + } + } +#ifdef GZIP + if (s->status == EXTRA_STATE) { + if (s->gzhead->extra != NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + + while (s->gzindex < (s->gzhead->extra_len & 0xffff)) { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) + break; + } + put_byte(s, s->gzhead->extra[s->gzindex]); + s->gzindex++; + } + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (s->gzindex == s->gzhead->extra_len) { + s->gzindex = 0; + s->status = NAME_STATE; + } + } + else + s->status = NAME_STATE; + } + if (s->status == NAME_STATE) { + if (s->gzhead->name != NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + int val; + + do { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) { + val = 1; + break; + } + } + val = s->gzhead->name[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (val == 0) { + s->gzindex = 0; + s->status = COMMENT_STATE; + } + } + else + s->status = COMMENT_STATE; + } + if (s->status == COMMENT_STATE) { + if (s->gzhead->comment != NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + int val; + + do { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) { + val = 1; + break; + } + } + val = s->gzhead->comment[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (val == 0) + s->status = HCRC_STATE; + } + else + s->status = HCRC_STATE; + } + if (s->status == HCRC_STATE) { + if (s->gzhead->hcrc) { + if (s->pending + 2 > s->pending_buf_size) + flush_pending(strm); + if (s->pending + 2 <= s->pending_buf_size) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + strm->adler = crc32(0L, Z_NULL, 0); + s->status = BUSY_STATE; + } + } + else + s->status = BUSY_STATE; + } +#endif + + /* Flush as much pending output as possible */ + if (s->pending != 0) { + flush_pending(strm); + if (strm->avail_out == 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s->last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUF_ERROR. + */ + } else if (strm->avail_in == 0 && flush <= old_flush && + flush != Z_FINISH) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s->status == FINISH_STATE && strm->avail_in != 0) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* Start a new block or continue the current one. + */ + if (strm->avail_in != 0 || s->lookahead != 0 || + (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { + block_state bstate; + + bstate = (*(configuration_table[s->level].func))(s, flush); + + if (bstate == finish_started || bstate == finish_done) { + s->status = FINISH_STATE; + } + if (bstate == need_more || bstate == finish_started) { + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate == block_done) { + if (flush == Z_PARTIAL_FLUSH) { + _tr_align(s); + } else { /* FULL_FLUSH or SYNC_FLUSH */ + _tr_stored_block(s, (char*)0, 0L, 0); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush == Z_FULL_FLUSH) { + CLEAR_HASH(s); /* forget history */ + } + } + flush_pending(strm); + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + Assert(strm->avail_out > 0, "bug2"); + + if (flush != Z_FINISH) return Z_OK; + if (s->wrap <= 0) return Z_STREAM_END; + + /* Write the trailer */ +#ifdef GZIP + if (s->wrap == 2) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); + put_byte(s, (Byte)(strm->total_in & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); + } + else +#endif + { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ + return s->pending != 0 ? Z_OK : Z_STREAM_END; +} + +/* ========================================================================= */ +int ZEXPORT deflateEnd (z_streamp strm) +{ + int status; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + + status = strm->state->status; + if (status != INIT_STATE && + status != EXTRA_STATE && + status != NAME_STATE && + status != COMMENT_STATE && + status != HCRC_STATE && + status != BUSY_STATE && + status != FINISH_STATE) { + return Z_STREAM_ERROR; + } + + /* Deallocate in reverse order of allocations: */ + TRY_FREE(strm, strm->state->pending_buf); + TRY_FREE(strm, strm->state->head); + TRY_FREE(strm, strm->state->prev); + TRY_FREE(strm, strm->state->window); + + ZFREE(strm, strm->state); + strm->state = Z_NULL; + + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; +} + +/* ========================================================================= + * Copy the source state to the destination state. + * To simplify the source, this is not supported for 16-bit MSDOS (which + * doesn't have enough memory anyway to duplicate compression states). + */ +int ZEXPORT deflateCopy (z_streamp dest, z_streamp source) +{ +#ifdef MAXSEG_64K + return Z_STREAM_ERROR; +#else + deflate_state *ds; + deflate_state *ss; + ushf *overlay; + + + if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { + return Z_STREAM_ERROR; + } + + ss = source->state; + + zmemcpy(dest, source, sizeof(z_stream)); + + ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); + if (ds == Z_NULL) return Z_MEM_ERROR; + dest->state = (struct internal_state FAR *) ds; + zmemcpy(ds, ss, sizeof(deflate_state)); + ds->strm = dest; + + ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); + ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); + ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); + overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); + ds->pending_buf = (uchf *) overlay; + + if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || + ds->pending_buf == Z_NULL) { + deflateEnd (dest); + return Z_MEM_ERROR; + } + /* following zmemcpy do not work for 16-bit MSDOS */ + zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); + zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); + zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); + zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); + + ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); + ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); + ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; + + ds->l_desc.dyn_tree = ds->dyn_ltree; + ds->d_desc.dyn_tree = ds->dyn_dtree; + ds->bl_desc.dyn_tree = ds->bl_tree; + + return Z_OK; +#endif /* MAXSEG_64K */ +} + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->next_in buffer and copying from it. + * (See also flush_pending()). + */ +local int read_buf(z_streamp strm, Bytef *buf, unsigned int size) +{ + unsigned len = strm->avail_in; + + if (len > size) len = size; + if (len == 0) return 0; + + strm->avail_in -= len; + + if (strm->state->wrap == 1) { + strm->adler = adler32(strm->adler, strm->next_in, len); + } +#ifdef GZIP + else if (strm->state->wrap == 2) { + strm->adler = crc32(strm->adler, strm->next_in, len); + } +#endif + zmemcpy(buf, strm->next_in, len); + strm->next_in += len; + strm->total_in += len; + + return (int)len; +} + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +local void lm_init (deflate_state *s) +{ + s->window_size = (ulg)2L*s->w_size; + + CLEAR_HASH(s); + + /* Set the default configuration parameters: + */ + s->max_lazy_match = configuration_table[s->level].max_lazy; + s->good_match = configuration_table[s->level].good_length; + s->nice_match = configuration_table[s->level].nice_length; + s->max_chain_length = configuration_table[s->level].max_chain; + + s->strstart = 0; + s->block_start = 0L; + s->lookahead = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + s->ins_h = 0; +#ifndef FASTEST +#ifdef ASMV + match_init(); /* initialize the asm code */ +#endif +#endif +} + +#ifndef FASTEST +/* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ +#ifndef ASMV +/* For 80x86 and 680x0, an optimized version will be provided in match.asm or + * match.S. The code will be functionally equivalent. + */ +local uInt longest_match(deflate_state *s, IPos cur_match) + + /* current match */ +{ + unsigned chain_length = s->max_chain_length;/* max hash chain length */ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + int best_len = (int)s->prev_length; /* best match length so far */ /*MAB casts */ + int nice_match = s->nice_match; /* stop if match long enough */ + IPos limit = s->strstart > (IPos)MAX_DIST(s) ? + s->strstart - (IPos)MAX_DIST(s) : NIL; + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + Posf *prev = s->prev; + uInt wmask = s->w_mask; + +#ifdef UNALIGNED_OK + /* Compare two bytes at a time. Note: this is not always beneficial. + * Try with and without -DUNALIGNED_OK to check. + */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; + register ush scan_start = *(ushf*)scan; + register ush scan_end = *(ushf*)(scan+best_len-1); +#else + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + register Byte scan_end1 = scan[best_len-1]; + register Byte scan_end = scan[best_len]; +#endif + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s->prev_length >= s->good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if ((uInt)nice_match > s->lookahead) nice_match = (int )s->lookahead; /*MAB casts */ + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + Assert(cur_match < s->strstart, "no future"); + match = s->window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2. Note that the checks below + * for insufficient lookahead only occur occasionally for performance + * reasons. Therefore uninitialized memory will be accessed, and + * conditional jumps will be made that depend on those values. + * However the length of the match is limited to the lookahead, so + * the output of deflate is not affected by the uninitialized values. + */ +#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) + /* This code assumes sizeof(unsigned short) == 2. Do not use + * UNALIGNED_OK if your compiler uses a different size. + */ + if (*(ushf*)(match+best_len-1) != scan_end || + *(ushf*)match != scan_start) continue; + + /* It is not necessary to compare scan[2] and match[2] since they are + * always equal when the other bytes match, given that the hash keys + * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at + * strstart+3, +5, ... up to strstart+257. We check for insufficient + * lookahead only every 4th comparison; the 128th check will be made + * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * necessary to put more guard bytes at the end of the window, or + * to check more often for insufficient lookahead. + */ + Assert(scan[2] == match[2], "scan[2]?"); + scan++, match++; + do { + } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + scan < strend); + /* The funny "do {}" generates better code on most compilers */ + + /* Here, scan <= window+strstart+257 */ + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + if (*scan == *match) scan++; + + len = (MAX_MATCH - 1) - (int)(strend-scan); + scan = strend - (MAX_MATCH-1); + +#else /* UNALIGNED_OK */ + + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match++; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ +#if 0 + + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); +#else + /*MAB: to silence compiler warning, intel 981*/ + do { + ++scan; ++match; if (*scan != *match) break; + ++scan; ++match; if (*scan != *match) break; + ++scan; ++match; if (*scan != *match) break; + ++scan; ++match; if (*scan != *match) break; + + ++scan; ++match; if (*scan != *match) break; + ++scan; ++match; if (*scan != *match) break; + ++scan; ++match; if (*scan != *match) break; + ++scan; ++match; if (*scan != *match) break; + } while (scan < strend); +#endif + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + +#endif /* UNALIGNED_OK */ + + if (len > best_len) { + s->match_start = cur_match; + best_len = len; + if (len >= nice_match) break; +#ifdef UNALIGNED_OK + scan_end = *(ushf*)(scan+best_len-1); +#else + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; +#endif + } + } while ((cur_match = prev[cur_match & wmask]) > limit + && --chain_length != 0); + + if ((uInt)best_len <= s->lookahead) return (uInt)best_len; + return s->lookahead; +} +#endif /* ASMV */ +#endif /* FASTEST */ + +/* --------------------------------------------------------------------------- + * Optimized version for level == 1 or strategy == Z_RLE only + */ +local uInt longest_match_fast(deflate_state *s, IPos cur_match) + + /* current match */ +{ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + Assert(cur_match < s->strstart, "no future"); + + match = s->window + cur_match; + + /* Return failure if the match length is less than 2: + */ + if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match += 2; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ +#if 0 + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + +#else + /*MAB: to silence compiler warning, intel 981*/ + do { + ++scan; ++match; if (*scan != *match) break; + ++scan; ++match; if (*scan != *match) break; + ++scan; ++match; if (*scan != *match) break; + ++scan; ++match; if (*scan != *match) break; + + ++scan; ++match; if (*scan != *match) break; + ++scan; ++match; if (*scan != *match) break; + ++scan; ++match; if (*scan != *match) break; + ++scan; ++match; if (*scan != *match) break; + } while (scan < strend); +#endif + + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + + if (len < MIN_MATCH) return MIN_MATCH - 1; + + s->match_start = cur_match; + return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; +} + +#ifdef DEBUG +/* =========================================================================== + * Check that the match at match_start is indeed a match. + */ +local void check_match(s, start, match, length) + deflate_state *s; + IPos start, match; + int length; +{ + /* check that the match is indeed a match */ + if (zmemcmp(s->window + match, + s->window + start, (size_t)length) != EQUAL) { /*MAB add size_t cast */ + fprintf(stderr, " start %u, match %u, length %d\n", + start, match, length); + do { + fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); + } while (--length != 0); + z_error("invalid match"); + } + if (z_verbose > 1) { + fprintf(stderr,"\\[%d,%d]", start-match, length); + do { putc(s->window[start++], stderr); } while (--length != 0); + } +} +#else +# define check_match(s, start, match, length) +#endif /* DEBUG */ + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +local void fill_window(deflate_state *s) +{ + register unsigned n, m; + register Posf *p; + unsigned more; /* Amount of free space at the end of the window. */ + uInt wsize = s->w_size; + + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + +#ifdef _MSC_VER +#pragma warning(disable:4127) +#endif + /* Deal with !@#$% 64K limit: */ + if (sizeof(int) <= 2) { + +#ifdef _MSC_VER +#pragma warning(default:4127) +#endif + if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + more = wsize; + + } else if (more == (unsigned)(-1)) { + /* Very unlikely, but possible on 16 bit machine if + * strstart == 0 && lookahead == 1 (input done a byte at time) + */ + more--; + } + } + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (s->strstart >= wsize+MAX_DIST(s)) { + + zmemcpy(s->window, s->window+wsize, (unsigned)wsize); + s->match_start -= wsize; + s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ + s->block_start -= (long) wsize; + + /* Slide the hash table (could be avoided with 32 bit values + at the expense of memory usage). We slide even when level == 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) + */ + /* %%% avoid this when Z_RLE */ + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + } while (--n); + + n = wsize; +#ifndef FASTEST + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +#endif + more += wsize; + } + if (s->strm->avail_in == 0) return; + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + Assert(more >= 2, "more < 2"); + + n = (unsigned)read_buf(s->strm, s->window + s->strstart + s->lookahead, more); /*MAB casts */ + s->lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s->lookahead >= MIN_MATCH) { + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); +} + +/* =========================================================================== + * Flush the current block, with given end-of-file flag. + * IN assertion: strstart is set to the end of the current match. + */ +#define FLUSH_BLOCK_ONLY(s, eof) { \ + _tr_flush_block(s, (s->block_start >= 0L ? \ + (charf *)&s->window[(unsigned)s->block_start] : \ + (charf *)Z_NULL), \ + (ulg)((long)s->strstart - s->block_start), \ + (eof)); \ + s->block_start = (long)s->strstart; /*MAB casts*/\ + flush_pending(s->strm); \ + Tracev((stderr,"[FLUSH]")); \ +} + +/* Same but force premature exit if necessary. */ +#define FLUSH_BLOCK(s, eof) { \ + FLUSH_BLOCK_ONLY(s, eof); \ + if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \ +} + +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * This function does not insert new strings in the dictionary since + * uncompressible data is probably not useful. This function is used + * only for the level=0 compression option. + * NOTE: this function should be optimized to avoid extra copying from + * window to pending_buf. + */ +local block_state deflate_stored(deflate_state *s, int flush) +{ + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + ulg max_block_size = 0xffff; + ulg max_start; + + if (max_block_size > s->pending_buf_size - 5) { + max_block_size = s->pending_buf_size - 5; + } + + /* Copy as much as possible from input to output: */ + for (;;) { + /* Fill the window as much as possible: */ + if (s->lookahead <= 1) { + + Assert(s->strstart < s->w_size+MAX_DIST(s) || + s->block_start >= (long)s->w_size, "slide too late"); + + fill_window(s); + if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; + + if (s->lookahead == 0) break; /* flush the current block */ + } + Assert(s->block_start >= 0L, "block gone"); + + s->strstart += s->lookahead; + s->lookahead = 0; + + /* Emit a stored block if pending_buf will be full: */ + max_start = (ulg)((ulg)s->block_start + (ulg)max_block_size); /*MAB casts */ + if (s->strstart == 0 || (ulg)s->strstart >= max_start) { + /* strstart == 0 is possible when wraparound on 16-bit machine */ + s->lookahead = (uInt)(s->strstart - max_start); + s->strstart = (uInt)max_start; + FLUSH_BLOCK(s, 0); + } + /* Flush if we may have to slide, otherwise block_start may become + * negative and the data will be gone: + */ + if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { + FLUSH_BLOCK(s, 0); + } + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +local block_state deflate_fast(deflate_state *s, int flush) +{ + IPos hash_head = NIL; /* head of the hash chain */ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ +#ifdef FASTEST + if ((s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) || + (s->strategy == Z_RLE && s->strstart - hash_head == 1)) { + s->match_length = longest_match_fast (s, hash_head); + } +#else + if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) { + s->match_length = longest_match (s, hash_head); + } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { + s->match_length = longest_match_fast (s, hash_head); + } +#endif + /* longest_match() or longest_match_fast() sets match_start */ + } + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->match_start, (int)s->match_length); /*MAB cast with int */ + + _tr_tally_dist(s, s->strstart - s->match_start, + s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ +#ifndef FASTEST + if (s->match_length <= s->max_insert_length && + s->lookahead >= MIN_MATCH) { + s->match_length--; /* string at strstart already in table */ + do { + s->strstart++; + INSERT_STRING(s, s->strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s->match_length != 0); + s->strstart++; + } else +#endif + { + s->strstart += s->match_length; + s->match_length = 0; + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +#ifndef FASTEST +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ +local block_state deflate_slow(deflate_state *s, int flush) +{ + IPos hash_head = NIL; /* head of hash chain */ + int bflush; /* set if current block must be flushed */ + + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + */ + s->prev_length = s->match_length, s->prev_match = s->match_start; + s->match_length = MIN_MATCH-1; + + if (hash_head != NIL && s->prev_length < s->max_lazy_match && + s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) { + s->match_length = longest_match (s, hash_head); + } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { + s->match_length = longest_match_fast (s, hash_head); + } + /* longest_match() or longest_match_fast() sets match_start */ + + if (s->match_length <= 5 && (s->strategy == Z_FILTERED +#if TOO_FAR <= 32767 + || (s->match_length == MIN_MATCH && + s->strstart - s->match_start > TOO_FAR) +#endif + )) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s->match_length = MIN_MATCH-1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { + uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ + + check_match(s, s->strstart-1, s->prev_match, (int)s->prev_length); /*MAB cast with int */ + + _tr_tally_dist(s, s->strstart -1 - s->prev_match, + s->prev_length - MIN_MATCH, bflush); + + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s->lookahead -= s->prev_length-1; + s->prev_length -= 2; + do { + if (++s->strstart <= max_insert) { + INSERT_STRING(s, s->strstart, hash_head); + } + } while (--s->prev_length != 0); + s->match_available = 0; + s->match_length = MIN_MATCH-1; + s->strstart++; + + if (bflush) FLUSH_BLOCK(s, 0); + + } else if (s->match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + if (bflush) { + FLUSH_BLOCK_ONLY(s, 0); + } + s->strstart++; + s->lookahead--; + if (s->strm->avail_out == 0) return need_more; + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s->match_available = 1; + s->strstart++; + s->lookahead--; + } + } + Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s->match_available) { + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + s->match_available = 0; + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} +#endif /* FASTEST */ + +#if 0 +/* =========================================================================== + * For Z_RLE, simply look for runs of bytes, generate matches only of distance + * one. Do not maintain a hash table. (It will be regenerated if this run of + * deflate switches away from Z_RLE.) + */ +local block_state deflate_rle(s, flush) + deflate_state *s; + int flush; +{ + int bflush; /* set if current block must be flushed */ + uInt run; /* length of run */ + uInt max; /* maximum length of run */ + uInt prev; /* byte at distance one to match */ + Bytef *scan; /* scan for end of run */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the longest encodable run. + */ + if (s->lookahead < MAX_MATCH) { + fill_window(s); + if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* See how many times the previous byte repeats */ + run = 0; + if (s->strstart > 0) { /* if there is a previous byte, that is */ + max = s->lookahead < MAX_MATCH ? s->lookahead : MAX_MATCH; + scan = s->window + s->strstart - 1; + prev = *scan++; + do { + if (*scan++ != prev) + break; + } while (++run < max); + } + + /* Emit match if have run of MIN_MATCH or longer, else emit literal */ + if (run >= MIN_MATCH) { + check_match(s, s->strstart, s->strstart - 1, run); + _tr_tally_dist(s, 1, run - MIN_MATCH, bflush); + s->lookahead -= run; + s->strstart += run; + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} +#endif diff --git a/DroidFish/jni/gtb/compression/zlib/deflate.h b/DroidFish/jni/gtb/compression/zlib/deflate.h new file mode 100644 index 0000000..422340f --- /dev/null +++ b/DroidFish/jni/gtb/compression/zlib/deflate.h @@ -0,0 +1,350 @@ +/* deflate.h -- internal compression state + * Copyright (C) 1995-2004 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef DEFLATE_H +#define DEFLATE_H + +#include "zutil.h" + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer creation by deflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip encoding + should be left enabled. */ +#ifndef NO_GZIP +# define GZIP +#endif + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define INIT_STATE 42 +#define EXTRA_STATE 69 +#define NAME_STATE 73 +#define COMMENT_STATE 91 +#define HCRC_STATE 103 +#define BUSY_STATE 113 +#define FINISH_STATE 666 +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union fc { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union dl { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} FAR ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ +} FAR tree_desc; + +typedef ush Pos; +typedef Pos FAR Posf; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct internal_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + uInt pending; /* nb of bytes in the pending buffer */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + gz_headerp gzhead; /* gzip header information to write */ + uInt gzindex; /* where in extra, name, or comment */ + Byte method; /* STORED (for zip only) or DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Bytef *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + ulg window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + Posf *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Posf *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + long block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + uInt max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + uInt max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + /* Didn't use ct_data typedef below to supress compiler warning */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uchf *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + uInt last_lit; /* running index in l_buf */ + + ushf *d_buf; + /* Buffer for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + int last_eob_len; /* bit length of EOB code for last block */ + +#ifdef DEBUG + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ +#endif + + ush bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + int bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + +} FAR deflate_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +/*MAB: Cast (z_Bytef) to silence compiler */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (z_Bytef)(c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + + /* in trees.c */ +void _tr_init OF((deflate_state *s)); +int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); +void _tr_align OF((deflate_state *s)); +void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef DEBUG +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch _length_code[]; + extern uch _dist_code[]; +#else + extern const uch _length_code[]; + extern const uch _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +/* +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (length); \ + ush dist = (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +*/ +/*MAB: Modify the top function to silence compiler with (uch) and (ush) casts */ +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (uch )(length); \ + ush dist = (ush) (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } + + + + + +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + +#endif /* DEFLATE_H */ diff --git a/DroidFish/jni/gtb/compression/zlib/infback.c b/DroidFish/jni/gtb/compression/zlib/infback.c new file mode 100644 index 0000000..e571d51 --- /dev/null +++ b/DroidFish/jni/gtb/compression/zlib/infback.c @@ -0,0 +1,620 @@ +/* infback.c -- inflate using a call-back interface + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + This code is largely copied from inflate.c. Normally either infback.o or + inflate.o would be linked into an application--not both. The interface + with inffast.c is retained so that optimized assembler-coded versions of + inflate_fast() can be used with either inflate.c or infback.c. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); + +/* + strm provides memory allocation functions in zalloc and zfree, or + Z_NULL to use the library memory allocation functions. + + windowBits is in the range 8..15, and window is a user-supplied + window and output buffer that is 2**windowBits bytes. + */ +int ZEXPORT inflateBackInit_(z_streamp strm, int windowBits, unsigned char *window, const char *version, int stream_size) +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL || window == Z_NULL || + windowBits < 8 || windowBits > 15) + return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *)ZALLOC(strm, 1, + sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + state->dmax = 32768U; + state->wbits = (unsigned)windowBits; /*MAB casts */ + state->wsize = 1U << windowBits; + state->window = window; + state->write = 0; + state->whave = 0; + return Z_OK; +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(struct inflate_state *state) +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +/* Macros for inflateBack(): */ + +/* Load returned state from inflate_fast() */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Set state from registers for inflate_fast() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Assure that some input is available. If input is requested, but denied, + then return a Z_BUF_ERROR from inflateBack(). */ +#define PULL() \ + do { \ + if (have == 0) { \ + have = in(in_desc, &next); \ + if (have == 0) { \ + next = Z_NULL; \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflateBack() + with an error if there is no input available. */ +#define PULLBYTE() \ + do { \ + PULL(); \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflateBack() with + an error. */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Assure that some output space is available, by writing out the window + if it's full. If the write fails, return from inflateBack() with a + Z_BUF_ERROR. */ +#define ROOM() \ + do { \ + if (left == 0) { \ + put = state->window; \ + left = state->wsize; \ + state->whave = left; \ + if (out(out_desc, put, left)) { \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* + strm provides the memory allocation functions and window buffer on input, + and provides information on the unused input on return. For Z_DATA_ERROR + returns, strm will also provide an error message. + + in() and out() are the call-back input and output functions. When + inflateBack() needs more input, it calls in(). When inflateBack() has + filled the window with output, or when it completes with data in the + window, it calls out() to write out the data. The application must not + change the provided input until in() is called again or inflateBack() + returns. The application must not change the window/output buffer until + inflateBack() returns. + + in() and out() are called with a descriptor parameter provided in the + inflateBack() call. This parameter can be a structure that provides the + information required to do the read or write, as well as accumulated + information on the input and output such as totals and check values. + + in() should return zero on failure. out() should return non-zero on + failure. If either in() or out() fails, than inflateBack() returns a + Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it + was in() or out() that caused in the error. Otherwise, inflateBack() + returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format + error, or Z_MEM_ERROR if it could not allocate memory for the state. + inflateBack() can also return Z_STREAM_ERROR if the input parameters + are not correct, i.e. strm is Z_NULL or the state was not initialized. + */ + +#ifdef _MSC_VER +#pragma warning(disable:4127) +#endif + +int ZEXPORT inflateBack(z_streamp strm, in_func in, void *in_desc, out_func out, void *out_desc) +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code this; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + /* Check that the strm exists and that the state was initialized */ + if (strm == Z_NULL || strm->state == Z_NULL) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* Reset the state */ + strm->msg = Z_NULL; + state->mode = TYPE; + state->last = 0; + state->whave = 0; + next = strm->next_in; + have = next != Z_NULL ? strm->avail_in : 0; + hold = 0; + bits = 0; + put = state->window; + left = state->wsize; + + /* Inflate until end of block marked as last */ + for (;;) + switch (state->mode) { + case TYPE: + /* determine and dispatch block type */ + if (state->last) { + BYTEBITS(); + state->mode = DONE; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + + case STORED: + /* get and verify stored block length */ + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + + /* copy stored block from input to output */ + while (state->length != 0) { + copy = state->length; + PULL(); + ROOM(); + if (copy > have) copy = have; + if (copy > left) copy = left; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + + case TABLE: + /* get dynamic table entries descriptor */ + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + + /* get code length code lengths (not a typo) */ + state->have = 0; + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + + /* get length and distance code code lengths */ + state->have = 0; + while (state->have < state->nlen + state->ndist) { + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.val < 16) { + NEEDBITS(this.bits); + DROPBITS(this.bits); + state->lens[state->have++] = this.val; + } + else { + if (this.val == 16) { + NEEDBITS(this.bits + 2); + DROPBITS(this.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = (unsigned)(state->lens[state->have - 1]); + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (this.val == 17) { + NEEDBITS(this.bits + 3); + DROPBITS(this.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(this.bits + 7); + DROPBITS(this.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* build code tables */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN; + + case LEN: + /* use inflate_fast() if we have enough input and output */ + if (have >= 6 && left >= 258) { + RESTORE(); + if (state->whave < state->wsize) + state->whave = state->wsize - left; + inflate_fast(strm, state->wsize); + LOAD(); + break; + } + + /* get a literal, length, or end-of-block code */ + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.op && (this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + state->length = (unsigned)this.val; + + /* process literal */ + if (this.op == 0) { + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + ROOM(); + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + } + + /* process end of block */ + if (this.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + + /* invalid code */ + if (this.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + + /* length code -- get extra bits, if any */ + state->extra = (unsigned)(this.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + + /* get distance code */ + for (;;) { + this = state->distcode[BITS(state->distbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if ((this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + if (this.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)this.val; + + /* get distance extra bits, if any */ + state->extra = (unsigned)(this.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } + if (state->offset > state->wsize - (state->whave < state->wsize ? + left : 0)) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + + /* copy match from window to output */ + do { + ROOM(); + copy = state->wsize - state->offset; + if (copy < left) { + from = put + copy; + copy = left - copy; + } + else { + from = put - state->offset; + copy = left; + } + if (copy > state->length) copy = state->length; + state->length -= copy; + left -= copy; + do { + *put++ = *from++; + } while (--copy); + } while (state->length != 0); + break; + + case DONE: + /* inflate stream terminated properly -- write leftover output */ + ret = Z_STREAM_END; + if (left < state->wsize) { + if (out(out_desc, state->window, state->wsize - left)) + ret = Z_BUF_ERROR; + } + goto inf_leave; + + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + + default: /* can't happen, but makes compilers happy */ + ret = Z_STREAM_ERROR; + goto inf_leave; + } + + /* Return unused input */ + inf_leave: + strm->next_in = next; + strm->avail_in = have; + return ret; +} + +#ifdef _MSC_VER +#pragma warning(default:4127) +#endif + +int ZEXPORT inflateBackEnd(z_streamp strm) +{ + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} diff --git a/DroidFish/jni/gtb/compression/zlib/inffast.c b/DroidFish/jni/gtb/compression/zlib/inffast.c new file mode 100644 index 0000000..e9400eb --- /dev/null +++ b/DroidFish/jni/gtb/compression/zlib/inffast.c @@ -0,0 +1,318 @@ +/* inffast.c -- fast decoding + * Copyright (C) 1995-2004 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifndef ASMINF + +/* Allow machine dependent optimization for post-increment or pre-increment. + Based on testing to date, + Pre-increment preferred for: + - PowerPC G3 (Adler) + - MIPS R5000 (Randers-Pehrson) + Post-increment preferred for: + - none + No measurable difference: + - Pentium III (Anderson) + - M68060 (Nikl) + */ +#ifdef POSTINC +# define OFF 0 +# define PUP(a) *(a)++ +#else +# define OFF 1 +# define PUP(a) *++(a) +#endif + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ +void inflate_fast(z_streamp strm, unsigned int start) + + /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + unsigned char FAR *in; /* local strm->next_in */ + unsigned char FAR *last; /* while in < last, enough input available */ + unsigned char FAR *out; /* local strm->next_out */ + unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ + unsigned char FAR *end; /* while out < end, enough space available */ +#ifdef INFLATE_STRICT + unsigned dmax; /* maximum distance from zlib header */ +#endif + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ + unsigned long hold; /* local strm->hold */ + unsigned bits; /* local strm->bits */ + code const FAR *lcode; /* local strm->lencode */ + code const FAR *dcode; /* local strm->distcode */ + unsigned lmask; /* mask for first level of length codes */ + unsigned dmask; /* mask for first level of distance codes */ + code this; /* retrieved table entry */ + unsigned op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + unsigned len; /* match length, unused bytes */ + unsigned dist; /* match distance */ + unsigned char FAR *from; /* where to copy match from */ + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + in = strm->next_in - OFF; + last = in + (strm->avail_in - 5); + out = strm->next_out - OFF; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - 257); +#ifdef INFLATE_STRICT + dmax = state->dmax; +#endif + wsize = state->wsize; + whave = state->whave; + write = state->write; + window = state->window; + hold = state->hold; + bits = state->bits; + lcode = state->lencode; + dcode = state->distcode; + lmask = (1U << state->lenbits) - 1; + dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + do { + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + this = lcode[hold & lmask]; + dolen: + op = (unsigned)(this.bits); + hold >>= op; + bits -= op; + op = (unsigned)(this.op); + if (op == 0) { /* literal */ + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + PUP(out) = (unsigned char)(this.val); + } + else if (op & 16) { /* length base */ + len = (unsigned)(this.val); + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + len += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + } + Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + this = dcode[hold & dmask]; + dodist: + op = (unsigned)(this.bits); + hold >>= op; + bits -= op; + op = (unsigned)(this.op); + if (op & 16) { /* distance base */ + dist = (unsigned)(this.val); + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + } + dist += (unsigned)hold & ((1U << op) - 1); +#ifdef INFLATE_STRICT + if (dist > dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + hold >>= op; + bits -= op; + Tracevv((stderr, "inflate: distance %u\n", dist)); + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + from = window - OFF; + if (write == 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + else if (write < op) { /* wrap around window */ + from += wsize + write - op; + op -= write; + if (op < len) { /* some from end of window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = window - OFF; + if (write < len) { /* some from start of window */ + op = write; + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + } + else { /* contiguous in window */ + from += write - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + while (len > 2) { + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + else { + from = out - dist; /* copy direct from output */ + do { /* minimum length is three */ + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } while (len > 2); + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + } + else if ((op & 64) == 0) { /* 2nd level distance code */ + this = dcode[this.val + (hold & ((1U << op) - 1))]; + goto dodist; + } + else { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + } + else if ((op & 64) == 0) { /* 2nd level length code */ + this = lcode[this.val + (hold & ((1U << op) - 1))]; + goto dolen; + } + else if (op & 32) { /* end-of-block */ + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + else { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + } while (in < last && out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + in -= len; + bits -= len << 3; + hold &= (1U << bits) - 1; + + /* update state and return */ + strm->next_in = in + OFF; + strm->next_out = out + OFF; + strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); + strm->avail_out = (unsigned)(out < end ? + 257 + (end - out) : 257 - (out - end)); + state->hold = hold; + state->bits = bits; + return; +} + +/* + inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): + - Using bit fields for code structure + - Different op definition to avoid & for extra bits (do & for table bits) + - Three separate decoding do-loops for direct, window, and write == 0 + - Special case for distance > 1 copies to do overlapped load and store copy + - Explicit branch predictions (based on measured branch probabilities) + - Deferring match copy and interspersed it with decoding subsequent codes + - Swapping literal/length else + - Swapping window/direct else + - Larger unrolled copy loops (three is about right) + - Moving len -= 3 statement into middle of loop + */ + +#endif /* !ASMINF */ diff --git a/DroidFish/jni/gtb/compression/zlib/inffast.h b/DroidFish/jni/gtb/compression/zlib/inffast.h new file mode 100644 index 0000000..1e88d2d --- /dev/null +++ b/DroidFish/jni/gtb/compression/zlib/inffast.h @@ -0,0 +1,11 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +void inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/DroidFish/jni/gtb/compression/zlib/inffixed.h b/DroidFish/jni/gtb/compression/zlib/inffixed.h new file mode 100644 index 0000000..75ed4b5 --- /dev/null +++ b/DroidFish/jni/gtb/compression/zlib/inffixed.h @@ -0,0 +1,94 @@ + /* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ + + /* WARNING: this file should *not* be used by applications. It + is part of the implementation of the compression library and + is subject to change. Applications should only use zlib.h. + */ + + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; + + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; diff --git a/DroidFish/jni/gtb/compression/zlib/inflate.c b/DroidFish/jni/gtb/compression/zlib/inflate.c new file mode 100644 index 0000000..16b95d0 --- /dev/null +++ b/DroidFish/jni/gtb/compression/zlib/inflate.c @@ -0,0 +1,1348 @@ +/* inflate.c -- zlib decompression + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * Change history: + * + * 1.2.beta0 24 Nov 2002 + * - First version -- complete rewrite of inflate to simplify code, avoid + * creation of window when not needed, minimize use of window when it is + * needed, make inffast.c even faster, implement gzip decoding, and to + * improve code readability and style over the previous zlib inflate code + * + * 1.2.beta1 25 Nov 2002 + * - Use pointers for available input and output checking in inffast.c + * - Remove input and output counters in inffast.c + * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 + * - Remove unnecessary second byte pull from length extra in inffast.c + * - Unroll direct copy to three copies per loop in inffast.c + * + * 1.2.beta2 4 Dec 2002 + * - Change external routine names to reduce potential conflicts + * - Correct filename to inffixed.h for fixed tables in inflate.c + * - Make hbuf[] unsigned char to match parameter type in inflate.c + * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) + * to avoid negation problem on Alphas (64 bit) in inflate.c + * + * 1.2.beta3 22 Dec 2002 + * - Add comments on state->bits assertion in inffast.c + * - Add comments on op field in inftrees.h + * - Fix bug in reuse of allocated window after inflateReset() + * - Remove bit fields--back to byte structure for speed + * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths + * - Change post-increments to pre-increments in inflate_fast(), PPC biased? + * - Add compile time option, POSTINC, to use post-increments instead (Intel?) + * - Make MATCH copy in inflate() much faster for when inflate_fast() not used + * - Use local copies of stream next and avail values, as well as local bit + * buffer and bit count in inflate()--for speed when inflate_fast() not used + * + * 1.2.beta4 1 Jan 2003 + * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings + * - Move a comment on output buffer sizes from inffast.c to inflate.c + * - Add comments in inffast.c to introduce the inflate_fast() routine + * - Rearrange window copies in inflate_fast() for speed and simplification + * - Unroll last copy for window match in inflate_fast() + * - Use local copies of window variables in inflate_fast() for speed + * - Pull out common write == 0 case for speed in inflate_fast() + * - Make op and len in inflate_fast() unsigned for consistency + * - Add FAR to lcode and dcode declarations in inflate_fast() + * - Simplified bad distance check in inflate_fast() + * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new + * source file infback.c to provide a call-back interface to inflate for + * programs like gzip and unzip -- uses window as output buffer to avoid + * window copying + * + * 1.2.beta5 1 Jan 2003 + * - Improved inflateBack() interface to allow the caller to provide initial + * input in strm. + * - Fixed stored blocks bug in inflateBack() + * + * 1.2.beta6 4 Jan 2003 + * - Added comments in inffast.c on effectiveness of POSTINC + * - Typecasting all around to reduce compiler warnings + * - Changed loops from while (1) or do {} while (1) to for (;;), again to + * make compilers happy + * - Changed type of window in inflateBackInit() to unsigned char * + * + * 1.2.beta7 27 Jan 2003 + * - Changed many types to unsigned or unsigned short to avoid warnings + * - Added inflateCopy() function + * + * 1.2.0 9 Mar 2003 + * - Changed inflateBack() interface to provide separate opaque descriptors + * for the in() and out() functions + * - Changed inflateBack() argument and in_func typedef to swap the length + * and buffer address return values for the input function + * - Check next_in and next_out for Z_NULL on entry to inflate() + * + * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifdef MAKEFIXED +# ifndef BUILDFIXED +# define BUILDFIXED +# endif +#endif + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); +local int updatewindow OF((z_streamp strm, unsigned out)); +#ifdef BUILDFIXED + void makefixed OF((void)); +#endif +local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf, + unsigned len)); + +int ZEXPORT inflateReset(z_streamp strm) +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + strm->total_in = strm->total_out = state->total = 0; + strm->msg = Z_NULL; + strm->adler = 1; /* to support ill-conceived Java test suite */ + state->mode = HEAD; + state->last = 0; + state->havedict = 0; + state->dmax = 32768U; + state->head = Z_NULL; + state->wsize = 0; + state->whave = 0; + state->write = 0; + state->hold = 0; + state->bits = 0; + state->lencode = state->distcode = state->next = state->codes; + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + +int ZEXPORT inflatePrime(z_streamp strm, int bits, int value) +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (bits > 16 || state->bits + (unsigned)bits > 32) return Z_STREAM_ERROR; /*MAB casts */ + value &= (int) ((1L << bits) - 1); /*MAB casts */ + state->hold += ((long unsigned)value << state->bits); /*MAB casts */ + state->bits += (unsigned) bits; /*MAB casts */ + return Z_OK; +} + +int ZEXPORT inflateInit2_(z_streamp strm, int windowBits, const char *version, int stream_size) +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL) return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *) + ZALLOC(strm, 1, sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + if (windowBits < 0) { + state->wrap = 0; + windowBits = -windowBits; + } + else { + state->wrap = (windowBits >> 4) + 1; +#ifdef GUNZIP + if (windowBits < 48) windowBits &= 15; +#endif + } + if (windowBits < 8 || windowBits > 15) { + ZFREE(strm, state); + strm->state = Z_NULL; + return Z_STREAM_ERROR; + } + state->wbits = (unsigned)windowBits; + state->window = Z_NULL; + return inflateReset(strm); +} + +int ZEXPORT inflateInit_(z_streamp strm, const char *version, int stream_size) +{ + return inflateInit2_(strm, DEF_WBITS, version, stream_size); +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(struct inflate_state *state) +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +#ifdef MAKEFIXED +#include + +/* + Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also + defines BUILDFIXED, so the tables are built on the fly. makefixed() writes + those tables to stdout, which would be piped to inffixed.h. A small program + can simply call makefixed to do this: + + void makefixed(void); + + int main(void) + { + makefixed(); + return 0; + } + + Then that can be linked with zlib built with MAKEFIXED defined and run: + + a.out > inffixed.h + */ +void makefixed() +{ + unsigned low, size; + struct inflate_state state; + + fixedtables(&state); + puts(" /* inffixed.h -- table for decoding fixed codes"); + puts(" * Generated automatically by makefixed()."); + puts(" */"); + puts(""); + puts(" /* WARNING: this file should *not* be used by applications."); + puts(" It is part of the implementation of this library and is"); + puts(" subject to change. Applications should only use zlib.h."); + puts(" */"); + puts(""); + size = 1U << 9; + printf(" static const code lenfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 7) == 0) printf("\n "); + printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits, + state.lencode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); + size = 1U << 5; + printf("\n static const code distfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 6) == 0) printf("\n "); + printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, + state.distcode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); +} +#endif /* MAKEFIXED */ + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +local int updatewindow(z_streamp strm, unsigned int out) +{ + struct inflate_state FAR *state; + unsigned copy, dist; + + state = (struct inflate_state FAR *)strm->state; + + /* if it hasn't been done already, allocate space for the window */ + if (state->window == Z_NULL) { + state->window = (unsigned char FAR *) + ZALLOC(strm, 1U << state->wbits, + sizeof(unsigned char)); + if (state->window == Z_NULL) return 1; + } + + /* if window not in use yet, initialize */ + if (state->wsize == 0) { + state->wsize = 1U << state->wbits; + state->write = 0; + state->whave = 0; + } + + /* copy state->wsize or less output bytes into the circular window */ + copy = out - strm->avail_out; + if (copy >= state->wsize) { + zmemcpy(state->window, strm->next_out - state->wsize, state->wsize); + state->write = 0; + state->whave = state->wsize; + } + else { + dist = state->wsize - state->write; + if (dist > copy) dist = copy; + zmemcpy(state->window + state->write, strm->next_out - copy, dist); + copy -= dist; + if (copy) { + zmemcpy(state->window, strm->next_out - copy, copy); + state->write = copy; + state->whave = state->wsize; + } + else { + state->write += dist; + if (state->write == state->wsize) state->write = 0; + if (state->whave < state->wsize) state->whave += dist; + } + } + return 0; +} + +/* Macros for inflate(): */ + +/* check function to use adler32() for zlib or crc32() for gzip */ +#ifdef GUNZIP +# define UPDATE(check, buf, len) \ + (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) +#else +# define UPDATE(check, buf, len) adler32(check, buf, len) +#endif + +/* check macros for header crc */ +#ifdef GUNZIP +# define CRC2(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + check = crc32(check, hbuf, 2); \ + } while (0) + +# define CRC4(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + hbuf[2] = (unsigned char)((word) >> 16); \ + hbuf[3] = (unsigned char)((word) >> 24); \ + check = crc32(check, hbuf, 4); \ + } while (0) +#endif + +/* Load registers with state in inflate() for speed */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Restore state from registers in inflate() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflate() + if there is no input available. */ +#define PULLBYTE() \ + do { \ + if (have == 0) goto inf_leave; \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflate(). */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Reverse the bytes in a 32-bit value */ +#define REVERSE(q) \ + ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + +/* + inflate() uses a state machine to process as much input data and generate as + much output data as possible before returning. The state machine is + structured roughly as follows: + + for (;;) switch (state) { + ... + case STATEn: + if (not enough input data or output space to make progress) + return; + ... make progress ... + state = STATEm; + break; + ... + } + + so when inflate() is called again, the same case is attempted again, and + if the appropriate resources are provided, the machine proceeds to the + next state. The NEEDBITS() macro is usually the way the state evaluates + whether it can proceed or should return. NEEDBITS() does the return if + the requested bits are not available. The typical use of the BITS macros + is: + + NEEDBITS(n); + ... do something with BITS(n) ... + DROPBITS(n); + + where NEEDBITS(n) either returns from inflate() if there isn't enough + input left to load n bits into the accumulator, or it continues. BITS(n) + gives the low n bits in the accumulator. When done, DROPBITS(n) drops + the low n bits off the accumulator. INITBITS() clears the accumulator + and sets the number of available bits to zero. BYTEBITS() discards just + enough bits to put the accumulator on a byte boundary. After BYTEBITS() + and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. + + NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return + if there is no input available. The decoding of variable length codes uses + PULLBYTE() directly in order to pull just enough bytes to decode the next + code, and no more. + + Some states loop until they get enough input, making sure that enough + state information is maintained to continue the loop where it left off + if NEEDBITS() returns in the loop. For example, want, need, and keep + would all have to actually be part of the saved state in case NEEDBITS() + returns: + + case STATEw: + while (want < need) { + NEEDBITS(n); + keep[want++] = BITS(n); + DROPBITS(n); + } + state = STATEx; + case STATEx: + + As shown above, if the next state is also the next case, then the break + is omitted. + + A state may also return if there is not enough output space available to + complete that state. Those states are copying stored data, writing a + literal byte, and copying a matching string. + + When returning, a "goto inf_leave" is used to update the total counters, + update the check value, and determine whether any progress has been made + during that inflate() call in order to return the proper return code. + Progress is defined as a change in either strm->avail_in or strm->avail_out. + When there is a window, goto inf_leave will update the window with the last + output written. If a goto inf_leave occurs in the middle of decompression + and there is no window currently, goto inf_leave will create one and copy + output to the window for the next call of inflate(). + + In this implementation, the flush parameter of inflate() only affects the + return code (per zlib.h). inflate() always writes as much as possible to + strm->next_out, given the space available and the provided input--the effect + documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers + the allocation of and copying into a sliding window until necessary, which + provides the effect documented in zlib.h for Z_FINISH when the entire input + stream available. So the only thing the flush parameter actually does is: + when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it + will return Z_BUF_ERROR if it has not reached the end of the stream. + */ + + +#ifdef _MSC_VER +#pragma warning(disable:4127) +#endif + +int ZEXPORT inflate(z_streamp strm, int flush) +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned in, out; /* save starting available input and output */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code this; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ +#ifdef GUNZIP + unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ +#endif + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0)) + return Z_STREAM_ERROR; + + state = (struct inflate_state FAR *)strm->state; + if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ + LOAD(); + in = have; + out = left; + ret = Z_OK; + for (;;) + switch (state->mode) { + case HEAD: + if (state->wrap == 0) { + state->mode = TYPEDO; + break; + } + NEEDBITS(16); +#ifdef GUNZIP + if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + state->check = crc32(0L, Z_NULL, 0); + CRC2(state->check, hold); + INITBITS(); + state->mode = FLAGS; + break; + } + state->flags = 0; /* expect zlib header */ + if (state->head != Z_NULL) + state->head->done = -1; + if (!(state->wrap & 1) || /* check if zlib header allowed */ +#else + if ( +#endif + ((BITS(8) << 8) + (hold >> 8)) % 31) { + strm->msg = (char *)"incorrect header check"; + state->mode = BAD; + break; + } + if (BITS(4) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + DROPBITS(4); + len = BITS(4) + 8; + if (len > state->wbits) { + strm->msg = (char *)"invalid window size"; + state->mode = BAD; + break; + } + state->dmax = 1U << len; + Tracev((stderr, "inflate: zlib header ok\n")); + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = hold & 0x200 ? DICTID : TYPE; + INITBITS(); + break; +#ifdef GUNZIP + case FLAGS: + NEEDBITS(16); + state->flags = (int)(hold); + if ((state->flags & 0xff) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + if (state->flags & 0xe000) { + strm->msg = (char *)"unknown header flags set"; + state->mode = BAD; + break; + } + if (state->head != Z_NULL) + state->head->text = (int)((hold >> 8) & 1); + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = TIME; + case TIME: + NEEDBITS(32); + if (state->head != Z_NULL) + state->head->time = hold; + if (state->flags & 0x0200) CRC4(state->check, hold); + INITBITS(); + state->mode = OS; + case OS: + NEEDBITS(16); + if (state->head != Z_NULL) { + state->head->xflags = (int)(hold & 0xff); + state->head->os = (int)(hold >> 8); + } + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = EXLEN; + case EXLEN: + if (state->flags & 0x0400) { + NEEDBITS(16); + state->length = (unsigned)(hold); + if (state->head != Z_NULL) + state->head->extra_len = (unsigned)hold; + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + } + else if (state->head != Z_NULL) + state->head->extra = Z_NULL; + state->mode = EXTRA; + case EXTRA: + if (state->flags & 0x0400) { + copy = state->length; + if (copy > have) copy = have; + if (copy) { + if (state->head != Z_NULL && + state->head->extra != Z_NULL) { + len = state->head->extra_len - state->length; + zmemcpy(state->head->extra + len, next, + len + copy > state->head->extra_max ? + state->head->extra_max - len : copy); + } + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + state->length -= copy; + } + if (state->length) goto inf_leave; + } + state->length = 0; + state->mode = NAME; + case NAME: + if (state->flags & 0x0800) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->name != Z_NULL && + state->length < state->head->name_max) + state->head->name[state->length++] = (Bytef) len; /*MAB: Cast to silence compiler */ + } while (len && copy < have); + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->name = Z_NULL; + state->length = 0; + state->mode = COMMENT; + case COMMENT: + if (state->flags & 0x1000) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->comment != Z_NULL && + state->length < state->head->comm_max) + state->head->comment[state->length++] = (Bytef) len; /*MAB: Cast to silence compiler */ + } while (len && copy < have); + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->comment = Z_NULL; + state->mode = HCRC; + case HCRC: + if (state->flags & 0x0200) { + NEEDBITS(16); + if (hold != (state->check & 0xffff)) { + strm->msg = (char *)"header crc mismatch"; + state->mode = BAD; + break; + } + INITBITS(); + } + if (state->head != Z_NULL) { + state->head->hcrc = (int)((state->flags >> 9) & 1); + state->head->done = 1; + } + strm->adler = state->check = crc32(0L, Z_NULL, 0); + state->mode = TYPE; + break; +#endif + case DICTID: + NEEDBITS(32); + strm->adler = state->check = REVERSE(hold); + INITBITS(); + state->mode = DICT; + case DICT: + if (state->havedict == 0) { + RESTORE(); + return Z_NEED_DICT; + } + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = TYPE; + case TYPE: + if (flush == Z_BLOCK) goto inf_leave; + case TYPEDO: + if (state->last) { + BYTEBITS(); + state->mode = CHECK; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + case STORED: + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + state->mode = COPY; + case COPY: + copy = state->length; + if (copy) { + if (copy > have) copy = have; + if (copy > left) copy = left; + if (copy == 0) goto inf_leave; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + break; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + case TABLE: + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + state->have = 0; + state->mode = LENLENS; + case LENLENS: + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + state->have = 0; + state->mode = CODELENS; + case CODELENS: + while (state->have < state->nlen + state->ndist) { + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.val < 16) { + NEEDBITS(this.bits); + DROPBITS(this.bits); + state->lens[state->have++] = this.val; + } + else { + if (this.val == 16) { + NEEDBITS(this.bits + 2); + DROPBITS(this.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = state->lens[state->have - 1]; + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (this.val == 17) { + NEEDBITS(this.bits + 3); + DROPBITS(this.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(this.bits + 7); + DROPBITS(this.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* build code tables */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN; + case LEN: + if (have >= 6 && left >= 258) { + RESTORE(); + inflate_fast(strm, out); + LOAD(); + break; + } + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.op && (this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + state->length = (unsigned)this.val; + if ((int)(this.op) == 0) { + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + state->mode = LIT; + break; + } + if (this.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + if (this.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + state->extra = (unsigned)(this.op) & 15; + state->mode = LENEXT; + case LENEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + state->mode = DIST; + case DIST: + for (;;) { + this = state->distcode[BITS(state->distbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if ((this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + if (this.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)this.val; + state->extra = (unsigned)(this.op) & 15; + state->mode = DISTEXT; + case DISTEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } +#ifdef INFLATE_STRICT + if (state->offset > state->dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + if (state->offset > state->whave + out - left) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + state->mode = MATCH; + case MATCH: + if (left == 0) goto inf_leave; + copy = out - left; + if (state->offset > copy) { /* copy from window */ + copy = state->offset - copy; + if (copy > state->write) { + copy -= state->write; + from = state->window + (state->wsize - copy); + } + else + from = state->window + (state->write - copy); + if (copy > state->length) copy = state->length; + } + else { /* copy from output */ + from = put - state->offset; + copy = state->length; + } + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = *from++; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; + case LIT: + if (left == 0) goto inf_leave; + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + case CHECK: + if (state->wrap) { + NEEDBITS(32); + out -= left; + strm->total_out += out; + state->total += out; + if (out) + strm->adler = state->check = + UPDATE(state->check, put - out, out); + out = left; + if (( +#ifdef GUNZIP + state->flags ? hold : +#endif + REVERSE(hold)) != state->check) { + strm->msg = (char *)"incorrect data check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: check matches trailer\n")); + } +#ifdef GUNZIP + state->mode = LENGTH; + case LENGTH: + if (state->wrap && state->flags) { + NEEDBITS(32); + if (hold != (state->total & 0xffffffffUL)) { + strm->msg = (char *)"incorrect length check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: length matches trailer\n")); + } +#endif + state->mode = DONE; + case DONE: + ret = Z_STREAM_END; + goto inf_leave; + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + default: + return Z_STREAM_ERROR; + } + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + inf_leave: + RESTORE(); + if (state->wsize || (state->mode < CHECK && out != strm->avail_out)) + if (updatewindow(strm, out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + in -= strm->avail_in; + out -= strm->avail_out; + strm->total_in += in; + strm->total_out += out; + state->total += out; + if (state->wrap && out) + strm->adler = state->check = + UPDATE(state->check, strm->next_out - out, out); + strm->data_type = (int)(state->bits + (state->last ? 64 : 0) + (state->mode == TYPE ? 128 : 0)); /*MAB casts */ + + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) + ret = Z_BUF_ERROR; + return ret; +} + +#ifdef _MSC_VER +#pragma warning(default:4127) +#endif + +int ZEXPORT inflateEnd(z_streamp strm) +{ + struct inflate_state FAR *state; + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->window != Z_NULL) ZFREE(strm, state->window); + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + +int ZEXPORT inflateSetDictionary(z_streamp strm, const Bytef *dictionary, uInt dictLength) +{ + struct inflate_state FAR *state; + unsigned long id; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->wrap != 0 && state->mode != DICT) + return Z_STREAM_ERROR; + + /* check for correct dictionary id */ + if (state->mode == DICT) { + id = adler32(0L, Z_NULL, 0); + id = adler32(id, dictionary, dictLength); + if (id != state->check) + return Z_DATA_ERROR; + } + + /* copy dictionary to window */ + if (updatewindow(strm, strm->avail_out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + if (dictLength > state->wsize) { + zmemcpy(state->window, dictionary + dictLength - state->wsize, + state->wsize); + state->whave = state->wsize; + } + else { + zmemcpy(state->window + state->wsize - dictLength, dictionary, + dictLength); + state->whave = dictLength; + } + state->havedict = 1; + Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} + +int ZEXPORT inflateGetHeader(z_streamp strm, gz_headerp head) +{ + struct inflate_state FAR *state; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; + + /* save header structure */ + state->head = head; + head->done = 0; + return Z_OK; +} + +/* + Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found + or when out of input. When called, *have is the number of pattern bytes + found in order so far, in 0..3. On return *have is updated to the new + state. If on return *have equals four, then the pattern was found and the + return value is how many bytes were read including the last byte of the + pattern. If *have is less than four, then the pattern has not been found + yet and the return value is len. In the latter case, syncsearch() can be + called again with more data and the *have state. *have is initialized to + zero for the first call. + */ +local unsigned syncsearch(unsigned int *have, unsigned char *buf, unsigned int len) +{ + unsigned got; + unsigned next; + + got = *have; + next = 0; + while (next < len && got < 4) { + if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) + got++; + else if (buf[next]) + got = 0; + else + got = 4 - got; + next++; + } + *have = got; + return next; +} + +int ZEXPORT inflateSync(z_streamp strm) +{ + unsigned len; /* number of bytes to look at or looked at */ + unsigned long in, out; /* temporary to save total_in and total_out */ + unsigned char buf[4]; /* to restore bit buffer to byte string */ + struct inflate_state FAR *state; + + /* check parameters */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; + + /* if first time, start search in bit buffer */ + if (state->mode != SYNC) { + state->mode = SYNC; + state->hold <<= state->bits & 7; + state->bits -= state->bits & 7; + len = 0; + while (state->bits >= 8) { + buf[len++] = (unsigned char)(state->hold); + state->hold >>= 8; + state->bits -= 8; + } + state->have = 0; + syncsearch(&(state->have), buf, len); + } + + /* search available input */ + len = syncsearch(&(state->have), strm->next_in, strm->avail_in); + strm->avail_in -= len; + strm->next_in += len; + strm->total_in += len; + + /* return no joy or set up to restart inflate() on a new block */ + if (state->have != 4) return Z_DATA_ERROR; + in = strm->total_in; out = strm->total_out; + inflateReset(strm); + strm->total_in = in; strm->total_out = out; + state->mode = TYPE; + return Z_OK; +} + +/* + Returns true if inflate is currently at the end of a block generated by + Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + implementation to provide an additional safety check. PPP uses + Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored + block. When decompressing, PPP checks that at the end of input packet, + inflate is waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint(z_streamp strm) +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + return state->mode == STORED && state->bits == 0; +} + +int ZEXPORT inflateCopy(z_streamp dest, z_streamp source) +{ + struct inflate_state FAR *state; + struct inflate_state FAR *copy; + unsigned char FAR *window; + unsigned wsize; + + /* check input */ + if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || + source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)source->state; + + /* allocate space */ + copy = (struct inflate_state FAR *) + ZALLOC(source, 1, sizeof(struct inflate_state)); + if (copy == Z_NULL) return Z_MEM_ERROR; + window = Z_NULL; + if (state->window != Z_NULL) { + window = (unsigned char FAR *) + ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); + if (window == Z_NULL) { + ZFREE(source, copy); + return Z_MEM_ERROR; + } + } + + /* copy state */ + zmemcpy(dest, source, sizeof(z_stream)); + zmemcpy(copy, state, sizeof(struct inflate_state)); + if (state->lencode >= state->codes && + state->lencode <= state->codes + ENOUGH - 1) { + copy->lencode = copy->codes + (state->lencode - state->codes); + copy->distcode = copy->codes + (state->distcode - state->codes); + } + copy->next = copy->codes + (state->next - state->codes); + if (window != Z_NULL) { + wsize = 1U << state->wbits; + zmemcpy(window, state->window, wsize); + } + copy->window = window; + dest->state = (struct internal_state FAR *)copy; + return Z_OK; +} diff --git a/DroidFish/jni/gtb/compression/zlib/inflate.h b/DroidFish/jni/gtb/compression/zlib/inflate.h new file mode 100644 index 0000000..85db032 --- /dev/null +++ b/DroidFish/jni/gtb/compression/zlib/inflate.h @@ -0,0 +1,115 @@ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2004 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer decoding by inflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip decoding + should be left enabled. */ +#ifndef NO_GZIP +# define GUNZIP +#endif + +/* Possible inflate modes between inflate() calls */ +typedef enum inflate_mode { + HEAD, /* i: waiting for magic header */ + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN, /* i: waiting for length/lit code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ + LENGTH, /* i: waiting for 32-bit length (gzip) */ + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to the BAD or MEM mode -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME + NAME -> COMMENT -> HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + Read deflate blocks: + TYPE -> STORED or TABLE or LEN or CHECK + STORED -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN + Read deflate codes: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* state maintained between inflate() calls. Approximately 7K bytes. */ +struct inflate_state { + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags (0 if zlib) */ + unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + gz_headerp head; /* where to save gzip header information */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ +}; diff --git a/DroidFish/jni/gtb/compression/zlib/inftrees.c b/DroidFish/jni/gtb/compression/zlib/inftrees.c new file mode 100644 index 0000000..a8d23db --- /dev/null +++ b/DroidFish/jni/gtb/compression/zlib/inftrees.c @@ -0,0 +1,323 @@ +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" + +#define MAXBITS 15 + +const char inflate_copyright[] = + " inflate 1.2.3 Copyright 1995-2005 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* + Build a set of tables to decode the provided canonical Huffman code. + The code lengths are lens[0..codes-1]. The result starts at *table, + whose indices are 0..2^bits-1. work is a writable array of at least + lens shorts, which is used as a work area. type is the type of code + to be generated, CODES, LENS, or DISTS. On return, zero is success, + -1 is an invalid code, and +1 means that ENOUGH isn't enough. table + on return points to the next available entry's address. bits is the + requested root table index bits, and on return it is the actual root + table index bits. It will differ if the request is greater than the + longest code or if it is less than the shortest code. + */ +int inflate_table(codetype type, short unsigned int *lens, unsigned int codes, code **table, unsigned int *bits, short unsigned int *work) +{ + unsigned len; /* a code's length in bits */ + unsigned sym; /* index of code symbols */ + unsigned min, max; /* minimum and maximum code lengths */ + unsigned root; /* number of index bits for root table */ + unsigned curr; /* number of index bits for current table */ + unsigned drop; /* code bits to drop for sub-table */ + int left; /* number of prefix codes available */ + unsigned used; /* code entries in table used */ + unsigned huff; /* Huffman code */ + unsigned incr; /* for incrementing code, index */ + unsigned fill; /* index for replicating entries */ + unsigned low; /* low bits for current root entry */ + unsigned mask; /* mask for low root bits */ + code this; /* table entry for duplication */ + code FAR *next; /* next available space in table */ + const unsigned short FAR *base; /* base value table to use */ + const unsigned short FAR *extra; /* extra bits table to use */ + int end; /* use base and extra for symbol > end */ + unsigned short count[MAXBITS+1]; /* number of codes of each length */ + unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ + static const unsigned short lbase[31] = { /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + static const unsigned short lext[31] = { /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 201, 196}; + static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0}; + static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64}; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) + count[len] = 0; + for (sym = 0; sym < codes; sym++) + count[lens[sym]]++; + + /* bound code lengths, force root to be within code lengths */ + root = *bits; + for (max = MAXBITS; max >= 1; max--) + if (count[max] != 0) break; + if (root > max) root = max; + if (max == 0) { /* no symbols to code at all */ + this.op = (unsigned char)64; /* invalid code marker */ + this.bits = (unsigned char)1; + this.val = (unsigned short)0; + *(*table)++ = this; /* make a table to force an error */ + *(*table)++ = this; + *bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min <= MAXBITS; min++) + if (count[min] != 0) break; + if (root < min) root = min; + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) return -1; /* over-subscribed */ + } + if (left > 0 && (type == CODES || max != 1)) + return -1; /* incomplete set */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = (unsigned short) (offs[len] + count[len]); /*MAB: Cast to unsigned short to silence compiler */ + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) + if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked when a LENS table is being made + against the space in *table, ENOUGH, minus the maximum space needed by + the worst case distance code, MAXD. This should never happen, but the + sufficiency of ENOUGH has not been proven exhaustively, hence the check. + This assumes that when type == LENS, bits == 9. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + end = 19; + break; + case LENS: + base = lbase; + base -= 257; + extra = lext; + extra -= 257; + end = 256; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } + + /* initialize state for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = *table; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = (unsigned)(-1); /* trigger new sub-table when len > root */ + used = 1U << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if (type == LENS && used >= ENOUGH - MAXD) + return 1; + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + this.bits = (unsigned char)(len - drop); + if ((int)(work[sym]) < end) { + this.op = (unsigned char)0; + this.val = work[sym]; + } + else if ((int)(work[sym]) > end) { + this.op = (unsigned char)(extra[work[sym]]); + this.val = base[work[sym]]; + } + else { + this.op = (unsigned char)(32 + 64); /* end of block */ + this.val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1U << (len - drop); + fill = 1U << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + next[(huff >> drop) + fill] = this; + } while (fill != 0); + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) == 0) { + if (len == max) break; + len = lens[work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) != low) { + /* if first time, transition to sub-tables */ + if (drop == 0) + drop = root; + + /* increment past last table */ + next += min; /* here min is 1 << curr */ + + /* determine length of next table */ + curr = len - drop; + left = (int)(1 << curr); + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) break; + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1U << curr; + if (type == LENS && used >= ENOUGH - MAXD) + return 1; + + /* point entry in root table to sub-table */ + low = huff & mask; + (*table)[low].op = (unsigned char)curr; + (*table)[low].bits = (unsigned char)root; + (*table)[low].val = (unsigned short)(next - *table); + } + } + + /* + Fill in rest of table for incomplete codes. This loop is similar to the + loop above in incrementing huff for table indices. It is assumed that + len is equal to curr + drop, so there is no loop needed to increment + through high index bits. When the current sub-table is filled, the loop + drops back to the root table to fill in any remaining entries there. + */ + this.op = (unsigned char)64; /* invalid code marker */ + this.bits = (unsigned char)(len - drop); + this.val = (unsigned short)0; + while (huff != 0) { + /* when done with sub-table, drop back to root table */ + if (drop != 0 && (huff & mask) != low) { + drop = 0; + len = root; + next = *table; + this.bits = (unsigned char)len; + } + + /* put invalid code marker in table */ + next[huff >> drop] = this; + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + } + + /* set return parameters */ + *table += used; + *bits = root; + return 0; +} diff --git a/DroidFish/jni/gtb/compression/zlib/inftrees.h b/DroidFish/jni/gtb/compression/zlib/inftrees.h new file mode 100644 index 0000000..9b4bd19 --- /dev/null +++ b/DroidFish/jni/gtb/compression/zlib/inftrees.h @@ -0,0 +1,55 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct code { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of dynamic tree. The maximum found in a long but non- + exhaustive search was 1444 code structures (852 for length/literals + and 592 for distances, the latter actually the result of an + exhaustive search). The true maximum is not known, but the value + below is more than safe. */ +#define ENOUGH 2048 +#define MAXD 592 + +/* Type of code to build for inftable() */ +typedef enum codetype { + CODES, + LENS, + DISTS +} codetype; + +extern int inflate_table OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); diff --git a/DroidFish/jni/gtb/compression/zlib/trees.c b/DroidFish/jni/gtb/compression/zlib/trees.c new file mode 100644 index 0000000..214f693 --- /dev/null +++ b/DroidFish/jni/gtb/compression/zlib/trees.c @@ -0,0 +1,1267 @@ +/* trees.c -- output deflated data using Huffman coding + * Copyright (C) 1995-2005 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process uses several Huffman trees. The more + * common source values are represented by shorter bit sequences. + * + * Each code tree is stored in a compressed form which is itself + * a Huffman encoding of the lengths of all the code strings (in + * ascending order by source values). The actual code strings are + * reconstructed from the lengths in the inflate process, as described + * in the deflate specification. + * + * REFERENCES + * + * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". + * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc + * + * Storer, James A. + * Data Compression: Methods and Theory, pp. 49-50. + * Computer Science Press, 1988. ISBN 0-7167-8156-5. + * + * Sedgewick, R. + * Algorithms, p290. + * Addison-Wesley, 1983. ISBN 0-201-06672-6. + */ + +/* @(#) $Id$ */ + +/* #define GEN_TREES_H */ + +#include "deflate.h" + +#ifdef DEBUG +# include +#endif + +/* =========================================================================== + * Constants + */ + +#define MAX_BL_BITS 7 +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +#define END_BLOCK 256 +/* end of block literal code */ + +#define REP_3_6 16 +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +#define REPZ_3_10 17 +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +#define REPZ_11_138 18 +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ + = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; + +local const int extra_dbits[D_CODES] /* extra bits for each distance code */ + = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ + = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + +local const uch bl_order[BL_CODES] + = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +#define Buf_size (8 * 2*sizeof(char)) +/* Number of bits used within bi_buf. (bi_buf might be implemented on + * more than 16 bits on some systems.) + */ + +/* =========================================================================== + * Local data. These are initialized only once. + */ + +#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ + +#if defined(GEN_TREES_H) || !defined(STDC) +/* non ANSI compilers may not accept trees.h */ + +local ct_data static_ltree[L_CODES+2]; +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + +local ct_data static_dtree[D_CODES]; +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + +uch _dist_code[DIST_CODE_LEN]; +/* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + +uch _length_code[MAX_MATCH-MIN_MATCH+1]; +/* length code for each normalized match length (0 == MIN_MATCH) */ + +local int base_length[LENGTH_CODES]; +/* First normalized length for each code (0 = MIN_MATCH) */ + +local int base_dist[D_CODES]; +/* First normalized distance for each code (0 = distance of 1) */ + +#else +# include "trees.h" +#endif /* GEN_TREES_H */ + +struct static_tree_desc_s { + const ct_data *static_tree; /* static tree or NULL */ + const intf *extra_bits; /* extra bits for each code or NULL */ + int extra_base; /* base index for extra_bits */ + int elems; /* max number of elements in the tree */ + int max_length; /* max bit length for the codes */ +}; + +local static_tree_desc static_l_desc = +{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; + +local static_tree_desc static_d_desc = +{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; + +local static_tree_desc static_bl_desc = +{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; + +/* =========================================================================== + * Local (static) routines in this file. + */ + +local void tr_static_init OF((void)); +local void init_block OF((deflate_state *s)); +local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); +local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); +local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); +local void build_tree OF((deflate_state *s, tree_desc *desc)); +local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local int build_bl_tree OF((deflate_state *s)); +local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, + int blcodes)); +local void compress_block OF((deflate_state *s, ct_data *ltree, + ct_data *dtree)); +local void set_data_type OF((deflate_state *s)); +local unsigned bi_reverse OF((unsigned value, int length)); +local void bi_windup OF((deflate_state *s)); +local void bi_flush OF((deflate_state *s)); +local void copy_block OF((deflate_state *s, charf *buf, unsigned len, + int header)); + +#ifdef GEN_TREES_H +local void gen_trees_header OF((void)); +#endif + +#ifndef DEBUG +# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) + /* Send a code of the given tree. c and tree must not have side effects */ + +#else /* DEBUG */ +# define send_code(s, c, tree) \ + { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ + send_bits(s, tree[c].Code, tree[c].Len); } +#endif + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +#define put_short(s, w) { \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ +} + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +#ifdef DEBUG +local void send_bits OF((deflate_state *s, int value, int length)); + +local void send_bits(s, value, length) + deflate_state *s; + int value; /* value to send */ + int length; /* number of bits */ +{ + Tracevv((stderr," l %2d v %4x ", length, value)); + Assert(length > 0 && length <= 15, "invalid length"); + s->bits_sent += (ulg)length; + + /* If not enough room in bi_buf, use (valid) bits from bi_buf and + * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + * unused bits in value. + */ + if (s->bi_valid > (int)Buf_size - length) { + s->bi_buf |= (ush)(value << s->bi_valid); /*MAB cast to ush */ + put_short(s, s->bi_buf); + s->bi_buf = (ush)((ush)value >> ((int)Buf_size - s->bi_valid)); /*MAB cast to int */ + s->bi_valid += length - (int)Buf_size; /*MAB cast to int */ + } else { + s->bi_buf |= (ush)(value << s->bi_valid); /*MAB cast to ush */ + s->bi_valid += length; + } +} +#else /* !DEBUG */ + +/*MAB: ORIGINAL, with warnings demanding castings. + +#define send_bits(s, value, length) \ +{ int len = length;\ + if (s->bi_valid > (int)Buf_size - len) {\ + int val = value;\ + s->bi_buf |= (val << s->bi_valid);\ + put_short(s, s->bi_buf);\ + s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ + s->bi_valid += len - Buf_size;\ + } else {\ + s->bi_buf |= (value) << s->bi_valid;\ + s->bi_valid += len;\ + }\ +} +*/ + + +/*MAB: modified */ +#define send_bits(s, value, length) \ +{ int len = (int)length;/*MAB casts*/\ + if (s->bi_valid > (int)Buf_size - len) {\ + int val = (int)value;/*MAB casts*/\ + s->bi_buf = (ush)(s->bi_buf | (val << s->bi_valid));/*MAB: Cast to silence compiler, see [1] above */\ + put_short(s, s->bi_buf);\ + s->bi_buf = (ush) ((ush)val >> ((int)Buf_size - s->bi_valid));/*MAB: Cast to silence compiler */\ + s->bi_valid += (int)(len - (int)Buf_size);/*MAB casts*/\ + } else {\ + s->bi_buf = (ush) (s->bi_buf | ((value) << s->bi_valid));/*MAB: Cast to silence compiler, see [2] above */\ + s->bi_valid += len;\ + }\ +} + +#endif /* DEBUG */ + +/*MAB: + +FUNCTION USED TO TEST THE CHANGES ABOVE + +[1] original: + s->bi_buf |= (ush)(val << s->bi_valid);\ + +[2] original: + s->bi_buf |= (ush) ((value) << s->bi_valid);\ +*/ + +#if 0 +static void send_bits(deflate_state *s, int value, int length) +{ int len = length;\ + if (s->bi_valid > (int)Buf_size - len) {\ + int val = value;\ + s->bi_buf = (ush)(s->bi_buf | (val << s->bi_valid));/*MAB: Cast to silence compiler, see [1] above */\ + put_short(s, s->bi_buf);\ + s->bi_buf = (ush) ((ush)val >> (Buf_size - s->bi_valid));/*MAB: Cast to silence compiler */\ + s->bi_valid += len - Buf_size;\ + } else {\ + s->bi_buf = (ush) (s->bi_buf | ((value) << s->bi_valid));/*MAB: Cast to silence compiler, see [2] above */\ + s->bi_valid += len;\ + }\ +} +#endif + + +/* the arguments must not have side effects */ + +/* =========================================================================== + * Initialize the various 'constant' tables. + */ +local void tr_static_init(void) +{ +#if defined(GEN_TREES_H) || !defined(STDC) + static int static_init_done = 0; + int n; /* iterates over tree elements */ + int bits; /* bit counter */ + int length; /* length value */ + int code; /* code value */ + int dist; /* distance index */ + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + if (static_init_done) return; + + /* For some embedded targets, global variables are not initialized: */ + static_l_desc.static_tree = static_ltree; + static_l_desc.extra_bits = extra_lbits; + static_d_desc.static_tree = static_dtree; + static_d_desc.extra_bits = extra_dbits; + static_bl_desc.extra_bits = extra_blbits; + + /* Initialize the mapping length (0..255) -> length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES-1; code++) { + base_length[code] = length; + for (n = 0; n < (1< dist code (0..29) */ + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ + for ( ; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + _dist_code[256 + dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + n = 0; + while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; + while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; + while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; + while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n].Len = 5; + static_dtree[n].Code = bi_reverse((unsigned)n, 5); + } + static_init_done = 1; + +# ifdef GEN_TREES_H + gen_trees_header(); +# endif +#endif /* defined(GEN_TREES_H) || !defined(STDC) */ +} + +/* =========================================================================== + * Genererate the file trees.h describing the static trees. + */ +#ifdef GEN_TREES_H +# ifndef DEBUG +# include +# endif + +# define SEPARATOR(i, last, width) \ + ((i) == (last)? "\n};\n\n" : \ + ((i) % (width) == (width)-1 ? ",\n" : ", ")) + +void gen_trees_header() +{ + FILE *header = fopen("trees.h", "w"); + int i; + + Assert (header != NULL, "Can't open trees.h"); + fprintf(header, + "/* header created automatically with -DGEN_TREES_H */\n\n"); + + fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); + for (i = 0; i < L_CODES+2; i++) { + fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, + static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); + } + + fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, + static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); + } + + fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n"); + for (i = 0; i < DIST_CODE_LEN; i++) { + fprintf(header, "%2u%s", _dist_code[i], + SEPARATOR(i, DIST_CODE_LEN-1, 20)); + } + + fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); + for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { + fprintf(header, "%2u%s", _length_code[i], + SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); + } + + fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); + for (i = 0; i < LENGTH_CODES; i++) { + fprintf(header, "%1u%s", base_length[i], + SEPARATOR(i, LENGTH_CODES-1, 20)); + } + + fprintf(header, "local const int base_dist[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "%5u%s", base_dist[i], + SEPARATOR(i, D_CODES-1, 10)); + } + + fclose(header); +} +#endif /* GEN_TREES_H */ + +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +void _tr_init(deflate_state *s) +{ + tr_static_init(); + + s->l_desc.dyn_tree = s->dyn_ltree; + s->l_desc.stat_desc = &static_l_desc; + + s->d_desc.dyn_tree = s->dyn_dtree; + s->d_desc.stat_desc = &static_d_desc; + + s->bl_desc.dyn_tree = s->bl_tree; + s->bl_desc.stat_desc = &static_bl_desc; + + s->bi_buf = 0; + s->bi_valid = 0; + s->last_eob_len = 8; /* enough lookahead for inflate */ +#ifdef DEBUG + s->compressed_len = 0L; + s->bits_sent = 0L; +#endif + + /* Initialize the first block of the first file: */ + init_block(s); +} + +/* =========================================================================== + * Initialize a new block. + */ +local void init_block(deflate_state *s) +{ + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->last_lit = s->matches = 0; +} + +#define SMALLEST 1 +/* Index within the heap array of least frequent node in the Huffman tree */ + + +/* =========================================================================== + * Remove the smallest element from the heap and recreate the heap with + * one less element. Updates heap and heap_len. + */ +#define pqremove(s, tree, top) \ +{\ + top = s->heap[SMALLEST]; \ + s->heap[SMALLEST] = s->heap[s->heap_len--]; \ + pqdownheap(s, tree, SMALLEST); \ +} + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +#define smaller(tree, n, m, depth) \ + (tree[n].Freq < tree[m].Freq || \ + (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +local void pqdownheap(deflate_state *s, ct_data *tree, int k) + + /* the tree to restore */ + /* node to move down */ +{ + int v = s->heap[k]; + int j = k << 1; /* left son of k */ + while (j <= s->heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s->heap_len && + smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s->heap[j], s->depth)) break; + + /* Exchange v with the smallest son */ + s->heap[k] = s->heap[j]; k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s->heap[k] = v; +} + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +local void gen_bitlen(deflate_state *s, tree_desc *desc) + + /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + int max_code = desc->max_code; + const ct_data *stree = desc->stat_desc->static_tree; + const intf *extra = desc->stat_desc->extra_bits; + int base = desc->stat_desc->extra_base; + int max_length = desc->stat_desc->max_length; + int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + int bits; /* bit length */ + int xbits; /* extra bits */ + ush f; /* frequency */ + int overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ + + for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + n = s->heap[h]; + bits = tree[tree[n].Dad].Len + 1; + if (bits > max_length) bits = max_length, overflow++; + tree[n].Len = (ush)bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) continue; /* not a leaf node */ + + s->bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n].Freq; + s->opt_len += (ulg)f * (ulg)(bits + xbits); /*MAB cast, (ulg)(bits + xbits) */ + if (stree) s->static_len += (ulg)f * (ulg)(stree[n].Len + xbits); /*MAB cast */ + } + if (overflow == 0) return; + + Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length-1; + while (s->bl_count[bits] == 0) bits--; + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits+1] = (ush)(s->bl_count[bits+1] + 2); /* move one overflow item as its brother */ /*MAB cast and expand += */ + s->bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits != 0; bits--) { + n = s->bl_count[bits]; + while (n != 0) { + m = s->heap[--h]; + if (m > max_code) continue; + if ((unsigned) tree[m].Len != (unsigned) bits) { + Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s->opt_len += (long unsigned)( /*MAB cast */ + ((long)bits - (long)tree[m].Len) + *(long)tree[m].Freq + ); + tree[m].Len = (ush)bits; + } + n--; + } + } +} + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +local void gen_codes (ct_data *tree, int max_code, ushf *bl_count) + /* the tree to decorate */ + /* largest code with non zero frequency */ + /* number of codes at each bit length */ +{ + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + ush code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (ush) ((code + bl_count[bits-1]) << 1); /*MAB: Casting to silence compiler */ + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; + const ct_data *stree = desc->stat_desc->static_tree; + int elems = desc->stat_desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s->heap_len = 0, s->heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n].Freq != 0) { + s->heap[++(s->heap_len)] = max_code = n; + s->depth[n] = 0; + } else { + tree[n].Len = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s->heap_len < 2) { + node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); + tree[node].Freq = 1; + s->depth[node] = 0; + s->opt_len--; if (stree) s->static_len -= stree[node].Len; + /* node is 0 or 1 so it does not have extra bits */ + } + desc->max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + pqremove(s, tree, n); /* n = node of least frequency */ + m = s->heap[SMALLEST]; /* m = node of next least frequency */ + + s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ + s->heap[--(s->heap_max)] = m; + + /* Create a new node father of n and m */ + tree[node].Freq = (ush) (tree[n].Freq + tree[m].Freq); /*MAB: Casting to silence compiler */ + s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? + s->depth[n] : s->depth[m]) + 1); + tree[n].Dad = tree[m].Dad = (ush)node; +#ifdef DUMP_BL_TREE + if (tree == s->bl_tree) { + fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", + node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); + } +#endif + /* and insert the new node in the heap */ + s->heap[SMALLEST] = node++; + pqdownheap(s, tree, SMALLEST); + + } while (s->heap_len >= 2); + + s->heap[--(s->heap_max)] = s->heap[SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, (tree_desc *)desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes ((ct_data *)tree, max_code, s->bl_count); +} + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +local void scan_tree (deflate_state *s, ct_data *tree, int max_code) + + /* the tree to be scanned */ + /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + if (nextlen == 0) max_count = 138, min_count = 3; + tree[max_code+1].Len = (ush)0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + #if 0 + s->bl_tree[curlen].Freq += count; + #else + /*MAB: This modification and casting to silence compiler */ + s->bl_tree[curlen].Freq = (ush) (s->bl_tree[curlen].Freq + count); + #endif + + } else if (curlen != 0) { + if (curlen != prevlen) s->bl_tree[curlen].Freq++; + s->bl_tree[REP_3_6].Freq++; + } else if (count <= 10) { + s->bl_tree[REPZ_3_10].Freq++; + } else { + s->bl_tree[REPZ_11_138].Freq++; + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +local void send_tree (deflate_state *s, ct_data *tree, int max_code) + + /* the tree to be scanned */ + /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen == 0) max_count = 138, min_count = 3; + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { send_code(s, curlen, s->bl_tree); } while (--count != 0); + + } else if (curlen != 0) { + if (curlen != prevlen) { + send_code(s, curlen, s->bl_tree); count--; + } + Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + + } else { + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +local int build_bl_tree(deflate_state *s) +{ + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); + scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, (tree_desc *)(&(s->bl_desc))); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; + } + /* Update opt_len to include the bit length tree and counts */ + s->opt_len += (long unsigned)(3*(max_blindex+1) + 5 + 5 + 4); /*MAB casts */ + Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + s->opt_len, s->static_len)); + + return max_blindex; +} + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +local void send_all_trees(deflate_state *s, int lcodes, int dcodes, int blcodes) + + /* number of codes for each tree */ +{ + int rank; /* index in bl_order */ + + Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + "too many codes"); + Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes-1, 5); + send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); + } + Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ + Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +} + +/* =========================================================================== + * Send a stored block + */ +void _tr_stored_block(deflate_state *s, charf *buf, ulg stored_len, int eof) + + /* input block */ + /* length of input block */ + /* true if this is the last block for a file */ +{ + send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */ +#ifdef DEBUG + s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; + s->compressed_len += (stored_len + 4) << 3; +#endif + copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ +} + +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + * The current inflate code requires 9 bits of lookahead. If the + * last two codes for the previous block (real code plus EOB) were coded + * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode + * the last real code. In this case we send two empty static blocks instead + * of one. (There are no problems if the previous block is stored or fixed.) + * To simplify the code, we assume the worst case of last real code encoded + * on one bit only. + */ +void _tr_align(deflate_state *s) +{ + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ +#endif + bi_flush(s); + /* Of the 10 bits for the empty block, we have already sent + * (10 - bi_valid) bits. The lookahead for the last real code (before + * the EOB of the previous block) was thus at least one plus the length + * of the EOB plus what we have just sent of the empty static block. + */ + if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; +#endif + bi_flush(s); + } + s->last_eob_len = 7; +} + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ +void _tr_flush_block(deflate_state *s, charf *buf, ulg stored_len, int eof) + + /* input block, or NULL if too old */ + /* length of input block */ + /* true if this is the last block for a file */ +{ + ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s->level > 0) { + + /* Check if the file is binary or text */ + if (stored_len > 0 && s->strm->data_type == Z_UNKNOWN) + set_data_type(s); + + /* Construct the literal and distance trees */ + build_tree(s, (tree_desc *)(&(s->l_desc))); + Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + + build_tree(s, (tree_desc *)(&(s->d_desc))); + Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute the block lengths in bytes. */ + opt_lenb = (s->opt_len+3+7)>>3; + static_lenb = (s->static_len+3+7)>>3; + + Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + s->last_lit)); + + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + + } else { + Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + +#ifdef FORCE_STORED + if (buf != (char*)0) { /* force stored block */ +#else + if (stored_len+4 <= opt_lenb && buf != (char*)0) { + /* 4: two words for the lengths */ +#endif + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, eof); + +#ifdef FORCE_STATIC + } else if (static_lenb >= 0) { /* force static trees */ +#else + } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { +#endif + send_bits(s, (STATIC_TREES<<1)+eof, 3); + compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->static_len; +#endif + } else { + send_bits(s, (DYN_TREES<<1)+eof, 3); + send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, + max_blindex+1); + compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->opt_len; +#endif + } + Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (eof) { + bi_windup(s); +#ifdef DEBUG + s->compressed_len += 7; /* align on byte boundary */ +#endif + } + Tracev((stderr,"\ncomprlen %lu(%lu) ", (unsigned long) (s->compressed_len>>3), /*MAB casts to ul */ + (unsigned long) (s->compressed_len-7ul*(unsigned long)eof))); /*MAB casts to ul */ +} + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +int _tr_tally (deflate_state *s, unsigned int dist, unsigned int lc) + + /* distance of matched string */ + /* match length-MIN_MATCH or unmatched char (if dist==0) */ +{ + s->d_buf[s->last_lit] = (ush)dist; + s->l_buf[s->last_lit++] = (uch)lc; + if (dist == 0) { + /* lc is the unmatched char */ + s->dyn_ltree[lc].Freq++; + } else { + s->matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + Assert((ush)dist < (ush)MAX_DIST(s) && + (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; + s->dyn_dtree[d_code(dist)].Freq++; + } + +#ifdef TRUNCATE_BLOCK + /* Try to guess if it is profitable to stop the current block here */ + if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { + /* Compute an upper bound for the compressed length */ + ulg out_length = (ulg)s->last_lit*8L; + ulg in_length = (ulg)((long)s->strstart - s->block_start); + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (ulg)s->dyn_dtree[dcode].Freq * + (5L+extra_dbits[dcode]); + } + out_length >>= 3; + Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", + s->last_lit, in_length, out_length, + 100L - out_length*100L/in_length)); + if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; + } +#endif + return (s->last_lit == s->lit_bufsize-1); + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ +} + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +local void compress_block(deflate_state *s, ct_data *ltree, ct_data *dtree) + + /* literal tree */ + /* distance tree */ +{ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned lx = 0; /* running index in l_buf */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (s->last_lit != 0) do { + dist = s->d_buf[lx]; + lc = s->l_buf[lx++]; + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code+LITERALS+1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = (unsigned)(d_code(dist)); /*MAB casts */ + Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= (unsigned)(base_dist[code]); /*MAB casts */ + send_bits(s, (int)dist, extra); /* send the extra distance bits */ /*MAB cast with int for debug */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, + "pendingBuf overflow"); + + } while (lx < s->last_lit); + + send_code(s, END_BLOCK, ltree); + s->last_eob_len = ltree[END_BLOCK].Len; +} + +/* =========================================================================== + * Set the data type to BINARY or TEXT, using a crude approximation: + * set it to Z_TEXT if all symbols are either printable characters (33 to 255) + * or white spaces (9 to 13, or 32); or set it to Z_BINARY otherwise. + * IN assertion: the fields Freq of dyn_ltree are set. + */ +local void set_data_type(deflate_state *s) +{ + int n; + + for (n = 0; n < 9; n++) + if (s->dyn_ltree[n].Freq != 0) + break; + if (n == 9) + for (n = 14; n < 32; n++) + if (s->dyn_ltree[n].Freq != 0) + break; + s->strm->data_type = (n == 32) ? Z_TEXT : Z_BINARY; +} + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +local unsigned bi_reverse(unsigned int code, int len) + /* the value to invert */ + /* its bit length */ +{ + register unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; +} + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +local void bi_flush(deflate_state *s) +{ + if (s->bi_valid == 16) { + put_short(s, s->bi_buf); + s->bi_buf = 0; + s->bi_valid = 0; + } else if (s->bi_valid >= 8) { + put_byte(s, (Byte)s->bi_buf); + s->bi_buf >>= 8; + s->bi_valid -= 8; + } +} + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +local void bi_windup(deflate_state *s) +{ + if (s->bi_valid > 8) { + put_short(s, s->bi_buf); + } else if (s->bi_valid > 0) { + put_byte(s, (Byte)s->bi_buf); + } + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef DEBUG + s->bits_sent = (s->bits_sent+7ul) & ~7ul; /*MAB add ul */ +#endif +} + +/* =========================================================================== + * Copy a stored block, storing first the length and its + * one's complement if requested. + */ +local void copy_block(deflate_state *s, charf *buf, unsigned int len, int header) + + /* the input data */ + /* its length */ + /* true if block header must be written */ +{ + bi_windup(s); /* align on byte boundary */ + s->last_eob_len = 8; /* enough lookahead for inflate */ + + if (header) { + put_short(s, (ush)len); + put_short(s, (ush)~len); +#ifdef DEBUG + s->bits_sent += 2*16; +#endif + } +#ifdef DEBUG + s->bits_sent += (ulg)len<<3; +#endif + while (len--) { + put_byte(s, *buf++); + } +} diff --git a/DroidFish/jni/gtb/compression/zlib/trees.h b/DroidFish/jni/gtb/compression/zlib/trees.h new file mode 100644 index 0000000..72facf9 --- /dev/null +++ b/DroidFish/jni/gtb/compression/zlib/trees.h @@ -0,0 +1,128 @@ +/* header created automatically with -DGEN_TREES_H */ + +local const ct_data static_ltree[L_CODES+2] = { +{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, +{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, +{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, +{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, +{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, +{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, +{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, +{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, +{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, +{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, +{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, +{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, +{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, +{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, +{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, +{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, +{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, +{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, +{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, +{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, +{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, +{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, +{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, +{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, +{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, +{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, +{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, +{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, +{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, +{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, +{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, +{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, +{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, +{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, +{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, +{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, +{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, +{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, +{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, +{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, +{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, +{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, +{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, +{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, +{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, +{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, +{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, +{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, +{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, +{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, +{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, +{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, +{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, +{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, +{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, +{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, +{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, +{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} +}; + +local const ct_data static_dtree[D_CODES] = { +{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, +{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, +{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, +{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, +{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, +{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} +}; + +const uch _dist_code[DIST_CODE_LEN] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, +10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, +18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +}; + +const uch _length_code[MAX_MATCH-MIN_MATCH+1]= { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, +13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, +17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, +19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, +21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, +22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 +}; + +local const int base_length[LENGTH_CODES] = { +0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, +64, 80, 96, 112, 128, 160, 192, 224, 0 +}; + +local const int base_dist[D_CODES] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 +}; + diff --git a/DroidFish/jni/gtb/compression/zlib/uncompr.c b/DroidFish/jni/gtb/compression/zlib/uncompr.c new file mode 100644 index 0000000..953fbd6 --- /dev/null +++ b/DroidFish/jni/gtb/compression/zlib/uncompr.c @@ -0,0 +1,57 @@ +/* uncompr.c -- decompress a memory buffer + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted. +*/ +int ZEXPORT uncompress (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen) +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; + + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + + err = inflateInit(&stream); + if (err != Z_OK) return err; + + err = inflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + inflateEnd(&stream); + if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) + return Z_DATA_ERROR; + return err; + } + *destLen = stream.total_out; + + err = inflateEnd(&stream); + return err; +} diff --git a/DroidFish/jni/gtb/compression/zlib/zcompress.c b/DroidFish/jni/gtb/compression/zlib/zcompress.c new file mode 100644 index 0000000..425c56a --- /dev/null +++ b/DroidFish/jni/gtb/compression/zlib/zcompress.c @@ -0,0 +1,69 @@ +/* compress.c -- compress a memory buffer + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least 0.1% larger than sourceLen plus + 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ +int ZEXPORT compress2 (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, int level) +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; +#ifdef MAXSEG_64K + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; +#endif + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + stream.opaque = (voidpf)0; + + err = deflateInit(&stream, level); + if (err != Z_OK) return err; + + err = deflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + deflateEnd(&stream); + return err == Z_OK ? Z_BUF_ERROR : err; + } + *destLen = stream.total_out; + + err = deflateEnd(&stream); + return err; +} + +/* =========================================================================== + */ +int ZEXPORT compress (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen) +{ + return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); +} + +/* =========================================================================== + If the default memLevel or windowBits for deflateInit() is changed, then + this function needs to be updated. + */ +uLong ZEXPORT compressBound (uLong sourceLen) +{ + return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11; +} diff --git a/DroidFish/jni/gtb/compression/zlib/zconf.h b/DroidFish/jni/gtb/compression/zlib/zconf.h new file mode 100644 index 0000000..03a9431 --- /dev/null +++ b/DroidFish/jni/gtb/compression/zlib/zconf.h @@ -0,0 +1,332 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflateParams z_deflateParams +# define deflateBound z_deflateBound +# define deflatePrime z_deflatePrime +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateCopy z_inflateCopy +# define inflateReset z_inflateReset +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table +# define zError z_zError + +# define alloc_func z_alloc_func +# define free_func z_free_func +# define in_func z_in_func +# define out_func z_out_func +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ +# include /* for off_t */ +# include /* for SEEK_* and off_t */ +# ifdef VMS +# include /* for off_t */ +# endif +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(__OS400__) +# define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +# ifdef FAR +# undef FAR +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(deflateBound,"DEBND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(compressBound,"CMBND") +# pragma map(inflate_table,"INTABL") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/DroidFish/jni/gtb/compression/zlib/zconf.in.h b/DroidFish/jni/gtb/compression/zlib/zconf.in.h new file mode 100644 index 0000000..03a9431 --- /dev/null +++ b/DroidFish/jni/gtb/compression/zlib/zconf.in.h @@ -0,0 +1,332 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflateParams z_deflateParams +# define deflateBound z_deflateBound +# define deflatePrime z_deflatePrime +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateCopy z_inflateCopy +# define inflateReset z_inflateReset +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table +# define zError z_zError + +# define alloc_func z_alloc_func +# define free_func z_free_func +# define in_func z_in_func +# define out_func z_out_func +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ +# include /* for off_t */ +# include /* for SEEK_* and off_t */ +# ifdef VMS +# include /* for off_t */ +# endif +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(__OS400__) +# define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +# ifdef FAR +# undef FAR +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(deflateBound,"DEBND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(compressBound,"CMBND") +# pragma map(inflate_table,"INTABL") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/DroidFish/jni/gtb/compression/zlib/zlib.h b/DroidFish/jni/gtb/compression/zlib/zlib.h new file mode 100644 index 0000000..0228179 --- /dev/null +++ b/DroidFish/jni/gtb/compression/zlib/zlib.h @@ -0,0 +1,1357 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.3, July 18th, 2005 + + Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.3" +#define ZLIB_VERNUM 0x1230 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. + + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip streams in memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative + * values are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field (though see inflate()) */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + This check is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to Z_NULL, deflateInit updates them to + use default allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce some + output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumualte before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In particular + avail_in is zero after the call if enough output space has been provided + before the call.) Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + the value returned by deflateBound (see below). If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not + fatal, and deflate() can be called again with more input and more output + space to continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there + is no more input data or no more space in the output buffer (see below + about the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, + Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() stop + if and when it gets to the next deflate block boundary. When decoding the + zlib or gzip format, this will cause inflate() to return immediately after + the header and before the first block. When doing a raw inflate, inflate() + will go ahead and process the first block, and will return when it gets to + the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 + if inflate() is currently decoding the last block in the deflate stream, + plus 128 if inflate() returned immediately after decoding an end-of-block + code or decoding the complete header up to just before the first byte of the + deflate stream. The end-of-block will not be indicated until all of the + uncompressed data from that block has been written to strm->next_out. The + number of unused bits may in general be greater than seven, except when + bit 7 of data_type is set, in which case the number of unused bits will be + less than eight. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster approach + may be used for the single inflate() call. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the only effect of the flush parameter in this implementation + is on the return value of inflate(), as noted below, or when it returns early + because Z_BLOCK is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the adler32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the adler32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() will decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically. Any information + contained in the gzip header is not retained, so applications that need that + information should instead use raw inflate, see inflateInit2() below, or + inflateBack() and perform their own processing of the gzip header and + trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may then + call inflateSync() to look for a good compression block if a partial recovery + of the data is desired. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute an adler32 check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), + no header crc, and the operating system will be set to 255 (unknown). If a + gzip stream is being written, strm->adler is a crc32 instead of an adler32. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as + Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy + parameter only affects the compression ratio but not the correctness of the + compressed output even if it is not set appropriately. Z_FIXED prevents the + use of dynamic Huffman codes, allowing for a simpler decoder for special + applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid + method). msg is set to null if there is no error message. deflateInit2 does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size in + deflate or deflate2. Thus the strings most likely to be useful should be + put at the end of the dictionary, not at the front. In addition, the + current implementation of deflate will use at most the window size minus + 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + adler32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different + strategy. If the compression level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. +*/ + +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() + or deflateInit2(). This would be used to allocate an output buffer + for deflation in a single pass, and so would be called before deflate(). +*/ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the + bits leftover from a previous deflate stream when appending to it. As such, + this function can only be used for raw deflate, and must be used before the + first deflate() call after a deflateInit2() or deflateReset(). bits must be + less than or equal to 16, and that many of the least significant bits of + value will be inserted in the output. + + deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is + a crc32 instead of an adler32. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg + is set to null if there is no error message. inflateInit2 does not perform + any decompression apart from reading the zlib header if present: this will + be done by inflate(). (So next_in and avail_in may be modified, but next_out + and avail_out are unchanged.) +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called + immediately after inflateInit2() or inflateReset() and before any call of + inflate() to set the dictionary. The application must insure that the + dictionary that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK can be used to + force inflate() to return immediately after header processing is complete + and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When + any of extra, name, or comment are not Z_NULL and the respective field is + not present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the paramaters are invalid, Z_MEM_ERROR if the internal state could not + be allocated, or Z_VERSION_ERROR if the version of the library does not + match the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is more efficient than inflate() for + file i/o applications in that it avoids copying between the output and the + sliding window by simply making the window itself the output buffer. This + function trusts the application to not change the output buffer passed by + the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free + the allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects + only the raw deflate stream to decompress. This is different from the + normal behavior of inflate(), which expects either a zlib or gzip header and + trailer around the deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero--buf is ignored in that + case--and inflateBack() will return a buffer error. inflateBack() will call + out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() + should return zero on success, or non-zero on failure. If out() returns + non-zero, inflateBack() will return with an error. Neither in() nor out() + are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format + error in the deflate stream (in which case strm->msg is set to indicate the + nature of the error), or Z_STREAM_ERROR if the stream was not properly + initialized. In the case of Z_BUF_ERROR, an input or output error can be + distinguished using strm->next_in which will be Z_NULL only if in() returned + an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to + out() returning non-zero. (in() will always be called before out(), so + strm->next_in is assured to be defined if out() returns non-zero.) Note + that inflateBack() cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the + basic stream-oriented functions. To simplify the interface, some + default options are assumed (compression level and memory usage, + standard memory allocation functions). The source code of these + utility functions can easily be modified if you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be at least the value returned + by compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + This function can be used to compress a whole file at once if the + input file is mmap'ed. + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before + a compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. +*/ + + +typedef voidp gzFile; + +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); +/* + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb") but can also include a compression level + ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for + Huffman only compression as in "wb1h", or 'R' for run-length encoding + as in "wb1R". (See the description of deflateInit2 for more information + about the strategy parameter.) + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). */ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen() associates a gzFile with the file descriptor fd. File + descriptors are obtained from calls like open, dup, creat, pipe or + fileno (in the file has been previously opened with fopen). + The mode parameter is as in gzopen. + The next call of gzclose on the returned gzFile will also close the + file descriptor fd, just like fclose(fdopen(fd), mode) closes the file + descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). + gzdopen returns NULL if there was insufficient memory to allocate + the (de)compression state. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. + If the input file was not in gzip format, gzread copies the given number + of bytes into the buffer. + gzread returns the number of uncompressed bytes actually read (0 for + end of file, -1 for error). */ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes actually written + (0 in case of error). +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). The number of + uncompressed bytes written is limited to 4095. The caller should assure that + this limit is not exceeded. If it is exceeded, then gzprintf() will return + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf() + because the secure snprintf() or vsnprintf() functions were not available. +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or + a newline character is read and transferred to buf, or an end-of-file + condition is encountered. The string is then terminated with a null + character. + gzgets returns buf, or Z_NULL in case of error. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read again later. + Only one character of push-back is allowed. gzungetc() returns the + character pushed, or -1 on failure. gzungetc() will fail if a + character has been pushed but not read yet, or if c is -1. The pushed + character will be discarded if the stream is repositioned with gzseek() + or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. The return value is the zlib + error number (see function gzerror below). gzflush returns Z_OK if + the flush parameter is Z_FINISH and all output could be flushed. + gzflush should be called only when strictly necessary because it can + degrade compression. +*/ + +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); +/* + Sets the starting position for the next gzread or gzwrite on the + given compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); +/* + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns 1 if file is being read directly without decompression, otherwise + zero. +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. The return value is the zlib + error number (see function gzerror below). +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the + compression library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); +/* + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. If buf is NULL, this function returns the required initial + value for the for the crc. Pre- and post-conditioning (one's complement) is + performed within this function so it shouldn't be done by the application. + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + +/* + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, sizeof(z_stream)) + + +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; /* hack for buggy compilers */ +#endif + +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/DroidFish/jni/gtb/compression/zlib/zutil.c b/DroidFish/jni/gtb/compression/zlib/zutil.c new file mode 100644 index 0000000..ff4d75c --- /dev/null +++ b/DroidFish/jni/gtb/compression/zlib/zutil.c @@ -0,0 +1,354 @@ +/* zutil.c -- target dependent utility functions for the compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zutil.h" + +#ifndef NO_DUMMY_DECL +struct internal_state {int dummy;}; /* for buggy compilers */ +#endif + +const char * const z_errmsg[10] = { +"need dictionary", /* Z_NEED_DICT 2 */ +"stream end", /* Z_STREAM_END 1 */ +"", /* Z_OK 0 */ +"file error", /* Z_ERRNO (-1) */ +"stream error", /* Z_STREAM_ERROR (-2) */ +"data error", /* Z_DATA_ERROR (-3) */ +"insufficient memory", /* Z_MEM_ERROR (-4) */ +"buffer error", /* Z_BUF_ERROR (-5) */ +"incompatible version",/* Z_VERSION_ERROR (-6) */ +""}; + + +const char * ZEXPORT zlibVersion(void) +{ + return ZLIB_VERSION; +} + +uLong ZEXPORT zlibCompileFlags(void) +{ + #if 1 + size_t uInt_size; + size_t uLong_size; + size_t voidpf_size; + size_t z_off_t_size; + #endif + + uLong flags; + flags = 0; + +/*MAB: The following #if was introduced to silence intel compiler */ +#if 1 + uInt_size = sizeof(uInt); + uLong_size = sizeof(uLong); + voidpf_size = sizeof(voidpf); + z_off_t_size = sizeof(z_off_t); + + switch (uInt_size) { + case 2: break; + case 4: flags += 1; break; + case 8: flags += 2; break; + default: flags += 3; + } + switch (uLong_size) { + case 2: break; + case 4: flags += 1 << 2; break; + case 8: flags += 2 << 2; break; + default: flags += 3 << 2; + } + switch (voidpf_size) { + case 2: break; + case 4: flags += 1 << 4; break; + case 8: flags += 2 << 4; break; + default: flags += 3 << 4; + } + switch (z_off_t_size) { + case 2: break; + case 4: flags += 1 << 6; break; + case 8: flags += 2 << 6; break; + default: flags += 3 << 6; + } +#else + switch (sizeof(uInt)) { + case 2: break; + case 4: flags += 1; break; + case 8: flags += 2; break; + default: flags += 3; + } + + switch (sizeof(uLong)) { + case 2: break; + case 4: flags += 1 << 2; break; + case 8: flags += 2 << 2; break; + default: flags += 3 << 2; + } + switch (sizeof(voidpf)) { + case 2: break; + case 4: flags += 1 << 4; break; + case 8: flags += 2 << 4; break; + default: flags += 3 << 4; + } + switch (sizeof(z_off_t)) { + case 2: break; + case 4: flags += 1 << 6; break; + case 8: flags += 2 << 6; break; + default: flags += 3 << 6; + } +#endif + +#ifdef DEBUG + flags += 1 << 8; +#endif +#if defined(ASMV) || defined(ASMINF) + flags += 1 << 9; +#endif +#ifdef ZLIB_WINAPI + flags += 1 << 10; +#endif +#ifdef BUILDFIXED + flags += 1 << 12; +#endif +#ifdef DYNAMIC_CRC_TABLE + flags += 1 << 13; +#endif +#ifdef NO_GZCOMPRESS + flags += 1L << 16; +#endif +#ifdef NO_GZIP + flags += 1L << 17; +#endif +#ifdef PKZIP_BUG_WORKAROUND + flags += 1L << 20; +#endif +#ifdef FASTEST + flags += 1L << 21; +#endif +#ifdef STDC +# ifdef NO_vsnprintf + flags += 1L << 25; +# ifdef HAS_vsprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_vsnprintf_void + flags += 1L << 26; +# endif +# endif +#else + flags += 1L << 24; +# ifdef NO_snprintf + flags += 1L << 25; +# ifdef HAS_sprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_snprintf_void + flags += 1L << 26; +# endif +# endif +#endif + return flags; +} + +#ifdef DEBUG + +# ifndef verbose +# define verbose 0 +# endif +int z_verbose = verbose; + +void z_error (m) + const char *m; /*MAB add const */ +{ + fprintf(stderr, "%s\n", m); + exit(1); +} +#endif + +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError(int err) +{ + return ERR_MSG(err); +} + +#if defined(_WIN32_WCE) + /* The Microsoft C Run-Time Library for Windows CE doesn't have + * errno. We define it as a global variable to simplify porting. + * Its value is always 0 and should not be used. + */ + int errno = 0; +#endif + +#ifndef HAVE_MEMCPY + +void zmemcpy(dest, source, len) + Bytef* dest; + const Bytef* source; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = *source++; /* ??? to be unrolled */ + } while (--len != 0); +} + +int zmemcmp(s1, s2, len) + const Bytef* s1; + const Bytef* s2; + uInt len; +{ + uInt j; + + for (j = 0; j < len; j++) { + if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; + } + return 0; +} + +void zmemzero(dest, len) + Bytef* dest; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); +} +#endif + + +#ifdef SYS16BIT + +#ifdef __TURBOC__ +/* Turbo C in 16-bit mode */ + +# define MY_ZCALLOC + +/* Turbo C malloc() does not allow dynamic allocation of 64K bytes + * and farmalloc(64K) returns a pointer with an offset of 8, so we + * must fix the pointer. Warning: the pointer must be put back to its + * original form in order to free it, use zcfree(). + */ + +#define MAX_PTR 10 +/* 10*64K = 640K */ + +local int next_ptr = 0; + +typedef struct ptr_table_s { + voidpf org_ptr; + voidpf new_ptr; +} ptr_table; + +local ptr_table table[MAX_PTR]; +/* This table is used to remember the original form of pointers + * to large buffers (64K). Such pointers are normalized with a zero offset. + * Since MSDOS is not a preemptive multitasking OS, this table is not + * protected from concurrent access. This hack doesn't work anyway on + * a protected system like OS/2. Use Microsoft C instead. + */ + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + voidpf buf = opaque; /* just to make some compilers happy */ + ulg bsize = (ulg)items*size; + + /* If we allocate less than 65520 bytes, we assume that farmalloc + * will return a usable pointer which doesn't have to be normalized. + */ + if (bsize < 65520L) { + buf = farmalloc(bsize); + if (*(ush*)&buf != 0) return buf; + } else { + buf = farmalloc(bsize + 16L); + } + if (buf == NULL || next_ptr >= MAX_PTR) return NULL; + table[next_ptr].org_ptr = buf; + + /* Normalize the pointer to seg:0 */ + *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; + *(ush*)&buf = 0; + table[next_ptr++].new_ptr = buf; + return buf; +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + int n; + if (*(ush*)&ptr != 0) { /* object < 64K */ + farfree(ptr); + return; + } + /* Find the original pointer */ + for (n = 0; n < next_ptr; n++) { + if (ptr != table[n].new_ptr) continue; + + farfree(table[n].org_ptr); + while (++n < next_ptr) { + table[n-1] = table[n]; + } + next_ptr--; + return; + } + ptr = opaque; /* just to make some compilers happy */ + Assert(0, "zcfree: ptr not found"); +} + +#endif /* __TURBOC__ */ + + +#ifdef M_I86 +/* Microsoft C in 16-bit mode */ + +# define MY_ZCALLOC + +#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) +# define _halloc halloc +# define _hfree hfree +#endif + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + return _halloc((long)items, size); +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + _hfree(ptr); +} + +#endif /* M_I86 */ + +#endif /* SYS16BIT */ + + +#ifndef MY_ZCALLOC /* Any system without a special alloc function */ + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern voidp calloc OF((uInt items, uInt size)); +extern void free OF((voidpf ptr)); +#endif + +voidpf zcalloc (voidpf opaque, unsigned int items, unsigned int size) +{ + if (opaque) items += size - size; /* make compiler happy */ + return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : + (voidpf)calloc(items, size); +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + free(ptr); + if (opaque) return; /* make compiler happy */ +} + +#endif /* MY_ZCALLOC */ diff --git a/DroidFish/jni/gtb/compression/zlib/zutil.h b/DroidFish/jni/gtb/compression/zlib/zutil.h new file mode 100644 index 0000000..53dc6cd --- /dev/null +++ b/DroidFish/jni/gtb/compression/zlib/zutil.h @@ -0,0 +1,269 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef ZUTIL_H +#define ZUTIL_H + +#define ZLIB_INTERNAL +#include "zlib.h" + +#ifdef STDC +# ifndef _WIN32_WCE +# include +# endif +# include +# include +#endif +#ifdef NO_ERRNO_H +# ifdef _WIN32_WCE + /* The Microsoft C Run-Time Library for Windows CE doesn't have + * errno. We define it as a global variable to simplify porting. + * Its value is always 0 and should not be used. We rename it to + * avoid conflict with other libraries that use the same workaround. + */ +# define errno z_errno +# endif + extern int errno; +#else +# ifndef _WIN32_WCE +# include +# endif +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = (char*)ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) +# define OS_CODE 0x00 +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include +# endif +#endif + +#ifdef AMIGA +# define OS_CODE 0x01 +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 0x02 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 0x05 +#endif + +#ifdef OS2 +# define OS_CODE 0x06 +# ifdef M_I86 + #include +# endif +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 0x07 +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +#endif + +#ifdef TOPS20 +# define OS_CODE 0x0a +#endif + +#ifdef WIN32 +# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ +# define OS_CODE 0x0b +# endif +#endif + +#ifdef __50SERIES /* Prime/PRIMOS */ +# define OS_CODE 0x0f +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) +# if defined(_WIN32_WCE) +# define fdopen(fd,mode) NULL /* No fdopen() */ +# ifndef _PTRDIFF_T_DEFINED + typedef int ptrdiff_t; +# define _PTRDIFF_T_DEFINED +# endif +# else +# define fdopen(fd,type) _fdopen(fd,type) +# endif +#endif + + /* common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#if defined(__CYGWIN__) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#ifndef HAVE_VSNPRINTF +# ifdef MSDOS + /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), + but for now we just assume it doesn't. */ +# define NO_vsnprintf +# endif +# ifdef __TURBOC__ +# define NO_vsnprintf +# endif +# ifdef WIN32 + /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ +# if !defined(vsnprintf) && !defined(NO_vsnprintf) +# define vsnprintf _vsnprintf +# endif +# endif +# ifdef __SASC +# define NO_vsnprintf +# endif +#endif +#ifdef VMS +# define NO_vsnprintf +#endif + +#if defined(pyr) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + extern void zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef DEBUG +# include + extern int z_verbose; + extern void z_error OF((const char *m)); /*MAB add const*/ +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + + +voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); +void zcfree OF((voidpf opaque, voidpf ptr)); + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +#endif /* ZUTIL_H */ diff --git a/DroidFish/jni/gtb/gtb-att.c b/DroidFish/jni/gtb/gtb-att.c new file mode 100644 index 0000000..6200164 --- /dev/null +++ b/DroidFish/jni/gtb/gtb-att.c @@ -0,0 +1,390 @@ +/* +This Software is distributed with the following X11 License, +sometimes also known as MIT license. + +Copyright (c) 2010 Miguel A. Ballicora + + 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. +*/ + +#include +#include +#include "gtb-att.h" + +#if 0 + +#include "mtypes.h" +#include "bool_t.h" +#include "maindef.h" + +#else + +/* mtypes.h */ + +typedef unsigned int SQUARE; +typedef unsigned char SQ_CONTENT; + +/* bool_t.h */ + +#if !defined(bool_t) +typedef int bool_t; +#endif + +#if !defined(TRUE) +#define TRUE ((bool_t)1) +#endif + +#if !defined(FALSE) +#define FALSE ((bool_t)0) +#endif + +/* maindef.h */ + +#define NOPIECE 0u +#define PAWN 1u +#define KNIGHT 2u +#define BISHOP 3u +#define ROOK 4u +#define QUEEN 5u +#define KING 6u +#define PIECE_MASK (KING|PAWN|KNIGHT|BISHOP|ROOK|QUEEN) + +/*Whites*/ +#define wK (KING | WHITES) +#define wP (PAWN | WHITES) +#define wN (KNIGHT | WHITES) +#define wB (BISHOP | WHITES) +#define wR (ROOK | WHITES) +#define wQ (QUEEN | WHITES) + +/*Blacks*/ +#define bK (KING | BLACKS) +#define bP (PAWN | BLACKS) +#define bN (KNIGHT | BLACKS) +#define bB (BISHOP | BLACKS) +#define bR (ROOK | BLACKS) +#define bQ (QUEEN | BLACKS) + +/*Bits that define color */ + +#define WHITES (1u<<6) +#define BLACKS (1u<<7) + +/*squares*/ +enum SQUARES { + A1,B1,C1,D1,E1,F1,G1,H1, + A2,B2,C2,D2,E2,F2,G2,H2, + A3,B3,C3,D3,E3,F3,G3,H3, + A4,B4,C4,D4,E4,F4,G4,H4, + A5,B5,C5,D5,E5,F5,G5,H5, + A6,B6,C6,D6,E6,F6,G6,H6, + A7,B7,C7,D7,E7,F7,G7,H7, + A8,B8,C8,D8,E8,F8,G8,H8, + NOSQUARE, + ERRSQUARE = 128 +}; +#endif + +/*----------------------------------------------------------------------*/ + +#ifndef NDEBUG +#define NDEBUG +#endif +#ifdef DEBUG +#undef NDEBUG +#endif +#include "assert.h" + +/*----------------------------------------------------------------------*/ + +/* global variables */ +uint64_t Reach [7] [64]; + +/* static variables */ +static unsigned char attmap [64] [64]; +static unsigned int attmsk [256]; + +/* static functions */ +static unsigned int mapx88 (unsigned int x); + +/* macros */ +#define BB_ISBITON(bb,bit) (0 != (((bb)>>(bit)) & U64(1))) + +#define map88(x) ( (x) + ((x)&070) ) +#define unmap88(x) ( ( (x) + ((x)& 07) ) >> 1 ) + +/*----------------------------------------------------------------------*/ + +static unsigned int +mapx88 (unsigned int x) +{ + return ((x & 070) << 1) | (x & 07); +} + + +void +attack_maps_init(void) +{ + int i; + unsigned int m, from, to; + unsigned int to88, fr88; + int diff; + + uint64_t rook, bishop, queen, knight, king; + + if (!reach_was_initialized()) { + printf ("Wrong initialization order of data\n"); + exit(EXIT_FAILURE); + } + + for (i = 0; i < 256; ++i) { + attmsk [i] = 0; + } + attmsk[wP] = 1 << 0; + attmsk[bP] = 1 << 1; + + attmsk[KNIGHT] = 1 << 2; + attmsk[wN] = 1 << 2; + attmsk[bN] = 1 << 2; + + attmsk[BISHOP] = 1 << 3; + attmsk[wB] = 1 << 3; + attmsk[bB] = 1 << 3; + + attmsk[ROOK ] = 1 << 4; + attmsk[wR] = 1 << 4; + attmsk[bR] = 1 << 4; + + attmsk[QUEEN ] = 1 << 5; + attmsk[wQ] = 1 << 5; + attmsk[bQ] = 1 << 5; + + attmsk[KING ] = 1 << 6; + attmsk[wK] = 1 << 6; + attmsk[bK] = 1 << 6; + + for (to = 0; to < 64; ++to) { + for (from = 0; from < 64; ++from) { + m = 0; + rook = Reach [ROOK] [from]; + bishop = Reach [BISHOP] [from]; + queen = Reach [QUEEN] [from]; + knight = Reach [KNIGHT] [from]; + king = Reach [KING] [from]; + + if (BB_ISBITON (knight, to)) { + m |= attmsk[wN]; + } + if (BB_ISBITON (king, to)) { + m |= attmsk[wK]; + } + if (BB_ISBITON (rook, to)) { + m |= attmsk[wR]; + } + if (BB_ISBITON (bishop, to)) { + m |= attmsk[wB]; + } + if (BB_ISBITON (queen, to)) { + m |= attmsk[wQ]; + } + + to88 = mapx88(to); + fr88 = mapx88(from); + diff = (int)to88 - (int)fr88; + + if (diff == 17 || diff == 15) { + m |= attmsk[wP]; + } + if (diff == -17 || diff == -15) { + m |= attmsk[bP]; + } + + attmap [to] [from] = (unsigned char) m; + } + } + +} + +bool_t +possible_attack(unsigned int from, unsigned int to, unsigned int piece) +{ + + assert (piece < 256); + assert (from < 64 && to < 64); + assert (reach_was_initialized()); + assert (attmsk [piece] != 0 || 0==fprintf(stderr, "PIECE=%d\n",piece) ); /* means piece has been considered */ + + return 0 != (attmap [to] [from] & attmsk [piece]); +} + +/* +| +| REACH ROUTINES +| +\*----------------------------------------------*/ + + +enum Key {REACH_INITIALIZED_KEY = 0x1313}; +static int reach_initialized_key = 0; + +bool_t +reach_was_initialized (void) +{ + return reach_initialized_key == REACH_INITIALIZED_KEY; +} + +void +reach_init (void) +{ + SQUARE buflist[64+1], *list; + SQ_CONTENT pc; + int stp_a [] = {15, -15 }; + int stp_b [] = {17, -17 }; + int STEP_A, STEP_B; + unsigned int side; + unsigned int index; + SQUARE sq, us; + + int s; + + for (pc = KNIGHT; pc < (KING+1); pc++) { + for (sq = 0; sq < 64; sq++) { + uint64_t bb = U64(0x0); + tolist_rev (U64(0x0), pc, sq, buflist); + for (list = buflist; *list != NOSQUARE; list++) { + bb |= U64(1) << *list; + } + Reach [pc] [sq] = bb; + } + } + + for (side = 0; side < 2; side++) { + index = 1u ^ side; + STEP_A = stp_a[side]; + STEP_B = stp_b[side]; + for (sq = 0; sq < 64; sq++) { + + int sq88 = (int)map88(sq); + uint64_t bb = U64(0x0); + + list = buflist; + + + s = sq88 + STEP_A; + if (0 == (s & 0x88)) { + us = (SQUARE)unmap88(s); + *list++ = us; + } + s = sq88 + STEP_B; + if (0 == (s & 0x88)) { + us = (SQUARE)unmap88(s); + *list++ = us; + } + *list = NOSQUARE; + + for (list = buflist; *list != NOSQUARE; list++) { + bb |= U64(1) << *list; + } + Reach [index] [sq] = bb; + } + } + reach_initialized_key = REACH_INITIALIZED_KEY; +} + +/*--------------------------------------------------------------------------------*/ + +static const int bstep[] = { 17, 15, -15, -17, 0}; +static const int rstep[] = { 1, 16, -1, -16, 0}; +static const int nstep[] = { 18, 33, 31, 14, -18, -33, -31, -14, 0}; +static const int kstep[] = { 1, 17, 16, 15, -1, -17, -16, -15, 0}; + +static const +int *psteparr[] = {NULL, NULL, /* NOPIECE & PAWN */ + nstep, bstep, rstep, kstep, kstep /* same for Q & K*/ + }; +static const +int pslider[] = {FALSE, FALSE, + FALSE, TRUE, TRUE, TRUE, FALSE + }; + +void +tolist_rev (uint64_t occ, SQ_CONTENT input_piece, SQUARE sq, SQUARE *list) +/* reversible moves from pieces. Output is a list of squares */ +{ + int direction; + unsigned int pc; + int s; + int from; + int step; + const int *steparr; + bool_t slider; + SQUARE us; + + assert (sq < 64); + + /* i.e. no pawn allowed as input */ + assert (input_piece == KNIGHT || input_piece == BISHOP || + input_piece == ROOK || input_piece == QUEEN || + input_piece == KING); + + from = (int)map88(sq); + + pc = input_piece & (PAWN|KNIGHT|BISHOP|ROOK|QUEEN|KING); + + steparr = psteparr [pc]; + slider = pslider [pc]; + + if (slider) { + + for (direction = 0; steparr[direction] != 0; direction++) { + step = steparr[direction]; + s = from + step; + while (0 == (s & 0x88)) { + us = (SQUARE)unmap88(s); + if (0 != (0x1u & (unsigned int)(occ >> us))) + break; + *list++ = us; + s += step; + } + } + + } else { + + for (direction = 0; steparr[direction] != 0; direction++) { + step = steparr[direction]; + s = from + step; + if (0 == (s & 0x88)) { + us = (SQUARE)unmap88(s); + if (0 == (0x1u & (unsigned int)(occ >> us))) { + *list++ = us; + } + } + } + } + + *list = NOSQUARE; + + return; +} + + + diff --git a/DroidFish/jni/gtb/gtb-att.h b/DroidFish/jni/gtb/gtb-att.h new file mode 100644 index 0000000..c89dbca --- /dev/null +++ b/DroidFish/jni/gtb/gtb-att.h @@ -0,0 +1,43 @@ +/* +This Software is distributed with the following X11 License, +sometimes also known as MIT license. + +Copyright (c) 2010 Miguel A. Ballicora + + 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. +*/ + +#if !defined(H_PROBATT) +#define H_PROBATT +/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ +#include "sysport.h" + +extern uint64_t Reach [7] [64]; + +extern void attack_maps_init (void); +extern int /*bool*/ possible_attack(unsigned int from, unsigned int to, unsigned int piece); +extern void reach_init (void); +extern int /*bool*/ reach_was_initialized (void); +extern void tolist_rev (uint64_t occ, unsigned char input_piece, unsigned int sq, unsigned int *list); + +/*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ +#endif diff --git a/DroidFish/jni/gtb/gtb-dec.c b/DroidFish/jni/gtb/gtb-dec.c new file mode 100644 index 0000000..be87aea --- /dev/null +++ b/DroidFish/jni/gtb/gtb-dec.c @@ -0,0 +1,133 @@ +/* +This Software is distributed with the following X11 License, +sometimes also known as MIT license. + +Copyright (c) 2010 Miguel A. Ballicora + + 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. +*/ + +/*--------------------------------------------------------------------------*\ +| +| Compressing wrapper functions +| +*---------------------------------------------------------------------------*/ +#define MAXBLOCK (1 << 16) + +#include +#include "gtb-dec.h" +#include "hzip.h" +#include "wrap.h" + +typedef int bool_t; + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0; +#endif + +/*static unsigned char intermediate_block[MAXBLOCK] ;*/ + +static int DECODE_SCHEME = CP4; +static int CP_SCHEME = CP4; + +static int f_decode (size_t z, unsigned char *bz, size_t n, unsigned char *bp); + +extern void +set_decoding_scheme(int x) +{ + DECODE_SCHEME = x; + CP_SCHEME = x; +} + +extern int decoding_scheme(void) +{ + return DECODE_SCHEME; +} + +extern int +decode (size_t z, unsigned char *bz, size_t n, unsigned char *bp) +{ + return f_decode (z, bz, n, bp); +} + +/*======================== WRAPPERS ========================*/ + +static int +f_decode (size_t z, unsigned char *bz, size_t n, unsigned char *bp) +{ +/* bp buffer provided +| bz buffer "zipped", compressed +| n len of buffer provided +| z len of buffer zipped +\*---------------------------------------------------------------*/ + +/* + unsigned char *ib = intermediate_block; + unsigned int m; + return huff_decode (bz, z, ib, &m, MAXBLOCK) && rle_decode (ib, m, bp, &n, MAXBLOCK); +*/ + + if (CP_SCHEME == CP1) { + + /* HUFFMAN */ + return huff_decode (bz, z, bp, &n, MAXBLOCK); + + } else if (CP_SCHEME == CP2) { + + /* LZF */ + return lzf_decode (bz, z, bp, &n, MAXBLOCK); + + } else if (CP_SCHEME == CP3) { + + /* ZLIB */ + return zlib_decode (bz, z, bp, &n, MAXBLOCK); + + } else if (CP_SCHEME == CP4) { + + /* LZMA86 */ + return lzma_decode (bz, z, bp, &n, n); /* maximum needs to be the exact number that it will produce */ + + } else if (CP_SCHEME == CP7) { + + /* RLE */ + return rle_decode (bz, z, bp, &n, MAXBLOCK); + + #if defined (LIBBZIP2) + } else if (CP_SCHEME == CP8) { + + /* BZIP2 */ + return bzip2_decode (bz, z, bp, &n, MAXBLOCK); + #endif + + } else if (CP_SCHEME == CP9) { + + return justcopy_decode (bz, z, bp, &n, MAXBLOCK); + + } else { + + return FALSE; + } +} + diff --git a/DroidFish/jni/gtb/gtb-dec.h b/DroidFish/jni/gtb/gtb-dec.h new file mode 100644 index 0000000..82ac347 --- /dev/null +++ b/DroidFish/jni/gtb/gtb-dec.h @@ -0,0 +1,50 @@ +/* +This Software is distributed with the following X11 License, +sometimes also known as MIT license. + +Copyright (c) 2010 Miguel A. Ballicora + + 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. +*/ + +/* gtb-dec.h */ +#if !defined(H_DECOD) +#define H_DECOD + +/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ +#include + +enum Compression {CP0, CP1, CP2, CP3, CP4, CP5, CP6, CP7, CP8, CP9, CP_END}; + +extern void set_decoding_scheme(int x); + +extern int decoding_scheme(void); + +extern int decode (size_t z, unsigned char *bz, size_t n, unsigned char *bp); + +/* +This function should be included with the TB compressor +extern int encode (size_t n, unsigned char *bp, size_t *z, unsigned char *bz); +*/ + +/*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ +#endif diff --git a/DroidFish/jni/gtb/gtb-probe.c b/DroidFish/jni/gtb/gtb-probe.c new file mode 100644 index 0000000..f97f489 --- /dev/null +++ b/DroidFish/jni/gtb/gtb-probe.c @@ -0,0 +1,8039 @@ +/* +This Software is distributed with the following X11 License, +sometimes also known as MIT license. + +Copyright (c) 2010 Miguel A. Ballicora + + 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. +*/ + + +/* NBBOTF will remove the internal bitbase on the fly */ +#ifdef NBBOTF + #ifdef WDL_PROBE + #undef WDL_PROBE + #endif +#else + #define WDL_PROBE +#endif + +/*-- Intended to be modified to make public --> Supporting functions the TB generator ---------------------*/ + +#ifdef GTB_SHARE +#define SHARED_forbuilding +#endif + +/*---------------------------------------------------------------------------------------------------------*/ +#include +#include +#include + +#include "gtb-probe.h" + +#if defined(SHARED_forbuilding) + #include "gtb-prob2.h" +#else + #define mySHARED static + typedef unsigned char SQ_CONTENT; + typedef unsigned int SQUARE; +#endif + +#include "sysport.h" +#include "gtb-att.h" +#include "gtb-types.h" + +/*---------------------------------------------------------------------------------------------------------*/ +/*#include "posit_t.h"*/ + +#define MAX_LISTSIZE 17 +#if 0 +typedef unsigned sq_t; +typedef unsigned char pc_t; +typedef uint32_t mv_t; +#endif + +struct posit { + sq_t ws[MAX_LISTSIZE]; + sq_t bs[MAX_LISTSIZE]; + pc_t wp[MAX_LISTSIZE]; + pc_t bp[MAX_LISTSIZE]; + sq_t ep; + unsigned int stm; + unsigned int cas; +}; +typedef struct posit posit_t; + +#if 0 +typedef long int tbkey_t; +#endif + +/*---------------------------------------------------------------------------------------------------------*/ +/*#include "bool_t.h"*/ + +#if !defined(H_BOOL) +typedef int bool_t; +#endif + +#if !defined(TRUE) +#define TRUE ((bool_t)1) +#endif + +#if !defined(FALSE) +#define FALSE ((bool_t)0) +#endif + +/*--------- private if external building code is not present ----------------------------------------------*/ + +#if !defined(SHARED_forbuilding) + +#define MAX_EGKEYS 145 +#define SLOTSIZE 1 +#define NOINDEX ((index_t)(-1)) + +#if 0 +typedef unsigned short int dtm_t; +typedef size_t index_t; +/*typedef int index_t;*/ +#endif + +enum Loading_status { + STATUS_ABSENT = 0, + STATUS_STATICRAM = 1, + STATUS_MALLOC = 2, + STATUS_FILE = 3, + STATUS_REJECT = 4 +}; + +struct endgamekey { + int id; + const char *str; + index_t maxindex; + index_t slice_n; + void (*itopc) (index_t, SQUARE *, SQUARE *); + bool_t (*pctoi) (const SQUARE *, const SQUARE *, index_t *); + dtm_t * egt_w; + dtm_t * egt_b; + FILE * fd; + int status; + int pathn; +}; +#endif + +/*----------------------------------------------------------------------------------------------------------*/ + +/* array for better moves */ +#ifdef GTB_SHARE +mySHARED int bettarr [2] [8] [8]; +#endif + +/*------------ ENUMS ----------------------------------------------------------*/ + +enum Mask_values { + RESMASK = tb_RESMASK, + INFOMASK = tb_INFOMASK, + PLYSHIFT = tb_PLYSHIFT +}; + +enum Info_values { + iDRAW = tb_DRAW, + iWMATE = tb_WMATE, + iBMATE = tb_BMATE, + iFORBID = tb_FORBID, + + iDRAWt = tb_DRAW |4, + iWMATEt = tb_WMATE |4, + iBMATEt = tb_BMATE |4, + iUNKNOWN = tb_UNKNOWN, + + iUNKNBIT = (1<<2) +}; + +/*-------------------------- inherited from a previous maindef.h -----------*/ + +#define WHITES (1u<<6) +#define BLACKS (1u<<7) + +#define NOPIECE 0u +#define PAWN 1u +#define KNIGHT 2u +#define BISHOP 3u +#define ROOK 4u +#define QUEEN 5u +#define KING 6u + +#define WH 0 +#define BL 1 +#define Opp(x) ((x)^1) +#define wK (KING | WHITES) + +/*------------------- + SQUARES + -------------------*/ + +/* from 1-63 different squares posibles */ + +/*squares*/ +enum SQUARES { + A1,B1,C1,D1,E1,F1,G1,H1, + A2,B2,C2,D2,E2,F2,G2,H2, + A3,B3,C3,D3,E3,F3,G3,H3, + A4,B4,C4,D4,E4,F4,G4,H4, + A5,B5,C5,D5,E5,F5,G5,H5, + A6,B6,C6,D6,E6,F6,G6,H6, + A7,B7,C7,D7,E7,F7,G7,H7, + A8,B8,C8,D8,E8,F8,G8,H8, + NOSQUARE, + ERRSQUARE = 128 +}; + +/*------------------- end of inherited from a previous maindef.h -----------*/ + +#if !defined(NDEBUG) +#define NDEBUG +#endif +#ifdef DEBUG +#undef NDEBUG +#endif +#include "assert.h" + +/*------------------- general DEFINES--------------------------- -----------*/ + +#define gtbNOSIDE ((unsigned)-1) +#define gtbNOINDEX ((index_t)-1) + +/*************************************************\ +| +| COMPRESSION SCHEMES +| +\*************************************************/ + +#include "gtb-dec.h" + +static const char *const Extension[] = { + ".gtb.cp0" + ,".gtb.cp1" + ,".gtb.cp2" + ,".gtb.cp3" + ,".gtb.cp4" + ,".gtb.cp5" + ,".gtb.cp6" + ,".gtb.cp7" + ,".gtb.cp8" + ,".gtb.cp9" +}; + +/*************************************************\ +| +| MOVES +| +\*************************************************/ + +enum move_kind { + NORMAL_MOVE = 0, + CASTLE_MOVE, + PASSNT_MOVE, + PROMOT_MOVE +}; + +enum move_content { + NOMOVE = 0 +}; + +#define MV_TYPE(mv) ( (BYTE) ((mv) >>6 & 3 ) ) +#define MV_TO(mv) ( (SQUARE) ((mv) >>8 & 63) ) +#define MV_PT(mv) ( (SQ_CONTENT) ((mv) >>(3+16) &7 ) ) +#define MV_TK(mv) ( (SQ_CONTENT) ((mv) >>(6+16) &7 ) ) +#define MV_FROM(mv) ( (SQUARE) ((mv) & 63) ) + +/* +| move,type,color,piece,from,to,taken,promoted +*------------------------------------------------------------------*/ + +#define MV_BUILD(mv,ty,co,pc,fr,to,tk,pm) ( \ + (mv) = (fr) | (to)<< 8 | (ty)<< 6 | (co)<<8 \ + | (pc)<<16 | (pm)<< (3+16) | (tk)<< (6+16) \ +) + +#define MV_ADD_TOTK(mv,to,tk) ( \ + mv |= (uint32_t)(to) << 8 \ + | (uint32_t)(tk) << (6+16) \ +) + +#define map88(x) ( (x) + ((x)&070) ) +#define unmap88(x) ( ( (x) + ((x)& 07) ) >> 1 ) + +/*************************************************\ +| +| STATIC VARIABLES +| +\*************************************************/ + +static int GTB_scheme = 4; + +/*************************************************\ +| +| needed for +| PRE LOAD CACHE AND DEPENDENT FUNCTIONS +| +\*************************************************/ + +#define EGTB_MAXBLOCKSIZE 65536 + +static int GTB_MAXOPEN = 4; + +static bool_t Uncompressed = TRUE; +static unsigned char Buffer_zipped [EGTB_MAXBLOCKSIZE]; +static unsigned char Buffer_packed [EGTB_MAXBLOCKSIZE]; +static unsigned int zipinfo_init (void); +static void zipinfo_done (void); + +enum Flip_flags { + WE_FLAG = 1, NS_FLAG = 2, NW_SE_FLAG = 4 +}; /* used in flipt */ + +struct filesopen { + int n; + tbkey_t *key; +}; + +/* STATIC GLOBALS */ + +static struct filesopen fd = {0, NULL}; + +static bool_t TB_INITIALIZED = FALSE; +static bool_t DTM_CACHE_INITIALIZED = FALSE; + +static int WDL_FRACTION = 64; +static int WDL_FRACTION_MAX = 128; + +static size_t DTM_cache_size = 0; +static size_t WDL_cache_size = 0; + +static unsigned int TB_AVAILABILITY = 0; + +/* LOCKS */ +static mythread_mutex_t Egtb_lock; + + +/****************************************************************************\ + * + * + * DEBUGGING or PRINTING ZONE + * + * + ****************************************************************************/ + +#if 0 +#define FOLLOW_EGTB +#ifndef DEBUG +#define DEBUG +#endif +#endif + +#define validsq(x) ((x) >= A1 && (x) <= H8) + +#if defined(DEBUG) +static void print_pos (const sq_t *ws, const sq_t *bs, const pc_t *wp, const pc_t *bp); +#endif + +#if defined(DEBUG) || defined(FOLLOW_EGTB) +static void output_state (unsigned stm, const SQUARE *wSQ, const SQUARE *bSQ, + const SQ_CONTENT *wPC, const SQ_CONTENT *bPC); +static const char *Square_str[64] = { + "a1","b1","c1","d1","e1","f1","g1","h1", + "a2","b2","c2","d2","e2","f2","g2","h2", + "a3","b3","c3","d3","e3","f3","g3","h3", + "a4","b4","c4","d4","e4","f4","g4","h4", + "a5","b5","c5","d5","e5","f5","g5","h5", + "a6","b6","c6","d6","e6","f6","g6","h6", + "a7","b7","c7","d7","e7","f7","g7","h7", + "a8","b8","c8","d8","e8","f8","g8","h8" +}; +static const char *P_str[] = { + "--", "P", "N", "B", "R", "Q", "K" +}; +#endif + +#ifdef FOLLOW_EGTB + #define STAB + #define STABCONDITION 1 /*(stm == BL && whiteSQ[0]==H1 && whiteSQ[1]==D1 && whiteSQ[2]==D3 && blackSQ[0]==C2 )*/ + static bool_t GLOB_REPORT = TRUE; +#endif + +#if defined(FOLLOW_EGTB) +static const char *Info_str[8] = { + " Draw", " Wmate", " Bmate", "Illegal", + "~Draw", "~Wmate", "~Bmate", "Unknown" +}; +#endif + +static void list_index (void); +static void fatal_error(void) { + exit(EXIT_FAILURE); +} + +#ifdef STAB + #define FOLLOW_LU(x,y) {if (GLOB_REPORT) printf ("************** %s: %lu\n", (x), (long unsigned)(y));} +#else + #define FOLLOW_LU(x,y) +#endif + +#ifdef STAB + #define FOLLOW_LULU(x,y,z) {if (GLOB_REPORT) printf ("************** %s: %lu, %lu\n", (x), (long unsigned)(y), (long unsigned)(z));} +#else + #define FOLLOW_LULU(x,y,z) +#endif + +#ifdef STAB + #define FOLLOW_label(x) {if (GLOB_REPORT) printf ("************** %s\n", (x));} +#else + #define FOLLOW_label(x) +#endif + +#ifdef STAB + #define FOLLOW_DTM(msg,dtm) {if (GLOB_REPORT) printf ("************** %s: %lu, info:%s, plies:%lu \n"\ + , (msg), (long unsigned)(dtm), (Info_str[(dtm)&INFOMASK]), (long unsigned)((dtm)>>PLYSHIFT)\ + );} +#else + #define FOLLOW_DTM(msg,dtm) +#endif + + +/*--------------------------------*\ +| +| +| INDEXING FUNCTIONS +| +| +*---------------------------------*/ + +#define IDX_set_empty(x) {x=0;x--;} +#define IDX_is_empty(x) (0==(1+(x))) + +#define NO_KKINDEX NOINDEX +#define MAX_KKINDEX 462 +#define MAX_PPINDEX 576 +#define MAX_PpINDEX (24 * 48) +/*1128*/ +#define MAX_AAINDEX ((63-62) + (62 * (127-62)/2) - 1 + 1) +#define MAX_AAAINDEX (64*21*31) +#define MAX_PP48_INDEX (1128) +/* (24*23*22/6) + 24 * (24*23/2) */ +#define MAX_PPP48_INDEX 8648 + +/* VARIABLES */ + +static index_t kkidx [64] [64]; +static index_t ppidx [24] [48]; +static index_t pp48_idx[48][48]; +static index_t ppp48_idx[48][48][48]; + +static sq_t wksq [MAX_KKINDEX]; +static sq_t bksq [MAX_KKINDEX]; +static sq_t pp48_sq_x[MAX_PP48_INDEX]; +static sq_t pp48_sq_y[MAX_PP48_INDEX]; + +static index_t pp_hi24 [MAX_PPINDEX]; /* was unsigned int */ +static index_t pp_lo48 [MAX_PPINDEX]; +static unsigned int flipt [64] [64]; +static index_t aaidx [64] [64]; /* was unsigned int */ +static unsigned char aabase [MAX_AAINDEX]; + +static uint8_t ppp48_sq_x[MAX_PPP48_INDEX]; +static uint8_t ppp48_sq_y[MAX_PPP48_INDEX]; +static uint8_t ppp48_sq_z[MAX_PPP48_INDEX]; + +/* FUNCTIONS */ + +static void init_indexing (int verbosity); +static void norm_kkindex (SQUARE x, SQUARE y, /*@out@*/ SQUARE *pi, /*@out@*/ SQUARE *pj); +static void pp_putanchorfirst (SQUARE a, SQUARE b, /*@out@*/ SQUARE *out_anchor, /*@out@*/ SQUARE *out_loosen); + +static index_t wsq_to_pidx24 (SQUARE pawn); +static index_t wsq_to_pidx48 (SQUARE pawn); +static SQUARE pidx24_to_wsq (index_t a); +static SQUARE pidx48_to_wsq (index_t a); + +static SQUARE flipWE (SQUARE x) { return x ^ 07;} +static SQUARE flipNS (SQUARE x) { return x ^ 070;} +static SQUARE flipNW_SE (SQUARE x) { return ((x&7)<<3) | (x>>3);} +static SQUARE getcol (SQUARE x) { return x & 7;} +static SQUARE getrow (SQUARE x) { return x >> 3;} +static bool_t in_queenside (sq_t x) { return 0 == (x & (1<<2));} + +/* 1:0 */ +static void kxk_indextopc (index_t i, SQUARE *pw, SQUARE *pb); + +/* 2:0 */ +static void kabk_indextopc (index_t i, SQUARE *pw, SQUARE *pb); +static void kakb_indextopc (index_t i, SQUARE *pw, SQUARE *pb); +static void kaak_indextopc (index_t i, SQUARE *pw, SQUARE *pb); + +/* 2:1 */ +static void kabkc_indextopc (index_t i, SQUARE *pw, SQUARE *pb); +static void kaakb_indextopc (index_t i, SQUARE *pw, SQUARE *pb); + +/* 3:0 */ +static void kabck_indextopc (index_t i, SQUARE *pw, SQUARE *pb); +static void kaabk_indextopc (index_t i, SQUARE *pw, SQUARE *pb); +static void kaaak_indextopc (index_t i, SQUARE *pw, SQUARE *pb); +static void kabbk_indextopc (index_t i, SQUARE *pw, SQUARE *pb); + +/* one pawn */ +static void kpk_indextopc (index_t i, SQUARE *pw, SQUARE *pb); + +/* 1:1 one pawn */ +static void kakp_indextopc (index_t i, SQUARE *pw, SQUARE *pb); + +/* 2:0 one pawn */ +static void kapk_indextopc (index_t i, SQUARE *pw, SQUARE *pb); + +/* 2:0 two pawns */ +static void kppk_indextopc (index_t i, SQUARE *pw, SQUARE *pb); + +/* 2:1 one pawn */ +static void kapkb_indextopc (index_t i, SQUARE *pw, SQUARE *pb); +static void kabkp_indextopc (index_t i, SQUARE *pw, SQUARE *pb); +static void kaakp_indextopc (index_t i, SQUARE *pw, SQUARE *pb); + +/* 2:1 + 3:0 two pawns */ +static void kppka_indextopc (index_t i, SQUARE *pw, SQUARE *pb); +static void kappk_indextopc (index_t i, SQUARE *pw, SQUARE *pb); +static void kapkp_indextopc (index_t i, SQUARE *pw, SQUARE *pb); + +/* 3:0 one pawn */ +static void kabpk_indextopc (index_t i, SQUARE *pw, SQUARE *pb); +static void kaapk_indextopc (index_t i, SQUARE *pw, SQUARE *pb); + +/* three pawns */ +static void kpppk_indextopc (index_t i, SQUARE *pw, SQUARE *pb); +static void kppkp_indextopc (index_t i, SQUARE *pw, SQUARE *pb); + +/* 1:1 two pawns */ +static void kpkp_indextopc (index_t i, SQUARE *pw, SQUARE *pb); + +/* corresponding pc to index */ +static bool_t kxk_pctoindex (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out); +static bool_t kabk_pctoindex (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out); +static bool_t kakb_pctoindex (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out); +static bool_t kpk_pctoindex (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out); +static bool_t kakp_pctoindex (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out); +static bool_t kapk_pctoindex (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out); +static bool_t kppk_pctoindex (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out); +static bool_t kaak_pctoindex (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out); +static bool_t kabkc_pctoindex (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out); + +static bool_t kaakb_pctoindex (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out);/**/ + +static bool_t kabck_pctoindex (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out); +static bool_t kaabk_pctoindex (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out);/**/ +static bool_t kaaak_pctoindex (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out); +static bool_t kabbk_pctoindex (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out);/**/ +static bool_t kapkb_pctoindex (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out); +static bool_t kabkp_pctoindex (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out); +static bool_t kaakp_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, /*@out@*/ index_t *out); +static bool_t kppka_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out); +static bool_t kappk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, /*@out@*/ index_t *out); +static bool_t kapkp_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, /*@out@*/ index_t *out); +static bool_t kabpk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, /*@out@*/ index_t *out); +static bool_t kaapk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, /*@out@*/ index_t *out); +static bool_t kppkp_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, /*@out@*/ index_t *out); +static bool_t kpppk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, /*@out@*/ index_t *out); +static bool_t kpkp_pctoindex (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out); + +/* testing functions */ +static bool_t test_kppk (void); +static bool_t test_kaakb (void); +static bool_t test_kaabk (void); +static bool_t test_kaaak (void); +static bool_t test_kabbk (void); +static bool_t test_kapkb (void); +static bool_t test_kabkp (void); +static bool_t test_kppka (void); +static bool_t test_kappk (void); +static bool_t test_kapkp (void); +static bool_t test_kabpk (void); +static bool_t test_kaapk (void); +static bool_t test_kaakp (void); +static bool_t test_kppkp (void); +static bool_t test_kpppk (void); + +static unsigned flip_type (SQUARE x, SQUARE y); +static index_t init_kkidx (void); +static index_t init_ppidx (void); +static void init_flipt (void); +static index_t init_aaidx (void); +static index_t init_aaa (void); +static index_t init_pp48_idx (void); +static index_t init_ppp48_idx (void); + +enum TB_INDEXES + { MAX_KXK = MAX_KKINDEX*64 + ,MAX_kabk = MAX_KKINDEX*64*64 + ,MAX_kakb = MAX_KKINDEX*64*64 + ,MAX_kpk = 24*64*64 + ,MAX_kakp = 24*64*64*64 + ,MAX_kapk = 24*64*64*64 + ,MAX_kppk = MAX_PPINDEX*64*64 + ,MAX_kpkp = MAX_PpINDEX*64*64 + ,MAX_kaak = MAX_KKINDEX*MAX_AAINDEX + ,MAX_kabkc = MAX_KKINDEX*64*64*64 + ,MAX_kabck = MAX_KKINDEX*64*64*64 + ,MAX_kaakb = MAX_KKINDEX*MAX_AAINDEX*64 + ,MAX_kaabk = MAX_KKINDEX*MAX_AAINDEX*64 + ,MAX_kabbk = MAX_KKINDEX*MAX_AAINDEX*64 + ,MAX_kaaak = MAX_KKINDEX*MAX_AAAINDEX + ,MAX_kapkb = 24*64*64*64*64 + ,MAX_kabkp = 24*64*64*64*64 + ,MAX_kabpk = 24*64*64*64*64 + ,MAX_kppka = MAX_kppk*64 + ,MAX_kappk = MAX_kppk*64 + ,MAX_kapkp = MAX_kpkp*64 + ,MAX_kaapk = 24*MAX_AAINDEX*64*64 + ,MAX_kaakp = 24*MAX_AAINDEX*64*64 + ,MAX_kppkp = 24*MAX_PP48_INDEX*64*64 + ,MAX_kpppk = MAX_PPP48_INDEX*64*64 +}; + +#if defined(SHARED_forbuilding) +extern index_t +biggest_memory_needed (void) { + return MAX_kabkc; +} +#endif + +/*--------------------------------*\ +| +| +| CACHE PROTOTYPES +| +| +*---------------------------------*/ + +#if !defined(SHARED_forbuilding) +mySHARED bool_t get_dtm (tbkey_t key, unsigned side, index_t idx, dtm_t *out, bool_t probe_hard); +#endif + +static bool_t get_dtm_from_cache (tbkey_t key, unsigned side, index_t idx, dtm_t *out); + + +/*--------------------------------*\ +| +| +| INIT +| +| +*---------------------------------*/ + +static bool_t fd_init (struct filesopen *pfd); +static void fd_done (struct filesopen *pfd); + +static void RAM_egtbfree (void); + +/*--------------------------------------------------------------------------*/ +#if !defined(SHARED_forbuilding) +mySHARED void egtb_freemem (int i); +#endif + +mySHARED struct endgamekey egkey[] = { + +{0, "kqk", MAX_KXK, 1, kxk_indextopc, kxk_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{1, "krk", MAX_KXK, 1, kxk_indextopc, kxk_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{2, "kbk", MAX_KXK, 1, kxk_indextopc, kxk_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{3, "knk", MAX_KXK, 1, kxk_indextopc, kxk_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{4, "kpk", MAX_kpk, 24,kpk_indextopc, kpk_pctoindex, NULL , NULL ,NULL ,0, 0 }, + /* 4 pieces */ +{5, "kqkq", MAX_kakb, 1, kakb_indextopc, kakb_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{6, "kqkr", MAX_kakb, 1, kakb_indextopc, kakb_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{7, "kqkb", MAX_kakb, 1, kakb_indextopc, kakb_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{8, "kqkn", MAX_kakb, 1, kakb_indextopc, kakb_pctoindex, NULL , NULL ,NULL ,0, 0 }, + +{9, "krkr", MAX_kakb, 1, kakb_indextopc, kakb_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{10,"krkb", MAX_kakb, 1, kakb_indextopc, kakb_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{11,"krkn", MAX_kakb, 1, kakb_indextopc, kakb_pctoindex, NULL , NULL ,NULL ,0, 0 }, + +{12,"kbkb", MAX_kakb, 1, kakb_indextopc, kakb_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{13,"kbkn", MAX_kakb, 1, kakb_indextopc, kakb_pctoindex, NULL , NULL ,NULL ,0, 0 }, + +{14,"knkn", MAX_kakb, 1, kakb_indextopc, kakb_pctoindex, NULL , NULL ,NULL ,0, 0 }, + /**/ +{15,"kqqk", MAX_kaak, 1, kaak_indextopc, kaak_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{16,"kqrk", MAX_kabk, 1, kabk_indextopc, kabk_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{17,"kqbk", MAX_kabk, 1, kabk_indextopc, kabk_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{18,"kqnk", MAX_kabk, 1, kabk_indextopc, kabk_pctoindex, NULL , NULL ,NULL ,0, 0 }, + +{19,"krrk", MAX_kaak, 1, kaak_indextopc, kaak_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{20,"krbk", MAX_kabk, 1, kabk_indextopc, kabk_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{21,"krnk", MAX_kabk, 1, kabk_indextopc, kabk_pctoindex, NULL , NULL ,NULL ,0, 0 }, + +{22,"kbbk", MAX_kaak, 1, kaak_indextopc, kaak_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{23,"kbnk", MAX_kabk, 1, kabk_indextopc, kabk_pctoindex, NULL , NULL ,NULL ,0, 0 }, + +{24,"knnk", MAX_kaak, 1, kaak_indextopc, kaak_pctoindex, NULL , NULL ,NULL ,0, 0 }, + /**/ + /**/ +{25,"kqkp", MAX_kakp, 24,kakp_indextopc, kakp_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{26,"krkp", MAX_kakp, 24,kakp_indextopc, kakp_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{27,"kbkp", MAX_kakp, 24,kakp_indextopc, kakp_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{28,"knkp", MAX_kakp, 24,kakp_indextopc, kakp_pctoindex, NULL , NULL ,NULL ,0, 0 }, + /**/ +{29,"kqpk", MAX_kapk, 24,kapk_indextopc, kapk_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{30,"krpk", MAX_kapk, 24,kapk_indextopc, kapk_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{31,"kbpk", MAX_kapk, 24,kapk_indextopc, kapk_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{32,"knpk", MAX_kapk, 24,kapk_indextopc, kapk_pctoindex, NULL , NULL ,NULL ,0, 0 }, + /**/ +{33,"kppk", MAX_kppk, MAX_PPINDEX ,kppk_indextopc, kppk_pctoindex, NULL , NULL ,NULL ,0, 0 }, + /**/ +{34,"kpkp", MAX_kpkp, MAX_PpINDEX ,kpkp_indextopc, kpkp_pctoindex, NULL , NULL ,NULL ,0, 0 }, + /**/ + /**/ + /* 5 pieces */ +{ 35,"kqqqk", MAX_kaaak, 1, kaaak_indextopc, kaaak_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 36,"kqqrk", MAX_kaabk, 1, kaabk_indextopc, kaabk_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 37,"kqqbk", MAX_kaabk, 1, kaabk_indextopc, kaabk_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 38,"kqqnk", MAX_kaabk, 1, kaabk_indextopc, kaabk_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 39,"kqrrk", MAX_kabbk, 1, kabbk_indextopc, kabbk_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 40,"kqrbk", MAX_kabck, 1, kabck_indextopc, kabck_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 41,"kqrnk", MAX_kabck, 1, kabck_indextopc, kabck_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 42,"kqbbk", MAX_kabbk, 1, kabbk_indextopc, kabbk_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 43,"kqbnk", MAX_kabck, 1, kabck_indextopc, kabck_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 44,"kqnnk", MAX_kabbk, 1, kabbk_indextopc, kabbk_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 45,"krrrk", MAX_kaaak, 1, kaaak_indextopc, kaaak_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 46,"krrbk", MAX_kaabk, 1, kaabk_indextopc, kaabk_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 47,"krrnk", MAX_kaabk, 1, kaabk_indextopc, kaabk_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 48,"krbbk", MAX_kabbk, 1, kabbk_indextopc, kabbk_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 49,"krbnk", MAX_kabck, 1, kabck_indextopc, kabck_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 50,"krnnk", MAX_kabbk, 1, kabbk_indextopc, kabbk_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 51,"kbbbk", MAX_kaaak, 1, kaaak_indextopc, kaaak_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 52,"kbbnk", MAX_kaabk, 1, kaabk_indextopc, kaabk_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 53,"kbnnk", MAX_kabbk, 1, kabbk_indextopc, kabbk_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 54,"knnnk", MAX_kaaak, 1, kaaak_indextopc, kaaak_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 55,"kqqkq", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 56,"kqqkr", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 57,"kqqkb", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 58,"kqqkn", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 59,"kqrkq", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 60,"kqrkr", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 61,"kqrkb", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 62,"kqrkn", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 63,"kqbkq", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 64,"kqbkr", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 65,"kqbkb", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 66,"kqbkn", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 67,"kqnkq", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 68,"kqnkr", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 69,"kqnkb", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 70,"kqnkn", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 71,"krrkq", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 72,"krrkr", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 73,"krrkb", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 74,"krrkn", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 75,"krbkq", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 76,"krbkr", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 77,"krbkb", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 78,"krbkn", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 79,"krnkq", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 80,"krnkr", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 81,"krnkb", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 82,"krnkn", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 83,"kbbkq", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 84,"kbbkr", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 85,"kbbkb", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 86,"kbbkn", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 87,"kbnkq", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 88,"kbnkr", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 89,"kbnkb", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 90,"kbnkn", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 91,"knnkq", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 92,"knnkr", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 93,"knnkb", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 94,"knnkn", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL , NULL ,NULL ,0, 0 }, + +{ 95,"kqqpk", MAX_kaapk, 24, kaapk_indextopc, kaapk_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 96,"kqrpk", MAX_kabpk, 24, kabpk_indextopc, kabpk_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 97,"kqbpk", MAX_kabpk, 24, kabpk_indextopc, kabpk_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 98,"kqnpk", MAX_kabpk, 24, kabpk_indextopc, kabpk_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{ 99,"krrpk", MAX_kaapk, 24, kaapk_indextopc, kaapk_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{100,"krbpk", MAX_kabpk, 24, kabpk_indextopc, kabpk_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{101,"krnpk", MAX_kabpk, 24, kabpk_indextopc, kabpk_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{102,"kbbpk", MAX_kaapk, 24, kaapk_indextopc, kaapk_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{103,"kbnpk", MAX_kabpk, 24, kabpk_indextopc, kabpk_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{104,"knnpk", MAX_kaapk, 24, kaapk_indextopc, kaapk_pctoindex, NULL , NULL ,NULL ,0, 0 }, + +{105,"kqppk", MAX_kappk, MAX_PPINDEX, kappk_indextopc, kappk_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{106,"krppk", MAX_kappk, MAX_PPINDEX, kappk_indextopc, kappk_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{107,"kbppk", MAX_kappk, MAX_PPINDEX, kappk_indextopc, kappk_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{108,"knppk", MAX_kappk, MAX_PPINDEX, kappk_indextopc, kappk_pctoindex, NULL , NULL ,NULL ,0, 0 }, + +{109,"kqpkq", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{110,"kqpkr", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{111,"kqpkb", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{112,"kqpkn", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{113,"krpkq", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{114,"krpkr", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{115,"krpkb", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{116,"krpkn", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{117,"kbpkq", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{118,"kbpkr", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{119,"kbpkb", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{120,"kbpkn", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{121,"knpkq", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{122,"knpkr", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{123,"knpkb", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{124,"knpkn", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL , NULL ,NULL ,0, 0 }, + +{125,"kppkq", MAX_kppka, MAX_PPINDEX, kppka_indextopc, kppka_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{126,"kppkr", MAX_kppka, MAX_PPINDEX, kppka_indextopc, kppka_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{127,"kppkb", MAX_kppka, MAX_PPINDEX, kppka_indextopc, kppka_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{128,"kppkn", MAX_kppka, MAX_PPINDEX, kppka_indextopc, kppka_pctoindex, NULL , NULL ,NULL ,0, 0 }, + +{129,"kqqkp", MAX_kaakp, 24, kaakp_indextopc, kaakp_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{130,"kqrkp", MAX_kabkp, 24, kabkp_indextopc, kabkp_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{131,"kqbkp", MAX_kabkp, 24, kabkp_indextopc, kabkp_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{132,"kqnkp", MAX_kabkp, 24, kabkp_indextopc, kabkp_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{133,"krrkp", MAX_kaakp, 24, kaakp_indextopc, kaakp_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{134,"krbkp", MAX_kabkp, 24, kabkp_indextopc, kabkp_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{135,"krnkp", MAX_kabkp, 24, kabkp_indextopc, kabkp_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{136,"kbbkp", MAX_kaakp, 24, kaakp_indextopc, kaakp_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{137,"kbnkp", MAX_kabkp, 24, kabkp_indextopc, kabkp_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{138,"knnkp", MAX_kaakp, 24, kaakp_indextopc, kaakp_pctoindex, NULL , NULL ,NULL ,0, 0 }, + +{139,"kqpkp", MAX_kapkp, MAX_PpINDEX, kapkp_indextopc, kapkp_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{140,"krpkp", MAX_kapkp, MAX_PpINDEX, kapkp_indextopc, kapkp_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{141,"kbpkp", MAX_kapkp, MAX_PpINDEX, kapkp_indextopc, kapkp_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{142,"knpkp", MAX_kapkp, MAX_PpINDEX, kapkp_indextopc, kapkp_pctoindex, NULL , NULL ,NULL ,0, 0 }, + +{143,"kppkp", MAX_kppkp, 24*MAX_PP48_INDEX, kppkp_indextopc, kppkp_pctoindex, NULL , NULL ,NULL ,0, 0 }, +{144,"kpppk", MAX_kpppk, MAX_PPP48_INDEX, kpppk_indextopc, kpppk_pctoindex, NULL , NULL ,NULL ,0, 0 }, + +{MAX_EGKEYS, NULL, 0, 1, NULL, NULL, NULL, NULL ,NULL ,0 ,0} + +}; + +static int eg_was_open[MAX_EGKEYS]; + +static uint64_t Bytes_read = 0; + +/****************************************************************************\ +| +| +| PATH MANAGEMENT ZONE +| +| +\****************************************************************************/ + +#define MAXPATHLEN tb_MAXPATHLEN +#define MAX_GTBPATHS 10 + +static int Gtbpath_end_index = 0; +static const char ** Gtbpath = NULL; + +/*---------------- EXTERNAL PATH MANAGEMENT --------------------------------*/ + +extern const char *tbpaths_getmain (void) { return Gtbpath[0];} + +extern const char ** +tbpaths_init(void) +{ + const char **newps; + newps = (const char **) malloc (sizeof (char *)); + if (newps != NULL) { + newps[0] = NULL; + } + return newps; +} + +static const char ** +tbpaths_add_single(const char **ps, const char *newpath) +{ + size_t counter; + const char **newps; + size_t i, psize; + char *ppath; + + if (NULL == ps) + return NULL; + + psize = strlen(newpath) + 1; + ppath = (char *) malloc (psize * sizeof (char)); + if (NULL == ppath) + return ps; /* failed to incorporate a new path */ + for (i = 0; i < psize; i++) ppath[i] = newpath[i]; + + for (counter = 0; ps[counter] != NULL; counter++) + ; + + /* cast to deal with const poisoning */ + newps = (const char **) realloc ((char **)ps, sizeof(char *) * (counter+2)); + if (newps != NULL) { + newps [counter] = ppath; + newps [counter+1] = NULL; + } + return newps; +} + + +extern const char ** +tbpaths_add(const char **ps, const char *newpath) +{ + size_t i, psize; + char *mpath; + + if (NULL == ps) + return NULL; + + psize = strlen(newpath) + 1; + mpath = (char *) malloc (psize * sizeof (char)); + if (NULL == mpath) { + return ps; /* failed to incorporate a new path */ + } + for (i = 0; i < psize; i++) mpath[i] = newpath[i]; + + for (i = 0; i < psize; i++) { + if(';' == mpath[i]) + mpath[i] = '\0'; + } + + for (i = 0;;) { + while (i < psize && mpath[i] == '\0') i++; + if (i >= psize) break; + ps = tbpaths_add_single (ps, &mpath[i]); + while (i < psize && mpath[i] != '\0') i++; + } + + free(mpath); + return ps; +} + + +extern const char ** +tbpaths_done(const char **ps) +{ + int counter; + void *q; + + if (ps != NULL) { + for (counter = 0; ps[counter] != NULL; counter++) { + /* cast to deal with const poisoning */ + void *p = (void *) ps[counter]; + free(p); + } + /* cast to deal with const poisoning */ + q = (void *) ps; + free(q); + } + return NULL; +} + +/*---------------- PATH INITIALIZATION ROUTINES ----------------------------*/ + +static void path_system_reset(void) {Gtbpath_end_index = 0;} + +static bool_t +path_system_init (const char **path) +{ + size_t i; + size_t sz; + const char *x; + bool_t ok = TRUE; + path_system_reset(); + + if (path == NULL) { + return FALSE; + } + + /* calculate needed size for Gtbpath */ + i = 0; + do { + x = path[i++]; + } while (x != NULL); + sz = i; /* sz includes the NULL */ + + + Gtbpath = (const char **) malloc (sz * sizeof(char *)); + + if (Gtbpath) { + + ok = TRUE; + /* point to the same strings provided */ + Gtbpath_end_index = 0; + for (i = 0; i < sz; i++) { + Gtbpath[i] = path[i]; + Gtbpath_end_index++; + } + + } else { + ok = FALSE; + } + return ok; + +} + +static void +path_system_done (void) +{ + /* before we free Gtbpath, we have to deal with the + "const poisoning" and cast it. free() does not accept + const pointers */ + char ** p = (char **) Gtbpath; + /* clean up */ + if (p != NULL) + free(p); + return; +} + + +/****************************************************************************\ + * + * + * General Initialization Zone + * + * + ****************************************************************************/ + + +#ifdef WDL_PROBE +static size_t wdl_cache_init (size_t cache_mem); +static void wdl_cache_flush (void); + +static void wdl_cache_reset_counters (void); +static void wdl_cache_done (void); + +static bool_t get_WDL_from_cache (tbkey_t key, unsigned side, index_t idx, unsigned int *out); +static bool_t wdl_preload_cache (tbkey_t key, unsigned side, index_t idx); +#endif + +#ifdef GTB_SHARE +static void init_bettarr (void); +#endif + +static void eg_was_open_reset(void) +{ + int i; + for (i = 0; i < MAX_EGKEYS; i++) { + eg_was_open[i] = 0; + } +} + +static long unsigned int eg_was_open_count(void) +{ + long int i, x; + for (i = 0, x = 0; i < MAX_EGKEYS; i++) { + x += eg_was_open[i]; + } + return (long unsigned) x; +} + + +enum Sizes {INISIZE = 4096}; +static char ini_str[INISIZE]; +static void sjoin(char *s, const char *tail, size_t max) {strncat(s, tail, max - strlen(s) - 1);} + +char * +tb_init (int verbosity, int decoding_sch, const char **paths) +{ + unsigned int zi; + int paths_ok; + char *ret_str; + char localstr[256]; + + assert(!TB_INITIALIZED); + + if (verbosity) { + ini_str[0] = '\0'; + ret_str = ini_str; + } else { + ret_str = NULL; + } + + paths_ok = path_system_init (paths); + + if (paths_ok && verbosity) { + int g; + assert(Gtbpath!=NULL); + sjoin(ini_str,"\nGTB PATHS\n",INISIZE); + for (g = 0; Gtbpath[g] != NULL; g++) { + const char *p = Gtbpath[g]; + if (0 == g) { + sprintf (localstr," main: %s\n", p); + } else { + sprintf (localstr," #%d: %s\n", g, p); + } + sjoin(ini_str,localstr,INISIZE); + } + } + + if (!paths_ok && verbosity) { + sjoin (ini_str,"\nGTB PATHS not initialized\n",INISIZE); + } + + if (!reach_was_initialized()) + reach_init(); + + attack_maps_init (); /* external initialization */ + + init_indexing(0 /* no verbosity */); + + #ifdef GTB_SHARE + init_bettarr(); + #endif + + if (!fd_init (&fd) && verbosity) { + sjoin (ini_str," File Open Memory initialization = **FAILED**\n",INISIZE); + return ret_str; + } + + GTB_scheme = decoding_sch; + Uncompressed = GTB_scheme == 0; + + if (GTB_scheme == 0) { + Uncompressed = TRUE; + } + + set_decoding_scheme(GTB_scheme); + + if (verbosity) { + sjoin (ini_str,"\nGTB initialization\n",INISIZE); + sprintf (localstr," Compression Scheme = %d\n", GTB_scheme); + sjoin (ini_str,localstr,INISIZE); + } + + zi = zipinfo_init(); + + TB_AVAILABILITY = zi; + + if (verbosity) { + if (0 == zi) { + sjoin (ini_str," Compression Indexes = **FAILED**\n",INISIZE); + } else { + int n, bit; + + n = 3; bit = 1; + if (zi&(1u<n = 0; + + allowed = mysys_fopen_max() - 5 /*stdin,stdout,sterr,stdlog,book*/; + if (allowed < 4) + GTB_MAXOPEN = 4; + if (allowed > 32) + GTB_MAXOPEN = 32; + + p = (tbkey_t *) malloc(sizeof(tbkey_t)*(size_t)GTB_MAXOPEN); + + if (p != NULL) { + for (i = 0; i < GTB_MAXOPEN; i++) { + p[i] = -1; + } + pfd->key = p; + return TRUE; + } else { + return FALSE; + } +} + +static void +fd_done (struct filesopen *pfd) +{ + int i; + tbkey_t closingkey; + FILE *finp; + + assert(pfd != NULL); + + for (i = 0; i < pfd->n; i++) { + closingkey = pfd->key[i]; + finp = egkey [closingkey].fd; + fclose (finp); + egkey[closingkey].fd = NULL; + pfd->key[i] = -1; + } + pfd->n = 0; + free(pfd->key); +} + +/****************************************************************************\ +| +| +| PROBE ZONE +| +| +\****************************************************************************/ + +#if !defined(SHARED_forbuilding) + +/* shared with building routines */ +mySHARED void list_sq_copy (const SQUARE *a, SQUARE *b); +mySHARED void list_pc_copy (const SQ_CONTENT *a, SQ_CONTENT *b); +mySHARED dtm_t inv_dtm (dtm_t x); +mySHARED bool_t egtb_get_id (SQ_CONTENT *w, SQ_CONTENT *b, tbkey_t *id); +mySHARED void list_sq_flipNS (SQUARE *s); +mySHARED dtm_t adjust_up (dtm_t dist); +mySHARED dtm_t bestx (unsigned stm, dtm_t a, dtm_t b); +mySHARED void sortlists (SQUARE *ws, SQ_CONTENT *wp); + +mySHARED /*@NULL@*/ FILE * fd_openit(tbkey_t key); + +mySHARED dtm_t dtm_unpack (unsigned stm, unsigned char packed); +mySHARED void unpackdist (dtm_t d, unsigned int *res, unsigned int *ply); +mySHARED dtm_t packdist (unsigned int inf, unsigned int ply); + +mySHARED bool_t fread_entry_packed (FILE *dest, unsigned side, dtm_t *px); +mySHARED bool_t fpark_entry_packed (FILE *finp, unsigned side, index_t max, index_t idx); +#endif + +/* use only with probe */ +static bool_t egtb_get_dtm (tbkey_t k, unsigned stm, const SQUARE *wS, const SQUARE *bS, bool_t probe_hard, dtm_t *dtm); +static void removepiece (SQUARE *ys, SQ_CONTENT *yp, int j); +static bool_t egtb_filepeek (tbkey_t key, unsigned side, index_t idx, dtm_t *out_dtm); + + +/*prototype*/ +#ifdef WDL_PROBE +static bool_t +tb_probe_wdl + (unsigned stm, + const SQUARE *inp_wSQ, + const SQUARE *inp_bSQ, + const SQ_CONTENT *inp_wPC, + const SQ_CONTENT *inp_bPC, + bool_t probingtype, + /*@out@*/ unsigned *res); +#endif + +static bool_t +tb_probe_ (unsigned stm, + SQUARE epsq, + const SQUARE *inp_wSQ, + const SQUARE *inp_bSQ, + const SQ_CONTENT *inp_wPC, + const SQ_CONTENT *inp_bPC, + bool_t probingtype, + /*@out@*/ unsigned *res, + /*@out@*/ unsigned *ply); + + +extern bool_t +tb_probe_soft + (unsigned stm, + SQUARE epsq, + unsigned castles, + const SQUARE *inp_wSQ, + const SQUARE *inp_bSQ, + const SQ_CONTENT *inp_wPC, + const SQ_CONTENT *inp_bPC, + /*@out@*/ unsigned *res, + /*@out@*/ unsigned *ply) +{ + if (castles != 0) + return FALSE; + return tb_probe_ (stm, epsq, inp_wSQ, inp_bSQ, inp_wPC, inp_bPC, FALSE, res, ply); +} + +extern bool_t +tb_probe_hard + (unsigned stm, + SQUARE epsq, + unsigned castles, + const SQUARE *inp_wSQ, + const SQUARE *inp_bSQ, + const SQ_CONTENT *inp_wPC, + const SQ_CONTENT *inp_bPC, + /*@out@*/ unsigned *res, + /*@out@*/ unsigned *ply) +{ + if (castles != 0) + return FALSE; + return tb_probe_ (stm, epsq, inp_wSQ, inp_bSQ, inp_wPC, inp_bPC, TRUE, res, ply); +} + +extern bool_t +tb_probe_WDL_soft + (unsigned stm, + SQUARE epsq, + unsigned castles, + const SQUARE *inp_wSQ, + const SQUARE *inp_bSQ, + const SQ_CONTENT *inp_wPC, + const SQ_CONTENT *inp_bPC, + /*@out@*/ unsigned *res) +{ + unsigned ply_n; + unsigned *ply = &ply_n; + if (castles != 0) + return FALSE; + if (epsq != NOSQUARE) + return tb_probe_ (stm, epsq, inp_wSQ, inp_bSQ, inp_wPC, inp_bPC, FALSE, res, ply); + + /* probe bitbase like, assuming no en passant */ + #ifdef WDL_PROBE + return tb_probe_wdl (stm, inp_wSQ, inp_bSQ, inp_wPC, inp_bPC, FALSE, res); + #else + return tb_probe_ (stm, epsq, inp_wSQ, inp_bSQ, inp_wPC, inp_bPC, FALSE, res, ply); + #endif +} + +extern bool_t +tb_probe_WDL_hard + (unsigned stm, + SQUARE epsq, + unsigned castles, + const SQUARE *inp_wSQ, + const SQUARE *inp_bSQ, + const SQ_CONTENT *inp_wPC, + const SQ_CONTENT *inp_bPC, + /*@out@*/ unsigned *res) +{ + unsigned ply_n; + unsigned *ply = &ply_n; + if (castles != 0) + return FALSE; + if (epsq != NOSQUARE) + return tb_probe_ (stm, epsq, inp_wSQ, inp_bSQ, inp_wPC, inp_bPC, TRUE, res, ply); + + /* probe bitbase like, assuming no en passant */ + #ifdef WDL_PROBE + return tb_probe_wdl (stm, inp_wSQ, inp_bSQ, inp_wPC, inp_bPC, TRUE, res); + #else + return tb_probe_ (stm, epsq, inp_wSQ, inp_bSQ, inp_wPC, inp_bPC, TRUE, res, ply); + #endif +} + + +static bool_t +tb_probe_ (unsigned stm, + SQUARE epsq, + const SQUARE *inp_wSQ, + const SQUARE *inp_bSQ, + const SQ_CONTENT *inp_wPC, + const SQ_CONTENT *inp_bPC, + bool_t probingtype, + /*@out@*/ unsigned *res, + /*@out@*/ unsigned *ply) +{ + int i = 0, j = 0; + tbkey_t id = -1; + dtm_t dtm; + + SQUARE storage_ws [MAX_LISTSIZE], storage_bs [MAX_LISTSIZE]; + SQ_CONTENT storage_wp [MAX_LISTSIZE], storage_bp [MAX_LISTSIZE]; + + SQUARE *ws = storage_ws; + SQUARE *bs = storage_bs; + SQ_CONTENT *wp = storage_wp; + SQ_CONTENT *bp = storage_bp; + + SQUARE *xs; + SQUARE *ys; + SQ_CONTENT *xp; + SQ_CONTENT *yp; + + SQUARE tmp_ws [MAX_LISTSIZE], tmp_bs [MAX_LISTSIZE]; + SQ_CONTENT tmp_wp [MAX_LISTSIZE], tmp_bp [MAX_LISTSIZE]; + + SQUARE *temps; + bool_t straight = FALSE; + + SQUARE capturer_a, capturer_b, xed = NOSQUARE; + + unsigned int plies; + unsigned int inf; + + bool_t okdtm = TRUE; + bool_t okcall = TRUE; + + /************************************/ + + assert (stm == WH || stm == BL); + /*assert (inp_wPC[0] == KING && inp_bPC[0] == KING );*/ + assert ((epsq >> 3) == 2 || (epsq >> 3) == 5 || epsq == NOSQUARE); + + /* VALID ONLY FOR KK!! */ + if (inp_wPC[1] == NOPIECE && inp_bPC[1] == NOPIECE) { + index_t dummy_i; + bool_t b = kxk_pctoindex (inp_wSQ, inp_bSQ, &dummy_i); + *res = b? iDRAW: iFORBID; + *ply = 0; + return TRUE; + } + + /* copy input */ + list_pc_copy (inp_wPC, wp); + list_pc_copy (inp_bPC, bp); + list_sq_copy (inp_wSQ, ws); + list_sq_copy (inp_bSQ, bs); + + sortlists (ws, wp); + sortlists (bs, bp); + + FOLLOW_label("EGTB_PROBE") + + if (egtb_get_id (wp, bp, &id)) { + FOLLOW_LU("got ID",id) + straight = TRUE; + } else if (egtb_get_id (bp, wp, &id)) { + FOLLOW_LU("rev ID",id) + straight = FALSE; + list_sq_flipNS (ws); + list_sq_flipNS (bs); + temps = ws; + ws = bs; + bs = temps; + stm = Opp(stm); + if (epsq != NOSQUARE) epsq ^= 070; /* added */ + {SQ_CONTENT *tempp = wp; wp = bp; bp = tempp;} /* added */ + } else { + #if defined(DEBUG) + printf("did not get id...\n"); + output_state (stm, ws, bs, wp, bp); + #endif + unpackdist (iFORBID, res, ply); + return FALSE; + } + + /* store position... */ + list_pc_copy (wp, tmp_wp); + list_pc_copy (bp, tmp_bp); + list_sq_copy (ws, tmp_ws); + list_sq_copy (bs, tmp_bs); + + /* x will be stm and y will be stw */ + if (stm == WH) { + xs = ws; + xp = wp; + ys = bs; + yp = bp; + } else { + xs = bs; + xp = bp; + ys = ws; + yp = wp; + } + + okdtm = egtb_get_dtm (id, stm, ws, bs, probingtype, &dtm); + + FOLLOW_LU("dtmok?",okdtm) + FOLLOW_DTM("dtm", dtm) + + if (okdtm) { + + capturer_a = NOSQUARE; + capturer_b = NOSQUARE; + + if (epsq != NOSQUARE) { + /* captured pawn, trick: from epsquare to captured */ + xed = epsq ^ (1<<3); + + /* find index captured (j) */ + for (j = 0; ys[j] != NOSQUARE; j++) { + if (ys[j] == xed) break; + } + + /* try first possible ep capture */ + if (0 == (0x88 & (map88(xed) + 1))) + capturer_a = xed + 1; + /* try second possible ep capture */ + if (0 == (0x88 & (map88(xed) - 1))) + capturer_b = xed - 1; + + if (ys[j] == xed) { + + /* find capturers (i) */ + for (i = 0; xs[i] != NOSQUARE && okcall; i++) { + + if (xp[i]==PAWN && (xs[i]==capturer_a || xs[i]==capturer_b)) { + dtm_t epscore = iFORBID; + + /* execute capture */ + xs[i] = epsq; + removepiece (ys, yp, j); + + okcall = tb_probe_ (Opp(stm), NOSQUARE, ws, bs, wp, bp, probingtype, &inf, &plies); + + if (okcall) { + epscore = packdist (inf, plies); + epscore = adjust_up (epscore); + + /* chooses to ep or not */ + dtm = bestx (stm, epscore, dtm); + } + + /* restore position */ + list_pc_copy (tmp_wp, wp); + list_pc_copy (tmp_bp, bp); + + list_sq_copy (tmp_ws, ws); + list_sq_copy (tmp_bs, bs); + } + } + } + } /* ep */ + + if (straight) { + unpackdist (dtm, res, ply); + } else { + unpackdist (inv_dtm (dtm), res, ply); + } + } + + if (!okdtm || !okcall) { + unpackdist (iFORBID, res, ply); + } + + return okdtm && okcall; +} + +#ifdef _MSC_VER +/* to silence warning for sprintf usage */ +#pragma warning(disable:4996) +#endif + +static bool_t +egtb_filepeek (tbkey_t key, unsigned side, index_t idx, dtm_t *out_dtm) +{ + FILE *finp; + +#define USE_FD + + #if !defined(USE_FD) + char buf[1024]; + char *filename = buf; + #endif + + bool_t ok; + dtm_t x=0; + index_t maxindex = egkey[key].maxindex; + + + + assert (Uncompressed); + assert (side == WH || side == BL); + assert (out_dtm != NULL); + assert (idx >= 0); + assert (key < MAX_EGKEYS); + + + #if defined(USE_FD) + if (NULL == (finp = egkey[key].fd) ) { + if (NULL == (finp = fd_openit (key))) { + return FALSE; + } + } + #else + sprintf (buf, "%s.gtb", egkey[key].str); + if (NULL == (finp = fopen (filename, "rb"))) { + return FALSE; + } + #endif + + ok = fpark_entry_packed (finp, side, maxindex, idx); + ok = ok && fread_entry_packed (finp, side, &x); + + if (ok) { + *out_dtm = x; + } else + *out_dtm = iFORBID; + + #if !defined(USE_FD) + fclose (finp); + #endif + + return ok; +} + +/* will get defined later */ +static bool_t dtm_cache_is_on (void); + +static bool_t +egtb_get_dtm (tbkey_t k, unsigned stm, const SQUARE *wS, const SQUARE *bS, bool_t probe_hard_flag, dtm_t *dtm) +{ + bool_t idxavail; + index_t idx; + dtm_t *tab[2]; + bool_t (*pc2idx) (const SQUARE *, const SQUARE *, index_t *); + + FOLLOW_label("egtb_get_dtm --> starts") + + if (egkey[k].status == STATUS_MALLOC || egkey[k].status == STATUS_STATICRAM) { + + tab[WH] = egkey[k].egt_w; + tab[BL] = egkey[k].egt_b; + pc2idx = egkey[k].pctoi; + + idxavail = pc2idx (wS, bS, &idx); + + FOLLOW_LU("indexavail (RAM)",idxavail) + + if (idxavail) { + *dtm = tab[stm][idx]; + } else { + *dtm = iFORBID; + } + + return TRUE; + + } else if (egkey[k].status == STATUS_ABSENT) { + + pc2idx = egkey[k].pctoi; + idxavail = pc2idx (wS, bS, &idx); + + FOLLOW_LU("indexavail (HD)",idxavail) + + if (idxavail) { + bool_t success; + + /* + | LOCK + *-------------------------------*/ + mythread_mutex_lock (&Egtb_lock); + + if (dtm_cache_is_on()) { + + success = get_dtm (k, stm, idx, dtm, probe_hard_flag); + + FOLLOW_LU("get_dtm (succ)",success) + FOLLOW_LU("get_dtm (dtm )",*dtm) + + #if defined(DEBUG) + if (Uncompressed) { + dtm_t dtm_temp; + bool_t ok; + bool_t success2; + + assert (decoding_scheme() == 0 && GTB_scheme == 0); + + success2 = egtb_filepeek (k, stm, idx, &dtm_temp); + ok = (success == success2) && (!success || *dtm == dtm_temp); + if (!ok) { + printf ("\nERROR\nsuccess1=%d sucess2=%d\n" + "k=%d stm=%u idx=%d dtm_peek=%d dtm_cache=%d\n", + success, success2, k, stm, idx, dtm_temp, *dtm); + fatal_error(); + } + } + #endif + + } else { + assert(Uncompressed); + if (probe_hard_flag && Uncompressed) + success = egtb_filepeek (k, stm, idx, dtm); + else + success = FALSE; + } + + mythread_mutex_unlock (&Egtb_lock); + /*------------------------------*\ + | UNLOCK + */ + + + if (success) { + return TRUE; + } else { + if (probe_hard_flag) /* after probing hard and failing, no chance to succeed later */ + egkey[k].status = STATUS_REJECT; + *dtm = iUNKNOWN; + return FALSE; + } + + } else { + *dtm = iFORBID; + return TRUE; + } + + } else if (egkey[k].status == STATUS_REJECT) { + + FOLLOW_label("STATUS_REJECT") + + *dtm = iFORBID; + return FALSE; + } else { + + FOLLOW_label("STATUS_WRONG!") + + assert(0); + *dtm = iFORBID; + return FALSE; + } + +} + +static void +removepiece (SQUARE *ys, SQ_CONTENT *yp, int j) +{ + int k; + for (k = j; ys[k] != NOSQUARE; k++) { + ys[k] = ys[k+1]; + yp[k] = yp[k+1]; + } +} + +/* +| +| mySHARED by probe and build +| +\*----------------------------------------------------*/ + +mySHARED /*@NULL@*/ FILE * +fd_openit (tbkey_t key) +{ + int i; + tbkey_t closingkey; + FILE * finp = NULL; + char buf[4096]; + char * filename = buf; + int start; + int end; + int pth; + const char * extension; + + assert (0 <= key && key < MAX_EGKEYS); + assert (0 <= fd.n && fd.n <= GTB_MAXOPEN); + + /* test if I reach limit of files open */ + if (fd.n == GTB_MAXOPEN) { + + /* fclose the last accessed, first in the list */ + closingkey = fd.key[0]; + finp = egkey [closingkey].fd; + assert (finp != NULL); + fclose (finp); + egkey[closingkey].fd = NULL; + finp = NULL; + + for (i = 1; i < fd.n; i++) { + fd.key[i-1] = fd.key[i]; + } + fd.key[--fd.n] = -1; + } + + assert (fd.n < GTB_MAXOPEN); + + /* set proper extensions to the File */ + if (Uncompressed) { + assert (decoding_scheme() == 0 && GTB_scheme == 0); + extension = ".gtb"; + } else { + extension = Extension[decoding_scheme()]; + } + + /* Scan folders to find the File*/ + finp = NULL; + + start = egkey[key].pathn; + end = Gtbpath_end_index; + +/*@@ +printf ("start: %d\n",start); +printf ("===================Gtbpath[0]=%s\n",Gtbpath[0]); +*/ + for (pth = start; NULL == finp && pth < end && Gtbpath[pth] != NULL; pth++) { + const char *path = Gtbpath[pth]; + size_t pl = strlen(path); +/*@@ +printf ("path: %s\n",path); +*/ + if (pl == 0) { + sprintf (buf, "%s%s%s", path, egkey[key].str, extension); + } else { + if (isfoldersep( path[pl-1] )) { + sprintf (buf, "%s%s%s", path, egkey[key].str, extension); + } else { + sprintf (buf, "%s%s%s%s", path, FOLDERSEP, egkey[key].str, extension); + } + } +/*printf ("try to open %s --> ",filename);*/ + /* Finally found the file? */ + finp = fopen (filename, "rb"); +/*printf ("%d\n",finp != NULL);*/ + } + + /* File was found and opened */ + if (NULL != finp) { + fd.key [fd.n++] = key; + egkey[key].fd = finp; + egkey[key].pathn = pth; /* remember succesful path */ + eg_was_open[key] = 1; + return finp; + } + + start = 0; + end = egkey[key].pathn; + for (pth = start; NULL == finp && pth < end && Gtbpath[pth] != NULL; pth++) { + const char *path = Gtbpath[pth]; + size_t pl = strlen(path); + + if (pl == 0) { + sprintf (buf, "%s%s%s", path, egkey[key].str, extension); + } else { + if (isfoldersep( path[pl-1] )) { + sprintf (buf, "%s%s%s", path, egkey[key].str, extension); + } else { + sprintf (buf, "%s%s%s%s", path, FOLDERSEP, egkey[key].str, extension); + } + } +/*printf ("try to open %s --> ",filename);*/ + /* Finally found the file? */ + finp = fopen (filename, "rb"); +/*printf ("%d\n",finp != NULL);*/ + } + + + /* File was found and opened */ + if (NULL != finp) { + fd.key [fd.n++] = key; + egkey[key].fd = finp; + egkey[key].pathn = pth; /* remember succesful path */ + eg_was_open[key] = 1; + } + + return finp; +} + +#ifdef _MSC_VER +/* to silence warning for sprintf usage */ +#pragma warning(default:4996) +#endif + +mySHARED void +sortlists (SQUARE *ws, SQ_CONTENT *wp) +{ + int i, j; + SQUARE ts; + SQ_CONTENT tp; + /* input is sorted */ + for (i = 0; wp[i] != NOPIECE; i++) { + for (j = (i+1); wp[j] != NOPIECE; j++) { + if (wp[j] > wp[i]) { + tp = wp[i]; wp[i] = wp[j]; wp[j] = tp; + ts = ws[i]; ws[i] = ws[j]; ws[j] = ts; + } + } + } +} + +mySHARED void +list_sq_copy (const SQUARE *a, SQUARE *b) +{ + while (NOSQUARE != (*b++ = *a++)) + ; +} + +mySHARED void +list_pc_copy (const SQ_CONTENT *a, SQ_CONTENT *b) +{ + while (NOPIECE != (*b++ = *a++)) + ; +} + +mySHARED dtm_t +inv_dtm (dtm_t x) +{ + unsigned mat; + assert ( (x & iUNKNBIT) == 0); + + if (x == iDRAW || x == iFORBID) + return x; + + mat = (unsigned)x & 3u; + if (mat == iWMATE) + mat = iBMATE; + else + mat = iWMATE; + + x = (dtm_t) (((unsigned)x & ~3u) | mat); + + return x; +} + +static const char pctoch[] = {'-','p','n','b','r','q','k'}; + +mySHARED bool_t +egtb_get_id (SQ_CONTENT *w, SQ_CONTENT *b, tbkey_t *id) +{ + + char pcstr[2*MAX_LISTSIZE]; + SQ_CONTENT *s; + char *t; + bool_t found; + tbkey_t i; + static tbkey_t cache_i = 0; + + assert (PAWN == 1 && KNIGHT == 2 && BISHOP == 3 && ROOK == 4 && QUEEN == 5 && KING == 6); + + t = pcstr; + + s = w; + while (NOPIECE != *s) + *t++ = pctoch[*s++]; + s = b; + while (NOPIECE != *s) + *t++ = pctoch[*s++]; + + *t = '\0'; + + found = (0 == strcmp(pcstr, egkey[cache_i].str)); + if (found) { + *id = cache_i; + return found; + } + + for (i = 0, found = FALSE; !found && egkey[i].str != NULL; i++) { + found = (0 == strcmp(pcstr, egkey[i].str)); + } + if (found) { + cache_i = *id = i - 1; + } + + return found; +} + +mySHARED void +list_sq_flipNS (SQUARE *s) +{ + while (*s != NOSQUARE) { + *s ^= 070; + s++; + } +} + +mySHARED void +unpackdist (dtm_t d, unsigned int *res, unsigned int *ply) +{ + *ply = (unsigned int)d >> PLYSHIFT; + *res = d & INFOMASK; +} + +mySHARED dtm_t +packdist (unsigned int inf, unsigned int ply) +{ + assert (inf <= INFOMASK); + return (dtm_t) (inf | ply << PLYSHIFT); +} + +mySHARED dtm_t +adjust_up (dtm_t dist) +{ + #if 0 + static const dtm_t adding[] = { + 0, 1<> 2; + + if (WH == stm) { + switch (info) { + case iWMATE: + moves = store + 1; + plies = moves * 2 - 1; + prefx = info; + break; + + case iBMATE: + moves = store; + plies = moves * 2; + prefx = info; + break; + + case iDRAW: + moves = store + 1 + 63; + plies = moves * 2 - 1; + prefx = iWMATE; + break; + + case iFORBID: + + moves = store + 63; + plies = moves * 2; + prefx = iBMATE; + break; + default: + plies = 0; + prefx = 0; + assert(0); + break; + + } + ret = (dtm_t) (prefx | (plies << 3)); + } else { + switch (info) { + case iBMATE: + moves = store + 1; + plies = moves * 2 - 1; + prefx = info; + break; + + case iWMATE: + moves = store; + plies = moves * 2; + prefx = info; + break; + + case iDRAW: + + if (store == 63) { + /* exception: no position in the 5-man + TBs needs to store 63 for iBMATE + it is then used to indicate iWMATE + when just overflows */ + store++; + + moves = store + 63; + plies = moves * 2; + prefx = iWMATE; + + break; + } + + moves = store + 1 + 63; + plies = moves * 2 - 1; + prefx = iBMATE; + break; + + case iFORBID: + + moves = store + 63; + plies = moves * 2; + prefx = iWMATE; + break; + default: + plies = 0; + prefx = 0; + assert(0); + break; + + } + ret = (dtm_t) (prefx | (plies << 3)); + } + return ret; +} + + +/* +static bool_t fwrite_entry_packed (FILE *dest, unsigned side, dtm_t x); +*/ + + +mySHARED bool_t +fread_entry_packed (FILE *finp, unsigned side, dtm_t *px) +{ + unsigned char p[SLOTSIZE]; + bool_t ok = (SLOTSIZE == fread (p, sizeof(unsigned char), SLOTSIZE, finp)); + if (ok) { + *px = dtm_unpack (side, p[0]); + } + return ok; +} + + +mySHARED bool_t +fpark_entry_packed (FILE *finp, unsigned side, index_t max, index_t idx) +{ + bool_t ok; + index_t i; + long int fseek_i; + index_t sz = (index_t) sizeof(unsigned char); + + assert (side == WH || side == BL); + assert (finp != NULL); + assert (idx >= 0); + i = ((index_t)side * max + idx) * sz; + fseek_i = (long int) i; + assert (fseek_i >= 0); + ok = (0 == fseek (finp, fseek_i, SEEK_SET)); + return ok; +} + +/*----------------------------------------------------*\ +| +| shared by probe and build +| +\*/ + + +/*---------------------------------------------------------------------*\ +| WDL CACHE Implementation ZONE +\*---------------------------------------------------------------------*/ + +#define WDL_entries_per_unit 4 +#define WDL_entry_mask 3 +static size_t WDL_units_per_block = 0; + +static bool_t WDL_CACHE_INITIALIZED = FALSE; + +typedef unsigned char unit_t; /* block unit */ + +typedef struct wdl_block wdl_block_t; + +struct wdl_block { + tbkey_t key; + unsigned side; + index_t offset; + unit_t *p_arr; + wdl_block_t *prev; + wdl_block_t *next; +}; + +struct WDL_CACHE { + /* defined at init */ + bool_t cached; + size_t max_blocks; + size_t entries_per_block; + unit_t * buffer; + + /* flushables */ + wdl_block_t * top; + wdl_block_t * bot; + size_t n; + wdl_block_t * blocks; /* was entry */ + + /* counters */ + uint64_t hard; + uint64_t soft; + uint64_t hardmisses; + uint64_t hits; + uint64_t softmisses; + uint64_t comparisons; +}; + +struct WDL_CACHE wdl_cache = {FALSE,0,0,NULL, + NULL,NULL,0,NULL, + 0,0,0,0,0,0}; + + +/*---------------------------------------------------------------------*\ +| DTM CACHE Implementation ZONE +\*---------------------------------------------------------------------*/ + +struct dtm_block; + +typedef struct dtm_block dtm_block_t; + +struct dtm_block { + tbkey_t key; + unsigned side; + index_t offset; + dtm_t *p_arr; + dtm_block_t *prev; + dtm_block_t *next; +}; + +struct cache_table { + /* defined at init */ + bool_t cached; + size_t max_blocks; + size_t entries_per_block; + dtm_t * buffer; + + /* flushables */ + dtm_block_t * top; + dtm_block_t * bot; + size_t n; + dtm_block_t * entry; + + /* counters */ + uint64_t hard; + uint64_t soft; + uint64_t hardmisses; + uint64_t hits; + uint64_t softmisses; + unsigned long comparisons; +}; + +struct cache_table dtm_cache = {FALSE,0,0,NULL, + NULL,NULL,0,NULL, + 0,0,0,0,0,0}; + +struct general_counters { + /* counters */ + uint64_t hits; + uint64_t miss; +}; + +static struct general_counters Drive = {0,0}; + + +static void split_index (size_t entries_per_block, index_t i, index_t *o, index_t *r); +static dtm_block_t *point_block_to_replace (void); +static bool_t preload_cache (tbkey_t key, unsigned side, index_t idx); +static void movetotop (dtm_block_t *t); + +/*--cache prototypes--------------------------------------------------------*/ + +/*- WDL --------------------------------------------------------------------*/ +#ifdef WDL_PROBE +static unsigned int wdl_extract (unit_t *uarr, index_t x); +static wdl_block_t * wdl_point_block_to_replace (void); +static void wdl_movetotop (wdl_block_t *t); + +#if 0 +static bool_t wdl_cache_init (size_t cache_mem); +static void wdl_cache_flush (void); +static bool_t get_WDL (tbkey_t key, unsigned side, index_t idx, unsigned int *info_out, bool_t probe_hard_flag); +#endif + +static bool_t wdl_cache_is_on (void); +static void wdl_cache_reset_counters (void); +static void wdl_cache_done (void); + +static wdl_block_t * wdl_point_block_to_replace (void); +static bool_t get_WDL_from_cache (tbkey_t key, unsigned side, index_t idx, unsigned int *out); +static void wdl_movetotop (wdl_block_t *t); +static bool_t wdl_preload_cache (tbkey_t key, unsigned side, index_t idx); +#endif +/*--------------------------------------------------------------------------*/ +/*- DTM --------------------------------------------------------------------*/ +static bool_t dtm_cache_is_on (void); +static void dtm_cache_reset_counters (void); +static void dtm_cache_done (void); + +static size_t dtm_cache_init (size_t cache_mem); +static void dtm_cache_flush (void); +/*--------------------------------------------------------------------------*/ + +static bool_t +dtm_cache_is_on (void) +{ + return dtm_cache.cached; +} + +static void +dtm_cache_reset_counters (void) +{ + dtm_cache.hard = 0; + dtm_cache.soft = 0; + dtm_cache.hardmisses = 0; + dtm_cache.hits = 0; + dtm_cache.softmisses = 0; + dtm_cache.comparisons = 0; + return; +} + + +static size_t +dtm_cache_init (size_t cache_mem) +{ + unsigned int i; + dtm_block_t *p; + size_t entries_per_block; + size_t max_blocks; + size_t block_mem; + + if (DTM_CACHE_INITIALIZED) + dtm_cache_done(); + + entries_per_block = 16 * 1024; /* fixed, needed for the compression schemes */ + + block_mem = entries_per_block * sizeof(dtm_t); + + max_blocks = cache_mem / block_mem; + if (!Uncompressed && 1 > max_blocks) + max_blocks = 1; + cache_mem = max_blocks * block_mem; + + + dtm_cache_reset_counters (); + + dtm_cache.entries_per_block = entries_per_block; + dtm_cache.max_blocks = max_blocks; + dtm_cache.cached = TRUE; + dtm_cache.top = NULL; + dtm_cache.bot = NULL; + dtm_cache.n = 0; + + if (0 == cache_mem || NULL == (dtm_cache.buffer = (dtm_t *) malloc (cache_mem))) { + dtm_cache.cached = FALSE; + dtm_cache.buffer = NULL; + dtm_cache.entry = NULL; + return 0; + } + + if (0 == max_blocks|| NULL == (dtm_cache.entry = (dtm_block_t *) malloc (max_blocks * sizeof(dtm_block_t)))) { + dtm_cache.cached = FALSE; + dtm_cache.entry = NULL; + free (dtm_cache.buffer); + dtm_cache.buffer = NULL; + return 0; + } + + for (i = 0; i < max_blocks; i++) { + p = &dtm_cache.entry[i]; + p->key = -1; + p->side = gtbNOSIDE; + p->offset = gtbNOINDEX; + p->p_arr = dtm_cache.buffer + i * entries_per_block; + p->prev = NULL; + p->next = NULL; + } + + DTM_CACHE_INITIALIZED = TRUE; + + return cache_mem; +} + + +static void +dtm_cache_done (void) +{ + assert(DTM_CACHE_INITIALIZED); + + dtm_cache.cached = FALSE; + dtm_cache.hard = 0; + dtm_cache.soft = 0; + dtm_cache.hardmisses = 0; + dtm_cache.hits = 0; + dtm_cache.softmisses = 0; + dtm_cache.comparisons = 0; + dtm_cache.max_blocks = 0; + dtm_cache.entries_per_block = 0; + + dtm_cache.top = NULL; + dtm_cache.bot = NULL; + dtm_cache.n = 0; + + if (dtm_cache.buffer != NULL) + free (dtm_cache.buffer); + dtm_cache.buffer = NULL; + + if (dtm_cache.entry != NULL) + free (dtm_cache.entry); + dtm_cache.entry = NULL; + + DTM_CACHE_INITIALIZED = FALSE; + + return; +} + +static void +dtm_cache_flush (void) +{ + unsigned int i; + dtm_block_t *p; + size_t entries_per_block = dtm_cache.entries_per_block; + size_t max_blocks = dtm_cache.max_blocks; + + dtm_cache.top = NULL; + dtm_cache.bot = NULL; + dtm_cache.n = 0; + + for (i = 0; i < max_blocks; i++) { + p = &dtm_cache.entry[i]; + p->key = -1; + p->side = gtbNOSIDE; + p->offset = gtbNOINDEX; + p->p_arr = dtm_cache.buffer + i * entries_per_block; + p->prev = NULL; + p->next = NULL; + } + dtm_cache_reset_counters (); + return; +} + + +/*---- end tbcache zone ----------------------------------------------------------------------*/ + +extern bool_t +tbcache_is_on (void) +{ + return dtm_cache_is_on() || wdl_cache_is_on(); +} + + +/* STATISTICS OUTPUT */ + +extern void +tbstats_get (struct TB_STATS *x) +{ + long unsigned mask = 0xfffffffflu; + uint64_t memory_hits, total_hits; + + + /* + | WDL CACHE + \*---------------------------------------------------*/ + + x->wdl_easy_hits[0] = (long unsigned)(wdl_cache.hits & mask); + x->wdl_easy_hits[1] = (long unsigned)(wdl_cache.hits >> 32); + + x->wdl_hard_prob[0] = (long unsigned)(wdl_cache.hard & mask); + x->wdl_hard_prob[1] = (long unsigned)(wdl_cache.hard >> 32); + + x->wdl_soft_prob[0] = (long unsigned)(wdl_cache.soft & mask); + x->wdl_soft_prob[1] = (long unsigned)(wdl_cache.soft >> 32); + + x->wdl_cachesize = WDL_cache_size; + + /* occupancy */ + x->wdl_occupancy = wdl_cache.max_blocks==0? 0:(double)100.0*(double)wdl_cache.n/(double)wdl_cache.max_blocks; + + /* + | DTM CACHE + \*---------------------------------------------------*/ + + x->dtm_easy_hits[0] = (long unsigned)(dtm_cache.hits & mask); + x->dtm_easy_hits[1] = (long unsigned)(dtm_cache.hits >> 32); + + x->dtm_hard_prob[0] = (long unsigned)(dtm_cache.hard & mask); + x->dtm_hard_prob[1] = (long unsigned)(dtm_cache.hard >> 32); + + x->dtm_soft_prob[0] = (long unsigned)(dtm_cache.soft & mask); + x->dtm_soft_prob[1] = (long unsigned)(dtm_cache.soft >> 32); + + x->dtm_cachesize = DTM_cache_size; + + /* occupancy */ + x->dtm_occupancy = dtm_cache.max_blocks==0? 0:(double)100.0*(double)dtm_cache.n/(double)dtm_cache.max_blocks; + + /* + | GENERAL + \*---------------------------------------------------*/ + + /* memory */ + memory_hits = wdl_cache.hits + dtm_cache.hits; + x->memory_hits[0] = (long unsigned)(memory_hits & mask); + x->memory_hits[1] = (long unsigned)(memory_hits >> 32); + + /* hard drive */ + x->drive_hits[0] = (long unsigned)(Drive.hits & mask); + x->drive_hits[1] = (long unsigned)(Drive.hits >> 32); + + x->drive_miss[0] = (long unsigned)(Drive.miss & mask); + x->drive_miss[1] = (long unsigned)(Drive.miss >> 32); + + x->bytes_read[0] = (long unsigned)(Bytes_read & mask); + x->bytes_read[1] = (long unsigned)(Bytes_read >> 32); + + x->files_opened = eg_was_open_count(); + + /* total */ + total_hits = memory_hits + Drive.hits; + x->total_hits[0] = (long unsigned)(total_hits & mask); + x->total_hits[1] = (long unsigned)(total_hits >> 32); + + /* efficiency */ + { uint64_t denominator = memory_hits + Drive.hits + Drive.miss; + x->memory_efficiency = 0==denominator? 0: 100.0 * (double)(memory_hits) / (double)(denominator); + } +} + + +extern bool_t +tbcache_init (size_t cache_mem, int wdl_fraction) +{ + assert (wdl_fraction <= WDL_FRACTION_MAX && wdl_fraction >= 0); + + /* defensive against input */ + if (wdl_fraction > WDL_FRACTION_MAX) wdl_fraction = WDL_FRACTION_MAX; + if (wdl_fraction < 0) wdl_fraction = 0; + WDL_FRACTION = wdl_fraction; + + DTM_cache_size = (cache_mem/(size_t)WDL_FRACTION_MAX)*(size_t)(WDL_FRACTION_MAX-WDL_FRACTION); + WDL_cache_size = (cache_mem/(size_t)WDL_FRACTION_MAX)*(size_t) WDL_FRACTION ; + + #ifdef WDL_PROBE + /* returns the actual memory allocated */ + DTM_cache_size = dtm_cache_init (DTM_cache_size); + WDL_cache_size = wdl_cache_init (WDL_cache_size); + #else + /* returns the actual memory allocated */ + DTM_cache_size = dtm_cache_init (DTM_cache_size); + #endif + tbstats_reset (); + return TRUE; +} + +extern bool_t +tbcache_restart (size_t cache_mem, int wdl_fraction) +{ + return tbcache_init (cache_mem, wdl_fraction); +} + +extern void +tbcache_done (void) +{ + dtm_cache_done(); + #ifdef WDL_PROBE + wdl_cache_done(); + #endif + tbstats_reset (); + return; +} + +extern void +tbcache_flush (void) +{ + dtm_cache_flush(); + #ifdef WDL_PROBE + wdl_cache_flush(); + #endif + tbstats_reset (); + return; +} + +extern void +tbstats_reset (void) +{ + dtm_cache_reset_counters (); + #ifdef WDL_PROBE + wdl_cache_reset_counters (); + #endif + eg_was_open_reset(); + Drive.hits = 0; + Drive.miss = 0; + return; +} + +static dtm_block_t * +dtm_cache_pointblock (tbkey_t key, unsigned side, index_t idx) +{ + index_t offset; + index_t remainder; + dtm_block_t * p; + dtm_block_t * ret; + + if (!dtm_cache_is_on()) + return NULL; + + split_index (dtm_cache.entries_per_block, idx, &offset, &remainder); + + ret = NULL; + + for (p = dtm_cache.top; p != NULL; p = p->prev) { + + dtm_cache.comparisons++; + + if (key == p->key && side == p->side && offset == p->offset) { + ret = p; + break; + } + } + + FOLLOW_LU("point_to_dtm_block ok?",(ret!=NULL)) + + return ret; +} + +/****************************************************************************\ +| +| +| WRAPPERS for ENCODING/DECODING FUNCTIONS ZONE +| +| +\****************************************************************************/ + +#include "gtb-dec.h" + +/* +| +| PRE LOAD CACHE AND DEPENDENT FUNCTIONS +| +\*--------------------------------------------------------------------------*/ + +struct ZIPINFO { + index_t extraoffset; + index_t totalblocks; + index_t * blockindex; +}; + +struct ZIPINFO Zipinfo[MAX_EGKEYS]; + +static index_t egtb_block_getnumber (tbkey_t key, unsigned side, index_t idx); +static index_t egtb_block_getsize (tbkey_t key, index_t idx); +static index_t egtb_block_getsize_zipped (tbkey_t key, index_t block ); +static bool_t egtb_block_park (tbkey_t key, index_t block); +static bool_t egtb_block_read (tbkey_t key, index_t len, unsigned char *buffer); +static bool_t egtb_block_decode (tbkey_t key, index_t z, unsigned char *bz, index_t n, unsigned char *bp); +static bool_t egtb_block_unpack (unsigned side, index_t n, const unsigned char *bp, dtm_t *out); +static bool_t egtb_file_beready (tbkey_t key); +static bool_t egtb_loadindexes (tbkey_t key); +static index_t egtb_block_uncompressed_to_index (tbkey_t key, index_t b); +static bool_t fread32 (FILE *f, unsigned long int *y); + + +static unsigned int +zipinfo_init (void) +{ + int i, start, end; + unsigned ret; + bool_t ok, complet[8] = {0,0,0,0,0,0,0,0}; + bool_t pa, partial[8] = {0,0,0,0,0,0,0,0}; + unsigned int z; + int x, j; + + /* reset all values */ + for (i = 0; i < MAX_EGKEYS; i++) { + Zipinfo[i].blockindex = NULL; + Zipinfo[i].extraoffset = 0; + Zipinfo[i].totalblocks = 0; + } + + /* load all values */ + start = 0; + end = 5; + x = 3; + for (i = start, ok = TRUE, pa = FALSE; i < end; i++) { + ok = NULL != fd_openit(i); + pa = pa || ok; + ok = ok && egtb_loadindexes (i); + } + complet[x] = ok; + partial[x] = pa; + + start = 5; + end = 35; + x = 4; + for (i = start, ok = TRUE, pa = FALSE; i < end; i++) { + ok = NULL != fd_openit(i); + pa = pa || ok; + ok = ok && egtb_loadindexes (i); + } + complet[x] = ok; + partial[x] = pa; + + start = 35; + end = MAX_EGKEYS; + x = 5; + for (i = start, ok = TRUE, pa = FALSE; i < end; i++) { + ok = NULL != fd_openit(i); + pa = pa || ok; + ok = ok && egtb_loadindexes (i); + } + complet[x] = ok; + partial[x] = pa; + + + for (j = 0, z = 0, x = 3; x < 8; x++) { + if (partial[x]) z |= 1u << j; + j++; + if (complet[x]) z |= 1u << j; + j++; + } + + ret = z; + + return ret; +} + +static void +zipinfo_done (void) +{ + int i; + bool_t ok; + for (i = 0, ok = TRUE; ok && i < MAX_EGKEYS; i++) { + if (Zipinfo[i].blockindex != NULL) { + free(Zipinfo[i].blockindex); + Zipinfo[i].blockindex = NULL; + Zipinfo[i].extraoffset = 0; + Zipinfo[i].totalblocks = 0; + } + } + return; +} + +static size_t +zipinfo_memory_allocated (void) +{ + int i; + index_t accum_blocks = 0; + for (i = 0; i < MAX_EGKEYS; i++) { + if (Zipinfo[i].blockindex != NULL) { + accum_blocks += Zipinfo[i].totalblocks; + } + } + return (size_t)accum_blocks * sizeof(index_t); +} + +extern size_t +tb_indexmemory (void) +{ + return zipinfo_memory_allocated (); +} + +static bool_t +fread32 (FILE *f, unsigned long int *y) +{ + enum SIZE {SZ = 4}; + int i; + unsigned long int x; + unsigned char p[SZ]; + bool_t ok; + + ok = (SZ == fread (p, sizeof(unsigned char), SZ, f)); + + if (ok) { + for (x = 0, i = 0; i < SZ; i++) { + x |= (unsigned long int)p[i] << (i*8); + } + *y = x; + } + return ok; +} + +static bool_t +egtb_loadindexes (tbkey_t key) +{ + + unsigned long int blocksize = 1; + unsigned long int tailblocksize1 = 0; + unsigned long int tailblocksize2 = 0; + unsigned long int offset=0; + unsigned long int dummy; + unsigned long int i; + unsigned long int blocks; + unsigned long int n_idx; + unsigned long int idx; + index_t *p; + + bool_t ok; + + FILE *f; + + if (Uncompressed) { + assert (decoding_scheme() == 0 && GTB_scheme == 0); + return TRUE; /* no need to load indexes */ + } + if (Zipinfo[key].blockindex != NULL) + return TRUE; /* indexes must have been loaded already */ + + if (NULL == (f = egkey[key].fd)) + return FALSE; /* file was no open */ + + /* Get Reserved bytes, blocksize, offset */ + ok = (0 == fseek (f, 0, SEEK_SET)) && + fread32 (f, &dummy) && + fread32 (f, &dummy) && + fread32 (f, &blocksize) && + fread32 (f, &dummy) && + fread32 (f, &tailblocksize1) && + fread32 (f, &dummy) && + fread32 (f, &tailblocksize2) && + fread32 (f, &dummy) && + fread32 (f, &offset) && + fread32 (f, &dummy); + + blocks = (offset - 40)/4 -1; + n_idx = blocks + 1; + + p = NULL; + + ok = ok && NULL != (p = (index_t *)malloc (n_idx * sizeof(index_t))); + + /* Input of Indexes */ + for (i = 0; ok && i < n_idx; i++) { + ok = fread32 (f, &idx); + p[i] = (index_t)idx; /* reads a 32 bit int, and converts it to index_t */ assert (sizeof(index_t) >= 4); + } + + if (ok) { + Zipinfo[key].extraoffset = 0; + assert (n_idx <= MAXINDEX_T); + Zipinfo[key].totalblocks = (index_t) n_idx; + Zipinfo[key].blockindex = p; + } + + if (!ok && p != NULL) { + free(p); + } + + return ok; +} + +static index_t +egtb_block_uncompressed_to_index (tbkey_t key, index_t b) +{ + index_t max; + index_t blocks_per_side; + index_t idx; + + max = egkey[key].maxindex; + blocks_per_side = 1 + (max-1) / (index_t)dtm_cache.entries_per_block; + + if (b < blocks_per_side) { + idx = 0; + } else { + b -= blocks_per_side; + idx = max; + } + idx += b * (index_t)dtm_cache.entries_per_block; + return idx; +} + + +static index_t +egtb_block_getnumber (tbkey_t key, unsigned side, index_t idx) +{ + index_t blocks_per_side; + index_t block_in_side; + index_t max = egkey[key].maxindex; + + blocks_per_side = 1 + (max-1) / (index_t)dtm_cache.entries_per_block; + block_in_side = idx / (index_t)dtm_cache.entries_per_block; + + return (index_t)side * blocks_per_side + block_in_side; /* block */ +} + + +static index_t +egtb_block_getsize (tbkey_t key, index_t idx) +{ + index_t blocksz = (index_t) dtm_cache.entries_per_block; + index_t maxindex = egkey[key].maxindex; + index_t block, offset, x; + + assert (dtm_cache.entries_per_block <= MAXINDEX_T); + assert (0 <= idx && idx < maxindex); + assert (key < MAX_EGKEYS); + + block = idx / blocksz; + offset = block * blocksz; + + /* + | adjust block size in case that this is the last block + | and is shorter than "blocksz" + */ + if ( (offset + blocksz) > maxindex) + x = maxindex - offset; /* last block size */ + else + x = blocksz; /* size of a normal block */ + + return x; +} + +static index_t +egtb_block_getsize_zipped (tbkey_t key, index_t block ) +{ + index_t i, j; + assert (Zipinfo[key].blockindex != NULL); + i = Zipinfo[key].blockindex[block]; + j = Zipinfo[key].blockindex[block+1]; + return j - i; +} + + +static bool_t +egtb_file_beready (tbkey_t key) +{ + bool_t success; + assert (key < MAX_EGKEYS); + success = (NULL != egkey[key].fd) || + (NULL != fd_openit(key) && egtb_loadindexes (key)); + return success; +} + + +static bool_t +egtb_block_park (tbkey_t key, index_t block) +{ + index_t i; + long fseek_i; + assert (egkey[key].fd != NULL); + + if (Uncompressed) { + assert (decoding_scheme() == 0 && GTB_scheme == 0); + i = egtb_block_uncompressed_to_index (key, block); + } else { + assert (Zipinfo[key].blockindex != NULL); + i = Zipinfo[key].blockindex[block]; + i += Zipinfo[key].extraoffset; + } + + fseek_i = (long) i; + assert (fseek_i >= 0); + return 0 == fseek (egkey[key].fd, fseek_i, SEEK_SET); +} + + +static bool_t +egtb_block_read (tbkey_t key, index_t len, unsigned char *buffer) +{ + assert (egkey[key].fd != NULL); + assert (sizeof(size_t) >= sizeof(len)); + return ((size_t)len == fread (buffer, sizeof (unsigned char), (size_t)len, egkey[key].fd)); +} + +tbkey_t TB_PROBE_indexing_dummy; + +static bool_t +egtb_block_decode (tbkey_t key, index_t z, unsigned char *bz, index_t n, unsigned char *bp) +/* bz:buffer zipped to bp:buffer packed */ +{ + size_t zz = (size_t) z; + size_t nn = (size_t) n; + TB_PROBE_indexing_dummy = key; /* to silence compiler */ + assert (sizeof(size_t) >= sizeof(n)); + assert (sizeof(size_t) >= sizeof(z)); + return decode (zz-1, bz+1, nn, bp); +} + +static bool_t +egtb_block_unpack (unsigned side, index_t n, const unsigned char *bp, dtm_t *out) +/* bp:buffer packed to out:distance to mate buffer */ +{ + index_t i; + for (i = 0; i < n; i++) { + *out++ = dtm_unpack (side, bp[i]); + } + return TRUE; +} + +static bool_t +preload_cache (tbkey_t key, unsigned side, index_t idx) +/* output to the least used block of the cache */ +{ + dtm_block_t *pblock; + dtm_t *p; + bool_t ok; + + FOLLOW_label("preload_cache starts") + + if (idx >= egkey[key].maxindex) { + FOLLOW_LULU("Wrong index", __LINE__, idx) + return FALSE; + } + + /* find aged blocked in cache */ + pblock = point_block_to_replace(); + + if (NULL == pblock) + return FALSE; + + p = pblock->p_arr; + + if (Uncompressed) { + + index_t block = egtb_block_getnumber (key, side, idx); + index_t n = egtb_block_getsize (key, idx); + + ok = egtb_file_beready (key) + && egtb_block_park (key, block) + && egtb_block_read (key, n, Buffer_packed) + && egtb_block_unpack (side, n, Buffer_packed, p); + + FOLLOW_LULU("preload_cache", __LINE__, ok) + + assert (decoding_scheme() == 0 && GTB_scheme == 0); + + if (ok) { Bytes_read = Bytes_read + (uint64_t) n; } + + } else { + + index_t block = 0; + index_t n = 0; + index_t z = 0; + + ok = egtb_file_beready (key); + + FOLLOW_LULU("preload_cache", __LINE__, ok) + + if (ok) { + block = egtb_block_getnumber (key, side, idx); + n = egtb_block_getsize (key, idx); + z = egtb_block_getsize_zipped (key, block); + } + + ok = ok + && egtb_block_park (key, block); + FOLLOW_LULU("preload_cache", __LINE__, ok) + + ok = ok + && egtb_block_read (key, z, Buffer_zipped); + FOLLOW_LULU("preload_cache", __LINE__, ok) + + ok = ok + && egtb_block_decode (key, z, Buffer_zipped, n, Buffer_packed); + FOLLOW_LULU("preload_cache", __LINE__, ok) + + ok = ok + && egtb_block_unpack (side, n, Buffer_packed, p); + FOLLOW_LULU("preload_cache", __LINE__, ok) + + if (ok) { Bytes_read = Bytes_read + (uint64_t) z; } + } + + if (ok) { + + index_t offset; + index_t remainder; + split_index (dtm_cache.entries_per_block, idx, &offset, &remainder); + + pblock->key = key; + pblock->side = side; + pblock->offset = offset; + } else { + /* make it unusable */ + pblock->key = -1; + pblock->side = gtbNOSIDE; + pblock->offset = gtbNOINDEX; + } + + FOLLOW_LU("preload_cache?", ok) + + return ok; +} + +/****************************************************************************\ +| +| +| MEMORY ALLOCATION ZONE +| +| +\****************************************************************************/ + + +mySHARED void +egtb_freemem (int i) +{ + if (egkey[i].status == STATUS_MALLOC) { + assert (egkey[i].egt_w != NULL); + assert (egkey[i].egt_b != NULL); + free (egkey[i].egt_w); + free (egkey[i].egt_b); + egkey[i].egt_w = NULL; + egkey[i].egt_b = NULL; + } + egkey[i].status = STATUS_ABSENT; +} + +/***************************************************************************/ + +mySHARED bool_t +get_dtm (tbkey_t key, unsigned side, index_t idx, dtm_t *out, bool_t probe_hard_flag) +{ + bool_t found; + + if (probe_hard_flag) { + dtm_cache.hard++; + } else { + dtm_cache.soft++; + } + + if (get_dtm_from_cache (key, side, idx, out)) { + dtm_cache.hits++; + found = TRUE; + } else if (probe_hard_flag) { + dtm_cache.hardmisses++; + found = preload_cache (key, side, idx) && + get_dtm_from_cache (key, side, idx, out); + + if (found) { + Drive.hits++; + } else { + Drive.miss++; + } + + + } else { + dtm_cache.softmisses++; + found = FALSE; + } + return found; +} + + +static bool_t +get_dtm_from_cache (tbkey_t key, unsigned side, index_t idx, dtm_t *out) +{ + index_t offset; + index_t remainder; + bool_t found; + dtm_block_t *p; + + if (!dtm_cache_is_on()) + return FALSE; + + split_index (dtm_cache.entries_per_block, idx, &offset, &remainder); + + found = NULL != (p = dtm_cache_pointblock (key, side, idx)); + + if (found) { + *out = p->p_arr[remainder]; + movetotop(p); + } + + FOLLOW_LU("get_dtm_from_cache ok?",found) + + return found; +} + + +static void +split_index (size_t entries_per_block, index_t i, index_t *o, index_t *r) +{ + index_t n; + n = i / (index_t) entries_per_block; + *o = n * (index_t) entries_per_block; + *r = i - *o; + return; +} + + +static dtm_block_t * +point_block_to_replace (void) +{ + dtm_block_t *p, *t, *s; + + assert (0 == dtm_cache.n || dtm_cache.top != NULL); + assert (0 == dtm_cache.n || dtm_cache.bot != NULL); + assert (0 == dtm_cache.n || dtm_cache.bot->prev == NULL); + assert (0 == dtm_cache.n || dtm_cache.top->next == NULL); + + /* no cache is being used */ + if (dtm_cache.max_blocks == 0) + return NULL; + + if (dtm_cache.n > 0 && -1 == dtm_cache.top->key) { + + /* top entry is unusable, should be the one to replace*/ + p = dtm_cache.top; + + } else + if (dtm_cache.n == 0) { + + assert (NULL != dtm_cache.entry); + p = &dtm_cache.entry[dtm_cache.n++]; + dtm_cache.top = p; + dtm_cache.bot = p; + + assert (NULL != p); + p->prev = NULL; + p->next = NULL; + + } else + if (dtm_cache.n < dtm_cache.max_blocks) { /* add */ + + assert (NULL != dtm_cache.entry); + s = dtm_cache.top; + p = &dtm_cache.entry[dtm_cache.n++]; + dtm_cache.top = p; + + assert (NULL != p && NULL != s); + s->next = p; + p->prev = s; + p->next = NULL; + + } else if (1 < dtm_cache.max_blocks) { /* replace*/ + + assert (NULL != dtm_cache.bot && NULL != dtm_cache.top); + t = dtm_cache.bot; + s = dtm_cache.top; + + dtm_cache.bot = t->next; + dtm_cache.top = t; + + s->next = t; + t->prev = s; + + assert (dtm_cache.top); + dtm_cache.top->next = NULL; + + assert (dtm_cache.bot); + dtm_cache.bot->prev = NULL; + + p = t; + + } else { + + assert (1 == dtm_cache.max_blocks); + p = dtm_cache.top; + assert (p == dtm_cache.bot && p == dtm_cache.entry); + } + + /* make the information content unusable, it will be replaced */ + p->key = -1; + p->side = gtbNOSIDE; + p->offset = gtbNOINDEX; + + return p; +} + +static void +movetotop (dtm_block_t *t) +{ + dtm_block_t *s, *nx, *pv; + + assert (t != NULL); + + if (t->next == NULL) /* at the top already */ + return; + + /* detach */ + pv = t->prev; + nx = t->next; + + if (pv == NULL) /* at the bottom */ + dtm_cache.bot = nx; + else + pv->next = nx; + + if (nx == NULL) /* at the top */ + dtm_cache.top = pv; + else + nx->prev = pv; + + /* relocate */ + s = dtm_cache.top; + assert (s != NULL); + if (s == NULL) + dtm_cache.bot = t; + else + s->next = t; + + t->next = NULL; + t->prev = s; + dtm_cache.top = t; + + return; +} + +/****************************************************************************\ + * + * + * INDEXING ZONE + * + * + ****************************************************************************/ + +static void +init_indexing (int verbosity) +{ + index_t a,b,c,d,e,f; + + init_flipt (); + + a = init_kkidx () ; + b = init_ppidx () ; + c = init_aaidx () ; + d = init_aaa () ; + e = init_pp48_idx () ; + f = init_ppp48_idx () ; + + if (verbosity) { + printf ("\nGTB supporting tables, Initialization\n"); + printf (" Max kk idx: %8d\n", (int)a ); + printf (" Max pp idx: %8d\n", (int)b ); + printf (" Max aa idx: %8d\n", (int)c ); + printf (" Max aaa idx: %8d\n", (int)d ); + printf (" Max pp48 idx: %8d\n", (int)e ); + printf (" Max ppp48 idx: %8d\n", (int)f ); + } + + if (!reach_was_initialized()) + reach_init(); + + /* testing used only in development stage */ + +#ifdef _MSC_VER +#pragma warning(disable:4127) +#endif + + if (0) { + list_index (); + printf ("\nTEST indexing functions\n"); + + test_kaakb (); + test_kaabk (); + test_kaaak (); + test_kabbk (); + + test_kapkb (); + test_kabkp (); + + test_kppka (); + + test_kapkp (); + test_kabpk(); + test_kaapk (); + + test_kappk (); + test_kaakp (); + test_kppk (); + test_kppkp (); + test_kpppk (); + } + +#ifdef _MSC_VER +#pragma warning(default:4127) +#endif + + return; +} + + +static index_t +init_kkidx (void) +/* modifies kkidx[][], wksq[], bksq[] */ +{ + index_t idx; + SQUARE x, y, i, j; + + /* default is noindex */ + for (x = 0; x < 64; x++) { + for (y = 0; y < 64; y++) { + IDX_set_empty(kkidx [x][y]); + } + } + + idx = 0; + for (x = 0; x < 64; x++) { + for (y = 0; y < 64; y++) { + + /* is x,y illegal? continue */ + if (possible_attack (x, y, wK) || x == y) + continue; + + /* normalize */ + /*i <-- x; j <-- y */ + norm_kkindex (x, y, &i, &j); + + if (IDX_is_empty(kkidx [i][j])) { /* still empty */ + kkidx [i][j] = idx; + kkidx [x][y] = idx; + bksq [idx] = i; + wksq [idx] = j; + idx++; + } + } + } + + assert (idx == MAX_KKINDEX); + + return idx; +} + + +static index_t +init_aaidx (void) +/* modifies aabase[], aaidx[][] */ +{ + index_t idx; + SQUARE x, y; + + /* default is noindex */ + for (x = 0; x < 64; x++) { + for (y = 0; y < 64; y++) { + IDX_set_empty(aaidx [x][y]); + } + } + + for (idx = 0; idx < MAX_AAINDEX; idx++) + aabase [idx] = 0; + + idx = 0; + for (x = 0; x < 64; x++) { + for (y = x + 1; y < 64; y++) { + + assert (idx == (int)((y - x) + x * (127-x)/2 - 1) ); + + if (IDX_is_empty(aaidx [x][y])) { /* still empty */ + aaidx [x] [y] = idx; + aaidx [y] [x] = idx; + aabase [idx] = (unsigned char) x; + idx++; + } else { + assert (aaidx [x] [y] == idx); + assert (aabase [idx] == x); + } + + + } + } + + assert (idx == MAX_AAINDEX); + + return idx; +} + + +static index_t +init_ppidx (void) +/* modifies ppidx[][], pp_hi24[], pp_lo48[] */ +{ + index_t i, j; + index_t idx = 0; + SQUARE a, b; + + /* default is noindex */ + for (i = 0; i < 24; i++) { + for (j = 0; j < 48; j++) { + IDX_set_empty(ppidx [i][j]); + } + } + + for (idx = 0; idx < MAX_PPINDEX; idx++) { + IDX_set_empty(pp_hi24 [idx]); + IDX_set_empty(pp_lo48 [idx]); + } + + idx = 0; + for (a = H7; a >= A2; a--) { + + if ((a & 07) < 4) /* square in the queen side */ + continue; + + for (b = a - 1; b >= A2; b--) { + + SQUARE anchor, loosen; + + pp_putanchorfirst (a, b, &anchor, &loosen); + + if ((anchor & 07) > 3) { /* square in the king side */ + anchor = flipWE(anchor); + loosen = flipWE(loosen); + } + + i = wsq_to_pidx24 (anchor); + j = wsq_to_pidx48 (loosen); + + if (IDX_is_empty(ppidx [i] [j])) { + + ppidx [i] [j] = idx; + assert (idx < MAX_PPINDEX); + pp_hi24 [idx] = i; + assert (i < 24); + pp_lo48 [idx] = j; + assert (j < 48); + idx++; + } + + } + } + assert (idx == MAX_PPINDEX); + return idx; +} + +static void +init_flipt (void) +{ + unsigned int i, j; + for (i = 0; i < 64; i++) { + for (j = 0; j < 64; j++) { + flipt [i] [j] = flip_type (i, j); + } + } +} + +/*--- NORMALIZE -------*/ + +static void +norm_kkindex (SQUARE x, SQUARE y, /*@out@*/ SQUARE *pi, /*@out@*/ SQUARE *pj) +{ + unsigned int rowx, rowy, colx, coly; + + assert (x < 64); + assert (y < 64); + + if (getcol(x) > 3) { + x = flipWE (x); /* x = x ^ 07 */ + y = flipWE (y); + } + if (getrow(x) > 3) { + x = flipNS (x); /* x = x ^ 070 */ + y = flipNS (y); + } + rowx = getrow(x); + colx = getcol(x); + if ( rowx > colx ) { + x = flipNW_SE (x); /* x = ((x&7)<<3) | (x>>3) */ + y = flipNW_SE (y); + } + rowy = getrow(y); + coly = getcol(y); + if ( rowx == colx && rowy > coly) { + x = flipNW_SE (x); + y = flipNW_SE (y); + } + + *pi = x; + *pj = y; +} + +static unsigned int +flip_type (SQUARE x, SQUARE y) +{ + unsigned int rowx, rowy, colx, coly; + unsigned int ret = 0; + + assert (x < 64); + assert (y < 64); + + + if (getcol(x) > 3) { + x = flipWE (x); /* x = x ^ 07 */ + y = flipWE (y); + ret |= 1; + } + if (getrow(x) > 3) { + x = flipNS (x); /* x = x ^ 070 */ + y = flipNS (y); + ret |= 2; + } + rowx = getrow(x); + colx = getcol(x); + if ( rowx > colx ) { + x = flipNW_SE (x); /* x = ((x&7)<<3) | (x>>3) */ + y = flipNW_SE (y); + ret |= 4; + } + rowy = getrow(y); + coly = getcol(y); + if ( rowx == colx && rowy > coly) { + x = flipNW_SE (x); + y = flipNW_SE (y); + ret |= 4; + } + return ret; +} + + +static void +pp_putanchorfirst (SQUARE a, SQUARE b, /*@out@*/ SQUARE *out_anchor, /*@out@*/ SQUARE *out_loosen) +{ + unsigned int anchor, loosen; + + unsigned int row_b, row_a; + row_b = b & 070; + row_a = a & 070; + + /* default */ + anchor = a; + loosen = b; + if (row_b > row_a) { + anchor = b; + loosen = a; + } + else + if (row_b == row_a) { + unsigned int x, col, inv, hi_a, hi_b; + x = a; + col = x & 07; + inv = col ^ 07; + x = (1u< hi_a) { + anchor = b; + loosen = a; + } + + if (hi_b < hi_a) { + anchor = a; + loosen = b; + } + + if (hi_b == hi_a) { + if (a < b) { + anchor = a; + loosen = b; + } else { + anchor = b; + loosen = a; + } + } + } + + *out_anchor = anchor; + *out_loosen = loosen; + return; +} + + +static index_t +wsq_to_pidx24 (SQUARE pawn) +{ + unsigned int idx24; + SQUARE sq = pawn; + + /* input can be only queen side, pawn valid */ + assert (A2 <= pawn && pawn < A8); + assert ((pawn & 07) < 4); + + sq ^= 070; /* flipNS*/ + sq -= 8; /* down one row*/ + idx24 = (sq+(sq&3)) >> 1; + assert (idx24 < 24); + return (index_t) idx24; +} + +static index_t +wsq_to_pidx48 (SQUARE pawn) +{ + unsigned int idx48; + SQUARE sq = pawn; + + /* input can be both queen or king side, pawn valid square */ + assert (A2 <= pawn && pawn < A8); + + sq ^= 070; /* flipNS*/ + sq -= 8; /* down one row*/ + idx48 = sq; + assert (idx48 < 48); + return (index_t)idx48; +} + +static SQUARE +pidx24_to_wsq (index_t a) +{ + enum {B11100 = 7u << 2}; + unsigned int x = (unsigned int) a; /* x is pslice */ + assert (a < 24); + + x += x & B11100; /* get upper part and double it */ + x += 8; /* add extra row */ + x ^= 070; /* flip NS */ + return (SQUARE) x; +} + +static SQUARE +pidx48_to_wsq (index_t a) +{ + unsigned int x; + assert (a < 48); + /* x is pslice */ + x = (unsigned int)a; + x += 8; /* add extra row */ + x ^= 070; /* flip NS */ + return x; +} + + +static void +kxk_indextopc (index_t i, SQUARE *pw, SQUARE *pb) +{ + enum {BLOCK_A = 64}; + + index_t a = i / BLOCK_A; + index_t b = i - a * BLOCK_A; + + pw[0] = wksq [a]; + pb[0] = bksq [a]; + pw[1] = (SQUARE) b; + pw[2] = NOSQUARE; + pb[1] = NOSQUARE; + + assert (kxk_pctoindex (pw, pb, &a) && a == i); + + return; +} + +static bool_t +kxk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out) +{ + enum {BLOCK_A = 64}; + SQUARE *p; + SQUARE ws[32], bs[32]; + index_t ki; + int i; + + unsigned int ft; + + ft = flip_type (inp_pb[0],inp_pw[0]); + + assert (ft < 8); + + + for (i = 0; inp_pw[i] != NOSQUARE; i++) { + ws[i] = inp_pw[i]; + } + ws[i] = NOSQUARE; + for (i = 0; inp_pb[i] != NOSQUARE; i++) { + bs[i] = inp_pb[i]; + } + bs[i] = NOSQUARE; + + if ((ft & 1) != 0) { + for (p = ws; *p != NOSQUARE; p++) + *p = flipWE (*p); + for (p = bs; *p != NOSQUARE; p++) + *p = flipWE (*p); + } + + if ((ft & 2) != 0) { + for (p = ws; *p != NOSQUARE; p++) + *p = flipNS (*p); + for (p = bs; *p != NOSQUARE; p++) + *p = flipNS (*p); + } + + if ((ft & 4) != 0) { + for (p = ws; *p != NOSQUARE; p++) + *p = flipNW_SE (*p); + for (p = bs; *p != NOSQUARE; p++) + *p = flipNW_SE (*p); + } + + ki = kkidx [bs[0]] [ws[0]]; /* kkidx [black king] [white king] */ + + if (IDX_is_empty(ki)) { + *out = NOINDEX; + return FALSE; + } + *out = ki * BLOCK_A + (index_t) ws[1]; + return TRUE; + +} + + +static void +kabk_indextopc (index_t i, SQUARE *pw, SQUARE *pb) +{ + enum {BLOCK_A = 64*64, BLOCK_B = 64}; + index_t a, b, c, r; + + r = i; + a = r / BLOCK_A; + r -= a * BLOCK_A; + b = r / BLOCK_B; + r -= b * BLOCK_B; + c = r; + + pw[0] = wksq [a]; + pb[0] = bksq [a]; + + pw[1] = (SQUARE) b; + pw[2] = (SQUARE) c; + pw[3] = NOSQUARE; + + pb[1] = NOSQUARE; + + assert (kabk_pctoindex (pw, pb, &a) && a == i); + + return; +} + + +static bool_t +kabk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out) +{ + enum {BLOCK_A = 64*64, BLOCK_B = 64}; + SQUARE *p; + SQUARE ws[32], bs[32]; + index_t ki; + int i; + + unsigned int ft; + + ft = flip_type (inp_pb[0],inp_pw[0]); + + assert (ft < 8); + + for (i = 0; inp_pw[i] != NOSQUARE; i++) { + ws[i] = inp_pw[i]; + } + ws[i] = NOSQUARE; + for (i = 0; inp_pb[i] != NOSQUARE; i++) { + bs[i] = inp_pb[i]; + } + bs[i] = NOSQUARE; + + if ((ft & 1) != 0) { + for (p = ws; *p != NOSQUARE; p++) + *p = flipWE (*p); + for (p = bs; *p != NOSQUARE; p++) + *p = flipWE (*p); + } + + if ((ft & 2) != 0) { + for (p = ws; *p != NOSQUARE; p++) + *p = flipNS (*p); + for (p = bs; *p != NOSQUARE; p++) + *p = flipNS (*p); + } + + if ((ft & 4) != 0) { + for (p = ws; *p != NOSQUARE; p++) + *p = flipNW_SE (*p); + for (p = bs; *p != NOSQUARE; p++) + *p = flipNW_SE (*p); + } + + ki = kkidx [bs[0]] [ws[0]]; /* kkidx [black king] [white king] */ + + if (IDX_is_empty(ki)) { + *out = NOINDEX; + return FALSE; + } + *out = ki * BLOCK_A + (index_t)ws[1] * BLOCK_B + (index_t)ws[2]; + return TRUE; + +} + + +static void +kabkc_indextopc (index_t i, SQUARE *pw, SQUARE *pb) +{ + enum {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64}; + index_t a, b, c, d, r; + + r = i; + a = r / BLOCK_A; + r -= a * BLOCK_A; + b = r / BLOCK_B; + r -= b * BLOCK_B; + c = r / BLOCK_C; + r -= c * BLOCK_C; + d = r; + + pw[0] = wksq [a]; + pb[0] = bksq [a]; + + pw[1] = (SQUARE) b; + pw[2] = (SQUARE) c; + pw[3] = NOSQUARE; + + pb[1] = (SQUARE) d; + pb[2] = NOSQUARE; + + assert (kabkc_pctoindex (pw, pb, &a) && a == i); + + return; +} + + +static bool_t +kabkc_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out) +{ + enum {N_WHITE = 3, N_BLACK = 2}; + + enum {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64}; + SQUARE ws[MAX_LISTSIZE], bs[MAX_LISTSIZE]; + index_t ki; + int i; + unsigned int ft; + + #if 0 + ft = flip_type (inp_pb[0], inp_pw[0]); + #else + ft = flipt [inp_pb[0]] [inp_pw[0]]; + #endif + + assert (ft < 8); + + for (i = 0; i < N_WHITE; i++) ws[i] = inp_pw[i]; ws[N_WHITE] = NOSQUARE; + for (i = 0; i < N_BLACK; i++) bs[i] = inp_pb[i]; bs[N_BLACK] = NOSQUARE; + + if ((ft & WE_FLAG) != 0) { + for (i = 0; i < N_WHITE; i++) ws[i] = flipWE (ws[i]); + for (i = 0; i < N_BLACK; i++) bs[i] = flipWE (bs[i]); + } + + if ((ft & NS_FLAG) != 0) { + for (i = 0; i < N_WHITE; i++) ws[i] = flipNS (ws[i]); + for (i = 0; i < N_BLACK; i++) bs[i] = flipNS (bs[i]); + } + + if ((ft & NW_SE_FLAG) != 0) { + for (i = 0; i < N_WHITE; i++) ws[i] = flipNW_SE (ws[i]); + for (i = 0; i < N_BLACK; i++) bs[i] = flipNW_SE (bs[i]); + } + + + ki = kkidx [bs[0]] [ws[0]]; /* kkidx [black king] [white king] */ + + if (IDX_is_empty(ki)) { + *out = NOINDEX; + return FALSE; + } + *out = ki * BLOCK_A + (index_t)ws[1] * BLOCK_B + (index_t)ws[2] * BLOCK_C + (index_t)bs[1]; + return TRUE; + +} + +/* ABC/ ***/ + +extern void +kabck_indextopc (index_t i, SQUARE *pw, SQUARE *pb) +{ + enum {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64}; + index_t a, b, c, d, r; + + r = i; + a = r / BLOCK_A; + r -= a * BLOCK_A; + b = r / BLOCK_B; + r -= b * BLOCK_B; + c = r / BLOCK_C; + r -= c * BLOCK_C; + d = r; + + pw[0] = wksq [a]; + pb[0] = bksq [a]; + + pw[1] = (SQUARE) b; + pw[2] = (SQUARE) c; + pw[3] = (SQUARE) d; + pw[4] = NOSQUARE; + + pb[1] = NOSQUARE; + + assert (kabck_pctoindex (pw, pb, &a) && a == i); + + return; +} + + +extern bool_t +kabck_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out) +{ + enum {N_WHITE = 4, N_BLACK = 1}; + enum {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64}; + + SQUARE ws[MAX_LISTSIZE], bs[MAX_LISTSIZE]; + index_t ki; + int i; + unsigned int ft; + + ft = flipt [inp_pb[0]] [inp_pw[0]]; + + assert (ft < 8); + + for (i = 0; i < N_WHITE; i++) ws[i] = inp_pw[i]; ws[N_WHITE] = NOSQUARE; + for (i = 0; i < N_BLACK; i++) bs[i] = inp_pb[i]; bs[N_BLACK] = NOSQUARE; + + if ((ft & WE_FLAG) != 0) { + for (i = 0; i < N_WHITE; i++) ws[i] = flipWE (ws[i]); + for (i = 0; i < N_BLACK; i++) bs[i] = flipWE (bs[i]); + } + + if ((ft & NS_FLAG) != 0) { + for (i = 0; i < N_WHITE; i++) ws[i] = flipNS (ws[i]); + for (i = 0; i < N_BLACK; i++) bs[i] = flipNS (bs[i]); + } + + if ((ft & NW_SE_FLAG) != 0) { + for (i = 0; i < N_WHITE; i++) ws[i] = flipNW_SE (ws[i]); + for (i = 0; i < N_BLACK; i++) bs[i] = flipNW_SE (bs[i]); + } + + + ki = kkidx [bs[0]] [ws[0]]; /* kkidx [black king] [white king] */ + + if (IDX_is_empty(ki)) { + *out = NOINDEX; + return FALSE; + } + *out = ki * BLOCK_A + (index_t)ws[1] * BLOCK_B + (index_t)ws[2] * BLOCK_C + (index_t)ws[3]; + return TRUE; + +} + + +static void +kakb_indextopc (index_t i, SQUARE *pw, SQUARE *pb) +{ + enum {BLOCK_A = 64*64, BLOCK_B = 64}; + index_t a, b, c, r; + + r = i; + a = r / BLOCK_A; + r -= a * BLOCK_A; + b = r / BLOCK_B; + r -= b * BLOCK_B; + c = r; + + pw[0] = wksq [a]; + pb[0] = bksq [a]; + + pw[1] = (SQUARE) b; + pw[2] = NOSQUARE; + + pb[1] = (SQUARE) c; + pb[2] = NOSQUARE; + + assert (kakb_pctoindex (pw, pb, &a) && a == i); + + return; +} + + +static bool_t +kakb_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out) +{ + enum {BLOCK_A = 64*64, BLOCK_B = 64}; + SQUARE ws[32], bs[32]; + index_t ki; + unsigned int ft; + + #if 0 + ft = flip_type (inp_pb[0], inp_pw[0]); + #else + ft = flipt [inp_pb[0]] [inp_pw[0]]; + #endif + + assert (ft < 8); + + ws[0] = inp_pw[0]; + ws[1] = inp_pw[1]; + ws[2] = NOSQUARE; + + bs[0] = inp_pb[0]; + bs[1] = inp_pb[1]; + bs[2] = NOSQUARE; + + if ((ft & 1) != 0) { + ws[0] = flipWE (ws[0]); + ws[1] = flipWE (ws[1]); + bs[0] = flipWE (bs[0]); + bs[1] = flipWE (bs[1]); + } + + if ((ft & 2) != 0) { + ws[0] = flipNS (ws[0]); + ws[1] = flipNS (ws[1]); + bs[0] = flipNS (bs[0]); + bs[1] = flipNS (bs[1]); + } + + if ((ft & 4) != 0) { + ws[0] = flipNW_SE (ws[0]); + ws[1] = flipNW_SE (ws[1]); + bs[0] = flipNW_SE (bs[0]); + bs[1] = flipNW_SE (bs[1]); + } + + ki = kkidx [bs[0]] [ws[0]]; /* kkidx [black king] [white king] */ + + if (IDX_is_empty(ki)) { + *out = NOINDEX; + return FALSE; + } + *out = ki * BLOCK_A + (index_t)ws[1] * BLOCK_B + (index_t)bs[1]; + return TRUE; + +} + +/********************** KAAKB *************************************/ + +static bool_t test_kaakb (void); +static bool_t kaakb_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out); +static void kaakb_indextopc (index_t i, SQUARE *pw, SQUARE *pb); + +static bool_t +test_kaakb (void) +{ + + enum {MAXPC = 16+1}; + char str[] = "kaakb"; + SQUARE a, b, c, d, e; + SQUARE pw[MAXPC], pb[MAXPC]; + SQUARE px[MAXPC], py[MAXPC]; + + index_t i, j; + bool_t err = FALSE; + + printf ("%8s ", str); + + for (a = 0; a < 64; a++) { + for (b = 0; b < 64; b++) { + for (c = 0; c < 64; c++) { + for (d = 0; d < 64; d++) { + for (e = 0; e < 64; e++) { + + pw[0] = a; + pw[1] = b; + pw[2] = c; + pw[3] = NOSQUARE; + + pb[0] = d; + pb[1] = e; + pb[2] = NOSQUARE; + + if (kaakb_pctoindex (pw, pb, &i)) { + kaakb_indextopc (i, px, py); + kaakb_pctoindex (px, py, &j); + if (i != j) { + err = TRUE; + } + assert (i == j); + } + + } + } + } + } + + if ((a&1)==0) { + printf("."); + fflush(stdout); + } + } + + if (err) + printf ("> %s NOT passed\n", str); + else + printf ("> %s PASSED\n", str); + return !err; +} + +static void +kaakb_indextopc (index_t i, SQUARE *pw, SQUARE *pb) +{ + enum { + BLOCK_B = 64, + BLOCK_A = BLOCK_B * MAX_AAINDEX + }; + index_t a, b, c, r, x, y; + + r = i; + a = r / BLOCK_A; + r -= a * BLOCK_A; + + b = r / BLOCK_B; + r -= b * BLOCK_B; + + c = r; + + assert (i == (a * BLOCK_A + b * BLOCK_B + c)); + + pw[0] = wksq [a]; + pb[0] = bksq [a]; + + x = aabase [b]; + y = (b + 1) + x - (x * (127-x)/2); + + pw[1] = (SQUARE) x; + pw[2] = (SQUARE) y; + pw[3] = NOSQUARE; + + pb[1] = (SQUARE) c; + pb[2] = NOSQUARE; + + assert (kaakb_pctoindex (pw, pb, &a) && a == i); + + return; +} + +static bool_t +kaakb_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, /*@out@*/ index_t *out) +{ + enum {N_WHITE = 3, N_BLACK = 2}; + enum { + BLOCK_B = 64, + BLOCK_A = BLOCK_B * MAX_AAINDEX + }; + SQUARE ws[MAX_LISTSIZE], bs[MAX_LISTSIZE]; + index_t ki, ai; + unsigned int ft; + int i; + + ft = flipt [inp_pb[0]] [inp_pw[0]]; + + assert (ft < 8); + + for (i = 0; i < N_WHITE; i++) ws[i] = inp_pw[i]; ws[N_WHITE] = NOSQUARE; + for (i = 0; i < N_BLACK; i++) bs[i] = inp_pb[i]; bs[N_BLACK] = NOSQUARE; + + if ((ft & WE_FLAG) != 0) { + for (i = 0; i < N_WHITE; i++) ws[i] = flipWE (ws[i]); + for (i = 0; i < N_BLACK; i++) bs[i] = flipWE (bs[i]); + } + + if ((ft & NS_FLAG) != 0) { + for (i = 0; i < N_WHITE; i++) ws[i] = flipNS (ws[i]); + for (i = 0; i < N_BLACK; i++) bs[i] = flipNS (bs[i]); + } + + if ((ft & NW_SE_FLAG) != 0) { + for (i = 0; i < N_WHITE; i++) ws[i] = flipNW_SE (ws[i]); + for (i = 0; i < N_BLACK; i++) bs[i] = flipNW_SE (bs[i]); + } + + ki = kkidx [bs[0]] [ws[0]]; /* kkidx [black king] [white king] */ + ai = aaidx [ws[1]] [ws[2]]; + + if (IDX_is_empty(ki) || IDX_is_empty(ai)) { + *out = NOINDEX; + return FALSE; + } + *out = ki * BLOCK_A + ai * BLOCK_B + (index_t)bs[1]; + return TRUE; +} + +/****************** End KAAKB *************************************/ + +/********************** KAAB/K ************************************/ + +static bool_t test_kaabk (void); +static bool_t kaabk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out); +static void kaabk_indextopc (index_t i, SQUARE *pw, SQUARE *pb); + +static bool_t +test_kaabk (void) +{ + + enum {MAXPC = 16+1}; + char str[] = "kaabk"; + SQUARE a, b, c, d, e; + SQUARE pw[MAXPC], pb[MAXPC]; + SQUARE px[MAXPC], py[MAXPC]; + + index_t i, j; + bool_t err = FALSE; + + printf ("%8s ", str); + + for (a = 0; a < 64; a++) { + for (b = 0; b < 64; b++) { + for (c = 0; c < 64; c++) { + for (d = 0; d < 64; d++) { + for (e = 0; e < 64; e++) { + + pw[0] = a; + pw[1] = b; + pw[2] = c; + pw[3] = d; + pw[4] = NOSQUARE; + + pb[0] = e; + pb[1] = NOSQUARE; + + if (kaabk_pctoindex (pw, pb, &i)) { + kaabk_indextopc (i, px, py); + kaabk_pctoindex (px, py, &j); + if (i != j) { + err = TRUE; + } + assert (i == j); + } + + } + } + } + } + + if ((a&1)==0) { + printf("."); + fflush(stdout); + } + } + + if (err) + printf ("> %s NOT passed\n", str); + else + printf ("> %s PASSED\n", str); + return !err; +} + +static void +kaabk_indextopc (index_t i, SQUARE *pw, SQUARE *pb) +{ + enum { + BLOCK_B = 64, + BLOCK_A = BLOCK_B * MAX_AAINDEX + }; + index_t a, b, c, r, x, y; + + r = i; + a = r / BLOCK_A; + r -= a * BLOCK_A; + + b = r / BLOCK_B; + r -= b * BLOCK_B; + + c = r; + + assert (i == (a * BLOCK_A + b * BLOCK_B + c)); + + pw[0] = wksq [a]; + pb[0] = bksq [a]; + + x = aabase [b]; + y = (b + 1) + x - (x * (127-x)/2); + + pw[1] = (SQUARE) x; + pw[2] = (SQUARE) y; + pw[3] = (SQUARE) c; + pw[4] = NOSQUARE; + + pb[1] = NOSQUARE; + + assert (kaabk_pctoindex (pw, pb, &a) && a == i); + + return; +} + +static bool_t +kaabk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, /*@out@*/ index_t *out) +{ + enum {N_WHITE = 4, N_BLACK = 1}; + enum { + BLOCK_B = 64, + BLOCK_A = BLOCK_B * MAX_AAINDEX + }; + SQUARE ws[MAX_LISTSIZE], bs[MAX_LISTSIZE]; + index_t ki, ai; + unsigned int ft; + int i; + + ft = flipt [inp_pb[0]] [inp_pw[0]]; + + assert (ft < 8); + + for (i = 0; i < N_WHITE; i++) ws[i] = inp_pw[i]; ws[N_WHITE] = NOSQUARE; + for (i = 0; i < N_BLACK; i++) bs[i] = inp_pb[i]; bs[N_BLACK] = NOSQUARE; + + if ((ft & WE_FLAG) != 0) { + for (i = 0; i < N_WHITE; i++) ws[i] = flipWE (ws[i]); + for (i = 0; i < N_BLACK; i++) bs[i] = flipWE (bs[i]); + } + + if ((ft & NS_FLAG) != 0) { + for (i = 0; i < N_WHITE; i++) ws[i] = flipNS (ws[i]); + for (i = 0; i < N_BLACK; i++) bs[i] = flipNS (bs[i]); + } + + if ((ft & NW_SE_FLAG) != 0) { + for (i = 0; i < N_WHITE; i++) ws[i] = flipNW_SE (ws[i]); + for (i = 0; i < N_BLACK; i++) bs[i] = flipNW_SE (bs[i]); + } + + ki = kkidx [bs[0]] [ws[0]]; /* kkidx [black king] [white king] */ + ai = aaidx [ws[1]] [ws[2]]; + + if (IDX_is_empty(ki) || IDX_is_empty(ai)) { + *out = NOINDEX; + return FALSE; + } + *out = ki * BLOCK_A + ai * BLOCK_B + (index_t)ws[3]; + return TRUE; +} + +/****************** End KAAB/K *************************************/ + +/********************** KABB/K ************************************/ + +static bool_t test_kabbk (void); +static bool_t kabbk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out); +static void kabbk_indextopc (index_t i, SQUARE *pw, SQUARE *pb); + +static bool_t +test_kabbk (void) +{ + + enum {MAXPC = 16+1}; + char str[] = "kabbk"; + SQUARE a, b, c, d, e; + SQUARE pw[MAXPC], pb[MAXPC]; + SQUARE px[MAXPC], py[MAXPC]; + + index_t i, j; + bool_t err = FALSE; + + printf ("%8s ", str); + + for (a = 0; a < 64; a++) { + for (b = 0; b < 64; b++) { + for (c = 0; c < 64; c++) { + for (d = 0; d < 64; d++) { + for (e = 0; e < 64; e++) { + + pw[0] = a; + pw[1] = b; + pw[2] = c; + pw[3] = d; + pw[4] = NOSQUARE; + + pb[0] = e; + pb[1] = NOSQUARE; + + if (kabbk_pctoindex (pw, pb, &i)) { + kabbk_indextopc (i, px, py); + kabbk_pctoindex (px, py, &j); + if (i != j) { + err = TRUE; + } + assert (i == j); + } + + } + } + } + } + + if ((a&1)==0) { + printf("."); + fflush(stdout); + } + } + + if (err) + printf ("> %s NOT passed\n", str); + else + printf ("> %s PASSED\n", str); + return !err; +} + +static void +kabbk_indextopc (index_t i, SQUARE *pw, SQUARE *pb) +{ + enum { + BLOCK_B = 64, + BLOCK_A = BLOCK_B * MAX_AAINDEX + }; + index_t a, b, c, r, x, y; + + r = i; + a = r / BLOCK_A; + r -= a * BLOCK_A; + + b = r / BLOCK_B; + r -= b * BLOCK_B; + + c = r; + + assert (i == (a * BLOCK_A + b * BLOCK_B + c)); + + pw[0] = wksq [a]; + pb[0] = bksq [a]; + + x = aabase [b]; + y = (b + 1) + x - (x * (127-x)/2); + + pw[1] = (SQUARE) c; + pw[2] = (SQUARE) x; + pw[3] = (SQUARE) y; + pw[4] = NOSQUARE; + + pb[1] = NOSQUARE; + + assert (kabbk_pctoindex (pw, pb, &a) && a == i); + + return; +} + +static bool_t +kabbk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, /*@out@*/ index_t *out) +{ + enum {N_WHITE = 4, N_BLACK = 1}; + enum { + BLOCK_B = 64, + BLOCK_A = BLOCK_B * MAX_AAINDEX + }; + SQUARE ws[MAX_LISTSIZE], bs[MAX_LISTSIZE]; + index_t ki, ai; + unsigned int ft; + int i; + + ft = flipt [inp_pb[0]] [inp_pw[0]]; + + assert (ft < 8); + + for (i = 0; i < N_WHITE; i++) ws[i] = inp_pw[i]; ws[N_WHITE] = NOSQUARE; + for (i = 0; i < N_BLACK; i++) bs[i] = inp_pb[i]; bs[N_BLACK] = NOSQUARE; + + if ((ft & WE_FLAG) != 0) { + for (i = 0; i < N_WHITE; i++) ws[i] = flipWE (ws[i]); + for (i = 0; i < N_BLACK; i++) bs[i] = flipWE (bs[i]); + } + + if ((ft & NS_FLAG) != 0) { + for (i = 0; i < N_WHITE; i++) ws[i] = flipNS (ws[i]); + for (i = 0; i < N_BLACK; i++) bs[i] = flipNS (bs[i]); + } + + if ((ft & NW_SE_FLAG) != 0) { + for (i = 0; i < N_WHITE; i++) ws[i] = flipNW_SE (ws[i]); + for (i = 0; i < N_BLACK; i++) bs[i] = flipNW_SE (bs[i]); + } + + ki = kkidx [bs[0]] [ws[0]]; /* kkidx [black king] [white king] */ + ai = aaidx [ws[2]] [ws[3]]; + + if (IDX_is_empty(ki) || IDX_is_empty(ai)) { + *out = NOINDEX; + return FALSE; + } + *out = ki * BLOCK_A + ai * BLOCK_B + (index_t)ws[1]; + return TRUE; +} + +/********************** End KABB/K *************************************/ + +/********************** init KAAA/K ************************************/ + +static index_t +aaa_getsubi (sq_t x, sq_t y, sq_t z); + +static sq_t aaa_xyz [MAX_AAAINDEX] [3]; +static index_t aaa_base [64]; + +static index_t +init_aaa (void) +/* modifies aaa_base[], aaa_xyz[][] */ +{ + index_t comb [64]; + index_t accum; + index_t a; + + index_t idx; + SQUARE x, y, z; + + /* getting aaa_base */ + comb [0] = 0; + for (a = 1; a < 64; a++) { + comb [a] = a * (a-1) / 2; + } + + accum = 0; + aaa_base [0] = accum; + for (a = 0; a < (64-1); a++) { + accum += comb[a]; + aaa_base [a+1] = accum; + } + + assert ((accum + comb[63]) == MAX_AAAINDEX); + /* end getting aaa_base */ + + + /* initialize aaa_xyz [][] */ + for (idx = 0; idx < MAX_AAAINDEX; idx++) { + IDX_set_empty (aaa_xyz[idx][0]); + IDX_set_empty (aaa_xyz[idx][1]); + IDX_set_empty (aaa_xyz[idx][2]); + } + + idx = 0; + for (z = 0; z < 64; z++) { + for (y = 0; y < z; y++) { + for (x = 0; x < y; x++) { + + assert (idx == aaa_getsubi (x, y, z)); + + aaa_xyz [idx] [0] = x; + aaa_xyz [idx] [1] = y; + aaa_xyz [idx] [2] = z; + + idx++; + } + } + } + + assert (idx == MAX_AAAINDEX); + + return idx; +} + + +static index_t +aaa_getsubi (sq_t x, sq_t y, sq_t z) +/* uses aaa_base */ +{ + index_t calc_idx, base; + + assert (x < 64 && y < 64 && z < 64); + assert (x < y && y < z); + + base = aaa_base[z]; + calc_idx = (index_t)x + ((index_t)y - 1) * (index_t)y / 2 + base; + + return calc_idx; +} + +/********************** KAAA/K ************************************/ + +static bool_t test_kaaak (void); +static bool_t kaaak_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out); +static void kaaak_indextopc (index_t i, SQUARE *pw, SQUARE *pb); + +static bool_t +test_kaaak (void) +{ + + enum {MAXPC = 16+1}; + char str[] = "kaaak"; + SQUARE a, b, c, d, e; + SQUARE pw[MAXPC], pb[MAXPC]; + SQUARE px[MAXPC], py[MAXPC]; + + index_t i, j; + bool_t err = FALSE; + + printf ("%8s ", str); + + for (a = 0; a < 64; a++) { + for (b = 0; b < 64; b++) { + for (c = 0; c < 64; c++) { + for (d = 0; d < 64; d++) { + for (e = 0; e < 64; e++) { + + pw[0] = a; + pw[1] = b; + pw[2] = c; + pw[3] = d; + pw[4] = NOSQUARE; + + pb[0] = e; + pb[1] = NOSQUARE; + + if (kaaak_pctoindex (pw, pb, &i)) { + kaaak_indextopc (i, px, py); + kaaak_pctoindex (px, py, &j); + if (i != j) { + err = TRUE; + } + assert (i == j); + } + + } + } + } + } + + if ((a&1)==0) { + printf("."); + fflush(stdout); + } + } + + if (err) + printf ("> %s NOT passed\n", str); + else + printf ("> %s PASSED\n", str); + return !err; +} + +static void +kaaak_indextopc (index_t i, SQUARE *pw, SQUARE *pb) +{ + enum { + BLOCK_A = MAX_AAAINDEX + }; + index_t a, b, r; + + r = i; + a = r / BLOCK_A; + r -= a * BLOCK_A; + + b = r; + + assert (i == (a * BLOCK_A + b)); + assert (b < BLOCK_A); + + pw[0] = wksq [a]; + pb[0] = bksq [a]; + + pw[1] = aaa_xyz [b] [0]; + pw[2] = aaa_xyz [b] [1]; + pw[3] = aaa_xyz [b] [2]; + pw[4] = NOSQUARE; + + pb[1] = NOSQUARE; + + assert (kaaak_pctoindex (pw, pb, &a) && a == i); + + return; +} + +static bool_t +kaaak_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out) +{ + enum {N_WHITE = 4, N_BLACK = 1}; + enum { + BLOCK_A = MAX_AAAINDEX + }; + SQUARE ws[MAX_LISTSIZE], bs[MAX_LISTSIZE]; + index_t ki, ai; + unsigned int ft; + int i; + + ft = flipt [inp_pb[0]] [inp_pw[0]]; + + assert (ft < 8); + + for (i = 0; i < N_WHITE; i++) ws[i] = inp_pw[i]; ws[N_WHITE] = NOSQUARE; + for (i = 0; i < N_BLACK; i++) bs[i] = inp_pb[i]; bs[N_BLACK] = NOSQUARE; + + if ((ft & WE_FLAG) != 0) { + for (i = 0; i < N_WHITE; i++) ws[i] = flipWE (ws[i]); + for (i = 0; i < N_BLACK; i++) bs[i] = flipWE (bs[i]); + } + + if ((ft & NS_FLAG) != 0) { + for (i = 0; i < N_WHITE; i++) ws[i] = flipNS (ws[i]); + for (i = 0; i < N_BLACK; i++) bs[i] = flipNS (bs[i]); + } + + if ((ft & NW_SE_FLAG) != 0) { + for (i = 0; i < N_WHITE; i++) ws[i] = flipNW_SE (ws[i]); + for (i = 0; i < N_BLACK; i++) bs[i] = flipNW_SE (bs[i]); + } + + + { + SQUARE tmp; + if (ws[2] < ws[1]) { + tmp = ws[1]; + ws[1] = ws[2]; + ws[2] = tmp; + } + if (ws[3] < ws[2]) { + tmp = ws[2]; + ws[2] = ws[3]; + ws[3] = tmp; + } + if (ws[2] < ws[1]) { + tmp = ws[1]; + ws[1] = ws[2]; + ws[2] = tmp; + } + } + + ki = kkidx [bs[0]] [ws[0]]; /* kkidx [black king] [white king] */ + +/*128 == (128 & (((ws[1]^ws[2])-1) | ((ws[1]^ws[3])-1) | ((ws[2]^ws[3])-1)) */ + + if (ws[1] == ws[2] || ws[1] == ws[3] || ws[2] == ws[3]) { + *out = NOINDEX; + return FALSE; + } + + ai = aaa_getsubi ( ws[1], ws[2], ws[3] ); + + if (IDX_is_empty(ki) || IDX_is_empty(ai)) { + *out = NOINDEX; + return FALSE; + } + *out = ki * BLOCK_A + ai; + return TRUE; +} + +/****************** End KAAB/K *************************************/ + +/********************** KAP/KB ************************************/ + +static bool_t test_kapkb (void); +static bool_t kapkb_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out); +static void kapkb_indextopc (index_t i, SQUARE *pw, SQUARE *pb); + +static bool_t +test_kapkb (void) +{ + + enum {MAXPC = 16+1}; + char str[] = "kapkb"; + SQUARE a, b, c, d, e; + SQUARE pw[MAXPC], pb[MAXPC]; + SQUARE px[MAXPC], py[MAXPC]; + + index_t i, j; + bool_t err = FALSE; + + printf ("%8s ", str); + + for (a = 0; a < 64; a++) { + for (b = 0; b < 64; b++) { + for (c = 0; c < 64; c++) { + for (d = 0; d < 64; d++) { + for (e = 0; e < 64; e++) { + + if (c <= H1 || c >= A8) + continue; + + pw[0] = a; + pw[1] = b; + pw[2] = c; + pw[3] = NOSQUARE; + + pb[0] = e; + pb[1] = d; + pb[2] = NOSQUARE; + + if (kapkb_pctoindex (pw, pb, &i)) { + kapkb_indextopc (i, px, py); + kapkb_pctoindex (px, py, &j); + if (i != j) { + err = TRUE; + } + assert (i == j); + } + + } + } + } + } + + if ((a&1)==0) { + printf("."); + fflush(stdout); + } + } + + if (err) + printf ("> %s NOT passed\n", str); + else + printf ("> %s PASSED\n", str); + return !err; +} + +static void +kapkb_indextopc (index_t i, SQUARE *pw, SQUARE *pb) +{ + /*---------------------------------------------------------* + inverse work to make sure that the following is valid + index = a * BLOCK_A + b * BLOCK_B + c * BLOCK_C + d * BLOCK_D + e; + *----------------------------------------------------------*/ + enum {B11100 = 7u << 2}; + enum {BLOCK_A = 64*64*64*64, BLOCK_B = 64*64*64, BLOCK_C = 64*64, BLOCK_D = 64}; + index_t a, b, c, d, e, r; + index_t x; + + r = i; + a = r / BLOCK_A; + r -= a * BLOCK_A; + b = r / BLOCK_B; + r -= b * BLOCK_B; + c = r / BLOCK_C; + r -= c * BLOCK_C; + d = r / BLOCK_D; + r -= d * BLOCK_D; + e = r; + + /* x is pslice */ + x = a; + x += x & B11100; /* get upper part and double it */ + x += 8; /* add extra row */ + x ^= 070; /* flip NS */ + + pw[0] = (SQUARE) b; + pb[0] = (SQUARE) c; + pw[1] = (SQUARE) d; + pw[2] = (SQUARE) x; + pw[3] = NOSQUARE; + pb[1] = (SQUARE) e; + pb[2] = NOSQUARE; + + assert (kapkb_pctoindex (pw, pb, &a) && a == i); + + return; +} + + +static bool_t +kapkb_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out) +{ + enum {BLOCK_A = 64*64*64*64, BLOCK_B = 64*64*64, BLOCK_C = 64*64, BLOCK_D = 64}; + index_t pslice; + SQUARE sq; + SQUARE pawn = pw[2]; + SQUARE wa = pw[1]; + SQUARE wk = pw[0]; + SQUARE bk = pb[0]; + SQUARE ba = pb[1]; + + assert (A2 <= pawn && pawn < A8); + + if ( !(A2 <= pawn && pawn < A8)) { + *out = NOINDEX; + return FALSE; + } + + if ((pawn & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */ + pawn = flipWE (pawn); + wk = flipWE (wk); + bk = flipWE (bk); + wa = flipWE (wa); + ba = flipWE (ba); + } + + sq = pawn; + sq ^= 070; /* flipNS*/ + sq -= 8; /* down one row*/ + pslice = (index_t) ((sq+(sq&3)) >> 1); + + *out = pslice * BLOCK_A + (index_t)wk * BLOCK_B + (index_t)bk * BLOCK_C + (index_t)wa * BLOCK_D + (index_t)ba; + + return TRUE; +} +/********************** end KAP/KB ************************************/ + +/************************* KAB/KP ************************************/ + +static bool_t test_kabkp (void); +static bool_t kabkp_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out); +static void kabkp_indextopc (index_t i, SQUARE *pw, SQUARE *pb); + +static bool_t +test_kabkp (void) +{ + + enum {MAXPC = 16+1}; + char str[] = "kabkp"; + SQUARE a, b, c, d, e; + SQUARE pw[MAXPC], pb[MAXPC]; + SQUARE px[MAXPC], py[MAXPC]; + + index_t i, j; + bool_t err = FALSE; + + printf ("%8s ", str); + + for (a = 0; a < 64; a++) { + for (b = 0; b < 64; b++) { + for (c = 0; c < 64; c++) { + for (d = 0; d < 64; d++) { + for (e = 0; e < 64; e++) { + + if (d <= H1 || d >= A8) + continue; + + pw[0] = a; + pw[1] = b; + pw[2] = c; + pw[3] = NOSQUARE; + + pb[0] = e; + pb[1] = d; + pb[2] = NOSQUARE; + + if (kabkp_pctoindex (pw, pb, &i)) { + kabkp_indextopc (i, px, py); + kabkp_pctoindex (px, py, &j); + if (i != j) { + err = TRUE; + } + assert (i == j); + } + + } + } + } + } + + if ((a&1)==0) { + printf("."); + fflush(stdout); + } + } + + if (err) + printf ("> %s NOT passed\n", str); + else + printf ("> %s PASSED\n", str); + return !err; +} + +static void +kabkp_indextopc (index_t i, SQUARE *pw, SQUARE *pb) +{ + /*---------------------------------------------------------* + inverse work to make sure that the following is valid + index = a * BLOCK_A + b * BLOCK_B + c * BLOCK_C + d * BLOCK_D + e; + *----------------------------------------------------------*/ + enum {B11100 = 7u << 2}; + enum {BLOCK_A = 64*64*64*64, BLOCK_B = 64*64*64, BLOCK_C = 64*64, BLOCK_D = 64}; + index_t a, b, c, d, e, r; + index_t x; + + r = i; + a = r / BLOCK_A; + r -= a * BLOCK_A; + b = r / BLOCK_B; + r -= b * BLOCK_B; + c = r / BLOCK_C; + r -= c * BLOCK_C; + d = r / BLOCK_D; + r -= d * BLOCK_D; + e = r; + + /* x is pslice */ + x = a; + x += x & B11100; /* get upper part and double it */ + x += 8; /* add extra row */ + /*x ^= 070;*/ /* do not flip NS */ + + pw[0] = (SQUARE) b; + pb[0] = (SQUARE) c; + pw[1] = (SQUARE) d; + pw[2] = (SQUARE) e; + pw[3] = NOSQUARE; + pb[1] = (SQUARE) x; + pb[2] = NOSQUARE; + + assert (kabkp_pctoindex (pw, pb, &a) && a == i); + + return; +} + + +static bool_t +kabkp_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out) +{ + enum {BLOCK_A = 64*64*64*64, BLOCK_B = 64*64*64, BLOCK_C = 64*64, BLOCK_D = 64}; + index_t pslice; + SQUARE sq; + SQUARE pawn = pb[1]; + SQUARE wa = pw[1]; + SQUARE wk = pw[0]; + SQUARE bk = pb[0]; + SQUARE wb = pw[2]; + + assert (A2 <= pawn && pawn < A8); + + if ( !(A2 <= pawn && pawn < A8)) { + *out = NOINDEX; + return FALSE; + } + + if ((pawn & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */ + pawn = flipWE (pawn); + wk = flipWE (wk); + bk = flipWE (bk); + wa = flipWE (wa); + wb = flipWE (wb); + } + + sq = pawn; + /*sq ^= 070;*/ /* do not flipNS*/ + sq -= 8; /* down one row*/ + pslice = (index_t) ((sq+(sq&3)) >> 1); + + *out = pslice * BLOCK_A + (index_t)wk * BLOCK_B + (index_t)bk * BLOCK_C + (index_t)wa * BLOCK_D + (index_t)wb; + + return TRUE; +} +/********************** end KAB/KP ************************************/ + + +static void +kpk_indextopc (index_t i, SQUARE *pw, SQUARE *pb) +{ + /*---------------------------------------------------------* + inverse work to make sure that the following is valid + index = a * BLOCK_A + b * BLOCK_B + c; + *----------------------------------------------------------*/ + enum {B11100 = 7u << 2}; + enum {BLOCK_A = 64*64, BLOCK_B = 64}; + index_t a, b, c, r; + index_t x; + + r = i; + a = r / BLOCK_A; + r -= a * BLOCK_A; + b = r / BLOCK_B; + r -= b * BLOCK_B; + c = r; + + /* x is pslice */ + x = a; + x += x & B11100; /* get upper part and double it */ + x += 8; /* add extra row */ + x ^= 070; /* flip NS */ + + pw[1] = (SQUARE) x; + pw[0] = (SQUARE) b; + pb[0] = (SQUARE) c; + + pw[2] = NOSQUARE; + pb[1] = NOSQUARE; + + assert (kpk_pctoindex (pw, pb, &a) && a == i); + + return; +} + + +static bool_t +kpk_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out) +{ + enum {BLOCK_A = 64*64, BLOCK_B = 64}; + index_t pslice; + SQUARE sq; + SQUARE pawn = pw[1]; + SQUARE wk = pw[0]; + SQUARE bk = pb[0]; + + #ifdef DEBUG + if ( !(A2 <= pawn && pawn < A8)) { + SQ_CONTENT wp[MAX_LISTSIZE], bp[MAX_LISTSIZE]; + bp [0] = wp[0] = KING; + wp[1] = PAWN; + wp[2] = bp[1] = NOPIECE; + output_state (0, pw, pb, wp, bp); + } + #endif + + assert (A2 <= pawn && pawn < A8); + + if ( !(A2 <= pawn && pawn < A8)) { + *out = NOINDEX; + return FALSE; + } + + if ((pawn & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */ + pawn = flipWE (pawn); + wk = flipWE (wk); + bk = flipWE (bk); + } + + sq = pawn; + sq ^= 070; /* flipNS*/ + sq -= 8; /* down one row*/ + pslice = (index_t) ((sq+(sq&3)) >> 1); + + *out = pslice * BLOCK_A + (index_t)wk * BLOCK_B + (index_t)bk; + + return TRUE; +} + + +/********************** KPP/K ************************************/ + +static bool_t test_kppk (void); +static bool_t kppk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out); +static void kppk_indextopc (index_t i, SQUARE *pw, SQUARE *pb); + +static bool_t +test_kppk (void) +{ + + enum {MAXPC = 16+1}; + char str[] = "kppk"; + SQUARE a, b, c, d; + SQUARE pw[MAXPC], pb[MAXPC]; + SQUARE px[MAXPC], py[MAXPC]; + + index_t i, j; + bool_t err = FALSE; + + printf ("%8s ", str); + + for (b = 0; b < 64; b++) { + for (c = 0; c < 64; c++) { + sq_t anchor1, anchor2, loosen1, loosen2; + if (c <= H1 || c >= A8) + continue; + if (b <= H1 || b >= A8) + continue; + + pp_putanchorfirst (b, c, &anchor1, &loosen1); + pp_putanchorfirst (c, b, &anchor2, &loosen2); + if (!(anchor1 == anchor2 && loosen1 == loosen2)) { + printf ("Output depends on input in pp_outanchorfirst()\n input:%u, %u\n",(unsigned)b,(unsigned)c); + fatal_error(); + } + } + } + + + for (a = 0; a < 64; a++) { + for (b = 0; b < 64; b++) { + for (c = 0; c < 64; c++) { + for (d = 0; d < 64; d++) { + + + if (c <= H1 || c >= A8) + continue; + if (b <= H1 || b >= A8) + continue; + + + pw[0] = a; + pw[1] = b; + pw[2] = c; + pw[3] = NOSQUARE; + + pb[0] = d; + pb[1] = NOSQUARE; + + if (kppk_pctoindex (pw, pb, &i)) { + kppk_indextopc (i, px, py); + kppk_pctoindex (px, py, &j); + if (i != j) { + err = TRUE; + } + assert (i == j); + } + + + } + } + } + + if ((a&1)==0) { + printf("."); + fflush(stdout); + } + } + + if (err) + printf ("> %s NOT passed\n", str); + else + printf ("> %s PASSED\n", str); + return !err; +} + +static void +kppk_indextopc (index_t i, SQUARE *pw, SQUARE *pb) +{ + /*---------------------------------------------------------* + inverse work to make sure that the following is valid + index = a * BLOCK_A + b * BLOCK_B + c; + *----------------------------------------------------------*/ + enum {B11100 = 7u << 2}; + enum {BLOCK_A = 64*64, BLOCK_B = 64}; + index_t a, b, c, r; + index_t m, n; + + r = i; + a = r / BLOCK_A; + r -= a * BLOCK_A; + b = r / BLOCK_B; + r -= b * BLOCK_B; + c = r; + + m = pp_hi24 [a]; + n = pp_lo48 [a]; + + pw[0] = (SQUARE) b; + pb[0] = (SQUARE) c; + pb[1] = NOSQUARE; + + pw[1] = pidx24_to_wsq (m); + pw[2] = pidx48_to_wsq (n); + + pw[3] = NOSQUARE; + + + assert (A2 <= pw[1] && pw[1] < A8); + assert (A2 <= pw[2] && pw[2] < A8); + +#ifdef DEBUG + if (!(kppk_pctoindex (pw, pb, &a) && a == i)) { + pc_t wp[] = {KING, PAWN, PAWN, NOPIECE}; + pc_t bp[] = {KING, NOPIECE}; + printf("Indexes not matching: input:%d, output:%d\n", i, a); + print_pos (pw, pb, wp, bp); + } +#endif + + assert (kppk_pctoindex (pw, pb, &a) && a == i); + + return; +} + + +static bool_t +kppk_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out) +{ + enum {BLOCK_A = 64*64, BLOCK_B = 64}; + index_t pp_slice; + SQUARE anchor, loosen; + + SQUARE wk = pw[0]; + SQUARE pawn_a = pw[1]; + SQUARE pawn_b = pw[2]; + SQUARE bk = pb[0]; + index_t i, j; + + #ifdef DEBUG + if (!(A2 <= pawn_a && pawn_a < A8)) { + printf ("\n\nsquare of pawn_a: %s\n", Square_str[pawn_a]); + printf(" wk %s\n p1 %s\n p2 %s\n bk %s\n" + , Square_str[wk] + , Square_str[pawn_a] + , Square_str[pawn_b] + , Square_str[bk] + ); + } + #endif + + assert (A2 <= pawn_a && pawn_a < A8); + assert (A2 <= pawn_b && pawn_b < A8); + + pp_putanchorfirst (pawn_a, pawn_b, &anchor, &loosen); + + if ((anchor & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */ + anchor = flipWE (anchor); + loosen = flipWE (loosen); + wk = flipWE (wk); + bk = flipWE (bk); + } + + i = wsq_to_pidx24 (anchor); + j = wsq_to_pidx48 (loosen); + + pp_slice = ppidx [i] [j]; + + if (IDX_is_empty(pp_slice)) { + *out = NOINDEX; + return FALSE; + } + + assert (pp_slice < MAX_PPINDEX ); + + *out = pp_slice * BLOCK_A + (index_t)wk * BLOCK_B + (index_t)bk; + + return TRUE; +} +/****************** end KPP/K ************************************/ + +static void +kakp_indextopc (index_t i, SQUARE *pw, SQUARE *pb) +{ + /*---------------------------------------------------------* + inverse work to make sure that the following is valid + index = a * BLOCK_A + b * BLOCK_B + c * BLOCK_C + d; + *----------------------------------------------------------*/ + enum {B11100 = 7u << 2}; + enum {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64}; + index_t a, b, c, d, r; + index_t x; + + r = i; + a = r / BLOCK_A; + r -= a * BLOCK_A; + b = r / BLOCK_B; + r -= b * BLOCK_B; + c = r / BLOCK_C; + r -= c * BLOCK_C; + d = r; + + /* x is pslice */ + x = a; + x += x & B11100; /* get upper part and double it */ + x += 8; /* add extra row */ +/* x ^= 070; */ /* flip NS */ + + pw[0] = (SQUARE) b; + pb[0] = (SQUARE) c; + pw[1] = (SQUARE) d; + pb[1] = (SQUARE) x; + pw[2] = NOSQUARE; + pb[2] = NOSQUARE; + + assert (kakp_pctoindex (pw, pb, &a) && a == i); + + return; +} + + +static bool_t +kakp_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out) +{ + enum {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64}; + index_t pslice; + SQUARE sq; + SQUARE pawn = pb[1]; + SQUARE wa = pw[1]; + SQUARE wk = pw[0]; + SQUARE bk = pb[0]; + + assert (A2 <= pawn && pawn < A8); + + if ( !(A2 <= pawn && pawn < A8)) { + *out = NOINDEX; + return FALSE; + } + + if ((pawn & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */ + pawn = flipWE (pawn); + wk = flipWE (wk); + bk = flipWE (bk); + wa = flipWE (wa); + } + + sq = pawn; + /*sq ^= 070;*/ /* flipNS*/ + sq -= 8; /* down one row*/ + pslice = (index_t) ((sq+(sq&3)) >> 1); + + *out = pslice * BLOCK_A + (index_t)wk * BLOCK_B + (index_t)bk * BLOCK_C + (index_t)wa; + + return TRUE; +} + + +static void +kapk_indextopc (index_t i, SQUARE *pw, SQUARE *pb) +{ + /*---------------------------------------------------------* + inverse work to make sure that the following is valid + index = a * BLOCK_A + b * BLOCK_B + c * BLOCK_C + d; + *----------------------------------------------------------*/ + enum {B11100 = 7u << 2}; + enum {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64}; + index_t a, b, c, d, r; + index_t x; + + r = i; + a = r / BLOCK_A; + r -= a * BLOCK_A; + b = r / BLOCK_B; + r -= b * BLOCK_B; + c = r / BLOCK_C; + r -= c * BLOCK_C; + d = r; + + /* x is pslice */ + x = a; + x += x & B11100; /* get upper part and double it */ + x += 8; /* add extra row */ + x ^= 070; /* flip NS */ + + pw[0] = (SQUARE) b; + pb[0] = (SQUARE) c; + pw[1] = (SQUARE) d; + pw[2] = (SQUARE) x; + pw[3] = NOSQUARE; + pb[1] = NOSQUARE; + + assert (kapk_pctoindex (pw, pb, &a) && a == i); + + return; +} + + +static bool_t +kapk_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out) +{ + enum {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64}; + index_t pslice; + SQUARE sq; + SQUARE pawn = pw[2]; + SQUARE wa = pw[1]; + SQUARE wk = pw[0]; + SQUARE bk = pb[0]; + + assert (A2 <= pawn && pawn < A8); + + if ( !(A2 <= pawn && pawn < A8)) { + *out = NOINDEX; + return FALSE; + } + + if ((pawn & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */ + pawn = flipWE (pawn); + wk = flipWE (wk); + bk = flipWE (bk); + wa = flipWE (wa); + } + + sq = pawn; + sq ^= 070; /* flipNS*/ + sq -= 8; /* down one row*/ + pslice = (index_t) ((sq+(sq&3)) >> 1); + + *out = pslice * BLOCK_A + (index_t)wk * BLOCK_B + (index_t)bk * BLOCK_C + (index_t)wa; + + return TRUE; +} + + +static void +kaak_indextopc (index_t i, SQUARE *pw, SQUARE *pb) +{ + enum {BLOCK_A = MAX_AAINDEX}; + index_t a, b, r, x, y; + + r = i; + a = r / BLOCK_A; + r -= a * BLOCK_A; + b = r; + + assert (i == (a * BLOCK_A + b)); + + pw[0] = wksq [a]; + pb[0] = bksq [a]; + + x = aabase [b]; + y = (b + 1) + x - (x * (127-x)/2); + + pw[1] = (SQUARE) x; + pw[2] = (SQUARE) y; + pw[3] = NOSQUARE; + + pb[1] = NOSQUARE; + + assert (kaak_pctoindex (pw, pb, &a) && a == i); + + return; +} + + +static bool_t +kaak_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out) +{ + enum {N_WHITE = 3, N_BLACK = 1}; + enum {BLOCK_A = MAX_AAINDEX}; + SQUARE ws[MAX_LISTSIZE], bs[MAX_LISTSIZE]; + index_t ki, ai; + unsigned int ft; + SQUARE i; + + ft = flipt [inp_pb[0]] [inp_pw[0]]; + + assert (ft < 8); + + for (i = 0; i < N_WHITE; i++) ws[i] = inp_pw[i]; + ws[N_WHITE] = NOSQUARE; + for (i = 0; i < N_BLACK; i++) bs[i] = inp_pb[i]; + bs[N_BLACK] = NOSQUARE; + + if ((ft & WE_FLAG) != 0) { + for (i = 0; i < N_WHITE; i++) ws[i] = flipWE (ws[i]); + for (i = 0; i < N_BLACK; i++) bs[i] = flipWE (bs[i]); + } + + if ((ft & NS_FLAG) != 0) { + for (i = 0; i < N_WHITE; i++) ws[i] = flipNS (ws[i]); + for (i = 0; i < N_BLACK; i++) bs[i] = flipNS (bs[i]); + } + + if ((ft & NW_SE_FLAG) != 0) { + for (i = 0; i < N_WHITE; i++) ws[i] = flipNW_SE (ws[i]); + for (i = 0; i < N_BLACK; i++) bs[i] = flipNW_SE (bs[i]); + } + + ki = kkidx [bs[0]] [ws[0]]; /* kkidx [black king] [white king] */ + ai = (index_t) aaidx [ws[1]] [ws[2]]; + + if (IDX_is_empty(ki) || IDX_is_empty(ai)) { + *out = NOINDEX; + return FALSE; + } + *out = ki * BLOCK_A + ai; + return TRUE; +} + +/********************** KPP/KA ************************************/ + +static bool_t test_kppka (void); +static bool_t kppka_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out); +static void kppka_indextopc (index_t i, SQUARE *pw, SQUARE *pb); + +static bool_t +test_kppka (void) +{ + + enum {MAXPC = 16+1}; + char str[] = "kppka"; + SQUARE a, b, c, d, e; + SQUARE pw[MAXPC], pb[MAXPC]; + SQUARE px[MAXPC], py[MAXPC]; + + index_t i, j; + bool_t err = FALSE; + + printf ("%8s ", str); + + for (a = 0; a < 64; a++) { + for (b = 0; b < 64; b++) { + for (c = 0; c < 64; c++) { + for (d = 0; d < 64; d++) { + for (e = 0; e < 64; e++) { + + if (c <= H1 || c >= A8) + continue; + if (b <= H1 || b >= A8) + continue; + + + pw[0] = a; + pw[1] = b; + pw[2] = c; + pw[3] = NOSQUARE; + + pb[0] = e; + pb[1] = d; + pb[2] = NOSQUARE; + + if (kppka_pctoindex (pw, pb, &i)) { + kppka_indextopc (i, px, py); + kppka_pctoindex (px, py, &j); + if (i != j) { + err = TRUE; + } + assert (i == j); + } + + } + } + } + } + + if ((a&1)==0) { + printf("."); + fflush(stdout); + } + } + + if (err) + printf ("> %s NOT passed\n", str); + else + printf ("> %s PASSED\n", str); + return !err; +} + + +static void +kppka_indextopc (index_t i, SQUARE *pw, SQUARE *pb) +{ + /*---------------------------------------------------------* + inverse work to make sure that the following is valid + index = a * BLOCK_A + b * BLOCK_B + c * BLOCK_C + d; + *----------------------------------------------------------*/ + + enum {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64}; + index_t a, b, c, d, r; + index_t m, n; + + r = i; + a = r / BLOCK_A; + r -= a * BLOCK_A; + b = r / BLOCK_B; + r -= b * BLOCK_B; + c = r / BLOCK_C; + r -= c * BLOCK_C; + d = r; + + m = pp_hi24 [a]; + n = pp_lo48 [a]; + + pw[0] = (SQUARE) b; + pw[1] = pidx24_to_wsq (m); + pw[2] = pidx48_to_wsq (n); + pw[3] = NOSQUARE; + + pb[0] = (SQUARE) c; + pb[1] = (SQUARE) d; + pb[2] = NOSQUARE; + + + assert (A2 <= pw[1] && pw[1] < A8); + assert (A2 <= pw[2] && pw[2] < A8); + assert (kppka_pctoindex (pw, pb, &a) && a == i); + + return; +} + + +static bool_t +kppka_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out) +{ + enum {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64}; + index_t pp_slice; + index_t i, j; + + SQUARE anchor, loosen; + + SQUARE wk = pw[0]; + SQUARE pawn_a = pw[1]; + SQUARE pawn_b = pw[2]; + SQUARE bk = pb[0]; + SQUARE ba = pb[1]; + + + assert (A2 <= pawn_a && pawn_a < A8); + assert (A2 <= pawn_b && pawn_b < A8); + + pp_putanchorfirst (pawn_a, pawn_b, &anchor, &loosen); + + if ((anchor & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */ + anchor = flipWE (anchor); + loosen = flipWE (loosen); + wk = flipWE (wk); + bk = flipWE (bk); + ba = flipWE (ba); + } + + i = wsq_to_pidx24 (anchor); + j = wsq_to_pidx48 (loosen); + + pp_slice = ppidx [i] [j]; + + if (IDX_is_empty(pp_slice)) { + *out = NOINDEX; + return FALSE; + } + + assert (pp_slice < MAX_PPINDEX ); + + *out = pp_slice * (index_t)BLOCK_A + (index_t)wk * (index_t)BLOCK_B + (index_t)bk * (index_t)BLOCK_C + (index_t)ba; + + return TRUE; +} + +/********************** end KPP/KA ************************************/ + +/********************** KAPP/K ************************************/ + +static bool_t test_kappk (void); +static bool_t kappk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out); +static void kappk_indextopc (index_t i, SQUARE *pw, SQUARE *pb); + +static bool_t +test_kappk (void) +{ + + enum {MAXPC = 16+1}; + char str[] = "kappk"; + SQUARE a, b, c, d, e; + SQUARE pw[MAXPC], pb[MAXPC]; + SQUARE px[MAXPC], py[MAXPC]; + + index_t i, j; + bool_t err = FALSE; + + printf ("%8s ", str); + + for (a = 0; a < 64; a++) { + for (b = 0; b < 64; b++) { + for (c = 0; c < 64; c++) { + for (d = 0; d < 64; d++) { + for (e = 0; e < 64; e++) { + + if (c <= H1 || c >= A8) + continue; + if (b <= H1 || b >= A8) + continue; + + + pw[0] = a; + pw[1] = d; + pw[2] = b; + pw[3] = c; + pw[4] = NOSQUARE; + + pb[0] = e; + pb[1] = NOSQUARE; + + if (kappk_pctoindex (pw, pb, &i)) { + kappk_indextopc (i, px, py); + kappk_pctoindex (px, py, &j); + if (i != j) { + err = TRUE; + } + assert (i == j); + } + + } + } + } + } + + if ((a&1)==0) { + printf("."); + fflush(stdout); + } + } + + if (err) + printf ("> %s NOT passed\n", str); + else + printf ("> %s PASSED\n", str); + return !err; +} + + +static void +kappk_indextopc (index_t i, SQUARE *pw, SQUARE *pb) +{ + /*---------------------------------------------------------* + inverse work to make sure that the following is valid + index = a * BLOCK_A + b * BLOCK_B + c * BLOCK_C + d; + *----------------------------------------------------------*/ + + enum {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64}; + index_t a, b, c, d, r; + index_t m, n; + + r = i; + a = r / BLOCK_A; + r -= a * BLOCK_A; + b = r / BLOCK_B; + r -= b * BLOCK_B; + c = r / BLOCK_C; + r -= c * BLOCK_C; + d = r; + + m = pp_hi24 [a]; + n = pp_lo48 [a]; + + pw[0] = (SQUARE) b; + pw[1] = (SQUARE) d; + pw[2] = pidx24_to_wsq (m); + pw[3] = pidx48_to_wsq (n); + pw[4] = NOSQUARE; + + pb[0] = (SQUARE) c; + pb[1] = NOSQUARE; + + + assert (A2 <= pw[3] && pw[3] < A8); + assert (A2 <= pw[2] && pw[2] < A8); + assert (kappk_pctoindex (pw, pb, &a) && a == i); + + return; +} + + +static bool_t +kappk_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out) +{ + enum {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64}; + index_t pp_slice; + SQUARE anchor, loosen; + + SQUARE wk = pw[0]; + SQUARE wa = pw[1]; + SQUARE pawn_a = pw[2]; + SQUARE pawn_b = pw[3]; + SQUARE bk = pb[0]; + + index_t i, j; + + assert (A2 <= pawn_a && pawn_a < A8); + assert (A2 <= pawn_b && pawn_b < A8); + + pp_putanchorfirst (pawn_a, pawn_b, &anchor, &loosen); + + if ((anchor & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */ + anchor = flipWE (anchor); + loosen = flipWE (loosen); + wk = flipWE (wk); + bk = flipWE (bk); + wa = flipWE (wa); + } + + i = wsq_to_pidx24 (anchor); + j = wsq_to_pidx48 (loosen); + + pp_slice = ppidx [i] [j]; + + if (IDX_is_empty(pp_slice)) { + *out = NOINDEX; + return FALSE; + } + + assert (pp_slice < MAX_PPINDEX ); + + *out = pp_slice * (index_t)BLOCK_A + (index_t)wk * (index_t)BLOCK_B + (index_t)bk * (index_t)BLOCK_C + (index_t)wa; + + return TRUE; +} + +/********************** end KAPP/K ************************************/ + +/********************** KAPP/K ************************************/ + +static bool_t test_kapkp (void); +static bool_t kapkp_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out); +static void kapkp_indextopc (index_t i, SQUARE *pw, SQUARE *pb); + +static bool_t +test_kapkp (void) +{ + + enum {MAXPC = 16+1}; + char str[] = "kapkp"; + SQUARE a, b, c, d, e; + SQUARE pw[MAXPC], pb[MAXPC]; + SQUARE px[MAXPC], py[MAXPC]; + + index_t i, j; + bool_t err = FALSE; + + printf ("%8s ", str); + + for (a = 0; a < 64; a++) { + for (b = 0; b < 64; b++) { + for (c = 0; c < 64; c++) { + for (d = 0; d < 64; d++) { + for (e = 0; e < 64; e++) { + + if (c <= H1 || c >= A8) + continue; + if (b <= H1 || b >= A8) + continue; + + + pw[0] = a; + pw[1] = d; + pw[2] = b; + pw[3] = NOSQUARE; + + pb[0] = e; + pb[1] = c; + pb[2] = NOSQUARE; + + if (kapkp_pctoindex (pw, pb, &i)) { + kapkp_indextopc (i, px, py); + kapkp_pctoindex (px, py, &j); + if (i != j) { + err = TRUE; + } + assert (i == j); + } + + } + } + } + } + + if ((a&1)==0) { + printf("."); + fflush(stdout); + } + } + + if (err) + printf ("> %s NOT passed\n", str); + else + printf ("> %s PASSED\n", str); + return !err; +} + + +static bool_t +kapkp_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out) +{ + enum {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64}; + index_t pp_slice; + SQUARE anchor, loosen; + + SQUARE wk = pw[0]; + SQUARE wa = pw[1]; + SQUARE pawn_a = pw[2]; + SQUARE bk = pb[0]; + SQUARE pawn_b = pb[1]; + index_t m, n; + + assert (A2 <= pawn_a && pawn_a < A8); + assert (A2 <= pawn_b && pawn_b < A8); + assert (pw[3] == NOSQUARE && pb[2] == NOSQUARE); + + anchor = pawn_a; + loosen = pawn_b; + + if ((anchor & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */ + anchor = flipWE (anchor); + loosen = flipWE (loosen); + wk = flipWE (wk); + bk = flipWE (bk); + wa = flipWE (wa); + } + + m = wsq_to_pidx24 (anchor); + n = (index_t)loosen - 8; + + pp_slice = m * 48 + n; + + if (IDX_is_empty(pp_slice)) { + *out = NOINDEX; + return FALSE; + } + + assert (pp_slice < (64*MAX_PpINDEX) ); + + *out = pp_slice * (index_t)BLOCK_A + (index_t)wk * (index_t)BLOCK_B + (index_t)bk * (index_t)BLOCK_C + (index_t)wa; + + return TRUE; +} + +static void +kapkp_indextopc (index_t i, SQUARE *pw, SQUARE *pb) +{ + /*---------------------------------------------------------* + inverse work to make sure that the following is valid + index = a * BLOCK_A + b * BLOCK_B + c * BLOCK_C + d; + *----------------------------------------------------------*/ + enum {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64}; + enum {block_m = 48}; + index_t a, b, c, d, r; + index_t m, n; + SQUARE sq_m, sq_n; + + r = i; + a = r / BLOCK_A; + r -= a * BLOCK_A; + b = r / BLOCK_B; + r -= b * BLOCK_B; + c = r / BLOCK_C; + r -= c * BLOCK_C; + d = r; + + /* unpack a, which is pslice, into m and n */ + r = a; + m = r / block_m; + r -= m * block_m; + n = r ; + + sq_m = pidx24_to_wsq (m); + sq_n = (SQUARE) n + 8; + + pw[0] = (SQUARE) b; + pb[0] = (SQUARE) c; + pw[1] = (SQUARE) d; + pw[2] = sq_m; + pb[1] = sq_n; + pw[3] = NOSQUARE; + pb[2] = NOSQUARE; + + assert (A2 <= sq_m && sq_m < A8); + assert (A2 <= sq_n && sq_n < A8); + assert (kapkp_pctoindex (pw, pb, &a) && a == i); + + return; +} + +/********************** end KAP/KP ************************************/ + +/********************** KABP/K ************************************/ + +static bool_t test_kabpk (void); +static bool_t kabpk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out); +static void kabpk_indextopc (index_t i, SQUARE *pw, SQUARE *pb); + +static bool_t +test_kabpk (void) +{ + + enum {MAXPC = 16+1}; + char str[] = "kabpk"; + SQUARE a, b, c, d, e; + SQUARE pw[MAXPC], pb[MAXPC]; + SQUARE px[MAXPC], py[MAXPC]; + + index_t i, j; + bool_t err = FALSE; + + printf ("%8s ", str); + + for (a = 0; a < 64; a++) { + for (b = 0; b < 64; b++) { + for (c = 0; c < 64; c++) { + for (d = 0; d < 64; d++) { + for (e = 0; e < 64; e++) { + + if (d <= H1 || d >= A8) + continue; + + pw[0] = a; + pw[1] = b; + pw[2] = c; + pw[3] = d; + pw[4] = NOSQUARE; + + pb[0] = e; + pb[1] = NOSQUARE; + + if (kabpk_pctoindex (pw, pb, &i)) { + kabpk_indextopc (i, px, py); + kabpk_pctoindex (px, py, &j); + if (i != j) { + err = TRUE; + } + assert (i == j); + } + + } + } + } + } + + if ((a&1)==0) { + printf("."); + fflush(stdout); + } + } + + if (err) + printf ("> %s NOT passed\n", str); + else + printf ("> %s PASSED\n", str); + return !err; +} + + +static void +kabpk_indextopc (index_t i, SQUARE *pw, SQUARE *pb) +{ + + /*---------------------------------------------------------* + inverse work to make sure that the following is valid + index = a * BLOCK_A + b * BLOCK_B + c * BLOCK_C + d * BLOCK_D + e; + *----------------------------------------------------------*/ + enum {BLOCK_A = 64*64*64*64, BLOCK_B = 64*64*64, BLOCK_C = 64*64, BLOCK_D = 64}; + index_t a, b, c, d, e, r; + SQUARE x; + + r = i; + a = r / BLOCK_A; + r -= a * BLOCK_A; + b = r / BLOCK_B; + r -= b * BLOCK_B; + c = r / BLOCK_C; + r -= c * BLOCK_C; + d = r / BLOCK_D; + r -= d * BLOCK_D; + e = r; + + x = pidx24_to_wsq(a); + + pw[0] = (SQUARE) b; + pw[1] = (SQUARE) d; + pw[2] = (SQUARE) e; + pw[3] = x; + pw[4] = NOSQUARE; + + pb[0] = (SQUARE) c; + pb[1] = NOSQUARE; + + assert (kabpk_pctoindex (pw, pb, &a) && a == i); + + return; +} + + +static bool_t +kabpk_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out) +{ + enum {BLOCK_A = 64*64*64*64, BLOCK_B = 64*64*64, BLOCK_C = 64*64, BLOCK_D = 64}; + index_t pslice; + + SQUARE wk = pw[0]; + SQUARE wa = pw[1]; + SQUARE wb = pw[2]; + SQUARE pawn = pw[3]; + SQUARE bk = pb[0]; + + assert (A2 <= pawn && pawn < A8); + + if ((pawn & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */ + pawn = flipWE (pawn); + wk = flipWE (wk); + bk = flipWE (bk); + wa = flipWE (wa); + wb = flipWE (wb); + } + + pslice = wsq_to_pidx24 (pawn); + + *out = pslice * (index_t)BLOCK_A + (index_t)wk * (index_t)BLOCK_B + (index_t)bk * (index_t)BLOCK_C + (index_t)wa * (index_t)BLOCK_D + (index_t)wb; + + return TRUE; +} + +/********************** end KABP/K ************************************/ + +/********************** KAAP/K ************************************/ + +static bool_t test_kaapk (void); +static bool_t kaapk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out); +static void kaapk_indextopc (index_t i, SQUARE *pw, SQUARE *pb); + +static bool_t +test_kaapk (void) +{ + + enum {MAXPC = 16+1}; + char str[] = "kaapk"; + SQUARE a, b, c, d, e; + SQUARE pw[MAXPC], pb[MAXPC]; + SQUARE px[MAXPC], py[MAXPC]; + + index_t i, j; + bool_t err = FALSE; + + printf ("%8s ", str); + + for (a = 0; a < 64; a++) { + for (b = 0; b < 64; b++) { + for (c = 0; c < 64; c++) { + for (d = 0; d < 64; d++) { + for (e = 0; e < 64; e++) { + + if (d <= H1 || d >= A8) + continue; + + pw[0] = a; + pw[1] = b; + pw[2] = c; + pw[3] = d; + pw[4] = NOSQUARE; + + pb[0] = e; + pb[1] = NOSQUARE; + + if (kaapk_pctoindex (pw, pb, &i)) { + kaapk_indextopc (i, px, py); + kaapk_pctoindex (px, py, &j); + if (i != j) { + err = TRUE; + } + assert (i == j); + } + + } + } + } + } + + if ((a&1)==0) { + printf("."); + fflush(stdout); + } + } + + if (err) + printf ("> %s NOT passed\n", str); + else + printf ("> %s PASSED\n", str); + return !err; +} + + +static void +kaapk_indextopc (index_t i, SQUARE *pw, SQUARE *pb) +{ + /*---------------------------------------------------------* + inverse work to make sure that the following is valid + index = a * BLOCK_A + b * BLOCK_B + c * BLOCK_C + d; + *----------------------------------------------------------*/ + enum {BLOCK_C = MAX_AAINDEX + ,BLOCK_B = 64*BLOCK_C + ,BLOCK_A = 64*BLOCK_B + }; + index_t a, b, c, d, r; + index_t x, y, z; + + assert (i >= 0); + + r = i; + a = r / BLOCK_A; + r -= a * BLOCK_A; + b = r / BLOCK_B; + r -= b * BLOCK_B; + c = r / BLOCK_C; + r -= c * BLOCK_C; + d = r; + + z = (index_t) pidx24_to_wsq(a); + + /* split d into x, y*/ + x = aabase [d]; + y = (d + 1) + x - (x * (127-x)/2); + + assert (aaidx[x][y] == aaidx[y][x]); + assert (aaidx[x][y] == d); + + + pw[0] = (SQUARE) b; + pw[1] = (SQUARE) x; + pw[2] = (SQUARE) y; + pw[3] = (SQUARE) z; + pw[4] = NOSQUARE; + + pb[0] = (SQUARE) c; + pb[1] = NOSQUARE; + + assert (kaapk_pctoindex (pw, pb, &a) && a == i); + + return; +} + + +static bool_t +kaapk_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out) +{ + enum {BLOCK_C = MAX_AAINDEX + ,BLOCK_B = 64*BLOCK_C + ,BLOCK_A = 64*BLOCK_B + }; + index_t aa_combo, pslice; + + SQUARE wk = pw[0]; + SQUARE wa = pw[1]; + SQUARE wa2 = pw[2]; + SQUARE pawn = pw[3]; + SQUARE bk = pb[0]; + + assert (A2 <= pawn && pawn < A8); + + if ((pawn & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */ + pawn = flipWE (pawn); + wk = flipWE (wk); + bk = flipWE (bk); + wa = flipWE (wa); + wa2 = flipWE (wa2); + } + + pslice = wsq_to_pidx24 (pawn); + + aa_combo = (index_t) aaidx [wa] [wa2]; + + if (IDX_is_empty(aa_combo)) { + *out = NOINDEX; + return FALSE; + } + + *out = pslice * (index_t)BLOCK_A + (index_t)wk * (index_t)BLOCK_B + (index_t)bk * (index_t)BLOCK_C + aa_combo; + + assert (*out >= 0); + + return TRUE; +} + +/********************** end KAAP/K ************************************/ + +/********************** KAA/KP ************************************/ + +static bool_t test_kaakp (void); +static bool_t kaakp_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out); +static void kaakp_indextopc (index_t i, SQUARE *pw, SQUARE *pb); + +static bool_t +test_kaakp (void) +{ + + enum {MAXPC = 16+1}; + char str[] = "kaakp"; + SQUARE a, b, c, d, e; + SQUARE pw[MAXPC], pb[MAXPC]; + SQUARE px[MAXPC], py[MAXPC]; + + index_t i, j; + bool_t err = FALSE; + + printf ("%8s ", str); + + for (a = 0; a < 64; a++) { + for (b = 0; b < 64; b++) { + for (c = 0; c < 64; c++) { + for (d = 0; d < 64; d++) { + for (e = 0; e < 64; e++) { + + if (d <= H1 || d >= A8) + continue; + + pw[0] = a; + pw[1] = b; + pw[2] = c; + pw[3] = NOSQUARE; + + pb[0] = e; + pb[1] = d; + pb[2] = NOSQUARE; + + if (kaakp_pctoindex (pw, pb, &i)) { + kaakp_indextopc (i, px, py); + kaakp_pctoindex (px, py, &j); + if (i != j) { + err = TRUE; + } + assert (i == j); + } + + } + } + } + } + + if ((a&1)==0) { + printf("."); + fflush(stdout); + } + } + + if (err) + printf ("> %s NOT passed\n", str); + else + printf ("> %s PASSED\n", str); + return !err; +} + + +static void +kaakp_indextopc (index_t i, SQUARE *pw, SQUARE *pb) +{ + /*---------------------------------------------------------* + inverse work to make sure that the following is valid + index = a * BLOCK_A + b * BLOCK_B + c * BLOCK_C + d; + *----------------------------------------------------------*/ + enum {BLOCK_C = MAX_AAINDEX + ,BLOCK_B = 64*BLOCK_C + ,BLOCK_A = 64*BLOCK_B + }; + index_t a, b, c, d, r; + index_t x, y, z; + SQUARE zq; + + assert (i >= 0); + + r = i; + a = r / BLOCK_A; + r -= a * BLOCK_A; + b = r / BLOCK_B; + r -= b * BLOCK_B; + c = r / BLOCK_C; + r -= c * BLOCK_C; + d = r; + + zq = pidx24_to_wsq(a); + z = (index_t)flipNS(zq); + + + /* split d into x, y*/ + x = aabase [d]; + y = (d + 1) + x - (x * (127-x)/2); + + assert (aaidx[x][y] == aaidx[y][x]); + assert (aaidx[x][y] == d); + + + pw[0] = (SQUARE)b; + pw[1] = (SQUARE)x; + pw[2] = (SQUARE)y; + pw[3] = NOSQUARE; + + pb[0] = (SQUARE)c; + pb[1] = (SQUARE)z; + pb[2] = NOSQUARE; + + assert (kaakp_pctoindex (pw, pb, &a) && a == i); + + return; +} + + +static bool_t +kaakp_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out) +{ + enum {BLOCK_C = MAX_AAINDEX + ,BLOCK_B = 64*BLOCK_C + ,BLOCK_A = 64*BLOCK_B + }; + index_t aa_combo, pslice; + + SQUARE wk = pw[0]; + SQUARE wa = pw[1]; + SQUARE wa2 = pw[2]; + SQUARE bk = pb[0]; + SQUARE pawn = pb[1]; + + assert (A2 <= pawn && pawn < A8); + + if ((pawn & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */ + pawn = flipWE (pawn); + wk = flipWE (wk); + bk = flipWE (bk); + wa = flipWE (wa); + wa2 = flipWE (wa2); + } + + pawn = flipNS(pawn); + pslice = wsq_to_pidx24 (pawn); + + aa_combo = (index_t)aaidx [wa] [wa2]; + + if (IDX_is_empty(aa_combo)) { + *out = NOINDEX; + return FALSE; + } + + *out = pslice * (index_t)BLOCK_A + (index_t)wk * (index_t)BLOCK_B + (index_t)bk * (index_t)BLOCK_C + aa_combo; + + assert (*out >= 0); + + return TRUE; +} + +/********************** end KAA/KP ************************************/ + +/********************** KPP/KP ************************************/ +/* +index_t pp48_idx[48][48]; +sq_t pp48_sq_x[MAX_PP48_INDEX]; +sq_t pp48_sq_y[MAX_PP48_INDEX]; +*/ +static bool_t test_kppkp (void); +static bool_t kppkp_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out); +static void kppkp_indextopc (index_t i, SQUARE *pw, SQUARE *pb); + +static sq_t map24_b (sq_t s); +static sq_t unmap24_b (index_t i); + +static index_t +init_pp48_idx (void) +/* modifies pp48_idx[][], pp48_sq_x[], pp48_sq_y[] */ +{ + enum {MAX_I = 48, MAX_J = 48}; + SQUARE i, j; + index_t idx = 0; + SQUARE a, b; + + /* default is noindex */ + for (i = 0; i < MAX_I; i++) { + for (j = 0; j < MAX_J; j++) { + IDX_set_empty (pp48_idx [i][j]); + } + } + + for (idx = 0; idx < MAX_PP48_INDEX; idx++) { + pp48_sq_x [idx] = NOSQUARE; + pp48_sq_y [idx] = NOSQUARE; + } + + idx = 0; + for (a = H7; a >= A2; a--) { + + for (b = a - 1; b >= A2; b--) { + + i = flipWE( flipNS (a) ) - 8; + j = flipWE( flipNS (b) ) - 8; + + if (IDX_is_empty(pp48_idx [i] [j])) { + + pp48_idx [i][j]= idx; assert (idx < MAX_PP48_INDEX); + pp48_idx [j][i]= idx; + pp48_sq_x [idx] = i; assert (i < MAX_I); + pp48_sq_y [idx] = j; assert (j < MAX_J); + idx++; + } + } + } + assert (idx == MAX_PP48_INDEX); + return idx; +} + + + +static bool_t +test_kppkp (void) +{ + + enum {MAXPC = 16+1}; + char str[] = "kppkp"; + SQUARE a, b, c, d, e; + SQUARE pw[MAXPC], pb[MAXPC]; + SQUARE px[MAXPC], py[MAXPC]; + + index_t i, j; + bool_t err = FALSE; + + printf ("%8s ", str); + + for (a = 0; a < 64; a++) { + for (b = 0; b < 64; b++) { + for (c = 0; c < 64; c++) { + for (d = 0; d < 64; d++) { + for (e = 0; e < 64; e++) { + + if (c <= H1 || c >= A8) + continue; + if (b <= H1 || b >= A8) + continue; + if (d <= H1 || d >= A8) + continue; + + pw[0] = a; + pw[1] = b; + pw[2] = c; + pw[3] = NOSQUARE; + + pb[0] = e; + pb[1] = d; + pb[2] = NOSQUARE; + + if (kppkp_pctoindex (pw, pb, &i)) { + kppkp_indextopc (i, px, py); + kppkp_pctoindex (px, py, &j); + if (i != j) { + err = TRUE; + } + assert (i == j); + } + + } + } + } + } + + if ((a&1)==0) { + printf("."); + fflush(stdout); + } + } + + if (err) + printf ("> %s NOT passed\n", str); + else + printf ("> %s PASSED\n", str); + return !err; +} + + +static void +kppkp_indextopc (index_t i, SQUARE *pw, SQUARE *pb) +{ + /*---------------------------------------------------------* + inverse work to make sure that the following is valid + index = a * BLOCK_A + b * BLOCK_B + c * BLOCK_C + d; + *----------------------------------------------------------*/ + + enum {BLOCK_A = MAX_PP48_INDEX*64*64, BLOCK_B = 64*64, BLOCK_C = 64}; + index_t a, b, c, d, r; + SQUARE m, n; + + r = i; + a = r / BLOCK_A; + r -= a * BLOCK_A; + b = r / BLOCK_B; + r -= b * BLOCK_B; + c = r / BLOCK_C; + r -= c * BLOCK_C; + d = r; + + m = pp48_sq_x [b]; + n = pp48_sq_y [b]; + + pw[0] = (SQUARE)c; + pw[1] = flipWE(flipNS(m+8)); + pw[2] = flipWE(flipNS(n+8)); + pw[3] = NOSQUARE; + + pb[0] = (SQUARE)d; + pb[1] = (SQUARE)unmap24_b (a); + pb[2] = NOSQUARE; + + + assert (A2 <= pw[1] && pw[1] < A8); + assert (A2 <= pw[2] && pw[2] < A8); + assert (A2 <= pb[1] && pb[1] < A8); + assert (kppkp_pctoindex (pw, pb, &a) && a == i); + + return; +} + + +static bool_t +kppkp_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out) +{ + enum {BLOCK_A = MAX_PP48_INDEX*64*64, BLOCK_B = 64*64, BLOCK_C = 64}; + index_t pp48_slice; + + SQUARE wk = pw[0]; + SQUARE pawn_a = pw[1]; + SQUARE pawn_b = pw[2]; + SQUARE bk = pb[0]; + SQUARE pawn_c = pb[1]; + SQUARE i, j, k; + + assert (A2 <= pawn_a && pawn_a < A8); + assert (A2 <= pawn_b && pawn_b < A8); + assert (A2 <= pawn_c && pawn_c < A8); + + if ((pawn_c & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */ + wk = flipWE (wk); + pawn_a = flipWE (pawn_a); + pawn_b = flipWE (pawn_b); + bk = flipWE (bk); + pawn_c = flipWE (pawn_c); + } + + i = flipWE( flipNS (pawn_a) ) - 8; + j = flipWE( flipNS (pawn_b) ) - 8; + k = map24_b (pawn_c); /* black pawn, so low indexes mean more advanced 0 == A2 */ + + pp48_slice = pp48_idx [i] [j]; + + if (IDX_is_empty(pp48_slice)) { + *out = NOINDEX; + return FALSE; + } + + assert (pp48_slice < MAX_PP48_INDEX ); + + *out = (index_t)k * (index_t)BLOCK_A + pp48_slice * (index_t)BLOCK_B + (index_t)wk * (index_t)BLOCK_C + (index_t)bk; + + return TRUE; +} + +static sq_t +map24_b (sq_t s) +{ + s -= 8; + return ((s&3)+s)>>1; +} + +static sq_t +unmap24_b (index_t i) +{ + return (sq_t) ((i&(4+8+16)) + i + 8); +} + +/********************** end KPP/KP ************************************/ + +/********************** KPPP/K ************************************/ + +static const sq_t itosq[48] = { + H7,G7,F7,E7, + H6,G6,F6,E6, + H5,G5,F5,E5, + H4,G4,F4,E4, + H3,G3,F3,E3, + H2,G2,F2,E2, + D7,C7,B7,A7, + D6,C6,B6,A6, + D5,C5,B5,A5, + D4,C4,B4,A4, + D3,C3,B3,A3, + D2,C2,B2,A2 +}; + +static bool_t test_kpppk (void); +static bool_t kpppk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out); +static void kpppk_indextopc (index_t i, SQUARE *pw, SQUARE *pb); + +static index_t +init_ppp48_idx (void) +/* modifies ppp48_idx[][], ppp48_sq_x[], ppp48_sq_y[], ppp48_sq_z[] */ +{ + enum {MAX_I = 48, MAX_J = 48, MAX_K = 48}; + SQUARE i, j, k; + index_t idx = 0; + SQUARE a, b, c; + int x, y, z; + + /* default is noindex */ + for (i = 0; i < MAX_I; i++) { + for (j = 0; j < MAX_J; j++) { + for (k = 0; k < MAX_K; k++) { + IDX_set_empty(ppp48_idx [i][j][k]); + } + } + } + + for (idx = 0; idx < MAX_PPP48_INDEX; idx++) { + ppp48_sq_x [idx] = (uint8_t)NOSQUARE; + ppp48_sq_y [idx] = (uint8_t)NOSQUARE; + ppp48_sq_z [idx] = (uint8_t)NOSQUARE; + } + + idx = 0; + for (x = 0; x < 48; x++) { + for (y = x+1; y < 48; y++) { + for (z = y+1; z < 48; z++) { + + a = itosq [x]; + b = itosq [y]; + c = itosq [z]; + + if (!in_queenside(b) || !in_queenside(c)) + continue; + + i = a - 8; + j = b - 8; + k = c - 8; + + if (IDX_is_empty(ppp48_idx [i] [j] [k])) { + + ppp48_idx [i][j][k] = idx; + ppp48_idx [i][k][j] = idx; + ppp48_idx [j][i][k] = idx; + ppp48_idx [j][k][i] = idx; + ppp48_idx [k][i][j] = idx; + ppp48_idx [k][j][i] = idx; + ppp48_sq_x [idx] = (uint8_t) i; assert (i < MAX_I); + ppp48_sq_y [idx] = (uint8_t) j; assert (j < MAX_J); + ppp48_sq_z [idx] = (uint8_t) k; assert (k < MAX_K); + idx++; + } + } + } + } + +/* assert (idx == MAX_PPP48_INDEX);*/ + return idx; +} + +static bool_t +test_kpppk (void) +{ + + enum {MAXPC = 16+1}; + char str[] = "kpppk"; + SQUARE a, b, c, d, e; + SQUARE pw[MAXPC], pb[MAXPC]; + SQUARE px[MAXPC], py[MAXPC]; + + index_t i, j; + bool_t err = FALSE; + + printf ("%8s ", str); + + for (a = 0; a < 64; a++) { + for (b = 0; b < 64; b++) { + for (c = 0; c < 64; c++) { + for (d = 0; d < 64; d++) { + for (e = 0; e < 64; e++) { + + if (c <= H1 || c >= A8) + continue; + if (b <= H1 || b >= A8) + continue; + if (d <= H1 || d >= A8) + continue; + + pw[0] = a; + pw[1] = b; + pw[2] = c; + pw[3] = d; + pw[4] = NOSQUARE; + + pb[0] = e; + pb[1] = NOSQUARE; + + if (kpppk_pctoindex (pw, pb, &i)) { + kpppk_indextopc (i, px, py); + kpppk_pctoindex (px, py, &j); + if (i != j) { + err = TRUE; + } + assert (i == j); + } + + } + } + } + } + + if ((a&1)==0) { + printf("."); + fflush(stdout); + } + } + + if (err) + printf ("> %s NOT passed\n", str); + else + printf ("> %s PASSED\n", str); + return !err; +} + + +static void +kpppk_indextopc (index_t i, SQUARE *pw, SQUARE *pb) +{ + /*---------------------------------------------------------* + inverse work to make sure that the following is valid + index = a * BLOCK_A + b * BLOCK_B + c * BLOCK_C + d; + *----------------------------------------------------------*/ + + enum {BLOCK_A = 64*64, BLOCK_B = 64}; + index_t a, b, c, r; + SQUARE m, n, o; + + r = i; + a = r / BLOCK_A; + r -= a * BLOCK_A; + b = r / BLOCK_B; + r -= b * BLOCK_B; + c = r; + + m = ppp48_sq_x [a]; + n = ppp48_sq_y [a]; + o = ppp48_sq_z [a]; + + + pw[0] = (SQUARE)b; + pw[1] = m + 8; + pw[2] = n + 8; + pw[3] = o + 8; + pw[4] = NOSQUARE; + + pb[0] = (SQUARE)c; + pb[1] = NOSQUARE; + + + assert (A2 <= pw[1] && pw[1] < A8); + assert (A2 <= pw[2] && pw[2] < A8); + assert (A2 <= pw[3] && pw[3] < A8); + assert (kpppk_pctoindex (pw, pb, &a) && a == i); + + return; +} + + +static bool_t +kpppk_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out) +{ + enum {BLOCK_A = 64*64, BLOCK_B = 64}; + index_t ppp48_slice; + + SQUARE wk = pw[0]; + SQUARE pawn_a = pw[1]; + SQUARE pawn_b = pw[2]; + SQUARE pawn_c = pw[3]; + + SQUARE bk = pb[0]; + + SQUARE i, j, k; + + assert (A2 <= pawn_a && pawn_a < A8); + assert (A2 <= pawn_b && pawn_b < A8); + assert (A2 <= pawn_c && pawn_c < A8); + + i = pawn_a - 8; + j = pawn_b - 8; + k = pawn_c - 8; + + ppp48_slice = ppp48_idx [i] [j] [k]; + + if (IDX_is_empty(ppp48_slice)) { + wk = flipWE (wk); + pawn_a = flipWE (pawn_a); + pawn_b = flipWE (pawn_b); + pawn_c = flipWE (pawn_c); + bk = flipWE (bk); + } + + i = pawn_a - 8; + j = pawn_b - 8; + k = pawn_c - 8; + + ppp48_slice = ppp48_idx [i] [j] [k]; + + if (IDX_is_empty(ppp48_slice)) { + *out = NOINDEX; + return FALSE; + } + + assert (ppp48_slice < MAX_PPP48_INDEX ); + + *out = (index_t)ppp48_slice * BLOCK_A + (index_t)wk * BLOCK_B + (index_t)bk; + + return TRUE; +} + + +/********************** end KPPP/K ************************************/ + + +static bool_t +kpkp_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out) +{ + enum {BLOCK_A = 64*64, BLOCK_B = 64}; + SQUARE pp_slice; + SQUARE anchor, loosen; + + SQUARE wk = pw[0]; + SQUARE bk = pb[0]; + SQUARE pawn_a = pw[1]; + SQUARE pawn_b = pb[1]; + + SQUARE m, n; + + #ifdef DEBUG + if (!(A2 <= pawn_a && pawn_a < A8)) { + printf ("\n\nsquare of pawn_a: %s\n", Square_str[pawn_a]); + printf(" wk %s\n p1 %s\n p2 %s\n bk %s\n" + , Square_str[wk] + , Square_str[pawn_a] + , Square_str[pawn_b] + , Square_str[bk] + ); + } + #endif + + assert (A2 <= pawn_a && pawn_a < A8); + assert (A2 <= pawn_b && pawn_b < A8); + assert (pw[2] == NOSQUARE && pb[2] == NOSQUARE); + + /*pp_putanchorfirst (pawn_a, pawn_b, &anchor, &loosen);*/ + anchor = pawn_a; + loosen = pawn_b; + + if ((anchor & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */ + anchor = flipWE (anchor); + loosen = flipWE (loosen); + wk = flipWE (wk); + bk = flipWE (bk); + } + + m = (SQUARE)wsq_to_pidx24 (anchor); + n = loosen - 8; + + pp_slice = m * 48 + n; + + if (IDX_is_empty(pp_slice)) { + *out = NOINDEX; + return FALSE; + } + + assert (pp_slice < MAX_PpINDEX ); + + *out = (index_t) (pp_slice * BLOCK_A + wk * BLOCK_B + bk); + + return TRUE; +} + + +static void +kpkp_indextopc (index_t i, SQUARE *pw, SQUARE *pb) +{ + /*---------------------------------------------------------* + inverse work to make sure that the following is valid + index = a * BLOCK_A + b * BLOCK_B + c; + *----------------------------------------------------------*/ + enum {B11100 = 7u << 2}; + enum {BLOCK_A = 64*64, BLOCK_B = 64}; + enum {block_m = 48}; + index_t a, b, c, r; + index_t m, n; + SQUARE sq_m, sq_n; + + r = i; + a = r / BLOCK_A; + r -= a * BLOCK_A; + b = r / BLOCK_B; + r -= b * BLOCK_B; + c = r; + + /* unpack a, which is pslice, into m and n */ + r = a; + m = r / block_m; + r -= m * block_m; + n = r ; + + sq_m = pidx24_to_wsq (m); + sq_n = (SQUARE)n + 8; + + pw[0] = (SQUARE)b; + pb[0] = (SQUARE)c; + pw[1] = sq_m; + pb[1] = sq_n; + pw[2] = NOSQUARE; + pb[2] = NOSQUARE; + + assert (A2 <= pw[1] && pw[1] < A8); + assert (A2 <= pb[1] && pb[1] < A8); + + return; +} + + +/****************************************************************************\ + * + * + * DEBUG ZONE + * + * + ****************************************************************************/ + +#if defined(DEBUG) +static void +print_pos (const sq_t *ws, const sq_t *bs, const pc_t *wp, const pc_t *bp) +{ + int i; + printf ("White: "); + for (i = 0; ws[i] != NOSQUARE; i++) { + printf ("%s%s ", P_str[wp[i]], Square_str[ws[i]]); + } + printf ("\nBlack: "); + for (i = 0; bs[i] != NOSQUARE; i++) { + printf ("%s%s ", P_str[bp[i]], Square_str[bs[i]]); + } + printf ("\n"); +} +#endif + +#if defined(DEBUG) || defined(FOLLOW_EGTB) +static void +output_state (unsigned stm, const SQUARE *wSQ, const SQUARE *bSQ, + const SQ_CONTENT *wPC, const SQ_CONTENT *bPC) +{ + int i; + assert (stm == WH || stm == BL); + + printf("\n%s to move\n", stm==WH?"White":"Black"); + printf("W: "); + for (i = 0; wSQ[i] != NOSQUARE; i++) { + printf("%s%s ", P_str[wPC[i]], Square_str[wSQ[i]]); + } + printf("\n"); + printf("B: "); + for (i = 0; bSQ[i] != NOSQUARE; i++) { + printf("%s%s ", P_str[bPC[i]], Square_str[bSQ[i]]); + } + printf("\n\n"); +} +#endif + +static void +list_index (void) +{ + enum {START_GTB = 0, END_GTB = (MAX_EGKEYS)}; + int i; + index_t accum = 0; + printf ("\nIndex for each GTB\n"); + printf ("%3s: %7s %7s %7s %7s\n" , "i", "TB", "RAM-slice", "RAM-max", "HD-cumulative"); + for (i = START_GTB; i < END_GTB; i++) { + index_t indiv_k = egkey[i].maxindex * (index_t)sizeof(dtm_t) * 2/1024; + accum += indiv_k; + printf ("%3d: %7s %8luk %8luk %8luM\n", i, egkey[i].str, (long unsigned)(indiv_k/egkey[i].slice_n), + (long unsigned)indiv_k, (long unsigned)accum/1024/2); + } + printf ("\n"); + return; +} + +/************************************************************************************************************** + + NEW_WDL + +**************************************************************************************************************/ + +/*---------------------------------------------------------------------*\ +| WDL CACHE Implementation ZONE +\*---------------------------------------------------------------------*/ + +/* +| WDL CACHE Statics +\*---------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------*/ +static unsigned int wdl_extract (unit_t *uarr, index_t x); +static wdl_block_t * wdl_point_block_to_replace (void); +static void wdl_movetotop (wdl_block_t *t); + +#if 0 +static bool_t wdl_cache_init (size_t cache_mem); +static void wdl_cache_flush (void); +static bool_t get_WDL (tbkey_t key, unsigned side, index_t idx, unsigned int *info_out, bool_t probe_hard_flag); +#endif + +static bool_t wdl_cache_is_on (void); +static void wdl_cache_reset_counters (void); +static void wdl_cache_done (void); + +static wdl_block_t * wdl_point_block_to_replace (void); +static bool_t get_WDL_from_cache (tbkey_t key, unsigned side, index_t idx, unsigned int *out); +static void wdl_movetotop (wdl_block_t *t); +static bool_t wdl_preload_cache (tbkey_t key, unsigned side, index_t idx); + +/*--------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------*\ +| WDL CACHE Maintainance +\*---------------------------------------------------------------------*/ + + +static size_t +wdl_cache_init (size_t cache_mem) +{ + unsigned int i; + wdl_block_t *p; + size_t entries_per_block; + size_t max_blocks; + size_t block_mem; + + if (WDL_CACHE_INITIALIZED) + wdl_cache_done(); + + entries_per_block = 16 * 1024; /* fixed, needed for the compression schemes */ + + WDL_units_per_block = entries_per_block / WDL_entries_per_unit; + block_mem = WDL_units_per_block * sizeof(unit_t); + + max_blocks = cache_mem / block_mem; + cache_mem = max_blocks * block_mem; + + + wdl_cache_reset_counters (); + + wdl_cache.entries_per_block = entries_per_block; + wdl_cache.max_blocks = max_blocks; + wdl_cache.cached = TRUE; + wdl_cache.top = NULL; + wdl_cache.bot = NULL; + wdl_cache.n = 0; + + if (0 == cache_mem || NULL == (wdl_cache.buffer = (unit_t *) malloc (cache_mem))) { + wdl_cache.cached = FALSE; + return 0; + } + + if (0 == max_blocks|| NULL == (wdl_cache.blocks = (wdl_block_t *) malloc (max_blocks * sizeof(wdl_block_t)))) { + wdl_cache.cached = FALSE; + free (wdl_cache.buffer); + return 0; + } + + for (i = 0; i < max_blocks; i++) { + p = &wdl_cache.blocks[i]; + p->key = -1; + p->side = gtbNOSIDE; + p->offset = gtbNOINDEX; + p->p_arr = wdl_cache.buffer + i * WDL_units_per_block; + p->prev = NULL; + p->next = NULL; + } + + WDL_CACHE_INITIALIZED = TRUE; + + return cache_mem; +} + + +static void +wdl_cache_done (void) +{ + assert(WDL_CACHE_INITIALIZED); + + wdl_cache.cached = FALSE; + wdl_cache.hard = 0; + wdl_cache.soft = 0; + wdl_cache.hardmisses = 0; + wdl_cache.hits = 0; + wdl_cache.softmisses = 0; + wdl_cache.comparisons = 0; + wdl_cache.max_blocks = 0; + wdl_cache.entries_per_block = 0; + + wdl_cache.top = NULL; + wdl_cache.bot = NULL; + wdl_cache.n = 0; + + if (wdl_cache.buffer != NULL) + free (wdl_cache.buffer); + wdl_cache.buffer = NULL; + + if (wdl_cache.blocks != NULL) + free (wdl_cache.blocks); + wdl_cache.blocks = NULL; + + WDL_CACHE_INITIALIZED = FALSE; + return; +} + + +static void +wdl_cache_flush (void) +{ + unsigned int i; + wdl_block_t *p; + size_t max_blocks = wdl_cache.max_blocks; + + wdl_cache.top = NULL; + wdl_cache.bot = NULL; + wdl_cache.n = 0; + + for (i = 0; i < max_blocks; i++) { + p = &wdl_cache.blocks[i]; + p->key = -1; + p->side = gtbNOSIDE; + p->offset = gtbNOINDEX; + p->p_arr = wdl_cache.buffer + i * WDL_units_per_block; + p->prev = NULL; + p->next = NULL; + } + + wdl_cache_reset_counters (); + + return; +} + + +static void +wdl_cache_reset_counters (void) +{ + wdl_cache.hard = 0; + wdl_cache.soft = 0; + wdl_cache.hardmisses = 0; + wdl_cache.hits = 0; + wdl_cache.softmisses = 0; + wdl_cache.comparisons = 0; + return; +} + + +static bool_t +wdl_cache_is_on (void) +{ + return wdl_cache.cached; +} + +/****************************************************************************\ +| Replacement +\****************************************************************************/ + +static wdl_block_t * +wdl_point_block_to_replace (void) +{ + wdl_block_t *p, *t, *s; + + assert (0 == wdl_cache.n || wdl_cache.top != NULL); + assert (0 == wdl_cache.n || wdl_cache.bot != NULL); + assert (0 == wdl_cache.n || wdl_cache.bot->prev == NULL); + assert (0 == wdl_cache.n || wdl_cache.top->next == NULL); + + if (wdl_cache.n > 0 && -1 == wdl_cache.top->key) { + + /* top blocks is unusable, should be the one to replace*/ + p = wdl_cache.top; + + } else + if (wdl_cache.n == 0) { + + p = &wdl_cache.blocks[wdl_cache.n++]; + wdl_cache.top = p; + wdl_cache.bot = p; + + p->prev = NULL; + p->next = NULL; + + } else + if (wdl_cache.n < wdl_cache.max_blocks) { /* add */ + + s = wdl_cache.top; + p = &wdl_cache.blocks[wdl_cache.n++]; + wdl_cache.top = p; + + s->next = p; + p->prev = s; + p->next = NULL; + + } else { /* replace*/ + + t = wdl_cache.bot; + s = wdl_cache.top; + wdl_cache.bot = t->next; + wdl_cache.top = t; + + s->next = t; + t->prev = s; + wdl_cache.top->next = NULL; + wdl_cache.bot->prev = NULL; + + p = t; + } + + /* make the information content unusable, it will be replaced */ + p->key = -1; + p->side = gtbNOSIDE; + p->offset = gtbNOINDEX; + + return p; +} + +/****************************************************************************\ +| +| NEW PROBING ZONE +| +\****************************************************************************/ + +static unsigned int wdl_extract (unit_t *uarr, index_t x); +static bool_t get_WDL_from_cache (tbkey_t key, unsigned side, index_t idx, unsigned int *info_out); +static unsigned dtm2WDL(dtm_t dtm); +static void wdl_movetotop (wdl_block_t *t); +static bool_t wdl_preload_cache (tbkey_t key, unsigned side, index_t idx); +static void dtm_block_2_wdl_block(dtm_block_t *g, wdl_block_t *w, size_t n); + +static bool_t +get_WDL (tbkey_t key, unsigned side, index_t idx, unsigned int *info_out, bool_t probe_hard_flag) +{ + dtm_t dtm; + bool_t found; + + found = get_WDL_from_cache (key, side, idx, info_out); + + if (found) { + wdl_cache.hits++; + } else { + /* may probe soft */ + found = get_dtm (key, side, idx, &dtm, probe_hard_flag); + if (found) { + *info_out = dtm2WDL(dtm); + /* move cache info from dtm_cache to WDL_cache */ + if (wdl_cache_is_on()) + wdl_preload_cache (key, side, idx); + } + } + + if (probe_hard_flag) { + wdl_cache.hard++; + if (!found) { + wdl_cache.hardmisses++; + } + } else { + wdl_cache.soft++; + if (!found) { + wdl_cache.softmisses++; + } + } + + return found; +} + +static bool_t +get_WDL_from_cache (tbkey_t key, unsigned side, index_t idx, unsigned int *out) +{ + index_t offset; + index_t remainder; + wdl_block_t *p; + wdl_block_t *ret; + + if (!wdl_cache_is_on()) + return FALSE; + + split_index (wdl_cache.entries_per_block, idx, &offset, &remainder); + + ret = NULL; + for (p = wdl_cache.top; p != NULL; p = p->prev) { + + wdl_cache.comparisons++; + + if (key == p->key && side == p->side && offset == p->offset) { + ret = p; + break; + } + } + + if (ret != NULL) { + *out = wdl_extract (ret->p_arr, remainder); + wdl_movetotop(ret); + } + + FOLLOW_LU("get_wdl_from_cache ok?",(ret != NULL)) + + return ret != NULL; +} + +static unsigned int +wdl_extract (unit_t *uarr, index_t x) +{ + index_t width = 2; + index_t nu = x/WDL_entries_per_unit; + index_t y = x - (nu * WDL_entries_per_unit); + return (uarr[nu] >> (y*width)) & WDL_entry_mask; +} + +static void +wdl_movetotop (wdl_block_t *t) +{ + wdl_block_t *s, *nx, *pv; + + assert (t != NULL); + + if (t->next == NULL) /* at the top already */ + return; + + /* detach */ + pv = t->prev; + nx = t->next; + + if (pv == NULL) /* at the bottom */ + wdl_cache.bot = nx; + else + pv->next = nx; + + if (nx == NULL) /* at the top */ + wdl_cache.top = pv; + else + nx->prev = pv; + + /* relocate */ + s = wdl_cache.top; + assert (s != NULL); + if (s == NULL) + wdl_cache.bot = t; + else + s->next = t; + + t->next = NULL; + t->prev = s; + wdl_cache.top = t; + + return; +} + +/****************************************************************************************************/ + +static bool_t +wdl_preload_cache (tbkey_t key, unsigned side, index_t idx) +/* output to the least used block of the cache */ +{ + dtm_block_t *dtm_block; + wdl_block_t *to_modify; + bool_t ok; + + FOLLOW_label("wdl preload_cache starts") + + if (idx >= egkey[key].maxindex) { + FOLLOW_LULU("Wrong index", __LINE__, idx) + return FALSE; + } + + /* find fresh block in dtm cache */ + dtm_block = dtm_cache_pointblock (key, side, idx); + + /* find aged blocked in wdl cache */ + to_modify = wdl_point_block_to_replace (); + + ok = !(NULL == dtm_block || NULL == to_modify); + + if (!ok) + return FALSE; + + /* transform and move a block */ + dtm_block_2_wdl_block(dtm_block, to_modify, dtm_cache.entries_per_block); + + if (ok) { + index_t offset; + index_t remainder; + split_index (wdl_cache.entries_per_block, idx, &offset, &remainder); + + to_modify->key = key; + to_modify->side = side; + to_modify->offset = offset; + } else { + /* make it unusable */ + to_modify->key = -1; + to_modify->side = gtbNOSIDE; + to_modify->offset = gtbNOINDEX; + } + + FOLLOW_LU("wdl preload_cache?", ok) + + return ok; +} + +/****************************************************************************************************/ + +static void +dtm_block_2_wdl_block(dtm_block_t *g, wdl_block_t *w, size_t n) +{ + int width = 2; + int shifting; + size_t i; + int j; + unsigned int x ,y; + dtm_t *s = g->p_arr; + unit_t *d = w->p_arr; + + for (i = 0, y = 0; i < n; i++) { + j = i & 3; /* modulo WDL_entries_per_unit */ + x = dtm2WDL(s[i]); + shifting = j * width; + y |= (x << shifting); + + if (j == 3) { + d[i/WDL_entries_per_unit] = (unit_t) y; + y = 0; + } + } + + if (0 != (n & 3)) { /* not multiple of 4 */ + d[(n-1)/WDL_entries_per_unit] = (unit_t) y; /* save the rest */ + y = 0; + } + + return; +} + +static unsigned +dtm2WDL(dtm_t dtm) +{ + return (unsigned) dtm & 3; +} + + +/**************************/ +#ifdef WDL_PROBE + +static unsigned int inv_wdl(unsigned w); +static bool_t egtb_get_wdl (tbkey_t k, unsigned stm, const SQUARE *wS, const SQUARE *bS, bool_t probe_hard_flag, unsigned int *wdl); + +static bool_t +tb_probe_wdl + (unsigned stm, + const SQUARE *inp_wSQ, + const SQUARE *inp_bSQ, + const SQ_CONTENT *inp_wPC, + const SQ_CONTENT *inp_bPC, + bool_t probingtype, + /*@out@*/ unsigned *res) +{ + tbkey_t id = -1; + unsigned int wdl = iUNKNOWN; + + SQUARE storage_ws [MAX_LISTSIZE], storage_bs [MAX_LISTSIZE]; + SQ_CONTENT storage_wp [MAX_LISTSIZE], storage_bp [MAX_LISTSIZE]; + + SQUARE *ws = storage_ws; + SQUARE *bs = storage_bs; + SQ_CONTENT *wp = storage_wp; + SQ_CONTENT *bp = storage_bp; + SQUARE tmp_ws [MAX_LISTSIZE], tmp_bs [MAX_LISTSIZE]; + SQ_CONTENT tmp_wp [MAX_LISTSIZE], tmp_bp [MAX_LISTSIZE]; + + SQUARE *temps; + bool_t straight = FALSE; + + bool_t okcall = TRUE; + unsigned ply_; + unsigned *ply = &ply_; + + /************************************/ + + assert (stm == WH || stm == BL); + + /* VALID ONLY FOR KK!! */ + if (inp_wPC[1] == NOPIECE && inp_bPC[1] == NOPIECE) { + index_t dummy_i; + bool_t b = kxk_pctoindex (inp_wSQ, inp_bSQ, &dummy_i); + *res = b? iDRAW: iFORBID; + *ply = 0; + return TRUE; + } + + /* copy input */ + list_pc_copy (inp_wPC, wp); + list_pc_copy (inp_bPC, bp); + list_sq_copy (inp_wSQ, ws); + list_sq_copy (inp_bSQ, bs); + + sortlists (ws, wp); + sortlists (bs, bp); + + FOLLOW_label("EGTB_PROBE") + + if (egtb_get_id (wp, bp, &id)) { + FOLLOW_LU("got ID",id) + straight = TRUE; + } else if (egtb_get_id (bp, wp, &id)) { + FOLLOW_LU("rev ID",id) + straight = FALSE; + list_sq_flipNS (ws); + list_sq_flipNS (bs); + temps = ws; + ws = bs; + bs = temps; + stm = Opp(stm); + /* no enpassant in this fuction, so no adjustment */ + {SQ_CONTENT *tempp = wp; wp = bp; bp = tempp;} /* added */ + } else { + #if defined(DEBUG) + printf("did not get id...\n"); + output_state (stm, ws, bs, wp, bp); + #endif + unpackdist (iFORBID, res, ply); + return FALSE; + } + + /* store position... */ + list_pc_copy (wp, tmp_wp); + list_pc_copy (bp, tmp_bp); + list_sq_copy (ws, tmp_ws); + list_sq_copy (bs, tmp_bs); + + /* x will be stm and y will be stw */ +/* + if (stm == WH) { + xs = ws; + xp = wp; + ys = bs; + yp = bp; + } else { + xs = bs; + xp = bp; + ys = ws; + yp = wp; + } +*/ + okcall = egtb_get_wdl (id, stm, ws, bs, probingtype, &wdl); + + FOLLOW_LU("dtmok?",okcall) + FOLLOW_DTM("wdl", wdl) + + if (okcall) { + + /*assert(epsq == NOSQUARE); */ + + if (straight) { + *res = wdl; + } else { + *res = inv_wdl (wdl); + } + } else { + unpackdist (iFORBID, res, ply); + } + + return okcall; +} + +static unsigned int +inv_wdl(unsigned w) +{ + unsigned r = tb_UNKNOWN; + switch (w) { + case tb_DRAW: r = tb_DRAW; break; + case tb_WMATE: r = tb_BMATE; break; + case tb_BMATE: r = tb_WMATE; break; + case tb_FORBID: r = tb_FORBID; break; + case tb_UNKNOWN: r = tb_UNKNOWN; break; + default: r = tb_UNKNOWN; break; + } + return r; +} + +static bool_t +egtb_get_wdl (tbkey_t k, unsigned stm, const SQUARE *wS, const SQUARE *bS, bool_t probe_hard_flag, unsigned int *wdl) +{ + bool_t idxavail; + index_t idx; + dtm_t *tab[2]; + bool_t (*pc2idx) (const SQUARE *, const SQUARE *, index_t *); + + FOLLOW_label("egtb_get_wdl --> starts") + + if (egkey[k].status == STATUS_MALLOC || egkey[k].status == STATUS_STATICRAM) { + + tab[WH] = egkey[k].egt_w; + tab[BL] = egkey[k].egt_b; + pc2idx = egkey[k].pctoi; + + idxavail = pc2idx (wS, bS, &idx); + + FOLLOW_LU("indexavail (RAM)",idxavail) + + if (idxavail) { + *wdl = dtm2WDL(tab[stm][idx]); + } else { + *wdl = dtm2WDL(iFORBID); + } + + return FALSE; + + } else if (egkey[k].status == STATUS_ABSENT) { + + pc2idx = egkey[k].pctoi; + idxavail = pc2idx (wS, bS, &idx); + + FOLLOW_LU("indexavail (HD)",idxavail) + + if (idxavail) { + bool_t success; + + /* + | LOCK + *-------------------------------*/ + mythread_mutex_lock (&Egtb_lock); + + success = get_WDL (k, stm, idx, wdl, probe_hard_flag); + FOLLOW_LU("get_wld (succ)",success) + FOLLOW_LU("get_wld (wdl )",*wdl) + + /* this may not be needed */ + if (!success) { + dtm_t dtm; + unsigned res, ply; + if (probe_hard_flag && Uncompressed) { + assert(Uncompressed); + success = egtb_filepeek (k, stm, idx, &dtm); + unpackdist (dtm, &res, &ply); + *wdl = res; + } + else + success = FALSE; + } + + mythread_mutex_unlock (&Egtb_lock); + /*------------------------------*\ + | UNLOCK + */ + + if (success) { + return TRUE; + } else { + if (probe_hard_flag) /* after probing hard and failing, no chance to succeed later */ + egkey[k].status = STATUS_REJECT; + *wdl = dtm2WDL(iUNKNOWN); + return FALSE; + } + + } else { + *wdl = dtm2WDL(iFORBID); + return TRUE; + } + } else if (egkey[k].status == STATUS_REJECT) { + FOLLOW_label("STATUS_REJECT") + *wdl = dtm2WDL(iFORBID); + return FALSE; + } else { + FOLLOW_label("STATUS_WRONG!") + assert(0); + *wdl = dtm2WDL(iFORBID); + return FALSE; + } + +} +#endif + + + diff --git a/DroidFish/jni/gtb/gtb-probe.h b/DroidFish/jni/gtb/gtb-probe.h new file mode 100644 index 0000000..cf98470 --- /dev/null +++ b/DroidFish/jni/gtb/gtb-probe.h @@ -0,0 +1,234 @@ +/* +This Software is distributed with the following X11 License, +sometimes also known as MIT license. + +Copyright (c) 2010 Miguel A. Ballicora + + 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. +*/ + +#if !defined(H_GTBPROBE) +#define H_GTBPROBE +#ifdef __cplusplus +extern "C" { +#endif +/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ + +#include + +#define tb_MAXPATHLEN 1024 + +/*----------------------------------*\ +| CONSTANTS +\*----------------------------------*/ + +enum TB_mask_values { tb_RESMASK = 3, tb_INFOMASK = 7, tb_PLYSHIFT = 3 }; + +enum TB_return_values { + tb_DRAW = 0, + tb_WMATE = 1, + tb_BMATE = 2, + tb_FORBID = 3, + tb_UNKNOWN = 7 +}; + +enum TB_pieces { + tb_NOPIECE, tb_PAWN, tb_KNIGHT, tb_BISHOP, tb_ROOK, tb_QUEEN, tb_KING +}; + +enum TB_sides { + tb_WHITE_TO_MOVE, tb_BLACK_TO_MOVE +}; + +enum TB_squares { + tb_A1, tb_B1, tb_C1, tb_D1, tb_E1, tb_F1, tb_G1, tb_H1, + tb_A2, tb_B2, tb_C2, tb_D2, tb_E2, tb_F2, tb_G2, tb_H2, + tb_A3, tb_B3, tb_C3, tb_D3, tb_E3, tb_F3, tb_G3, tb_H3, + tb_A4, tb_B4, tb_C4, tb_D4, tb_E4, tb_F4, tb_G4, tb_H4, + tb_A5, tb_B5, tb_C5, tb_D5, tb_E5, tb_F5, tb_G5, tb_H5, + tb_A6, tb_B6, tb_C6, tb_D6, tb_E6, tb_F6, tb_G6, tb_H6, + tb_A7, tb_B7, tb_C7, tb_D7, tb_E7, tb_F7, tb_G7, tb_H7, + tb_A8, tb_B8, tb_C8, tb_D8, tb_E8, tb_F8, tb_G8, tb_H8, + tb_NOSQUARE +}; + +enum TB_castling { + tb_NOCASTLE = 0, + tb_WOO = 8, + tb_WOOO = 4, + tb_BOO = 2, + tb_BOOO = 1 +}; + +enum TB_compression_scheme { + tb_UNCOMPRESSED, tb_CP1, tb_CP2, tb_CP3, tb_CP4 +}; + +/*----------------------------------*\ +| FUNCTIONS +\*----------------------------------*/ + +extern char * tb_init (int verbosity, int compression_scheme, const char **paths); + +extern char * tb_restart(int verbosity, int compression_scheme, const char **paths); + +extern void tb_done (void); + +extern int /*bool*/ tb_probe_hard + (unsigned stm, + unsigned epsq, + unsigned castles, + const unsigned *inp_wSQ, + const unsigned *inp_bSQ, + const unsigned char *inp_wPC, + const unsigned char *inp_bPC, + /*@out@*/ unsigned *tbinfo, + /*@out@*/ unsigned *plies); + +extern int /*bool*/ tb_probe_soft + (unsigned stm, + unsigned epsq, + unsigned castles, + const unsigned *inp_wSQ, + const unsigned *inp_bSQ, + const unsigned char *inp_wPC, + const unsigned char *inp_bPC, + /*@out@*/ unsigned *tbinfo, + /*@out@*/ unsigned *plies); + +extern int /*bool*/ tb_probe_WDL_hard + (unsigned stm, + unsigned epsq, + unsigned castles, + const unsigned *inp_wSQ, + const unsigned *inp_bSQ, + const unsigned char *inp_wPC, + const unsigned char *inp_bPC, + /*@out@*/ unsigned *tbinfo); + +extern int /*bool*/ tb_probe_WDL_soft + (unsigned stm, + unsigned epsq, + unsigned castles, + const unsigned *inp_wSQ, + const unsigned *inp_bSQ, + const unsigned char *inp_wPC, + const unsigned char *inp_bPC, + /*@out@*/ unsigned *tbinfo); + +extern int /*bool*/ tb_is_initialized (void); + +/* +| tb_availability() returns 0 if no TBs available +| Otherwise, the following bits are turned 'on' if... +| ---------------------------------- +| bit: meaning +| ---------------------------------- +| 0: at least one 3-pc TB is present +| 1: 3-pc TBs are complete +| 2: at least one 4-pc TB is present +| 3: 4-pc TBs are complete +| 4: at least one 5-pc TB is present +| 5: 5-pc TBs are complete +| 6: at least one 6-pc TB is present +| 7: 6-pc TBs are complete +| Example: if 63 is returned, it means all 3-4-5-pc TBs are present +| Bits 6 and 7 will be always off, of course, until 6-piece TBs +| are supported. +*/ + +extern unsigned int tb_availability(void); + +/* +| tb_indexmemory ()returns +| how much memory has been allocated for indexes +*/ + +extern size_t tb_indexmemory (void); + +/*----------------------------------*\ +| cache +\*----------------------------------*/ + +extern int /*bool*/ tbcache_init (size_t cache_mem, int wdl_fraction); +extern int /*bool*/ tbcache_restart (size_t cache_mem, int wdl_fraction); +extern void tbcache_done (void); +extern int /*bool*/ tbcache_is_on (void); +extern void tbcache_flush (void); + +/*----------------------------------*\ +| STATS +\*----------------------------------*/ + +/* +| For maximum portability, some stats are provided +| in two 32 bits integers rather than a single 64 bit number. +| For intance, prob_hard_hits[0] contains the less significant 32 bits +| (0 to 31), and prob_hard_hits[1] the most significant ones (32 to 63). +| The 64-bit number can be recreated like this: +| uint64_t x; +| x = (uint64_t)probe_hard_hits[0]|((uint64_t)probe_hard_hits[1]<<32); +| The user has the responsibility to combine the numbers and use the +| proper 64 bit integers. +*/ + +struct TB_STATS { + long unsigned int wdl_easy_hits [2]; /* hits that were found in own wdl cache */ + long unsigned int wdl_hard_prob [2]; /* hard probes to the wdl cache: if fail, they will go to HD */ + long unsigned int wdl_soft_prob [2]; /* soft probes to the wdl cache: if fail, they won't go to HD */ + size_t wdl_cachesize ; /* size allocated for wdl cache */ + double wdl_occupancy ; /* % of slots filled in wdl cache */ + + long unsigned int dtm_easy_hits [2]; /* hits that were found in own dtm cache */ + long unsigned int dtm_hard_prob [2]; /* hard probes to the dtm cache: if fail, they will go to HD */ + long unsigned int dtm_soft_prob [2]; /* soft probes to the dtm cache: if fail, they won't go to HD */ + size_t dtm_cachesize ; /* size allocated for dtm cache */ + double dtm_occupancy ; /* % of slots filled in dtm cache */ + + long unsigned int total_hits [2]; /* succesful probes */ + long unsigned int memory_hits [2]; /* succesful probes to memory */ + long unsigned int drive_hits [2]; /* succesful probes to the Hard drive */ + long unsigned int drive_miss [2]; /* failing probes to the Hard drive */ + long unsigned int bytes_read [2]; /* bytes read from Hard drive */ + long unsigned int files_opened ; /* number of files newly opened */ + double memory_efficiency ; /* % hits from memory over total hits */ +}; + +extern void tbstats_reset (void); +extern void tbstats_get (struct TB_STATS *stats); + + +/*----------------------------------*\ +| PATH MANAGEMENT +\*----------------------------------*/ + +extern const char ** tbpaths_init (void); +extern const char ** tbpaths_add (const char **ps, const char *newpath); +extern const char ** tbpaths_done (const char **ps); + +extern const char * tbpaths_getmain (void); + +/*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ +#ifdef __cplusplus +} +#endif +#endif diff --git a/DroidFish/jni/gtb/gtb-types.h b/DroidFish/jni/gtb/gtb-types.h new file mode 100644 index 0000000..01cc69d --- /dev/null +++ b/DroidFish/jni/gtb/gtb-types.h @@ -0,0 +1,25 @@ +#if !defined(H_GTBTYPES) +#define H_GTBTYPES +#ifdef __cplusplus +extern "C" { +#endif +/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ +#include "sysport.h" + +typedef uint32_t sq_t; +typedef uint8_t pc_t; +typedef uint32_t mv_t; +typedef int32_t tbkey_t; +typedef uint16_t dtm_t; +typedef int32_t index_t; + +#define MAXINDEX_T ((1ul << 31)-1ul) + +/*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ +#ifdef __cplusplus +} +#endif +#endif + + + diff --git a/DroidFish/jni/gtb/license.txt b/DroidFish/jni/gtb/license.txt new file mode 100644 index 0000000..57b5fd8 --- /dev/null +++ b/DroidFish/jni/gtb/license.txt @@ -0,0 +1,100 @@ + Gaviota Tablebases Probing Code API + Copyright (c) 2010 Miguel A. Ballicora +----------------------------------------------------------------------------- + + LICENSES + +----------------------------------------------------------------------------- +This Software is distributed with the following X11 License, +sometimes also known as MIT license. + +Copyright (c) 2010 Miguel A. Ballicora + + 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. + +----------------------------------------------------------------------------- +This Software also contain the following compression libraries: +----------------------------------------------------------------------------- +LZMA: +2009-02-02 : Igor Pavlov : Public domain +----------------------------------------------------------------------------- +ZLIB License + +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.3, July 18th, 2005 + + Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ +---------------------------------------------------------------------------- +LZF: + +Copyright (c) 2000-2007 Marc Alexander Lehmann + +Redistribution and use in source and binary forms, with or without modifica- +tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. 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 AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- +CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- +CIAL, 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 OTH- +ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +OF THE POSSIBILITY OF SUCH DAMAGE. + +Alternatively, the following files carry an additional notice that +explicitly allows relicensing under the GPLv2: lzf.c lzf.h lzfP.h lzf_c.c +lzf_d.c +----------------------------------------------------------------------------- diff --git a/DroidFish/jni/gtb/progname.h b/DroidFish/jni/gtb/progname.h new file mode 100644 index 0000000..d5f1734 --- /dev/null +++ b/DroidFish/jni/gtb/progname.h @@ -0,0 +1 @@ +#define PROGRAM_NAME "tbprobe" diff --git a/DroidFish/jni/gtb/readme.txt b/DroidFish/jni/gtb/readme.txt new file mode 100644 index 0000000..9029ec3 --- /dev/null +++ b/DroidFish/jni/gtb/readme.txt @@ -0,0 +1,147 @@ + Gaviota Tablebases Probing Code API + Copyright (c) 2010-2011 Miguel A. Ballicora +----------------------------------------------------------------------------- + +This software provides C code to probe the Gaviota Endgame Tablebases. +It is released under then X11 ("MIT") license (see license.txt). + +This API (Application Programming Interface) is designed to be as portable +as possible. Functions could be called from Linux or Windows. +Most likely it will work in other operating systems but that has not been +tested. This API is a beta version and as such, it is not guaranteed any +type of backward compatibility or to remain untouched, at least until +version 1.0 is released. + +A very small set of tablebase files is included in this distribution +for testing purposes (only 3 pieces). They are compressed with four +different compression schemes. For a more complete set, please download +Gaviota from + +http://sites.google.com/site/gaviotachessengine/ + +and generate the 4 and 5 piece tablebases. Instructions how to generate +and compressed them are in the website. More information can always be found: + +http://sites.google.com/site/gaviotachessengine/Home/endgame-tablebases-1 + +Alternatively, already compressed tablebase files (ready to go!) can be +downloaded from + +http://www.olympuschess.com/egtb/gaviota/ (Many thanks to Josh Shriver) + +"tbprobe" is distributed here as a tablebase probing example. The current API +is relatively "low level" to optimize performance. We hope the small program +tbprobe is self explanatory. A thorough and detailed documentation may be +released later. However, it seems that everybody who attempted to implement +this probing code was successful relatively easy. + +We plan to support an interface with a FEN notation; thus, it is expected +that some other functions maybe added to this API. + +Four different types of compression are included. It is possible that in the +future some other compression schemes could be provided, but only if they +represent a serious improvement in speed or memory size. To maximize +backward compatibility between versions of programs and TBs, it is strongly +recommended that engine developers always support at least scheme 4 (tb_CP4), +which is considered the default at this point. For that reason, it is +suggested that testers always have a set of TBs compressed with scheme 4. + +This API is designed to be multithreading friendly. Regions where different +threads could access data from this API were protected with a mutex to avoid +problems. + +-------------------------- How to use this API ------------------------------ + +To include this code in any engine or GUI, the following files should be +compiled and linked: + +gtb-probe.c +gtb-dec.c +gtb-att.c +sysport/sysport.c +compression/wrap.c +compression/huffman/hzip.c +compression/liblzf/lzf_c.c +compression/liblzf/lzf_d.c +compression/zlib/zcompress.c +compression/zlib/uncompr.c +compression/zlib/inflate.c +compression/zlib/deflate.c +compression/zlib/adler32.c +compression/zlib/crc32.c +compression/zlib/infback.c +compression/zlib/inffast.c +compression/zlib/inftrees.c +compression/zlib/trees.c +compression/zlib/zutil.c +compression/lzma/LzmaEnc.c +compression/lzma/LzmaDec.c +compression/lzma/Alloc.c +compression/lzma/LzFind.c +compression/lzma/Lzma86Enc.c +compression/lzma/Lzma86Dec.c +compression/lzma/Bra86.c + +The following files will be "included" +gtb-probe.h +gtb-dec.h +gtb-att.h +gtb-types.h + +plus all the *.h files in the folders, so set the proper -I flags: +sysport/ +compression/ +compression/huffman/ +compression/liblzf/ +compression/zlib/ +compression/lzma/ + +The following libraries should be linked in Linux +-lpthread +-lm + +In Windows, the appropriate MT (multithreaded library should be linked too) + +These switches should be set in the compiler +-D NDEBUG +-D Z_PREFIX + +The first one removes the assert code, and the second +one makes sure that there is no collision between some names in the +zlib library and names in other compression libraries. + +-------------------------- COMPILATION EXAMPLE ------------------------------ + +The file compile.sh is an example of how tbprobe can be +compiled in Linux using gcc. + +Rakefile.rb is the ruby version of Makefile. You have to install 'rake' +to execute it. This is what I use but you don't have to. It is provided +out of laziness. I should probably remove it. + +------------------ COMPILING A STATIC LIBRARY (optional) -------------------- + +Aaron Becker wrote a Makefile to compile a static library --> libgtb.a +I just applied this modification from his fork. +For now, this for Linux only. Type 'make' to compile it. +Some people may find this approach more convenient since the library +has to be compiled only once. Of course, this library needs to be included +at linking time, when you compile your own program + +---------------------------- For UCI Authors -------------------------------- + +Generally, UCI (Universal Chess Interface) GUIs use standard labels for +Tablebase paths and cache sizes. For instance, NalimovPath and NalimovCache +are used for the Nalimov tablebases. Therefore, engine authors are strongly +encouraged (Please!) to follow a common standard to simplify the life of GUI +developers and users. For that reason, it is suggested to implement as +parameters: GaviotaTbPath and GaviotaTbCache in their communication with a +UCI graphical user interface. + +----------------------------------------------------------------------------- + +Good luck with the tablebases! + +Miguel + +***************************************************************************** diff --git a/DroidFish/jni/gtb/sysport/sysport.c b/DroidFish/jni/gtb/sysport/sysport.c new file mode 100644 index 0000000..af44f17 --- /dev/null +++ b/DroidFish/jni/gtb/sysport/sysport.c @@ -0,0 +1,274 @@ +#include +#include +#include +#include "sysport.h" + +/**** CLOCK *************************************************************************/ + +#if defined(USECLOCK) + + #include + extern myclock_t myclock(void) {return (myclock_t)clock();} + extern myclock_t ticks_per_sec (void) {return CLOCKS_PER_SEC;} + +#elif defined(USEWINCLOCK) + + #define WIN32_LEAN_AND_MEAN + #include + extern myclock_t myclock(void) {return (myclock_t)GetTickCount();} + extern myclock_t ticks_per_sec (void) {return 1000;} + + +#elif defined(USELINCLOCK) + + #include + extern myclock_t myclock(void) + { + struct timeval tv; + gettimeofday(&tv, NULL); + return (myclock_t)tv.tv_sec * 1000 + (myclock_t)tv.tv_usec/1000; + } + extern myclock_t ticks_per_sec (void) {return 1000;} + +#else + + #error No Clock specified in compilation + +#endif + +/**** PATH NAMES *************************************************************************/ + +#if defined(GCCLINUX) + extern int isfoldersep (int x) { return x == '/';} +#elif defined(MVSC) + extern int isfoldersep (int x) { return x == '\\' || x == ':';} +#else + extern int isfoldersep (int x) { return x == '/' || x == '\\' || x == ':';} +#endif + +/**** Maximum Files Open *****************************************************************/ + +#if defined(GCCLINUX) + #include + #if 0 + struct rlimit { + rlim_t rlim_cur; /* Soft limit */ + rlim_t rlim_max; /* Hard limit (ceiling for rlim_cur) */ + }; + #endif + extern int mysys_fopen_max (void) + { + int ok; + struct rlimit rl; + ok = 0 == getrlimit(RLIMIT_NOFILE, &rl); + if (ok) + return (int)rl.rlim_cur; + else + return FOPEN_MAX; + } +#elif defined(MVSC) + extern int mysys_fopen_max (void) { return FOPEN_MAX;} +#else + extern int mysys_fopen_max (void) { return FOPEN_MAX;} +#endif + + +#if defined(MULTI_THREADED_INTERFACE) +/**** THREADS ****************************************************************************/ + +/* +| +| POSIX +| +\*-------------------------*/ +#if defined (POSIX_THREADS) + +#include + +extern int /* boolean */ +mythread_create (/*@out@*/ mythread_t *thread, routine_t start_routine, void *arg, /*@out@*/ int *ret_error) +{ + const pthread_attr_t *attr = NULL; /* default attributes */ + int ret; + ret = pthread_create (thread, attr, start_routine, arg); + *ret_error = ret; + return 0 == ret; +} + +extern int /* boolean */ +mythread_join (mythread_t thread) +{ + void *p; /* value return from pthread_exit, not used */ + int ret = pthread_join (thread, &p); + return 0 == ret; +} + +extern void +mythread_exit (void) +{ + pthread_exit (NULL); +} + + +extern const char * +mythread_create_error (int err) +{ + const char *s; + switch (err) { + case 0 : s = "Success"; break; + case EAGAIN: s = "EAGAIN" ; break; + case EINVAL: s = "EINVAL" ; break; + case EPERM : s = "EPERM" ; break; + default : s = "Unknown error"; break; + } + return s; +} + +extern void mythread_mutex_init (mythread_mutex_t *m) { pthread_mutex_init (m,NULL);} +extern void mythread_mutex_destroy (mythread_mutex_t *m) { pthread_mutex_destroy(m) ;} +extern void mythread_mutex_lock (mythread_mutex_t *m) { pthread_mutex_lock (m) ;} +extern void mythread_mutex_unlock (mythread_mutex_t *m) { pthread_mutex_unlock (m) ;} + +#ifdef SPINLOCKS +extern void mythread_spinx_init (mythread_spinx_t *m) { pthread_spin_init (m,0);} /**/ +extern void mythread_spinx_destroy (mythread_spinx_t *m) { pthread_spin_destroy(m) ;} /**/ +extern void mythread_spinx_lock (mythread_spinx_t *m) { pthread_spin_lock (m) ;} /**/ +extern void mythread_spinx_unlock (mythread_spinx_t *m) { pthread_spin_unlock (m) ;} /**/ +#else +extern void mythread_spinx_init (mythread_spinx_t *m) { pthread_mutex_init (m,NULL);} /**/ +extern void mythread_spinx_destroy (mythread_spinx_t *m) { pthread_mutex_destroy(m) ;} /**/ +extern void mythread_spinx_lock (mythread_spinx_t *m) { pthread_mutex_lock (m) ;} /**/ +extern void mythread_spinx_unlock (mythread_spinx_t *m) { pthread_mutex_unlock (m) ;} /**/ +#endif + +/* semaphores */ +extern int /* boolean */ +mysem_init (mysem_t *sem, unsigned int value) + { return -1 != sem_init (sem, 0 /*not shared with processes*/, value);} + +extern int /* boolean */ +mysem_wait (mysem_t *sem) + { return 0 == sem_wait (sem);} + +extern int /* boolean */ +mysem_post (mysem_t *sem) + { return 0 == sem_post (sem);} + +extern int /* boolean */ +mysem_destroy (mysem_t *sem) + { return 0 == sem_destroy (sem);} + +/* +| +| NT_THREADS +| +\*-------------------------*/ +#elif defined(NT_THREADS) + +#define WIN32_LEAN_AND_MEAN +#include +#include + +extern int /* boolean */ +mythread_create (/*@out@*/ mythread_t *thread, routine_t start_routine, void *arg, /*@out@*/ int *ret_error) +{ + static unsigned int thread_id; + mythread_t t; + int /* boolean */ is_ok; + + t = (mythread_t) _beginthreadex (NULL, 0, start_routine, arg, 0, &thread_id ); + is_ok = (t != 0); + *thread = t; + *ret_error = is_ok? 0: errno; + return is_ok; +} + +extern int /* boolean */ +mythread_join (mythread_t thread) +{ + unsigned long int ret; + ret = WaitForSingleObject (thread, INFINITE); + CloseHandle(thread); + return ret != WAIT_FAILED; +} + +extern void +mythread_exit (void) +{ + return; +} + +extern const char * +mythread_create_error (int err) +{ + const char *s; + switch (err) { + case 0 : s = "Success"; break; + case EAGAIN: s = "EAGAIN" ; break; + case EINVAL: s = "EINVAL" ; break; + case EPERM : s = "EPERM" ; break; + default : s = "Unknown error"; break; + } + return s; +} + +extern void mythread_mutex_init (mythread_mutex_t *m) { *m = CreateMutex(0, FALSE, 0) ;} +extern void mythread_mutex_destroy (mythread_mutex_t *m) { CloseHandle(*m) ;} +extern void mythread_mutex_lock (mythread_mutex_t *m) { WaitForSingleObject(*m, INFINITE) ;} +extern void mythread_mutex_unlock (mythread_mutex_t *m) { ReleaseMutex(*m) ;} + +extern void mythread_spinx_init (mythread_spinx_t *m) { InitializeCriticalSection(m) ;} /**/ +extern void mythread_spinx_destroy (mythread_spinx_t *m) { DeleteCriticalSection(m) ;} /**/ +extern void mythread_spinx_lock (mythread_spinx_t *m) { EnterCriticalSection (m) ;} /**/ +extern void mythread_spinx_unlock (mythread_spinx_t *m) { LeaveCriticalSection (m) ;} /**/ + +/* semaphores */ +extern int /* boolean */ +mysem_init (mysem_t *sem, unsigned int value) +{ + mysem_t h = + CreateSemaphore( + NULL, /* cannot be inherited */ + (LONG)value,/* Initial Count */ + 256, /* Maximum Count */ + NULL /* Name --> NULL, not shared among threads */ + ); + + if (h != NULL) *sem = h; + + return h != NULL; +} + +extern int /* boolean */ +mysem_wait (mysem_t *sem) +{ + HANDLE h = *sem; + return WAIT_FAILED != WaitForSingleObject (h, INFINITE); +} + +extern int /* boolean */ +mysem_post (mysem_t *sem) +{ + HANDLE h = *sem; + return 0 != ReleaseSemaphore(h, 1, NULL); +} + +extern int /* boolean */ +mysem_destroy (mysem_t *sem) +{ + return 0 != CloseHandle( *sem); +} + +/**** THREADS ****************************************************************************/ +#else + #error Definition of threads not present +#endif + +/* MULTI_THREADED_INTERFACE */ +#endif + + + + + + diff --git a/DroidFish/jni/gtb/sysport/sysport.h b/DroidFish/jni/gtb/sysport/sysport.h new file mode 100644 index 0000000..15c8ef3 --- /dev/null +++ b/DroidFish/jni/gtb/sysport/sysport.h @@ -0,0 +1,237 @@ +#if !defined(H_SYSPOR) +#define H_SYSPOR + +/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ + +/* +| Define +| MONOTHREAD: if SMP functions are not going to be used nor linked with -lpthread +| +*/ + +#if defined(MINGW) + #include + #if !defined(MVSC) + #define MVSC + #endif +#endif + +#ifdef _MSC_VER + #include + #if !defined(MVSC) + #define MVSC + #endif +#else + #include +#endif + + +#if defined(__linux__) || defined(__GNUC__) + #if !defined(GCCLINUX) + #define GCCLINUX + #endif +#endif + +#if defined(MINGW) + #undef GCCLINUX +#endif + +/* +| +| To allow multithreaded functions, MULTI_THREADED_INTERFACE should be defined +| +\*--------------------------------------------------------------------------------*/ + + +#if defined(CYGWIN) + #define USECLOCK + #define MULTI_THREADED_INTERFACE + #undef NT_THREADS + #define POSIX_THREADS + #define GCCLINUX_INTEGERS +#elif defined(MINGW) + #define USEWINCLOCK + #define MULTI_THREADED_INTERFACE + #define NT_THREADS + #undef POSIX_THREADS + #define MSWINDOWS_INTEGERS +#elif defined(GCCLINUX) + #define USELINCLOCK + #define MULTI_THREADED_INTERFACE + #undef NT_THREADS + #define POSIX_THREADS + #define GCCLINUX_INTEGERS +#elif defined(MVSC) + #define USEWINCLOCK + #define MULTI_THREADED_INTERFACE + #define NT_THREADS + #undef POSIX_THREADS + #define MSWINDOWS_INTEGERS +#else + #error COMPILER NOT DEFINED +#endif + +#if defined(MONOTHREAD) + #undef MULTI_THREADED_INTERFACE +#endif + + +#if defined(GCCLINUX) || defined(MINGW) + #define U64(x) (x##ull) +#elif defined(MVSC) + #define U64(x) (x##ui64) +#else + #error OS not defined properly +#endif + + +#if defined(GCCLINUX) || defined(MINGW) +/* + typedef unsigned long long int uint64_t; + typedef long long int int64_t; + typedef unsigned char uint8_t; + typedef unsigned short int uint16_t; + typedef unsigned int uint32_t; +*/ + + #include + +#elif defined(MVSC) + + typedef unsigned char uint8_t; + typedef unsigned short int uint16_t; + typedef unsigned int uint32_t; + typedef unsigned __int64 uint64_t; + + typedef signed char int8_t; + typedef short int int16_t; + typedef int int32_t; + typedef __int64 int64_t; + +#else + #error OS not defined properly for 64 bit integers +#endif + + +/*----------------- + PATH NAMES +------------------*/ + +#if defined(GCCLINUX) + #define FOLDERSEP "/" +#elif defined(MVSC) + #define FOLDERSEP "\\" +#else + #define FOLDERSEP "/" +#endif + +/* path names */ +extern int isfoldersep (int x); + +/*----------------- + FOPEN MAX +------------------*/ + +extern int mysys_fopen_max (void); + +/*------------ + TIMER +-------------*/ + +typedef int64_t myclock_t; + +extern myclock_t myclock(void); +extern myclock_t ticks_per_sec (void); + +#define MYCLOCKS_PER_SEC (ticks_per_sec()) +#define GET_TICK (myclock()) + + +/*********************************************************************/ +#if defined(MULTI_THREADED_INTERFACE) + +/*------------ + THREADS +-------------*/ + +#if defined (POSIX_THREADS) + + #include + #include + + #define THREAD_CALL + + typedef void * thread_return_t; + typedef pthread_t mythread_t; + typedef thread_return_t (THREAD_CALL *routine_t) (void *); + typedef pthread_mutex_t mythread_mutex_t; + + #ifdef SPINLOCKS + typedef pthread_spinlock_t mythread_spinx_t; + #else + typedef pthread_mutex_t mythread_spinx_t; + #endif + + typedef sem_t mysem_t; + + +#elif defined(NT_THREADS) + + #define WIN32_LEAN_AND_MEAN + + #include + #include + + #define THREAD_CALL __stdcall + + typedef unsigned thread_return_t; + typedef HANDLE mythread_t; + typedef thread_return_t (THREAD_CALL *routine_t) (void *); + typedef HANDLE mythread_mutex_t; + + #define SPINLOCKS + + #ifdef SPINLOCKS + typedef CRITICAL_SECTION mythread_spinx_t; + #else + typedef HANDLE mythread_spinx_t; + #endif + + typedef HANDLE mysem_t; + +#else + #error Definition of threads not present +#endif + + + +extern int /*boolean*/ mythread_create (/*@out@*/ mythread_t *thread, routine_t start_routine, void *arg, /*@out@*/ int *ret_error); +extern int /*boolean*/ mythread_join (mythread_t thread); +extern void mythread_exit (void); +extern const char * mythread_create_error (int err); + +extern void mythread_mutex_init (mythread_mutex_t *m); +extern void mythread_mutex_destroy (mythread_mutex_t *m); +extern void mythread_mutex_lock (mythread_mutex_t *m); +extern void mythread_mutex_unlock (mythread_mutex_t *m); + +extern void mythread_spinx_init (mythread_spinx_t *m); /**/ +extern void mythread_spinx_destroy (mythread_spinx_t *m); /**/ +extern void mythread_spinx_lock (mythread_spinx_t *m); /**/ +extern void mythread_spinx_unlock (mythread_spinx_t *m); /**/ + +/* semaphores*/ +extern int /*boolean*/ mysem_init (mysem_t *sem, unsigned int value); +extern int /*boolean*/ mysem_wait (mysem_t *sem); +extern int /*boolean*/ mysem_post (mysem_t *sem); +extern int /*boolean*/ mysem_destroy (mysem_t *sem); +#endif + + + + + +/* end MULTI_THREADED_INTERFACE*/ +#endif + +/*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ diff --git a/DroidFish/jni/gtb/version.h b/DroidFish/jni/gtb/version.h new file mode 100644 index 0000000..4a7b0ec --- /dev/null +++ b/DroidFish/jni/gtb/version.h @@ -0,0 +1,2 @@ +#define VERSION "0.4.3" + diff --git a/DroidFish/jni/gtb/version.txt b/DroidFish/jni/gtb/version.txt new file mode 100644 index 0000000..17b2ccd --- /dev/null +++ b/DroidFish/jni/gtb/version.txt @@ -0,0 +1 @@ +0.4.3 diff --git a/DroidFish/res/values/strings.xml b/DroidFish/res/values/strings.xml index 3b997ee..27075b8 100644 --- a/DroidFish/res/values/strings.xml +++ b/DroidFish/res/values/strings.xml @@ -188,6 +188,7 @@ combined with the very strong Stockfish 2.2.2 chess engine.\n\ * Extensive PGN support\n\ * Adjustable playing strength\n\ * Third party UCI engines\n\ +* Gaviota endgame tablebases\n\ \n\ Hints\n\ * In game mode, long press chess board to activate copy/paste menu.\n\ @@ -243,6 +244,11 @@ DroidFish can use third party UCI engines. To use this feature:\n\ Note! The binaries must be compiled for Android.\n\ 2. From the menu, choose Select Chess Engine and select the engine to use.\n\ \n\ +Gaviota endgame tablebases\n\ +To use Gaviota endgame tablebases:\n\ +1. Copy .gtb files to the DroidFish/gtb directory on the SD card.\n\ +2. Use the Endgame Tablebases preferences screen to control how the tablebases are used.\n\ +\n\ License\n\ GNU GPL v3\n\ \n\ @@ -251,6 +257,11 @@ GNU GPL v3\n\ * Droidfish is developed by Peter Österlund.\n\ * User interface improvements by Aaro Korhonen.\n\ \n\ +* Gaviota Tablebases Probing Code API, Copyright \u00a9 2010 Miguel A. Ballicora.\n\ +* LZMA compression by Igor Pavlov.\n\ +* ZLIB compression, Copyright \u00a9 1995-2005 Jean-loup Gailly and Mark Adler.\n\ +* LZF compression, Copyright \u00a9 2000-2007 Marc Alexander Lehmann.\n\ +\n\ Translations\n\ * German translation by Uwe Walschus.\n\ * Spanish translation by Amador Cuesta.\n\ @@ -503,6 +514,7 @@ you are not actively using the program.\ Arrow 5 Arrow 6 Square Labels + Tablebase hints Move List Current Move Other @@ -546,4 +558,15 @@ you are not actively using the program.\ Include information about draw and resign actions Clock Include time information for each move + Endgame Tablebases + Show Hints + When touching a piece, show EGTB value for all possible moves by that piece + Edit Board Hints + When touching a piece, show EGTB value for all possible alternate positions of that piece + Probe at Root + Filter out non-optimal moves before starting search + Engine Probing + Enable EGTB probing in engine, when supported. Takes effect next time engine is started + GTB Directory + Directory where Gaviota tablebases are installed. Leave blank to use default directory diff --git a/DroidFish/res/xml/preferences.xml b/DroidFish/res/xml/preferences.xml index 70eab2e..ce8aa87 100644 --- a/DroidFish/res/xml/preferences.xml +++ b/DroidFish/res/xml/preferences.xml @@ -231,7 +231,12 @@ android:title="@string/prefs_color_squareLabel_title" android:defaultValue="#FFFF0000"> - + + + + + + + + + + + + + + + diff --git a/DroidFish/src/org/petero/droidfish/ChessBoard.java b/DroidFish/src/org/petero/droidfish/ChessBoard.java index f631466..2b16e9d 100644 --- a/DroidFish/src/org/petero/droidfish/ChessBoard.java +++ b/DroidFish/src/org/petero/droidfish/ChessBoard.java @@ -53,6 +53,17 @@ public class ChessBoard extends View { List moveHints; + /** Decoration for a square. Currently the only possible decoration is a number. */ + public final static class SquareDecoration { + int sq; + int number; + public SquareDecoration(int sq, int number) { + this.sq = sq; + this.number = number; + } + } + private ArrayList decorations; + protected Paint darkPaint; protected Paint brightPaint; private Paint selectedSquarePaint; @@ -60,6 +71,7 @@ public class ChessBoard extends View { private Paint whitePiecePaint; private Paint blackPiecePaint; private Paint labelPaint; + private Paint decorationPaint; private ArrayList moveMarkPaint; public ChessBoard(Context context, AttributeSet attrs) { @@ -93,6 +105,9 @@ public class ChessBoard extends View { labelPaint = new Paint(); labelPaint.setAntiAlias(true); + + decorationPaint = new Paint(); + decorationPaint.setAntiAlias(true); moveMarkPaint = new ArrayList(); for (int i = 0; i < 6; i++) { @@ -122,6 +137,7 @@ public class ChessBoard extends View { whitePiecePaint.setColor(ct.getColor(ColorTheme.BRIGHT_PIECE)); blackPiecePaint.setColor(ct.getColor(ColorTheme.DARK_PIECE)); labelPaint.setColor(ct.getColor(ColorTheme.SQUARE_LABEL)); + decorationPaint.setColor(ct.getColor(ColorTheme.DECORATION)); for (int i = 0; i < 6; i++) moveMarkPaint.get(i).setColor(ct.getColor(ColorTheme.ARROW_0 + i)); @@ -130,7 +146,7 @@ public class ChessBoard extends View { private Handler handlerTimer = new Handler(); - final class AnimInfo { + private final class AnimInfo { AnimInfo() { startTime = -1; } boolean paused; long posHash; // Position the animation is valid for @@ -183,7 +199,7 @@ public class ChessBoard extends View { drawPiece(canvas, xCrd, yCrd, piece); } } - AnimInfo anim = new AnimInfo(); + private AnimInfo anim = new AnimInfo(); /** * Set up move animation. The animation will start the next time setPosition is called. @@ -191,7 +207,7 @@ public class ChessBoard extends View { * @param move The move leading to the target position. * @param forward True if forward direction, false for undo move. */ - public void setAnimMove(Position sourcePos, Move move, boolean forward) { + public final void setAnimMove(Position sourcePos, Move move, boolean forward) { anim.startTime = -1; anim.paused = true; // Animation starts at next position update if (forward) { @@ -366,6 +382,7 @@ public class ChessBoard extends View { blackPiecePaint.setTextSize(sqSize); whitePiecePaint.setTextSize(sqSize); labelPaint.setTextSize(sqSize/4.0f); + decorationPaint.setTextSize(sqSize/3.0f); computeOrigin(width, height); for (int x = 0; x < 8; x++) { for (int y = 0; y < 8; y++) { @@ -406,8 +423,10 @@ public class ChessBoard extends View { cursorSquarePaint.setStrokeWidth(sqSize/(float)16); canvas.drawRect(x0, y0, x0 + sqSize, y0 + sqSize, cursorSquarePaint); } - if (!animActive) + if (!animActive) { drawMoveHints(canvas); + drawDecorations(canvas); + } anim.draw(canvas); // long t1 = System.currentTimeMillis(); @@ -511,8 +530,7 @@ public class ChessBoard extends View { private final void drawLabel(Canvas canvas, int xCrd, int yCrd, boolean right, boolean bottom, char c) { - String s = ""; - s += c; + String s = Character.toString(c); if (labelBounds == null) { labelBounds = new Rect(); labelPaint.getTextBounds("f", 0, 1, labelBounds); @@ -556,7 +574,7 @@ public class ChessBoard extends View { return sq; } - final private boolean myColor(int piece) { + private final boolean myColor(int piece) { return (piece != Piece.EMPTY) && (Piece.isWhite(piece) == pos.whiteMove); } @@ -667,4 +685,48 @@ public class ChessBoard extends View { invalidate(); } } + + public final void setSquareDecorations(ArrayList decorations) { + boolean equal = false; + if ((this.decorations == null) || (decorations == null)) { + equal = this.decorations == decorations; + } else { + equal = this.decorations.equals(decorations); + } + if (!equal) { + this.decorations = decorations; + invalidate(); + } + } + + private final void drawDecorations(Canvas canvas) { + if (decorations == null) + return; + for (SquareDecoration sd : decorations) { + int sq = sd.sq; + if ((sd.sq < 0) || (sd.sq >= 64)) + continue; + int xCrd = getXCrd(Position.getX(sq)); + int yCrd = getYCrd(Position.getY(sq)); + + int num = sd.number; + String s; + if (num > 0) + s = "+" + String.valueOf(num); + else if (num < 0) + s = String.valueOf(num); + else + s = "0"; + + Rect bounds = new Rect(); + decorationPaint.getTextBounds(s, 0, s.length(), bounds); + xCrd += (sqSize - (bounds.left + bounds.right)) / 2; + yCrd += (sqSize - (bounds.top + bounds.bottom)) / 2; + canvas.drawText(s, xCrd, yCrd, decorationPaint); + } + } + + public final int getSelectedSquare() { + return selectedSquare; + } } diff --git a/DroidFish/src/org/petero/droidfish/ColorTheme.java b/DroidFish/src/org/petero/droidfish/ColorTheme.java index 823c696..82e2061 100644 --- a/DroidFish/src/org/petero/droidfish/ColorTheme.java +++ b/DroidFish/src/org/petero/droidfish/ColorTheme.java @@ -46,13 +46,14 @@ public class ColorTheme { final static int ARROW_4 = 11; final static int ARROW_5 = 12; final static int SQUARE_LABEL = 13; - private final static int numColors = 14; + final static int DECORATION = 14; + private final static int numColors = 15; private int colorTable[] = new int[numColors]; private static final String[] prefNames = { "darkSquare", "brightSquare", "selectedSquare", "cursorSquare", "darkPiece", "brightPiece", "currentMove", - "arrow0", "arrow1", "arrow2", "arrow3", "arrow4", "arrow5", "squareLabel" + "arrow0", "arrow1", "arrow2", "arrow3", "arrow4", "arrow5", "squareLabel", "decoration" }; private static final String prefPrefix = "color_"; @@ -61,19 +62,23 @@ public class ColorTheme { private final static String themeColors[][] = { { "#FF808080", "#FFBEBE5A", "#FFFF0000", "#FF00FF00", "#FF000000", "#FFFFFFFF", "#FF888888", - "#A01F1FFF", "#A0FF1F1F", "#501F1FFF", "#50FF1F1F", "#1E1F1FFF", "#28FF1F1F", "#FFFF0000" + "#A01F1FFF", "#A0FF1F1F", "#501F1FFF", "#50FF1F1F", "#1E1F1FFF", "#28FF1F1F", "#FFFF0000", + "#FF9F9F66" }, { "#FF77A26D", "#FFC8C365", "#FFFFFF00", "#FF00FF00", "#FF202020", "#FFFFFFCC", "#FF6B9262", - "#A01F1FFF", "#A0FF1F1F", "#501F1FFF", "#50FF1F1F", "#1E1F1FFF", "#28FF1F1F", "#FFFF0000" + "#A01F1FFF", "#A0FF1F1F", "#501F1FFF", "#50FF1F1F", "#1E1F1FFF", "#28FF1F1F", "#FFFF0000", + "#FF808080" }, { "#FF83A5D2", "#FFFFFFFA", "#FF3232D1", "#FF5F5FFD", "#FF282828", "#FFF0F0F0", "#FF3333FF", - "#A01F1FFF", "#A01FFF1F", "#501F1FFF", "#501FFF1F", "#1E1F1FFF", "#281FFF1F", "#FFFF0000" + "#A01F1FFF", "#A01FFF1F", "#501F1FFF", "#501FFF1F", "#1E1F1FFF", "#281FFF1F", "#FFFF0000", + "#FF808080" }, { "#FF666666", "#FFDDDDDD", "#FFFF0000", "#FF0000FF", "#FF000000", "#FFFFFFFF", "#FF888888", - "#A01F1FFF", "#A0FF1F1F", "#501F1FFF", "#50FF1F1F", "#1E1F1FFF", "#28FF1F1F", "#FFFF0000" + "#A01F1FFF", "#A0FF1F1F", "#501F1FFF", "#50FF1F1F", "#1E1F1FFF", "#28FF1F1F", "#FFFF0000", + "#FF909090" } }; diff --git a/DroidFish/src/org/petero/droidfish/DroidFish.java b/DroidFish/src/org/petero/droidfish/DroidFish.java index f8fadf1..ccaba57 100644 --- a/DroidFish/src/org/petero/droidfish/DroidFish.java +++ b/DroidFish/src/org/petero/droidfish/DroidFish.java @@ -28,6 +28,7 @@ import java.util.HashMap; import java.util.List; import java.util.TreeMap; +import org.petero.droidfish.ChessBoard.SquareDecoration; import org.petero.droidfish.activities.CPUWarning; import org.petero.droidfish.activities.EditBoard; import org.petero.droidfish.activities.EditPGNLoad; @@ -39,10 +40,12 @@ import org.petero.droidfish.engine.EngineUtil; import org.petero.droidfish.gamelogic.DroidChessController; import org.petero.droidfish.gamelogic.ChessParseError; import org.petero.droidfish.gamelogic.Move; +import org.petero.droidfish.gamelogic.Pair; import org.petero.droidfish.gamelogic.Position; import org.petero.droidfish.gamelogic.TextIO; import org.petero.droidfish.gamelogic.PgnToken; import org.petero.droidfish.gamelogic.GameTree.Node; +import org.petero.droidfish.gtb.Probe; import android.app.Activity; import android.app.AlertDialog; @@ -163,8 +166,10 @@ public class DroidFish extends Activity implements GUIInterface { private final static String bookDir = "DroidFish"; private final static String pgnDir = "DroidFish" + File.separator + "pgn"; private final static String engineDir = "DroidFish" + File.separator + "uci"; + private final static String gtbDefaultDir = "DroidFish" + File.separator + "gtb"; private BookOptions bookOptions = new BookOptions(); private PGNOptions pgnOptions = new PGNOptions(); + private EGTBOptions egtbOptions = new EGTBOptions(); private long lastVisibleMillis; // Time when GUI became invisible. 0 if currently visible. private long lastComputationMillis; // Time when engine last showed that it was computing. @@ -235,6 +240,7 @@ public class DroidFish extends Activity implements GUIInterface { new File(extDir + sep + bookDir).mkdirs(); new File(extDir + sep + pgnDir).mkdirs(); new File(extDir + sep + engineDir).mkdirs(); + new File(extDir + sep + gtbDefaultDir).mkdirs(); } private String getPgnIntent() { @@ -404,6 +410,7 @@ public class DroidFish extends Activity implements GUIInterface { Move m = cb.mousePressed(sq); if (m != null) ctrl.makeHumanMove(m); + setEgtbHints(cb.getSelectedSquare()); } } }); @@ -416,9 +423,9 @@ public class DroidFish extends Activity implements GUIInterface { public void onTrackballEvent(MotionEvent event) { if (ctrl.humansTurn()) { Move m = cb.handleTrackballEvent(event); - if (m != null) { + if (m != null) ctrl.makeHumanMove(m); - } + setEgtbHints(cb.getSelectedSquare()); } } }); @@ -609,6 +616,20 @@ public class DroidFish extends Activity implements GUIInterface { bookOptions.random = (settings.getInt("bookRandom", 500) - 500) * (3.0 / 500); setBookOptions(); + egtbOptions.hints = settings.getBoolean("tbHints", false); + egtbOptions.hintsEdit = settings.getBoolean("tbHintsEdit", false); + egtbOptions.rootProbe = settings.getBoolean("tbRootProbe", false); + egtbOptions.engineProbe = settings.getBoolean("tbEngineProbe", true); + String gtbPath = settings.getString("gtbPath", ""); + if (gtbPath.length() == 0) { + File extDir = Environment.getExternalStorageDirectory(); + String sep = File.separator; + gtbPath = extDir.getAbsolutePath() + sep + gtbDefaultDir; + } + egtbOptions.gtbPath = gtbPath; + setEgtbOptions(); + setEgtbHints(cb.getSelectedSquare()); + updateThinkingInfo(); pgnOptions.view.variations = settings.getBoolean("viewVariations", true); @@ -679,6 +700,29 @@ public class DroidFish extends Activity implements GUIInterface { ctrl.setBookOptions(options); } + private final void setEgtbOptions() { + ctrl.setEgtbOptions(new EGTBOptions(egtbOptions)); + } + + private final void setEgtbHints(int sq) { + if (!egtbOptions.hints || (sq < 0)) { + cb.setSquareDecorations(null); + return; + } + + Probe gtbProbe = Probe.getInstance(); + ArrayList> x = gtbProbe.movePieceProbe(cb.pos, sq); + if (x == null) { + cb.setSquareDecorations(null); + return; + } + + ArrayList sd = new ArrayList(); + for (Pair p : x) + sd.add(new SquareDecoration(p.first, p.second)); + cb.setSquareDecorations(sd); + } + @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.options_menu, menu); @@ -841,6 +885,7 @@ public class DroidFish extends Activity implements GUIInterface { @Override public void setSelection(int sq) { cb.setSelection(sq); + setEgtbHints(sq); } @Override @@ -940,12 +985,13 @@ public class DroidFish extends Activity implements GUIInterface { } @Override - public void setPosition(Position pos, String variantInfo, List variantMoves) { + public void setPosition(Position pos, String variantInfo, ArrayList variantMoves) { variantStr = variantInfo; this.variantMoves = variantMoves; cb.setPosition(pos); setBoardFlip(); updateThinkingInfo(); + setEgtbHints(cb.getSelectedSquare()); } private String thinkingStr1 = ""; @@ -953,12 +999,12 @@ public class DroidFish extends Activity implements GUIInterface { private String bookInfoStr = ""; private String variantStr = ""; private ArrayList> pvMoves = new ArrayList>(); - private List bookMoves = null; - private List variantMoves = null; + private ArrayList bookMoves = null; + private ArrayList variantMoves = null; @Override public void setThinkingInfo(String pvStr, String statStr, String bookInfo, - ArrayList> pvMoves, List bookMoves) { + ArrayList> pvMoves, ArrayList bookMoves) { thinkingStr1 = pvStr; thinkingStr2 = statStr; bookInfoStr = bookInfo; diff --git a/DroidFish/src/org/petero/droidfish/EGTBOptions.java b/DroidFish/src/org/petero/droidfish/EGTBOptions.java new file mode 100644 index 0000000..73f902d --- /dev/null +++ b/DroidFish/src/org/petero/droidfish/EGTBOptions.java @@ -0,0 +1,44 @@ +package org.petero.droidfish; + +/** Endgame tablebase probing options. */ +public final class EGTBOptions { + public boolean hints; // Hints when playing/analyzing + public boolean hintsEdit; // Hints in "edit board" mode + public boolean rootProbe; // Only search optimal moves at root + public boolean engineProbe; // Let engine use EGTB + public String gtbPath; // GTB directory path + + public EGTBOptions() { + hints = false; + hintsEdit = false; + rootProbe = false; + engineProbe = false; + gtbPath = ""; + } + + public EGTBOptions(EGTBOptions other) { + hints = other.hints; + hintsEdit = other.hintsEdit; + rootProbe = other.rootProbe; + engineProbe = other.engineProbe; + gtbPath = other.gtbPath; + } + + @Override + public boolean equals(Object o) { + if ((o == null) || (o.getClass() != this.getClass())) + return false; + EGTBOptions other = (EGTBOptions)o; + + return ((hints == other.hints) && + (hintsEdit == other.hintsEdit) && + (rootProbe == other.rootProbe) && + (engineProbe == other.engineProbe) && + gtbPath.equals(other.gtbPath)); + } + + @Override + public int hashCode() { + return 0; + } +} diff --git a/DroidFish/src/org/petero/droidfish/GUIInterface.java b/DroidFish/src/org/petero/droidfish/GUIInterface.java index 3126110..cbfa105 100644 --- a/DroidFish/src/org/petero/droidfish/GUIInterface.java +++ b/DroidFish/src/org/petero/droidfish/GUIInterface.java @@ -19,7 +19,6 @@ package org.petero.droidfish; import java.util.ArrayList; -import java.util.List; import org.petero.droidfish.gamelogic.Game; import org.petero.droidfish.gamelogic.Move; @@ -31,7 +30,7 @@ import android.content.Context; public interface GUIInterface { /** Update the displayed board position. */ - public void setPosition(Position pos, String variantInfo, List variantMoves); + public void setPosition(Position pos, String variantInfo, ArrayList variantMoves); /** Mark square sq as selected. Set to -1 to clear selection. */ public void setSelection(int sq); @@ -55,7 +54,7 @@ public interface GUIInterface { /** Update the computer thinking information. */ public void setThinkingInfo(String pvStr, String statStr, String bookInfo, - ArrayList> pvMoves, List bookMoves); + ArrayList> pvMoves, ArrayList bookMoves); /** Ask what to promote a pawn to. Should call reportPromotePiece() when done. */ public void requestPromotePiece(); diff --git a/DroidFish/src/org/petero/droidfish/activities/ChessBoardEdit.java b/DroidFish/src/org/petero/droidfish/activities/ChessBoardEdit.java index 8b8ebd0..aff4a2b 100644 --- a/DroidFish/src/org/petero/droidfish/activities/ChessBoardEdit.java +++ b/DroidFish/src/org/petero/droidfish/activities/ChessBoardEdit.java @@ -58,7 +58,7 @@ public class ChessBoardEdit extends ChessBoard { y0 = (height - (sqSize * 10 + gap)) / 2; } - int extraPieces(int x, int y) { + private final int extraPieces(int x, int y) { if (y == -1) { // White pieces switch (x) { case 0: return Piece.WKING; diff --git a/DroidFish/src/org/petero/droidfish/activities/EditBoard.java b/DroidFish/src/org/petero/droidfish/activities/EditBoard.java index c6850c4..2cf5d32 100644 --- a/DroidFish/src/org/petero/droidfish/activities/EditBoard.java +++ b/DroidFish/src/org/petero/droidfish/activities/EditBoard.java @@ -18,21 +18,28 @@ package org.petero.droidfish.activities; +import java.util.ArrayList; + import org.petero.droidfish.ChessBoard; import org.petero.droidfish.R; +import org.petero.droidfish.ChessBoard.SquareDecoration; import org.petero.droidfish.gamelogic.ChessParseError; import org.petero.droidfish.gamelogic.Move; +import org.petero.droidfish.gamelogic.Pair; import org.petero.droidfish.gamelogic.Piece; import org.petero.droidfish.gamelogic.Position; import org.petero.droidfish.gamelogic.TextIO; +import org.petero.droidfish.gtb.Probe; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.content.DialogInterface; import android.content.Intent; +import android.content.SharedPreferences; import android.content.res.Configuration; import android.os.Bundle; +import android.preference.PreferenceManager; import android.text.ClipboardManager; import android.view.GestureDetector; import android.view.KeyEvent; @@ -53,12 +60,17 @@ public class EditBoard extends Activity { private Button okButton; private Button cancelButton; + boolean egtbHints; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); initUI(); + SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this); + egtbHints = settings.getBoolean("tbHintsEdit", false); + Intent i = getIntent(); Position pos; try { @@ -78,7 +90,7 @@ public class EditBoard extends Activity { cb.cursorY = oldCB.cursorY; cb.cursorVisible = oldCB.cursorVisible; cb.setPosition(oldCB.pos); - cb.setSelection(oldCB.selectedSquare); + setSelection(oldCB.selectedSquare); status.setText(statusStr); } @@ -128,6 +140,7 @@ public class EditBoard extends Activity { Move m = cb.mousePressed(sq); if (m != null) doMove(m); + setEgtbHints(cb.getSelectedSquare()); } }); cb.setOnTouchListener(new OnTouchListener() { @@ -138,9 +151,9 @@ public class EditBoard extends Activity { cb.setOnTrackballListener(new ChessBoard.OnTrackballListener() { public void onTrackballEvent(MotionEvent event) { Move m = cb.handleTrackballEvent(event); - if (m != null) { + if (m != null) doMove(m); - } + setEgtbHints(cb.getSelectedSquare()); } }); cb.setOnLongClickListener(new OnLongClickListener() { @@ -152,10 +165,34 @@ public class EditBoard extends Activity { }); } + private final void setSelection(int sq) { + cb.setSelection(sq); + setEgtbHints(sq); + } + + private final void setEgtbHints(int sq) { + if (!egtbHints || (sq < 0)) { + cb.setSquareDecorations(null); + return; + } + + Probe gtbProbe = Probe.getInstance(); + ArrayList> x = gtbProbe.relocatePieceProbe(cb.pos, sq); + if (x == null) { + cb.setSquareDecorations(null); + return; + } + + ArrayList sd = new ArrayList(); + for (Pair p : x) + sd.add(new SquareDecoration(p.first, p.second)); + cb.setSquareDecorations(sd); + } + private void doMove(Move m) { if (m.to < 0) { if ((m.from < 0) || (cb.pos.getPiece(m.from) == Piece.EMPTY)) { - cb.setSelection(m.to); + setSelection(m.to); return; } } @@ -172,9 +209,9 @@ public class EditBoard extends Activity { pos.setPiece(m.from, Piece.EMPTY); cb.setPosition(pos); if (m.from >= 0) - cb.setSelection(-1); + setSelection(-1); else - cb.setSelection(m.from); + setSelection(m.from); checkValid(); } @@ -263,13 +300,13 @@ public class EditBoard extends Activity { switch (item) { case 0: // Edit side to move showDialog(SIDE_DIALOG); - cb.setSelection(-1); + setSelection(-1); checkValid(); break; case 1: { // Clear board Position pos = new Position(); cb.setPosition(pos); - cb.setSelection(-1); + setSelection(-1); checkValid(); break; } @@ -277,7 +314,7 @@ public class EditBoard extends Activity { try { Position pos = TextIO.readFEN(TextIO.startPosFEN); cb.setPosition(pos); - cb.setSelection(-1); + setSelection(-1); checkValid(); } catch (ChessParseError e) { } @@ -286,19 +323,19 @@ public class EditBoard extends Activity { case 3: // Edit castling flags removeDialog(CASTLE_DIALOG); showDialog(CASTLE_DIALOG); - cb.setSelection(-1); + setSelection(-1); checkValid(); break; case 4: // Edit en passant file removeDialog(EP_DIALOG); showDialog(EP_DIALOG); - cb.setSelection(-1); + setSelection(-1); checkValid(); break; case 5: // Edit move counters removeDialog(MOVCNT_DIALOG); showDialog(MOVCNT_DIALOG); - cb.setSelection(-1); + setSelection(-1); checkValid(); break; case 6: { // Copy position @@ -306,7 +343,7 @@ public class EditBoard extends Activity { String fen = TextIO.toFEN(cb.pos) + "\n"; ClipboardManager clipboard = (ClipboardManager)getSystemService(CLIPBOARD_SERVICE); clipboard.setText(fen); - cb.setSelection(-1); + setSelection(-1); break; } case 7: { // Paste position @@ -321,7 +358,7 @@ public class EditBoard extends Activity { cb.setPosition(e.pos); Toast.makeText(getApplicationContext(), getParseErrString(e), Toast.LENGTH_SHORT).show(); } - cb.setSelection(-1); + setSelection(-1); checkValid(); } break; diff --git a/DroidFish/src/org/petero/droidfish/book/BookOptions.java b/DroidFish/src/org/petero/droidfish/book/BookOptions.java index d175a8f..18bfc08 100644 --- a/DroidFish/src/org/petero/droidfish/book/BookOptions.java +++ b/DroidFish/src/org/petero/droidfish/book/BookOptions.java @@ -19,7 +19,7 @@ package org.petero.droidfish.book; /** Settings controlling opening book usage */ -public class BookOptions { +public final class BookOptions { public String filename = ""; public int maxLength = 1000000; diff --git a/DroidFish/src/org/petero/droidfish/engine/DroidComputerPlayer.java b/DroidFish/src/org/petero/droidfish/engine/DroidComputerPlayer.java index 4b22e74..caeb84a 100644 --- a/DroidFish/src/org/petero/droidfish/engine/DroidComputerPlayer.java +++ b/DroidFish/src/org/petero/droidfish/engine/DroidComputerPlayer.java @@ -23,6 +23,7 @@ import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; +import org.petero.droidfish.EGTBOptions; import org.petero.droidfish.book.BookOptions; import org.petero.droidfish.book.DroidBook; import org.petero.droidfish.gamelogic.Move; @@ -33,6 +34,8 @@ import org.petero.droidfish.gamelogic.SearchListener; import org.petero.droidfish.gamelogic.TextIO; import org.petero.droidfish.gamelogic.UndoInfo; import org.petero.droidfish.gamelogic.SearchListener.PvInfo; +import org.petero.droidfish.gtb.Probe; +import org.petero.droidfish.gtb.Probe.ProbeResult; import android.content.Context; @@ -45,6 +48,8 @@ public class DroidComputerPlayer { private final Context context; private final SearchListener listener; private final DroidBook book; + private EGTBOptions egtbOptions; + private final Probe gtbProbe; /** Set when "ucinewgame" needs to be sent. */ private boolean newGame = false; @@ -118,6 +123,7 @@ public class DroidComputerPlayer { long[] posHashList; // For draw decision after completed search int posHashListSize; // For draw decision after completed search + ArrayList searchMoves; // Moves to search, or null to search all moves /** * Create a request to start an engine. @@ -238,6 +244,8 @@ public class DroidComputerPlayer { this.context = context; this.listener = listener; book = DroidBook.getInstance(); + egtbOptions = new EGTBOptions(); + gtbProbe = Probe.getInstance(); engineState = new EngineState(); searchRequest = null; } @@ -264,12 +272,21 @@ public class DroidComputerPlayer { public final void setBookOptions(BookOptions options) { book.setOptions(options); } + + public final void setEgtbOptions(EGTBOptions options) { + egtbOptions = options; + gtbProbe.setPath(options.gtbPath); + } /** Return all book moves, both as a formatted string and as a list of moves. */ public final Pair> getBookHints(Position pos) { return book.getAllBookMoves(pos); } + public final ProbeResult egtbProbe(Position pos) { + return gtbProbe.probeHard(pos); + } + /** Get engine reported name. */ public final synchronized String getEngineName() { return engineName; @@ -319,6 +336,22 @@ public class DroidComputerPlayer { handleQueue(); } + /** Decide what moves to search. Filters out non-optimal moves if tablebases are used. */ + private final ArrayList movesToSearch(SearchRequest sr) { + ArrayList moves = null; + if (egtbOptions.rootProbe) { + moves = gtbProbe.findOptimal(sr.currPos); + } + if (moves != null) { + sr.searchMoves = moves; + } else { + moves = new MoveGen().pseudoLegalMoves(sr.currPos); + moves = MoveGen.removeIllegal(sr.currPos, moves); + sr.searchMoves = null; + } + return moves; + } + /** * Start a search. Search result is returned to the search listener object. * The result can be a valid move string, in which case the move is played @@ -352,9 +385,8 @@ public class DroidComputerPlayer { } } - // If only one legal move, play it without searching - ArrayList moves = new MoveGen().pseudoLegalMoves(sr.currPos); - moves = MoveGen.removeIllegal(sr.currPos, moves); + // If only one move to search, play it without searching + ArrayList moves = movesToSearch(sr); if (moves.size() == 0) { listener.notifySearchResult(sr.searchId, "", null); // User set up a position where computer has no valid moves. return; @@ -381,8 +413,7 @@ public class DroidComputerPlayer { stopSearch(); // If no legal moves, there is nothing to analyze - ArrayList moves = new MoveGen().pseudoLegalMoves(sr.currPos); - moves = MoveGen.removeIllegal(sr.currPos, moves); + ArrayList moves = movesToSearch(sr); if (moves.size() == 0) return; @@ -485,7 +516,7 @@ public class DroidComputerPlayer { engineState.searchId = searchRequest.searchId; - // Reduce remaining time there was an engine delay + // Reduce remaining time if there was an engine delay if (isSearch) { long now = System.currentTimeMillis(); int delay = (int)(now - searchRequest.startTime); @@ -530,6 +561,13 @@ public class DroidComputerPlayer { goStr.append(String.format(" movestogo %d", sr.movesToGo)); if (sr.ponderMove != null) goStr.append(" ponder"); + if (sr.searchMoves != null) { + goStr.append(" searchmoves"); + for (Move m : sr.searchMoves) { + goStr.append(' '); + goStr.append(TextIO.moveToUCIString(m)); + } + } uciEngine.writeLineToEngine(goStr.toString()); engineState.setState((sr.ponderMove == null) ? MainState.SEARCH : MainState.PONDER); } else { // Analyze @@ -547,7 +585,16 @@ public class DroidComputerPlayer { uciEngine.writeLineToEngine(posStr.toString()); uciEngine.setOption("UCI_AnalyseMode", true); uciEngine.setOption("Threads", sr.engineThreads > 0 ? sr.engineThreads : numCPUs); - uciEngine.writeLineToEngine("go infinite"); + StringBuilder goStr = new StringBuilder(96); + goStr.append("go infinite"); + if (sr.searchMoves != null) { + goStr.append(" searchmoves"); + for (Move m : sr.searchMoves) { + goStr.append(' '); + goStr.append(TextIO.moveToUCIString(m)); + } + } + uciEngine.writeLineToEngine(goStr.toString()); engineState.setState(MainState.ANALYZE); } } @@ -624,7 +671,7 @@ public class DroidComputerPlayer { switch (engineState.state) { case READ_OPTIONS: { if (readUCIOption(uci, s)) { - uci.initOptions(); + uci.initOptions(egtbOptions); uci.writeLineToEngine("ucinewgame"); uci.writeLineToEngine("isready"); engineState.setState(MainState.WAIT_READY); diff --git a/DroidFish/src/org/petero/droidfish/engine/ExternalEngine.java b/DroidFish/src/org/petero/droidfish/engine/ExternalEngine.java index c531553..b4c4d67 100644 --- a/DroidFish/src/org/petero/droidfish/engine/ExternalEngine.java +++ b/DroidFish/src/org/petero/droidfish/engine/ExternalEngine.java @@ -27,6 +27,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.nio.channels.FileChannel; +import org.petero.droidfish.EGTBOptions; import org.petero.droidfish.R; import android.content.Context; @@ -160,9 +161,13 @@ public class ExternalEngine extends UCIEngineBase { /** @inheritDoc */ @Override - public void initOptions() { - super.initOptions(); + public void initOptions(EGTBOptions egtbOptions) { + super.initOptions(egtbOptions); setOption("Hash", 16); + if (egtbOptions.engineProbe) { + setOption("GaviotaTbPath", egtbOptions.gtbPath); + setOption("GaviotaTbCache", 8); + } } /** @inheritDoc */ diff --git a/DroidFish/src/org/petero/droidfish/engine/UCIEngine.java b/DroidFish/src/org/petero/droidfish/engine/UCIEngine.java index c9ed733..c5bedd5 100644 --- a/DroidFish/src/org/petero/droidfish/engine/UCIEngine.java +++ b/DroidFish/src/org/petero/droidfish/engine/UCIEngine.java @@ -18,6 +18,8 @@ package org.petero.droidfish.engine; +import org.petero.droidfish.EGTBOptions; + public interface UCIEngine { /** For reporting engine error messages. */ @@ -30,7 +32,7 @@ public interface UCIEngine { public void initialize(); /** Initialize default options. */ - public void initOptions(); + public void initOptions(EGTBOptions egtbOptions); /** Shut down engine. */ public void shutDown(); diff --git a/DroidFish/src/org/petero/droidfish/engine/UCIEngineBase.java b/DroidFish/src/org/petero/droidfish/engine/UCIEngineBase.java index 1c3e702..0af6b49 100644 --- a/DroidFish/src/org/petero/droidfish/engine/UCIEngineBase.java +++ b/DroidFish/src/org/petero/droidfish/engine/UCIEngineBase.java @@ -21,6 +21,7 @@ package org.petero.droidfish.engine; import java.util.HashMap; import java.util.HashSet; +import org.petero.droidfish.EGTBOptions; import org.petero.droidfish.engine.cuckoochess.CuckooChessEngine; import android.content.Context; @@ -61,7 +62,7 @@ public abstract class UCIEngineBase implements UCIEngine { } @Override - public void initOptions() { + public void initOptions(EGTBOptions egtbOptions) { isUCI = true; } diff --git a/DroidFish/src/org/petero/droidfish/engine/cuckoochess/CuckooChessEngine.java b/DroidFish/src/org/petero/droidfish/engine/cuckoochess/CuckooChessEngine.java index 9d09d6e..08c06d7 100644 --- a/DroidFish/src/org/petero/droidfish/engine/cuckoochess/CuckooChessEngine.java +++ b/DroidFish/src/org/petero/droidfish/engine/cuckoochess/CuckooChessEngine.java @@ -25,6 +25,7 @@ import chess.Position; import chess.TextIO; import java.util.ArrayList; +import org.petero.droidfish.EGTBOptions; import org.petero.droidfish.engine.LocalPipe; import org.petero.droidfish.engine.UCIEngineBase; @@ -73,8 +74,8 @@ public class CuckooChessEngine extends UCIEngineBase { /** @inheritDoc */ @Override - public final void initOptions() { - super.initOptions(); + public final void initOptions(EGTBOptions egtbOptions) { + super.initOptions(egtbOptions); } /** @inheritDoc */ diff --git a/DroidFish/src/org/petero/droidfish/gamelogic/DroidChessController.java b/DroidFish/src/org/petero/droidfish/gamelogic/DroidChessController.java index c6da2c6..645c89e 100644 --- a/DroidFish/src/org/petero/droidfish/gamelogic/DroidChessController.java +++ b/DroidFish/src/org/petero/droidfish/gamelogic/DroidChessController.java @@ -22,6 +22,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import org.petero.droidfish.EGTBOptions; import org.petero.droidfish.GUIInterface; import org.petero.droidfish.GameMode; import org.petero.droidfish.PGNOptions; @@ -40,6 +41,7 @@ public class DroidChessController { private DroidComputerPlayer computerPlayer = null; private PgnToken.PgnTokenReceiver gameTextListener = null; private BookOptions bookOptions = new BookOptions(); + private EGTBOptions egtbOptions = new EGTBOptions(); private Game game = null; private Move ponderMove = null; private GUIInterface gui; @@ -81,6 +83,7 @@ public class DroidChessController { if (computerPlayer == null) { computerPlayer = new DroidComputerPlayer(gui.getContext(), listener); computerPlayer.setBookOptions(bookOptions); + computerPlayer.setEgtbOptions(egtbOptions); } computerPlayer.queueStartEngine(searchId, engine); searchId++; @@ -139,6 +142,14 @@ public class DroidChessController { } } + public final synchronized void setEgtbOptions(EGTBOptions options) { + if (!egtbOptions.equals(options)) { + egtbOptions = options; + if (computerPlayer != null) + computerPlayer.setEgtbOptions(egtbOptions); + } + } + /** Set engine and engine strength. Restart computer thinking if appropriate. * @param engine Name of engine. * @param strength Engine strength, 0 - 1000. */ @@ -560,7 +571,7 @@ public class DroidChessController { private boolean whiteMove = true; private String bookInfo = ""; - private List bookMoves = null; + private ArrayList bookMoves = null; private Move ponderMove = null; private ArrayList pvInfoV = new ArrayList(); @@ -676,7 +687,7 @@ public class DroidChessController { } @Override - public void notifyBookInfo(int id, String bookInfo, List moveList) { + public void notifyBookInfo(int id, String bookInfo, ArrayList moveList) { this.bookInfo = bookInfo; bookMoves = moveList; setSearchInfo(id); @@ -944,7 +955,7 @@ public class DroidChessController { } private final synchronized void setThinkingInfo(int id, ArrayList> pvMoves, String pvStr, - String statStr, String bookInfo, List bookMoves) { + String statStr, String bookInfo, ArrayList bookMoves) { if (id == searchId) gui.setThinkingInfo(pvStr, statStr, bookInfo, pvMoves, bookMoves); } diff --git a/DroidFish/src/org/petero/droidfish/gamelogic/GameTree.java b/DroidFish/src/org/petero/droidfish/gamelogic/GameTree.java index 520df7b..66d8f8b 100644 --- a/DroidFish/src/org/petero/droidfish/gamelogic/GameTree.java +++ b/DroidFish/src/org/petero/droidfish/gamelogic/GameTree.java @@ -674,10 +674,10 @@ public class GameTree { } /** List of possible continuation moves. */ - public final List variations() { + public final ArrayList variations() { if (currentNode.verifyChildren(currentPos)) updateListener(); - List ret = new ArrayList(); + ArrayList ret = new ArrayList(); for (Node child : currentNode.children) ret.add(child.move); return ret; diff --git a/DroidFish/src/org/petero/droidfish/gamelogic/SearchListener.java b/DroidFish/src/org/petero/droidfish/gamelogic/SearchListener.java index 4de4755..3d6afba 100644 --- a/DroidFish/src/org/petero/droidfish/gamelogic/SearchListener.java +++ b/DroidFish/src/org/petero/droidfish/gamelogic/SearchListener.java @@ -19,7 +19,6 @@ package org.petero.droidfish.gamelogic; import java.util.ArrayList; -import java.util.List; /** @@ -83,7 +82,7 @@ public interface SearchListener { public void notifyStats(int id, int nodes, int nps, int time); /** Report opening book information. */ - public void notifyBookInfo(int id, String bookInfo, List moveList); + public void notifyBookInfo(int id, String bookInfo, ArrayList moveList); /** Report move (or command, such as "resign") played by the engine. */ public void notifySearchResult(int id, String cmd, Move ponder); diff --git a/DroidFish/src/org/petero/droidfish/gtb/GtbProbe.java b/DroidFish/src/org/petero/droidfish/gtb/GtbProbe.java new file mode 100644 index 0000000..885f8f2 --- /dev/null +++ b/DroidFish/src/org/petero/droidfish/gtb/GtbProbe.java @@ -0,0 +1,83 @@ +/* + GtbProbe - Java interface to Gaviota endgame tablebases. + Copyright (C) 2011-2012 Peter Österlund, peterosterlund2@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +package org.petero.droidfish.gtb; + +/** Interface to native gtb probing code. */ +class GtbProbe { + static { + System.loadLibrary("gtb"); + } + + private String currTbPath = ""; + + GtbProbe() { + } + + final synchronized void setPath(String tbPath) { + if (!currTbPath.equals(tbPath)) { + currTbPath = tbPath; + init(tbPath); + } + } + + final static int NOPIECE = 0; + final static int PAWN = 1; + final static int KNIGHT = 2; + final static int BISHOP = 3; + final static int ROOK = 4; + final static int QUEEN = 5; + final static int KING = 6; + + final static int NOSQUARE = 64; + + // Castle masks + final static int H1_CASTLE = 8; + final static int A1_CASTLE = 4; + final static int H8_CASTLE = 2; + final static int A8_CASTLE = 1; + + // tbinfo values + final static int DRAW = 0; + final static int WMATE = 1; + final static int BMATE = 2; + final static int FORBID = 3; + final static int UNKNOWN = 7; + + /** + * Probe table bases. + * @param wtm True if white to move. + * @param epSq En passant square, or NOSQUARE. + * @param castleMask Castle mask. + * @param whiteSquares Array of squares occupied by white pieces, terminated with NOSQUARE. + * @param blackSquares Array of squares occupied by black pieces, terminated with NOSQUARE. + * @param whitePieces Array of white pieces, terminated with NOPIECE. + * @param blackPieces Array of black pieces, terminated with NOPIECE. + * @param result Two element array. Set to [tbinfo, plies]. + * @return True if success. + */ + public final native boolean probeHard(boolean wtm, int epSq, + int castleMask, + int[] whiteSquares, + int[] blackSquares, + byte[] whitePieces, + byte[] blackPieces, + int[] result); + + private final native static boolean init(String tbPath); +} diff --git a/DroidFish/src/org/petero/droidfish/gtb/Probe.java b/DroidFish/src/org/petero/droidfish/gtb/Probe.java new file mode 100644 index 0000000..92338d5 --- /dev/null +++ b/DroidFish/src/org/petero/droidfish/gtb/Probe.java @@ -0,0 +1,278 @@ +/* + GtbCuckoo - Interface to Gaviota endgame tablebases. + Copyright (C) 2011-2012 Peter Österlund, peterosterlund2@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +package org.petero.droidfish.gtb; + +import java.util.ArrayList; + +import org.petero.droidfish.gamelogic.Move; +import org.petero.droidfish.gamelogic.MoveGen; +import org.petero.droidfish.gamelogic.Pair; +import org.petero.droidfish.gamelogic.Piece; +import org.petero.droidfish.gamelogic.Position; +import org.petero.droidfish.gamelogic.UndoInfo; + +/** Interface between Position class and GTB probing code. */ +public class Probe { + private final GtbProbe gtb; + private final int whiteSquares[]; + private final int blackSquares[]; + private final byte whitePieces[]; + private final byte blackPieces[]; + + private static final Probe INSTANCE = new Probe(); + + /** Get singleton instance. */ + public static Probe getInstance() { + return INSTANCE; + } + + /** Constructor. */ + private Probe() { + gtb = new GtbProbe(); + whiteSquares = new int[65]; + blackSquares = new int[65]; + whitePieces = new byte[65]; + blackPieces = new byte[65]; + } + + public void setPath(String tbPath) { + gtb.setPath(tbPath); + } + + public static final class ProbeResult { + public final static int DRAW = 0; + public final static int WMATE = 1; + public final static int BMATE = 2; + public final static int UNKNOWN = 3; + + public int result; + public int movesToMate; // Full moves to mate, or 0 if DRAW or UNKNOWN. + } + + /** + * Probe table bases. + * @param pos The position to probe. + * @param result Two element array. Set to [tbinfo, plies]. + * @return True if success. + */ + public final ProbeResult probeHard(Position pos) { + int castleMask = 0; + if (pos.a1Castle()) castleMask |= GtbProbe.A1_CASTLE; + if (pos.h1Castle()) castleMask |= GtbProbe.H1_CASTLE; + if (pos.a8Castle()) castleMask |= GtbProbe.A8_CASTLE; + if (pos.h8Castle()) castleMask |= GtbProbe.H8_CASTLE; + + int nWhite = 0; + int nBlack = 0; + for (int sq = 0; sq < 64; sq++) { + int p = pos.getPiece(sq); + switch (p) { + case Piece.WKING: + whiteSquares[nWhite] = sq; + whitePieces[nWhite++] = GtbProbe.KING; + break; + case Piece.WQUEEN: + whiteSquares[nWhite] = sq; + whitePieces[nWhite++] = GtbProbe.QUEEN; + break; + case Piece.WROOK: + whiteSquares[nWhite] = sq; + whitePieces[nWhite++] = GtbProbe.ROOK; + break; + case Piece.WBISHOP: + whiteSquares[nWhite] = sq; + whitePieces[nWhite++] = GtbProbe.BISHOP; + break; + case Piece.WKNIGHT: + whiteSquares[nWhite] = sq; + whitePieces[nWhite++] = GtbProbe.KNIGHT; + break; + case Piece.WPAWN: + whiteSquares[nWhite] = sq; + whitePieces[nWhite++] = GtbProbe.PAWN; + break; + + case Piece.BKING: + blackSquares[nBlack] = sq; + blackPieces[nBlack++] = GtbProbe.KING; + break; + case Piece.BQUEEN: + blackSquares[nBlack] = sq; + blackPieces[nBlack++] = GtbProbe.QUEEN; + break; + case Piece.BROOK: + blackSquares[nBlack] = sq; + blackPieces[nBlack++] = GtbProbe.ROOK; + break; + case Piece.BBISHOP: + blackSquares[nBlack] = sq; + blackPieces[nBlack++] = GtbProbe.BISHOP; + break; + case Piece.BKNIGHT: + blackSquares[nBlack] = sq; + blackPieces[nBlack++] = GtbProbe.KNIGHT; + break; + case Piece.BPAWN: + blackSquares[nBlack] = sq; + blackPieces[nBlack++] = GtbProbe.PAWN; + break; + } + } + whiteSquares[nWhite] = GtbProbe.NOSQUARE; + blackSquares[nBlack] = GtbProbe.NOSQUARE; + whitePieces[nWhite] = GtbProbe.NOPIECE; + blackPieces[nBlack] = GtbProbe.NOPIECE; + int epSquare = pos.getEpSquare(); + if (epSquare == -1) + epSquare = GtbProbe.NOSQUARE; + + int[] result = new int[2]; + boolean res = gtb.probeHard(pos.whiteMove, epSquare, castleMask, + whiteSquares, blackSquares, whitePieces, blackPieces, + result); + ProbeResult ret = new ProbeResult(); + if (res) { + switch (result[0]) { + case GtbProbe.DRAW: + ret.result = ProbeResult.DRAW; + ret.movesToMate = 0; + break; + case GtbProbe.WMATE: + ret.result = ProbeResult.WMATE; + ret.movesToMate = (result[1] + 1) / 2; + break; + case GtbProbe.BMATE: + ret.result = ProbeResult.BMATE; + ret.movesToMate = (result[1] + 1) / 2; + break; + default: + ret.result = ProbeResult.UNKNOWN; + ret.movesToMate = 0; + break; + } + } else { + ret.result = ProbeResult.UNKNOWN; + ret.movesToMate = 0; + } + return ret; + } + + /** Return a list of all legal moves that are not known to be non-optimal. + * Returns null if no legal move could be excluded. */ + public final ArrayList findOptimal(Position pos) { + ArrayList moveList = new MoveGen().pseudoLegalMoves(pos); + moveList = MoveGen.removeIllegal(pos, moveList); + ArrayList optimalMoves = new ArrayList(); + ArrayList unknownMoves = new ArrayList(); + final int MATE0 = 100000; + int bestScore = -1000000; + UndoInfo ui = new UndoInfo(); + for (Move m : moveList) { + pos.makeMove(m, ui); + ProbeResult res = probeHard(pos); + pos.unMakeMove(m, ui); + if (res.result == ProbeResult.UNKNOWN) { + unknownMoves.add(m); + } else { + int wScore; + if (res.result == ProbeResult.WMATE) + wScore = MATE0 - res.movesToMate; + else if (res.result == ProbeResult.BMATE) + wScore = -(MATE0 - res.movesToMate); + else + wScore = 0; + int score = pos.whiteMove ? wScore : -wScore; + if (score > bestScore) { + optimalMoves.clear(); + optimalMoves.add(m); + bestScore = score; + } else if (score == bestScore) { + optimalMoves.add(m); + } else { + // Ignore move + } + } + } + for (Move m : unknownMoves) + optimalMoves.add(m); + return (optimalMoves.size() < moveList.size()) ? optimalMoves : null; + } + + /** For a given position and from square, return EGTB information + * about all legal destination squares. Return null if no information available. */ + public final ArrayList> movePieceProbe(Position pos, int fromSq) { + int p = pos.getPiece(fromSq); + if ((p == Piece.EMPTY) || (pos.whiteMove != Piece.isWhite(p))) + return null; + ArrayList> ret = new ArrayList>(); + + ArrayList moveList = new MoveGen().pseudoLegalMoves(pos); + moveList = MoveGen.removeIllegal(pos, moveList); + UndoInfo ui = new UndoInfo(); + for (Move m : moveList) { + if (m.from != fromSq) + continue; + pos.makeMove(m, ui); + ProbeResult res = probeHard(pos); + pos.unMakeMove(m, ui); + if (res.result == ProbeResult.UNKNOWN) + continue; + int score = 0; + if (res.result == ProbeResult.WMATE) { + score = pos.whiteMove ? res.movesToMate + 1 : -res.movesToMate; + } else if (res.result == ProbeResult.BMATE) { + score = pos.whiteMove ? -res.movesToMate : res.movesToMate + 1; + } + ret.add(new Pair(m.to, score)); + } + return ret; + } + + /** For a given position and from square, return EGTB information + * about all legal alternative positions for the piece on from square. + * Return null if no information is available. */ + public final ArrayList> relocatePieceProbe(Position pos, int fromSq) { + int p = pos.getPiece(fromSq); + if (p == Piece.EMPTY) + return null; + boolean isPawn = (Piece.makeWhite(p) == Piece.WPAWN); + ArrayList> ret = new ArrayList>(); + for (int sq = 0; sq < 64; sq++) { + if ((sq != fromSq) && (pos.getPiece(sq) != Piece.EMPTY)) + continue; + if (isPawn && ((sq < 8) || (sq >= 56))) + continue; + pos.setPiece(fromSq, Piece.EMPTY); + pos.setPiece(sq, p); + ProbeResult res = probeHard(pos); + pos.setPiece(sq, Piece.EMPTY); + pos.setPiece(fromSq, p); + if (res.result == ProbeResult.UNKNOWN) + continue; + int score = 0; + if (res.result == ProbeResult.WMATE) { + score = res.movesToMate; + } else if (res.result == ProbeResult.BMATE) { + score = -res.movesToMate; + } + ret.add(new Pair(sq, score)); + } + return ret; + } +}