linux/lib/lz4/lz4_compress.c
<<
>>
Prefs
   1/*
   2 * LZ4 - Fast LZ compression algorithm
   3 * Copyright (C) 2011 - 2016, Yann Collet.
   4 * BSD 2 - Clause License (http://www.opensource.org/licenses/bsd - license.php)
   5 * Redistribution and use in source and binary forms, with or without
   6 * modification, are permitted provided that the following conditions are
   7 * met:
   8 *      * Redistributions of source code must retain the above copyright
   9 *        notice, this list of conditions and the following disclaimer.
  10 *      * Redistributions in binary form must reproduce the above
  11 * copyright notice, this list of conditions and the following disclaimer
  12 * in the documentation and/or other materials provided with the
  13 * distribution.
  14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  15 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  16 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  17 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  18 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  19 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  20 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25 * You can contact the author at :
  26 *      - LZ4 homepage : http://www.lz4.org
  27 *      - LZ4 source repository : https://github.com/lz4/lz4
  28 *
  29 *      Changed for kernel usage by:
  30 *      Sven Schmidt <4sschmid@informatik.uni-hamburg.de>
  31 */
  32
  33/*-************************************
  34 *      Dependencies
  35 **************************************/
  36#include <linux/lz4.h>
  37#include "lz4defs.h"
  38#include <linux/module.h>
  39#include <linux/kernel.h>
  40#include <asm/unaligned.h>
  41
  42static const int LZ4_minLength = (MFLIMIT + 1);
  43static const int LZ4_64Klimit = ((64 * KB) + (MFLIMIT - 1));
  44
  45/*-******************************
  46 *      Compression functions
  47 ********************************/
  48static FORCE_INLINE U32 LZ4_hash4(
  49        U32 sequence,
  50        tableType_t const tableType)
  51{
  52        if (tableType == byU16)
  53                return ((sequence * 2654435761U)
  54                        >> ((MINMATCH * 8) - (LZ4_HASHLOG + 1)));
  55        else
  56                return ((sequence * 2654435761U)
  57                        >> ((MINMATCH * 8) - LZ4_HASHLOG));
  58}
  59
  60static FORCE_INLINE U32 LZ4_hash5(
  61        U64 sequence,
  62        tableType_t const tableType)
  63{
  64        const U32 hashLog = (tableType == byU16)
  65                ? LZ4_HASHLOG + 1
  66                : LZ4_HASHLOG;
  67
  68#if LZ4_LITTLE_ENDIAN
  69        static const U64 prime5bytes = 889523592379ULL;
  70
  71        return (U32)(((sequence << 24) * prime5bytes) >> (64 - hashLog));
  72#else
  73        static const U64 prime8bytes = 11400714785074694791ULL;
  74
  75        return (U32)(((sequence >> 24) * prime8bytes) >> (64 - hashLog));
  76#endif
  77}
  78
  79static FORCE_INLINE U32 LZ4_hashPosition(
  80        const void *p,
  81        tableType_t const tableType)
  82{
  83#if LZ4_ARCH64
  84        if (tableType == byU32)
  85                return LZ4_hash5(LZ4_read_ARCH(p), tableType);
  86#endif
  87
  88        return LZ4_hash4(LZ4_read32(p), tableType);
  89}
  90
  91static void LZ4_putPositionOnHash(
  92        const BYTE *p,
  93        U32 h,
  94        void *tableBase,
  95        tableType_t const tableType,
  96        const BYTE *srcBase)
  97{
  98        switch (tableType) {
  99        case byPtr:
 100        {
 101                const BYTE **hashTable = (const BYTE **)tableBase;
 102
 103                hashTable[h] = p;
 104                return;
 105        }
 106        case byU32:
 107        {
 108                U32 *hashTable = (U32 *) tableBase;
 109
 110                hashTable[h] = (U32)(p - srcBase);
 111                return;
 112        }
 113        case byU16:
 114        {
 115                U16 *hashTable = (U16 *) tableBase;
 116
 117                hashTable[h] = (U16)(p - srcBase);
 118                return;
 119        }
 120        }
 121}
 122
 123static FORCE_INLINE void LZ4_putPosition(
 124        const BYTE *p,
 125        void *tableBase,
 126        tableType_t tableType,
 127        const BYTE *srcBase)
 128{
 129        U32 const h = LZ4_hashPosition(p, tableType);
 130
 131        LZ4_putPositionOnHash(p, h, tableBase, tableType, srcBase);
 132}
 133
 134static const BYTE *LZ4_getPositionOnHash(
 135        U32 h,
 136        void *tableBase,
 137        tableType_t tableType,
 138        const BYTE *srcBase)
 139{
 140        if (tableType == byPtr) {
 141                const BYTE **hashTable = (const BYTE **) tableBase;
 142
 143                return hashTable[h];
 144        }
 145
 146        if (tableType == byU32) {
 147                const U32 * const hashTable = (U32 *) tableBase;
 148
 149                return hashTable[h] + srcBase;
 150        }
 151
 152        {
 153                /* default, to ensure a return */
 154                const U16 * const hashTable = (U16 *) tableBase;
 155
 156                return hashTable[h] + srcBase;
 157        }
 158}
 159
 160static FORCE_INLINE const BYTE *LZ4_getPosition(
 161        const BYTE *p,
 162        void *tableBase,
 163        tableType_t tableType,
 164        const BYTE *srcBase)
 165{
 166        U32 const h = LZ4_hashPosition(p, tableType);
 167
 168        return LZ4_getPositionOnHash(h, tableBase, tableType, srcBase);
 169}
 170
 171
 172/*
 173 * LZ4_compress_generic() :
 174 * inlined, to ensure branches are decided at compilation time
 175 */
 176static FORCE_INLINE int LZ4_compress_generic(
 177        LZ4_stream_t_internal * const dictPtr,
 178        const char * const source,
 179        char * const dest,
 180        const int inputSize,
 181        const int maxOutputSize,
 182        const limitedOutput_directive outputLimited,
 183        const tableType_t tableType,
 184        const dict_directive dict,
 185        const dictIssue_directive dictIssue,
 186        const U32 acceleration)
 187{
 188        const BYTE *ip = (const BYTE *) source;
 189        const BYTE *base;
 190        const BYTE *lowLimit;
 191        const BYTE * const lowRefLimit = ip - dictPtr->dictSize;
 192        const BYTE * const dictionary = dictPtr->dictionary;
 193        const BYTE * const dictEnd = dictionary + dictPtr->dictSize;
 194        const size_t dictDelta = dictEnd - (const BYTE *)source;
 195        const BYTE *anchor = (const BYTE *) source;
 196        const BYTE * const iend = ip + inputSize;
 197        const BYTE * const mflimit = iend - MFLIMIT;
 198        const BYTE * const matchlimit = iend - LASTLITERALS;
 199
 200        BYTE *op = (BYTE *) dest;
 201        BYTE * const olimit = op + maxOutputSize;
 202
 203        U32 forwardH;
 204        size_t refDelta = 0;
 205
 206        /* Init conditions */
 207        if ((U32)inputSize > (U32)LZ4_MAX_INPUT_SIZE) {
 208                /* Unsupported inputSize, too large (or negative) */
 209                return 0;
 210        }
 211
 212        switch (dict) {
 213        case noDict:
 214        default:
 215                base = (const BYTE *)source;
 216                lowLimit = (const BYTE *)source;
 217                break;
 218        case withPrefix64k:
 219                base = (const BYTE *)source - dictPtr->currentOffset;
 220                lowLimit = (const BYTE *)source - dictPtr->dictSize;
 221                break;
 222        case usingExtDict:
 223                base = (const BYTE *)source - dictPtr->currentOffset;
 224                lowLimit = (const BYTE *)source;
 225                break;
 226        }
 227
 228        if ((tableType == byU16)
 229                && (inputSize >= LZ4_64Klimit)) {
 230                /* Size too large (not within 64K limit) */
 231                return 0;
 232        }
 233
 234        if (inputSize < LZ4_minLength) {
 235                /* Input too small, no compression (all literals) */
 236                goto _last_literals;
 237        }
 238
 239        /* First Byte */
 240        LZ4_putPosition(ip, dictPtr->hashTable, tableType, base);
 241        ip++;
 242        forwardH = LZ4_hashPosition(ip, tableType);
 243
 244        /* Main Loop */
 245        for ( ; ; ) {
 246                const BYTE *match;
 247                BYTE *token;
 248
 249                /* Find a match */
 250                {
 251                        const BYTE *forwardIp = ip;
 252                        unsigned int step = 1;
 253                        unsigned int searchMatchNb = acceleration << LZ4_SKIPTRIGGER;
 254
 255                        do {
 256                                U32 const h = forwardH;
 257
 258                                ip = forwardIp;
 259                                forwardIp += step;
 260                                step = (searchMatchNb++ >> LZ4_SKIPTRIGGER);
 261
 262                                if (unlikely(forwardIp > mflimit))
 263                                        goto _last_literals;
 264
 265                                match = LZ4_getPositionOnHash(h,
 266                                        dictPtr->hashTable,
 267                                        tableType, base);
 268
 269                                if (dict == usingExtDict) {
 270                                        if (match < (const BYTE *)source) {
 271                                                refDelta = dictDelta;
 272                                                lowLimit = dictionary;
 273                                        } else {
 274                                                refDelta = 0;
 275                                                lowLimit = (const BYTE *)source;
 276                                }        }
 277
 278                                forwardH = LZ4_hashPosition(forwardIp,
 279                                        tableType);
 280
 281                                LZ4_putPositionOnHash(ip, h, dictPtr->hashTable,
 282                                        tableType, base);
 283                        } while (((dictIssue == dictSmall)
 284                                        ? (match < lowRefLimit)
 285                                        : 0)
 286                                || ((tableType == byU16)
 287                                        ? 0
 288                                        : (match + MAX_DISTANCE < ip))
 289                                || (LZ4_read32(match + refDelta)
 290                                        != LZ4_read32(ip)));
 291                }
 292
 293                /* Catch up */
 294                while (((ip > anchor) & (match + refDelta > lowLimit))
 295                                && (unlikely(ip[-1] == match[refDelta - 1]))) {
 296                        ip--;
 297                        match--;
 298                }
 299
 300                /* Encode Literals */
 301                {
 302                        unsigned const int litLength = (unsigned int)(ip - anchor);
 303
 304                        token = op++;
 305
 306                        if ((outputLimited) &&
 307                                /* Check output buffer overflow */
 308                                (unlikely(op + litLength +
 309                                        (2 + 1 + LASTLITERALS) +
 310                                        (litLength / 255) > olimit)))
 311                                return 0;
 312
 313                        if (litLength >= RUN_MASK) {
 314                                int len = (int)litLength - RUN_MASK;
 315
 316                                *token = (RUN_MASK << ML_BITS);
 317
 318                                for (; len >= 255; len -= 255)
 319                                        *op++ = 255;
 320                                *op++ = (BYTE)len;
 321                        } else
 322                                *token = (BYTE)(litLength << ML_BITS);
 323
 324                        /* Copy Literals */
 325                        LZ4_wildCopy(op, anchor, op + litLength);
 326                        op += litLength;
 327                }
 328
 329_next_match:
 330                /* Encode Offset */
 331                LZ4_writeLE16(op, (U16)(ip - match));
 332                op += 2;
 333
 334                /* Encode MatchLength */
 335                {
 336                        unsigned int matchCode;
 337
 338                        if ((dict == usingExtDict)
 339                                && (lowLimit == dictionary)) {
 340                                const BYTE *limit;
 341
 342                                match += refDelta;
 343                                limit = ip + (dictEnd - match);
 344
 345                                if (limit > matchlimit)
 346                                        limit = matchlimit;
 347
 348                                matchCode = LZ4_count(ip + MINMATCH,
 349                                        match + MINMATCH, limit);
 350
 351                                ip += MINMATCH + matchCode;
 352
 353                                if (ip == limit) {
 354                                        unsigned const int more = LZ4_count(ip,
 355                                                (const BYTE *)source,
 356                                                matchlimit);
 357
 358                                        matchCode += more;
 359                                        ip += more;
 360                                }
 361                        } else {
 362                                matchCode = LZ4_count(ip + MINMATCH,
 363                                        match + MINMATCH, matchlimit);
 364                                ip += MINMATCH + matchCode;
 365                        }
 366
 367                        if (outputLimited &&
 368                                /* Check output buffer overflow */
 369                                (unlikely(op +
 370                                        (1 + LASTLITERALS) +
 371                                        (matchCode >> 8) > olimit)))
 372                                return 0;
 373
 374                        if (matchCode >= ML_MASK) {
 375                                *token += ML_MASK;
 376                                matchCode -= ML_MASK;
 377                                LZ4_write32(op, 0xFFFFFFFF);
 378
 379                                while (matchCode >= 4 * 255) {
 380                                        op += 4;
 381                                        LZ4_write32(op, 0xFFFFFFFF);
 382                                        matchCode -= 4 * 255;
 383                                }
 384
 385                                op += matchCode / 255;
 386                                *op++ = (BYTE)(matchCode % 255);
 387                        } else
 388                                *token += (BYTE)(matchCode);
 389                }
 390
 391                anchor = ip;
 392
 393                /* Test end of chunk */
 394                if (ip > mflimit)
 395                        break;
 396
 397                /* Fill table */
 398                LZ4_putPosition(ip - 2, dictPtr->hashTable, tableType, base);
 399
 400                /* Test next position */
 401                match = LZ4_getPosition(ip, dictPtr->hashTable,
 402                        tableType, base);
 403
 404                if (dict == usingExtDict) {
 405                        if (match < (const BYTE *)source) {
 406                                refDelta = dictDelta;
 407                                lowLimit = dictionary;
 408                        } else {
 409                                refDelta = 0;
 410                                lowLimit = (const BYTE *)source;
 411                        }
 412                }
 413
 414                LZ4_putPosition(ip, dictPtr->hashTable, tableType, base);
 415
 416                if (((dictIssue == dictSmall) ? (match >= lowRefLimit) : 1)
 417                        && (match + MAX_DISTANCE >= ip)
 418                        && (LZ4_read32(match + refDelta) == LZ4_read32(ip))) {
 419                        token = op++;
 420                        *token = 0;
 421                        goto _next_match;
 422                }
 423
 424                /* Prepare next loop */
 425                forwardH = LZ4_hashPosition(++ip, tableType);
 426        }
 427
 428_last_literals:
 429        /* Encode Last Literals */
 430        {
 431                size_t const lastRun = (size_t)(iend - anchor);
 432
 433                if ((outputLimited) &&
 434                        /* Check output buffer overflow */
 435                        ((op - (BYTE *)dest) + lastRun + 1 +
 436                        ((lastRun + 255 - RUN_MASK) / 255) > (U32)maxOutputSize))
 437                        return 0;
 438
 439                if (lastRun >= RUN_MASK) {
 440                        size_t accumulator = lastRun - RUN_MASK;
 441                        *op++ = RUN_MASK << ML_BITS;
 442                        for (; accumulator >= 255; accumulator -= 255)
 443                                *op++ = 255;
 444                        *op++ = (BYTE) accumulator;
 445                } else {
 446                        *op++ = (BYTE)(lastRun << ML_BITS);
 447                }
 448
 449                LZ4_memcpy(op, anchor, lastRun);
 450
 451                op += lastRun;
 452        }
 453
 454        /* End */
 455        return (int) (((char *)op) - dest);
 456}
 457
 458static int LZ4_compress_fast_extState(
 459        void *state,
 460        const char *source,
 461        char *dest,
 462        int inputSize,
 463        int maxOutputSize,
 464        int acceleration)
 465{
 466        LZ4_stream_t_internal *ctx = &((LZ4_stream_t *)state)->internal_donotuse;
 467#if LZ4_ARCH64
 468        const tableType_t tableType = byU32;
 469#else
 470        const tableType_t tableType = byPtr;
 471#endif
 472
 473        LZ4_resetStream((LZ4_stream_t *)state);
 474
 475        if (acceleration < 1)
 476                acceleration = LZ4_ACCELERATION_DEFAULT;
 477
 478        if (maxOutputSize >= LZ4_COMPRESSBOUND(inputSize)) {
 479                if (inputSize < LZ4_64Klimit)
 480                        return LZ4_compress_generic(ctx, source,
 481                                dest, inputSize, 0,
 482                                noLimit, byU16, noDict,
 483                                noDictIssue, acceleration);
 484                else
 485                        return LZ4_compress_generic(ctx, source,
 486                                dest, inputSize, 0,
 487                                noLimit, tableType, noDict,
 488                                noDictIssue, acceleration);
 489        } else {
 490                if (inputSize < LZ4_64Klimit)
 491                        return LZ4_compress_generic(ctx, source,
 492                                dest, inputSize,
 493                                maxOutputSize, limitedOutput, byU16, noDict,
 494                                noDictIssue, acceleration);
 495                else
 496                        return LZ4_compress_generic(ctx, source,
 497                                dest, inputSize,
 498                                maxOutputSize, limitedOutput, tableType, noDict,
 499                                noDictIssue, acceleration);
 500        }
 501}
 502
 503int LZ4_compress_fast(const char *source, char *dest, int inputSize,
 504        int maxOutputSize, int acceleration, void *wrkmem)
 505{
 506        return LZ4_compress_fast_extState(wrkmem, source, dest, inputSize,
 507                maxOutputSize, acceleration);
 508}
 509EXPORT_SYMBOL(LZ4_compress_fast);
 510
 511int LZ4_compress_default(const char *source, char *dest, int inputSize,
 512        int maxOutputSize, void *wrkmem)
 513{
 514        return LZ4_compress_fast(source, dest, inputSize,
 515                maxOutputSize, LZ4_ACCELERATION_DEFAULT, wrkmem);
 516}
 517EXPORT_SYMBOL(LZ4_compress_default);
 518
 519/*-******************************
 520 *      *_destSize() variant
 521 ********************************/
 522static int LZ4_compress_destSize_generic(
 523        LZ4_stream_t_internal * const ctx,
 524        const char * const src,
 525        char * const dst,
 526        int * const srcSizePtr,
 527        const int targetDstSize,
 528        const tableType_t tableType)
 529{
 530        const BYTE *ip = (const BYTE *) src;
 531        const BYTE *base = (const BYTE *) src;
 532        const BYTE *lowLimit = (const BYTE *) src;
 533        const BYTE *anchor = ip;
 534        const BYTE * const iend = ip + *srcSizePtr;
 535        const BYTE * const mflimit = iend - MFLIMIT;
 536        const BYTE * const matchlimit = iend - LASTLITERALS;
 537
 538        BYTE *op = (BYTE *) dst;
 539        BYTE * const oend = op + targetDstSize;
 540        BYTE * const oMaxLit = op + targetDstSize - 2 /* offset */
 541                - 8 /* because 8 + MINMATCH == MFLIMIT */ - 1 /* token */;
 542        BYTE * const oMaxMatch = op + targetDstSize
 543                - (LASTLITERALS + 1 /* token */);
 544        BYTE * const oMaxSeq = oMaxLit - 1 /* token */;
 545
 546        U32 forwardH;
 547
 548        /* Init conditions */
 549        /* Impossible to store anything */
 550        if (targetDstSize < 1)
 551                return 0;
 552        /* Unsupported input size, too large (or negative) */
 553        if ((U32)*srcSizePtr > (U32)LZ4_MAX_INPUT_SIZE)
 554                return 0;
 555        /* Size too large (not within 64K limit) */
 556        if ((tableType == byU16) && (*srcSizePtr >= LZ4_64Klimit))
 557                return 0;
 558        /* Input too small, no compression (all literals) */
 559        if (*srcSizePtr < LZ4_minLength)
 560                goto _last_literals;
 561
 562        /* First Byte */
 563        *srcSizePtr = 0;
 564        LZ4_putPosition(ip, ctx->hashTable, tableType, base);
 565        ip++; forwardH = LZ4_hashPosition(ip, tableType);
 566
 567        /* Main Loop */
 568        for ( ; ; ) {
 569                const BYTE *match;
 570                BYTE *token;
 571
 572                /* Find a match */
 573                {
 574                        const BYTE *forwardIp = ip;
 575                        unsigned int step = 1;
 576                        unsigned int searchMatchNb = 1 << LZ4_SKIPTRIGGER;
 577
 578                        do {
 579                                U32 h = forwardH;
 580
 581                                ip = forwardIp;
 582                                forwardIp += step;
 583                                step = (searchMatchNb++ >> LZ4_SKIPTRIGGER);
 584
 585                                if (unlikely(forwardIp > mflimit))
 586                                        goto _last_literals;
 587
 588                                match = LZ4_getPositionOnHash(h, ctx->hashTable,
 589                                        tableType, base);
 590                                forwardH = LZ4_hashPosition(forwardIp,
 591                                        tableType);
 592                                LZ4_putPositionOnHash(ip, h,
 593                                        ctx->hashTable, tableType,
 594                                        base);
 595
 596                        } while (((tableType == byU16)
 597                                ? 0
 598                                : (match + MAX_DISTANCE < ip))
 599                                || (LZ4_read32(match) != LZ4_read32(ip)));
 600                }
 601
 602                /* Catch up */
 603                while ((ip > anchor)
 604                        && (match > lowLimit)
 605                        && (unlikely(ip[-1] == match[-1]))) {
 606                        ip--;
 607                        match--;
 608                }
 609
 610                /* Encode Literal length */
 611                {
 612                        unsigned int litLength = (unsigned int)(ip - anchor);
 613
 614                        token = op++;
 615                        if (op + ((litLength + 240) / 255)
 616                                + litLength > oMaxLit) {
 617                                /* Not enough space for a last match */
 618                                op--;
 619                                goto _last_literals;
 620                        }
 621                        if (litLength >= RUN_MASK) {
 622                                unsigned int len = litLength - RUN_MASK;
 623                                *token = (RUN_MASK<<ML_BITS);
 624                                for (; len >= 255; len -= 255)
 625                                        *op++ = 255;
 626                                *op++ = (BYTE)len;
 627                        } else
 628                                *token = (BYTE)(litLength << ML_BITS);
 629
 630                        /* Copy Literals */
 631                        LZ4_wildCopy(op, anchor, op + litLength);
 632                        op += litLength;
 633                }
 634
 635_next_match:
 636                /* Encode Offset */
 637                LZ4_writeLE16(op, (U16)(ip - match)); op += 2;
 638
 639                /* Encode MatchLength */
 640                {
 641                        size_t matchLength = LZ4_count(ip + MINMATCH,
 642                        match + MINMATCH, matchlimit);
 643
 644                        if (op + ((matchLength + 240)/255) > oMaxMatch) {
 645                                /* Match description too long : reduce it */
 646                                matchLength = (15 - 1) + (oMaxMatch - op) * 255;
 647                        }
 648                        ip += MINMATCH + matchLength;
 649
 650                        if (matchLength >= ML_MASK) {
 651                                *token += ML_MASK;
 652                                matchLength -= ML_MASK;
 653                                while (matchLength >= 255) {
 654                                        matchLength -= 255;
 655                                        *op++ = 255;
 656                                }
 657                                *op++ = (BYTE)matchLength;
 658                        } else
 659                                *token += (BYTE)(matchLength);
 660                }
 661
 662                anchor = ip;
 663
 664                /* Test end of block */
 665                if (ip > mflimit)
 666                        break;
 667                if (op > oMaxSeq)
 668                        break;
 669
 670                /* Fill table */
 671                LZ4_putPosition(ip - 2, ctx->hashTable, tableType, base);
 672
 673                /* Test next position */
 674                match = LZ4_getPosition(ip, ctx->hashTable, tableType, base);
 675                LZ4_putPosition(ip, ctx->hashTable, tableType, base);
 676
 677                if ((match + MAX_DISTANCE >= ip)
 678                        && (LZ4_read32(match) == LZ4_read32(ip))) {
 679                        token = op++; *token = 0;
 680                        goto _next_match;
 681                }
 682
 683                /* Prepare next loop */
 684                forwardH = LZ4_hashPosition(++ip, tableType);
 685        }
 686
 687_last_literals:
 688        /* Encode Last Literals */
 689        {
 690                size_t lastRunSize = (size_t)(iend - anchor);
 691
 692                if (op + 1 /* token */
 693                        + ((lastRunSize + 240) / 255) /* litLength */
 694                        + lastRunSize /* literals */ > oend) {
 695                        /* adapt lastRunSize to fill 'dst' */
 696                        lastRunSize     = (oend - op) - 1;
 697                        lastRunSize -= (lastRunSize + 240) / 255;
 698                }
 699                ip = anchor + lastRunSize;
 700
 701                if (lastRunSize >= RUN_MASK) {
 702                        size_t accumulator = lastRunSize - RUN_MASK;
 703
 704                        *op++ = RUN_MASK << ML_BITS;
 705                        for (; accumulator >= 255; accumulator -= 255)
 706                                *op++ = 255;
 707                        *op++ = (BYTE) accumulator;
 708                } else {
 709                        *op++ = (BYTE)(lastRunSize<<ML_BITS);
 710                }
 711                LZ4_memcpy(op, anchor, lastRunSize);
 712                op += lastRunSize;
 713        }
 714
 715        /* End */
 716        *srcSizePtr = (int) (((const char *)ip) - src);
 717        return (int) (((char *)op) - dst);
 718}
 719
 720static int LZ4_compress_destSize_extState(
 721        LZ4_stream_t *state,
 722        const char *src,
 723        char *dst,
 724        int *srcSizePtr,
 725        int targetDstSize)
 726{
 727#if LZ4_ARCH64
 728        const tableType_t tableType = byU32;
 729#else
 730        const tableType_t tableType = byPtr;
 731#endif
 732
 733        LZ4_resetStream(state);
 734
 735        if (targetDstSize >= LZ4_COMPRESSBOUND(*srcSizePtr)) {
 736                /* compression success is guaranteed */
 737                return LZ4_compress_fast_extState(
 738                        state, src, dst, *srcSizePtr,
 739                        targetDstSize, 1);
 740        } else {
 741                if (*srcSizePtr < LZ4_64Klimit)
 742                        return LZ4_compress_destSize_generic(
 743                                &state->internal_donotuse,
 744                                src, dst, srcSizePtr,
 745                                targetDstSize, byU16);
 746                else
 747                        return LZ4_compress_destSize_generic(
 748                                &state->internal_donotuse,
 749                                src, dst, srcSizePtr,
 750                                targetDstSize, tableType);
 751        }
 752}
 753
 754
 755int LZ4_compress_destSize(
 756        const char *src,
 757        char *dst,
 758        int *srcSizePtr,
 759        int targetDstSize,
 760        void *wrkmem)
 761{
 762        return LZ4_compress_destSize_extState(wrkmem, src, dst, srcSizePtr,
 763                targetDstSize);
 764}
 765EXPORT_SYMBOL(LZ4_compress_destSize);
 766
 767/*-******************************
 768 *      Streaming functions
 769 ********************************/
 770void LZ4_resetStream(LZ4_stream_t *LZ4_stream)
 771{
 772        memset(LZ4_stream, 0, sizeof(LZ4_stream_t));
 773}
 774
 775int LZ4_loadDict(LZ4_stream_t *LZ4_dict,
 776        const char *dictionary, int dictSize)
 777{
 778        LZ4_stream_t_internal *dict = &LZ4_dict->internal_donotuse;
 779        const BYTE *p = (const BYTE *)dictionary;
 780        const BYTE * const dictEnd = p + dictSize;
 781        const BYTE *base;
 782
 783        if ((dict->initCheck)
 784                || (dict->currentOffset > 1 * GB)) {
 785                /* Uninitialized structure, or reuse overflow */
 786                LZ4_resetStream(LZ4_dict);
 787        }
 788
 789        if (dictSize < (int)HASH_UNIT) {
 790                dict->dictionary = NULL;
 791                dict->dictSize = 0;
 792                return 0;
 793        }
 794
 795        if ((dictEnd - p) > 64 * KB)
 796                p = dictEnd - 64 * KB;
 797        dict->currentOffset += 64 * KB;
 798        base = p - dict->currentOffset;
 799        dict->dictionary = p;
 800        dict->dictSize = (U32)(dictEnd - p);
 801        dict->currentOffset += dict->dictSize;
 802
 803        while (p <= dictEnd - HASH_UNIT) {
 804                LZ4_putPosition(p, dict->hashTable, byU32, base);
 805                p += 3;
 806        }
 807
 808        return dict->dictSize;
 809}
 810EXPORT_SYMBOL(LZ4_loadDict);
 811
 812static void LZ4_renormDictT(LZ4_stream_t_internal *LZ4_dict,
 813        const BYTE *src)
 814{
 815        if ((LZ4_dict->currentOffset > 0x80000000) ||
 816                ((uptrval)LZ4_dict->currentOffset > (uptrval)src)) {
 817                /* address space overflow */
 818                /* rescale hash table */
 819                U32 const delta = LZ4_dict->currentOffset - 64 * KB;
 820                const BYTE *dictEnd = LZ4_dict->dictionary + LZ4_dict->dictSize;
 821                int i;
 822
 823                for (i = 0; i < LZ4_HASH_SIZE_U32; i++) {
 824                        if (LZ4_dict->hashTable[i] < delta)
 825                                LZ4_dict->hashTable[i] = 0;
 826                        else
 827                                LZ4_dict->hashTable[i] -= delta;
 828                }
 829                LZ4_dict->currentOffset = 64 * KB;
 830                if (LZ4_dict->dictSize > 64 * KB)
 831                        LZ4_dict->dictSize = 64 * KB;
 832                LZ4_dict->dictionary = dictEnd - LZ4_dict->dictSize;
 833        }
 834}
 835
 836int LZ4_saveDict(LZ4_stream_t *LZ4_dict, char *safeBuffer, int dictSize)
 837{
 838        LZ4_stream_t_internal * const dict = &LZ4_dict->internal_donotuse;
 839        const BYTE * const previousDictEnd = dict->dictionary + dict->dictSize;
 840
 841        if ((U32)dictSize > 64 * KB) {
 842                /* useless to define a dictionary > 64 * KB */
 843                dictSize = 64 * KB;
 844        }
 845        if ((U32)dictSize > dict->dictSize)
 846                dictSize = dict->dictSize;
 847
 848        memmove(safeBuffer, previousDictEnd - dictSize, dictSize);
 849
 850        dict->dictionary = (const BYTE *)safeBuffer;
 851        dict->dictSize = (U32)dictSize;
 852
 853        return dictSize;
 854}
 855EXPORT_SYMBOL(LZ4_saveDict);
 856
 857int LZ4_compress_fast_continue(LZ4_stream_t *LZ4_stream, const char *source,
 858        char *dest, int inputSize, int maxOutputSize, int acceleration)
 859{
 860        LZ4_stream_t_internal *streamPtr = &LZ4_stream->internal_donotuse;
 861        const BYTE * const dictEnd = streamPtr->dictionary
 862                + streamPtr->dictSize;
 863
 864        const BYTE *smallest = (const BYTE *) source;
 865
 866        if (streamPtr->initCheck) {
 867                /* Uninitialized structure detected */
 868                return 0;
 869        }
 870
 871        if ((streamPtr->dictSize > 0) && (smallest > dictEnd))
 872                smallest = dictEnd;
 873
 874        LZ4_renormDictT(streamPtr, smallest);
 875
 876        if (acceleration < 1)
 877                acceleration = LZ4_ACCELERATION_DEFAULT;
 878
 879        /* Check overlapping input/dictionary space */
 880        {
 881                const BYTE *sourceEnd = (const BYTE *) source + inputSize;
 882
 883                if ((sourceEnd > streamPtr->dictionary)
 884                        && (sourceEnd < dictEnd)) {
 885                        streamPtr->dictSize = (U32)(dictEnd - sourceEnd);
 886                        if (streamPtr->dictSize > 64 * KB)
 887                                streamPtr->dictSize = 64 * KB;
 888                        if (streamPtr->dictSize < 4)
 889                                streamPtr->dictSize = 0;
 890                        streamPtr->dictionary = dictEnd - streamPtr->dictSize;
 891                }
 892        }
 893
 894        /* prefix mode : source data follows dictionary */
 895        if (dictEnd == (const BYTE *)source) {
 896                int result;
 897
 898                if ((streamPtr->dictSize < 64 * KB) &&
 899                        (streamPtr->dictSize < streamPtr->currentOffset)) {
 900                        result = LZ4_compress_generic(
 901                                streamPtr, source, dest, inputSize,
 902                                maxOutputSize, limitedOutput, byU32,
 903                                withPrefix64k, dictSmall, acceleration);
 904                } else {
 905                        result = LZ4_compress_generic(
 906                                streamPtr, source, dest, inputSize,
 907                                maxOutputSize, limitedOutput, byU32,
 908                                withPrefix64k, noDictIssue, acceleration);
 909                }
 910                streamPtr->dictSize += (U32)inputSize;
 911                streamPtr->currentOffset += (U32)inputSize;
 912                return result;
 913        }
 914
 915        /* external dictionary mode */
 916        {
 917                int result;
 918
 919                if ((streamPtr->dictSize < 64 * KB) &&
 920                        (streamPtr->dictSize < streamPtr->currentOffset)) {
 921                        result = LZ4_compress_generic(
 922                                streamPtr, source, dest, inputSize,
 923                                maxOutputSize, limitedOutput, byU32,
 924                                usingExtDict, dictSmall, acceleration);
 925                } else {
 926                        result = LZ4_compress_generic(
 927                                streamPtr, source, dest, inputSize,
 928                                maxOutputSize, limitedOutput, byU32,
 929                                usingExtDict, noDictIssue, acceleration);
 930                }
 931                streamPtr->dictionary = (const BYTE *)source;
 932                streamPtr->dictSize = (U32)inputSize;
 933                streamPtr->currentOffset += (U32)inputSize;
 934                return result;
 935        }
 936}
 937EXPORT_SYMBOL(LZ4_compress_fast_continue);
 938
 939MODULE_LICENSE("Dual BSD/GPL");
 940MODULE_DESCRIPTION("LZ4 compressor");
 941