contrib/python-zstandard/zstd/compress/zstd_compress.c
changeset 30924 c32454d69b85
parent 30822 b54a2984cdd4
child 37495 b1fb341d8a61
equal deleted inserted replaced
30923:5b60464efbde 30924:c32454d69b85
    49 
    49 
    50 
    50 
    51 /*-*************************************
    51 /*-*************************************
    52 *  Context memory management
    52 *  Context memory management
    53 ***************************************/
    53 ***************************************/
    54 struct ZSTD_CCtx_s
    54 struct ZSTD_CCtx_s {
    55 {
       
    56     const BYTE* nextSrc;    /* next block here to continue on current prefix */
    55     const BYTE* nextSrc;    /* next block here to continue on current prefix */
    57     const BYTE* base;       /* All regular indexes relative to this position */
    56     const BYTE* base;       /* All regular indexes relative to this position */
    58     const BYTE* dictBase;   /* extDict indexes relative to this position */
    57     const BYTE* dictBase;   /* extDict indexes relative to this position */
    59     U32   dictLimit;        /* below that point, need extDict */
    58     U32   dictLimit;        /* below that point, need extDict */
    60     U32   lowLimit;         /* below that point, no more data */
    59     U32   lowLimit;         /* below that point, no more data */
    61     U32   nextToUpdate;     /* index from which to continue dictionary update */
    60     U32   nextToUpdate;     /* index from which to continue dictionary update */
    62     U32   nextToUpdate3;    /* index from which to continue dictionary update */
    61     U32   nextToUpdate3;    /* index from which to continue dictionary update */
    63     U32   hashLog3;         /* dispatch table : larger == faster, more memory */
    62     U32   hashLog3;         /* dispatch table : larger == faster, more memory */
    64     U32   loadedDictEnd;
    63     U32   loadedDictEnd;    /* index of end of dictionary */
       
    64     U32   forceWindow;      /* force back-references to respect limit of 1<<wLog, even for dictionary */
    65     ZSTD_compressionStage_e stage;
    65     ZSTD_compressionStage_e stage;
    66     U32   rep[ZSTD_REP_NUM];
    66     U32   rep[ZSTD_REP_NUM];
    67     U32   savedRep[ZSTD_REP_NUM];
    67     U32   repToConfirm[ZSTD_REP_NUM];
    68     U32   dictID;
    68     U32   dictID;
    69     ZSTD_parameters params;
    69     ZSTD_parameters params;
    70     void* workSpace;
    70     void* workSpace;
    71     size_t workSpaceSize;
    71     size_t workSpaceSize;
    72     size_t blockSize;
    72     size_t blockSize;
    99     if (!customMem.customAlloc || !customMem.customFree) return NULL;
    99     if (!customMem.customAlloc || !customMem.customFree) return NULL;
   100 
   100 
   101     cctx = (ZSTD_CCtx*) ZSTD_malloc(sizeof(ZSTD_CCtx), customMem);
   101     cctx = (ZSTD_CCtx*) ZSTD_malloc(sizeof(ZSTD_CCtx), customMem);
   102     if (!cctx) return NULL;
   102     if (!cctx) return NULL;
   103     memset(cctx, 0, sizeof(ZSTD_CCtx));
   103     memset(cctx, 0, sizeof(ZSTD_CCtx));
   104     memcpy(&(cctx->customMem), &customMem, sizeof(customMem));
   104     cctx->customMem = customMem;
   105     return cctx;
   105     return cctx;
   106 }
   106 }
   107 
   107 
   108 size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)
   108 size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)
   109 {
   109 {
   115 
   115 
   116 size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx)
   116 size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx)
   117 {
   117 {
   118     if (cctx==NULL) return 0;   /* support sizeof on NULL */
   118     if (cctx==NULL) return 0;   /* support sizeof on NULL */
   119     return sizeof(*cctx) + cctx->workSpaceSize;
   119     return sizeof(*cctx) + cctx->workSpaceSize;
       
   120 }
       
   121 
       
   122 size_t ZSTD_setCCtxParameter(ZSTD_CCtx* cctx, ZSTD_CCtxParameter param, unsigned value)
       
   123 {
       
   124     switch(param)
       
   125     {
       
   126     case ZSTD_p_forceWindow : cctx->forceWindow = value>0; cctx->loadedDictEnd = 0; return 0;
       
   127     default: return ERROR(parameter_unknown);
       
   128     }
   120 }
   129 }
   121 
   130 
   122 const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx)   /* hidden interface */
   131 const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx)   /* hidden interface */
   123 {
   132 {
   124     return &(ctx->seqStore);
   133     return &(ctx->seqStore);
   316 
   325 
   317         return 0;
   326         return 0;
   318     }
   327     }
   319 }
   328 }
   320 
   329 
       
   330 /* ZSTD_invalidateRepCodes() :
       
   331  * ensures next compression will not use repcodes from previous block.
       
   332  * Note : only works with regular variant;
       
   333  *        do not use with extDict variant ! */
       
   334 void ZSTD_invalidateRepCodes(ZSTD_CCtx* cctx) {
       
   335     int i;
       
   336     for (i=0; i<ZSTD_REP_NUM; i++) cctx->rep[i] = 0;
       
   337 }
   321 
   338 
   322 /*! ZSTD_copyCCtx() :
   339 /*! ZSTD_copyCCtx() :
   323 *   Duplicate an existing context `srcCCtx` into another one `dstCCtx`.
   340 *   Duplicate an existing context `srcCCtx` into another one `dstCCtx`.
   324 *   Only works during stage ZSTDcs_init (i.e. after creation, but before first call to ZSTD_compressContinue()).
   341 *   Only works during stage ZSTDcs_init (i.e. after creation, but before first call to ZSTD_compressContinue()).
   325 *   @return : 0, or an error code */
   342 *   @return : 0, or an error code */
   733     { size_t const minGain = ZSTD_minGain(srcSize);
   750     { size_t const minGain = ZSTD_minGain(srcSize);
   734       size_t const maxCSize = srcSize - minGain;
   751       size_t const maxCSize = srcSize - minGain;
   735       if ((size_t)(op-ostart) >= maxCSize) return 0; }
   752       if ((size_t)(op-ostart) >= maxCSize) return 0; }
   736 
   753 
   737     /* confirm repcodes */
   754     /* confirm repcodes */
   738     { int i; for (i=0; i<ZSTD_REP_NUM; i++) zc->rep[i] = zc->savedRep[i]; }
   755     { int i; for (i=0; i<ZSTD_REP_NUM; i++) zc->rep[i] = zc->repToConfirm[i]; }
   739 
   756 
   740     return op - ostart;
   757     return op - ostart;
   741 }
   758 }
   742 
   759 
       
   760 
       
   761 #if 0 /* for debug */
       
   762 #  define STORESEQ_DEBUG
       
   763 #include <stdio.h>   /* fprintf */
       
   764 U32 g_startDebug = 0;
       
   765 const BYTE* g_start = NULL;
       
   766 #endif
   743 
   767 
   744 /*! ZSTD_storeSeq() :
   768 /*! ZSTD_storeSeq() :
   745     Store a sequence (literal length, literals, offset code and match length code) into seqStore_t.
   769     Store a sequence (literal length, literals, offset code and match length code) into seqStore_t.
   746     `offsetCode` : distance to match, or 0 == repCode.
   770     `offsetCode` : distance to match, or 0 == repCode.
   747     `matchCode` : matchLength - MINMATCH
   771     `matchCode` : matchLength - MINMATCH
   748 */
   772 */
   749 MEM_STATIC void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const void* literals, U32 offsetCode, size_t matchCode)
   773 MEM_STATIC void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const void* literals, U32 offsetCode, size_t matchCode)
   750 {
   774 {
   751 #if 0  /* for debug */
   775 #ifdef STORESEQ_DEBUG
   752     static const BYTE* g_start = NULL;
   776     if (g_startDebug) {
   753     const U32 pos = (U32)((const BYTE*)literals - g_start);
   777         const U32 pos = (U32)((const BYTE*)literals - g_start);
   754     if (g_start==NULL) g_start = (const BYTE*)literals;
   778         if (g_start==NULL) g_start = (const BYTE*)literals;
   755     //if ((pos > 1) && (pos < 50000))
   779         if ((pos > 1895000) && (pos < 1895300))
   756         printf("Cpos %6u :%5u literals & match %3u bytes at distance %6u \n",
   780             fprintf(stderr, "Cpos %6u :%5u literals & match %3u bytes at distance %6u \n",
   757                pos, (U32)litLength, (U32)matchCode+MINMATCH, (U32)offsetCode);
   781                    pos, (U32)litLength, (U32)matchCode+MINMATCH, (U32)offsetCode);
       
   782     }
   758 #endif
   783 #endif
   759     /* copy Literals */
   784     /* copy Literals */
   760     ZSTD_wildcopy(seqStorePtr->lit, literals, litLength);
   785     ZSTD_wildcopy(seqStorePtr->lit, literals, litLength);
   761     seqStorePtr->lit += litLength;
   786     seqStorePtr->lit += litLength;
   762 
   787 
  1002                 anchor = ip;
  1027                 anchor = ip;
  1003                 continue;   /* faster when present ... (?) */
  1028                 continue;   /* faster when present ... (?) */
  1004     }   }   }
  1029     }   }   }
  1005 
  1030 
  1006     /* save reps for next block */
  1031     /* save reps for next block */
  1007     cctx->savedRep[0] = offset_1 ? offset_1 : offsetSaved;
  1032     cctx->repToConfirm[0] = offset_1 ? offset_1 : offsetSaved;
  1008     cctx->savedRep[1] = offset_2 ? offset_2 : offsetSaved;
  1033     cctx->repToConfirm[1] = offset_2 ? offset_2 : offsetSaved;
  1009 
  1034 
  1010     /* Last Literals */
  1035     /* Last Literals */
  1011     {   size_t const lastLLSize = iend - anchor;
  1036     {   size_t const lastLLSize = iend - anchor;
  1012         memcpy(seqStorePtr->lit, anchor, lastLLSize);
  1037         memcpy(seqStorePtr->lit, anchor, lastLLSize);
  1013         seqStorePtr->lit += lastLLSize;
  1038         seqStorePtr->lit += lastLLSize;
  1117                 }
  1142                 }
  1118                 break;
  1143                 break;
  1119     }   }   }
  1144     }   }   }
  1120 
  1145 
  1121     /* save reps for next block */
  1146     /* save reps for next block */
  1122     ctx->savedRep[0] = offset_1; ctx->savedRep[1] = offset_2;
  1147     ctx->repToConfirm[0] = offset_1; ctx->repToConfirm[1] = offset_2;
  1123 
  1148 
  1124     /* Last Literals */
  1149     /* Last Literals */
  1125     {   size_t const lastLLSize = iend - anchor;
  1150     {   size_t const lastLLSize = iend - anchor;
  1126         memcpy(seqStorePtr->lit, anchor, lastLLSize);
  1151         memcpy(seqStorePtr->lit, anchor, lastLLSize);
  1127         seqStorePtr->lit += lastLLSize;
  1152         seqStorePtr->lit += lastLLSize;
  1271                 anchor = ip;
  1296                 anchor = ip;
  1272                 continue;   /* faster when present ... (?) */
  1297                 continue;   /* faster when present ... (?) */
  1273     }   }   }
  1298     }   }   }
  1274 
  1299 
  1275     /* save reps for next block */
  1300     /* save reps for next block */
  1276     cctx->savedRep[0] = offset_1 ? offset_1 : offsetSaved;
  1301     cctx->repToConfirm[0] = offset_1 ? offset_1 : offsetSaved;
  1277     cctx->savedRep[1] = offset_2 ? offset_2 : offsetSaved;
  1302     cctx->repToConfirm[1] = offset_2 ? offset_2 : offsetSaved;
  1278 
  1303 
  1279     /* Last Literals */
  1304     /* Last Literals */
  1280     {   size_t const lastLLSize = iend - anchor;
  1305     {   size_t const lastLLSize = iend - anchor;
  1281         memcpy(seqStorePtr->lit, anchor, lastLLSize);
  1306         memcpy(seqStorePtr->lit, anchor, lastLLSize);
  1282         seqStorePtr->lit += lastLLSize;
  1307         seqStorePtr->lit += lastLLSize;
  1421                 }
  1446                 }
  1422                 break;
  1447                 break;
  1423     }   }   }
  1448     }   }   }
  1424 
  1449 
  1425     /* save reps for next block */
  1450     /* save reps for next block */
  1426     ctx->savedRep[0] = offset_1; ctx->savedRep[1] = offset_2;
  1451     ctx->repToConfirm[0] = offset_1; ctx->repToConfirm[1] = offset_2;
  1427 
  1452 
  1428     /* Last Literals */
  1453     /* Last Literals */
  1429     {   size_t const lastLLSize = iend - anchor;
  1454     {   size_t const lastLLSize = iend - anchor;
  1430         memcpy(seqStorePtr->lit, anchor, lastLLSize);
  1455         memcpy(seqStorePtr->lit, anchor, lastLLSize);
  1431         seqStorePtr->lit += lastLLSize;
  1456         seqStorePtr->lit += lastLLSize;
  1953             anchor = ip;
  1978             anchor = ip;
  1954             continue;   /* faster when present ... (?) */
  1979             continue;   /* faster when present ... (?) */
  1955     }   }
  1980     }   }
  1956 
  1981 
  1957     /* Save reps for next block */
  1982     /* Save reps for next block */
  1958     ctx->savedRep[0] = offset_1 ? offset_1 : savedOffset;
  1983     ctx->repToConfirm[0] = offset_1 ? offset_1 : savedOffset;
  1959     ctx->savedRep[1] = offset_2 ? offset_2 : savedOffset;
  1984     ctx->repToConfirm[1] = offset_2 ? offset_2 : savedOffset;
  1960 
  1985 
  1961     /* Last Literals */
  1986     /* Last Literals */
  1962     {   size_t const lastLLSize = iend - anchor;
  1987     {   size_t const lastLLSize = iend - anchor;
  1963         memcpy(seqStorePtr->lit, anchor, lastLLSize);
  1988         memcpy(seqStorePtr->lit, anchor, lastLLSize);
  1964         seqStorePtr->lit += lastLLSize;
  1989         seqStorePtr->lit += lastLLSize;
  2148             }
  2173             }
  2149             break;
  2174             break;
  2150     }   }
  2175     }   }
  2151 
  2176 
  2152     /* Save reps for next block */
  2177     /* Save reps for next block */
  2153     ctx->savedRep[0] = offset_1; ctx->savedRep[1] = offset_2;
  2178     ctx->repToConfirm[0] = offset_1; ctx->repToConfirm[1] = offset_2;
  2154 
  2179 
  2155     /* Last Literals */
  2180     /* Last Literals */
  2156     {   size_t const lastLLSize = iend - anchor;
  2181     {   size_t const lastLLSize = iend - anchor;
  2157         memcpy(seqStorePtr->lit, anchor, lastLLSize);
  2182         memcpy(seqStorePtr->lit, anchor, lastLLSize);
  2158         seqStorePtr->lit += lastLLSize;
  2183         seqStorePtr->lit += lastLLSize;
  2407         cctx->lowLimit = lowLimitMax;
  2432         cctx->lowLimit = lowLimitMax;
  2408     }
  2433     }
  2409 
  2434 
  2410     cctx->nextSrc = ip + srcSize;
  2435     cctx->nextSrc = ip + srcSize;
  2411 
  2436 
  2412     {   size_t const cSize = frame ?
  2437     if (srcSize) {
       
  2438         size_t const cSize = frame ?
  2413                              ZSTD_compress_generic (cctx, dst, dstCapacity, src, srcSize, lastFrameChunk) :
  2439                              ZSTD_compress_generic (cctx, dst, dstCapacity, src, srcSize, lastFrameChunk) :
  2414                              ZSTD_compressBlock_internal (cctx, dst, dstCapacity, src, srcSize);
  2440                              ZSTD_compressBlock_internal (cctx, dst, dstCapacity, src, srcSize);
  2415         if (ZSTD_isError(cSize)) return cSize;
  2441         if (ZSTD_isError(cSize)) return cSize;
  2416         return cSize + fhSize;
  2442         return cSize + fhSize;
  2417     }
  2443     } else
       
  2444         return fhSize;
  2418 }
  2445 }
  2419 
  2446 
  2420 
  2447 
  2421 size_t ZSTD_compressContinue (ZSTD_CCtx* cctx,
  2448 size_t ZSTD_compressContinue (ZSTD_CCtx* cctx,
  2422                               void* dst, size_t dstCapacity,
  2449                               void* dst, size_t dstCapacity,
  2448     zc->lowLimit = zc->dictLimit;
  2475     zc->lowLimit = zc->dictLimit;
  2449     zc->dictLimit = (U32)(zc->nextSrc - zc->base);
  2476     zc->dictLimit = (U32)(zc->nextSrc - zc->base);
  2450     zc->dictBase = zc->base;
  2477     zc->dictBase = zc->base;
  2451     zc->base += ip - zc->nextSrc;
  2478     zc->base += ip - zc->nextSrc;
  2452     zc->nextToUpdate = zc->dictLimit;
  2479     zc->nextToUpdate = zc->dictLimit;
  2453     zc->loadedDictEnd = (U32)(iend - zc->base);
  2480     zc->loadedDictEnd = zc->forceWindow ? 0 : (U32)(iend - zc->base);
  2454 
  2481 
  2455     zc->nextSrc = iend;
  2482     zc->nextSrc = iend;
  2456     if (srcSize <= HASH_READ_SIZE) return 0;
  2483     if (srcSize <= HASH_READ_SIZE) return 0;
  2457 
  2484 
  2458     switch(zc->params.cParams.strategy)
  2485     switch(zc->params.cParams.strategy)
  2555         CHECK_E(FSE_buildCTable_wksp(cctx->litlengthCTable, litlengthNCount, litlengthMaxValue, litlengthLog, scratchBuffer, sizeof(scratchBuffer)), dictionary_corrupted);
  2582         CHECK_E(FSE_buildCTable_wksp(cctx->litlengthCTable, litlengthNCount, litlengthMaxValue, litlengthLog, scratchBuffer, sizeof(scratchBuffer)), dictionary_corrupted);
  2556         dictPtr += litlengthHeaderSize;
  2583         dictPtr += litlengthHeaderSize;
  2557     }
  2584     }
  2558 
  2585 
  2559     if (dictPtr+12 > dictEnd) return ERROR(dictionary_corrupted);
  2586     if (dictPtr+12 > dictEnd) return ERROR(dictionary_corrupted);
  2560     cctx->rep[0] = MEM_readLE32(dictPtr+0); if (cctx->rep[0] >= dictSize) return ERROR(dictionary_corrupted);
  2587     cctx->rep[0] = MEM_readLE32(dictPtr+0); if (cctx->rep[0] == 0 || cctx->rep[0] >= dictSize) return ERROR(dictionary_corrupted);
  2561     cctx->rep[1] = MEM_readLE32(dictPtr+4); if (cctx->rep[1] >= dictSize) return ERROR(dictionary_corrupted);
  2588     cctx->rep[1] = MEM_readLE32(dictPtr+4); if (cctx->rep[1] == 0 || cctx->rep[1] >= dictSize) return ERROR(dictionary_corrupted);
  2562     cctx->rep[2] = MEM_readLE32(dictPtr+8); if (cctx->rep[2] >= dictSize) return ERROR(dictionary_corrupted);
  2589     cctx->rep[2] = MEM_readLE32(dictPtr+8); if (cctx->rep[2] == 0 || cctx->rep[2] >= dictSize) return ERROR(dictionary_corrupted);
  2563     dictPtr += 12;
  2590     dictPtr += 12;
  2564 
  2591 
  2565     {   U32 offcodeMax = MaxOff;
  2592     {   U32 offcodeMax = MaxOff;
  2566         if ((size_t)(dictEnd - dictPtr) <= ((U32)-1) - 128 KB) {
  2593         if ((size_t)(dictEnd - dictPtr) <= ((U32)-1) - 128 KB) {
  2567             U32 const maxOffset = (U32)(dictEnd - dictPtr) + 128 KB; /* The maximum offset that must be supported */
  2594             U32 const maxOffset = (U32)(dictEnd - dictPtr) + 128 KB; /* The maximum offset that must be supported */
  2592         if (ZSTD_isError(loadError)) return loadError;
  2619         if (ZSTD_isError(loadError)) return loadError;
  2593         return ZSTD_loadDictionaryContent(zc, (const char*)dict+eSize, dictSize-eSize);
  2620         return ZSTD_loadDictionaryContent(zc, (const char*)dict+eSize, dictSize-eSize);
  2594     }
  2621     }
  2595 }
  2622 }
  2596 
  2623 
  2597 
       
  2598 /*! ZSTD_compressBegin_internal() :
  2624 /*! ZSTD_compressBegin_internal() :
  2599 *   @return : 0, or an error code */
  2625 *   @return : 0, or an error code */
  2600 static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
  2626 static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
  2601                              const void* dict, size_t dictSize,
  2627                              const void* dict, size_t dictSize,
  2602                                    ZSTD_parameters params, U64 pledgedSrcSize)
  2628                                    ZSTD_parameters params, U64 pledgedSrcSize)
  2624     ZSTD_parameters const params = ZSTD_getParams(compressionLevel, 0, dictSize);
  2650     ZSTD_parameters const params = ZSTD_getParams(compressionLevel, 0, dictSize);
  2625     return ZSTD_compressBegin_internal(cctx, dict, dictSize, params, 0);
  2651     return ZSTD_compressBegin_internal(cctx, dict, dictSize, params, 0);
  2626 }
  2652 }
  2627 
  2653 
  2628 
  2654 
  2629 size_t ZSTD_compressBegin(ZSTD_CCtx* zc, int compressionLevel)
  2655 size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel)
  2630 {
  2656 {
  2631     return ZSTD_compressBegin_usingDict(zc, NULL, 0, compressionLevel);
  2657     return ZSTD_compressBegin_usingDict(cctx, NULL, 0, compressionLevel);
  2632 }
  2658 }
  2633 
  2659 
  2634 
  2660 
  2635 /*! ZSTD_writeEpilogue() :
  2661 /*! ZSTD_writeEpilogue() :
  2636 *   Ends a frame.
  2662 *   Ends a frame.
  2731 
  2757 
  2732 
  2758 
  2733 /* =====  Dictionary API  ===== */
  2759 /* =====  Dictionary API  ===== */
  2734 
  2760 
  2735 struct ZSTD_CDict_s {
  2761 struct ZSTD_CDict_s {
  2736     void* dictContent;
  2762     void* dictBuffer;
       
  2763     const void* dictContent;
  2737     size_t dictContentSize;
  2764     size_t dictContentSize;
  2738     ZSTD_CCtx* refContext;
  2765     ZSTD_CCtx* refContext;
  2739 };  /* typedef'd tp ZSTD_CDict within "zstd.h" */
  2766 };  /* typedef'd tp ZSTD_CDict within "zstd.h" */
  2740 
  2767 
  2741 size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict)
  2768 size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict)
  2742 {
  2769 {
  2743     if (cdict==NULL) return 0;   /* support sizeof on NULL */
  2770     if (cdict==NULL) return 0;   /* support sizeof on NULL */
  2744     return ZSTD_sizeof_CCtx(cdict->refContext) + cdict->dictContentSize;
  2771     return ZSTD_sizeof_CCtx(cdict->refContext) + (cdict->dictBuffer ? cdict->dictContentSize : 0) + sizeof(*cdict);
  2745 }
  2772 }
  2746 
  2773 
  2747 ZSTD_CDict* ZSTD_createCDict_advanced(const void* dict, size_t dictSize, ZSTD_parameters params, ZSTD_customMem customMem)
  2774 ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize, unsigned byReference,
       
  2775                                       ZSTD_parameters params, ZSTD_customMem customMem)
  2748 {
  2776 {
  2749     if (!customMem.customAlloc && !customMem.customFree) customMem = defaultCustomMem;
  2777     if (!customMem.customAlloc && !customMem.customFree) customMem = defaultCustomMem;
  2750     if (!customMem.customAlloc || !customMem.customFree) return NULL;
  2778     if (!customMem.customAlloc || !customMem.customFree) return NULL;
  2751 
  2779 
  2752     {   ZSTD_CDict* const cdict = (ZSTD_CDict*) ZSTD_malloc(sizeof(ZSTD_CDict), customMem);
  2780     {   ZSTD_CDict* const cdict = (ZSTD_CDict*) ZSTD_malloc(sizeof(ZSTD_CDict), customMem);
  2753         void* const dictContent = ZSTD_malloc(dictSize, customMem);
       
  2754         ZSTD_CCtx* const cctx = ZSTD_createCCtx_advanced(customMem);
  2781         ZSTD_CCtx* const cctx = ZSTD_createCCtx_advanced(customMem);
  2755 
  2782 
  2756         if (!dictContent || !cdict || !cctx) {
  2783         if (!cdict || !cctx) {
  2757             ZSTD_free(dictContent, customMem);
       
  2758             ZSTD_free(cdict, customMem);
  2784             ZSTD_free(cdict, customMem);
  2759             ZSTD_free(cctx, customMem);
  2785             ZSTD_free(cctx, customMem);
  2760             return NULL;
  2786             return NULL;
  2761         }
  2787         }
  2762 
  2788 
  2763         if (dictSize) {
  2789         if ((byReference) || (!dictBuffer) || (!dictSize)) {
  2764             memcpy(dictContent, dict, dictSize);
  2790             cdict->dictBuffer = NULL;
       
  2791             cdict->dictContent = dictBuffer;
       
  2792         } else {
       
  2793             void* const internalBuffer = ZSTD_malloc(dictSize, customMem);
       
  2794             if (!internalBuffer) { ZSTD_free(cctx, customMem); ZSTD_free(cdict, customMem); return NULL; }
       
  2795             memcpy(internalBuffer, dictBuffer, dictSize);
       
  2796             cdict->dictBuffer = internalBuffer;
       
  2797             cdict->dictContent = internalBuffer;
  2765         }
  2798         }
  2766         {   size_t const errorCode = ZSTD_compressBegin_advanced(cctx, dictContent, dictSize, params, 0);
  2799 
       
  2800         {   size_t const errorCode = ZSTD_compressBegin_advanced(cctx, cdict->dictContent, dictSize, params, 0);
  2767             if (ZSTD_isError(errorCode)) {
  2801             if (ZSTD_isError(errorCode)) {
  2768                 ZSTD_free(dictContent, customMem);
  2802                 ZSTD_free(cdict->dictBuffer, customMem);
       
  2803                 ZSTD_free(cctx, customMem);
  2769                 ZSTD_free(cdict, customMem);
  2804                 ZSTD_free(cdict, customMem);
  2770                 ZSTD_free(cctx, customMem);
       
  2771                 return NULL;
  2805                 return NULL;
  2772         }   }
  2806         }   }
  2773 
  2807 
  2774         cdict->dictContent = dictContent;
  2808         cdict->refContext = cctx;
  2775         cdict->dictContentSize = dictSize;
  2809         cdict->dictContentSize = dictSize;
  2776         cdict->refContext = cctx;
       
  2777         return cdict;
  2810         return cdict;
  2778     }
  2811     }
  2779 }
  2812 }
  2780 
  2813 
  2781 ZSTD_CDict* ZSTD_createCDict(const void* dict, size_t dictSize, int compressionLevel)
  2814 ZSTD_CDict* ZSTD_createCDict(const void* dict, size_t dictSize, int compressionLevel)
  2782 {
  2815 {
  2783     ZSTD_customMem const allocator = { NULL, NULL, NULL };
  2816     ZSTD_customMem const allocator = { NULL, NULL, NULL };
  2784     ZSTD_parameters params = ZSTD_getParams(compressionLevel, 0, dictSize);
  2817     ZSTD_parameters params = ZSTD_getParams(compressionLevel, 0, dictSize);
  2785     params.fParams.contentSizeFlag = 1;
  2818     params.fParams.contentSizeFlag = 1;
  2786     return ZSTD_createCDict_advanced(dict, dictSize, params, allocator);
  2819     return ZSTD_createCDict_advanced(dict, dictSize, 0, params, allocator);
       
  2820 }
       
  2821 
       
  2822 ZSTD_CDict* ZSTD_createCDict_byReference(const void* dict, size_t dictSize, int compressionLevel)
       
  2823 {
       
  2824     ZSTD_customMem const allocator = { NULL, NULL, NULL };
       
  2825     ZSTD_parameters params = ZSTD_getParams(compressionLevel, 0, dictSize);
       
  2826     params.fParams.contentSizeFlag = 1;
       
  2827     return ZSTD_createCDict_advanced(dict, dictSize, 1, params, allocator);
  2787 }
  2828 }
  2788 
  2829 
  2789 size_t ZSTD_freeCDict(ZSTD_CDict* cdict)
  2830 size_t ZSTD_freeCDict(ZSTD_CDict* cdict)
  2790 {
  2831 {
  2791     if (cdict==NULL) return 0;   /* support free on NULL */
  2832     if (cdict==NULL) return 0;   /* support free on NULL */
  2792     {   ZSTD_customMem const cMem = cdict->refContext->customMem;
  2833     {   ZSTD_customMem const cMem = cdict->refContext->customMem;
  2793         ZSTD_freeCCtx(cdict->refContext);
  2834         ZSTD_freeCCtx(cdict->refContext);
  2794         ZSTD_free(cdict->dictContent, cMem);
  2835         ZSTD_free(cdict->dictBuffer, cMem);
  2795         ZSTD_free(cdict, cMem);
  2836         ZSTD_free(cdict, cMem);
  2796         return 0;
  2837         return 0;
  2797     }
  2838     }
  2798 }
  2839 }
  2799 
  2840 
  2800 static ZSTD_parameters ZSTD_getParamsFromCDict(const ZSTD_CDict* cdict) {
  2841 static ZSTD_parameters ZSTD_getParamsFromCDict(const ZSTD_CDict* cdict) {
  2801     return ZSTD_getParamsFromCCtx(cdict->refContext);
  2842     return ZSTD_getParamsFromCCtx(cdict->refContext);
  2802 }
  2843 }
  2803 
  2844 
  2804 size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict, U64 pledgedSrcSize)
  2845 size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict, unsigned long long pledgedSrcSize)
  2805 {
  2846 {
  2806     if (cdict->dictContentSize) CHECK_F(ZSTD_copyCCtx(cctx, cdict->refContext, pledgedSrcSize))
  2847     if (cdict->dictContentSize) CHECK_F(ZSTD_copyCCtx(cctx, cdict->refContext, pledgedSrcSize))
  2807     else CHECK_F(ZSTD_compressBegin_advanced(cctx, NULL, 0, cdict->refContext->params, pledgedSrcSize));
  2848     else CHECK_F(ZSTD_compressBegin_advanced(cctx, NULL, 0, cdict->refContext->params, pledgedSrcSize));
  2808     return 0;
  2849     return 0;
  2809 }
  2850 }
  2898 size_t ZSTD_CStreamInSize(void)  { return ZSTD_BLOCKSIZE_ABSOLUTEMAX; }
  2939 size_t ZSTD_CStreamInSize(void)  { return ZSTD_BLOCKSIZE_ABSOLUTEMAX; }
  2899 size_t ZSTD_CStreamOutSize(void) { return ZSTD_compressBound(ZSTD_BLOCKSIZE_ABSOLUTEMAX) + ZSTD_blockHeaderSize + 4 /* 32-bits hash */ ; }
  2940 size_t ZSTD_CStreamOutSize(void) { return ZSTD_compressBound(ZSTD_BLOCKSIZE_ABSOLUTEMAX) + ZSTD_blockHeaderSize + 4 /* 32-bits hash */ ; }
  2900 
  2941 
  2901 size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize)
  2942 size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize)
  2902 {
  2943 {
  2903     if (zcs->inBuffSize==0) return ERROR(stage_wrong);   /* zcs has not been init at least once */
  2944     if (zcs->inBuffSize==0) return ERROR(stage_wrong);   /* zcs has not been init at least once => can't reset */
  2904 
  2945 
  2905     if (zcs->cdict) CHECK_F(ZSTD_compressBegin_usingCDict(zcs->cctx, zcs->cdict, pledgedSrcSize))
  2946     if (zcs->cdict) CHECK_F(ZSTD_compressBegin_usingCDict(zcs->cctx, zcs->cdict, pledgedSrcSize))
  2906     else CHECK_F(ZSTD_compressBegin_advanced(zcs->cctx, NULL, 0, zcs->params, pledgedSrcSize));
  2947     else CHECK_F(ZSTD_compressBegin_advanced(zcs->cctx, NULL, 0, zcs->params, pledgedSrcSize));
  2907 
  2948 
  2908     zcs->inToCompress = 0;
  2949     zcs->inToCompress = 0;
  2935         ZSTD_free(zcs->outBuff, zcs->customMem);
  2976         ZSTD_free(zcs->outBuff, zcs->customMem);
  2936         zcs->outBuff = (char*) ZSTD_malloc(zcs->outBuffSize, zcs->customMem);
  2977         zcs->outBuff = (char*) ZSTD_malloc(zcs->outBuffSize, zcs->customMem);
  2937         if (zcs->outBuff == NULL) return ERROR(memory_allocation);
  2978         if (zcs->outBuff == NULL) return ERROR(memory_allocation);
  2938     }
  2979     }
  2939 
  2980 
  2940     if (dict) {
  2981     if (dict && dictSize >= 8) {
  2941         ZSTD_freeCDict(zcs->cdictLocal);
  2982         ZSTD_freeCDict(zcs->cdictLocal);
  2942         zcs->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize, params, zcs->customMem);
  2983         zcs->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize, 0, params, zcs->customMem);
  2943         if (zcs->cdictLocal == NULL) return ERROR(memory_allocation);
  2984         if (zcs->cdictLocal == NULL) return ERROR(memory_allocation);
  2944         zcs->cdict = zcs->cdictLocal;
  2985         zcs->cdict = zcs->cdictLocal;
  2945     } else zcs->cdict = NULL;
  2986     } else zcs->cdict = NULL;
  2946 
  2987 
  2947     zcs->checksum = params.fParams.checksumFlag > 0;
  2988     zcs->checksum = params.fParams.checksumFlag > 0;
  2954 size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict)
  2995 size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict)
  2955 {
  2996 {
  2956     ZSTD_parameters const params = ZSTD_getParamsFromCDict(cdict);
  2997     ZSTD_parameters const params = ZSTD_getParamsFromCDict(cdict);
  2957     size_t const initError =  ZSTD_initCStream_advanced(zcs, NULL, 0, params, 0);
  2998     size_t const initError =  ZSTD_initCStream_advanced(zcs, NULL, 0, params, 0);
  2958     zcs->cdict = cdict;
  2999     zcs->cdict = cdict;
       
  3000     zcs->cctx->dictID = params.fParams.noDictIDFlag ? 0 : cdict->refContext->dictID;
  2959     return initError;
  3001     return initError;
  2960 }
  3002 }
  2961 
  3003 
  2962 size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel)
  3004 size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel)
  2963 {
  3005 {
  2965     return ZSTD_initCStream_advanced(zcs, dict, dictSize, params, 0);
  3007     return ZSTD_initCStream_advanced(zcs, dict, dictSize, params, 0);
  2966 }
  3008 }
  2967 
  3009 
  2968 size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pledgedSrcSize)
  3010 size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pledgedSrcSize)
  2969 {
  3011 {
  2970     ZSTD_parameters const params = ZSTD_getParams(compressionLevel, pledgedSrcSize, 0);
  3012     ZSTD_parameters params = ZSTD_getParams(compressionLevel, pledgedSrcSize, 0);
       
  3013     if (pledgedSrcSize) params.fParams.contentSizeFlag = 1;
  2971     return ZSTD_initCStream_advanced(zcs, NULL, 0, params, pledgedSrcSize);
  3014     return ZSTD_initCStream_advanced(zcs, NULL, 0, params, pledgedSrcSize);
  2972 }
  3015 }
  2973 
  3016 
  2974 size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel)
  3017 size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel)
  2975 {
  3018 {