From 7ed9d943b31d3ee9c5fb2387e84a241ba33afe90 Mon Sep 17 00:00:00 2001 From: Lasse Collin Date: Wed, 31 Dec 2008 00:30:49 +0200 Subject: Remove lzma_init() and other init functions from liblzma API. Half of developers were already forgetting to use these functions, which could have caused total breakage in some future liblzma version or even now if --enable-small was used. Now liblzma uses pthread_once() to do the initializations unless it has been built with --disable-threads which make these initializations thread-unsafe. When --enable-small isn't used, liblzma currently gets needlessly linked against libpthread (on systems that have it). While it is stupid for now, liblzma will need threads in future anyway, so this stupidity will be temporary only. When --enable-small is used, different code CRC32 and CRC64 is now used than without --enable-small. This made the resulting binary slightly smaller, but the main reason was to clean it up and to handle the lack of lzma_init_check(). The pkg-config file lzma.pc was renamed to liblzma.pc. I'm not sure if it works correctly and portably for static linking (Libs.private includes -pthread or other operating system specific flags). Hopefully someone complains if it is bad. lzma_rc_prices[] is now included as a precomputed array even with --enable-small. It's just 128 bytes now that it uses uint8_t instead of uint32_t. Smaller array seemed to be at least as fast as the more bloated uint32_t array on x86; hopefully it's not bad on other architectures. --- src/liblzma/api/Makefile.am | 1 - src/liblzma/api/lzma.h | 1 - src/liblzma/api/lzma/init.h | 85 ----------------------------- src/liblzma/check/Makefile.am | 29 ++++------ src/liblzma/check/check.c | 10 ++-- src/liblzma/check/check.h | 25 ++++----- src/liblzma/check/check_init.c | 37 ------------- src/liblzma/check/crc32.c | 88 ------------------------------- src/liblzma/check/crc32_fast.c | 88 +++++++++++++++++++++++++++++++ src/liblzma/check/crc32_init.c | 55 ------------------- src/liblzma/check/crc32_small.c | 54 +++++++++++++++++++ src/liblzma/check/crc32_tablegen.c | 55 ++++++++++++++++--- src/liblzma/check/crc64.c | 75 -------------------------- src/liblzma/check/crc64_fast.c | 75 ++++++++++++++++++++++++++ src/liblzma/check/crc64_small.c | 54 +++++++++++++++++++ src/liblzma/check/crc64_tablegen.c | 55 ++++++++++++++++--- src/liblzma/common/Makefile.am | 3 -- src/liblzma/common/common.h | 1 + src/liblzma/common/init.c | 39 -------------- src/liblzma/common/init_decoder.c | 31 ----------- src/liblzma/common/init_encoder.c | 40 -------------- src/liblzma/liblzma.pc.in | 12 +++++ src/liblzma/lz/lz_encoder.c | 6 +++ src/liblzma/lzma.pc.in | 11 ---- src/liblzma/rangecoder/Makefile.am | 8 +-- src/liblzma/rangecoder/price.h | 16 +----- src/liblzma/rangecoder/price_table.c | 2 +- src/liblzma/rangecoder/price_table_init.c | 55 ------------------- src/liblzma/rangecoder/price_tablegen.c | 51 +++++++++++++++--- 29 files changed, 459 insertions(+), 603 deletions(-) delete mode 100644 src/liblzma/api/lzma/init.h delete mode 100644 src/liblzma/check/check_init.c delete mode 100644 src/liblzma/check/crc32.c create mode 100644 src/liblzma/check/crc32_fast.c delete mode 100644 src/liblzma/check/crc32_init.c create mode 100644 src/liblzma/check/crc32_small.c delete mode 100644 src/liblzma/check/crc64.c create mode 100644 src/liblzma/check/crc64_fast.c create mode 100644 src/liblzma/check/crc64_small.c delete mode 100644 src/liblzma/common/init.c delete mode 100644 src/liblzma/common/init_decoder.c delete mode 100644 src/liblzma/common/init_encoder.c create mode 100644 src/liblzma/liblzma.pc.in delete mode 100644 src/liblzma/lzma.pc.in delete mode 100644 src/liblzma/rangecoder/price_table_init.c (limited to 'src/liblzma') diff --git a/src/liblzma/api/Makefile.am b/src/liblzma/api/Makefile.am index c69e7548..f5101f96 100644 --- a/src/liblzma/api/Makefile.am +++ b/src/liblzma/api/Makefile.am @@ -22,7 +22,6 @@ nobase_include_HEADERS = \ lzma/filter.h \ lzma/index.h \ lzma/index_hash.h \ - lzma/init.h \ lzma/lzma.h \ lzma/simple.h \ lzma/stream_flags.h \ diff --git a/src/liblzma/api/lzma.h b/src/liblzma/api/lzma.h index d19687b7..ef7a1086 100644 --- a/src/liblzma/api/lzma.h +++ b/src/liblzma/api/lzma.h @@ -197,7 +197,6 @@ extern "C" { /* Basic features */ #include "lzma/version.h" -#include "lzma/init.h" #include "lzma/base.h" #include "lzma/vli.h" #include "lzma/check.h" diff --git a/src/liblzma/api/lzma/init.h b/src/liblzma/api/lzma/init.h deleted file mode 100644 index 9195e752..00000000 --- a/src/liblzma/api/lzma/init.h +++ /dev/null @@ -1,85 +0,0 @@ -/** - * \file lzma/init.h - * \brief Initializations - * - * \author Copyright (C) 1999-2006 Igor Pavlov - * \author Copyright (C) 2007 Lasse Collin - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - */ - -#ifndef LZMA_H_INTERNAL -# error Never include this file directly. Use instead. -#endif - - -/** - * \brief Initialize all internal static variables - * - * Depending on the build options, liblzma may have some internal static - * variables, that must be initialized before using any other part of - * the library (*). It is recommended to do these initializations in the very - * beginning of the application by calling appropriate initialization function. - * - * (*) There are some exceptions to this rule. FIXME - * - * The initialization functions are not necessarily thread-safe, thus the - * required initializations must be done before creating any threads. (The - * rest of the functions of liblzma are thread-safe.) Calling the - * initialization functions multiple times does no harm, although it - * still shouldn't be done when there are multiple threads running. - * - * lzma_init() initializes all internal static variables by calling - * lzma_init_encoder() and lzma_init_decoder(). - * - * If you need only encoder, decoder, or neither-encoder-nor-decoder - * functions, you may use other initialization functions, which initialize - * only a subset of liblzma's internal static variables. Using those - * functions have the following advantages: - * - When linking statically against liblzma, fewer useless functions will - * get linked into the binary. E.g. if you need only the decoder functions, - * using lzma_init_decoder() avoids linking bunch of encoder related code. - * - There is less things to initialize, making the initialization - * process slightly faster. - */ -extern void lzma_init(void); - - -/** - * \brief Initialize internal static variables needed by encoders - * - * If you need only the encoder functions, you may use this function to - * initialize only the things required by encoders. - * - * This function also calls lzma_init_check(). - */ -extern void lzma_init_encoder(void); - - -/** - * \brief Initialize internal static variables needed by decoders - * - * If you need only the decoder functions, you may use this function to - * initialize only the things required by decoders. - * - * This function also calls lzma_init_check(). - */ -extern void lzma_init_decoder(void); - - -/** - * \brief Initialize internal static variables needed by integrity checks - * - * Currently this initializes CRC32 and CRC64 lookup tables if precalculated - * tables haven't been built into the library. This function can be useful - * if the only thing you need from liblzma is the integrity check functions. - */ -extern void lzma_init_check(void); diff --git a/src/liblzma/check/Makefile.am b/src/liblzma/check/Makefile.am index 182e0868..f323e6fe 100644 --- a/src/liblzma/check/Makefile.am +++ b/src/liblzma/check/Makefile.am @@ -13,46 +13,37 @@ noinst_LTLIBRARIES = libcheck.la libcheck_la_SOURCES = \ check.c \ check.h \ - check_init.c \ crc_macros.h libcheck_la_CPPFLAGS = \ -I@top_srcdir@/src/liblzma/api \ -I@top_srcdir@/src/liblzma/common if COND_CHECK_CRC32 - +if COND_SMALL +libcheck_la_SOURCES += crc32_small.c +else +libcheck_la_SOURCES += crc32_table.c crc32_table_le.h crc32_table_be.h if COND_ASM_X86 libcheck_la_SOURCES += crc32_x86.S else -libcheck_la_SOURCES += crc32.c +libcheck_la_SOURCES += crc32_fast.c endif - -if COND_SMALL -libcheck_la_SOURCES += crc32_init.c -else -libcheck_la_SOURCES += crc32_table.c crc32_table_le.h crc32_table_be.h endif - endif - if COND_CHECK_CRC64 - +if COND_SMALL +libcheck_la_SOURCES += crc64_small.c +else +libcheck_la_SOURCES += crc64_table.c crc64_table_le.h crc64_table_be.h if COND_ASM_X86 libcheck_la_SOURCES += crc64_x86.S else -libcheck_la_SOURCES += crc64.c +libcheck_la_SOURCES += crc64_fast.c endif - -if COND_SMALL -libcheck_la_SOURCES += crc64_init.c -else -libcheck_la_SOURCES += crc64_table.c crc64_table_le.h crc64_table_be.h endif - endif - if COND_CHECK_SHA256 libcheck_la_SOURCES += sha256.c # Hide bogus warning to allow usage of -Werror. If more issues like this diff --git a/src/liblzma/check/check.c b/src/liblzma/check/check.c index ed64fe5c..699647ed 100644 --- a/src/liblzma/check/check.c +++ b/src/liblzma/check/check.c @@ -1,7 +1,7 @@ /////////////////////////////////////////////////////////////////////////////// // /// \file check.c -/// \brief Check sizes +/// \brief Single API to access different integrity checks // // This code has been put into the public domain. // @@ -17,7 +17,7 @@ extern LZMA_API lzma_bool lzma_check_is_supported(lzma_check type) { - if ((unsigned)(type) > LZMA_CHECK_ID_MAX) + if ((unsigned int)(type) > LZMA_CHECK_ID_MAX) return false; static const lzma_bool available_checks[LZMA_CHECK_ID_MAX + 1] = { @@ -57,14 +57,14 @@ lzma_check_is_supported(lzma_check type) false, // Reserved }; - return available_checks[(unsigned)(type)]; + return available_checks[(unsigned int)(type)]; } extern LZMA_API uint32_t lzma_check_size(lzma_check type) { - if ((unsigned)(type) > LZMA_CHECK_ID_MAX) + if ((unsigned int)(type) > LZMA_CHECK_ID_MAX) return UINT32_MAX; // See file-format.txt section 2.1.1.2. @@ -77,7 +77,7 @@ lzma_check_size(lzma_check type) 64, 64, 64 }; - return check_sizes[(unsigned)(type)]; + return check_sizes[(unsigned int)(type)]; } diff --git a/src/liblzma/check/check.h b/src/liblzma/check/check.h index 8f387799..73c6391d 100644 --- a/src/liblzma/check/check.h +++ b/src/liblzma/check/check.h @@ -57,46 +57,39 @@ typedef struct { } lzma_check_state; +/// lzma_crc32_table[0] is needed by LZ encoder so we need to keep +/// the array two-dimensional. #ifdef HAVE_SMALL -extern uint32_t lzma_crc32_table[8][256]; -extern uint64_t lzma_crc64_table[4][256]; +extern uint32_t lzma_crc32_table[1][256]; #else extern const uint32_t lzma_crc32_table[8][256]; extern const uint64_t lzma_crc64_table[4][256]; #endif -/// \brief Initializes *check depending on type +/// \brief Initialize *check depending on type /// /// \return LZMA_OK on success. LZMA_UNSUPPORTED_CHECK if the type is not /// supported by the current version or build of liblzma. /// LZMA_PROG_ERROR if type > LZMA_CHECK_ID_MAX. -/// extern void lzma_check_init(lzma_check_state *check, lzma_check type); - -/// \brief Updates *check -/// +/// Update the check state extern void lzma_check_update(lzma_check_state *check, lzma_check type, const uint8_t *buf, size_t size); - -/// \brief Finishes *check -/// +/// Finish the check calculation and store the result to check->buffer.u8. extern void lzma_check_finish(lzma_check_state *check, lzma_check type); -extern void lzma_crc32_init(void); - - -extern void lzma_crc64_init(void); - - +/// Prepare SHA-256 state for new input. extern void lzma_sha256_init(lzma_check_state *check); +/// Update the SHA-256 hash state extern void lzma_sha256_update( const uint8_t *buf, size_t size, lzma_check_state *check); +/// Finish the SHA-256 calculation and store the result to check->buffer.u8. extern void lzma_sha256_finish(lzma_check_state *check); #endif diff --git a/src/liblzma/check/check_init.c b/src/liblzma/check/check_init.c deleted file mode 100644 index 1b2cfe02..00000000 --- a/src/liblzma/check/check_init.c +++ /dev/null @@ -1,37 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// -/// \file check_init.c -/// \brief Static initializations for integrity checks -// -// This code has been put into the public domain. -// -// This library 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. -// -/////////////////////////////////////////////////////////////////////////////// - -#include "check.h" - - -extern LZMA_API void -lzma_init_check(void) -{ -#ifdef HAVE_SMALL - static bool already_initialized = false; - if (already_initialized) - return; - -# ifdef HAVE_CHECK_CRC32 - lzma_crc32_init(); -# endif - -# ifdef HAVE_CHECK_CRC64 - lzma_crc64_init(); -# endif - - already_initialized = true; -#endif - - return; -} diff --git a/src/liblzma/check/crc32.c b/src/liblzma/check/crc32.c deleted file mode 100644 index 698cf768..00000000 --- a/src/liblzma/check/crc32.c +++ /dev/null @@ -1,88 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// -/// \file crc32.c -/// \brief CRC32 calculation -// -// This code has been put into the public domain. -// -// This library 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. -// -/////////////////////////////////////////////////////////////////////////////// - -#include "check.h" -#include "crc_macros.h" - - -// If you make any changes, do some bench marking! Seemingly unrelated -// changes can very easily ruin the performance (and very probably is -// very compiler dependent). -extern LZMA_API uint32_t -lzma_crc32(const uint8_t *buf, size_t size, uint32_t crc) -{ - crc = ~crc; - -#ifdef WORDS_BIGENDIAN - crc = bswap_32(crc); -#endif - - if (size > 8) { - // Fix the alignment, if needed. The if statement above - // ensures that this won't read past the end of buf[]. - while ((uintptr_t)(buf) & 7) { - crc = lzma_crc32_table[0][*buf++ ^ A(crc)] ^ S8(crc); - --size; - } - - // Calculate the position where to stop. - const uint8_t *const limit = buf + (size & ~(size_t)(7)); - - // Calculate how many bytes must be calculated separately - // before returning the result. - size &= (size_t)(7); - - // Calculate the CRC32 using the slice-by-eight algorithm. - // It is explained in this document: - // http://www.intel.com/technology/comms/perfnet/download/CRC_generators.pdf - // - // The code below is different than the code in Intel's - // paper, but the principle is identical. This should be - // faster with GCC than Intel's code. This is tested only - // with GCC 3.4.6 and 4.1.2 on x86, so your results may vary. - // - // Using -Os and -fomit-frame-pointer seem to give the best - // results at least with GCC 4.1.2 on x86. It's sill far - // from the speed of hand-optimized assembler. - while (buf < limit) { - crc ^= *(uint32_t *)(buf); - buf += 4; - - crc = lzma_crc32_table[7][A(crc)] - ^ lzma_crc32_table[6][B(crc)] - ^ lzma_crc32_table[5][C(crc)] - ^ lzma_crc32_table[4][D(crc)]; - - const uint32_t tmp = *(uint32_t *)(buf); - buf += 4; - - // It is critical for performance, that - // the crc variable is XORed between the - // two table-lookup pairs. - crc = lzma_crc32_table[3][A(tmp)] - ^ lzma_crc32_table[2][B(tmp)] - ^ crc - ^ lzma_crc32_table[1][C(tmp)] - ^ lzma_crc32_table[0][D(tmp)]; - } - } - - while (size-- != 0) - crc = lzma_crc32_table[0][*buf++ ^ A(crc)] ^ S8(crc); - -#ifdef WORDS_BIGENDIAN - crc = bswap_32(crc); -#endif - - return ~crc; -} diff --git a/src/liblzma/check/crc32_fast.c b/src/liblzma/check/crc32_fast.c new file mode 100644 index 00000000..698cf768 --- /dev/null +++ b/src/liblzma/check/crc32_fast.c @@ -0,0 +1,88 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file crc32.c +/// \brief CRC32 calculation +// +// This code has been put into the public domain. +// +// This library 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. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "check.h" +#include "crc_macros.h" + + +// If you make any changes, do some bench marking! Seemingly unrelated +// changes can very easily ruin the performance (and very probably is +// very compiler dependent). +extern LZMA_API uint32_t +lzma_crc32(const uint8_t *buf, size_t size, uint32_t crc) +{ + crc = ~crc; + +#ifdef WORDS_BIGENDIAN + crc = bswap_32(crc); +#endif + + if (size > 8) { + // Fix the alignment, if needed. The if statement above + // ensures that this won't read past the end of buf[]. + while ((uintptr_t)(buf) & 7) { + crc = lzma_crc32_table[0][*buf++ ^ A(crc)] ^ S8(crc); + --size; + } + + // Calculate the position where to stop. + const uint8_t *const limit = buf + (size & ~(size_t)(7)); + + // Calculate how many bytes must be calculated separately + // before returning the result. + size &= (size_t)(7); + + // Calculate the CRC32 using the slice-by-eight algorithm. + // It is explained in this document: + // http://www.intel.com/technology/comms/perfnet/download/CRC_generators.pdf + // + // The code below is different than the code in Intel's + // paper, but the principle is identical. This should be + // faster with GCC than Intel's code. This is tested only + // with GCC 3.4.6 and 4.1.2 on x86, so your results may vary. + // + // Using -Os and -fomit-frame-pointer seem to give the best + // results at least with GCC 4.1.2 on x86. It's sill far + // from the speed of hand-optimized assembler. + while (buf < limit) { + crc ^= *(uint32_t *)(buf); + buf += 4; + + crc = lzma_crc32_table[7][A(crc)] + ^ lzma_crc32_table[6][B(crc)] + ^ lzma_crc32_table[5][C(crc)] + ^ lzma_crc32_table[4][D(crc)]; + + const uint32_t tmp = *(uint32_t *)(buf); + buf += 4; + + // It is critical for performance, that + // the crc variable is XORed between the + // two table-lookup pairs. + crc = lzma_crc32_table[3][A(tmp)] + ^ lzma_crc32_table[2][B(tmp)] + ^ crc + ^ lzma_crc32_table[1][C(tmp)] + ^ lzma_crc32_table[0][D(tmp)]; + } + } + + while (size-- != 0) + crc = lzma_crc32_table[0][*buf++ ^ A(crc)] ^ S8(crc); + +#ifdef WORDS_BIGENDIAN + crc = bswap_32(crc); +#endif + + return ~crc; +} diff --git a/src/liblzma/check/crc32_init.c b/src/liblzma/check/crc32_init.c deleted file mode 100644 index 8b596091..00000000 --- a/src/liblzma/check/crc32_init.c +++ /dev/null @@ -1,55 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// -/// \file crc32_init.c -/// \brief CRC32 table initialization -// -// This code is based on various public domain sources. -// This code has been put into the public domain. -// -// This library 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. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifdef HAVE_CONFIG_H -# include "check.h" -#endif - -#ifdef WORDS_BIGENDIAN -# include "../../common/bswap.h" -#endif - - -uint32_t lzma_crc32_table[8][256]; - - -extern void -lzma_crc32_init(void) -{ - static const uint32_t poly32 = UINT32_C(0xEDB88320); - - for (size_t s = 0; s < 8; ++s) { - for (size_t b = 0; b < 256; ++b) { - uint32_t r = s == 0 ? b : lzma_crc32_table[s - 1][b]; - - for (size_t i = 0; i < 8; ++i) { - if (r & 1) - r = (r >> 1) ^ poly32; - else - r >>= 1; - } - - lzma_crc32_table[s][b] = r; - } - } - -#ifdef WORDS_BIGENDIAN - for (size_t s = 0; s < 8; ++s) - for (size_t b = 0; b < 256; ++b) - lzma_crc32_table[s][b] - = bswap_32(lzma_crc32_table[s][b]); -#endif - - return; -} diff --git a/src/liblzma/check/crc32_small.c b/src/liblzma/check/crc32_small.c new file mode 100644 index 00000000..db26f8d4 --- /dev/null +++ b/src/liblzma/check/crc32_small.c @@ -0,0 +1,54 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file crc32_small.c +/// \brief CRC32 calculation (size-optimized) +// +// This code has been put into the public domain. +// +// This library 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. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "check.h" + + +uint32_t lzma_crc32_table[1][256]; + + +static void +crc32_init(void) +{ + static const uint32_t poly32 = UINT32_C(0xEDB88320); + + for (size_t b = 0; b < 256; ++b) { + uint32_t r = b; + for (size_t i = 0; i < 8; ++i) { + if (r & 1) + r = (r >> 1) ^ poly32; + else + r >>= 1; + } + + lzma_crc32_table[0][b] = r; + } + + return; +} + + +extern LZMA_API uint32_t +lzma_crc32(const uint8_t *buf, size_t size, uint32_t crc) +{ + mythread_once(crc32_init); + + crc = ~crc; + + while (size != 0) { + crc = lzma_crc32_table[0][*buf++ ^ (crc & 0xFF)] ^ (crc >> 8); + --size; + } + + return ~crc; +} diff --git a/src/liblzma/check/crc32_tablegen.c b/src/liblzma/check/crc32_tablegen.c index f793d594..d0c41caa 100644 --- a/src/liblzma/check/crc32_tablegen.c +++ b/src/liblzma/check/crc32_tablegen.c @@ -1,7 +1,7 @@ /////////////////////////////////////////////////////////////////////////////// // /// \file crc32_tablegen.c -/// \brief Generates CRC32 crc32_table.c +/// \brief Generate crc32_table_le.h and crc32_table_be.h /// /// Compiling: gcc -std=c99 -o crc32_tablegen crc32_tablegen.c /// Add -DWORDS_BIGENDIAN to generate big endian table. @@ -14,18 +14,50 @@ // /////////////////////////////////////////////////////////////////////////////// -#include #include #include -#include "crc32_init.c" +#ifdef WORDS_BIGENDIAN +# include "../../common/bswap.h" +#endif -int -main() +static uint32_t crc32_table[8][256]; + + +static void +init_crc32_table(void) { - lzma_crc32_init(); + static const uint32_t poly32 = UINT32_C(0xEDB88320); + + for (size_t s = 0; s < 8; ++s) { + for (size_t b = 0; b < 256; ++b) { + uint32_t r = s == 0 ? b : crc32_table[s - 1][b]; + + for (size_t i = 0; i < 8; ++i) { + if (r & 1) + r = (r >> 1) ^ poly32; + else + r >>= 1; + } + + crc32_table[s][b] = r; + } + } +#ifdef WORDS_BIGENDIAN + for (size_t s = 0; s < 8; ++s) + for (size_t b = 0; b < 256; ++b) + crc32_table[s][b] = bswap_32(crc32_table[s][b]); +#endif + + return; +} + + +static void +print_crc32_table(void) +{ printf("/* This file has been automatically generated by " "crc32_tablegen.c. */\n\n" "const uint32_t lzma_crc32_table[8][256] = {\n\t{"); @@ -35,7 +67,7 @@ main() if ((b % 4) == 0) printf("\n\t\t"); - printf("0x%08" PRIX32, lzma_crc32_table[s][b]); + printf("0x%08" PRIX32, crc32_table[s][b]); if (b != 255) printf(", "); @@ -47,5 +79,14 @@ main() printf("\n\t}, {"); } + return; +} + + +int +main(void) +{ + init_crc32_table(); + print_crc32_table(); return 0; } diff --git a/src/liblzma/check/crc64.c b/src/liblzma/check/crc64.c deleted file mode 100644 index 00fbfd53..00000000 --- a/src/liblzma/check/crc64.c +++ /dev/null @@ -1,75 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// -/// \file crc64.c -/// \brief CRC64 calculation -// -// This code has been put into the public domain. -// -// This library 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. -// -/////////////////////////////////////////////////////////////////////////////// - -#include "check.h" -#include "crc_macros.h" - - -#ifdef WORDS_BIGENDIAN -# define A1(x) ((x) >> 56) -#else -# define A1 A -#endif - - -// See comments in crc32.c. -extern LZMA_API uint64_t -lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc) -{ - crc = ~crc; - -#ifdef WORDS_BIGENDIAN - crc = bswap_64(crc); -#endif - - if (size > 4) { - while ((uintptr_t)(buf) & 3) { - crc = lzma_crc64_table[0][*buf++ ^ A1(crc)] ^ S8(crc); - --size; - } - - const uint8_t *const limit = buf + (size & ~(size_t)(3)); - size &= (size_t)(3); - - // Calculate the CRC64 using the slice-by-four algorithm. - // - // In contrast to CRC32 code, this one seems to be fastest - // with -O3 -fomit-frame-pointer. - while (buf < limit) { -#ifdef WORDS_BIGENDIAN - const uint32_t tmp = (crc >> 32) ^ *(uint32_t *)(buf); -#else - const uint32_t tmp = crc ^ *(uint32_t *)(buf); -#endif - buf += 4; - - // It is critical for performance, that - // the crc variable is XORed between the - // two table-lookup pairs. - crc = lzma_crc64_table[3][A(tmp)] - ^ lzma_crc64_table[2][B(tmp)] - ^ S32(crc) - ^ lzma_crc64_table[1][C(tmp)] - ^ lzma_crc64_table[0][D(tmp)]; - } - } - - while (size-- != 0) - crc = lzma_crc64_table[0][*buf++ ^ A1(crc)] ^ S8(crc); - -#ifdef WORDS_BIGENDIAN - crc = bswap_64(crc); -#endif - - return ~crc; -} diff --git a/src/liblzma/check/crc64_fast.c b/src/liblzma/check/crc64_fast.c new file mode 100644 index 00000000..00fbfd53 --- /dev/null +++ b/src/liblzma/check/crc64_fast.c @@ -0,0 +1,75 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file crc64.c +/// \brief CRC64 calculation +// +// This code has been put into the public domain. +// +// This library 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. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "check.h" +#include "crc_macros.h" + + +#ifdef WORDS_BIGENDIAN +# define A1(x) ((x) >> 56) +#else +# define A1 A +#endif + + +// See comments in crc32.c. +extern LZMA_API uint64_t +lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc) +{ + crc = ~crc; + +#ifdef WORDS_BIGENDIAN + crc = bswap_64(crc); +#endif + + if (size > 4) { + while ((uintptr_t)(buf) & 3) { + crc = lzma_crc64_table[0][*buf++ ^ A1(crc)] ^ S8(crc); + --size; + } + + const uint8_t *const limit = buf + (size & ~(size_t)(3)); + size &= (size_t)(3); + + // Calculate the CRC64 using the slice-by-four algorithm. + // + // In contrast to CRC32 code, this one seems to be fastest + // with -O3 -fomit-frame-pointer. + while (buf < limit) { +#ifdef WORDS_BIGENDIAN + const uint32_t tmp = (crc >> 32) ^ *(uint32_t *)(buf); +#else + const uint32_t tmp = crc ^ *(uint32_t *)(buf); +#endif + buf += 4; + + // It is critical for performance, that + // the crc variable is XORed between the + // two table-lookup pairs. + crc = lzma_crc64_table[3][A(tmp)] + ^ lzma_crc64_table[2][B(tmp)] + ^ S32(crc) + ^ lzma_crc64_table[1][C(tmp)] + ^ lzma_crc64_table[0][D(tmp)]; + } + } + + while (size-- != 0) + crc = lzma_crc64_table[0][*buf++ ^ A1(crc)] ^ S8(crc); + +#ifdef WORDS_BIGENDIAN + crc = bswap_64(crc); +#endif + + return ~crc; +} diff --git a/src/liblzma/check/crc64_small.c b/src/liblzma/check/crc64_small.c new file mode 100644 index 00000000..112bc032 --- /dev/null +++ b/src/liblzma/check/crc64_small.c @@ -0,0 +1,54 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file crc64_small.c +/// \brief CRC64 calculation (size-optimized) +// +// This code has been put into the public domain. +// +// This library 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. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "check.h" + + +static uint64_t crc64_table[256]; + + +static void +crc64_init(void) +{ + static const uint64_t poly64 = UINT64_C(0xC96C5795D7870F42); + + for (size_t b = 0; b < 256; ++b) { + uint64_t r = b; + for (size_t i = 0; i < 8; ++i) { + if (r & 1) + r = (r >> 1) ^ poly64; + else + r >>= 1; + } + + crc64_table[b] = r; + } + + return; +} + + +extern LZMA_API uint64_t +lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc) +{ + mythread_once(crc64_init); + + crc = ~crc; + + while (size != 0) { + crc = crc64_table[*buf++ ^ (crc & 0xFF)] ^ (crc >> 8); + --size; + } + + return ~crc; +} diff --git a/src/liblzma/check/crc64_tablegen.c b/src/liblzma/check/crc64_tablegen.c index 78e39068..b20086f8 100644 --- a/src/liblzma/check/crc64_tablegen.c +++ b/src/liblzma/check/crc64_tablegen.c @@ -1,7 +1,7 @@ /////////////////////////////////////////////////////////////////////////////// // /// \file crc64_tablegen.c -/// \brief Generates CRC64 crc64_table.c +/// \brief Generate crc64_table_le.h and crc64_table_be.h /// /// Compiling: gcc -std=c99 -o crc64_tablegen crc64_tablegen.c /// Add -DWORDS_BIGENDIAN to generate big endian table. @@ -14,18 +14,50 @@ // /////////////////////////////////////////////////////////////////////////////// -#include #include #include -#include "crc64_init.c" +#ifdef WORDS_BIGENDIAN +# include "../../common/bswap.h" +#endif -int -main() +static uint64_t crc64_table[4][256]; + + +extern void +init_crc64_table(void) { - lzma_crc64_init(); + static const uint64_t poly64 = UINT64_C(0xC96C5795D7870F42); + + for (size_t s = 0; s < 4; ++s) { + for (size_t b = 0; b < 256; ++b) { + uint64_t r = s == 0 ? b : crc64_table[s - 1][b]; + + for (size_t i = 0; i < 8; ++i) { + if (r & 1) + r = (r >> 1) ^ poly64; + else + r >>= 1; + } + + crc64_table[s][b] = r; + } + } +#ifdef WORDS_BIGENDIAN + for (size_t s = 0; s < 4; ++s) + for (size_t b = 0; b < 256; ++b) + crc64_table[s][b] = bswap_64(crc64_table[s][b]); +#endif + + return; +} + + +static void +print_crc64_table(void) +{ printf("/* This file has been automatically generated by " "crc64_tablegen.c. */\n\n" "const uint64_t lzma_crc64_table[4][256] = {\n\t{"); @@ -36,7 +68,7 @@ main() printf("\n\t\t"); printf("UINT64_C(0x%016" PRIX64 ")", - lzma_crc64_table[s][b]); + crc64_table[s][b]); if (b != 255) printf(", "); @@ -48,5 +80,14 @@ main() printf("\n\t}, {"); } + return; +} + + +int +main(void) +{ + init_crc64_table(); + print_crc64_table(); return 0; } diff --git a/src/liblzma/common/Makefile.am b/src/liblzma/common/Makefile.am index 20f3f93b..f64abdf5 100644 --- a/src/liblzma/common/Makefile.am +++ b/src/liblzma/common/Makefile.am @@ -32,7 +32,6 @@ libcommon_la_SOURCES = \ filter_common.h \ index.c \ index.h \ - init.c \ stream_flags_common.c \ stream_flags_common.h \ vli_size.c @@ -49,7 +48,6 @@ libcommon_la_SOURCES += \ filter_flags_encoder.c \ index_encoder.c \ index_encoder.h \ - init_encoder.c \ stream_encoder.c \ stream_encoder.h \ stream_flags_encoder.c \ @@ -69,7 +67,6 @@ libcommon_la_SOURCES += \ filter_flags_decoder.c \ index_decoder.c \ index_hash.c \ - init_decoder.c \ stream_decoder.c \ stream_decoder.h \ stream_flags_decoder.c \ diff --git a/src/liblzma/common/common.h b/src/liblzma/common/common.h index ef8d0cbf..44117c9a 100644 --- a/src/liblzma/common/common.h +++ b/src/liblzma/common/common.h @@ -21,6 +21,7 @@ #define LZMA_COMMON_H #include "../../common/sysdefs.h" +#include "../../common/mythread.h" #include "../../common/integer.h" // Don't use ifdef... diff --git a/src/liblzma/common/init.c b/src/liblzma/common/init.c deleted file mode 100644 index fb377f5a..00000000 --- a/src/liblzma/common/init.c +++ /dev/null @@ -1,39 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// -/// \file init.c -/// \brief Static internal initializations -/// -/// The initializations have been splitted to so many small files to prevent -/// an application needing only decoder functions from statically linking -/// also the encoder functions. -// -// Copyright (C) 2007 Lasse Collin -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library 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 -// Lesser General Public License for more details. -// -/////////////////////////////////////////////////////////////////////////////// - -#include "common.h" - - -extern LZMA_API void -lzma_init(void) -{ -#ifdef HAVE_ENCODER - lzma_init_encoder(); -#endif - -#ifdef HAVE_DECODER - lzma_init_decoder(); -#endif - - return; -} diff --git a/src/liblzma/common/init_decoder.c b/src/liblzma/common/init_decoder.c deleted file mode 100644 index e319b2f8..00000000 --- a/src/liblzma/common/init_decoder.c +++ /dev/null @@ -1,31 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// -/// \file init_decoder.c -/// \brief Static internal initializations -// -// Copyright (C) 2007 Lasse Collin -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library 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 -// Lesser General Public License for more details. -// -/////////////////////////////////////////////////////////////////////////////// - -#include "common.h" - - -extern LZMA_API void -lzma_init_decoder(void) -{ - // So far there's no decoder-specific stuff to initialize. - - lzma_init_check(); - - return; -} diff --git a/src/liblzma/common/init_encoder.c b/src/liblzma/common/init_encoder.c deleted file mode 100644 index 1130e6b8..00000000 --- a/src/liblzma/common/init_encoder.c +++ /dev/null @@ -1,40 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// -/// \file init_encoder.c -/// \brief Static internal initializations -// -// Copyright (C) 2007 Lasse Collin -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library 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 -// Lesser General Public License for more details. -// -/////////////////////////////////////////////////////////////////////////////// - -#include "common.h" -#include "range_encoder.h" -#include "lzma_encoder.h" - - -extern LZMA_API void -lzma_init_encoder(void) -{ - static bool already_initialized = false; - if (already_initialized) - return; - - lzma_init_check(); - -#if defined(HAVE_SMALL) && defined(HAVE_ENCODER_LZMA1) - lzma_rc_init(); -#endif - - already_initialized = true; - return; -} diff --git a/src/liblzma/liblzma.pc.in b/src/liblzma/liblzma.pc.in new file mode 100644 index 00000000..e192352f --- /dev/null +++ b/src/liblzma/liblzma.pc.in @@ -0,0 +1,12 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: liblzma +Description: General purporse data compression library +URL: http://tukaani.org/xz/ +Version: @PACKAGE_VERSION@ +Cflags: -I${includedir} +Libs: -L${libdir} -llzma +Libs.private: @PTHREAD_CFLAGS@ @PTHREAD_LIBS@ diff --git a/src/liblzma/lz/lz_encoder.c b/src/liblzma/lz/lz_encoder.c index d598f71a..7bd6d03e 100644 --- a/src/liblzma/lz/lz_encoder.c +++ b/src/liblzma/lz/lz_encoder.c @@ -472,6 +472,12 @@ lzma_lz_encoder_init(lzma_next_coder *next, lzma_allocator *allocator, lzma_allocator *allocator, const void *options, lzma_lz_options *lz_options)) { +#ifdef HAVE_SMALL + // We need that the CRC32 table has been initialized. + // This is enough to do it. + lzma_crc32(NULL, 0, 0); +#endif + // Allocate and initialize the base data structure. if (next->coder == NULL) { next->coder = lzma_alloc(sizeof(lzma_coder), allocator); diff --git a/src/liblzma/lzma.pc.in b/src/liblzma/lzma.pc.in deleted file mode 100644 index 5bf9bb10..00000000 --- a/src/liblzma/lzma.pc.in +++ /dev/null @@ -1,11 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: liblzma -Description: LZMA compression library -URL: http://tukaani.org/lzma/ -Version: @PACKAGE_VERSION@ -Cflags: -I${includedir} -Libs: -L${libdir} -llzma diff --git a/src/liblzma/rangecoder/Makefile.am b/src/liblzma/rangecoder/Makefile.am index b2e62d4a..a202e34e 100644 --- a/src/liblzma/rangecoder/Makefile.am +++ b/src/liblzma/rangecoder/Makefile.am @@ -24,12 +24,8 @@ librangecoder_la_CPPFLAGS = \ if COND_ENCODER_LZMA1 librangecoder_la_SOURCES += \ range_encoder.h \ - price.h -if COND_SMALL -librangecoder_la_SOURCES += price_table_init.c -else -librangecoder_la_SOURCES += price_table.c -endif + price.h \ + price_table.c endif if COND_DECODER_LZMA1 diff --git a/src/liblzma/rangecoder/price.h b/src/liblzma/rangecoder/price.h index 001f753d..e336885c 100644 --- a/src/liblzma/rangecoder/price.h +++ b/src/liblzma/rangecoder/price.h @@ -28,20 +28,8 @@ #define RC_INFINITY_PRICE (UINT32_C(1) << 30) -#if !defined(LZMA_RANGE_ENCODER_H) || defined(HAVE_SMALL) -/// Probability prices used by *_get_price() macros. This is initialized -/// by lzma_rc_init() and is not modified later. -extern uint32_t lzma_rc_prices[RC_PRICE_TABLE_SIZE]; - -/// Initializes lzma_rc_prices[]. This needs to be called only once. -extern void lzma_rc_init(void); - -#else -// Not building a size optimized version, so we use a precomputed -// constant table. -extern const uint32_t lzma_rc_prices[RC_PRICE_TABLE_SIZE]; - -#endif +/// Lookup table for the inline functions defined in this file. +extern const uint8_t lzma_rc_prices[RC_PRICE_TABLE_SIZE]; static inline uint32_t diff --git a/src/liblzma/rangecoder/price_table.c b/src/liblzma/rangecoder/price_table.c index 539206b1..ac64bf62 100644 --- a/src/liblzma/rangecoder/price_table.c +++ b/src/liblzma/rangecoder/price_table.c @@ -2,7 +2,7 @@ #include "range_encoder.h" -const uint32_t lzma_rc_prices[RC_PRICE_TABLE_SIZE] = { +const uint8_t lzma_rc_prices[RC_PRICE_TABLE_SIZE] = { 128, 103, 91, 84, 78, 73, 69, 66, 63, 61, 58, 56, 54, 52, 51, 49, 48, 46, 45, 44, 43, 42, 41, 40, diff --git a/src/liblzma/rangecoder/price_table_init.c b/src/liblzma/rangecoder/price_table_init.c deleted file mode 100644 index 9c7d799b..00000000 --- a/src/liblzma/rangecoder/price_table_init.c +++ /dev/null @@ -1,55 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// -/// \file price_table_init.c -/// \brief Static initializations for the range encoder's prices array -// -// Copyright (C) 1999-2006 Igor Pavlov -// Copyright (C) 2007 Lasse Collin -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library 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 -// Lesser General Public License for more details. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifdef HAVE_CONFIG_H -# include "range_encoder.h" -#endif - - -uint32_t lzma_rc_prices[RC_PRICE_TABLE_SIZE]; - - -extern void -lzma_rc_init(void) -{ - for (uint32_t i = (UINT32_C(1) << RC_MOVE_REDUCING_BITS) / 2; - i < RC_BIT_MODEL_TOTAL; - i += (UINT32_C(1) << RC_MOVE_REDUCING_BITS)) { - const uint32_t cycles_bits = RC_BIT_PRICE_SHIFT_BITS; - uint32_t w = i; - uint32_t bit_count = 0; - - for (uint32_t j = 0; j < cycles_bits; ++j) { - w *= w; - bit_count <<= 1; - - while (w >= (UINT32_C(1) << 16)) { - w >>= 1; - ++bit_count; - } - } - - lzma_rc_prices[i >> RC_MOVE_REDUCING_BITS] - = (RC_BIT_MODEL_TOTAL_BITS << cycles_bits) - - 15 - bit_count; - } - - return; -} diff --git a/src/liblzma/rangecoder/price_tablegen.c b/src/liblzma/rangecoder/price_tablegen.c index 68513635..4895ac76 100644 --- a/src/liblzma/rangecoder/price_tablegen.c +++ b/src/liblzma/rangecoder/price_tablegen.c @@ -19,23 +19,51 @@ // /////////////////////////////////////////////////////////////////////////////// -#include #include #include #include "range_common.h" #include "price.h" -#include "price_table_init.c" -int -main(void) +static uint32_t rc_prices[RC_PRICE_TABLE_SIZE]; + + +static void +init_price_table(void) { - lzma_rc_init(); + for (uint32_t i = (UINT32_C(1) << RC_MOVE_REDUCING_BITS) / 2; + i < RC_BIT_MODEL_TOTAL; + i += (UINT32_C(1) << RC_MOVE_REDUCING_BITS)) { + const uint32_t cycles_bits = RC_BIT_PRICE_SHIFT_BITS; + uint32_t w = i; + uint32_t bit_count = 0; + + for (uint32_t j = 0; j < cycles_bits; ++j) { + w *= w; + bit_count <<= 1; + + while (w >= (UINT32_C(1) << 16)) { + w >>= 1; + ++bit_count; + } + } + + rc_prices[i >> RC_MOVE_REDUCING_BITS] + = (RC_BIT_MODEL_TOTAL_BITS << cycles_bits) + - 15 - bit_count; + } + + return; +} + +static void +print_price_table(void) +{ printf("/* This file has been automatically generated by " "price_tablegen.c. */\n\n" "#include \"range_encoder.h\"\n\n" - "const uint32_t lzma_rc_prices[" + "const uint8_t lzma_rc_prices[" "RC_PRICE_TABLE_SIZE] = {"); const size_t array_size = sizeof(lzma_rc_prices) @@ -44,7 +72,7 @@ main(void) if (i % 8 == 0) printf("\n\t"); - printf("%4" PRIu32, lzma_rc_prices[i]); + printf("%4" PRIu32, rc_prices[i]); if (i != array_size - 1) printf(","); @@ -52,5 +80,14 @@ main(void) printf("\n};\n"); + return; +} + + +int +main(void) +{ + init_price_table(); + print_price_table(); return 0; } -- cgit v1.2.3