zstdlib 0.7.0-x64-mingw32 → 0.10.0-x64-mingw32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGES.md +20 -0
- data/README.md +7 -1
- data/Rakefile +38 -8
- data/ext/{zstdlib → zstdlib_c}/extconf.rb +11 -6
- data/ext/{zstdlib → zstdlib_c}/ruby/zlib-2.2/zstdlib.c +2 -2
- data/ext/{zstdlib → zstdlib_c}/ruby/zlib-2.3/zstdlib.c +2 -2
- data/ext/{zstdlib → zstdlib_c}/ruby/zlib-2.4/zstdlib.c +2 -2
- data/ext/{zstdlib → zstdlib_c}/ruby/zlib-2.5/zstdlib.c +2 -2
- data/ext/{zstdlib → zstdlib_c}/ruby/zlib-2.6/zstdlib.c +2 -2
- data/ext/{zstdlib → zstdlib_c}/ruby/zlib-2.7/zstdlib.c +2 -2
- data/ext/zstdlib_c/ruby/zlib-3.0/zstdlib.c +4994 -0
- data/ext/zstdlib_c/ruby/zlib-3.1/zstdlib.c +5076 -0
- data/ext/{zstdlib/zlib-1.2.11 → zstdlib_c/zlib-1.2.12}/adler32.c +0 -0
- data/ext/{zstdlib/zlib-1.2.11 → zstdlib_c/zlib-1.2.12}/compress.c +0 -0
- data/ext/zstdlib_c/zlib-1.2.12/crc32.c +1116 -0
- data/ext/zstdlib_c/zlib-1.2.12/crc32.h +9446 -0
- data/ext/{zstdlib/zlib-1.2.11 → zstdlib_c/zlib-1.2.12}/deflate.c +78 -30
- data/ext/{zstdlib/zlib-1.2.11 → zstdlib_c/zlib-1.2.12}/deflate.h +12 -15
- data/ext/{zstdlib/zlib-1.2.11 → zstdlib_c/zlib-1.2.12}/gzclose.c +0 -0
- data/ext/{zstdlib/zlib-1.2.11 → zstdlib_c/zlib-1.2.12}/gzguts.h +3 -2
- data/ext/{zstdlib/zlib-1.2.11 → zstdlib_c/zlib-1.2.12}/gzlib.c +5 -3
- data/ext/{zstdlib/zlib-1.2.11 → zstdlib_c/zlib-1.2.12}/gzread.c +5 -7
- data/ext/{zstdlib/zlib-1.2.11 → zstdlib_c/zlib-1.2.12}/gzwrite.c +25 -13
- data/ext/{zstdlib/zlib-1.2.11 → zstdlib_c/zlib-1.2.12}/infback.c +2 -1
- data/ext/{zstdlib/zlib-1.2.11 → zstdlib_c/zlib-1.2.12}/inffast.c +14 -14
- data/ext/{zstdlib/zlib-1.2.11 → zstdlib_c/zlib-1.2.12}/inffast.h +0 -0
- data/ext/{zstdlib/zlib-1.2.11 → zstdlib_c/zlib-1.2.12}/inffixed.h +0 -0
- data/ext/{zstdlib/zlib-1.2.11 → zstdlib_c/zlib-1.2.12}/inflate.c +39 -8
- data/ext/{zstdlib/zlib-1.2.11 → zstdlib_c/zlib-1.2.12}/inflate.h +3 -2
- data/ext/{zstdlib/zlib-1.2.11 → zstdlib_c/zlib-1.2.12}/inftrees.c +3 -3
- data/ext/{zstdlib/zlib-1.2.11 → zstdlib_c/zlib-1.2.12}/inftrees.h +0 -0
- data/ext/{zstdlib/zlib-1.2.11 → zstdlib_c/zlib-1.2.12}/trees.c +27 -48
- data/ext/{zstdlib/zlib-1.2.11 → zstdlib_c/zlib-1.2.12}/trees.h +0 -0
- data/ext/{zstdlib/zlib-1.2.11 → zstdlib_c/zlib-1.2.12}/uncompr.c +0 -0
- data/ext/{zstdlib/zlib-1.2.11 → zstdlib_c/zlib-1.2.12}/zconf.h +0 -0
- data/ext/{zstdlib/zlib-1.2.11 → zstdlib_c/zlib-1.2.12}/zlib.h +123 -100
- data/ext/{zstdlib/zlib-1.2.11 → zstdlib_c/zlib-1.2.12}/zutil.c +2 -2
- data/ext/{zstdlib/zlib-1.2.11 → zstdlib_c/zlib-1.2.12}/zutil.h +12 -9
- data/ext/{zstdlib → zstdlib_c}/zlib.mk +0 -0
- data/ext/{zstdlib → zstdlib_c}/zlibwrapper/zlibwrapper.c +1 -5
- data/ext/{zstdlib → zstdlib_c}/zlibwrapper.mk +0 -0
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/common/bitstream.h +46 -22
- data/ext/zstdlib_c/zstd-1.5.2/lib/common/compiler.h +335 -0
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/common/cpu.h +1 -3
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/common/debug.c +1 -1
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/common/debug.h +12 -19
- data/ext/zstdlib_c/zstd-1.5.2/lib/common/entropy_common.c +368 -0
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/common/error_private.c +2 -1
- data/ext/zstdlib_c/zstd-1.5.2/lib/common/error_private.h +159 -0
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/common/fse.h +41 -12
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/common/fse_decompress.c +139 -22
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/common/huf.h +47 -23
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/common/mem.h +87 -98
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/common/pool.c +34 -23
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/common/pool.h +4 -4
- data/ext/zstdlib_c/zstd-1.5.2/lib/common/portability_macros.h +137 -0
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/common/threading.c +6 -5
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/common/threading.h +0 -0
- data/ext/zstdlib_c/zstd-1.5.2/lib/common/xxhash.c +24 -0
- data/ext/zstdlib_c/zstd-1.5.2/lib/common/xxhash.h +5686 -0
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/common/zstd_common.c +10 -10
- data/ext/zstdlib_c/zstd-1.5.2/lib/common/zstd_deps.h +111 -0
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/common/zstd_internal.h +191 -145
- data/ext/zstdlib_c/zstd-1.5.2/lib/common/zstd_trace.h +163 -0
- data/ext/zstdlib_c/zstd-1.5.2/lib/compress/clevels.h +134 -0
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/compress/fse_compress.c +89 -46
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/compress/hist.c +27 -29
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/compress/hist.h +2 -2
- data/ext/zstdlib_c/zstd-1.5.2/lib/compress/huf_compress.c +1370 -0
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/compress/zstd_compress.c +2917 -868
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/compress/zstd_compress_internal.h +458 -125
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/compress/zstd_compress_literals.c +12 -11
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/compress/zstd_compress_literals.h +4 -2
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/compress/zstd_compress_sequences.c +41 -18
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/compress/zstd_compress_sequences.h +1 -1
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/compress/zstd_compress_superblock.c +26 -298
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/compress/zstd_compress_superblock.h +1 -1
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/compress/zstd_cwksp.h +234 -83
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/compress/zstd_double_fast.c +313 -138
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/compress/zstd_double_fast.h +1 -1
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/compress/zstd_fast.c +329 -150
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/compress/zstd_fast.h +1 -1
- data/ext/zstdlib_c/zstd-1.5.2/lib/compress/zstd_lazy.c +2104 -0
- data/ext/zstdlib_c/zstd-1.5.2/lib/compress/zstd_lazy.h +125 -0
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/compress/zstd_ldm.c +321 -216
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/compress/zstd_ldm.h +9 -2
- data/ext/zstdlib_c/zstd-1.5.2/lib/compress/zstd_ldm_geartab.h +106 -0
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/compress/zstd_opt.c +412 -166
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/compress/zstd_opt.h +1 -1
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/compress/zstdmt_compress.c +169 -453
- data/ext/zstdlib_c/zstd-1.5.2/lib/compress/zstdmt_compress.h +113 -0
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/decompress/huf_decompress.c +1044 -403
- data/ext/zstdlib_c/zstd-1.5.2/lib/decompress/huf_decompress_amd64.S +585 -0
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/decompress/zstd_ddict.c +9 -9
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/decompress/zstd_ddict.h +2 -2
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/decompress/zstd_decompress.c +450 -105
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/decompress/zstd_decompress_block.c +913 -273
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/decompress/zstd_decompress_block.h +14 -5
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/decompress/zstd_decompress_internal.h +59 -12
- data/ext/zstdlib_c/zstd-1.5.2/lib/zdict.h +452 -0
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/lib/zstd.h +699 -214
- data/ext/{zstdlib/zstd-1.4.5/lib/common → zstdlib_c/zstd-1.5.2/lib}/zstd_errors.h +2 -1
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/zlibWrapper/gzclose.c +0 -0
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/zlibWrapper/gzcompatibility.h +1 -1
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/zlibWrapper/gzguts.h +0 -0
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/zlibWrapper/gzlib.c +0 -0
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/zlibWrapper/gzread.c +0 -0
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/zlibWrapper/gzwrite.c +0 -0
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/zlibWrapper/zstd_zlibwrapper.c +133 -44
- data/ext/{zstdlib/zstd-1.4.5 → zstdlib_c/zstd-1.5.2}/zlibWrapper/zstd_zlibwrapper.h +1 -1
- data/ext/zstdlib_c/zstd.mk +15 -0
- data/lib/2.4/zstdlib_c.so +0 -0
- data/lib/2.5/zstdlib_c.so +0 -0
- data/lib/2.6/zstdlib_c.so +0 -0
- data/lib/2.7/zstdlib_c.so +0 -0
- data/lib/3.0/zstdlib_c.so +0 -0
- data/lib/zstdlib.rb +2 -2
- metadata +124 -116
- data/ext/zstdlib/zlib-1.2.11/crc32.c +0 -442
- data/ext/zstdlib/zlib-1.2.11/crc32.h +0 -441
- data/ext/zstdlib/zstd-1.4.5/lib/common/compiler.h +0 -175
- data/ext/zstdlib/zstd-1.4.5/lib/common/entropy_common.c +0 -216
- data/ext/zstdlib/zstd-1.4.5/lib/common/error_private.h +0 -80
- data/ext/zstdlib/zstd-1.4.5/lib/common/xxhash.c +0 -864
- data/ext/zstdlib/zstd-1.4.5/lib/common/xxhash.h +0 -285
- data/ext/zstdlib/zstd-1.4.5/lib/compress/huf_compress.c +0 -798
- data/ext/zstdlib/zstd-1.4.5/lib/compress/zstd_lazy.c +0 -1138
- data/ext/zstdlib/zstd-1.4.5/lib/compress/zstd_lazy.h +0 -67
- data/ext/zstdlib/zstd-1.4.5/lib/compress/zstdmt_compress.h +0 -192
- data/ext/zstdlib/zstd.mk +0 -14
- data/lib/2.2/zstdlib.so +0 -0
- data/lib/2.3/zstdlib.so +0 -0
- data/lib/2.4/zstdlib.so +0 -0
- data/lib/2.5/zstdlib.so +0 -0
- data/lib/2.6/zstdlib.so +0 -0
- data/lib/2.7/zstdlib.so +0 -0
| @@ -1,5 +1,5 @@ | |
| 1 1 | 
             
            /*
         | 
| 2 | 
            -
             * Copyright (c)  | 
| 2 | 
            +
             * Copyright (c) Yann Collet, Facebook, Inc.
         | 
| 3 3 | 
             
             * All rights reserved.
         | 
| 4 4 | 
             
             *
         | 
| 5 5 | 
             
             * This source code is licensed under both the BSD-style license (found in the
         | 
| @@ -11,13 +11,126 @@ | |
| 11 11 | 
             
            #include "zstd_ldm.h"
         | 
| 12 12 |  | 
| 13 13 | 
             
            #include "../common/debug.h"
         | 
| 14 | 
            +
            #include "../common/xxhash.h"
         | 
| 14 15 | 
             
            #include "zstd_fast.h"          /* ZSTD_fillHashTable() */
         | 
| 15 16 | 
             
            #include "zstd_double_fast.h"   /* ZSTD_fillDoubleHashTable() */
         | 
| 17 | 
            +
            #include "zstd_ldm_geartab.h"
         | 
| 16 18 |  | 
| 17 19 | 
             
            #define LDM_BUCKET_SIZE_LOG 3
         | 
| 18 20 | 
             
            #define LDM_MIN_MATCH_LENGTH 64
         | 
| 19 21 | 
             
            #define LDM_HASH_RLOG 7
         | 
| 20 | 
            -
             | 
| 22 | 
            +
             | 
| 23 | 
            +
            typedef struct {
         | 
| 24 | 
            +
                U64 rolling;
         | 
| 25 | 
            +
                U64 stopMask;
         | 
| 26 | 
            +
            } ldmRollingHashState_t;
         | 
| 27 | 
            +
             | 
| 28 | 
            +
            /** ZSTD_ldm_gear_init():
         | 
| 29 | 
            +
             *
         | 
| 30 | 
            +
             * Initializes the rolling hash state such that it will honor the
         | 
| 31 | 
            +
             * settings in params. */
         | 
| 32 | 
            +
            static void ZSTD_ldm_gear_init(ldmRollingHashState_t* state, ldmParams_t const* params)
         | 
| 33 | 
            +
            {
         | 
| 34 | 
            +
                unsigned maxBitsInMask = MIN(params->minMatchLength, 64);
         | 
| 35 | 
            +
                unsigned hashRateLog = params->hashRateLog;
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                state->rolling = ~(U32)0;
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                /* The choice of the splitting criterion is subject to two conditions:
         | 
| 40 | 
            +
                 *   1. it has to trigger on average every 2^(hashRateLog) bytes;
         | 
| 41 | 
            +
                 *   2. ideally, it has to depend on a window of minMatchLength bytes.
         | 
| 42 | 
            +
                 *
         | 
| 43 | 
            +
                 * In the gear hash algorithm, bit n depends on the last n bytes;
         | 
| 44 | 
            +
                 * so in order to obtain a good quality splitting criterion it is
         | 
| 45 | 
            +
                 * preferable to use bits with high weight.
         | 
| 46 | 
            +
                 *
         | 
| 47 | 
            +
                 * To match condition 1 we use a mask with hashRateLog bits set
         | 
| 48 | 
            +
                 * and, because of the previous remark, we make sure these bits
         | 
| 49 | 
            +
                 * have the highest possible weight while still respecting
         | 
| 50 | 
            +
                 * condition 2.
         | 
| 51 | 
            +
                 */
         | 
| 52 | 
            +
                if (hashRateLog > 0 && hashRateLog <= maxBitsInMask) {
         | 
| 53 | 
            +
                    state->stopMask = (((U64)1 << hashRateLog) - 1) << (maxBitsInMask - hashRateLog);
         | 
| 54 | 
            +
                } else {
         | 
| 55 | 
            +
                    /* In this degenerate case we simply honor the hash rate. */
         | 
| 56 | 
            +
                    state->stopMask = ((U64)1 << hashRateLog) - 1;
         | 
| 57 | 
            +
                }
         | 
| 58 | 
            +
            }
         | 
| 59 | 
            +
             | 
| 60 | 
            +
            /** ZSTD_ldm_gear_reset()
         | 
| 61 | 
            +
             * Feeds [data, data + minMatchLength) into the hash without registering any
         | 
| 62 | 
            +
             * splits. This effectively resets the hash state. This is used when skipping
         | 
| 63 | 
            +
             * over data, either at the beginning of a block, or skipping sections.
         | 
| 64 | 
            +
             */
         | 
| 65 | 
            +
            static void ZSTD_ldm_gear_reset(ldmRollingHashState_t* state,
         | 
| 66 | 
            +
                                            BYTE const* data, size_t minMatchLength)
         | 
| 67 | 
            +
            {
         | 
| 68 | 
            +
                U64 hash = state->rolling;
         | 
| 69 | 
            +
                size_t n = 0;
         | 
| 70 | 
            +
             | 
| 71 | 
            +
            #define GEAR_ITER_ONCE() do {                                  \
         | 
| 72 | 
            +
                    hash = (hash << 1) + ZSTD_ldm_gearTab[data[n] & 0xff]; \
         | 
| 73 | 
            +
                    n += 1;                                                \
         | 
| 74 | 
            +
                } while (0)
         | 
| 75 | 
            +
                while (n + 3 < minMatchLength) {
         | 
| 76 | 
            +
                    GEAR_ITER_ONCE();
         | 
| 77 | 
            +
                    GEAR_ITER_ONCE();
         | 
| 78 | 
            +
                    GEAR_ITER_ONCE();
         | 
| 79 | 
            +
                    GEAR_ITER_ONCE();
         | 
| 80 | 
            +
                }
         | 
| 81 | 
            +
                while (n < minMatchLength) {
         | 
| 82 | 
            +
                    GEAR_ITER_ONCE();
         | 
| 83 | 
            +
                }
         | 
| 84 | 
            +
            #undef GEAR_ITER_ONCE
         | 
| 85 | 
            +
            }
         | 
| 86 | 
            +
             | 
| 87 | 
            +
            /** ZSTD_ldm_gear_feed():
         | 
| 88 | 
            +
             *
         | 
| 89 | 
            +
             * Registers in the splits array all the split points found in the first
         | 
| 90 | 
            +
             * size bytes following the data pointer. This function terminates when
         | 
| 91 | 
            +
             * either all the data has been processed or LDM_BATCH_SIZE splits are
         | 
| 92 | 
            +
             * present in the splits array.
         | 
| 93 | 
            +
             *
         | 
| 94 | 
            +
             * Precondition: The splits array must not be full.
         | 
| 95 | 
            +
             * Returns: The number of bytes processed. */
         | 
| 96 | 
            +
            static size_t ZSTD_ldm_gear_feed(ldmRollingHashState_t* state,
         | 
| 97 | 
            +
                                             BYTE const* data, size_t size,
         | 
| 98 | 
            +
                                             size_t* splits, unsigned* numSplits)
         | 
| 99 | 
            +
            {
         | 
| 100 | 
            +
                size_t n;
         | 
| 101 | 
            +
                U64 hash, mask;
         | 
| 102 | 
            +
             | 
| 103 | 
            +
                hash = state->rolling;
         | 
| 104 | 
            +
                mask = state->stopMask;
         | 
| 105 | 
            +
                n = 0;
         | 
| 106 | 
            +
             | 
| 107 | 
            +
            #define GEAR_ITER_ONCE() do { \
         | 
| 108 | 
            +
                    hash = (hash << 1) + ZSTD_ldm_gearTab[data[n] & 0xff]; \
         | 
| 109 | 
            +
                    n += 1; \
         | 
| 110 | 
            +
                    if (UNLIKELY((hash & mask) == 0)) { \
         | 
| 111 | 
            +
                        splits[*numSplits] = n; \
         | 
| 112 | 
            +
                        *numSplits += 1; \
         | 
| 113 | 
            +
                        if (*numSplits == LDM_BATCH_SIZE) \
         | 
| 114 | 
            +
                            goto done; \
         | 
| 115 | 
            +
                    } \
         | 
| 116 | 
            +
                } while (0)
         | 
| 117 | 
            +
             | 
| 118 | 
            +
                while (n + 3 < size) {
         | 
| 119 | 
            +
                    GEAR_ITER_ONCE();
         | 
| 120 | 
            +
                    GEAR_ITER_ONCE();
         | 
| 121 | 
            +
                    GEAR_ITER_ONCE();
         | 
| 122 | 
            +
                    GEAR_ITER_ONCE();
         | 
| 123 | 
            +
                }
         | 
| 124 | 
            +
                while (n < size) {
         | 
| 125 | 
            +
                    GEAR_ITER_ONCE();
         | 
| 126 | 
            +
                }
         | 
| 127 | 
            +
             | 
| 128 | 
            +
            #undef GEAR_ITER_ONCE
         | 
| 129 | 
            +
             | 
| 130 | 
            +
            done:
         | 
| 131 | 
            +
                state->rolling = hash;
         | 
| 132 | 
            +
                return n;
         | 
| 133 | 
            +
            }
         | 
| 21 134 |  | 
| 22 135 | 
             
            void ZSTD_ldm_adjustParameters(ldmParams_t* params,
         | 
| 23 136 | 
             
                                           ZSTD_compressionParameters const* cParams)
         | 
| @@ -27,13 +140,6 @@ void ZSTD_ldm_adjustParameters(ldmParams_t* params, | |
| 27 140 | 
             
                DEBUGLOG(4, "ZSTD_ldm_adjustParameters");
         | 
| 28 141 | 
             
                if (!params->bucketSizeLog) params->bucketSizeLog = LDM_BUCKET_SIZE_LOG;
         | 
| 29 142 | 
             
                if (!params->minMatchLength) params->minMatchLength = LDM_MIN_MATCH_LENGTH;
         | 
| 30 | 
            -
                if (cParams->strategy >= ZSTD_btopt) {
         | 
| 31 | 
            -
                  /* Get out of the way of the optimal parser */
         | 
| 32 | 
            -
                  U32 const minMatch = MAX(cParams->targetLength, params->minMatchLength);
         | 
| 33 | 
            -
                  assert(minMatch >= ZSTD_LDM_MINMATCH_MIN);
         | 
| 34 | 
            -
                  assert(minMatch <= ZSTD_LDM_MINMATCH_MAX);
         | 
| 35 | 
            -
                  params->minMatchLength = minMatch;
         | 
| 36 | 
            -
                }
         | 
| 37 143 | 
             
                if (params->hashLog == 0) {
         | 
| 38 144 | 
             
                    params->hashLog = MAX(ZSTD_HASHLOG_MIN, params->windowLog - LDM_HASH_RLOG);
         | 
| 39 145 | 
             
                    assert(params->hashLog <= ZSTD_HASHLOG_MAX);
         | 
| @@ -53,47 +159,12 @@ size_t ZSTD_ldm_getTableSize(ldmParams_t params) | |
| 53 159 | 
             
                size_t const ldmBucketSize = ((size_t)1) << (params.hashLog - ldmBucketSizeLog);
         | 
| 54 160 | 
             
                size_t const totalSize = ZSTD_cwksp_alloc_size(ldmBucketSize)
         | 
| 55 161 | 
             
                                       + ZSTD_cwksp_alloc_size(ldmHSize * sizeof(ldmEntry_t));
         | 
| 56 | 
            -
                return params.enableLdm ? totalSize : 0;
         | 
| 162 | 
            +
                return params.enableLdm == ZSTD_ps_enable ? totalSize : 0;
         | 
| 57 163 | 
             
            }
         | 
| 58 164 |  | 
| 59 165 | 
             
            size_t ZSTD_ldm_getMaxNbSeq(ldmParams_t params, size_t maxChunkSize)
         | 
| 60 166 | 
             
            {
         | 
| 61 | 
            -
                return params.enableLdm ? (maxChunkSize / params.minMatchLength) : 0;
         | 
| 62 | 
            -
            }
         | 
| 63 | 
            -
             | 
| 64 | 
            -
            /** ZSTD_ldm_getSmallHash() :
         | 
| 65 | 
            -
             *  numBits should be <= 32
         | 
| 66 | 
            -
             *  If numBits==0, returns 0.
         | 
| 67 | 
            -
             *  @return : the most significant numBits of value. */
         | 
| 68 | 
            -
            static U32 ZSTD_ldm_getSmallHash(U64 value, U32 numBits)
         | 
| 69 | 
            -
            {
         | 
| 70 | 
            -
                assert(numBits <= 32);
         | 
| 71 | 
            -
                return numBits == 0 ? 0 : (U32)(value >> (64 - numBits));
         | 
| 72 | 
            -
            }
         | 
| 73 | 
            -
             | 
| 74 | 
            -
            /** ZSTD_ldm_getChecksum() :
         | 
| 75 | 
            -
             *  numBitsToDiscard should be <= 32
         | 
| 76 | 
            -
             *  @return : the next most significant 32 bits after numBitsToDiscard */
         | 
| 77 | 
            -
            static U32 ZSTD_ldm_getChecksum(U64 hash, U32 numBitsToDiscard)
         | 
| 78 | 
            -
            {
         | 
| 79 | 
            -
                assert(numBitsToDiscard <= 32);
         | 
| 80 | 
            -
                return (hash >> (64 - 32 - numBitsToDiscard)) & 0xFFFFFFFF;
         | 
| 81 | 
            -
            }
         | 
| 82 | 
            -
             | 
| 83 | 
            -
            /** ZSTD_ldm_getTag() ;
         | 
| 84 | 
            -
             *  Given the hash, returns the most significant numTagBits bits
         | 
| 85 | 
            -
             *  after (32 + hbits) bits.
         | 
| 86 | 
            -
             *
         | 
| 87 | 
            -
             *  If there are not enough bits remaining, return the last
         | 
| 88 | 
            -
             *  numTagBits bits. */
         | 
| 89 | 
            -
            static U32 ZSTD_ldm_getTag(U64 hash, U32 hbits, U32 numTagBits)
         | 
| 90 | 
            -
            {
         | 
| 91 | 
            -
                assert(numTagBits < 32 && hbits <= 32);
         | 
| 92 | 
            -
                if (32 - hbits < numTagBits) {
         | 
| 93 | 
            -
                    return hash & (((U32)1 << numTagBits) - 1);
         | 
| 94 | 
            -
                } else {
         | 
| 95 | 
            -
                    return (hash >> (32 - hbits - numTagBits)) & (((U32)1 << numTagBits) - 1);
         | 
| 96 | 
            -
                }
         | 
| 167 | 
            +
                return params.enableLdm == ZSTD_ps_enable ? (maxChunkSize / params.minMatchLength) : 0;
         | 
| 97 168 | 
             
            }
         | 
| 98 169 |  | 
| 99 170 | 
             
            /** ZSTD_ldm_getBucket() :
         | 
| @@ -110,38 +181,12 @@ static void ZSTD_ldm_insertEntry(ldmState_t* ldmState, | |
| 110 181 | 
             
                                             size_t const hash, const ldmEntry_t entry,
         | 
| 111 182 | 
             
                                             ldmParams_t const ldmParams)
         | 
| 112 183 | 
             
            {
         | 
| 113 | 
            -
                BYTE* const  | 
| 114 | 
            -
                 | 
| 115 | 
            -
             | 
| 116 | 
            -
                 | 
| 117 | 
            -
             | 
| 184 | 
            +
                BYTE* const pOffset = ldmState->bucketOffsets + hash;
         | 
| 185 | 
            +
                unsigned const offset = *pOffset;
         | 
| 186 | 
            +
             | 
| 187 | 
            +
                *(ZSTD_ldm_getBucket(ldmState, hash, ldmParams) + offset) = entry;
         | 
| 188 | 
            +
                *pOffset = (BYTE)((offset + 1) & ((1u << ldmParams.bucketSizeLog) - 1));
         | 
| 118 189 |  | 
| 119 | 
            -
            /** ZSTD_ldm_makeEntryAndInsertByTag() :
         | 
| 120 | 
            -
             *
         | 
| 121 | 
            -
             *  Gets the small hash, checksum, and tag from the rollingHash.
         | 
| 122 | 
            -
             *
         | 
| 123 | 
            -
             *  If the tag matches (1 << ldmParams.hashRateLog)-1, then
         | 
| 124 | 
            -
             *  creates an ldmEntry from the offset, and inserts it into the hash table.
         | 
| 125 | 
            -
             *
         | 
| 126 | 
            -
             *  hBits is the length of the small hash, which is the most significant hBits
         | 
| 127 | 
            -
             *  of rollingHash. The checksum is the next 32 most significant bits, followed
         | 
| 128 | 
            -
             *  by ldmParams.hashRateLog bits that make up the tag. */
         | 
| 129 | 
            -
            static void ZSTD_ldm_makeEntryAndInsertByTag(ldmState_t* ldmState,
         | 
| 130 | 
            -
                                                         U64 const rollingHash,
         | 
| 131 | 
            -
                                                         U32 const hBits,
         | 
| 132 | 
            -
                                                         U32 const offset,
         | 
| 133 | 
            -
                                                         ldmParams_t const ldmParams)
         | 
| 134 | 
            -
            {
         | 
| 135 | 
            -
                U32 const tag = ZSTD_ldm_getTag(rollingHash, hBits, ldmParams.hashRateLog);
         | 
| 136 | 
            -
                U32 const tagMask = ((U32)1 << ldmParams.hashRateLog) - 1;
         | 
| 137 | 
            -
                if (tag == tagMask) {
         | 
| 138 | 
            -
                    U32 const hash = ZSTD_ldm_getSmallHash(rollingHash, hBits);
         | 
| 139 | 
            -
                    U32 const checksum = ZSTD_ldm_getChecksum(rollingHash, hBits);
         | 
| 140 | 
            -
                    ldmEntry_t entry;
         | 
| 141 | 
            -
                    entry.offset = offset;
         | 
| 142 | 
            -
                    entry.checksum = checksum;
         | 
| 143 | 
            -
                    ZSTD_ldm_insertEntry(ldmState, hash, entry, ldmParams);
         | 
| 144 | 
            -
                }
         | 
| 145 190 | 
             
            }
         | 
| 146 191 |  | 
| 147 192 | 
             
            /** ZSTD_ldm_countBackwardsMatch() :
         | 
| @@ -150,10 +195,10 @@ static void ZSTD_ldm_makeEntryAndInsertByTag(ldmState_t* ldmState, | |
| 150 195 | 
             
             *  We count only bytes where pMatch >= pBase and pIn >= pAnchor. */
         | 
| 151 196 | 
             
            static size_t ZSTD_ldm_countBackwardsMatch(
         | 
| 152 197 | 
             
                        const BYTE* pIn, const BYTE* pAnchor,
         | 
| 153 | 
            -
                        const BYTE* pMatch, const BYTE*  | 
| 198 | 
            +
                        const BYTE* pMatch, const BYTE* pMatchBase)
         | 
| 154 199 | 
             
            {
         | 
| 155 200 | 
             
                size_t matchLength = 0;
         | 
| 156 | 
            -
                while (pIn > pAnchor && pMatch >  | 
| 201 | 
            +
                while (pIn > pAnchor && pMatch > pMatchBase && pIn[-1] == pMatch[-1]) {
         | 
| 157 202 | 
             
                    pIn--;
         | 
| 158 203 | 
             
                    pMatch--;
         | 
| 159 204 | 
             
                    matchLength++;
         | 
| @@ -161,6 +206,27 @@ static size_t ZSTD_ldm_countBackwardsMatch( | |
| 161 206 | 
             
                return matchLength;
         | 
| 162 207 | 
             
            }
         | 
| 163 208 |  | 
| 209 | 
            +
            /** ZSTD_ldm_countBackwardsMatch_2segments() :
         | 
| 210 | 
            +
             *  Returns the number of bytes that match backwards from pMatch,
         | 
| 211 | 
            +
             *  even with the backwards match spanning 2 different segments.
         | 
| 212 | 
            +
             *
         | 
| 213 | 
            +
             *  On reaching `pMatchBase`, start counting from mEnd */
         | 
| 214 | 
            +
            static size_t ZSTD_ldm_countBackwardsMatch_2segments(
         | 
| 215 | 
            +
                                const BYTE* pIn, const BYTE* pAnchor,
         | 
| 216 | 
            +
                                const BYTE* pMatch, const BYTE* pMatchBase,
         | 
| 217 | 
            +
                                const BYTE* pExtDictStart, const BYTE* pExtDictEnd)
         | 
| 218 | 
            +
            {
         | 
| 219 | 
            +
                size_t matchLength = ZSTD_ldm_countBackwardsMatch(pIn, pAnchor, pMatch, pMatchBase);
         | 
| 220 | 
            +
                if (pMatch - matchLength != pMatchBase || pMatchBase == pExtDictStart) {
         | 
| 221 | 
            +
                    /* If backwards match is entirely in the extDict or prefix, immediately return */
         | 
| 222 | 
            +
                    return matchLength;
         | 
| 223 | 
            +
                }
         | 
| 224 | 
            +
                DEBUGLOG(7, "ZSTD_ldm_countBackwardsMatch_2segments: found 2-parts backwards match (length in prefix==%zu)", matchLength);
         | 
| 225 | 
            +
                matchLength += ZSTD_ldm_countBackwardsMatch(pIn - matchLength, pAnchor, pExtDictEnd, pExtDictStart);
         | 
| 226 | 
            +
                DEBUGLOG(7, "final backwards match length = %zu", matchLength);
         | 
| 227 | 
            +
                return matchLength;
         | 
| 228 | 
            +
            }
         | 
| 229 | 
            +
             | 
| 164 230 | 
             
            /** ZSTD_ldm_fillFastTables() :
         | 
| 165 231 | 
             
             *
         | 
| 166 232 | 
             
             *  Fills the relevant tables for the ZSTD_fast and ZSTD_dfast strategies.
         | 
| @@ -198,43 +264,42 @@ static size_t ZSTD_ldm_fillFastTables(ZSTD_matchState_t* ms, | |
| 198 264 | 
             
                return 0;
         | 
| 199 265 | 
             
            }
         | 
| 200 266 |  | 
| 201 | 
            -
            /** ZSTD_ldm_fillLdmHashTable() :
         | 
| 202 | 
            -
             *
         | 
| 203 | 
            -
             *  Fills hashTable from (lastHashed + 1) to iend (non-inclusive).
         | 
| 204 | 
            -
             *  lastHash is the rolling hash that corresponds to lastHashed.
         | 
| 205 | 
            -
             *
         | 
| 206 | 
            -
             *  Returns the rolling hash corresponding to position iend-1. */
         | 
| 207 | 
            -
            static U64 ZSTD_ldm_fillLdmHashTable(ldmState_t* state,
         | 
| 208 | 
            -
                                                 U64 lastHash, const BYTE* lastHashed,
         | 
| 209 | 
            -
                                                 const BYTE* iend, const BYTE* base,
         | 
| 210 | 
            -
                                                 U32 hBits, ldmParams_t const ldmParams)
         | 
| 211 | 
            -
            {
         | 
| 212 | 
            -
                U64 rollingHash = lastHash;
         | 
| 213 | 
            -
                const BYTE* cur = lastHashed + 1;
         | 
| 214 | 
            -
             | 
| 215 | 
            -
                while (cur < iend) {
         | 
| 216 | 
            -
                    rollingHash = ZSTD_rollingHash_rotate(rollingHash, cur[-1],
         | 
| 217 | 
            -
                                                          cur[ldmParams.minMatchLength-1],
         | 
| 218 | 
            -
                                                          state->hashPower);
         | 
| 219 | 
            -
                    ZSTD_ldm_makeEntryAndInsertByTag(state,
         | 
| 220 | 
            -
                                                     rollingHash, hBits,
         | 
| 221 | 
            -
                                                     (U32)(cur - base), ldmParams);
         | 
| 222 | 
            -
                    ++cur;
         | 
| 223 | 
            -
                }
         | 
| 224 | 
            -
                return rollingHash;
         | 
| 225 | 
            -
            }
         | 
| 226 | 
            -
             | 
| 227 267 | 
             
            void ZSTD_ldm_fillHashTable(
         | 
| 228 | 
            -
                        ldmState_t*  | 
| 268 | 
            +
                        ldmState_t* ldmState, const BYTE* ip,
         | 
| 229 269 | 
             
                        const BYTE* iend, ldmParams_t const* params)
         | 
| 230 270 | 
             
            {
         | 
| 271 | 
            +
                U32 const minMatchLength = params->minMatchLength;
         | 
| 272 | 
            +
                U32 const hBits = params->hashLog - params->bucketSizeLog;
         | 
| 273 | 
            +
                BYTE const* const base = ldmState->window.base;
         | 
| 274 | 
            +
                BYTE const* const istart = ip;
         | 
| 275 | 
            +
                ldmRollingHashState_t hashState;
         | 
| 276 | 
            +
                size_t* const splits = ldmState->splitIndices;
         | 
| 277 | 
            +
                unsigned numSplits;
         | 
| 278 | 
            +
             | 
| 231 279 | 
             
                DEBUGLOG(5, "ZSTD_ldm_fillHashTable");
         | 
| 232 | 
            -
             | 
| 233 | 
            -
             | 
| 234 | 
            -
             | 
| 235 | 
            -
             | 
| 236 | 
            -
             | 
| 237 | 
            -
             | 
| 280 | 
            +
             | 
| 281 | 
            +
                ZSTD_ldm_gear_init(&hashState, params);
         | 
| 282 | 
            +
                while (ip < iend) {
         | 
| 283 | 
            +
                    size_t hashed;
         | 
| 284 | 
            +
                    unsigned n;
         | 
| 285 | 
            +
             | 
| 286 | 
            +
                    numSplits = 0;
         | 
| 287 | 
            +
                    hashed = ZSTD_ldm_gear_feed(&hashState, ip, iend - ip, splits, &numSplits);
         | 
| 288 | 
            +
             | 
| 289 | 
            +
                    for (n = 0; n < numSplits; n++) {
         | 
| 290 | 
            +
                        if (ip + splits[n] >= istart + minMatchLength) {
         | 
| 291 | 
            +
                            BYTE const* const split = ip + splits[n] - minMatchLength;
         | 
| 292 | 
            +
                            U64 const xxhash = XXH64(split, minMatchLength, 0);
         | 
| 293 | 
            +
                            U32 const hash = (U32)(xxhash & (((U32)1 << hBits) - 1));
         | 
| 294 | 
            +
                            ldmEntry_t entry;
         | 
| 295 | 
            +
             | 
| 296 | 
            +
                            entry.offset = (U32)(split - base);
         | 
| 297 | 
            +
                            entry.checksum = (U32)(xxhash >> 32);
         | 
| 298 | 
            +
                            ZSTD_ldm_insertEntry(ldmState, hash, entry, *params);
         | 
| 299 | 
            +
                        }
         | 
| 300 | 
            +
                    }
         | 
| 301 | 
            +
             | 
| 302 | 
            +
                    ip += hashed;
         | 
| 238 303 | 
             
                }
         | 
| 239 304 | 
             
            }
         | 
| 240 305 |  | 
| @@ -246,10 +311,10 @@ void ZSTD_ldm_fillHashTable( | |
| 246 311 | 
             
             *  (after a long match, only update tables a limited amount). */
         | 
| 247 312 | 
             
            static void ZSTD_ldm_limitTableUpdate(ZSTD_matchState_t* ms, const BYTE* anchor)
         | 
| 248 313 | 
             
            {
         | 
| 249 | 
            -
                U32 const  | 
| 250 | 
            -
                if ( | 
| 314 | 
            +
                U32 const curr = (U32)(anchor - ms->window.base);
         | 
| 315 | 
            +
                if (curr > ms->nextToUpdate + 1024) {
         | 
| 251 316 | 
             
                    ms->nextToUpdate =
         | 
| 252 | 
            -
                         | 
| 317 | 
            +
                        curr - MIN(512, curr - ms->nextToUpdate - 1024);
         | 
| 253 318 | 
             
                }
         | 
| 254 319 | 
             
            }
         | 
| 255 320 |  | 
| @@ -260,11 +325,8 @@ static size_t ZSTD_ldm_generateSequences_internal( | |
| 260 325 | 
             
                /* LDM parameters */
         | 
| 261 326 | 
             
                int const extDict = ZSTD_window_hasExtDict(ldmState->window);
         | 
| 262 327 | 
             
                U32 const minMatchLength = params->minMatchLength;
         | 
| 263 | 
            -
                 | 
| 328 | 
            +
                U32 const entsPerBucket = 1U << params->bucketSizeLog;
         | 
| 264 329 | 
             
                U32 const hBits = params->hashLog - params->bucketSizeLog;
         | 
| 265 | 
            -
                U32 const ldmBucketSize = 1U << params->bucketSizeLog;
         | 
| 266 | 
            -
                U32 const hashRateLog = params->hashRateLog;
         | 
| 267 | 
            -
                U32 const ldmTagMask = (1U << params->hashRateLog) - 1;
         | 
| 268 330 | 
             
                /* Prefix and extDict parameters */
         | 
| 269 331 | 
             
                U32 const dictLimit = ldmState->window.dictLimit;
         | 
| 270 332 | 
             
                U32 const lowestIndex = extDict ? ldmState->window.lowLimit : dictLimit;
         | 
| @@ -276,45 +338,69 @@ static size_t ZSTD_ldm_generateSequences_internal( | |
| 276 338 | 
             
                /* Input bounds */
         | 
| 277 339 | 
             
                BYTE const* const istart = (BYTE const*)src;
         | 
| 278 340 | 
             
                BYTE const* const iend = istart + srcSize;
         | 
| 279 | 
            -
                BYTE const* const ilimit = iend -  | 
| 341 | 
            +
                BYTE const* const ilimit = iend - HASH_READ_SIZE;
         | 
| 280 342 | 
             
                /* Input positions */
         | 
| 281 343 | 
             
                BYTE const* anchor = istart;
         | 
| 282 344 | 
             
                BYTE const* ip = istart;
         | 
| 283 | 
            -
                /* Rolling hash */
         | 
| 284 | 
            -
                 | 
| 285 | 
            -
                 | 
| 286 | 
            -
             | 
| 287 | 
            -
                 | 
| 288 | 
            -
             | 
| 289 | 
            -
             | 
| 290 | 
            -
             | 
| 291 | 
            -
                     | 
| 292 | 
            -
             | 
| 293 | 
            -
             | 
| 294 | 
            -
             | 
| 295 | 
            -
             | 
| 296 | 
            -
             | 
| 297 | 
            -
             | 
| 345 | 
            +
                /* Rolling hash state */
         | 
| 346 | 
            +
                ldmRollingHashState_t hashState;
         | 
| 347 | 
            +
                /* Arrays for staged-processing */
         | 
| 348 | 
            +
                size_t* const splits = ldmState->splitIndices;
         | 
| 349 | 
            +
                ldmMatchCandidate_t* const candidates = ldmState->matchCandidates;
         | 
| 350 | 
            +
                unsigned numSplits;
         | 
| 351 | 
            +
             | 
| 352 | 
            +
                if (srcSize < minMatchLength)
         | 
| 353 | 
            +
                    return iend - anchor;
         | 
| 354 | 
            +
             | 
| 355 | 
            +
                /* Initialize the rolling hash state with the first minMatchLength bytes */
         | 
| 356 | 
            +
                ZSTD_ldm_gear_init(&hashState, params);
         | 
| 357 | 
            +
                ZSTD_ldm_gear_reset(&hashState, ip, minMatchLength);
         | 
| 358 | 
            +
                ip += minMatchLength;
         | 
| 359 | 
            +
             | 
| 360 | 
            +
                while (ip < ilimit) {
         | 
| 361 | 
            +
                    size_t hashed;
         | 
| 362 | 
            +
                    unsigned n;
         | 
| 363 | 
            +
             | 
| 364 | 
            +
                    numSplits = 0;
         | 
| 365 | 
            +
                    hashed = ZSTD_ldm_gear_feed(&hashState, ip, ilimit - ip,
         | 
| 366 | 
            +
                                                splits, &numSplits);
         | 
| 367 | 
            +
             | 
| 368 | 
            +
                    for (n = 0; n < numSplits; n++) {
         | 
| 369 | 
            +
                        BYTE const* const split = ip + splits[n] - minMatchLength;
         | 
| 370 | 
            +
                        U64 const xxhash = XXH64(split, minMatchLength, 0);
         | 
| 371 | 
            +
                        U32 const hash = (U32)(xxhash & (((U32)1 << hBits) - 1));
         | 
| 372 | 
            +
             | 
| 373 | 
            +
                        candidates[n].split = split;
         | 
| 374 | 
            +
                        candidates[n].hash = hash;
         | 
| 375 | 
            +
                        candidates[n].checksum = (U32)(xxhash >> 32);
         | 
| 376 | 
            +
                        candidates[n].bucket = ZSTD_ldm_getBucket(ldmState, hash, *params);
         | 
| 377 | 
            +
                        PREFETCH_L1(candidates[n].bucket);
         | 
| 298 378 | 
             
                    }
         | 
| 299 | 
            -
                    lastHashed = ip;
         | 
| 300 379 |  | 
| 301 | 
            -
                     | 
| 302 | 
            -
             | 
| 303 | 
            -
             | 
| 304 | 
            -
             | 
| 305 | 
            -
             | 
| 380 | 
            +
                    for (n = 0; n < numSplits; n++) {
         | 
| 381 | 
            +
                        size_t forwardMatchLength = 0, backwardMatchLength = 0,
         | 
| 382 | 
            +
                               bestMatchLength = 0, mLength;
         | 
| 383 | 
            +
                        U32 offset;
         | 
| 384 | 
            +
                        BYTE const* const split = candidates[n].split;
         | 
| 385 | 
            +
                        U32 const checksum = candidates[n].checksum;
         | 
| 386 | 
            +
                        U32 const hash = candidates[n].hash;
         | 
| 387 | 
            +
                        ldmEntry_t* const bucket = candidates[n].bucket;
         | 
| 388 | 
            +
                        ldmEntry_t const* cur;
         | 
| 389 | 
            +
                        ldmEntry_t const* bestEntry = NULL;
         | 
| 390 | 
            +
                        ldmEntry_t newEntry;
         | 
| 391 | 
            +
             | 
| 392 | 
            +
                        newEntry.offset = (U32)(split - base);
         | 
| 393 | 
            +
                        newEntry.checksum = checksum;
         | 
| 394 | 
            +
             | 
| 395 | 
            +
                        /* If a split point would generate a sequence overlapping with
         | 
| 396 | 
            +
                         * the previous one, we merely register it in the hash table and
         | 
| 397 | 
            +
                         * move on */
         | 
| 398 | 
            +
                        if (split < anchor) {
         | 
| 399 | 
            +
                            ZSTD_ldm_insertEntry(ldmState, hash, newEntry, *params);
         | 
| 400 | 
            +
                            continue;
         | 
| 401 | 
            +
                        }
         | 
| 306 402 |  | 
| 307 | 
            -
             | 
| 308 | 
            -
                    {
         | 
| 309 | 
            -
                        ldmEntry_t* const bucket =
         | 
| 310 | 
            -
                            ZSTD_ldm_getBucket(ldmState,
         | 
| 311 | 
            -
                                               ZSTD_ldm_getSmallHash(rollingHash, hBits),
         | 
| 312 | 
            -
                                               *params);
         | 
| 313 | 
            -
                        ldmEntry_t* cur;
         | 
| 314 | 
            -
                        size_t bestMatchLength = 0;
         | 
| 315 | 
            -
                        U32 const checksum = ZSTD_ldm_getChecksum(rollingHash, hBits);
         | 
| 316 | 
            -
             | 
| 317 | 
            -
                        for (cur = bucket; cur < bucket + ldmBucketSize; ++cur) {
         | 
| 403 | 
            +
                        for (cur = bucket; cur < bucket + entsPerBucket; cur++) {
         | 
| 318 404 | 
             
                            size_t curForwardMatchLength, curBackwardMatchLength,
         | 
| 319 405 | 
             
                                   curTotalMatchLength;
         | 
| 320 406 | 
             
                            if (cur->checksum != checksum || cur->offset <= lowestIndex) {
         | 
| @@ -328,30 +414,23 @@ static size_t ZSTD_ldm_generateSequences_internal( | |
| 328 414 | 
             
                                    cur->offset < dictLimit ? dictEnd : iend;
         | 
| 329 415 | 
             
                                BYTE const* const lowMatchPtr =
         | 
| 330 416 | 
             
                                    cur->offset < dictLimit ? dictStart : lowPrefixPtr;
         | 
| 331 | 
            -
             | 
| 332 | 
            -
             | 
| 333 | 
            -
                                                            ip, pMatch, iend,
         | 
| 334 | 
            -
                                                            matchEnd, lowPrefixPtr);
         | 
| 417 | 
            +
                                curForwardMatchLength =
         | 
| 418 | 
            +
                                    ZSTD_count_2segments(split, pMatch, iend, matchEnd, lowPrefixPtr);
         | 
| 335 419 | 
             
                                if (curForwardMatchLength < minMatchLength) {
         | 
| 336 420 | 
             
                                    continue;
         | 
| 337 421 | 
             
                                }
         | 
| 338 | 
            -
                                curBackwardMatchLength =
         | 
| 339 | 
            -
             | 
| 340 | 
            -
                                                                 lowMatchPtr);
         | 
| 341 | 
            -
                                curTotalMatchLength = curForwardMatchLength +
         | 
| 342 | 
            -
                                                      curBackwardMatchLength;
         | 
| 422 | 
            +
                                curBackwardMatchLength = ZSTD_ldm_countBackwardsMatch_2segments(
         | 
| 423 | 
            +
                                        split, anchor, pMatch, lowMatchPtr, dictStart, dictEnd);
         | 
| 343 424 | 
             
                            } else { /* !extDict */
         | 
| 344 425 | 
             
                                BYTE const* const pMatch = base + cur->offset;
         | 
| 345 | 
            -
                                curForwardMatchLength = ZSTD_count( | 
| 426 | 
            +
                                curForwardMatchLength = ZSTD_count(split, pMatch, iend);
         | 
| 346 427 | 
             
                                if (curForwardMatchLength < minMatchLength) {
         | 
| 347 428 | 
             
                                    continue;
         | 
| 348 429 | 
             
                                }
         | 
| 349 430 | 
             
                                curBackwardMatchLength =
         | 
| 350 | 
            -
                                    ZSTD_ldm_countBackwardsMatch( | 
| 351 | 
            -
                                                                 lowPrefixPtr);
         | 
| 352 | 
            -
                                curTotalMatchLength = curForwardMatchLength +
         | 
| 353 | 
            -
                                                      curBackwardMatchLength;
         | 
| 431 | 
            +
                                    ZSTD_ldm_countBackwardsMatch(split, anchor, pMatch, lowPrefixPtr);
         | 
| 354 432 | 
             
                            }
         | 
| 433 | 
            +
                            curTotalMatchLength = curForwardMatchLength + curBackwardMatchLength;
         | 
| 355 434 |  | 
| 356 435 | 
             
                            if (curTotalMatchLength > bestMatchLength) {
         | 
| 357 436 | 
             
                                bestMatchLength = curTotalMatchLength;
         | 
| @@ -360,57 +439,54 @@ static size_t ZSTD_ldm_generateSequences_internal( | |
| 360 439 | 
             
                                bestEntry = cur;
         | 
| 361 440 | 
             
                            }
         | 
| 362 441 | 
             
                        }
         | 
| 363 | 
            -
                    }
         | 
| 364 | 
            -
             | 
| 365 | 
            -
                    /* No match found -- continue searching */
         | 
| 366 | 
            -
                    if (bestEntry == NULL) {
         | 
| 367 | 
            -
                        ZSTD_ldm_makeEntryAndInsertByTag(ldmState, rollingHash,
         | 
| 368 | 
            -
                                                         hBits, current,
         | 
| 369 | 
            -
                                                         *params);
         | 
| 370 | 
            -
                        ip++;
         | 
| 371 | 
            -
                        continue;
         | 
| 372 | 
            -
                    }
         | 
| 373 442 |  | 
| 374 | 
            -
             | 
| 375 | 
            -
             | 
| 376 | 
            -
             | 
| 443 | 
            +
                        /* No match found -- insert an entry into the hash table
         | 
| 444 | 
            +
                         * and process the next candidate match */
         | 
| 445 | 
            +
                        if (bestEntry == NULL) {
         | 
| 446 | 
            +
                            ZSTD_ldm_insertEntry(ldmState, hash, newEntry, *params);
         | 
| 447 | 
            +
                            continue;
         | 
| 448 | 
            +
                        }
         | 
| 377 449 |  | 
| 378 | 
            -
             | 
| 379 | 
            -
                         | 
| 380 | 
            -
             | 
| 381 | 
            -
             | 
| 382 | 
            -
             | 
| 383 | 
            -
             | 
| 384 | 
            -
             | 
| 385 | 
            -
             | 
| 386 | 
            -
             | 
| 387 | 
            -
             | 
| 388 | 
            -
             | 
| 389 | 
            -
                             | 
| 390 | 
            -
             | 
| 391 | 
            -
                         | 
| 392 | 
            -
                        seq->offset = offset;
         | 
| 393 | 
            -
                        rawSeqStore->size++;
         | 
| 394 | 
            -
                    }
         | 
| 450 | 
            +
                        /* Match found */
         | 
| 451 | 
            +
                        offset = (U32)(split - base) - bestEntry->offset;
         | 
| 452 | 
            +
                        mLength = forwardMatchLength + backwardMatchLength;
         | 
| 453 | 
            +
                        {
         | 
| 454 | 
            +
                            rawSeq* const seq = rawSeqStore->seq + rawSeqStore->size;
         | 
| 455 | 
            +
             | 
| 456 | 
            +
                            /* Out of sequence storage */
         | 
| 457 | 
            +
                            if (rawSeqStore->size == rawSeqStore->capacity)
         | 
| 458 | 
            +
                                return ERROR(dstSize_tooSmall);
         | 
| 459 | 
            +
                            seq->litLength = (U32)(split - backwardMatchLength - anchor);
         | 
| 460 | 
            +
                            seq->matchLength = (U32)mLength;
         | 
| 461 | 
            +
                            seq->offset = offset;
         | 
| 462 | 
            +
                            rawSeqStore->size++;
         | 
| 463 | 
            +
                        }
         | 
| 395 464 |  | 
| 396 | 
            -
             | 
| 397 | 
            -
             | 
| 398 | 
            -
             | 
| 399 | 
            -
                                                     *params);
         | 
| 465 | 
            +
                        /* Insert the current entry into the hash table --- it must be
         | 
| 466 | 
            +
                         * done after the previous block to avoid clobbering bestEntry */
         | 
| 467 | 
            +
                        ZSTD_ldm_insertEntry(ldmState, hash, newEntry, *params);
         | 
| 400 468 |  | 
| 401 | 
            -
             | 
| 469 | 
            +
                        anchor = split + forwardMatchLength;
         | 
| 402 470 |  | 
| 403 | 
            -
             | 
| 404 | 
            -
             | 
| 405 | 
            -
             | 
| 406 | 
            -
             | 
| 407 | 
            -
             | 
| 408 | 
            -
             | 
| 409 | 
            -
             | 
| 471 | 
            +
                        /* If we find a match that ends after the data that we've hashed
         | 
| 472 | 
            +
                         * then we have a repeating, overlapping, pattern. E.g. all zeros.
         | 
| 473 | 
            +
                         * If one repetition of the pattern matches our `stopMask` then all
         | 
| 474 | 
            +
                         * repetitions will. We don't need to insert them all into out table,
         | 
| 475 | 
            +
                         * only the first one. So skip over overlapping matches.
         | 
| 476 | 
            +
                         * This is a major speed boost (20x) for compressing a single byte
         | 
| 477 | 
            +
                         * repeated, when that byte ends up in the table.
         | 
| 478 | 
            +
                         */
         | 
| 479 | 
            +
                        if (anchor > ip + hashed) {
         | 
| 480 | 
            +
                            ZSTD_ldm_gear_reset(&hashState, anchor - minMatchLength, minMatchLength);
         | 
| 481 | 
            +
                            /* Continue the outer loop at anchor (ip + hashed == anchor). */
         | 
| 482 | 
            +
                            ip = anchor - hashed;
         | 
| 483 | 
            +
                            break;
         | 
| 484 | 
            +
                        }
         | 
| 410 485 | 
             
                    }
         | 
| 411 | 
            -
             | 
| 412 | 
            -
                     | 
| 486 | 
            +
             | 
| 487 | 
            +
                    ip += hashed;
         | 
| 413 488 | 
             
                }
         | 
| 489 | 
            +
             | 
| 414 490 | 
             
                return iend - anchor;
         | 
| 415 491 | 
             
            }
         | 
| 416 492 |  | 
| @@ -459,7 +535,7 @@ size_t ZSTD_ldm_generateSequences( | |
| 459 535 |  | 
| 460 536 | 
             
                    assert(chunkStart < iend);
         | 
| 461 537 | 
             
                    /* 1. Perform overflow correction if necessary. */
         | 
| 462 | 
            -
                    if (ZSTD_window_needOverflowCorrection(ldmState->window, chunkEnd)) {
         | 
| 538 | 
            +
                    if (ZSTD_window_needOverflowCorrection(ldmState->window, 0, maxDist, ldmState->loadedDictEnd, chunkStart, chunkEnd)) {
         | 
| 463 539 | 
             
                        U32 const ldmHSize = 1U << params->hashLog;
         | 
| 464 540 | 
             
                        U32 const correction = ZSTD_window_correctOverflow(
         | 
| 465 541 | 
             
                            &ldmState->window, /* cycleLog */ 0, maxDist, chunkStart);
         | 
| @@ -503,7 +579,9 @@ size_t ZSTD_ldm_generateSequences( | |
| 503 579 | 
             
                return 0;
         | 
| 504 580 | 
             
            }
         | 
| 505 581 |  | 
| 506 | 
            -
            void | 
| 582 | 
            +
            void
         | 
| 583 | 
            +
            ZSTD_ldm_skipSequences(rawSeqStore_t* rawSeqStore, size_t srcSize, U32 const minMatch)
         | 
| 584 | 
            +
            {
         | 
| 507 585 | 
             
                while (srcSize > 0 && rawSeqStore->pos < rawSeqStore->size) {
         | 
| 508 586 | 
             
                    rawSeq* seq = rawSeqStore->seq + rawSeqStore->pos;
         | 
| 509 587 | 
             
                    if (srcSize <= seq->litLength) {
         | 
| @@ -562,14 +640,32 @@ static rawSeq maybeSplitSequence(rawSeqStore_t* rawSeqStore, | |
| 562 640 | 
             
                return sequence;
         | 
| 563 641 | 
             
            }
         | 
| 564 642 |  | 
| 643 | 
            +
            void ZSTD_ldm_skipRawSeqStoreBytes(rawSeqStore_t* rawSeqStore, size_t nbBytes) {
         | 
| 644 | 
            +
                U32 currPos = (U32)(rawSeqStore->posInSequence + nbBytes);
         | 
| 645 | 
            +
                while (currPos && rawSeqStore->pos < rawSeqStore->size) {
         | 
| 646 | 
            +
                    rawSeq currSeq = rawSeqStore->seq[rawSeqStore->pos];
         | 
| 647 | 
            +
                    if (currPos >= currSeq.litLength + currSeq.matchLength) {
         | 
| 648 | 
            +
                        currPos -= currSeq.litLength + currSeq.matchLength;
         | 
| 649 | 
            +
                        rawSeqStore->pos++;
         | 
| 650 | 
            +
                    } else {
         | 
| 651 | 
            +
                        rawSeqStore->posInSequence = currPos;
         | 
| 652 | 
            +
                        break;
         | 
| 653 | 
            +
                    }
         | 
| 654 | 
            +
                }
         | 
| 655 | 
            +
                if (currPos == 0 || rawSeqStore->pos == rawSeqStore->size) {
         | 
| 656 | 
            +
                    rawSeqStore->posInSequence = 0;
         | 
| 657 | 
            +
                }
         | 
| 658 | 
            +
            }
         | 
| 659 | 
            +
             | 
| 565 660 | 
             
            size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
         | 
| 566 661 | 
             
                ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
         | 
| 662 | 
            +
                ZSTD_paramSwitch_e useRowMatchFinder,
         | 
| 567 663 | 
             
                void const* src, size_t srcSize)
         | 
| 568 664 | 
             
            {
         | 
| 569 665 | 
             
                const ZSTD_compressionParameters* const cParams = &ms->cParams;
         | 
| 570 666 | 
             
                unsigned const minMatch = cParams->minMatch;
         | 
| 571 667 | 
             
                ZSTD_blockCompressor const blockCompressor =
         | 
| 572 | 
            -
                    ZSTD_selectBlockCompressor(cParams->strategy, ZSTD_matchState_dictMode(ms));
         | 
| 668 | 
            +
                    ZSTD_selectBlockCompressor(cParams->strategy, useRowMatchFinder, ZSTD_matchState_dictMode(ms));
         | 
| 573 669 | 
             
                /* Input bounds */
         | 
| 574 670 | 
             
                BYTE const* const istart = (BYTE const*)src;
         | 
| 575 671 | 
             
                BYTE const* const iend = istart + srcSize;
         | 
| @@ -577,9 +673,18 @@ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore, | |
| 577 673 | 
             
                BYTE const* ip = istart;
         | 
| 578 674 |  | 
| 579 675 | 
             
                DEBUGLOG(5, "ZSTD_ldm_blockCompress: srcSize=%zu", srcSize);
         | 
| 676 | 
            +
                /* If using opt parser, use LDMs only as candidates rather than always accepting them */
         | 
| 677 | 
            +
                if (cParams->strategy >= ZSTD_btopt) {
         | 
| 678 | 
            +
                    size_t lastLLSize;
         | 
| 679 | 
            +
                    ms->ldmSeqStore = rawSeqStore;
         | 
| 680 | 
            +
                    lastLLSize = blockCompressor(ms, seqStore, rep, src, srcSize);
         | 
| 681 | 
            +
                    ZSTD_ldm_skipRawSeqStoreBytes(rawSeqStore, srcSize);
         | 
| 682 | 
            +
                    return lastLLSize;
         | 
| 683 | 
            +
                }
         | 
| 684 | 
            +
             | 
| 580 685 | 
             
                assert(rawSeqStore->pos <= rawSeqStore->size);
         | 
| 581 686 | 
             
                assert(rawSeqStore->size <= rawSeqStore->capacity);
         | 
| 582 | 
            -
                /* Loop through each sequence and apply the block compressor to the  | 
| 687 | 
            +
                /* Loop through each sequence and apply the block compressor to the literals */
         | 
| 583 688 | 
             
                while (rawSeqStore->pos < rawSeqStore->size && ip < iend) {
         | 
| 584 689 | 
             
                    /* maybeSplitSequence updates rawSeqStore->pos */
         | 
| 585 690 | 
             
                    rawSeq const sequence = maybeSplitSequence(rawSeqStore,
         | 
| @@ -606,8 +711,8 @@ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore, | |
| 606 711 | 
             
                        rep[0] = sequence.offset;
         | 
| 607 712 | 
             
                        /* Store the sequence */
         | 
| 608 713 | 
             
                        ZSTD_storeSeq(seqStore, newLitLength, ip - newLitLength, iend,
         | 
| 609 | 
            -
                                      sequence.offset | 
| 610 | 
            -
                                      sequence.matchLength | 
| 714 | 
            +
                                      STORE_OFFSET(sequence.offset),
         | 
| 715 | 
            +
                                      sequence.matchLength);
         | 
| 611 716 | 
             
                        ip += sequence.matchLength;
         | 
| 612 717 | 
             
                    }
         | 
| 613 718 | 
             
                }
         |