18c2ecf20Sopenharmony_ci/** 28c2ecf20Sopenharmony_ci * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. 38c2ecf20Sopenharmony_ci * All rights reserved. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * This source code is licensed under the BSD-style license found in the 68c2ecf20Sopenharmony_ci * LICENSE file in the root directory of https://github.com/facebook/zstd. 78c2ecf20Sopenharmony_ci * An additional grant of patent rights can be found in the PATENTS file in the 88c2ecf20Sopenharmony_ci * same directory. 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * This program is free software; you can redistribute it and/or modify it under 118c2ecf20Sopenharmony_ci * the terms of the GNU General Public License version 2 as published by the 128c2ecf20Sopenharmony_ci * Free Software Foundation. This program is dual-licensed; you may select 138c2ecf20Sopenharmony_ci * either version 2 of the GNU General Public License ("GPL") or BSD license 148c2ecf20Sopenharmony_ci * ("BSD"). 158c2ecf20Sopenharmony_ci */ 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci/*-************************************* 188c2ecf20Sopenharmony_ci* Dependencies 198c2ecf20Sopenharmony_ci***************************************/ 208c2ecf20Sopenharmony_ci#include "fse.h" 218c2ecf20Sopenharmony_ci#include "huf.h" 228c2ecf20Sopenharmony_ci#include "mem.h" 238c2ecf20Sopenharmony_ci#include "zstd_internal.h" /* includes zstd.h */ 248c2ecf20Sopenharmony_ci#include <linux/kernel.h> 258c2ecf20Sopenharmony_ci#include <linux/module.h> 268c2ecf20Sopenharmony_ci#include <linux/string.h> /* memset */ 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci/*-************************************* 298c2ecf20Sopenharmony_ci* Constants 308c2ecf20Sopenharmony_ci***************************************/ 318c2ecf20Sopenharmony_cistatic const U32 g_searchStrength = 8; /* control skip over incompressible data */ 328c2ecf20Sopenharmony_ci#define HASH_READ_SIZE 8 338c2ecf20Sopenharmony_citypedef enum { ZSTDcs_created = 0, ZSTDcs_init, ZSTDcs_ongoing, ZSTDcs_ending } ZSTD_compressionStage_e; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci/*-************************************* 368c2ecf20Sopenharmony_ci* Helper functions 378c2ecf20Sopenharmony_ci***************************************/ 388c2ecf20Sopenharmony_cisize_t ZSTD_compressBound(size_t srcSize) { return FSE_compressBound(srcSize) + 12; } 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci/*-************************************* 418c2ecf20Sopenharmony_ci* Sequence storage 428c2ecf20Sopenharmony_ci***************************************/ 438c2ecf20Sopenharmony_cistatic void ZSTD_resetSeqStore(seqStore_t *ssPtr) 448c2ecf20Sopenharmony_ci{ 458c2ecf20Sopenharmony_ci ssPtr->lit = ssPtr->litStart; 468c2ecf20Sopenharmony_ci ssPtr->sequences = ssPtr->sequencesStart; 478c2ecf20Sopenharmony_ci ssPtr->longLengthID = 0; 488c2ecf20Sopenharmony_ci} 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci/*-************************************* 518c2ecf20Sopenharmony_ci* Context memory management 528c2ecf20Sopenharmony_ci***************************************/ 538c2ecf20Sopenharmony_cistruct ZSTD_CCtx_s { 548c2ecf20Sopenharmony_ci const BYTE *nextSrc; /* next block here to continue on curr prefix */ 558c2ecf20Sopenharmony_ci const BYTE *base; /* All regular indexes relative to this position */ 568c2ecf20Sopenharmony_ci const BYTE *dictBase; /* extDict indexes relative to this position */ 578c2ecf20Sopenharmony_ci U32 dictLimit; /* below that point, need extDict */ 588c2ecf20Sopenharmony_ci U32 lowLimit; /* below that point, no more data */ 598c2ecf20Sopenharmony_ci U32 nextToUpdate; /* index from which to continue dictionary update */ 608c2ecf20Sopenharmony_ci U32 nextToUpdate3; /* index from which to continue dictionary update */ 618c2ecf20Sopenharmony_ci U32 hashLog3; /* dispatch table : larger == faster, more memory */ 628c2ecf20Sopenharmony_ci U32 loadedDictEnd; /* index of end of dictionary */ 638c2ecf20Sopenharmony_ci U32 forceWindow; /* force back-references to respect limit of 1<<wLog, even for dictionary */ 648c2ecf20Sopenharmony_ci U32 forceRawDict; /* Force loading dictionary in "content-only" mode (no header analysis) */ 658c2ecf20Sopenharmony_ci ZSTD_compressionStage_e stage; 668c2ecf20Sopenharmony_ci U32 rep[ZSTD_REP_NUM]; 678c2ecf20Sopenharmony_ci U32 repToConfirm[ZSTD_REP_NUM]; 688c2ecf20Sopenharmony_ci U32 dictID; 698c2ecf20Sopenharmony_ci ZSTD_parameters params; 708c2ecf20Sopenharmony_ci void *workSpace; 718c2ecf20Sopenharmony_ci size_t workSpaceSize; 728c2ecf20Sopenharmony_ci size_t blockSize; 738c2ecf20Sopenharmony_ci U64 frameContentSize; 748c2ecf20Sopenharmony_ci struct xxh64_state xxhState; 758c2ecf20Sopenharmony_ci ZSTD_customMem customMem; 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci seqStore_t seqStore; /* sequences storage ptrs */ 788c2ecf20Sopenharmony_ci U32 *hashTable; 798c2ecf20Sopenharmony_ci U32 *hashTable3; 808c2ecf20Sopenharmony_ci U32 *chainTable; 818c2ecf20Sopenharmony_ci HUF_CElt *hufTable; 828c2ecf20Sopenharmony_ci U32 flagStaticTables; 838c2ecf20Sopenharmony_ci HUF_repeat flagStaticHufTable; 848c2ecf20Sopenharmony_ci FSE_CTable offcodeCTable[FSE_CTABLE_SIZE_U32(OffFSELog, MaxOff)]; 858c2ecf20Sopenharmony_ci FSE_CTable matchlengthCTable[FSE_CTABLE_SIZE_U32(MLFSELog, MaxML)]; 868c2ecf20Sopenharmony_ci FSE_CTable litlengthCTable[FSE_CTABLE_SIZE_U32(LLFSELog, MaxLL)]; 878c2ecf20Sopenharmony_ci unsigned tmpCounters[HUF_COMPRESS_WORKSPACE_SIZE_U32]; 888c2ecf20Sopenharmony_ci}; 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_cisize_t ZSTD_CCtxWorkspaceBound(ZSTD_compressionParameters cParams) 918c2ecf20Sopenharmony_ci{ 928c2ecf20Sopenharmony_ci size_t const blockSize = MIN(ZSTD_BLOCKSIZE_ABSOLUTEMAX, (size_t)1 << cParams.windowLog); 938c2ecf20Sopenharmony_ci U32 const divider = (cParams.searchLength == 3) ? 3 : 4; 948c2ecf20Sopenharmony_ci size_t const maxNbSeq = blockSize / divider; 958c2ecf20Sopenharmony_ci size_t const tokenSpace = blockSize + 11 * maxNbSeq; 968c2ecf20Sopenharmony_ci size_t const chainSize = (cParams.strategy == ZSTD_fast) ? 0 : (1 << cParams.chainLog); 978c2ecf20Sopenharmony_ci size_t const hSize = ((size_t)1) << cParams.hashLog; 988c2ecf20Sopenharmony_ci U32 const hashLog3 = (cParams.searchLength > 3) ? 0 : MIN(ZSTD_HASHLOG3_MAX, cParams.windowLog); 998c2ecf20Sopenharmony_ci size_t const h3Size = ((size_t)1) << hashLog3; 1008c2ecf20Sopenharmony_ci size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32); 1018c2ecf20Sopenharmony_ci size_t const optSpace = 1028c2ecf20Sopenharmony_ci ((MaxML + 1) + (MaxLL + 1) + (MaxOff + 1) + (1 << Litbits)) * sizeof(U32) + (ZSTD_OPT_NUM + 1) * (sizeof(ZSTD_match_t) + sizeof(ZSTD_optimal_t)); 1038c2ecf20Sopenharmony_ci size_t const workspaceSize = tableSpace + (256 * sizeof(U32)) /* huffTable */ + tokenSpace + 1048c2ecf20Sopenharmony_ci (((cParams.strategy == ZSTD_btopt) || (cParams.strategy == ZSTD_btopt2)) ? optSpace : 0); 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci return ZSTD_ALIGN(sizeof(ZSTD_stack)) + ZSTD_ALIGN(sizeof(ZSTD_CCtx)) + ZSTD_ALIGN(workspaceSize); 1078c2ecf20Sopenharmony_ci} 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_cistatic ZSTD_CCtx *ZSTD_createCCtx_advanced(ZSTD_customMem customMem) 1108c2ecf20Sopenharmony_ci{ 1118c2ecf20Sopenharmony_ci ZSTD_CCtx *cctx; 1128c2ecf20Sopenharmony_ci if (!customMem.customAlloc || !customMem.customFree) 1138c2ecf20Sopenharmony_ci return NULL; 1148c2ecf20Sopenharmony_ci cctx = (ZSTD_CCtx *)ZSTD_malloc(sizeof(ZSTD_CCtx), customMem); 1158c2ecf20Sopenharmony_ci if (!cctx) 1168c2ecf20Sopenharmony_ci return NULL; 1178c2ecf20Sopenharmony_ci memset(cctx, 0, sizeof(ZSTD_CCtx)); 1188c2ecf20Sopenharmony_ci cctx->customMem = customMem; 1198c2ecf20Sopenharmony_ci return cctx; 1208c2ecf20Sopenharmony_ci} 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ciZSTD_CCtx *ZSTD_initCCtx(void *workspace, size_t workspaceSize) 1238c2ecf20Sopenharmony_ci{ 1248c2ecf20Sopenharmony_ci ZSTD_customMem const stackMem = ZSTD_initStack(workspace, workspaceSize); 1258c2ecf20Sopenharmony_ci ZSTD_CCtx *cctx = ZSTD_createCCtx_advanced(stackMem); 1268c2ecf20Sopenharmony_ci if (cctx) { 1278c2ecf20Sopenharmony_ci cctx->workSpace = ZSTD_stackAllocAll(cctx->customMem.opaque, &cctx->workSpaceSize); 1288c2ecf20Sopenharmony_ci } 1298c2ecf20Sopenharmony_ci return cctx; 1308c2ecf20Sopenharmony_ci} 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_cisize_t ZSTD_freeCCtx(ZSTD_CCtx *cctx) 1338c2ecf20Sopenharmony_ci{ 1348c2ecf20Sopenharmony_ci if (cctx == NULL) 1358c2ecf20Sopenharmony_ci return 0; /* support free on NULL */ 1368c2ecf20Sopenharmony_ci ZSTD_free(cctx->workSpace, cctx->customMem); 1378c2ecf20Sopenharmony_ci ZSTD_free(cctx, cctx->customMem); 1388c2ecf20Sopenharmony_ci return 0; /* reserved as a potential error code in the future */ 1398c2ecf20Sopenharmony_ci} 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ciconst seqStore_t *ZSTD_getSeqStore(const ZSTD_CCtx *ctx) /* hidden interface */ { return &(ctx->seqStore); } 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_cistatic ZSTD_parameters ZSTD_getParamsFromCCtx(const ZSTD_CCtx *cctx) { return cctx->params; } 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci/** ZSTD_checkParams() : 1468c2ecf20Sopenharmony_ci ensure param values remain within authorized range. 1478c2ecf20Sopenharmony_ci @return : 0, or an error code if one value is beyond authorized range */ 1488c2ecf20Sopenharmony_cisize_t ZSTD_checkCParams(ZSTD_compressionParameters cParams) 1498c2ecf20Sopenharmony_ci{ 1508c2ecf20Sopenharmony_ci#define CLAMPCHECK(val, min, max) \ 1518c2ecf20Sopenharmony_ci { \ 1528c2ecf20Sopenharmony_ci if ((val < min) | (val > max)) \ 1538c2ecf20Sopenharmony_ci return ERROR(compressionParameter_unsupported); \ 1548c2ecf20Sopenharmony_ci } 1558c2ecf20Sopenharmony_ci CLAMPCHECK(cParams.windowLog, ZSTD_WINDOWLOG_MIN, ZSTD_WINDOWLOG_MAX); 1568c2ecf20Sopenharmony_ci CLAMPCHECK(cParams.chainLog, ZSTD_CHAINLOG_MIN, ZSTD_CHAINLOG_MAX); 1578c2ecf20Sopenharmony_ci CLAMPCHECK(cParams.hashLog, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX); 1588c2ecf20Sopenharmony_ci CLAMPCHECK(cParams.searchLog, ZSTD_SEARCHLOG_MIN, ZSTD_SEARCHLOG_MAX); 1598c2ecf20Sopenharmony_ci CLAMPCHECK(cParams.searchLength, ZSTD_SEARCHLENGTH_MIN, ZSTD_SEARCHLENGTH_MAX); 1608c2ecf20Sopenharmony_ci CLAMPCHECK(cParams.targetLength, ZSTD_TARGETLENGTH_MIN, ZSTD_TARGETLENGTH_MAX); 1618c2ecf20Sopenharmony_ci if ((U32)(cParams.strategy) > (U32)ZSTD_btopt2) 1628c2ecf20Sopenharmony_ci return ERROR(compressionParameter_unsupported); 1638c2ecf20Sopenharmony_ci return 0; 1648c2ecf20Sopenharmony_ci} 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci/** ZSTD_cycleLog() : 1678c2ecf20Sopenharmony_ci * condition for correct operation : hashLog > 1 */ 1688c2ecf20Sopenharmony_cistatic U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat) 1698c2ecf20Sopenharmony_ci{ 1708c2ecf20Sopenharmony_ci U32 const btScale = ((U32)strat >= (U32)ZSTD_btlazy2); 1718c2ecf20Sopenharmony_ci return hashLog - btScale; 1728c2ecf20Sopenharmony_ci} 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci/** ZSTD_adjustCParams() : 1758c2ecf20Sopenharmony_ci optimize `cPar` for a given input (`srcSize` and `dictSize`). 1768c2ecf20Sopenharmony_ci mostly downsizing to reduce memory consumption and initialization. 1778c2ecf20Sopenharmony_ci Both `srcSize` and `dictSize` are optional (use 0 if unknown), 1788c2ecf20Sopenharmony_ci but if both are 0, no optimization can be done. 1798c2ecf20Sopenharmony_ci Note : cPar is considered validated at this stage. Use ZSTD_checkParams() to ensure that. */ 1808c2ecf20Sopenharmony_ciZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize) 1818c2ecf20Sopenharmony_ci{ 1828c2ecf20Sopenharmony_ci if (srcSize + dictSize == 0) 1838c2ecf20Sopenharmony_ci return cPar; /* no size information available : no adjustment */ 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci /* resize params, to use less memory when necessary */ 1868c2ecf20Sopenharmony_ci { 1878c2ecf20Sopenharmony_ci U32 const minSrcSize = (srcSize == 0) ? 500 : 0; 1888c2ecf20Sopenharmony_ci U64 const rSize = srcSize + dictSize + minSrcSize; 1898c2ecf20Sopenharmony_ci if (rSize < ((U64)1 << ZSTD_WINDOWLOG_MAX)) { 1908c2ecf20Sopenharmony_ci U32 const srcLog = MAX(ZSTD_HASHLOG_MIN, ZSTD_highbit32((U32)(rSize)-1) + 1); 1918c2ecf20Sopenharmony_ci if (cPar.windowLog > srcLog) 1928c2ecf20Sopenharmony_ci cPar.windowLog = srcLog; 1938c2ecf20Sopenharmony_ci } 1948c2ecf20Sopenharmony_ci } 1958c2ecf20Sopenharmony_ci if (cPar.hashLog > cPar.windowLog) 1968c2ecf20Sopenharmony_ci cPar.hashLog = cPar.windowLog; 1978c2ecf20Sopenharmony_ci { 1988c2ecf20Sopenharmony_ci U32 const cycleLog = ZSTD_cycleLog(cPar.chainLog, cPar.strategy); 1998c2ecf20Sopenharmony_ci if (cycleLog > cPar.windowLog) 2008c2ecf20Sopenharmony_ci cPar.chainLog -= (cycleLog - cPar.windowLog); 2018c2ecf20Sopenharmony_ci } 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci if (cPar.windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN) 2048c2ecf20Sopenharmony_ci cPar.windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN; /* required for frame header */ 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci return cPar; 2078c2ecf20Sopenharmony_ci} 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_cistatic U32 ZSTD_equivalentParams(ZSTD_parameters param1, ZSTD_parameters param2) 2108c2ecf20Sopenharmony_ci{ 2118c2ecf20Sopenharmony_ci return (param1.cParams.hashLog == param2.cParams.hashLog) & (param1.cParams.chainLog == param2.cParams.chainLog) & 2128c2ecf20Sopenharmony_ci (param1.cParams.strategy == param2.cParams.strategy) & ((param1.cParams.searchLength == 3) == (param2.cParams.searchLength == 3)); 2138c2ecf20Sopenharmony_ci} 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci/*! ZSTD_continueCCtx() : 2168c2ecf20Sopenharmony_ci reuse CCtx without reset (note : requires no dictionary) */ 2178c2ecf20Sopenharmony_cistatic size_t ZSTD_continueCCtx(ZSTD_CCtx *cctx, ZSTD_parameters params, U64 frameContentSize) 2188c2ecf20Sopenharmony_ci{ 2198c2ecf20Sopenharmony_ci U32 const end = (U32)(cctx->nextSrc - cctx->base); 2208c2ecf20Sopenharmony_ci cctx->params = params; 2218c2ecf20Sopenharmony_ci cctx->frameContentSize = frameContentSize; 2228c2ecf20Sopenharmony_ci cctx->lowLimit = end; 2238c2ecf20Sopenharmony_ci cctx->dictLimit = end; 2248c2ecf20Sopenharmony_ci cctx->nextToUpdate = end + 1; 2258c2ecf20Sopenharmony_ci cctx->stage = ZSTDcs_init; 2268c2ecf20Sopenharmony_ci cctx->dictID = 0; 2278c2ecf20Sopenharmony_ci cctx->loadedDictEnd = 0; 2288c2ecf20Sopenharmony_ci { 2298c2ecf20Sopenharmony_ci int i; 2308c2ecf20Sopenharmony_ci for (i = 0; i < ZSTD_REP_NUM; i++) 2318c2ecf20Sopenharmony_ci cctx->rep[i] = repStartValue[i]; 2328c2ecf20Sopenharmony_ci } 2338c2ecf20Sopenharmony_ci cctx->seqStore.litLengthSum = 0; /* force reset of btopt stats */ 2348c2ecf20Sopenharmony_ci xxh64_reset(&cctx->xxhState, 0); 2358c2ecf20Sopenharmony_ci return 0; 2368c2ecf20Sopenharmony_ci} 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_citypedef enum { ZSTDcrp_continue, ZSTDcrp_noMemset, ZSTDcrp_fullReset } ZSTD_compResetPolicy_e; 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci/*! ZSTD_resetCCtx_advanced() : 2418c2ecf20Sopenharmony_ci note : `params` must be validated */ 2428c2ecf20Sopenharmony_cistatic size_t ZSTD_resetCCtx_advanced(ZSTD_CCtx *zc, ZSTD_parameters params, U64 frameContentSize, ZSTD_compResetPolicy_e const crp) 2438c2ecf20Sopenharmony_ci{ 2448c2ecf20Sopenharmony_ci if (crp == ZSTDcrp_continue) 2458c2ecf20Sopenharmony_ci if (ZSTD_equivalentParams(params, zc->params)) { 2468c2ecf20Sopenharmony_ci zc->flagStaticTables = 0; 2478c2ecf20Sopenharmony_ci zc->flagStaticHufTable = HUF_repeat_none; 2488c2ecf20Sopenharmony_ci return ZSTD_continueCCtx(zc, params, frameContentSize); 2498c2ecf20Sopenharmony_ci } 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci { 2528c2ecf20Sopenharmony_ci size_t const blockSize = MIN(ZSTD_BLOCKSIZE_ABSOLUTEMAX, (size_t)1 << params.cParams.windowLog); 2538c2ecf20Sopenharmony_ci U32 const divider = (params.cParams.searchLength == 3) ? 3 : 4; 2548c2ecf20Sopenharmony_ci size_t const maxNbSeq = blockSize / divider; 2558c2ecf20Sopenharmony_ci size_t const tokenSpace = blockSize + 11 * maxNbSeq; 2568c2ecf20Sopenharmony_ci size_t const chainSize = (params.cParams.strategy == ZSTD_fast) ? 0 : (1 << params.cParams.chainLog); 2578c2ecf20Sopenharmony_ci size_t const hSize = ((size_t)1) << params.cParams.hashLog; 2588c2ecf20Sopenharmony_ci U32 const hashLog3 = (params.cParams.searchLength > 3) ? 0 : MIN(ZSTD_HASHLOG3_MAX, params.cParams.windowLog); 2598c2ecf20Sopenharmony_ci size_t const h3Size = ((size_t)1) << hashLog3; 2608c2ecf20Sopenharmony_ci size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32); 2618c2ecf20Sopenharmony_ci void *ptr; 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci /* Check if workSpace is large enough, alloc a new one if needed */ 2648c2ecf20Sopenharmony_ci { 2658c2ecf20Sopenharmony_ci size_t const optSpace = ((MaxML + 1) + (MaxLL + 1) + (MaxOff + 1) + (1 << Litbits)) * sizeof(U32) + 2668c2ecf20Sopenharmony_ci (ZSTD_OPT_NUM + 1) * (sizeof(ZSTD_match_t) + sizeof(ZSTD_optimal_t)); 2678c2ecf20Sopenharmony_ci size_t const neededSpace = tableSpace + (256 * sizeof(U32)) /* huffTable */ + tokenSpace + 2688c2ecf20Sopenharmony_ci (((params.cParams.strategy == ZSTD_btopt) || (params.cParams.strategy == ZSTD_btopt2)) ? optSpace : 0); 2698c2ecf20Sopenharmony_ci if (zc->workSpaceSize < neededSpace) { 2708c2ecf20Sopenharmony_ci ZSTD_free(zc->workSpace, zc->customMem); 2718c2ecf20Sopenharmony_ci zc->workSpace = ZSTD_malloc(neededSpace, zc->customMem); 2728c2ecf20Sopenharmony_ci if (zc->workSpace == NULL) 2738c2ecf20Sopenharmony_ci return ERROR(memory_allocation); 2748c2ecf20Sopenharmony_ci zc->workSpaceSize = neededSpace; 2758c2ecf20Sopenharmony_ci } 2768c2ecf20Sopenharmony_ci } 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci if (crp != ZSTDcrp_noMemset) 2798c2ecf20Sopenharmony_ci memset(zc->workSpace, 0, tableSpace); /* reset tables only */ 2808c2ecf20Sopenharmony_ci xxh64_reset(&zc->xxhState, 0); 2818c2ecf20Sopenharmony_ci zc->hashLog3 = hashLog3; 2828c2ecf20Sopenharmony_ci zc->hashTable = (U32 *)(zc->workSpace); 2838c2ecf20Sopenharmony_ci zc->chainTable = zc->hashTable + hSize; 2848c2ecf20Sopenharmony_ci zc->hashTable3 = zc->chainTable + chainSize; 2858c2ecf20Sopenharmony_ci ptr = zc->hashTable3 + h3Size; 2868c2ecf20Sopenharmony_ci zc->hufTable = (HUF_CElt *)ptr; 2878c2ecf20Sopenharmony_ci zc->flagStaticTables = 0; 2888c2ecf20Sopenharmony_ci zc->flagStaticHufTable = HUF_repeat_none; 2898c2ecf20Sopenharmony_ci ptr = ((U32 *)ptr) + 256; /* note : HUF_CElt* is incomplete type, size is simulated using U32 */ 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci zc->nextToUpdate = 1; 2928c2ecf20Sopenharmony_ci zc->nextSrc = NULL; 2938c2ecf20Sopenharmony_ci zc->base = NULL; 2948c2ecf20Sopenharmony_ci zc->dictBase = NULL; 2958c2ecf20Sopenharmony_ci zc->dictLimit = 0; 2968c2ecf20Sopenharmony_ci zc->lowLimit = 0; 2978c2ecf20Sopenharmony_ci zc->params = params; 2988c2ecf20Sopenharmony_ci zc->blockSize = blockSize; 2998c2ecf20Sopenharmony_ci zc->frameContentSize = frameContentSize; 3008c2ecf20Sopenharmony_ci { 3018c2ecf20Sopenharmony_ci int i; 3028c2ecf20Sopenharmony_ci for (i = 0; i < ZSTD_REP_NUM; i++) 3038c2ecf20Sopenharmony_ci zc->rep[i] = repStartValue[i]; 3048c2ecf20Sopenharmony_ci } 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci if ((params.cParams.strategy == ZSTD_btopt) || (params.cParams.strategy == ZSTD_btopt2)) { 3078c2ecf20Sopenharmony_ci zc->seqStore.litFreq = (U32 *)ptr; 3088c2ecf20Sopenharmony_ci zc->seqStore.litLengthFreq = zc->seqStore.litFreq + (1 << Litbits); 3098c2ecf20Sopenharmony_ci zc->seqStore.matchLengthFreq = zc->seqStore.litLengthFreq + (MaxLL + 1); 3108c2ecf20Sopenharmony_ci zc->seqStore.offCodeFreq = zc->seqStore.matchLengthFreq + (MaxML + 1); 3118c2ecf20Sopenharmony_ci ptr = zc->seqStore.offCodeFreq + (MaxOff + 1); 3128c2ecf20Sopenharmony_ci zc->seqStore.matchTable = (ZSTD_match_t *)ptr; 3138c2ecf20Sopenharmony_ci ptr = zc->seqStore.matchTable + ZSTD_OPT_NUM + 1; 3148c2ecf20Sopenharmony_ci zc->seqStore.priceTable = (ZSTD_optimal_t *)ptr; 3158c2ecf20Sopenharmony_ci ptr = zc->seqStore.priceTable + ZSTD_OPT_NUM + 1; 3168c2ecf20Sopenharmony_ci zc->seqStore.litLengthSum = 0; 3178c2ecf20Sopenharmony_ci } 3188c2ecf20Sopenharmony_ci zc->seqStore.sequencesStart = (seqDef *)ptr; 3198c2ecf20Sopenharmony_ci ptr = zc->seqStore.sequencesStart + maxNbSeq; 3208c2ecf20Sopenharmony_ci zc->seqStore.llCode = (BYTE *)ptr; 3218c2ecf20Sopenharmony_ci zc->seqStore.mlCode = zc->seqStore.llCode + maxNbSeq; 3228c2ecf20Sopenharmony_ci zc->seqStore.ofCode = zc->seqStore.mlCode + maxNbSeq; 3238c2ecf20Sopenharmony_ci zc->seqStore.litStart = zc->seqStore.ofCode + maxNbSeq; 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci zc->stage = ZSTDcs_init; 3268c2ecf20Sopenharmony_ci zc->dictID = 0; 3278c2ecf20Sopenharmony_ci zc->loadedDictEnd = 0; 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci return 0; 3308c2ecf20Sopenharmony_ci } 3318c2ecf20Sopenharmony_ci} 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci/* ZSTD_invalidateRepCodes() : 3348c2ecf20Sopenharmony_ci * ensures next compression will not use repcodes from previous block. 3358c2ecf20Sopenharmony_ci * Note : only works with regular variant; 3368c2ecf20Sopenharmony_ci * do not use with extDict variant ! */ 3378c2ecf20Sopenharmony_civoid ZSTD_invalidateRepCodes(ZSTD_CCtx *cctx) 3388c2ecf20Sopenharmony_ci{ 3398c2ecf20Sopenharmony_ci int i; 3408c2ecf20Sopenharmony_ci for (i = 0; i < ZSTD_REP_NUM; i++) 3418c2ecf20Sopenharmony_ci cctx->rep[i] = 0; 3428c2ecf20Sopenharmony_ci} 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci/*! ZSTD_copyCCtx() : 3458c2ecf20Sopenharmony_ci* Duplicate an existing context `srcCCtx` into another one `dstCCtx`. 3468c2ecf20Sopenharmony_ci* Only works during stage ZSTDcs_init (i.e. after creation, but before first call to ZSTD_compressContinue()). 3478c2ecf20Sopenharmony_ci* @return : 0, or an error code */ 3488c2ecf20Sopenharmony_cisize_t ZSTD_copyCCtx(ZSTD_CCtx *dstCCtx, const ZSTD_CCtx *srcCCtx, unsigned long long pledgedSrcSize) 3498c2ecf20Sopenharmony_ci{ 3508c2ecf20Sopenharmony_ci if (srcCCtx->stage != ZSTDcs_init) 3518c2ecf20Sopenharmony_ci return ERROR(stage_wrong); 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci memcpy(&dstCCtx->customMem, &srcCCtx->customMem, sizeof(ZSTD_customMem)); 3548c2ecf20Sopenharmony_ci { 3558c2ecf20Sopenharmony_ci ZSTD_parameters params = srcCCtx->params; 3568c2ecf20Sopenharmony_ci params.fParams.contentSizeFlag = (pledgedSrcSize > 0); 3578c2ecf20Sopenharmony_ci ZSTD_resetCCtx_advanced(dstCCtx, params, pledgedSrcSize, ZSTDcrp_noMemset); 3588c2ecf20Sopenharmony_ci } 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci /* copy tables */ 3618c2ecf20Sopenharmony_ci { 3628c2ecf20Sopenharmony_ci size_t const chainSize = (srcCCtx->params.cParams.strategy == ZSTD_fast) ? 0 : (1 << srcCCtx->params.cParams.chainLog); 3638c2ecf20Sopenharmony_ci size_t const hSize = ((size_t)1) << srcCCtx->params.cParams.hashLog; 3648c2ecf20Sopenharmony_ci size_t const h3Size = (size_t)1 << srcCCtx->hashLog3; 3658c2ecf20Sopenharmony_ci size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32); 3668c2ecf20Sopenharmony_ci memcpy(dstCCtx->workSpace, srcCCtx->workSpace, tableSpace); 3678c2ecf20Sopenharmony_ci } 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci /* copy dictionary offsets */ 3708c2ecf20Sopenharmony_ci dstCCtx->nextToUpdate = srcCCtx->nextToUpdate; 3718c2ecf20Sopenharmony_ci dstCCtx->nextToUpdate3 = srcCCtx->nextToUpdate3; 3728c2ecf20Sopenharmony_ci dstCCtx->nextSrc = srcCCtx->nextSrc; 3738c2ecf20Sopenharmony_ci dstCCtx->base = srcCCtx->base; 3748c2ecf20Sopenharmony_ci dstCCtx->dictBase = srcCCtx->dictBase; 3758c2ecf20Sopenharmony_ci dstCCtx->dictLimit = srcCCtx->dictLimit; 3768c2ecf20Sopenharmony_ci dstCCtx->lowLimit = srcCCtx->lowLimit; 3778c2ecf20Sopenharmony_ci dstCCtx->loadedDictEnd = srcCCtx->loadedDictEnd; 3788c2ecf20Sopenharmony_ci dstCCtx->dictID = srcCCtx->dictID; 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci /* copy entropy tables */ 3818c2ecf20Sopenharmony_ci dstCCtx->flagStaticTables = srcCCtx->flagStaticTables; 3828c2ecf20Sopenharmony_ci dstCCtx->flagStaticHufTable = srcCCtx->flagStaticHufTable; 3838c2ecf20Sopenharmony_ci if (srcCCtx->flagStaticTables) { 3848c2ecf20Sopenharmony_ci memcpy(dstCCtx->litlengthCTable, srcCCtx->litlengthCTable, sizeof(dstCCtx->litlengthCTable)); 3858c2ecf20Sopenharmony_ci memcpy(dstCCtx->matchlengthCTable, srcCCtx->matchlengthCTable, sizeof(dstCCtx->matchlengthCTable)); 3868c2ecf20Sopenharmony_ci memcpy(dstCCtx->offcodeCTable, srcCCtx->offcodeCTable, sizeof(dstCCtx->offcodeCTable)); 3878c2ecf20Sopenharmony_ci } 3888c2ecf20Sopenharmony_ci if (srcCCtx->flagStaticHufTable) { 3898c2ecf20Sopenharmony_ci memcpy(dstCCtx->hufTable, srcCCtx->hufTable, 256 * 4); 3908c2ecf20Sopenharmony_ci } 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci return 0; 3938c2ecf20Sopenharmony_ci} 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci/*! ZSTD_reduceTable() : 3968c2ecf20Sopenharmony_ci* reduce table indexes by `reducerValue` */ 3978c2ecf20Sopenharmony_cistatic void ZSTD_reduceTable(U32 *const table, U32 const size, U32 const reducerValue) 3988c2ecf20Sopenharmony_ci{ 3998c2ecf20Sopenharmony_ci U32 u; 4008c2ecf20Sopenharmony_ci for (u = 0; u < size; u++) { 4018c2ecf20Sopenharmony_ci if (table[u] < reducerValue) 4028c2ecf20Sopenharmony_ci table[u] = 0; 4038c2ecf20Sopenharmony_ci else 4048c2ecf20Sopenharmony_ci table[u] -= reducerValue; 4058c2ecf20Sopenharmony_ci } 4068c2ecf20Sopenharmony_ci} 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci/*! ZSTD_reduceIndex() : 4098c2ecf20Sopenharmony_ci* rescale all indexes to avoid future overflow (indexes are U32) */ 4108c2ecf20Sopenharmony_cistatic void ZSTD_reduceIndex(ZSTD_CCtx *zc, const U32 reducerValue) 4118c2ecf20Sopenharmony_ci{ 4128c2ecf20Sopenharmony_ci { 4138c2ecf20Sopenharmony_ci U32 const hSize = 1 << zc->params.cParams.hashLog; 4148c2ecf20Sopenharmony_ci ZSTD_reduceTable(zc->hashTable, hSize, reducerValue); 4158c2ecf20Sopenharmony_ci } 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci { 4188c2ecf20Sopenharmony_ci U32 const chainSize = (zc->params.cParams.strategy == ZSTD_fast) ? 0 : (1 << zc->params.cParams.chainLog); 4198c2ecf20Sopenharmony_ci ZSTD_reduceTable(zc->chainTable, chainSize, reducerValue); 4208c2ecf20Sopenharmony_ci } 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci { 4238c2ecf20Sopenharmony_ci U32 const h3Size = (zc->hashLog3) ? 1 << zc->hashLog3 : 0; 4248c2ecf20Sopenharmony_ci ZSTD_reduceTable(zc->hashTable3, h3Size, reducerValue); 4258c2ecf20Sopenharmony_ci } 4268c2ecf20Sopenharmony_ci} 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci/*-******************************************************* 4298c2ecf20Sopenharmony_ci* Block entropic compression 4308c2ecf20Sopenharmony_ci*********************************************************/ 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci/* See doc/zstd_compression_format.md for detailed format description */ 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_cisize_t ZSTD_noCompressBlock(void *dst, size_t dstCapacity, const void *src, size_t srcSize) 4358c2ecf20Sopenharmony_ci{ 4368c2ecf20Sopenharmony_ci if (srcSize + ZSTD_blockHeaderSize > dstCapacity) 4378c2ecf20Sopenharmony_ci return ERROR(dstSize_tooSmall); 4388c2ecf20Sopenharmony_ci memcpy((BYTE *)dst + ZSTD_blockHeaderSize, src, srcSize); 4398c2ecf20Sopenharmony_ci ZSTD_writeLE24(dst, (U32)(srcSize << 2) + (U32)bt_raw); 4408c2ecf20Sopenharmony_ci return ZSTD_blockHeaderSize + srcSize; 4418c2ecf20Sopenharmony_ci} 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_cistatic size_t ZSTD_noCompressLiterals(void *dst, size_t dstCapacity, const void *src, size_t srcSize) 4448c2ecf20Sopenharmony_ci{ 4458c2ecf20Sopenharmony_ci BYTE *const ostart = (BYTE * const)dst; 4468c2ecf20Sopenharmony_ci U32 const flSize = 1 + (srcSize > 31) + (srcSize > 4095); 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_ci if (srcSize + flSize > dstCapacity) 4498c2ecf20Sopenharmony_ci return ERROR(dstSize_tooSmall); 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_ci switch (flSize) { 4528c2ecf20Sopenharmony_ci case 1: /* 2 - 1 - 5 */ ostart[0] = (BYTE)((U32)set_basic + (srcSize << 3)); break; 4538c2ecf20Sopenharmony_ci case 2: /* 2 - 2 - 12 */ ZSTD_writeLE16(ostart, (U16)((U32)set_basic + (1 << 2) + (srcSize << 4))); break; 4548c2ecf20Sopenharmony_ci default: /*note : should not be necessary : flSize is within {1,2,3} */ 4558c2ecf20Sopenharmony_ci case 3: /* 2 - 2 - 20 */ ZSTD_writeLE32(ostart, (U32)((U32)set_basic + (3 << 2) + (srcSize << 4))); break; 4568c2ecf20Sopenharmony_ci } 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_ci memcpy(ostart + flSize, src, srcSize); 4598c2ecf20Sopenharmony_ci return srcSize + flSize; 4608c2ecf20Sopenharmony_ci} 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_cistatic size_t ZSTD_compressRleLiteralsBlock(void *dst, size_t dstCapacity, const void *src, size_t srcSize) 4638c2ecf20Sopenharmony_ci{ 4648c2ecf20Sopenharmony_ci BYTE *const ostart = (BYTE * const)dst; 4658c2ecf20Sopenharmony_ci U32 const flSize = 1 + (srcSize > 31) + (srcSize > 4095); 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci (void)dstCapacity; /* dstCapacity already guaranteed to be >=4, hence large enough */ 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci switch (flSize) { 4708c2ecf20Sopenharmony_ci case 1: /* 2 - 1 - 5 */ ostart[0] = (BYTE)((U32)set_rle + (srcSize << 3)); break; 4718c2ecf20Sopenharmony_ci case 2: /* 2 - 2 - 12 */ ZSTD_writeLE16(ostart, (U16)((U32)set_rle + (1 << 2) + (srcSize << 4))); break; 4728c2ecf20Sopenharmony_ci default: /*note : should not be necessary : flSize is necessarily within {1,2,3} */ 4738c2ecf20Sopenharmony_ci case 3: /* 2 - 2 - 20 */ ZSTD_writeLE32(ostart, (U32)((U32)set_rle + (3 << 2) + (srcSize << 4))); break; 4748c2ecf20Sopenharmony_ci } 4758c2ecf20Sopenharmony_ci 4768c2ecf20Sopenharmony_ci ostart[flSize] = *(const BYTE *)src; 4778c2ecf20Sopenharmony_ci return flSize + 1; 4788c2ecf20Sopenharmony_ci} 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_cistatic size_t ZSTD_minGain(size_t srcSize) { return (srcSize >> 6) + 2; } 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_cistatic size_t ZSTD_compressLiterals(ZSTD_CCtx *zc, void *dst, size_t dstCapacity, const void *src, size_t srcSize) 4838c2ecf20Sopenharmony_ci{ 4848c2ecf20Sopenharmony_ci size_t const minGain = ZSTD_minGain(srcSize); 4858c2ecf20Sopenharmony_ci size_t const lhSize = 3 + (srcSize >= 1 KB) + (srcSize >= 16 KB); 4868c2ecf20Sopenharmony_ci BYTE *const ostart = (BYTE *)dst; 4878c2ecf20Sopenharmony_ci U32 singleStream = srcSize < 256; 4888c2ecf20Sopenharmony_ci symbolEncodingType_e hType = set_compressed; 4898c2ecf20Sopenharmony_ci size_t cLitSize; 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_ci/* small ? don't even attempt compression (speed opt) */ 4928c2ecf20Sopenharmony_ci#define LITERAL_NOENTROPY 63 4938c2ecf20Sopenharmony_ci { 4948c2ecf20Sopenharmony_ci size_t const minLitSize = zc->flagStaticHufTable == HUF_repeat_valid ? 6 : LITERAL_NOENTROPY; 4958c2ecf20Sopenharmony_ci if (srcSize <= minLitSize) 4968c2ecf20Sopenharmony_ci return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize); 4978c2ecf20Sopenharmony_ci } 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci if (dstCapacity < lhSize + 1) 5008c2ecf20Sopenharmony_ci return ERROR(dstSize_tooSmall); /* not enough space for compression */ 5018c2ecf20Sopenharmony_ci { 5028c2ecf20Sopenharmony_ci HUF_repeat repeat = zc->flagStaticHufTable; 5038c2ecf20Sopenharmony_ci int const preferRepeat = zc->params.cParams.strategy < ZSTD_lazy ? srcSize <= 1024 : 0; 5048c2ecf20Sopenharmony_ci if (repeat == HUF_repeat_valid && lhSize == 3) 5058c2ecf20Sopenharmony_ci singleStream = 1; 5068c2ecf20Sopenharmony_ci cLitSize = singleStream ? HUF_compress1X_repeat(ostart + lhSize, dstCapacity - lhSize, src, srcSize, 255, 11, zc->tmpCounters, 5078c2ecf20Sopenharmony_ci sizeof(zc->tmpCounters), zc->hufTable, &repeat, preferRepeat) 5088c2ecf20Sopenharmony_ci : HUF_compress4X_repeat(ostart + lhSize, dstCapacity - lhSize, src, srcSize, 255, 11, zc->tmpCounters, 5098c2ecf20Sopenharmony_ci sizeof(zc->tmpCounters), zc->hufTable, &repeat, preferRepeat); 5108c2ecf20Sopenharmony_ci if (repeat != HUF_repeat_none) { 5118c2ecf20Sopenharmony_ci hType = set_repeat; 5128c2ecf20Sopenharmony_ci } /* reused the existing table */ 5138c2ecf20Sopenharmony_ci else { 5148c2ecf20Sopenharmony_ci zc->flagStaticHufTable = HUF_repeat_check; 5158c2ecf20Sopenharmony_ci } /* now have a table to reuse */ 5168c2ecf20Sopenharmony_ci } 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_ci if ((cLitSize == 0) | (cLitSize >= srcSize - minGain)) { 5198c2ecf20Sopenharmony_ci zc->flagStaticHufTable = HUF_repeat_none; 5208c2ecf20Sopenharmony_ci return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize); 5218c2ecf20Sopenharmony_ci } 5228c2ecf20Sopenharmony_ci if (cLitSize == 1) { 5238c2ecf20Sopenharmony_ci zc->flagStaticHufTable = HUF_repeat_none; 5248c2ecf20Sopenharmony_ci return ZSTD_compressRleLiteralsBlock(dst, dstCapacity, src, srcSize); 5258c2ecf20Sopenharmony_ci } 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci /* Build header */ 5288c2ecf20Sopenharmony_ci switch (lhSize) { 5298c2ecf20Sopenharmony_ci case 3: /* 2 - 2 - 10 - 10 */ 5308c2ecf20Sopenharmony_ci { 5318c2ecf20Sopenharmony_ci U32 const lhc = hType + ((!singleStream) << 2) + ((U32)srcSize << 4) + ((U32)cLitSize << 14); 5328c2ecf20Sopenharmony_ci ZSTD_writeLE24(ostart, lhc); 5338c2ecf20Sopenharmony_ci break; 5348c2ecf20Sopenharmony_ci } 5358c2ecf20Sopenharmony_ci case 4: /* 2 - 2 - 14 - 14 */ 5368c2ecf20Sopenharmony_ci { 5378c2ecf20Sopenharmony_ci U32 const lhc = hType + (2 << 2) + ((U32)srcSize << 4) + ((U32)cLitSize << 18); 5388c2ecf20Sopenharmony_ci ZSTD_writeLE32(ostart, lhc); 5398c2ecf20Sopenharmony_ci break; 5408c2ecf20Sopenharmony_ci } 5418c2ecf20Sopenharmony_ci default: /* should not be necessary, lhSize is only {3,4,5} */ 5428c2ecf20Sopenharmony_ci case 5: /* 2 - 2 - 18 - 18 */ 5438c2ecf20Sopenharmony_ci { 5448c2ecf20Sopenharmony_ci U32 const lhc = hType + (3 << 2) + ((U32)srcSize << 4) + ((U32)cLitSize << 22); 5458c2ecf20Sopenharmony_ci ZSTD_writeLE32(ostart, lhc); 5468c2ecf20Sopenharmony_ci ostart[4] = (BYTE)(cLitSize >> 10); 5478c2ecf20Sopenharmony_ci break; 5488c2ecf20Sopenharmony_ci } 5498c2ecf20Sopenharmony_ci } 5508c2ecf20Sopenharmony_ci return lhSize + cLitSize; 5518c2ecf20Sopenharmony_ci} 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_cistatic const BYTE LL_Code[64] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 16, 17, 17, 18, 18, 5548c2ecf20Sopenharmony_ci 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 5558c2ecf20Sopenharmony_ci 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24}; 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_cistatic const BYTE ML_Code[128] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 5588c2ecf20Sopenharmony_ci 26, 27, 28, 29, 30, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 36, 36, 37, 37, 37, 37, 38, 38, 38, 38, 5598c2ecf20Sopenharmony_ci 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 5608c2ecf20Sopenharmony_ci 40, 40, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 42, 42, 42, 42, 42, 42, 42, 42, 5618c2ecf20Sopenharmony_ci 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42}; 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_civoid ZSTD_seqToCodes(const seqStore_t *seqStorePtr) 5648c2ecf20Sopenharmony_ci{ 5658c2ecf20Sopenharmony_ci BYTE const LL_deltaCode = 19; 5668c2ecf20Sopenharmony_ci BYTE const ML_deltaCode = 36; 5678c2ecf20Sopenharmony_ci const seqDef *const sequences = seqStorePtr->sequencesStart; 5688c2ecf20Sopenharmony_ci BYTE *const llCodeTable = seqStorePtr->llCode; 5698c2ecf20Sopenharmony_ci BYTE *const ofCodeTable = seqStorePtr->ofCode; 5708c2ecf20Sopenharmony_ci BYTE *const mlCodeTable = seqStorePtr->mlCode; 5718c2ecf20Sopenharmony_ci U32 const nbSeq = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart); 5728c2ecf20Sopenharmony_ci U32 u; 5738c2ecf20Sopenharmony_ci for (u = 0; u < nbSeq; u++) { 5748c2ecf20Sopenharmony_ci U32 const llv = sequences[u].litLength; 5758c2ecf20Sopenharmony_ci U32 const mlv = sequences[u].matchLength; 5768c2ecf20Sopenharmony_ci llCodeTable[u] = (llv > 63) ? (BYTE)ZSTD_highbit32(llv) + LL_deltaCode : LL_Code[llv]; 5778c2ecf20Sopenharmony_ci ofCodeTable[u] = (BYTE)ZSTD_highbit32(sequences[u].offset); 5788c2ecf20Sopenharmony_ci mlCodeTable[u] = (mlv > 127) ? (BYTE)ZSTD_highbit32(mlv) + ML_deltaCode : ML_Code[mlv]; 5798c2ecf20Sopenharmony_ci } 5808c2ecf20Sopenharmony_ci if (seqStorePtr->longLengthID == 1) 5818c2ecf20Sopenharmony_ci llCodeTable[seqStorePtr->longLengthPos] = MaxLL; 5828c2ecf20Sopenharmony_ci if (seqStorePtr->longLengthID == 2) 5838c2ecf20Sopenharmony_ci mlCodeTable[seqStorePtr->longLengthPos] = MaxML; 5848c2ecf20Sopenharmony_ci} 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_ciZSTD_STATIC size_t ZSTD_compressSequences_internal(ZSTD_CCtx *zc, void *dst, size_t dstCapacity) 5878c2ecf20Sopenharmony_ci{ 5888c2ecf20Sopenharmony_ci const int longOffsets = zc->params.cParams.windowLog > STREAM_ACCUMULATOR_MIN; 5898c2ecf20Sopenharmony_ci const seqStore_t *seqStorePtr = &(zc->seqStore); 5908c2ecf20Sopenharmony_ci FSE_CTable *CTable_LitLength = zc->litlengthCTable; 5918c2ecf20Sopenharmony_ci FSE_CTable *CTable_OffsetBits = zc->offcodeCTable; 5928c2ecf20Sopenharmony_ci FSE_CTable *CTable_MatchLength = zc->matchlengthCTable; 5938c2ecf20Sopenharmony_ci U32 LLtype, Offtype, MLtype; /* compressed, raw or rle */ 5948c2ecf20Sopenharmony_ci const seqDef *const sequences = seqStorePtr->sequencesStart; 5958c2ecf20Sopenharmony_ci const BYTE *const ofCodeTable = seqStorePtr->ofCode; 5968c2ecf20Sopenharmony_ci const BYTE *const llCodeTable = seqStorePtr->llCode; 5978c2ecf20Sopenharmony_ci const BYTE *const mlCodeTable = seqStorePtr->mlCode; 5988c2ecf20Sopenharmony_ci BYTE *const ostart = (BYTE *)dst; 5998c2ecf20Sopenharmony_ci BYTE *const oend = ostart + dstCapacity; 6008c2ecf20Sopenharmony_ci BYTE *op = ostart; 6018c2ecf20Sopenharmony_ci size_t const nbSeq = seqStorePtr->sequences - seqStorePtr->sequencesStart; 6028c2ecf20Sopenharmony_ci BYTE *seqHead; 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_ci U32 *count; 6058c2ecf20Sopenharmony_ci S16 *norm; 6068c2ecf20Sopenharmony_ci U32 *workspace; 6078c2ecf20Sopenharmony_ci size_t workspaceSize = sizeof(zc->tmpCounters); 6088c2ecf20Sopenharmony_ci { 6098c2ecf20Sopenharmony_ci size_t spaceUsed32 = 0; 6108c2ecf20Sopenharmony_ci count = (U32 *)zc->tmpCounters + spaceUsed32; 6118c2ecf20Sopenharmony_ci spaceUsed32 += MaxSeq + 1; 6128c2ecf20Sopenharmony_ci norm = (S16 *)((U32 *)zc->tmpCounters + spaceUsed32); 6138c2ecf20Sopenharmony_ci spaceUsed32 += ALIGN(sizeof(S16) * (MaxSeq + 1), sizeof(U32)) >> 2; 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_ci workspace = (U32 *)zc->tmpCounters + spaceUsed32; 6168c2ecf20Sopenharmony_ci workspaceSize -= (spaceUsed32 << 2); 6178c2ecf20Sopenharmony_ci } 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_ci /* Compress literals */ 6208c2ecf20Sopenharmony_ci { 6218c2ecf20Sopenharmony_ci const BYTE *const literals = seqStorePtr->litStart; 6228c2ecf20Sopenharmony_ci size_t const litSize = seqStorePtr->lit - literals; 6238c2ecf20Sopenharmony_ci size_t const cSize = ZSTD_compressLiterals(zc, op, dstCapacity, literals, litSize); 6248c2ecf20Sopenharmony_ci if (ZSTD_isError(cSize)) 6258c2ecf20Sopenharmony_ci return cSize; 6268c2ecf20Sopenharmony_ci op += cSize; 6278c2ecf20Sopenharmony_ci } 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_ci /* Sequences Header */ 6308c2ecf20Sopenharmony_ci if ((oend - op) < 3 /*max nbSeq Size*/ + 1 /*seqHead */) 6318c2ecf20Sopenharmony_ci return ERROR(dstSize_tooSmall); 6328c2ecf20Sopenharmony_ci if (nbSeq < 0x7F) 6338c2ecf20Sopenharmony_ci *op++ = (BYTE)nbSeq; 6348c2ecf20Sopenharmony_ci else if (nbSeq < LONGNBSEQ) 6358c2ecf20Sopenharmony_ci op[0] = (BYTE)((nbSeq >> 8) + 0x80), op[1] = (BYTE)nbSeq, op += 2; 6368c2ecf20Sopenharmony_ci else 6378c2ecf20Sopenharmony_ci op[0] = 0xFF, ZSTD_writeLE16(op + 1, (U16)(nbSeq - LONGNBSEQ)), op += 3; 6388c2ecf20Sopenharmony_ci if (nbSeq == 0) 6398c2ecf20Sopenharmony_ci return op - ostart; 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_ci /* seqHead : flags for FSE encoding type */ 6428c2ecf20Sopenharmony_ci seqHead = op++; 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_ci#define MIN_SEQ_FOR_DYNAMIC_FSE 64 6458c2ecf20Sopenharmony_ci#define MAX_SEQ_FOR_STATIC_FSE 1000 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_ci /* convert length/distances into codes */ 6488c2ecf20Sopenharmony_ci ZSTD_seqToCodes(seqStorePtr); 6498c2ecf20Sopenharmony_ci 6508c2ecf20Sopenharmony_ci /* CTable for Literal Lengths */ 6518c2ecf20Sopenharmony_ci { 6528c2ecf20Sopenharmony_ci U32 max = MaxLL; 6538c2ecf20Sopenharmony_ci size_t const mostFrequent = FSE_countFast_wksp(count, &max, llCodeTable, nbSeq, workspace); 6548c2ecf20Sopenharmony_ci if ((mostFrequent == nbSeq) && (nbSeq > 2)) { 6558c2ecf20Sopenharmony_ci *op++ = llCodeTable[0]; 6568c2ecf20Sopenharmony_ci FSE_buildCTable_rle(CTable_LitLength, (BYTE)max); 6578c2ecf20Sopenharmony_ci LLtype = set_rle; 6588c2ecf20Sopenharmony_ci } else if ((zc->flagStaticTables) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) { 6598c2ecf20Sopenharmony_ci LLtype = set_repeat; 6608c2ecf20Sopenharmony_ci } else if ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (LL_defaultNormLog - 1)))) { 6618c2ecf20Sopenharmony_ci FSE_buildCTable_wksp(CTable_LitLength, LL_defaultNorm, MaxLL, LL_defaultNormLog, workspace, workspaceSize); 6628c2ecf20Sopenharmony_ci LLtype = set_basic; 6638c2ecf20Sopenharmony_ci } else { 6648c2ecf20Sopenharmony_ci size_t nbSeq_1 = nbSeq; 6658c2ecf20Sopenharmony_ci const U32 tableLog = FSE_optimalTableLog(LLFSELog, nbSeq, max); 6668c2ecf20Sopenharmony_ci if (count[llCodeTable[nbSeq - 1]] > 1) { 6678c2ecf20Sopenharmony_ci count[llCodeTable[nbSeq - 1]]--; 6688c2ecf20Sopenharmony_ci nbSeq_1--; 6698c2ecf20Sopenharmony_ci } 6708c2ecf20Sopenharmony_ci FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max); 6718c2ecf20Sopenharmony_ci { 6728c2ecf20Sopenharmony_ci size_t const NCountSize = FSE_writeNCount(op, oend - op, norm, max, tableLog); /* overflow protected */ 6738c2ecf20Sopenharmony_ci if (FSE_isError(NCountSize)) 6748c2ecf20Sopenharmony_ci return NCountSize; 6758c2ecf20Sopenharmony_ci op += NCountSize; 6768c2ecf20Sopenharmony_ci } 6778c2ecf20Sopenharmony_ci FSE_buildCTable_wksp(CTable_LitLength, norm, max, tableLog, workspace, workspaceSize); 6788c2ecf20Sopenharmony_ci LLtype = set_compressed; 6798c2ecf20Sopenharmony_ci } 6808c2ecf20Sopenharmony_ci } 6818c2ecf20Sopenharmony_ci 6828c2ecf20Sopenharmony_ci /* CTable for Offsets */ 6838c2ecf20Sopenharmony_ci { 6848c2ecf20Sopenharmony_ci U32 max = MaxOff; 6858c2ecf20Sopenharmony_ci size_t const mostFrequent = FSE_countFast_wksp(count, &max, ofCodeTable, nbSeq, workspace); 6868c2ecf20Sopenharmony_ci if ((mostFrequent == nbSeq) && (nbSeq > 2)) { 6878c2ecf20Sopenharmony_ci *op++ = ofCodeTable[0]; 6888c2ecf20Sopenharmony_ci FSE_buildCTable_rle(CTable_OffsetBits, (BYTE)max); 6898c2ecf20Sopenharmony_ci Offtype = set_rle; 6908c2ecf20Sopenharmony_ci } else if ((zc->flagStaticTables) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) { 6918c2ecf20Sopenharmony_ci Offtype = set_repeat; 6928c2ecf20Sopenharmony_ci } else if ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (OF_defaultNormLog - 1)))) { 6938c2ecf20Sopenharmony_ci FSE_buildCTable_wksp(CTable_OffsetBits, OF_defaultNorm, MaxOff, OF_defaultNormLog, workspace, workspaceSize); 6948c2ecf20Sopenharmony_ci Offtype = set_basic; 6958c2ecf20Sopenharmony_ci } else { 6968c2ecf20Sopenharmony_ci size_t nbSeq_1 = nbSeq; 6978c2ecf20Sopenharmony_ci const U32 tableLog = FSE_optimalTableLog(OffFSELog, nbSeq, max); 6988c2ecf20Sopenharmony_ci if (count[ofCodeTable[nbSeq - 1]] > 1) { 6998c2ecf20Sopenharmony_ci count[ofCodeTable[nbSeq - 1]]--; 7008c2ecf20Sopenharmony_ci nbSeq_1--; 7018c2ecf20Sopenharmony_ci } 7028c2ecf20Sopenharmony_ci FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max); 7038c2ecf20Sopenharmony_ci { 7048c2ecf20Sopenharmony_ci size_t const NCountSize = FSE_writeNCount(op, oend - op, norm, max, tableLog); /* overflow protected */ 7058c2ecf20Sopenharmony_ci if (FSE_isError(NCountSize)) 7068c2ecf20Sopenharmony_ci return NCountSize; 7078c2ecf20Sopenharmony_ci op += NCountSize; 7088c2ecf20Sopenharmony_ci } 7098c2ecf20Sopenharmony_ci FSE_buildCTable_wksp(CTable_OffsetBits, norm, max, tableLog, workspace, workspaceSize); 7108c2ecf20Sopenharmony_ci Offtype = set_compressed; 7118c2ecf20Sopenharmony_ci } 7128c2ecf20Sopenharmony_ci } 7138c2ecf20Sopenharmony_ci 7148c2ecf20Sopenharmony_ci /* CTable for MatchLengths */ 7158c2ecf20Sopenharmony_ci { 7168c2ecf20Sopenharmony_ci U32 max = MaxML; 7178c2ecf20Sopenharmony_ci size_t const mostFrequent = FSE_countFast_wksp(count, &max, mlCodeTable, nbSeq, workspace); 7188c2ecf20Sopenharmony_ci if ((mostFrequent == nbSeq) && (nbSeq > 2)) { 7198c2ecf20Sopenharmony_ci *op++ = *mlCodeTable; 7208c2ecf20Sopenharmony_ci FSE_buildCTable_rle(CTable_MatchLength, (BYTE)max); 7218c2ecf20Sopenharmony_ci MLtype = set_rle; 7228c2ecf20Sopenharmony_ci } else if ((zc->flagStaticTables) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) { 7238c2ecf20Sopenharmony_ci MLtype = set_repeat; 7248c2ecf20Sopenharmony_ci } else if ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (ML_defaultNormLog - 1)))) { 7258c2ecf20Sopenharmony_ci FSE_buildCTable_wksp(CTable_MatchLength, ML_defaultNorm, MaxML, ML_defaultNormLog, workspace, workspaceSize); 7268c2ecf20Sopenharmony_ci MLtype = set_basic; 7278c2ecf20Sopenharmony_ci } else { 7288c2ecf20Sopenharmony_ci size_t nbSeq_1 = nbSeq; 7298c2ecf20Sopenharmony_ci const U32 tableLog = FSE_optimalTableLog(MLFSELog, nbSeq, max); 7308c2ecf20Sopenharmony_ci if (count[mlCodeTable[nbSeq - 1]] > 1) { 7318c2ecf20Sopenharmony_ci count[mlCodeTable[nbSeq - 1]]--; 7328c2ecf20Sopenharmony_ci nbSeq_1--; 7338c2ecf20Sopenharmony_ci } 7348c2ecf20Sopenharmony_ci FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max); 7358c2ecf20Sopenharmony_ci { 7368c2ecf20Sopenharmony_ci size_t const NCountSize = FSE_writeNCount(op, oend - op, norm, max, tableLog); /* overflow protected */ 7378c2ecf20Sopenharmony_ci if (FSE_isError(NCountSize)) 7388c2ecf20Sopenharmony_ci return NCountSize; 7398c2ecf20Sopenharmony_ci op += NCountSize; 7408c2ecf20Sopenharmony_ci } 7418c2ecf20Sopenharmony_ci FSE_buildCTable_wksp(CTable_MatchLength, norm, max, tableLog, workspace, workspaceSize); 7428c2ecf20Sopenharmony_ci MLtype = set_compressed; 7438c2ecf20Sopenharmony_ci } 7448c2ecf20Sopenharmony_ci } 7458c2ecf20Sopenharmony_ci 7468c2ecf20Sopenharmony_ci *seqHead = (BYTE)((LLtype << 6) + (Offtype << 4) + (MLtype << 2)); 7478c2ecf20Sopenharmony_ci zc->flagStaticTables = 0; 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_ci /* Encoding Sequences */ 7508c2ecf20Sopenharmony_ci { 7518c2ecf20Sopenharmony_ci BIT_CStream_t blockStream; 7528c2ecf20Sopenharmony_ci FSE_CState_t stateMatchLength; 7538c2ecf20Sopenharmony_ci FSE_CState_t stateOffsetBits; 7548c2ecf20Sopenharmony_ci FSE_CState_t stateLitLength; 7558c2ecf20Sopenharmony_ci 7568c2ecf20Sopenharmony_ci CHECK_E(BIT_initCStream(&blockStream, op, oend - op), dstSize_tooSmall); /* not enough space remaining */ 7578c2ecf20Sopenharmony_ci 7588c2ecf20Sopenharmony_ci /* first symbols */ 7598c2ecf20Sopenharmony_ci FSE_initCState2(&stateMatchLength, CTable_MatchLength, mlCodeTable[nbSeq - 1]); 7608c2ecf20Sopenharmony_ci FSE_initCState2(&stateOffsetBits, CTable_OffsetBits, ofCodeTable[nbSeq - 1]); 7618c2ecf20Sopenharmony_ci FSE_initCState2(&stateLitLength, CTable_LitLength, llCodeTable[nbSeq - 1]); 7628c2ecf20Sopenharmony_ci BIT_addBits(&blockStream, sequences[nbSeq - 1].litLength, LL_bits[llCodeTable[nbSeq - 1]]); 7638c2ecf20Sopenharmony_ci if (ZSTD_32bits()) 7648c2ecf20Sopenharmony_ci BIT_flushBits(&blockStream); 7658c2ecf20Sopenharmony_ci BIT_addBits(&blockStream, sequences[nbSeq - 1].matchLength, ML_bits[mlCodeTable[nbSeq - 1]]); 7668c2ecf20Sopenharmony_ci if (ZSTD_32bits()) 7678c2ecf20Sopenharmony_ci BIT_flushBits(&blockStream); 7688c2ecf20Sopenharmony_ci if (longOffsets) { 7698c2ecf20Sopenharmony_ci U32 const ofBits = ofCodeTable[nbSeq - 1]; 7708c2ecf20Sopenharmony_ci int const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN - 1); 7718c2ecf20Sopenharmony_ci if (extraBits) { 7728c2ecf20Sopenharmony_ci BIT_addBits(&blockStream, sequences[nbSeq - 1].offset, extraBits); 7738c2ecf20Sopenharmony_ci BIT_flushBits(&blockStream); 7748c2ecf20Sopenharmony_ci } 7758c2ecf20Sopenharmony_ci BIT_addBits(&blockStream, sequences[nbSeq - 1].offset >> extraBits, ofBits - extraBits); 7768c2ecf20Sopenharmony_ci } else { 7778c2ecf20Sopenharmony_ci BIT_addBits(&blockStream, sequences[nbSeq - 1].offset, ofCodeTable[nbSeq - 1]); 7788c2ecf20Sopenharmony_ci } 7798c2ecf20Sopenharmony_ci BIT_flushBits(&blockStream); 7808c2ecf20Sopenharmony_ci 7818c2ecf20Sopenharmony_ci { 7828c2ecf20Sopenharmony_ci size_t n; 7838c2ecf20Sopenharmony_ci for (n = nbSeq - 2; n < nbSeq; n--) { /* intentional underflow */ 7848c2ecf20Sopenharmony_ci BYTE const llCode = llCodeTable[n]; 7858c2ecf20Sopenharmony_ci BYTE const ofCode = ofCodeTable[n]; 7868c2ecf20Sopenharmony_ci BYTE const mlCode = mlCodeTable[n]; 7878c2ecf20Sopenharmony_ci U32 const llBits = LL_bits[llCode]; 7888c2ecf20Sopenharmony_ci U32 const ofBits = ofCode; /* 32b*/ /* 64b*/ 7898c2ecf20Sopenharmony_ci U32 const mlBits = ML_bits[mlCode]; 7908c2ecf20Sopenharmony_ci /* (7)*/ /* (7)*/ 7918c2ecf20Sopenharmony_ci FSE_encodeSymbol(&blockStream, &stateOffsetBits, ofCode); /* 15 */ /* 15 */ 7928c2ecf20Sopenharmony_ci FSE_encodeSymbol(&blockStream, &stateMatchLength, mlCode); /* 24 */ /* 24 */ 7938c2ecf20Sopenharmony_ci if (ZSTD_32bits()) 7948c2ecf20Sopenharmony_ci BIT_flushBits(&blockStream); /* (7)*/ 7958c2ecf20Sopenharmony_ci FSE_encodeSymbol(&blockStream, &stateLitLength, llCode); /* 16 */ /* 33 */ 7968c2ecf20Sopenharmony_ci if (ZSTD_32bits() || (ofBits + mlBits + llBits >= 64 - 7 - (LLFSELog + MLFSELog + OffFSELog))) 7978c2ecf20Sopenharmony_ci BIT_flushBits(&blockStream); /* (7)*/ 7988c2ecf20Sopenharmony_ci BIT_addBits(&blockStream, sequences[n].litLength, llBits); 7998c2ecf20Sopenharmony_ci if (ZSTD_32bits() && ((llBits + mlBits) > 24)) 8008c2ecf20Sopenharmony_ci BIT_flushBits(&blockStream); 8018c2ecf20Sopenharmony_ci BIT_addBits(&blockStream, sequences[n].matchLength, mlBits); 8028c2ecf20Sopenharmony_ci if (ZSTD_32bits()) 8038c2ecf20Sopenharmony_ci BIT_flushBits(&blockStream); /* (7)*/ 8048c2ecf20Sopenharmony_ci if (longOffsets) { 8058c2ecf20Sopenharmony_ci int const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN - 1); 8068c2ecf20Sopenharmony_ci if (extraBits) { 8078c2ecf20Sopenharmony_ci BIT_addBits(&blockStream, sequences[n].offset, extraBits); 8088c2ecf20Sopenharmony_ci BIT_flushBits(&blockStream); /* (7)*/ 8098c2ecf20Sopenharmony_ci } 8108c2ecf20Sopenharmony_ci BIT_addBits(&blockStream, sequences[n].offset >> extraBits, ofBits - extraBits); /* 31 */ 8118c2ecf20Sopenharmony_ci } else { 8128c2ecf20Sopenharmony_ci BIT_addBits(&blockStream, sequences[n].offset, ofBits); /* 31 */ 8138c2ecf20Sopenharmony_ci } 8148c2ecf20Sopenharmony_ci BIT_flushBits(&blockStream); /* (7)*/ 8158c2ecf20Sopenharmony_ci } 8168c2ecf20Sopenharmony_ci } 8178c2ecf20Sopenharmony_ci 8188c2ecf20Sopenharmony_ci FSE_flushCState(&blockStream, &stateMatchLength); 8198c2ecf20Sopenharmony_ci FSE_flushCState(&blockStream, &stateOffsetBits); 8208c2ecf20Sopenharmony_ci FSE_flushCState(&blockStream, &stateLitLength); 8218c2ecf20Sopenharmony_ci 8228c2ecf20Sopenharmony_ci { 8238c2ecf20Sopenharmony_ci size_t const streamSize = BIT_closeCStream(&blockStream); 8248c2ecf20Sopenharmony_ci if (streamSize == 0) 8258c2ecf20Sopenharmony_ci return ERROR(dstSize_tooSmall); /* not enough space */ 8268c2ecf20Sopenharmony_ci op += streamSize; 8278c2ecf20Sopenharmony_ci } 8288c2ecf20Sopenharmony_ci } 8298c2ecf20Sopenharmony_ci return op - ostart; 8308c2ecf20Sopenharmony_ci} 8318c2ecf20Sopenharmony_ci 8328c2ecf20Sopenharmony_ciZSTD_STATIC size_t ZSTD_compressSequences(ZSTD_CCtx *zc, void *dst, size_t dstCapacity, size_t srcSize) 8338c2ecf20Sopenharmony_ci{ 8348c2ecf20Sopenharmony_ci size_t const cSize = ZSTD_compressSequences_internal(zc, dst, dstCapacity); 8358c2ecf20Sopenharmony_ci size_t const minGain = ZSTD_minGain(srcSize); 8368c2ecf20Sopenharmony_ci size_t const maxCSize = srcSize - minGain; 8378c2ecf20Sopenharmony_ci /* If the srcSize <= dstCapacity, then there is enough space to write a 8388c2ecf20Sopenharmony_ci * raw uncompressed block. Since we ran out of space, the block must not 8398c2ecf20Sopenharmony_ci * be compressible, so fall back to a raw uncompressed block. 8408c2ecf20Sopenharmony_ci */ 8418c2ecf20Sopenharmony_ci int const uncompressibleError = cSize == ERROR(dstSize_tooSmall) && srcSize <= dstCapacity; 8428c2ecf20Sopenharmony_ci int i; 8438c2ecf20Sopenharmony_ci 8448c2ecf20Sopenharmony_ci if (ZSTD_isError(cSize) && !uncompressibleError) 8458c2ecf20Sopenharmony_ci return cSize; 8468c2ecf20Sopenharmony_ci if (cSize >= maxCSize || uncompressibleError) { 8478c2ecf20Sopenharmony_ci zc->flagStaticHufTable = HUF_repeat_none; 8488c2ecf20Sopenharmony_ci return 0; 8498c2ecf20Sopenharmony_ci } 8508c2ecf20Sopenharmony_ci /* confirm repcodes */ 8518c2ecf20Sopenharmony_ci for (i = 0; i < ZSTD_REP_NUM; i++) 8528c2ecf20Sopenharmony_ci zc->rep[i] = zc->repToConfirm[i]; 8538c2ecf20Sopenharmony_ci return cSize; 8548c2ecf20Sopenharmony_ci} 8558c2ecf20Sopenharmony_ci 8568c2ecf20Sopenharmony_ci/*! ZSTD_storeSeq() : 8578c2ecf20Sopenharmony_ci Store a sequence (literal length, literals, offset code and match length code) into seqStore_t. 8588c2ecf20Sopenharmony_ci `offsetCode` : distance to match, or 0 == repCode. 8598c2ecf20Sopenharmony_ci `matchCode` : matchLength - MINMATCH 8608c2ecf20Sopenharmony_ci*/ 8618c2ecf20Sopenharmony_ciZSTD_STATIC void ZSTD_storeSeq(seqStore_t *seqStorePtr, size_t litLength, const void *literals, U32 offsetCode, size_t matchCode) 8628c2ecf20Sopenharmony_ci{ 8638c2ecf20Sopenharmony_ci /* copy Literals */ 8648c2ecf20Sopenharmony_ci ZSTD_wildcopy(seqStorePtr->lit, literals, litLength); 8658c2ecf20Sopenharmony_ci seqStorePtr->lit += litLength; 8668c2ecf20Sopenharmony_ci 8678c2ecf20Sopenharmony_ci /* literal Length */ 8688c2ecf20Sopenharmony_ci if (litLength > 0xFFFF) { 8698c2ecf20Sopenharmony_ci seqStorePtr->longLengthID = 1; 8708c2ecf20Sopenharmony_ci seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart); 8718c2ecf20Sopenharmony_ci } 8728c2ecf20Sopenharmony_ci seqStorePtr->sequences[0].litLength = (U16)litLength; 8738c2ecf20Sopenharmony_ci 8748c2ecf20Sopenharmony_ci /* match offset */ 8758c2ecf20Sopenharmony_ci seqStorePtr->sequences[0].offset = offsetCode + 1; 8768c2ecf20Sopenharmony_ci 8778c2ecf20Sopenharmony_ci /* match Length */ 8788c2ecf20Sopenharmony_ci if (matchCode > 0xFFFF) { 8798c2ecf20Sopenharmony_ci seqStorePtr->longLengthID = 2; 8808c2ecf20Sopenharmony_ci seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart); 8818c2ecf20Sopenharmony_ci } 8828c2ecf20Sopenharmony_ci seqStorePtr->sequences[0].matchLength = (U16)matchCode; 8838c2ecf20Sopenharmony_ci 8848c2ecf20Sopenharmony_ci seqStorePtr->sequences++; 8858c2ecf20Sopenharmony_ci} 8868c2ecf20Sopenharmony_ci 8878c2ecf20Sopenharmony_ci/*-************************************* 8888c2ecf20Sopenharmony_ci* Match length counter 8898c2ecf20Sopenharmony_ci***************************************/ 8908c2ecf20Sopenharmony_cistatic unsigned ZSTD_NbCommonBytes(register size_t val) 8918c2ecf20Sopenharmony_ci{ 8928c2ecf20Sopenharmony_ci if (ZSTD_isLittleEndian()) { 8938c2ecf20Sopenharmony_ci if (ZSTD_64bits()) { 8948c2ecf20Sopenharmony_ci return (__builtin_ctzll((U64)val) >> 3); 8958c2ecf20Sopenharmony_ci } else { /* 32 bits */ 8968c2ecf20Sopenharmony_ci return (__builtin_ctz((U32)val) >> 3); 8978c2ecf20Sopenharmony_ci } 8988c2ecf20Sopenharmony_ci } else { /* Big Endian CPU */ 8998c2ecf20Sopenharmony_ci if (ZSTD_64bits()) { 9008c2ecf20Sopenharmony_ci return (__builtin_clzll(val) >> 3); 9018c2ecf20Sopenharmony_ci } else { /* 32 bits */ 9028c2ecf20Sopenharmony_ci return (__builtin_clz((U32)val) >> 3); 9038c2ecf20Sopenharmony_ci } 9048c2ecf20Sopenharmony_ci } 9058c2ecf20Sopenharmony_ci} 9068c2ecf20Sopenharmony_ci 9078c2ecf20Sopenharmony_cistatic size_t ZSTD_count(const BYTE *pIn, const BYTE *pMatch, const BYTE *const pInLimit) 9088c2ecf20Sopenharmony_ci{ 9098c2ecf20Sopenharmony_ci const BYTE *const pStart = pIn; 9108c2ecf20Sopenharmony_ci const BYTE *const pInLoopLimit = pInLimit - (sizeof(size_t) - 1); 9118c2ecf20Sopenharmony_ci 9128c2ecf20Sopenharmony_ci while (pIn < pInLoopLimit) { 9138c2ecf20Sopenharmony_ci size_t const diff = ZSTD_readST(pMatch) ^ ZSTD_readST(pIn); 9148c2ecf20Sopenharmony_ci if (!diff) { 9158c2ecf20Sopenharmony_ci pIn += sizeof(size_t); 9168c2ecf20Sopenharmony_ci pMatch += sizeof(size_t); 9178c2ecf20Sopenharmony_ci continue; 9188c2ecf20Sopenharmony_ci } 9198c2ecf20Sopenharmony_ci pIn += ZSTD_NbCommonBytes(diff); 9208c2ecf20Sopenharmony_ci return (size_t)(pIn - pStart); 9218c2ecf20Sopenharmony_ci } 9228c2ecf20Sopenharmony_ci if (ZSTD_64bits()) 9238c2ecf20Sopenharmony_ci if ((pIn < (pInLimit - 3)) && (ZSTD_read32(pMatch) == ZSTD_read32(pIn))) { 9248c2ecf20Sopenharmony_ci pIn += 4; 9258c2ecf20Sopenharmony_ci pMatch += 4; 9268c2ecf20Sopenharmony_ci } 9278c2ecf20Sopenharmony_ci if ((pIn < (pInLimit - 1)) && (ZSTD_read16(pMatch) == ZSTD_read16(pIn))) { 9288c2ecf20Sopenharmony_ci pIn += 2; 9298c2ecf20Sopenharmony_ci pMatch += 2; 9308c2ecf20Sopenharmony_ci } 9318c2ecf20Sopenharmony_ci if ((pIn < pInLimit) && (*pMatch == *pIn)) 9328c2ecf20Sopenharmony_ci pIn++; 9338c2ecf20Sopenharmony_ci return (size_t)(pIn - pStart); 9348c2ecf20Sopenharmony_ci} 9358c2ecf20Sopenharmony_ci 9368c2ecf20Sopenharmony_ci/** ZSTD_count_2segments() : 9378c2ecf20Sopenharmony_ci* can count match length with `ip` & `match` in 2 different segments. 9388c2ecf20Sopenharmony_ci* convention : on reaching mEnd, match count continue starting from iStart 9398c2ecf20Sopenharmony_ci*/ 9408c2ecf20Sopenharmony_cistatic size_t ZSTD_count_2segments(const BYTE *ip, const BYTE *match, const BYTE *iEnd, const BYTE *mEnd, const BYTE *iStart) 9418c2ecf20Sopenharmony_ci{ 9428c2ecf20Sopenharmony_ci const BYTE *const vEnd = MIN(ip + (mEnd - match), iEnd); 9438c2ecf20Sopenharmony_ci size_t const matchLength = ZSTD_count(ip, match, vEnd); 9448c2ecf20Sopenharmony_ci if (match + matchLength != mEnd) 9458c2ecf20Sopenharmony_ci return matchLength; 9468c2ecf20Sopenharmony_ci return matchLength + ZSTD_count(ip + matchLength, iStart, iEnd); 9478c2ecf20Sopenharmony_ci} 9488c2ecf20Sopenharmony_ci 9498c2ecf20Sopenharmony_ci/*-************************************* 9508c2ecf20Sopenharmony_ci* Hashes 9518c2ecf20Sopenharmony_ci***************************************/ 9528c2ecf20Sopenharmony_cistatic const U32 prime3bytes = 506832829U; 9538c2ecf20Sopenharmony_cistatic U32 ZSTD_hash3(U32 u, U32 h) { return ((u << (32 - 24)) * prime3bytes) >> (32 - h); } 9548c2ecf20Sopenharmony_ciZSTD_STATIC size_t ZSTD_hash3Ptr(const void *ptr, U32 h) { return ZSTD_hash3(ZSTD_readLE32(ptr), h); } /* only in zstd_opt.h */ 9558c2ecf20Sopenharmony_ci 9568c2ecf20Sopenharmony_cistatic const U32 prime4bytes = 2654435761U; 9578c2ecf20Sopenharmony_cistatic U32 ZSTD_hash4(U32 u, U32 h) { return (u * prime4bytes) >> (32 - h); } 9588c2ecf20Sopenharmony_cistatic size_t ZSTD_hash4Ptr(const void *ptr, U32 h) { return ZSTD_hash4(ZSTD_read32(ptr), h); } 9598c2ecf20Sopenharmony_ci 9608c2ecf20Sopenharmony_cistatic const U64 prime5bytes = 889523592379ULL; 9618c2ecf20Sopenharmony_cistatic size_t ZSTD_hash5(U64 u, U32 h) { return (size_t)(((u << (64 - 40)) * prime5bytes) >> (64 - h)); } 9628c2ecf20Sopenharmony_cistatic size_t ZSTD_hash5Ptr(const void *p, U32 h) { return ZSTD_hash5(ZSTD_readLE64(p), h); } 9638c2ecf20Sopenharmony_ci 9648c2ecf20Sopenharmony_cistatic const U64 prime6bytes = 227718039650203ULL; 9658c2ecf20Sopenharmony_cistatic size_t ZSTD_hash6(U64 u, U32 h) { return (size_t)(((u << (64 - 48)) * prime6bytes) >> (64 - h)); } 9668c2ecf20Sopenharmony_cistatic size_t ZSTD_hash6Ptr(const void *p, U32 h) { return ZSTD_hash6(ZSTD_readLE64(p), h); } 9678c2ecf20Sopenharmony_ci 9688c2ecf20Sopenharmony_cistatic const U64 prime7bytes = 58295818150454627ULL; 9698c2ecf20Sopenharmony_cistatic size_t ZSTD_hash7(U64 u, U32 h) { return (size_t)(((u << (64 - 56)) * prime7bytes) >> (64 - h)); } 9708c2ecf20Sopenharmony_cistatic size_t ZSTD_hash7Ptr(const void *p, U32 h) { return ZSTD_hash7(ZSTD_readLE64(p), h); } 9718c2ecf20Sopenharmony_ci 9728c2ecf20Sopenharmony_cistatic const U64 prime8bytes = 0xCF1BBCDCB7A56463ULL; 9738c2ecf20Sopenharmony_cistatic size_t ZSTD_hash8(U64 u, U32 h) { return (size_t)(((u)*prime8bytes) >> (64 - h)); } 9748c2ecf20Sopenharmony_cistatic size_t ZSTD_hash8Ptr(const void *p, U32 h) { return ZSTD_hash8(ZSTD_readLE64(p), h); } 9758c2ecf20Sopenharmony_ci 9768c2ecf20Sopenharmony_cistatic size_t ZSTD_hashPtr(const void *p, U32 hBits, U32 mls) 9778c2ecf20Sopenharmony_ci{ 9788c2ecf20Sopenharmony_ci switch (mls) { 9798c2ecf20Sopenharmony_ci // case 3: return ZSTD_hash3Ptr(p, hBits); 9808c2ecf20Sopenharmony_ci default: 9818c2ecf20Sopenharmony_ci case 4: return ZSTD_hash4Ptr(p, hBits); 9828c2ecf20Sopenharmony_ci case 5: return ZSTD_hash5Ptr(p, hBits); 9838c2ecf20Sopenharmony_ci case 6: return ZSTD_hash6Ptr(p, hBits); 9848c2ecf20Sopenharmony_ci case 7: return ZSTD_hash7Ptr(p, hBits); 9858c2ecf20Sopenharmony_ci case 8: return ZSTD_hash8Ptr(p, hBits); 9868c2ecf20Sopenharmony_ci } 9878c2ecf20Sopenharmony_ci} 9888c2ecf20Sopenharmony_ci 9898c2ecf20Sopenharmony_ci/*-************************************* 9908c2ecf20Sopenharmony_ci* Fast Scan 9918c2ecf20Sopenharmony_ci***************************************/ 9928c2ecf20Sopenharmony_cistatic void ZSTD_fillHashTable(ZSTD_CCtx *zc, const void *end, const U32 mls) 9938c2ecf20Sopenharmony_ci{ 9948c2ecf20Sopenharmony_ci U32 *const hashTable = zc->hashTable; 9958c2ecf20Sopenharmony_ci U32 const hBits = zc->params.cParams.hashLog; 9968c2ecf20Sopenharmony_ci const BYTE *const base = zc->base; 9978c2ecf20Sopenharmony_ci const BYTE *ip = base + zc->nextToUpdate; 9988c2ecf20Sopenharmony_ci const BYTE *const iend = ((const BYTE *)end) - HASH_READ_SIZE; 9998c2ecf20Sopenharmony_ci const size_t fastHashFillStep = 3; 10008c2ecf20Sopenharmony_ci 10018c2ecf20Sopenharmony_ci while (ip <= iend) { 10028c2ecf20Sopenharmony_ci hashTable[ZSTD_hashPtr(ip, hBits, mls)] = (U32)(ip - base); 10038c2ecf20Sopenharmony_ci ip += fastHashFillStep; 10048c2ecf20Sopenharmony_ci } 10058c2ecf20Sopenharmony_ci} 10068c2ecf20Sopenharmony_ci 10078c2ecf20Sopenharmony_ciFORCE_INLINE 10088c2ecf20Sopenharmony_civoid ZSTD_compressBlock_fast_generic(ZSTD_CCtx *cctx, const void *src, size_t srcSize, const U32 mls) 10098c2ecf20Sopenharmony_ci{ 10108c2ecf20Sopenharmony_ci U32 *const hashTable = cctx->hashTable; 10118c2ecf20Sopenharmony_ci U32 const hBits = cctx->params.cParams.hashLog; 10128c2ecf20Sopenharmony_ci seqStore_t *seqStorePtr = &(cctx->seqStore); 10138c2ecf20Sopenharmony_ci const BYTE *const base = cctx->base; 10148c2ecf20Sopenharmony_ci const BYTE *const istart = (const BYTE *)src; 10158c2ecf20Sopenharmony_ci const BYTE *ip = istart; 10168c2ecf20Sopenharmony_ci const BYTE *anchor = istart; 10178c2ecf20Sopenharmony_ci const U32 lowestIndex = cctx->dictLimit; 10188c2ecf20Sopenharmony_ci const BYTE *const lowest = base + lowestIndex; 10198c2ecf20Sopenharmony_ci const BYTE *const iend = istart + srcSize; 10208c2ecf20Sopenharmony_ci const BYTE *const ilimit = iend - HASH_READ_SIZE; 10218c2ecf20Sopenharmony_ci U32 offset_1 = cctx->rep[0], offset_2 = cctx->rep[1]; 10228c2ecf20Sopenharmony_ci U32 offsetSaved = 0; 10238c2ecf20Sopenharmony_ci 10248c2ecf20Sopenharmony_ci /* init */ 10258c2ecf20Sopenharmony_ci ip += (ip == lowest); 10268c2ecf20Sopenharmony_ci { 10278c2ecf20Sopenharmony_ci U32 const maxRep = (U32)(ip - lowest); 10288c2ecf20Sopenharmony_ci if (offset_2 > maxRep) 10298c2ecf20Sopenharmony_ci offsetSaved = offset_2, offset_2 = 0; 10308c2ecf20Sopenharmony_ci if (offset_1 > maxRep) 10318c2ecf20Sopenharmony_ci offsetSaved = offset_1, offset_1 = 0; 10328c2ecf20Sopenharmony_ci } 10338c2ecf20Sopenharmony_ci 10348c2ecf20Sopenharmony_ci /* Main Search Loop */ 10358c2ecf20Sopenharmony_ci while (ip < ilimit) { /* < instead of <=, because repcode check at (ip+1) */ 10368c2ecf20Sopenharmony_ci size_t mLength; 10378c2ecf20Sopenharmony_ci size_t const h = ZSTD_hashPtr(ip, hBits, mls); 10388c2ecf20Sopenharmony_ci U32 const curr = (U32)(ip - base); 10398c2ecf20Sopenharmony_ci U32 const matchIndex = hashTable[h]; 10408c2ecf20Sopenharmony_ci const BYTE *match = base + matchIndex; 10418c2ecf20Sopenharmony_ci hashTable[h] = curr; /* update hash table */ 10428c2ecf20Sopenharmony_ci 10438c2ecf20Sopenharmony_ci if ((offset_1 > 0) & (ZSTD_read32(ip + 1 - offset_1) == ZSTD_read32(ip + 1))) { 10448c2ecf20Sopenharmony_ci mLength = ZSTD_count(ip + 1 + 4, ip + 1 + 4 - offset_1, iend) + 4; 10458c2ecf20Sopenharmony_ci ip++; 10468c2ecf20Sopenharmony_ci ZSTD_storeSeq(seqStorePtr, ip - anchor, anchor, 0, mLength - MINMATCH); 10478c2ecf20Sopenharmony_ci } else { 10488c2ecf20Sopenharmony_ci U32 offset; 10498c2ecf20Sopenharmony_ci if ((matchIndex <= lowestIndex) || (ZSTD_read32(match) != ZSTD_read32(ip))) { 10508c2ecf20Sopenharmony_ci ip += ((ip - anchor) >> g_searchStrength) + 1; 10518c2ecf20Sopenharmony_ci continue; 10528c2ecf20Sopenharmony_ci } 10538c2ecf20Sopenharmony_ci mLength = ZSTD_count(ip + 4, match + 4, iend) + 4; 10548c2ecf20Sopenharmony_ci offset = (U32)(ip - match); 10558c2ecf20Sopenharmony_ci while (((ip > anchor) & (match > lowest)) && (ip[-1] == match[-1])) { 10568c2ecf20Sopenharmony_ci ip--; 10578c2ecf20Sopenharmony_ci match--; 10588c2ecf20Sopenharmony_ci mLength++; 10598c2ecf20Sopenharmony_ci } /* catch up */ 10608c2ecf20Sopenharmony_ci offset_2 = offset_1; 10618c2ecf20Sopenharmony_ci offset_1 = offset; 10628c2ecf20Sopenharmony_ci 10638c2ecf20Sopenharmony_ci ZSTD_storeSeq(seqStorePtr, ip - anchor, anchor, offset + ZSTD_REP_MOVE, mLength - MINMATCH); 10648c2ecf20Sopenharmony_ci } 10658c2ecf20Sopenharmony_ci 10668c2ecf20Sopenharmony_ci /* match found */ 10678c2ecf20Sopenharmony_ci ip += mLength; 10688c2ecf20Sopenharmony_ci anchor = ip; 10698c2ecf20Sopenharmony_ci 10708c2ecf20Sopenharmony_ci if (ip <= ilimit) { 10718c2ecf20Sopenharmony_ci /* Fill Table */ 10728c2ecf20Sopenharmony_ci hashTable[ZSTD_hashPtr(base + curr + 2, hBits, mls)] = curr + 2; /* here because curr+2 could be > iend-8 */ 10738c2ecf20Sopenharmony_ci hashTable[ZSTD_hashPtr(ip - 2, hBits, mls)] = (U32)(ip - 2 - base); 10748c2ecf20Sopenharmony_ci /* check immediate repcode */ 10758c2ecf20Sopenharmony_ci while ((ip <= ilimit) && ((offset_2 > 0) & (ZSTD_read32(ip) == ZSTD_read32(ip - offset_2)))) { 10768c2ecf20Sopenharmony_ci /* store sequence */ 10778c2ecf20Sopenharmony_ci size_t const rLength = ZSTD_count(ip + 4, ip + 4 - offset_2, iend) + 4; 10788c2ecf20Sopenharmony_ci { 10798c2ecf20Sopenharmony_ci U32 const tmpOff = offset_2; 10808c2ecf20Sopenharmony_ci offset_2 = offset_1; 10818c2ecf20Sopenharmony_ci offset_1 = tmpOff; 10828c2ecf20Sopenharmony_ci } /* swap offset_2 <=> offset_1 */ 10838c2ecf20Sopenharmony_ci hashTable[ZSTD_hashPtr(ip, hBits, mls)] = (U32)(ip - base); 10848c2ecf20Sopenharmony_ci ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, rLength - MINMATCH); 10858c2ecf20Sopenharmony_ci ip += rLength; 10868c2ecf20Sopenharmony_ci anchor = ip; 10878c2ecf20Sopenharmony_ci continue; /* faster when present ... (?) */ 10888c2ecf20Sopenharmony_ci } 10898c2ecf20Sopenharmony_ci } 10908c2ecf20Sopenharmony_ci } 10918c2ecf20Sopenharmony_ci 10928c2ecf20Sopenharmony_ci /* save reps for next block */ 10938c2ecf20Sopenharmony_ci cctx->repToConfirm[0] = offset_1 ? offset_1 : offsetSaved; 10948c2ecf20Sopenharmony_ci cctx->repToConfirm[1] = offset_2 ? offset_2 : offsetSaved; 10958c2ecf20Sopenharmony_ci 10968c2ecf20Sopenharmony_ci /* Last Literals */ 10978c2ecf20Sopenharmony_ci { 10988c2ecf20Sopenharmony_ci size_t const lastLLSize = iend - anchor; 10998c2ecf20Sopenharmony_ci memcpy(seqStorePtr->lit, anchor, lastLLSize); 11008c2ecf20Sopenharmony_ci seqStorePtr->lit += lastLLSize; 11018c2ecf20Sopenharmony_ci } 11028c2ecf20Sopenharmony_ci} 11038c2ecf20Sopenharmony_ci 11048c2ecf20Sopenharmony_cistatic void ZSTD_compressBlock_fast(ZSTD_CCtx *ctx, const void *src, size_t srcSize) 11058c2ecf20Sopenharmony_ci{ 11068c2ecf20Sopenharmony_ci const U32 mls = ctx->params.cParams.searchLength; 11078c2ecf20Sopenharmony_ci switch (mls) { 11088c2ecf20Sopenharmony_ci default: /* includes case 3 */ 11098c2ecf20Sopenharmony_ci case 4: ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 4); return; 11108c2ecf20Sopenharmony_ci case 5: ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 5); return; 11118c2ecf20Sopenharmony_ci case 6: ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 6); return; 11128c2ecf20Sopenharmony_ci case 7: ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 7); return; 11138c2ecf20Sopenharmony_ci } 11148c2ecf20Sopenharmony_ci} 11158c2ecf20Sopenharmony_ci 11168c2ecf20Sopenharmony_cistatic void ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx *ctx, const void *src, size_t srcSize, const U32 mls) 11178c2ecf20Sopenharmony_ci{ 11188c2ecf20Sopenharmony_ci U32 *hashTable = ctx->hashTable; 11198c2ecf20Sopenharmony_ci const U32 hBits = ctx->params.cParams.hashLog; 11208c2ecf20Sopenharmony_ci seqStore_t *seqStorePtr = &(ctx->seqStore); 11218c2ecf20Sopenharmony_ci const BYTE *const base = ctx->base; 11228c2ecf20Sopenharmony_ci const BYTE *const dictBase = ctx->dictBase; 11238c2ecf20Sopenharmony_ci const BYTE *const istart = (const BYTE *)src; 11248c2ecf20Sopenharmony_ci const BYTE *ip = istart; 11258c2ecf20Sopenharmony_ci const BYTE *anchor = istart; 11268c2ecf20Sopenharmony_ci const U32 lowestIndex = ctx->lowLimit; 11278c2ecf20Sopenharmony_ci const BYTE *const dictStart = dictBase + lowestIndex; 11288c2ecf20Sopenharmony_ci const U32 dictLimit = ctx->dictLimit; 11298c2ecf20Sopenharmony_ci const BYTE *const lowPrefixPtr = base + dictLimit; 11308c2ecf20Sopenharmony_ci const BYTE *const dictEnd = dictBase + dictLimit; 11318c2ecf20Sopenharmony_ci const BYTE *const iend = istart + srcSize; 11328c2ecf20Sopenharmony_ci const BYTE *const ilimit = iend - 8; 11338c2ecf20Sopenharmony_ci U32 offset_1 = ctx->rep[0], offset_2 = ctx->rep[1]; 11348c2ecf20Sopenharmony_ci 11358c2ecf20Sopenharmony_ci /* Search Loop */ 11368c2ecf20Sopenharmony_ci while (ip < ilimit) { /* < instead of <=, because (ip+1) */ 11378c2ecf20Sopenharmony_ci const size_t h = ZSTD_hashPtr(ip, hBits, mls); 11388c2ecf20Sopenharmony_ci const U32 matchIndex = hashTable[h]; 11398c2ecf20Sopenharmony_ci const BYTE *matchBase = matchIndex < dictLimit ? dictBase : base; 11408c2ecf20Sopenharmony_ci const BYTE *match = matchBase + matchIndex; 11418c2ecf20Sopenharmony_ci const U32 curr = (U32)(ip - base); 11428c2ecf20Sopenharmony_ci const U32 repIndex = curr + 1 - offset_1; /* offset_1 expected <= curr +1 */ 11438c2ecf20Sopenharmony_ci const BYTE *repBase = repIndex < dictLimit ? dictBase : base; 11448c2ecf20Sopenharmony_ci const BYTE *repMatch = repBase + repIndex; 11458c2ecf20Sopenharmony_ci size_t mLength; 11468c2ecf20Sopenharmony_ci hashTable[h] = curr; /* update hash table */ 11478c2ecf20Sopenharmony_ci 11488c2ecf20Sopenharmony_ci if ((((U32)((dictLimit - 1) - repIndex) >= 3) /* intentional underflow */ & (repIndex > lowestIndex)) && 11498c2ecf20Sopenharmony_ci (ZSTD_read32(repMatch) == ZSTD_read32(ip + 1))) { 11508c2ecf20Sopenharmony_ci const BYTE *repMatchEnd = repIndex < dictLimit ? dictEnd : iend; 11518c2ecf20Sopenharmony_ci mLength = ZSTD_count_2segments(ip + 1 + EQUAL_READ32, repMatch + EQUAL_READ32, iend, repMatchEnd, lowPrefixPtr) + EQUAL_READ32; 11528c2ecf20Sopenharmony_ci ip++; 11538c2ecf20Sopenharmony_ci ZSTD_storeSeq(seqStorePtr, ip - anchor, anchor, 0, mLength - MINMATCH); 11548c2ecf20Sopenharmony_ci } else { 11558c2ecf20Sopenharmony_ci if ((matchIndex < lowestIndex) || (ZSTD_read32(match) != ZSTD_read32(ip))) { 11568c2ecf20Sopenharmony_ci ip += ((ip - anchor) >> g_searchStrength) + 1; 11578c2ecf20Sopenharmony_ci continue; 11588c2ecf20Sopenharmony_ci } 11598c2ecf20Sopenharmony_ci { 11608c2ecf20Sopenharmony_ci const BYTE *matchEnd = matchIndex < dictLimit ? dictEnd : iend; 11618c2ecf20Sopenharmony_ci const BYTE *lowMatchPtr = matchIndex < dictLimit ? dictStart : lowPrefixPtr; 11628c2ecf20Sopenharmony_ci U32 offset; 11638c2ecf20Sopenharmony_ci mLength = ZSTD_count_2segments(ip + EQUAL_READ32, match + EQUAL_READ32, iend, matchEnd, lowPrefixPtr) + EQUAL_READ32; 11648c2ecf20Sopenharmony_ci while (((ip > anchor) & (match > lowMatchPtr)) && (ip[-1] == match[-1])) { 11658c2ecf20Sopenharmony_ci ip--; 11668c2ecf20Sopenharmony_ci match--; 11678c2ecf20Sopenharmony_ci mLength++; 11688c2ecf20Sopenharmony_ci } /* catch up */ 11698c2ecf20Sopenharmony_ci offset = curr - matchIndex; 11708c2ecf20Sopenharmony_ci offset_2 = offset_1; 11718c2ecf20Sopenharmony_ci offset_1 = offset; 11728c2ecf20Sopenharmony_ci ZSTD_storeSeq(seqStorePtr, ip - anchor, anchor, offset + ZSTD_REP_MOVE, mLength - MINMATCH); 11738c2ecf20Sopenharmony_ci } 11748c2ecf20Sopenharmony_ci } 11758c2ecf20Sopenharmony_ci 11768c2ecf20Sopenharmony_ci /* found a match : store it */ 11778c2ecf20Sopenharmony_ci ip += mLength; 11788c2ecf20Sopenharmony_ci anchor = ip; 11798c2ecf20Sopenharmony_ci 11808c2ecf20Sopenharmony_ci if (ip <= ilimit) { 11818c2ecf20Sopenharmony_ci /* Fill Table */ 11828c2ecf20Sopenharmony_ci hashTable[ZSTD_hashPtr(base + curr + 2, hBits, mls)] = curr + 2; 11838c2ecf20Sopenharmony_ci hashTable[ZSTD_hashPtr(ip - 2, hBits, mls)] = (U32)(ip - 2 - base); 11848c2ecf20Sopenharmony_ci /* check immediate repcode */ 11858c2ecf20Sopenharmony_ci while (ip <= ilimit) { 11868c2ecf20Sopenharmony_ci U32 const curr2 = (U32)(ip - base); 11878c2ecf20Sopenharmony_ci U32 const repIndex2 = curr2 - offset_2; 11888c2ecf20Sopenharmony_ci const BYTE *repMatch2 = repIndex2 < dictLimit ? dictBase + repIndex2 : base + repIndex2; 11898c2ecf20Sopenharmony_ci if ((((U32)((dictLimit - 1) - repIndex2) >= 3) & (repIndex2 > lowestIndex)) /* intentional overflow */ 11908c2ecf20Sopenharmony_ci && (ZSTD_read32(repMatch2) == ZSTD_read32(ip))) { 11918c2ecf20Sopenharmony_ci const BYTE *const repEnd2 = repIndex2 < dictLimit ? dictEnd : iend; 11928c2ecf20Sopenharmony_ci size_t repLength2 = 11938c2ecf20Sopenharmony_ci ZSTD_count_2segments(ip + EQUAL_READ32, repMatch2 + EQUAL_READ32, iend, repEnd2, lowPrefixPtr) + EQUAL_READ32; 11948c2ecf20Sopenharmony_ci U32 tmpOffset = offset_2; 11958c2ecf20Sopenharmony_ci offset_2 = offset_1; 11968c2ecf20Sopenharmony_ci offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */ 11978c2ecf20Sopenharmony_ci ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, repLength2 - MINMATCH); 11988c2ecf20Sopenharmony_ci hashTable[ZSTD_hashPtr(ip, hBits, mls)] = curr2; 11998c2ecf20Sopenharmony_ci ip += repLength2; 12008c2ecf20Sopenharmony_ci anchor = ip; 12018c2ecf20Sopenharmony_ci continue; 12028c2ecf20Sopenharmony_ci } 12038c2ecf20Sopenharmony_ci break; 12048c2ecf20Sopenharmony_ci } 12058c2ecf20Sopenharmony_ci } 12068c2ecf20Sopenharmony_ci } 12078c2ecf20Sopenharmony_ci 12088c2ecf20Sopenharmony_ci /* save reps for next block */ 12098c2ecf20Sopenharmony_ci ctx->repToConfirm[0] = offset_1; 12108c2ecf20Sopenharmony_ci ctx->repToConfirm[1] = offset_2; 12118c2ecf20Sopenharmony_ci 12128c2ecf20Sopenharmony_ci /* Last Literals */ 12138c2ecf20Sopenharmony_ci { 12148c2ecf20Sopenharmony_ci size_t const lastLLSize = iend - anchor; 12158c2ecf20Sopenharmony_ci memcpy(seqStorePtr->lit, anchor, lastLLSize); 12168c2ecf20Sopenharmony_ci seqStorePtr->lit += lastLLSize; 12178c2ecf20Sopenharmony_ci } 12188c2ecf20Sopenharmony_ci} 12198c2ecf20Sopenharmony_ci 12208c2ecf20Sopenharmony_cistatic void ZSTD_compressBlock_fast_extDict(ZSTD_CCtx *ctx, const void *src, size_t srcSize) 12218c2ecf20Sopenharmony_ci{ 12228c2ecf20Sopenharmony_ci U32 const mls = ctx->params.cParams.searchLength; 12238c2ecf20Sopenharmony_ci switch (mls) { 12248c2ecf20Sopenharmony_ci default: /* includes case 3 */ 12258c2ecf20Sopenharmony_ci case 4: ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 4); return; 12268c2ecf20Sopenharmony_ci case 5: ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 5); return; 12278c2ecf20Sopenharmony_ci case 6: ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 6); return; 12288c2ecf20Sopenharmony_ci case 7: ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 7); return; 12298c2ecf20Sopenharmony_ci } 12308c2ecf20Sopenharmony_ci} 12318c2ecf20Sopenharmony_ci 12328c2ecf20Sopenharmony_ci/*-************************************* 12338c2ecf20Sopenharmony_ci* Double Fast 12348c2ecf20Sopenharmony_ci***************************************/ 12358c2ecf20Sopenharmony_cistatic void ZSTD_fillDoubleHashTable(ZSTD_CCtx *cctx, const void *end, const U32 mls) 12368c2ecf20Sopenharmony_ci{ 12378c2ecf20Sopenharmony_ci U32 *const hashLarge = cctx->hashTable; 12388c2ecf20Sopenharmony_ci U32 const hBitsL = cctx->params.cParams.hashLog; 12398c2ecf20Sopenharmony_ci U32 *const hashSmall = cctx->chainTable; 12408c2ecf20Sopenharmony_ci U32 const hBitsS = cctx->params.cParams.chainLog; 12418c2ecf20Sopenharmony_ci const BYTE *const base = cctx->base; 12428c2ecf20Sopenharmony_ci const BYTE *ip = base + cctx->nextToUpdate; 12438c2ecf20Sopenharmony_ci const BYTE *const iend = ((const BYTE *)end) - HASH_READ_SIZE; 12448c2ecf20Sopenharmony_ci const size_t fastHashFillStep = 3; 12458c2ecf20Sopenharmony_ci 12468c2ecf20Sopenharmony_ci while (ip <= iend) { 12478c2ecf20Sopenharmony_ci hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = (U32)(ip - base); 12488c2ecf20Sopenharmony_ci hashLarge[ZSTD_hashPtr(ip, hBitsL, 8)] = (U32)(ip - base); 12498c2ecf20Sopenharmony_ci ip += fastHashFillStep; 12508c2ecf20Sopenharmony_ci } 12518c2ecf20Sopenharmony_ci} 12528c2ecf20Sopenharmony_ci 12538c2ecf20Sopenharmony_ciFORCE_INLINE 12548c2ecf20Sopenharmony_civoid ZSTD_compressBlock_doubleFast_generic(ZSTD_CCtx *cctx, const void *src, size_t srcSize, const U32 mls) 12558c2ecf20Sopenharmony_ci{ 12568c2ecf20Sopenharmony_ci U32 *const hashLong = cctx->hashTable; 12578c2ecf20Sopenharmony_ci const U32 hBitsL = cctx->params.cParams.hashLog; 12588c2ecf20Sopenharmony_ci U32 *const hashSmall = cctx->chainTable; 12598c2ecf20Sopenharmony_ci const U32 hBitsS = cctx->params.cParams.chainLog; 12608c2ecf20Sopenharmony_ci seqStore_t *seqStorePtr = &(cctx->seqStore); 12618c2ecf20Sopenharmony_ci const BYTE *const base = cctx->base; 12628c2ecf20Sopenharmony_ci const BYTE *const istart = (const BYTE *)src; 12638c2ecf20Sopenharmony_ci const BYTE *ip = istart; 12648c2ecf20Sopenharmony_ci const BYTE *anchor = istart; 12658c2ecf20Sopenharmony_ci const U32 lowestIndex = cctx->dictLimit; 12668c2ecf20Sopenharmony_ci const BYTE *const lowest = base + lowestIndex; 12678c2ecf20Sopenharmony_ci const BYTE *const iend = istart + srcSize; 12688c2ecf20Sopenharmony_ci const BYTE *const ilimit = iend - HASH_READ_SIZE; 12698c2ecf20Sopenharmony_ci U32 offset_1 = cctx->rep[0], offset_2 = cctx->rep[1]; 12708c2ecf20Sopenharmony_ci U32 offsetSaved = 0; 12718c2ecf20Sopenharmony_ci 12728c2ecf20Sopenharmony_ci /* init */ 12738c2ecf20Sopenharmony_ci ip += (ip == lowest); 12748c2ecf20Sopenharmony_ci { 12758c2ecf20Sopenharmony_ci U32 const maxRep = (U32)(ip - lowest); 12768c2ecf20Sopenharmony_ci if (offset_2 > maxRep) 12778c2ecf20Sopenharmony_ci offsetSaved = offset_2, offset_2 = 0; 12788c2ecf20Sopenharmony_ci if (offset_1 > maxRep) 12798c2ecf20Sopenharmony_ci offsetSaved = offset_1, offset_1 = 0; 12808c2ecf20Sopenharmony_ci } 12818c2ecf20Sopenharmony_ci 12828c2ecf20Sopenharmony_ci /* Main Search Loop */ 12838c2ecf20Sopenharmony_ci while (ip < ilimit) { /* < instead of <=, because repcode check at (ip+1) */ 12848c2ecf20Sopenharmony_ci size_t mLength; 12858c2ecf20Sopenharmony_ci size_t const h2 = ZSTD_hashPtr(ip, hBitsL, 8); 12868c2ecf20Sopenharmony_ci size_t const h = ZSTD_hashPtr(ip, hBitsS, mls); 12878c2ecf20Sopenharmony_ci U32 const curr = (U32)(ip - base); 12888c2ecf20Sopenharmony_ci U32 const matchIndexL = hashLong[h2]; 12898c2ecf20Sopenharmony_ci U32 const matchIndexS = hashSmall[h]; 12908c2ecf20Sopenharmony_ci const BYTE *matchLong = base + matchIndexL; 12918c2ecf20Sopenharmony_ci const BYTE *match = base + matchIndexS; 12928c2ecf20Sopenharmony_ci hashLong[h2] = hashSmall[h] = curr; /* update hash tables */ 12938c2ecf20Sopenharmony_ci 12948c2ecf20Sopenharmony_ci if ((offset_1 > 0) & (ZSTD_read32(ip + 1 - offset_1) == ZSTD_read32(ip + 1))) { /* note : by construction, offset_1 <= curr */ 12958c2ecf20Sopenharmony_ci mLength = ZSTD_count(ip + 1 + 4, ip + 1 + 4 - offset_1, iend) + 4; 12968c2ecf20Sopenharmony_ci ip++; 12978c2ecf20Sopenharmony_ci ZSTD_storeSeq(seqStorePtr, ip - anchor, anchor, 0, mLength - MINMATCH); 12988c2ecf20Sopenharmony_ci } else { 12998c2ecf20Sopenharmony_ci U32 offset; 13008c2ecf20Sopenharmony_ci if ((matchIndexL > lowestIndex) && (ZSTD_read64(matchLong) == ZSTD_read64(ip))) { 13018c2ecf20Sopenharmony_ci mLength = ZSTD_count(ip + 8, matchLong + 8, iend) + 8; 13028c2ecf20Sopenharmony_ci offset = (U32)(ip - matchLong); 13038c2ecf20Sopenharmony_ci while (((ip > anchor) & (matchLong > lowest)) && (ip[-1] == matchLong[-1])) { 13048c2ecf20Sopenharmony_ci ip--; 13058c2ecf20Sopenharmony_ci matchLong--; 13068c2ecf20Sopenharmony_ci mLength++; 13078c2ecf20Sopenharmony_ci } /* catch up */ 13088c2ecf20Sopenharmony_ci } else if ((matchIndexS > lowestIndex) && (ZSTD_read32(match) == ZSTD_read32(ip))) { 13098c2ecf20Sopenharmony_ci size_t const h3 = ZSTD_hashPtr(ip + 1, hBitsL, 8); 13108c2ecf20Sopenharmony_ci U32 const matchIndex3 = hashLong[h3]; 13118c2ecf20Sopenharmony_ci const BYTE *match3 = base + matchIndex3; 13128c2ecf20Sopenharmony_ci hashLong[h3] = curr + 1; 13138c2ecf20Sopenharmony_ci if ((matchIndex3 > lowestIndex) && (ZSTD_read64(match3) == ZSTD_read64(ip + 1))) { 13148c2ecf20Sopenharmony_ci mLength = ZSTD_count(ip + 9, match3 + 8, iend) + 8; 13158c2ecf20Sopenharmony_ci ip++; 13168c2ecf20Sopenharmony_ci offset = (U32)(ip - match3); 13178c2ecf20Sopenharmony_ci while (((ip > anchor) & (match3 > lowest)) && (ip[-1] == match3[-1])) { 13188c2ecf20Sopenharmony_ci ip--; 13198c2ecf20Sopenharmony_ci match3--; 13208c2ecf20Sopenharmony_ci mLength++; 13218c2ecf20Sopenharmony_ci } /* catch up */ 13228c2ecf20Sopenharmony_ci } else { 13238c2ecf20Sopenharmony_ci mLength = ZSTD_count(ip + 4, match + 4, iend) + 4; 13248c2ecf20Sopenharmony_ci offset = (U32)(ip - match); 13258c2ecf20Sopenharmony_ci while (((ip > anchor) & (match > lowest)) && (ip[-1] == match[-1])) { 13268c2ecf20Sopenharmony_ci ip--; 13278c2ecf20Sopenharmony_ci match--; 13288c2ecf20Sopenharmony_ci mLength++; 13298c2ecf20Sopenharmony_ci } /* catch up */ 13308c2ecf20Sopenharmony_ci } 13318c2ecf20Sopenharmony_ci } else { 13328c2ecf20Sopenharmony_ci ip += ((ip - anchor) >> g_searchStrength) + 1; 13338c2ecf20Sopenharmony_ci continue; 13348c2ecf20Sopenharmony_ci } 13358c2ecf20Sopenharmony_ci 13368c2ecf20Sopenharmony_ci offset_2 = offset_1; 13378c2ecf20Sopenharmony_ci offset_1 = offset; 13388c2ecf20Sopenharmony_ci 13398c2ecf20Sopenharmony_ci ZSTD_storeSeq(seqStorePtr, ip - anchor, anchor, offset + ZSTD_REP_MOVE, mLength - MINMATCH); 13408c2ecf20Sopenharmony_ci } 13418c2ecf20Sopenharmony_ci 13428c2ecf20Sopenharmony_ci /* match found */ 13438c2ecf20Sopenharmony_ci ip += mLength; 13448c2ecf20Sopenharmony_ci anchor = ip; 13458c2ecf20Sopenharmony_ci 13468c2ecf20Sopenharmony_ci if (ip <= ilimit) { 13478c2ecf20Sopenharmony_ci /* Fill Table */ 13488c2ecf20Sopenharmony_ci hashLong[ZSTD_hashPtr(base + curr + 2, hBitsL, 8)] = hashSmall[ZSTD_hashPtr(base + curr + 2, hBitsS, mls)] = 13498c2ecf20Sopenharmony_ci curr + 2; /* here because curr+2 could be > iend-8 */ 13508c2ecf20Sopenharmony_ci hashLong[ZSTD_hashPtr(ip - 2, hBitsL, 8)] = hashSmall[ZSTD_hashPtr(ip - 2, hBitsS, mls)] = (U32)(ip - 2 - base); 13518c2ecf20Sopenharmony_ci 13528c2ecf20Sopenharmony_ci /* check immediate repcode */ 13538c2ecf20Sopenharmony_ci while ((ip <= ilimit) && ((offset_2 > 0) & (ZSTD_read32(ip) == ZSTD_read32(ip - offset_2)))) { 13548c2ecf20Sopenharmony_ci /* store sequence */ 13558c2ecf20Sopenharmony_ci size_t const rLength = ZSTD_count(ip + 4, ip + 4 - offset_2, iend) + 4; 13568c2ecf20Sopenharmony_ci { 13578c2ecf20Sopenharmony_ci U32 const tmpOff = offset_2; 13588c2ecf20Sopenharmony_ci offset_2 = offset_1; 13598c2ecf20Sopenharmony_ci offset_1 = tmpOff; 13608c2ecf20Sopenharmony_ci } /* swap offset_2 <=> offset_1 */ 13618c2ecf20Sopenharmony_ci hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = (U32)(ip - base); 13628c2ecf20Sopenharmony_ci hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = (U32)(ip - base); 13638c2ecf20Sopenharmony_ci ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, rLength - MINMATCH); 13648c2ecf20Sopenharmony_ci ip += rLength; 13658c2ecf20Sopenharmony_ci anchor = ip; 13668c2ecf20Sopenharmony_ci continue; /* faster when present ... (?) */ 13678c2ecf20Sopenharmony_ci } 13688c2ecf20Sopenharmony_ci } 13698c2ecf20Sopenharmony_ci } 13708c2ecf20Sopenharmony_ci 13718c2ecf20Sopenharmony_ci /* save reps for next block */ 13728c2ecf20Sopenharmony_ci cctx->repToConfirm[0] = offset_1 ? offset_1 : offsetSaved; 13738c2ecf20Sopenharmony_ci cctx->repToConfirm[1] = offset_2 ? offset_2 : offsetSaved; 13748c2ecf20Sopenharmony_ci 13758c2ecf20Sopenharmony_ci /* Last Literals */ 13768c2ecf20Sopenharmony_ci { 13778c2ecf20Sopenharmony_ci size_t const lastLLSize = iend - anchor; 13788c2ecf20Sopenharmony_ci memcpy(seqStorePtr->lit, anchor, lastLLSize); 13798c2ecf20Sopenharmony_ci seqStorePtr->lit += lastLLSize; 13808c2ecf20Sopenharmony_ci } 13818c2ecf20Sopenharmony_ci} 13828c2ecf20Sopenharmony_ci 13838c2ecf20Sopenharmony_cistatic void ZSTD_compressBlock_doubleFast(ZSTD_CCtx *ctx, const void *src, size_t srcSize) 13848c2ecf20Sopenharmony_ci{ 13858c2ecf20Sopenharmony_ci const U32 mls = ctx->params.cParams.searchLength; 13868c2ecf20Sopenharmony_ci switch (mls) { 13878c2ecf20Sopenharmony_ci default: /* includes case 3 */ 13888c2ecf20Sopenharmony_ci case 4: ZSTD_compressBlock_doubleFast_generic(ctx, src, srcSize, 4); return; 13898c2ecf20Sopenharmony_ci case 5: ZSTD_compressBlock_doubleFast_generic(ctx, src, srcSize, 5); return; 13908c2ecf20Sopenharmony_ci case 6: ZSTD_compressBlock_doubleFast_generic(ctx, src, srcSize, 6); return; 13918c2ecf20Sopenharmony_ci case 7: ZSTD_compressBlock_doubleFast_generic(ctx, src, srcSize, 7); return; 13928c2ecf20Sopenharmony_ci } 13938c2ecf20Sopenharmony_ci} 13948c2ecf20Sopenharmony_ci 13958c2ecf20Sopenharmony_cistatic void ZSTD_compressBlock_doubleFast_extDict_generic(ZSTD_CCtx *ctx, const void *src, size_t srcSize, const U32 mls) 13968c2ecf20Sopenharmony_ci{ 13978c2ecf20Sopenharmony_ci U32 *const hashLong = ctx->hashTable; 13988c2ecf20Sopenharmony_ci U32 const hBitsL = ctx->params.cParams.hashLog; 13998c2ecf20Sopenharmony_ci U32 *const hashSmall = ctx->chainTable; 14008c2ecf20Sopenharmony_ci U32 const hBitsS = ctx->params.cParams.chainLog; 14018c2ecf20Sopenharmony_ci seqStore_t *seqStorePtr = &(ctx->seqStore); 14028c2ecf20Sopenharmony_ci const BYTE *const base = ctx->base; 14038c2ecf20Sopenharmony_ci const BYTE *const dictBase = ctx->dictBase; 14048c2ecf20Sopenharmony_ci const BYTE *const istart = (const BYTE *)src; 14058c2ecf20Sopenharmony_ci const BYTE *ip = istart; 14068c2ecf20Sopenharmony_ci const BYTE *anchor = istart; 14078c2ecf20Sopenharmony_ci const U32 lowestIndex = ctx->lowLimit; 14088c2ecf20Sopenharmony_ci const BYTE *const dictStart = dictBase + lowestIndex; 14098c2ecf20Sopenharmony_ci const U32 dictLimit = ctx->dictLimit; 14108c2ecf20Sopenharmony_ci const BYTE *const lowPrefixPtr = base + dictLimit; 14118c2ecf20Sopenharmony_ci const BYTE *const dictEnd = dictBase + dictLimit; 14128c2ecf20Sopenharmony_ci const BYTE *const iend = istart + srcSize; 14138c2ecf20Sopenharmony_ci const BYTE *const ilimit = iend - 8; 14148c2ecf20Sopenharmony_ci U32 offset_1 = ctx->rep[0], offset_2 = ctx->rep[1]; 14158c2ecf20Sopenharmony_ci 14168c2ecf20Sopenharmony_ci /* Search Loop */ 14178c2ecf20Sopenharmony_ci while (ip < ilimit) { /* < instead of <=, because (ip+1) */ 14188c2ecf20Sopenharmony_ci const size_t hSmall = ZSTD_hashPtr(ip, hBitsS, mls); 14198c2ecf20Sopenharmony_ci const U32 matchIndex = hashSmall[hSmall]; 14208c2ecf20Sopenharmony_ci const BYTE *matchBase = matchIndex < dictLimit ? dictBase : base; 14218c2ecf20Sopenharmony_ci const BYTE *match = matchBase + matchIndex; 14228c2ecf20Sopenharmony_ci 14238c2ecf20Sopenharmony_ci const size_t hLong = ZSTD_hashPtr(ip, hBitsL, 8); 14248c2ecf20Sopenharmony_ci const U32 matchLongIndex = hashLong[hLong]; 14258c2ecf20Sopenharmony_ci const BYTE *matchLongBase = matchLongIndex < dictLimit ? dictBase : base; 14268c2ecf20Sopenharmony_ci const BYTE *matchLong = matchLongBase + matchLongIndex; 14278c2ecf20Sopenharmony_ci 14288c2ecf20Sopenharmony_ci const U32 curr = (U32)(ip - base); 14298c2ecf20Sopenharmony_ci const U32 repIndex = curr + 1 - offset_1; /* offset_1 expected <= curr +1 */ 14308c2ecf20Sopenharmony_ci const BYTE *repBase = repIndex < dictLimit ? dictBase : base; 14318c2ecf20Sopenharmony_ci const BYTE *repMatch = repBase + repIndex; 14328c2ecf20Sopenharmony_ci size_t mLength; 14338c2ecf20Sopenharmony_ci hashSmall[hSmall] = hashLong[hLong] = curr; /* update hash table */ 14348c2ecf20Sopenharmony_ci 14358c2ecf20Sopenharmony_ci if ((((U32)((dictLimit - 1) - repIndex) >= 3) /* intentional underflow */ & (repIndex > lowestIndex)) && 14368c2ecf20Sopenharmony_ci (ZSTD_read32(repMatch) == ZSTD_read32(ip + 1))) { 14378c2ecf20Sopenharmony_ci const BYTE *repMatchEnd = repIndex < dictLimit ? dictEnd : iend; 14388c2ecf20Sopenharmony_ci mLength = ZSTD_count_2segments(ip + 1 + 4, repMatch + 4, iend, repMatchEnd, lowPrefixPtr) + 4; 14398c2ecf20Sopenharmony_ci ip++; 14408c2ecf20Sopenharmony_ci ZSTD_storeSeq(seqStorePtr, ip - anchor, anchor, 0, mLength - MINMATCH); 14418c2ecf20Sopenharmony_ci } else { 14428c2ecf20Sopenharmony_ci if ((matchLongIndex > lowestIndex) && (ZSTD_read64(matchLong) == ZSTD_read64(ip))) { 14438c2ecf20Sopenharmony_ci const BYTE *matchEnd = matchLongIndex < dictLimit ? dictEnd : iend; 14448c2ecf20Sopenharmony_ci const BYTE *lowMatchPtr = matchLongIndex < dictLimit ? dictStart : lowPrefixPtr; 14458c2ecf20Sopenharmony_ci U32 offset; 14468c2ecf20Sopenharmony_ci mLength = ZSTD_count_2segments(ip + 8, matchLong + 8, iend, matchEnd, lowPrefixPtr) + 8; 14478c2ecf20Sopenharmony_ci offset = curr - matchLongIndex; 14488c2ecf20Sopenharmony_ci while (((ip > anchor) & (matchLong > lowMatchPtr)) && (ip[-1] == matchLong[-1])) { 14498c2ecf20Sopenharmony_ci ip--; 14508c2ecf20Sopenharmony_ci matchLong--; 14518c2ecf20Sopenharmony_ci mLength++; 14528c2ecf20Sopenharmony_ci } /* catch up */ 14538c2ecf20Sopenharmony_ci offset_2 = offset_1; 14548c2ecf20Sopenharmony_ci offset_1 = offset; 14558c2ecf20Sopenharmony_ci ZSTD_storeSeq(seqStorePtr, ip - anchor, anchor, offset + ZSTD_REP_MOVE, mLength - MINMATCH); 14568c2ecf20Sopenharmony_ci 14578c2ecf20Sopenharmony_ci } else if ((matchIndex > lowestIndex) && (ZSTD_read32(match) == ZSTD_read32(ip))) { 14588c2ecf20Sopenharmony_ci size_t const h3 = ZSTD_hashPtr(ip + 1, hBitsL, 8); 14598c2ecf20Sopenharmony_ci U32 const matchIndex3 = hashLong[h3]; 14608c2ecf20Sopenharmony_ci const BYTE *const match3Base = matchIndex3 < dictLimit ? dictBase : base; 14618c2ecf20Sopenharmony_ci const BYTE *match3 = match3Base + matchIndex3; 14628c2ecf20Sopenharmony_ci U32 offset; 14638c2ecf20Sopenharmony_ci hashLong[h3] = curr + 1; 14648c2ecf20Sopenharmony_ci if ((matchIndex3 > lowestIndex) && (ZSTD_read64(match3) == ZSTD_read64(ip + 1))) { 14658c2ecf20Sopenharmony_ci const BYTE *matchEnd = matchIndex3 < dictLimit ? dictEnd : iend; 14668c2ecf20Sopenharmony_ci const BYTE *lowMatchPtr = matchIndex3 < dictLimit ? dictStart : lowPrefixPtr; 14678c2ecf20Sopenharmony_ci mLength = ZSTD_count_2segments(ip + 9, match3 + 8, iend, matchEnd, lowPrefixPtr) + 8; 14688c2ecf20Sopenharmony_ci ip++; 14698c2ecf20Sopenharmony_ci offset = curr + 1 - matchIndex3; 14708c2ecf20Sopenharmony_ci while (((ip > anchor) & (match3 > lowMatchPtr)) && (ip[-1] == match3[-1])) { 14718c2ecf20Sopenharmony_ci ip--; 14728c2ecf20Sopenharmony_ci match3--; 14738c2ecf20Sopenharmony_ci mLength++; 14748c2ecf20Sopenharmony_ci } /* catch up */ 14758c2ecf20Sopenharmony_ci } else { 14768c2ecf20Sopenharmony_ci const BYTE *matchEnd = matchIndex < dictLimit ? dictEnd : iend; 14778c2ecf20Sopenharmony_ci const BYTE *lowMatchPtr = matchIndex < dictLimit ? dictStart : lowPrefixPtr; 14788c2ecf20Sopenharmony_ci mLength = ZSTD_count_2segments(ip + 4, match + 4, iend, matchEnd, lowPrefixPtr) + 4; 14798c2ecf20Sopenharmony_ci offset = curr - matchIndex; 14808c2ecf20Sopenharmony_ci while (((ip > anchor) & (match > lowMatchPtr)) && (ip[-1] == match[-1])) { 14818c2ecf20Sopenharmony_ci ip--; 14828c2ecf20Sopenharmony_ci match--; 14838c2ecf20Sopenharmony_ci mLength++; 14848c2ecf20Sopenharmony_ci } /* catch up */ 14858c2ecf20Sopenharmony_ci } 14868c2ecf20Sopenharmony_ci offset_2 = offset_1; 14878c2ecf20Sopenharmony_ci offset_1 = offset; 14888c2ecf20Sopenharmony_ci ZSTD_storeSeq(seqStorePtr, ip - anchor, anchor, offset + ZSTD_REP_MOVE, mLength - MINMATCH); 14898c2ecf20Sopenharmony_ci 14908c2ecf20Sopenharmony_ci } else { 14918c2ecf20Sopenharmony_ci ip += ((ip - anchor) >> g_searchStrength) + 1; 14928c2ecf20Sopenharmony_ci continue; 14938c2ecf20Sopenharmony_ci } 14948c2ecf20Sopenharmony_ci } 14958c2ecf20Sopenharmony_ci 14968c2ecf20Sopenharmony_ci /* found a match : store it */ 14978c2ecf20Sopenharmony_ci ip += mLength; 14988c2ecf20Sopenharmony_ci anchor = ip; 14998c2ecf20Sopenharmony_ci 15008c2ecf20Sopenharmony_ci if (ip <= ilimit) { 15018c2ecf20Sopenharmony_ci /* Fill Table */ 15028c2ecf20Sopenharmony_ci hashSmall[ZSTD_hashPtr(base + curr + 2, hBitsS, mls)] = curr + 2; 15038c2ecf20Sopenharmony_ci hashLong[ZSTD_hashPtr(base + curr + 2, hBitsL, 8)] = curr + 2; 15048c2ecf20Sopenharmony_ci hashSmall[ZSTD_hashPtr(ip - 2, hBitsS, mls)] = (U32)(ip - 2 - base); 15058c2ecf20Sopenharmony_ci hashLong[ZSTD_hashPtr(ip - 2, hBitsL, 8)] = (U32)(ip - 2 - base); 15068c2ecf20Sopenharmony_ci /* check immediate repcode */ 15078c2ecf20Sopenharmony_ci while (ip <= ilimit) { 15088c2ecf20Sopenharmony_ci U32 const curr2 = (U32)(ip - base); 15098c2ecf20Sopenharmony_ci U32 const repIndex2 = curr2 - offset_2; 15108c2ecf20Sopenharmony_ci const BYTE *repMatch2 = repIndex2 < dictLimit ? dictBase + repIndex2 : base + repIndex2; 15118c2ecf20Sopenharmony_ci if ((((U32)((dictLimit - 1) - repIndex2) >= 3) & (repIndex2 > lowestIndex)) /* intentional overflow */ 15128c2ecf20Sopenharmony_ci && (ZSTD_read32(repMatch2) == ZSTD_read32(ip))) { 15138c2ecf20Sopenharmony_ci const BYTE *const repEnd2 = repIndex2 < dictLimit ? dictEnd : iend; 15148c2ecf20Sopenharmony_ci size_t const repLength2 = 15158c2ecf20Sopenharmony_ci ZSTD_count_2segments(ip + EQUAL_READ32, repMatch2 + EQUAL_READ32, iend, repEnd2, lowPrefixPtr) + EQUAL_READ32; 15168c2ecf20Sopenharmony_ci U32 tmpOffset = offset_2; 15178c2ecf20Sopenharmony_ci offset_2 = offset_1; 15188c2ecf20Sopenharmony_ci offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */ 15198c2ecf20Sopenharmony_ci ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, repLength2 - MINMATCH); 15208c2ecf20Sopenharmony_ci hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = curr2; 15218c2ecf20Sopenharmony_ci hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = curr2; 15228c2ecf20Sopenharmony_ci ip += repLength2; 15238c2ecf20Sopenharmony_ci anchor = ip; 15248c2ecf20Sopenharmony_ci continue; 15258c2ecf20Sopenharmony_ci } 15268c2ecf20Sopenharmony_ci break; 15278c2ecf20Sopenharmony_ci } 15288c2ecf20Sopenharmony_ci } 15298c2ecf20Sopenharmony_ci } 15308c2ecf20Sopenharmony_ci 15318c2ecf20Sopenharmony_ci /* save reps for next block */ 15328c2ecf20Sopenharmony_ci ctx->repToConfirm[0] = offset_1; 15338c2ecf20Sopenharmony_ci ctx->repToConfirm[1] = offset_2; 15348c2ecf20Sopenharmony_ci 15358c2ecf20Sopenharmony_ci /* Last Literals */ 15368c2ecf20Sopenharmony_ci { 15378c2ecf20Sopenharmony_ci size_t const lastLLSize = iend - anchor; 15388c2ecf20Sopenharmony_ci memcpy(seqStorePtr->lit, anchor, lastLLSize); 15398c2ecf20Sopenharmony_ci seqStorePtr->lit += lastLLSize; 15408c2ecf20Sopenharmony_ci } 15418c2ecf20Sopenharmony_ci} 15428c2ecf20Sopenharmony_ci 15438c2ecf20Sopenharmony_cistatic void ZSTD_compressBlock_doubleFast_extDict(ZSTD_CCtx *ctx, const void *src, size_t srcSize) 15448c2ecf20Sopenharmony_ci{ 15458c2ecf20Sopenharmony_ci U32 const mls = ctx->params.cParams.searchLength; 15468c2ecf20Sopenharmony_ci switch (mls) { 15478c2ecf20Sopenharmony_ci default: /* includes case 3 */ 15488c2ecf20Sopenharmony_ci case 4: ZSTD_compressBlock_doubleFast_extDict_generic(ctx, src, srcSize, 4); return; 15498c2ecf20Sopenharmony_ci case 5: ZSTD_compressBlock_doubleFast_extDict_generic(ctx, src, srcSize, 5); return; 15508c2ecf20Sopenharmony_ci case 6: ZSTD_compressBlock_doubleFast_extDict_generic(ctx, src, srcSize, 6); return; 15518c2ecf20Sopenharmony_ci case 7: ZSTD_compressBlock_doubleFast_extDict_generic(ctx, src, srcSize, 7); return; 15528c2ecf20Sopenharmony_ci } 15538c2ecf20Sopenharmony_ci} 15548c2ecf20Sopenharmony_ci 15558c2ecf20Sopenharmony_ci/*-************************************* 15568c2ecf20Sopenharmony_ci* Binary Tree search 15578c2ecf20Sopenharmony_ci***************************************/ 15588c2ecf20Sopenharmony_ci/** ZSTD_insertBt1() : add one or multiple positions to tree. 15598c2ecf20Sopenharmony_ci* ip : assumed <= iend-8 . 15608c2ecf20Sopenharmony_ci* @return : nb of positions added */ 15618c2ecf20Sopenharmony_cistatic U32 ZSTD_insertBt1(ZSTD_CCtx *zc, const BYTE *const ip, const U32 mls, const BYTE *const iend, U32 nbCompares, U32 extDict) 15628c2ecf20Sopenharmony_ci{ 15638c2ecf20Sopenharmony_ci U32 *const hashTable = zc->hashTable; 15648c2ecf20Sopenharmony_ci U32 const hashLog = zc->params.cParams.hashLog; 15658c2ecf20Sopenharmony_ci size_t const h = ZSTD_hashPtr(ip, hashLog, mls); 15668c2ecf20Sopenharmony_ci U32 *const bt = zc->chainTable; 15678c2ecf20Sopenharmony_ci U32 const btLog = zc->params.cParams.chainLog - 1; 15688c2ecf20Sopenharmony_ci U32 const btMask = (1 << btLog) - 1; 15698c2ecf20Sopenharmony_ci U32 matchIndex = hashTable[h]; 15708c2ecf20Sopenharmony_ci size_t commonLengthSmaller = 0, commonLengthLarger = 0; 15718c2ecf20Sopenharmony_ci const BYTE *const base = zc->base; 15728c2ecf20Sopenharmony_ci const BYTE *const dictBase = zc->dictBase; 15738c2ecf20Sopenharmony_ci const U32 dictLimit = zc->dictLimit; 15748c2ecf20Sopenharmony_ci const BYTE *const dictEnd = dictBase + dictLimit; 15758c2ecf20Sopenharmony_ci const BYTE *const prefixStart = base + dictLimit; 15768c2ecf20Sopenharmony_ci const BYTE *match; 15778c2ecf20Sopenharmony_ci const U32 curr = (U32)(ip - base); 15788c2ecf20Sopenharmony_ci const U32 btLow = btMask >= curr ? 0 : curr - btMask; 15798c2ecf20Sopenharmony_ci U32 *smallerPtr = bt + 2 * (curr & btMask); 15808c2ecf20Sopenharmony_ci U32 *largerPtr = smallerPtr + 1; 15818c2ecf20Sopenharmony_ci U32 dummy32; /* to be nullified at the end */ 15828c2ecf20Sopenharmony_ci U32 const windowLow = zc->lowLimit; 15838c2ecf20Sopenharmony_ci U32 matchEndIdx = curr + 8; 15848c2ecf20Sopenharmony_ci size_t bestLength = 8; 15858c2ecf20Sopenharmony_ci 15868c2ecf20Sopenharmony_ci hashTable[h] = curr; /* Update Hash Table */ 15878c2ecf20Sopenharmony_ci 15888c2ecf20Sopenharmony_ci while (nbCompares-- && (matchIndex > windowLow)) { 15898c2ecf20Sopenharmony_ci U32 *const nextPtr = bt + 2 * (matchIndex & btMask); 15908c2ecf20Sopenharmony_ci size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */ 15918c2ecf20Sopenharmony_ci 15928c2ecf20Sopenharmony_ci if ((!extDict) || (matchIndex + matchLength >= dictLimit)) { 15938c2ecf20Sopenharmony_ci match = base + matchIndex; 15948c2ecf20Sopenharmony_ci if (match[matchLength] == ip[matchLength]) 15958c2ecf20Sopenharmony_ci matchLength += ZSTD_count(ip + matchLength + 1, match + matchLength + 1, iend) + 1; 15968c2ecf20Sopenharmony_ci } else { 15978c2ecf20Sopenharmony_ci match = dictBase + matchIndex; 15988c2ecf20Sopenharmony_ci matchLength += ZSTD_count_2segments(ip + matchLength, match + matchLength, iend, dictEnd, prefixStart); 15998c2ecf20Sopenharmony_ci if (matchIndex + matchLength >= dictLimit) 16008c2ecf20Sopenharmony_ci match = base + matchIndex; /* to prepare for next usage of match[matchLength] */ 16018c2ecf20Sopenharmony_ci } 16028c2ecf20Sopenharmony_ci 16038c2ecf20Sopenharmony_ci if (matchLength > bestLength) { 16048c2ecf20Sopenharmony_ci bestLength = matchLength; 16058c2ecf20Sopenharmony_ci if (matchLength > matchEndIdx - matchIndex) 16068c2ecf20Sopenharmony_ci matchEndIdx = matchIndex + (U32)matchLength; 16078c2ecf20Sopenharmony_ci } 16088c2ecf20Sopenharmony_ci 16098c2ecf20Sopenharmony_ci if (ip + matchLength == iend) /* equal : no way to know if inf or sup */ 16108c2ecf20Sopenharmony_ci break; /* drop , to guarantee consistency ; miss a bit of compression, but other solutions can corrupt the tree */ 16118c2ecf20Sopenharmony_ci 16128c2ecf20Sopenharmony_ci if (match[matchLength] < ip[matchLength]) { /* necessarily within correct buffer */ 16138c2ecf20Sopenharmony_ci /* match is smaller than curr */ 16148c2ecf20Sopenharmony_ci *smallerPtr = matchIndex; /* update smaller idx */ 16158c2ecf20Sopenharmony_ci commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */ 16168c2ecf20Sopenharmony_ci if (matchIndex <= btLow) { 16178c2ecf20Sopenharmony_ci smallerPtr = &dummy32; 16188c2ecf20Sopenharmony_ci break; 16198c2ecf20Sopenharmony_ci } /* beyond tree size, stop the search */ 16208c2ecf20Sopenharmony_ci smallerPtr = nextPtr + 1; /* new "smaller" => larger of match */ 16218c2ecf20Sopenharmony_ci matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to curr) */ 16228c2ecf20Sopenharmony_ci } else { 16238c2ecf20Sopenharmony_ci /* match is larger than curr */ 16248c2ecf20Sopenharmony_ci *largerPtr = matchIndex; 16258c2ecf20Sopenharmony_ci commonLengthLarger = matchLength; 16268c2ecf20Sopenharmony_ci if (matchIndex <= btLow) { 16278c2ecf20Sopenharmony_ci largerPtr = &dummy32; 16288c2ecf20Sopenharmony_ci break; 16298c2ecf20Sopenharmony_ci } /* beyond tree size, stop the search */ 16308c2ecf20Sopenharmony_ci largerPtr = nextPtr; 16318c2ecf20Sopenharmony_ci matchIndex = nextPtr[0]; 16328c2ecf20Sopenharmony_ci } 16338c2ecf20Sopenharmony_ci } 16348c2ecf20Sopenharmony_ci 16358c2ecf20Sopenharmony_ci *smallerPtr = *largerPtr = 0; 16368c2ecf20Sopenharmony_ci if (bestLength > 384) 16378c2ecf20Sopenharmony_ci return MIN(192, (U32)(bestLength - 384)); /* speed optimization */ 16388c2ecf20Sopenharmony_ci if (matchEndIdx > curr + 8) 16398c2ecf20Sopenharmony_ci return matchEndIdx - curr - 8; 16408c2ecf20Sopenharmony_ci return 1; 16418c2ecf20Sopenharmony_ci} 16428c2ecf20Sopenharmony_ci 16438c2ecf20Sopenharmony_cistatic size_t ZSTD_insertBtAndFindBestMatch(ZSTD_CCtx *zc, const BYTE *const ip, const BYTE *const iend, size_t *offsetPtr, U32 nbCompares, const U32 mls, 16448c2ecf20Sopenharmony_ci U32 extDict) 16458c2ecf20Sopenharmony_ci{ 16468c2ecf20Sopenharmony_ci U32 *const hashTable = zc->hashTable; 16478c2ecf20Sopenharmony_ci U32 const hashLog = zc->params.cParams.hashLog; 16488c2ecf20Sopenharmony_ci size_t const h = ZSTD_hashPtr(ip, hashLog, mls); 16498c2ecf20Sopenharmony_ci U32 *const bt = zc->chainTable; 16508c2ecf20Sopenharmony_ci U32 const btLog = zc->params.cParams.chainLog - 1; 16518c2ecf20Sopenharmony_ci U32 const btMask = (1 << btLog) - 1; 16528c2ecf20Sopenharmony_ci U32 matchIndex = hashTable[h]; 16538c2ecf20Sopenharmony_ci size_t commonLengthSmaller = 0, commonLengthLarger = 0; 16548c2ecf20Sopenharmony_ci const BYTE *const base = zc->base; 16558c2ecf20Sopenharmony_ci const BYTE *const dictBase = zc->dictBase; 16568c2ecf20Sopenharmony_ci const U32 dictLimit = zc->dictLimit; 16578c2ecf20Sopenharmony_ci const BYTE *const dictEnd = dictBase + dictLimit; 16588c2ecf20Sopenharmony_ci const BYTE *const prefixStart = base + dictLimit; 16598c2ecf20Sopenharmony_ci const U32 curr = (U32)(ip - base); 16608c2ecf20Sopenharmony_ci const U32 btLow = btMask >= curr ? 0 : curr - btMask; 16618c2ecf20Sopenharmony_ci const U32 windowLow = zc->lowLimit; 16628c2ecf20Sopenharmony_ci U32 *smallerPtr = bt + 2 * (curr & btMask); 16638c2ecf20Sopenharmony_ci U32 *largerPtr = bt + 2 * (curr & btMask) + 1; 16648c2ecf20Sopenharmony_ci U32 matchEndIdx = curr + 8; 16658c2ecf20Sopenharmony_ci U32 dummy32; /* to be nullified at the end */ 16668c2ecf20Sopenharmony_ci size_t bestLength = 0; 16678c2ecf20Sopenharmony_ci 16688c2ecf20Sopenharmony_ci hashTable[h] = curr; /* Update Hash Table */ 16698c2ecf20Sopenharmony_ci 16708c2ecf20Sopenharmony_ci while (nbCompares-- && (matchIndex > windowLow)) { 16718c2ecf20Sopenharmony_ci U32 *const nextPtr = bt + 2 * (matchIndex & btMask); 16728c2ecf20Sopenharmony_ci size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */ 16738c2ecf20Sopenharmony_ci const BYTE *match; 16748c2ecf20Sopenharmony_ci 16758c2ecf20Sopenharmony_ci if ((!extDict) || (matchIndex + matchLength >= dictLimit)) { 16768c2ecf20Sopenharmony_ci match = base + matchIndex; 16778c2ecf20Sopenharmony_ci if (match[matchLength] == ip[matchLength]) 16788c2ecf20Sopenharmony_ci matchLength += ZSTD_count(ip + matchLength + 1, match + matchLength + 1, iend) + 1; 16798c2ecf20Sopenharmony_ci } else { 16808c2ecf20Sopenharmony_ci match = dictBase + matchIndex; 16818c2ecf20Sopenharmony_ci matchLength += ZSTD_count_2segments(ip + matchLength, match + matchLength, iend, dictEnd, prefixStart); 16828c2ecf20Sopenharmony_ci if (matchIndex + matchLength >= dictLimit) 16838c2ecf20Sopenharmony_ci match = base + matchIndex; /* to prepare for next usage of match[matchLength] */ 16848c2ecf20Sopenharmony_ci } 16858c2ecf20Sopenharmony_ci 16868c2ecf20Sopenharmony_ci if (matchLength > bestLength) { 16878c2ecf20Sopenharmony_ci if (matchLength > matchEndIdx - matchIndex) 16888c2ecf20Sopenharmony_ci matchEndIdx = matchIndex + (U32)matchLength; 16898c2ecf20Sopenharmony_ci if ((4 * (int)(matchLength - bestLength)) > (int)(ZSTD_highbit32(curr - matchIndex + 1) - ZSTD_highbit32((U32)offsetPtr[0] + 1))) 16908c2ecf20Sopenharmony_ci bestLength = matchLength, *offsetPtr = ZSTD_REP_MOVE + curr - matchIndex; 16918c2ecf20Sopenharmony_ci if (ip + matchLength == iend) /* equal : no way to know if inf or sup */ 16928c2ecf20Sopenharmony_ci break; /* drop, to guarantee consistency (miss a little bit of compression) */ 16938c2ecf20Sopenharmony_ci } 16948c2ecf20Sopenharmony_ci 16958c2ecf20Sopenharmony_ci if (match[matchLength] < ip[matchLength]) { 16968c2ecf20Sopenharmony_ci /* match is smaller than curr */ 16978c2ecf20Sopenharmony_ci *smallerPtr = matchIndex; /* update smaller idx */ 16988c2ecf20Sopenharmony_ci commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */ 16998c2ecf20Sopenharmony_ci if (matchIndex <= btLow) { 17008c2ecf20Sopenharmony_ci smallerPtr = &dummy32; 17018c2ecf20Sopenharmony_ci break; 17028c2ecf20Sopenharmony_ci } /* beyond tree size, stop the search */ 17038c2ecf20Sopenharmony_ci smallerPtr = nextPtr + 1; /* new "smaller" => larger of match */ 17048c2ecf20Sopenharmony_ci matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to curr) */ 17058c2ecf20Sopenharmony_ci } else { 17068c2ecf20Sopenharmony_ci /* match is larger than curr */ 17078c2ecf20Sopenharmony_ci *largerPtr = matchIndex; 17088c2ecf20Sopenharmony_ci commonLengthLarger = matchLength; 17098c2ecf20Sopenharmony_ci if (matchIndex <= btLow) { 17108c2ecf20Sopenharmony_ci largerPtr = &dummy32; 17118c2ecf20Sopenharmony_ci break; 17128c2ecf20Sopenharmony_ci } /* beyond tree size, stop the search */ 17138c2ecf20Sopenharmony_ci largerPtr = nextPtr; 17148c2ecf20Sopenharmony_ci matchIndex = nextPtr[0]; 17158c2ecf20Sopenharmony_ci } 17168c2ecf20Sopenharmony_ci } 17178c2ecf20Sopenharmony_ci 17188c2ecf20Sopenharmony_ci *smallerPtr = *largerPtr = 0; 17198c2ecf20Sopenharmony_ci 17208c2ecf20Sopenharmony_ci zc->nextToUpdate = (matchEndIdx > curr + 8) ? matchEndIdx - 8 : curr + 1; 17218c2ecf20Sopenharmony_ci return bestLength; 17228c2ecf20Sopenharmony_ci} 17238c2ecf20Sopenharmony_ci 17248c2ecf20Sopenharmony_cistatic void ZSTD_updateTree(ZSTD_CCtx *zc, const BYTE *const ip, const BYTE *const iend, const U32 nbCompares, const U32 mls) 17258c2ecf20Sopenharmony_ci{ 17268c2ecf20Sopenharmony_ci const BYTE *const base = zc->base; 17278c2ecf20Sopenharmony_ci const U32 target = (U32)(ip - base); 17288c2ecf20Sopenharmony_ci U32 idx = zc->nextToUpdate; 17298c2ecf20Sopenharmony_ci 17308c2ecf20Sopenharmony_ci while (idx < target) 17318c2ecf20Sopenharmony_ci idx += ZSTD_insertBt1(zc, base + idx, mls, iend, nbCompares, 0); 17328c2ecf20Sopenharmony_ci} 17338c2ecf20Sopenharmony_ci 17348c2ecf20Sopenharmony_ci/** ZSTD_BtFindBestMatch() : Tree updater, providing best match */ 17358c2ecf20Sopenharmony_cistatic size_t ZSTD_BtFindBestMatch(ZSTD_CCtx *zc, const BYTE *const ip, const BYTE *const iLimit, size_t *offsetPtr, const U32 maxNbAttempts, const U32 mls) 17368c2ecf20Sopenharmony_ci{ 17378c2ecf20Sopenharmony_ci if (ip < zc->base + zc->nextToUpdate) 17388c2ecf20Sopenharmony_ci return 0; /* skipped area */ 17398c2ecf20Sopenharmony_ci ZSTD_updateTree(zc, ip, iLimit, maxNbAttempts, mls); 17408c2ecf20Sopenharmony_ci return ZSTD_insertBtAndFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, mls, 0); 17418c2ecf20Sopenharmony_ci} 17428c2ecf20Sopenharmony_ci 17438c2ecf20Sopenharmony_cistatic size_t ZSTD_BtFindBestMatch_selectMLS(ZSTD_CCtx *zc, /* Index table will be updated */ 17448c2ecf20Sopenharmony_ci const BYTE *ip, const BYTE *const iLimit, size_t *offsetPtr, const U32 maxNbAttempts, const U32 matchLengthSearch) 17458c2ecf20Sopenharmony_ci{ 17468c2ecf20Sopenharmony_ci switch (matchLengthSearch) { 17478c2ecf20Sopenharmony_ci default: /* includes case 3 */ 17488c2ecf20Sopenharmony_ci case 4: return ZSTD_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4); 17498c2ecf20Sopenharmony_ci case 5: return ZSTD_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5); 17508c2ecf20Sopenharmony_ci case 7: 17518c2ecf20Sopenharmony_ci case 6: return ZSTD_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6); 17528c2ecf20Sopenharmony_ci } 17538c2ecf20Sopenharmony_ci} 17548c2ecf20Sopenharmony_ci 17558c2ecf20Sopenharmony_cistatic void ZSTD_updateTree_extDict(ZSTD_CCtx *zc, const BYTE *const ip, const BYTE *const iend, const U32 nbCompares, const U32 mls) 17568c2ecf20Sopenharmony_ci{ 17578c2ecf20Sopenharmony_ci const BYTE *const base = zc->base; 17588c2ecf20Sopenharmony_ci const U32 target = (U32)(ip - base); 17598c2ecf20Sopenharmony_ci U32 idx = zc->nextToUpdate; 17608c2ecf20Sopenharmony_ci 17618c2ecf20Sopenharmony_ci while (idx < target) 17628c2ecf20Sopenharmony_ci idx += ZSTD_insertBt1(zc, base + idx, mls, iend, nbCompares, 1); 17638c2ecf20Sopenharmony_ci} 17648c2ecf20Sopenharmony_ci 17658c2ecf20Sopenharmony_ci/** Tree updater, providing best match */ 17668c2ecf20Sopenharmony_cistatic size_t ZSTD_BtFindBestMatch_extDict(ZSTD_CCtx *zc, const BYTE *const ip, const BYTE *const iLimit, size_t *offsetPtr, const U32 maxNbAttempts, 17678c2ecf20Sopenharmony_ci const U32 mls) 17688c2ecf20Sopenharmony_ci{ 17698c2ecf20Sopenharmony_ci if (ip < zc->base + zc->nextToUpdate) 17708c2ecf20Sopenharmony_ci return 0; /* skipped area */ 17718c2ecf20Sopenharmony_ci ZSTD_updateTree_extDict(zc, ip, iLimit, maxNbAttempts, mls); 17728c2ecf20Sopenharmony_ci return ZSTD_insertBtAndFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, mls, 1); 17738c2ecf20Sopenharmony_ci} 17748c2ecf20Sopenharmony_ci 17758c2ecf20Sopenharmony_cistatic size_t ZSTD_BtFindBestMatch_selectMLS_extDict(ZSTD_CCtx *zc, /* Index table will be updated */ 17768c2ecf20Sopenharmony_ci const BYTE *ip, const BYTE *const iLimit, size_t *offsetPtr, const U32 maxNbAttempts, 17778c2ecf20Sopenharmony_ci const U32 matchLengthSearch) 17788c2ecf20Sopenharmony_ci{ 17798c2ecf20Sopenharmony_ci switch (matchLengthSearch) { 17808c2ecf20Sopenharmony_ci default: /* includes case 3 */ 17818c2ecf20Sopenharmony_ci case 4: return ZSTD_BtFindBestMatch_extDict(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4); 17828c2ecf20Sopenharmony_ci case 5: return ZSTD_BtFindBestMatch_extDict(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5); 17838c2ecf20Sopenharmony_ci case 7: 17848c2ecf20Sopenharmony_ci case 6: return ZSTD_BtFindBestMatch_extDict(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6); 17858c2ecf20Sopenharmony_ci } 17868c2ecf20Sopenharmony_ci} 17878c2ecf20Sopenharmony_ci 17888c2ecf20Sopenharmony_ci/* ********************************* 17898c2ecf20Sopenharmony_ci* Hash Chain 17908c2ecf20Sopenharmony_ci***********************************/ 17918c2ecf20Sopenharmony_ci#define NEXT_IN_CHAIN(d, mask) chainTable[(d)&mask] 17928c2ecf20Sopenharmony_ci 17938c2ecf20Sopenharmony_ci/* Update chains up to ip (excluded) 17948c2ecf20Sopenharmony_ci Assumption : always within prefix (i.e. not within extDict) */ 17958c2ecf20Sopenharmony_ciFORCE_INLINE 17968c2ecf20Sopenharmony_ciU32 ZSTD_insertAndFindFirstIndex(ZSTD_CCtx *zc, const BYTE *ip, U32 mls) 17978c2ecf20Sopenharmony_ci{ 17988c2ecf20Sopenharmony_ci U32 *const hashTable = zc->hashTable; 17998c2ecf20Sopenharmony_ci const U32 hashLog = zc->params.cParams.hashLog; 18008c2ecf20Sopenharmony_ci U32 *const chainTable = zc->chainTable; 18018c2ecf20Sopenharmony_ci const U32 chainMask = (1 << zc->params.cParams.chainLog) - 1; 18028c2ecf20Sopenharmony_ci const BYTE *const base = zc->base; 18038c2ecf20Sopenharmony_ci const U32 target = (U32)(ip - base); 18048c2ecf20Sopenharmony_ci U32 idx = zc->nextToUpdate; 18058c2ecf20Sopenharmony_ci 18068c2ecf20Sopenharmony_ci while (idx < target) { /* catch up */ 18078c2ecf20Sopenharmony_ci size_t const h = ZSTD_hashPtr(base + idx, hashLog, mls); 18088c2ecf20Sopenharmony_ci NEXT_IN_CHAIN(idx, chainMask) = hashTable[h]; 18098c2ecf20Sopenharmony_ci hashTable[h] = idx; 18108c2ecf20Sopenharmony_ci idx++; 18118c2ecf20Sopenharmony_ci } 18128c2ecf20Sopenharmony_ci 18138c2ecf20Sopenharmony_ci zc->nextToUpdate = target; 18148c2ecf20Sopenharmony_ci return hashTable[ZSTD_hashPtr(ip, hashLog, mls)]; 18158c2ecf20Sopenharmony_ci} 18168c2ecf20Sopenharmony_ci 18178c2ecf20Sopenharmony_ci/* inlining is important to hardwire a hot branch (template emulation) */ 18188c2ecf20Sopenharmony_ciFORCE_INLINE 18198c2ecf20Sopenharmony_cisize_t ZSTD_HcFindBestMatch_generic(ZSTD_CCtx *zc, /* Index table will be updated */ 18208c2ecf20Sopenharmony_ci const BYTE *const ip, const BYTE *const iLimit, size_t *offsetPtr, const U32 maxNbAttempts, const U32 mls, 18218c2ecf20Sopenharmony_ci const U32 extDict) 18228c2ecf20Sopenharmony_ci{ 18238c2ecf20Sopenharmony_ci U32 *const chainTable = zc->chainTable; 18248c2ecf20Sopenharmony_ci const U32 chainSize = (1 << zc->params.cParams.chainLog); 18258c2ecf20Sopenharmony_ci const U32 chainMask = chainSize - 1; 18268c2ecf20Sopenharmony_ci const BYTE *const base = zc->base; 18278c2ecf20Sopenharmony_ci const BYTE *const dictBase = zc->dictBase; 18288c2ecf20Sopenharmony_ci const U32 dictLimit = zc->dictLimit; 18298c2ecf20Sopenharmony_ci const BYTE *const prefixStart = base + dictLimit; 18308c2ecf20Sopenharmony_ci const BYTE *const dictEnd = dictBase + dictLimit; 18318c2ecf20Sopenharmony_ci const U32 lowLimit = zc->lowLimit; 18328c2ecf20Sopenharmony_ci const U32 curr = (U32)(ip - base); 18338c2ecf20Sopenharmony_ci const U32 minChain = curr > chainSize ? curr - chainSize : 0; 18348c2ecf20Sopenharmony_ci int nbAttempts = maxNbAttempts; 18358c2ecf20Sopenharmony_ci size_t ml = EQUAL_READ32 - 1; 18368c2ecf20Sopenharmony_ci 18378c2ecf20Sopenharmony_ci /* HC4 match finder */ 18388c2ecf20Sopenharmony_ci U32 matchIndex = ZSTD_insertAndFindFirstIndex(zc, ip, mls); 18398c2ecf20Sopenharmony_ci 18408c2ecf20Sopenharmony_ci for (; (matchIndex > lowLimit) & (nbAttempts > 0); nbAttempts--) { 18418c2ecf20Sopenharmony_ci const BYTE *match; 18428c2ecf20Sopenharmony_ci size_t currMl = 0; 18438c2ecf20Sopenharmony_ci if ((!extDict) || matchIndex >= dictLimit) { 18448c2ecf20Sopenharmony_ci match = base + matchIndex; 18458c2ecf20Sopenharmony_ci if (match[ml] == ip[ml]) /* potentially better */ 18468c2ecf20Sopenharmony_ci currMl = ZSTD_count(ip, match, iLimit); 18478c2ecf20Sopenharmony_ci } else { 18488c2ecf20Sopenharmony_ci match = dictBase + matchIndex; 18498c2ecf20Sopenharmony_ci if (ZSTD_read32(match) == ZSTD_read32(ip)) /* assumption : matchIndex <= dictLimit-4 (by table construction) */ 18508c2ecf20Sopenharmony_ci currMl = ZSTD_count_2segments(ip + EQUAL_READ32, match + EQUAL_READ32, iLimit, dictEnd, prefixStart) + EQUAL_READ32; 18518c2ecf20Sopenharmony_ci } 18528c2ecf20Sopenharmony_ci 18538c2ecf20Sopenharmony_ci /* save best solution */ 18548c2ecf20Sopenharmony_ci if (currMl > ml) { 18558c2ecf20Sopenharmony_ci ml = currMl; 18568c2ecf20Sopenharmony_ci *offsetPtr = curr - matchIndex + ZSTD_REP_MOVE; 18578c2ecf20Sopenharmony_ci if (ip + currMl == iLimit) 18588c2ecf20Sopenharmony_ci break; /* best possible, and avoid read overflow*/ 18598c2ecf20Sopenharmony_ci } 18608c2ecf20Sopenharmony_ci 18618c2ecf20Sopenharmony_ci if (matchIndex <= minChain) 18628c2ecf20Sopenharmony_ci break; 18638c2ecf20Sopenharmony_ci matchIndex = NEXT_IN_CHAIN(matchIndex, chainMask); 18648c2ecf20Sopenharmony_ci } 18658c2ecf20Sopenharmony_ci 18668c2ecf20Sopenharmony_ci return ml; 18678c2ecf20Sopenharmony_ci} 18688c2ecf20Sopenharmony_ci 18698c2ecf20Sopenharmony_ciFORCE_INLINE size_t ZSTD_HcFindBestMatch_selectMLS(ZSTD_CCtx *zc, const BYTE *ip, const BYTE *const iLimit, size_t *offsetPtr, const U32 maxNbAttempts, 18708c2ecf20Sopenharmony_ci const U32 matchLengthSearch) 18718c2ecf20Sopenharmony_ci{ 18728c2ecf20Sopenharmony_ci switch (matchLengthSearch) { 18738c2ecf20Sopenharmony_ci default: /* includes case 3 */ 18748c2ecf20Sopenharmony_ci case 4: return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4, 0); 18758c2ecf20Sopenharmony_ci case 5: return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5, 0); 18768c2ecf20Sopenharmony_ci case 7: 18778c2ecf20Sopenharmony_ci case 6: return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6, 0); 18788c2ecf20Sopenharmony_ci } 18798c2ecf20Sopenharmony_ci} 18808c2ecf20Sopenharmony_ci 18818c2ecf20Sopenharmony_ciFORCE_INLINE size_t ZSTD_HcFindBestMatch_extDict_selectMLS(ZSTD_CCtx *zc, const BYTE *ip, const BYTE *const iLimit, size_t *offsetPtr, const U32 maxNbAttempts, 18828c2ecf20Sopenharmony_ci const U32 matchLengthSearch) 18838c2ecf20Sopenharmony_ci{ 18848c2ecf20Sopenharmony_ci switch (matchLengthSearch) { 18858c2ecf20Sopenharmony_ci default: /* includes case 3 */ 18868c2ecf20Sopenharmony_ci case 4: return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4, 1); 18878c2ecf20Sopenharmony_ci case 5: return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5, 1); 18888c2ecf20Sopenharmony_ci case 7: 18898c2ecf20Sopenharmony_ci case 6: return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6, 1); 18908c2ecf20Sopenharmony_ci } 18918c2ecf20Sopenharmony_ci} 18928c2ecf20Sopenharmony_ci 18938c2ecf20Sopenharmony_ci/* ******************************* 18948c2ecf20Sopenharmony_ci* Common parser - lazy strategy 18958c2ecf20Sopenharmony_ci*********************************/ 18968c2ecf20Sopenharmony_ciFORCE_INLINE 18978c2ecf20Sopenharmony_civoid ZSTD_compressBlock_lazy_generic(ZSTD_CCtx *ctx, const void *src, size_t srcSize, const U32 searchMethod, const U32 depth) 18988c2ecf20Sopenharmony_ci{ 18998c2ecf20Sopenharmony_ci seqStore_t *seqStorePtr = &(ctx->seqStore); 19008c2ecf20Sopenharmony_ci const BYTE *const istart = (const BYTE *)src; 19018c2ecf20Sopenharmony_ci const BYTE *ip = istart; 19028c2ecf20Sopenharmony_ci const BYTE *anchor = istart; 19038c2ecf20Sopenharmony_ci const BYTE *const iend = istart + srcSize; 19048c2ecf20Sopenharmony_ci const BYTE *const ilimit = iend - 8; 19058c2ecf20Sopenharmony_ci const BYTE *const base = ctx->base + ctx->dictLimit; 19068c2ecf20Sopenharmony_ci 19078c2ecf20Sopenharmony_ci U32 const maxSearches = 1 << ctx->params.cParams.searchLog; 19088c2ecf20Sopenharmony_ci U32 const mls = ctx->params.cParams.searchLength; 19098c2ecf20Sopenharmony_ci 19108c2ecf20Sopenharmony_ci typedef size_t (*searchMax_f)(ZSTD_CCtx * zc, const BYTE *ip, const BYTE *iLimit, size_t *offsetPtr, U32 maxNbAttempts, U32 matchLengthSearch); 19118c2ecf20Sopenharmony_ci searchMax_f const searchMax = searchMethod ? ZSTD_BtFindBestMatch_selectMLS : ZSTD_HcFindBestMatch_selectMLS; 19128c2ecf20Sopenharmony_ci U32 offset_1 = ctx->rep[0], offset_2 = ctx->rep[1], savedOffset = 0; 19138c2ecf20Sopenharmony_ci 19148c2ecf20Sopenharmony_ci /* init */ 19158c2ecf20Sopenharmony_ci ip += (ip == base); 19168c2ecf20Sopenharmony_ci ctx->nextToUpdate3 = ctx->nextToUpdate; 19178c2ecf20Sopenharmony_ci { 19188c2ecf20Sopenharmony_ci U32 const maxRep = (U32)(ip - base); 19198c2ecf20Sopenharmony_ci if (offset_2 > maxRep) 19208c2ecf20Sopenharmony_ci savedOffset = offset_2, offset_2 = 0; 19218c2ecf20Sopenharmony_ci if (offset_1 > maxRep) 19228c2ecf20Sopenharmony_ci savedOffset = offset_1, offset_1 = 0; 19238c2ecf20Sopenharmony_ci } 19248c2ecf20Sopenharmony_ci 19258c2ecf20Sopenharmony_ci /* Match Loop */ 19268c2ecf20Sopenharmony_ci while (ip < ilimit) { 19278c2ecf20Sopenharmony_ci size_t matchLength = 0; 19288c2ecf20Sopenharmony_ci size_t offset = 0; 19298c2ecf20Sopenharmony_ci const BYTE *start = ip + 1; 19308c2ecf20Sopenharmony_ci 19318c2ecf20Sopenharmony_ci /* check repCode */ 19328c2ecf20Sopenharmony_ci if ((offset_1 > 0) & (ZSTD_read32(ip + 1) == ZSTD_read32(ip + 1 - offset_1))) { 19338c2ecf20Sopenharmony_ci /* repcode : we take it */ 19348c2ecf20Sopenharmony_ci matchLength = ZSTD_count(ip + 1 + EQUAL_READ32, ip + 1 + EQUAL_READ32 - offset_1, iend) + EQUAL_READ32; 19358c2ecf20Sopenharmony_ci if (depth == 0) 19368c2ecf20Sopenharmony_ci goto _storeSequence; 19378c2ecf20Sopenharmony_ci } 19388c2ecf20Sopenharmony_ci 19398c2ecf20Sopenharmony_ci /* first search (depth 0) */ 19408c2ecf20Sopenharmony_ci { 19418c2ecf20Sopenharmony_ci size_t offsetFound = 99999999; 19428c2ecf20Sopenharmony_ci size_t const ml2 = searchMax(ctx, ip, iend, &offsetFound, maxSearches, mls); 19438c2ecf20Sopenharmony_ci if (ml2 > matchLength) 19448c2ecf20Sopenharmony_ci matchLength = ml2, start = ip, offset = offsetFound; 19458c2ecf20Sopenharmony_ci } 19468c2ecf20Sopenharmony_ci 19478c2ecf20Sopenharmony_ci if (matchLength < EQUAL_READ32) { 19488c2ecf20Sopenharmony_ci ip += ((ip - anchor) >> g_searchStrength) + 1; /* jump faster over incompressible sections */ 19498c2ecf20Sopenharmony_ci continue; 19508c2ecf20Sopenharmony_ci } 19518c2ecf20Sopenharmony_ci 19528c2ecf20Sopenharmony_ci /* let's try to find a better solution */ 19538c2ecf20Sopenharmony_ci if (depth >= 1) 19548c2ecf20Sopenharmony_ci while (ip < ilimit) { 19558c2ecf20Sopenharmony_ci ip++; 19568c2ecf20Sopenharmony_ci if ((offset) && ((offset_1 > 0) & (ZSTD_read32(ip) == ZSTD_read32(ip - offset_1)))) { 19578c2ecf20Sopenharmony_ci size_t const mlRep = ZSTD_count(ip + EQUAL_READ32, ip + EQUAL_READ32 - offset_1, iend) + EQUAL_READ32; 19588c2ecf20Sopenharmony_ci int const gain2 = (int)(mlRep * 3); 19598c2ecf20Sopenharmony_ci int const gain1 = (int)(matchLength * 3 - ZSTD_highbit32((U32)offset + 1) + 1); 19608c2ecf20Sopenharmony_ci if ((mlRep >= EQUAL_READ32) && (gain2 > gain1)) 19618c2ecf20Sopenharmony_ci matchLength = mlRep, offset = 0, start = ip; 19628c2ecf20Sopenharmony_ci } 19638c2ecf20Sopenharmony_ci { 19648c2ecf20Sopenharmony_ci size_t offset2 = 99999999; 19658c2ecf20Sopenharmony_ci size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls); 19668c2ecf20Sopenharmony_ci int const gain2 = (int)(ml2 * 4 - ZSTD_highbit32((U32)offset2 + 1)); /* raw approx */ 19678c2ecf20Sopenharmony_ci int const gain1 = (int)(matchLength * 4 - ZSTD_highbit32((U32)offset + 1) + 4); 19688c2ecf20Sopenharmony_ci if ((ml2 >= EQUAL_READ32) && (gain2 > gain1)) { 19698c2ecf20Sopenharmony_ci matchLength = ml2, offset = offset2, start = ip; 19708c2ecf20Sopenharmony_ci continue; /* search a better one */ 19718c2ecf20Sopenharmony_ci } 19728c2ecf20Sopenharmony_ci } 19738c2ecf20Sopenharmony_ci 19748c2ecf20Sopenharmony_ci /* let's find an even better one */ 19758c2ecf20Sopenharmony_ci if ((depth == 2) && (ip < ilimit)) { 19768c2ecf20Sopenharmony_ci ip++; 19778c2ecf20Sopenharmony_ci if ((offset) && ((offset_1 > 0) & (ZSTD_read32(ip) == ZSTD_read32(ip - offset_1)))) { 19788c2ecf20Sopenharmony_ci size_t const ml2 = ZSTD_count(ip + EQUAL_READ32, ip + EQUAL_READ32 - offset_1, iend) + EQUAL_READ32; 19798c2ecf20Sopenharmony_ci int const gain2 = (int)(ml2 * 4); 19808c2ecf20Sopenharmony_ci int const gain1 = (int)(matchLength * 4 - ZSTD_highbit32((U32)offset + 1) + 1); 19818c2ecf20Sopenharmony_ci if ((ml2 >= EQUAL_READ32) && (gain2 > gain1)) 19828c2ecf20Sopenharmony_ci matchLength = ml2, offset = 0, start = ip; 19838c2ecf20Sopenharmony_ci } 19848c2ecf20Sopenharmony_ci { 19858c2ecf20Sopenharmony_ci size_t offset2 = 99999999; 19868c2ecf20Sopenharmony_ci size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls); 19878c2ecf20Sopenharmony_ci int const gain2 = (int)(ml2 * 4 - ZSTD_highbit32((U32)offset2 + 1)); /* raw approx */ 19888c2ecf20Sopenharmony_ci int const gain1 = (int)(matchLength * 4 - ZSTD_highbit32((U32)offset + 1) + 7); 19898c2ecf20Sopenharmony_ci if ((ml2 >= EQUAL_READ32) && (gain2 > gain1)) { 19908c2ecf20Sopenharmony_ci matchLength = ml2, offset = offset2, start = ip; 19918c2ecf20Sopenharmony_ci continue; 19928c2ecf20Sopenharmony_ci } 19938c2ecf20Sopenharmony_ci } 19948c2ecf20Sopenharmony_ci } 19958c2ecf20Sopenharmony_ci break; /* nothing found : store previous solution */ 19968c2ecf20Sopenharmony_ci } 19978c2ecf20Sopenharmony_ci 19988c2ecf20Sopenharmony_ci /* NOTE: 19998c2ecf20Sopenharmony_ci * start[-offset+ZSTD_REP_MOVE-1] is undefined behavior. 20008c2ecf20Sopenharmony_ci * (-offset+ZSTD_REP_MOVE-1) is unsigned, and is added to start, which 20018c2ecf20Sopenharmony_ci * overflows the pointer, which is undefined behavior. 20028c2ecf20Sopenharmony_ci */ 20038c2ecf20Sopenharmony_ci /* catch up */ 20048c2ecf20Sopenharmony_ci if (offset) { 20058c2ecf20Sopenharmony_ci while ((start > anchor) && (start > base + offset - ZSTD_REP_MOVE) && 20068c2ecf20Sopenharmony_ci (start[-1] == (start-offset+ZSTD_REP_MOVE)[-1])) /* only search for offset within prefix */ 20078c2ecf20Sopenharmony_ci { 20088c2ecf20Sopenharmony_ci start--; 20098c2ecf20Sopenharmony_ci matchLength++; 20108c2ecf20Sopenharmony_ci } 20118c2ecf20Sopenharmony_ci offset_2 = offset_1; 20128c2ecf20Sopenharmony_ci offset_1 = (U32)(offset - ZSTD_REP_MOVE); 20138c2ecf20Sopenharmony_ci } 20148c2ecf20Sopenharmony_ci 20158c2ecf20Sopenharmony_ci /* store sequence */ 20168c2ecf20Sopenharmony_ci_storeSequence: 20178c2ecf20Sopenharmony_ci { 20188c2ecf20Sopenharmony_ci size_t const litLength = start - anchor; 20198c2ecf20Sopenharmony_ci ZSTD_storeSeq(seqStorePtr, litLength, anchor, (U32)offset, matchLength - MINMATCH); 20208c2ecf20Sopenharmony_ci anchor = ip = start + matchLength; 20218c2ecf20Sopenharmony_ci } 20228c2ecf20Sopenharmony_ci 20238c2ecf20Sopenharmony_ci /* check immediate repcode */ 20248c2ecf20Sopenharmony_ci while ((ip <= ilimit) && ((offset_2 > 0) & (ZSTD_read32(ip) == ZSTD_read32(ip - offset_2)))) { 20258c2ecf20Sopenharmony_ci /* store sequence */ 20268c2ecf20Sopenharmony_ci matchLength = ZSTD_count(ip + EQUAL_READ32, ip + EQUAL_READ32 - offset_2, iend) + EQUAL_READ32; 20278c2ecf20Sopenharmony_ci offset = offset_2; 20288c2ecf20Sopenharmony_ci offset_2 = offset_1; 20298c2ecf20Sopenharmony_ci offset_1 = (U32)offset; /* swap repcodes */ 20308c2ecf20Sopenharmony_ci ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, matchLength - MINMATCH); 20318c2ecf20Sopenharmony_ci ip += matchLength; 20328c2ecf20Sopenharmony_ci anchor = ip; 20338c2ecf20Sopenharmony_ci continue; /* faster when present ... (?) */ 20348c2ecf20Sopenharmony_ci } 20358c2ecf20Sopenharmony_ci } 20368c2ecf20Sopenharmony_ci 20378c2ecf20Sopenharmony_ci /* Save reps for next block */ 20388c2ecf20Sopenharmony_ci ctx->repToConfirm[0] = offset_1 ? offset_1 : savedOffset; 20398c2ecf20Sopenharmony_ci ctx->repToConfirm[1] = offset_2 ? offset_2 : savedOffset; 20408c2ecf20Sopenharmony_ci 20418c2ecf20Sopenharmony_ci /* Last Literals */ 20428c2ecf20Sopenharmony_ci { 20438c2ecf20Sopenharmony_ci size_t const lastLLSize = iend - anchor; 20448c2ecf20Sopenharmony_ci memcpy(seqStorePtr->lit, anchor, lastLLSize); 20458c2ecf20Sopenharmony_ci seqStorePtr->lit += lastLLSize; 20468c2ecf20Sopenharmony_ci } 20478c2ecf20Sopenharmony_ci} 20488c2ecf20Sopenharmony_ci 20498c2ecf20Sopenharmony_cistatic void ZSTD_compressBlock_btlazy2(ZSTD_CCtx *ctx, const void *src, size_t srcSize) { ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 1, 2); } 20508c2ecf20Sopenharmony_ci 20518c2ecf20Sopenharmony_cistatic void ZSTD_compressBlock_lazy2(ZSTD_CCtx *ctx, const void *src, size_t srcSize) { ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 0, 2); } 20528c2ecf20Sopenharmony_ci 20538c2ecf20Sopenharmony_cistatic void ZSTD_compressBlock_lazy(ZSTD_CCtx *ctx, const void *src, size_t srcSize) { ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 0, 1); } 20548c2ecf20Sopenharmony_ci 20558c2ecf20Sopenharmony_cistatic void ZSTD_compressBlock_greedy(ZSTD_CCtx *ctx, const void *src, size_t srcSize) { ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 0, 0); } 20568c2ecf20Sopenharmony_ci 20578c2ecf20Sopenharmony_ciFORCE_INLINE 20588c2ecf20Sopenharmony_civoid ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx *ctx, const void *src, size_t srcSize, const U32 searchMethod, const U32 depth) 20598c2ecf20Sopenharmony_ci{ 20608c2ecf20Sopenharmony_ci seqStore_t *seqStorePtr = &(ctx->seqStore); 20618c2ecf20Sopenharmony_ci const BYTE *const istart = (const BYTE *)src; 20628c2ecf20Sopenharmony_ci const BYTE *ip = istart; 20638c2ecf20Sopenharmony_ci const BYTE *anchor = istart; 20648c2ecf20Sopenharmony_ci const BYTE *const iend = istart + srcSize; 20658c2ecf20Sopenharmony_ci const BYTE *const ilimit = iend - 8; 20668c2ecf20Sopenharmony_ci const BYTE *const base = ctx->base; 20678c2ecf20Sopenharmony_ci const U32 dictLimit = ctx->dictLimit; 20688c2ecf20Sopenharmony_ci const U32 lowestIndex = ctx->lowLimit; 20698c2ecf20Sopenharmony_ci const BYTE *const prefixStart = base + dictLimit; 20708c2ecf20Sopenharmony_ci const BYTE *const dictBase = ctx->dictBase; 20718c2ecf20Sopenharmony_ci const BYTE *const dictEnd = dictBase + dictLimit; 20728c2ecf20Sopenharmony_ci const BYTE *const dictStart = dictBase + ctx->lowLimit; 20738c2ecf20Sopenharmony_ci 20748c2ecf20Sopenharmony_ci const U32 maxSearches = 1 << ctx->params.cParams.searchLog; 20758c2ecf20Sopenharmony_ci const U32 mls = ctx->params.cParams.searchLength; 20768c2ecf20Sopenharmony_ci 20778c2ecf20Sopenharmony_ci typedef size_t (*searchMax_f)(ZSTD_CCtx * zc, const BYTE *ip, const BYTE *iLimit, size_t *offsetPtr, U32 maxNbAttempts, U32 matchLengthSearch); 20788c2ecf20Sopenharmony_ci searchMax_f searchMax = searchMethod ? ZSTD_BtFindBestMatch_selectMLS_extDict : ZSTD_HcFindBestMatch_extDict_selectMLS; 20798c2ecf20Sopenharmony_ci 20808c2ecf20Sopenharmony_ci U32 offset_1 = ctx->rep[0], offset_2 = ctx->rep[1]; 20818c2ecf20Sopenharmony_ci 20828c2ecf20Sopenharmony_ci /* init */ 20838c2ecf20Sopenharmony_ci ctx->nextToUpdate3 = ctx->nextToUpdate; 20848c2ecf20Sopenharmony_ci ip += (ip == prefixStart); 20858c2ecf20Sopenharmony_ci 20868c2ecf20Sopenharmony_ci /* Match Loop */ 20878c2ecf20Sopenharmony_ci while (ip < ilimit) { 20888c2ecf20Sopenharmony_ci size_t matchLength = 0; 20898c2ecf20Sopenharmony_ci size_t offset = 0; 20908c2ecf20Sopenharmony_ci const BYTE *start = ip + 1; 20918c2ecf20Sopenharmony_ci U32 curr = (U32)(ip - base); 20928c2ecf20Sopenharmony_ci 20938c2ecf20Sopenharmony_ci /* check repCode */ 20948c2ecf20Sopenharmony_ci { 20958c2ecf20Sopenharmony_ci const U32 repIndex = (U32)(curr + 1 - offset_1); 20968c2ecf20Sopenharmony_ci const BYTE *const repBase = repIndex < dictLimit ? dictBase : base; 20978c2ecf20Sopenharmony_ci const BYTE *const repMatch = repBase + repIndex; 20988c2ecf20Sopenharmony_ci if (((U32)((dictLimit - 1) - repIndex) >= 3) & (repIndex > lowestIndex)) /* intentional overflow */ 20998c2ecf20Sopenharmony_ci if (ZSTD_read32(ip + 1) == ZSTD_read32(repMatch)) { 21008c2ecf20Sopenharmony_ci /* repcode detected we should take it */ 21018c2ecf20Sopenharmony_ci const BYTE *const repEnd = repIndex < dictLimit ? dictEnd : iend; 21028c2ecf20Sopenharmony_ci matchLength = 21038c2ecf20Sopenharmony_ci ZSTD_count_2segments(ip + 1 + EQUAL_READ32, repMatch + EQUAL_READ32, iend, repEnd, prefixStart) + EQUAL_READ32; 21048c2ecf20Sopenharmony_ci if (depth == 0) 21058c2ecf20Sopenharmony_ci goto _storeSequence; 21068c2ecf20Sopenharmony_ci } 21078c2ecf20Sopenharmony_ci } 21088c2ecf20Sopenharmony_ci 21098c2ecf20Sopenharmony_ci /* first search (depth 0) */ 21108c2ecf20Sopenharmony_ci { 21118c2ecf20Sopenharmony_ci size_t offsetFound = 99999999; 21128c2ecf20Sopenharmony_ci size_t const ml2 = searchMax(ctx, ip, iend, &offsetFound, maxSearches, mls); 21138c2ecf20Sopenharmony_ci if (ml2 > matchLength) 21148c2ecf20Sopenharmony_ci matchLength = ml2, start = ip, offset = offsetFound; 21158c2ecf20Sopenharmony_ci } 21168c2ecf20Sopenharmony_ci 21178c2ecf20Sopenharmony_ci if (matchLength < EQUAL_READ32) { 21188c2ecf20Sopenharmony_ci ip += ((ip - anchor) >> g_searchStrength) + 1; /* jump faster over incompressible sections */ 21198c2ecf20Sopenharmony_ci continue; 21208c2ecf20Sopenharmony_ci } 21218c2ecf20Sopenharmony_ci 21228c2ecf20Sopenharmony_ci /* let's try to find a better solution */ 21238c2ecf20Sopenharmony_ci if (depth >= 1) 21248c2ecf20Sopenharmony_ci while (ip < ilimit) { 21258c2ecf20Sopenharmony_ci ip++; 21268c2ecf20Sopenharmony_ci curr++; 21278c2ecf20Sopenharmony_ci /* check repCode */ 21288c2ecf20Sopenharmony_ci if (offset) { 21298c2ecf20Sopenharmony_ci const U32 repIndex = (U32)(curr - offset_1); 21308c2ecf20Sopenharmony_ci const BYTE *const repBase = repIndex < dictLimit ? dictBase : base; 21318c2ecf20Sopenharmony_ci const BYTE *const repMatch = repBase + repIndex; 21328c2ecf20Sopenharmony_ci if (((U32)((dictLimit - 1) - repIndex) >= 3) & (repIndex > lowestIndex)) /* intentional overflow */ 21338c2ecf20Sopenharmony_ci if (ZSTD_read32(ip) == ZSTD_read32(repMatch)) { 21348c2ecf20Sopenharmony_ci /* repcode detected */ 21358c2ecf20Sopenharmony_ci const BYTE *const repEnd = repIndex < dictLimit ? dictEnd : iend; 21368c2ecf20Sopenharmony_ci size_t const repLength = 21378c2ecf20Sopenharmony_ci ZSTD_count_2segments(ip + EQUAL_READ32, repMatch + EQUAL_READ32, iend, repEnd, prefixStart) + 21388c2ecf20Sopenharmony_ci EQUAL_READ32; 21398c2ecf20Sopenharmony_ci int const gain2 = (int)(repLength * 3); 21408c2ecf20Sopenharmony_ci int const gain1 = (int)(matchLength * 3 - ZSTD_highbit32((U32)offset + 1) + 1); 21418c2ecf20Sopenharmony_ci if ((repLength >= EQUAL_READ32) && (gain2 > gain1)) 21428c2ecf20Sopenharmony_ci matchLength = repLength, offset = 0, start = ip; 21438c2ecf20Sopenharmony_ci } 21448c2ecf20Sopenharmony_ci } 21458c2ecf20Sopenharmony_ci 21468c2ecf20Sopenharmony_ci /* search match, depth 1 */ 21478c2ecf20Sopenharmony_ci { 21488c2ecf20Sopenharmony_ci size_t offset2 = 99999999; 21498c2ecf20Sopenharmony_ci size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls); 21508c2ecf20Sopenharmony_ci int const gain2 = (int)(ml2 * 4 - ZSTD_highbit32((U32)offset2 + 1)); /* raw approx */ 21518c2ecf20Sopenharmony_ci int const gain1 = (int)(matchLength * 4 - ZSTD_highbit32((U32)offset + 1) + 4); 21528c2ecf20Sopenharmony_ci if ((ml2 >= EQUAL_READ32) && (gain2 > gain1)) { 21538c2ecf20Sopenharmony_ci matchLength = ml2, offset = offset2, start = ip; 21548c2ecf20Sopenharmony_ci continue; /* search a better one */ 21558c2ecf20Sopenharmony_ci } 21568c2ecf20Sopenharmony_ci } 21578c2ecf20Sopenharmony_ci 21588c2ecf20Sopenharmony_ci /* let's find an even better one */ 21598c2ecf20Sopenharmony_ci if ((depth == 2) && (ip < ilimit)) { 21608c2ecf20Sopenharmony_ci ip++; 21618c2ecf20Sopenharmony_ci curr++; 21628c2ecf20Sopenharmony_ci /* check repCode */ 21638c2ecf20Sopenharmony_ci if (offset) { 21648c2ecf20Sopenharmony_ci const U32 repIndex = (U32)(curr - offset_1); 21658c2ecf20Sopenharmony_ci const BYTE *const repBase = repIndex < dictLimit ? dictBase : base; 21668c2ecf20Sopenharmony_ci const BYTE *const repMatch = repBase + repIndex; 21678c2ecf20Sopenharmony_ci if (((U32)((dictLimit - 1) - repIndex) >= 3) & (repIndex > lowestIndex)) /* intentional overflow */ 21688c2ecf20Sopenharmony_ci if (ZSTD_read32(ip) == ZSTD_read32(repMatch)) { 21698c2ecf20Sopenharmony_ci /* repcode detected */ 21708c2ecf20Sopenharmony_ci const BYTE *const repEnd = repIndex < dictLimit ? dictEnd : iend; 21718c2ecf20Sopenharmony_ci size_t repLength = ZSTD_count_2segments(ip + EQUAL_READ32, repMatch + EQUAL_READ32, iend, 21728c2ecf20Sopenharmony_ci repEnd, prefixStart) + 21738c2ecf20Sopenharmony_ci EQUAL_READ32; 21748c2ecf20Sopenharmony_ci int gain2 = (int)(repLength * 4); 21758c2ecf20Sopenharmony_ci int gain1 = (int)(matchLength * 4 - ZSTD_highbit32((U32)offset + 1) + 1); 21768c2ecf20Sopenharmony_ci if ((repLength >= EQUAL_READ32) && (gain2 > gain1)) 21778c2ecf20Sopenharmony_ci matchLength = repLength, offset = 0, start = ip; 21788c2ecf20Sopenharmony_ci } 21798c2ecf20Sopenharmony_ci } 21808c2ecf20Sopenharmony_ci 21818c2ecf20Sopenharmony_ci /* search match, depth 2 */ 21828c2ecf20Sopenharmony_ci { 21838c2ecf20Sopenharmony_ci size_t offset2 = 99999999; 21848c2ecf20Sopenharmony_ci size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls); 21858c2ecf20Sopenharmony_ci int const gain2 = (int)(ml2 * 4 - ZSTD_highbit32((U32)offset2 + 1)); /* raw approx */ 21868c2ecf20Sopenharmony_ci int const gain1 = (int)(matchLength * 4 - ZSTD_highbit32((U32)offset + 1) + 7); 21878c2ecf20Sopenharmony_ci if ((ml2 >= EQUAL_READ32) && (gain2 > gain1)) { 21888c2ecf20Sopenharmony_ci matchLength = ml2, offset = offset2, start = ip; 21898c2ecf20Sopenharmony_ci continue; 21908c2ecf20Sopenharmony_ci } 21918c2ecf20Sopenharmony_ci } 21928c2ecf20Sopenharmony_ci } 21938c2ecf20Sopenharmony_ci break; /* nothing found : store previous solution */ 21948c2ecf20Sopenharmony_ci } 21958c2ecf20Sopenharmony_ci 21968c2ecf20Sopenharmony_ci /* catch up */ 21978c2ecf20Sopenharmony_ci if (offset) { 21988c2ecf20Sopenharmony_ci U32 const matchIndex = (U32)((start - base) - (offset - ZSTD_REP_MOVE)); 21998c2ecf20Sopenharmony_ci const BYTE *match = (matchIndex < dictLimit) ? dictBase + matchIndex : base + matchIndex; 22008c2ecf20Sopenharmony_ci const BYTE *const mStart = (matchIndex < dictLimit) ? dictStart : prefixStart; 22018c2ecf20Sopenharmony_ci while ((start > anchor) && (match > mStart) && (start[-1] == match[-1])) { 22028c2ecf20Sopenharmony_ci start--; 22038c2ecf20Sopenharmony_ci match--; 22048c2ecf20Sopenharmony_ci matchLength++; 22058c2ecf20Sopenharmony_ci } /* catch up */ 22068c2ecf20Sopenharmony_ci offset_2 = offset_1; 22078c2ecf20Sopenharmony_ci offset_1 = (U32)(offset - ZSTD_REP_MOVE); 22088c2ecf20Sopenharmony_ci } 22098c2ecf20Sopenharmony_ci 22108c2ecf20Sopenharmony_ci /* store sequence */ 22118c2ecf20Sopenharmony_ci _storeSequence : { 22128c2ecf20Sopenharmony_ci size_t const litLength = start - anchor; 22138c2ecf20Sopenharmony_ci ZSTD_storeSeq(seqStorePtr, litLength, anchor, (U32)offset, matchLength - MINMATCH); 22148c2ecf20Sopenharmony_ci anchor = ip = start + matchLength; 22158c2ecf20Sopenharmony_ci } 22168c2ecf20Sopenharmony_ci 22178c2ecf20Sopenharmony_ci /* check immediate repcode */ 22188c2ecf20Sopenharmony_ci while (ip <= ilimit) { 22198c2ecf20Sopenharmony_ci const U32 repIndex = (U32)((ip - base) - offset_2); 22208c2ecf20Sopenharmony_ci const BYTE *const repBase = repIndex < dictLimit ? dictBase : base; 22218c2ecf20Sopenharmony_ci const BYTE *const repMatch = repBase + repIndex; 22228c2ecf20Sopenharmony_ci if (((U32)((dictLimit - 1) - repIndex) >= 3) & (repIndex > lowestIndex)) /* intentional overflow */ 22238c2ecf20Sopenharmony_ci if (ZSTD_read32(ip) == ZSTD_read32(repMatch)) { 22248c2ecf20Sopenharmony_ci /* repcode detected we should take it */ 22258c2ecf20Sopenharmony_ci const BYTE *const repEnd = repIndex < dictLimit ? dictEnd : iend; 22268c2ecf20Sopenharmony_ci matchLength = 22278c2ecf20Sopenharmony_ci ZSTD_count_2segments(ip + EQUAL_READ32, repMatch + EQUAL_READ32, iend, repEnd, prefixStart) + EQUAL_READ32; 22288c2ecf20Sopenharmony_ci offset = offset_2; 22298c2ecf20Sopenharmony_ci offset_2 = offset_1; 22308c2ecf20Sopenharmony_ci offset_1 = (U32)offset; /* swap offset history */ 22318c2ecf20Sopenharmony_ci ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, matchLength - MINMATCH); 22328c2ecf20Sopenharmony_ci ip += matchLength; 22338c2ecf20Sopenharmony_ci anchor = ip; 22348c2ecf20Sopenharmony_ci continue; /* faster when present ... (?) */ 22358c2ecf20Sopenharmony_ci } 22368c2ecf20Sopenharmony_ci break; 22378c2ecf20Sopenharmony_ci } 22388c2ecf20Sopenharmony_ci } 22398c2ecf20Sopenharmony_ci 22408c2ecf20Sopenharmony_ci /* Save reps for next block */ 22418c2ecf20Sopenharmony_ci ctx->repToConfirm[0] = offset_1; 22428c2ecf20Sopenharmony_ci ctx->repToConfirm[1] = offset_2; 22438c2ecf20Sopenharmony_ci 22448c2ecf20Sopenharmony_ci /* Last Literals */ 22458c2ecf20Sopenharmony_ci { 22468c2ecf20Sopenharmony_ci size_t const lastLLSize = iend - anchor; 22478c2ecf20Sopenharmony_ci memcpy(seqStorePtr->lit, anchor, lastLLSize); 22488c2ecf20Sopenharmony_ci seqStorePtr->lit += lastLLSize; 22498c2ecf20Sopenharmony_ci } 22508c2ecf20Sopenharmony_ci} 22518c2ecf20Sopenharmony_ci 22528c2ecf20Sopenharmony_civoid ZSTD_compressBlock_greedy_extDict(ZSTD_CCtx *ctx, const void *src, size_t srcSize) { ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 0, 0); } 22538c2ecf20Sopenharmony_ci 22548c2ecf20Sopenharmony_cistatic void ZSTD_compressBlock_lazy_extDict(ZSTD_CCtx *ctx, const void *src, size_t srcSize) 22558c2ecf20Sopenharmony_ci{ 22568c2ecf20Sopenharmony_ci ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 0, 1); 22578c2ecf20Sopenharmony_ci} 22588c2ecf20Sopenharmony_ci 22598c2ecf20Sopenharmony_cistatic void ZSTD_compressBlock_lazy2_extDict(ZSTD_CCtx *ctx, const void *src, size_t srcSize) 22608c2ecf20Sopenharmony_ci{ 22618c2ecf20Sopenharmony_ci ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 0, 2); 22628c2ecf20Sopenharmony_ci} 22638c2ecf20Sopenharmony_ci 22648c2ecf20Sopenharmony_cistatic void ZSTD_compressBlock_btlazy2_extDict(ZSTD_CCtx *ctx, const void *src, size_t srcSize) 22658c2ecf20Sopenharmony_ci{ 22668c2ecf20Sopenharmony_ci ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 1, 2); 22678c2ecf20Sopenharmony_ci} 22688c2ecf20Sopenharmony_ci 22698c2ecf20Sopenharmony_ci/* The optimal parser */ 22708c2ecf20Sopenharmony_ci#include "zstd_opt.h" 22718c2ecf20Sopenharmony_ci 22728c2ecf20Sopenharmony_cistatic void ZSTD_compressBlock_btopt(ZSTD_CCtx *ctx, const void *src, size_t srcSize) 22738c2ecf20Sopenharmony_ci{ 22748c2ecf20Sopenharmony_ci#ifdef ZSTD_OPT_H_91842398743 22758c2ecf20Sopenharmony_ci ZSTD_compressBlock_opt_generic(ctx, src, srcSize, 0); 22768c2ecf20Sopenharmony_ci#else 22778c2ecf20Sopenharmony_ci (void)ctx; 22788c2ecf20Sopenharmony_ci (void)src; 22798c2ecf20Sopenharmony_ci (void)srcSize; 22808c2ecf20Sopenharmony_ci return; 22818c2ecf20Sopenharmony_ci#endif 22828c2ecf20Sopenharmony_ci} 22838c2ecf20Sopenharmony_ci 22848c2ecf20Sopenharmony_cistatic void ZSTD_compressBlock_btopt2(ZSTD_CCtx *ctx, const void *src, size_t srcSize) 22858c2ecf20Sopenharmony_ci{ 22868c2ecf20Sopenharmony_ci#ifdef ZSTD_OPT_H_91842398743 22878c2ecf20Sopenharmony_ci ZSTD_compressBlock_opt_generic(ctx, src, srcSize, 1); 22888c2ecf20Sopenharmony_ci#else 22898c2ecf20Sopenharmony_ci (void)ctx; 22908c2ecf20Sopenharmony_ci (void)src; 22918c2ecf20Sopenharmony_ci (void)srcSize; 22928c2ecf20Sopenharmony_ci return; 22938c2ecf20Sopenharmony_ci#endif 22948c2ecf20Sopenharmony_ci} 22958c2ecf20Sopenharmony_ci 22968c2ecf20Sopenharmony_cistatic void ZSTD_compressBlock_btopt_extDict(ZSTD_CCtx *ctx, const void *src, size_t srcSize) 22978c2ecf20Sopenharmony_ci{ 22988c2ecf20Sopenharmony_ci#ifdef ZSTD_OPT_H_91842398743 22998c2ecf20Sopenharmony_ci ZSTD_compressBlock_opt_extDict_generic(ctx, src, srcSize, 0); 23008c2ecf20Sopenharmony_ci#else 23018c2ecf20Sopenharmony_ci (void)ctx; 23028c2ecf20Sopenharmony_ci (void)src; 23038c2ecf20Sopenharmony_ci (void)srcSize; 23048c2ecf20Sopenharmony_ci return; 23058c2ecf20Sopenharmony_ci#endif 23068c2ecf20Sopenharmony_ci} 23078c2ecf20Sopenharmony_ci 23088c2ecf20Sopenharmony_cistatic void ZSTD_compressBlock_btopt2_extDict(ZSTD_CCtx *ctx, const void *src, size_t srcSize) 23098c2ecf20Sopenharmony_ci{ 23108c2ecf20Sopenharmony_ci#ifdef ZSTD_OPT_H_91842398743 23118c2ecf20Sopenharmony_ci ZSTD_compressBlock_opt_extDict_generic(ctx, src, srcSize, 1); 23128c2ecf20Sopenharmony_ci#else 23138c2ecf20Sopenharmony_ci (void)ctx; 23148c2ecf20Sopenharmony_ci (void)src; 23158c2ecf20Sopenharmony_ci (void)srcSize; 23168c2ecf20Sopenharmony_ci return; 23178c2ecf20Sopenharmony_ci#endif 23188c2ecf20Sopenharmony_ci} 23198c2ecf20Sopenharmony_ci 23208c2ecf20Sopenharmony_citypedef void (*ZSTD_blockCompressor)(ZSTD_CCtx *ctx, const void *src, size_t srcSize); 23218c2ecf20Sopenharmony_ci 23228c2ecf20Sopenharmony_cistatic ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, int extDict) 23238c2ecf20Sopenharmony_ci{ 23248c2ecf20Sopenharmony_ci static const ZSTD_blockCompressor blockCompressor[2][8] = { 23258c2ecf20Sopenharmony_ci {ZSTD_compressBlock_fast, ZSTD_compressBlock_doubleFast, ZSTD_compressBlock_greedy, ZSTD_compressBlock_lazy, ZSTD_compressBlock_lazy2, 23268c2ecf20Sopenharmony_ci ZSTD_compressBlock_btlazy2, ZSTD_compressBlock_btopt, ZSTD_compressBlock_btopt2}, 23278c2ecf20Sopenharmony_ci {ZSTD_compressBlock_fast_extDict, ZSTD_compressBlock_doubleFast_extDict, ZSTD_compressBlock_greedy_extDict, ZSTD_compressBlock_lazy_extDict, 23288c2ecf20Sopenharmony_ci ZSTD_compressBlock_lazy2_extDict, ZSTD_compressBlock_btlazy2_extDict, ZSTD_compressBlock_btopt_extDict, ZSTD_compressBlock_btopt2_extDict}}; 23298c2ecf20Sopenharmony_ci 23308c2ecf20Sopenharmony_ci return blockCompressor[extDict][(U32)strat]; 23318c2ecf20Sopenharmony_ci} 23328c2ecf20Sopenharmony_ci 23338c2ecf20Sopenharmony_cistatic size_t ZSTD_compressBlock_internal(ZSTD_CCtx *zc, void *dst, size_t dstCapacity, const void *src, size_t srcSize) 23348c2ecf20Sopenharmony_ci{ 23358c2ecf20Sopenharmony_ci ZSTD_blockCompressor const blockCompressor = ZSTD_selectBlockCompressor(zc->params.cParams.strategy, zc->lowLimit < zc->dictLimit); 23368c2ecf20Sopenharmony_ci const BYTE *const base = zc->base; 23378c2ecf20Sopenharmony_ci const BYTE *const istart = (const BYTE *)src; 23388c2ecf20Sopenharmony_ci const U32 curr = (U32)(istart - base); 23398c2ecf20Sopenharmony_ci if (srcSize < MIN_CBLOCK_SIZE + ZSTD_blockHeaderSize + 1) 23408c2ecf20Sopenharmony_ci return 0; /* don't even attempt compression below a certain srcSize */ 23418c2ecf20Sopenharmony_ci ZSTD_resetSeqStore(&(zc->seqStore)); 23428c2ecf20Sopenharmony_ci if (curr > zc->nextToUpdate + 384) 23438c2ecf20Sopenharmony_ci zc->nextToUpdate = curr - MIN(192, (U32)(curr - zc->nextToUpdate - 384)); /* update tree not updated after finding very long rep matches */ 23448c2ecf20Sopenharmony_ci blockCompressor(zc, src, srcSize); 23458c2ecf20Sopenharmony_ci return ZSTD_compressSequences(zc, dst, dstCapacity, srcSize); 23468c2ecf20Sopenharmony_ci} 23478c2ecf20Sopenharmony_ci 23488c2ecf20Sopenharmony_ci/*! ZSTD_compress_generic() : 23498c2ecf20Sopenharmony_ci* Compress a chunk of data into one or multiple blocks. 23508c2ecf20Sopenharmony_ci* All blocks will be terminated, all input will be consumed. 23518c2ecf20Sopenharmony_ci* Function will issue an error if there is not enough `dstCapacity` to hold the compressed content. 23528c2ecf20Sopenharmony_ci* Frame is supposed already started (header already produced) 23538c2ecf20Sopenharmony_ci* @return : compressed size, or an error code 23548c2ecf20Sopenharmony_ci*/ 23558c2ecf20Sopenharmony_cistatic size_t ZSTD_compress_generic(ZSTD_CCtx *cctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize, U32 lastFrameChunk) 23568c2ecf20Sopenharmony_ci{ 23578c2ecf20Sopenharmony_ci size_t blockSize = cctx->blockSize; 23588c2ecf20Sopenharmony_ci size_t remaining = srcSize; 23598c2ecf20Sopenharmony_ci const BYTE *ip = (const BYTE *)src; 23608c2ecf20Sopenharmony_ci BYTE *const ostart = (BYTE *)dst; 23618c2ecf20Sopenharmony_ci BYTE *op = ostart; 23628c2ecf20Sopenharmony_ci U32 const maxDist = 1 << cctx->params.cParams.windowLog; 23638c2ecf20Sopenharmony_ci 23648c2ecf20Sopenharmony_ci if (cctx->params.fParams.checksumFlag && srcSize) 23658c2ecf20Sopenharmony_ci xxh64_update(&cctx->xxhState, src, srcSize); 23668c2ecf20Sopenharmony_ci 23678c2ecf20Sopenharmony_ci while (remaining) { 23688c2ecf20Sopenharmony_ci U32 const lastBlock = lastFrameChunk & (blockSize >= remaining); 23698c2ecf20Sopenharmony_ci size_t cSize; 23708c2ecf20Sopenharmony_ci 23718c2ecf20Sopenharmony_ci if (dstCapacity < ZSTD_blockHeaderSize + MIN_CBLOCK_SIZE) 23728c2ecf20Sopenharmony_ci return ERROR(dstSize_tooSmall); /* not enough space to store compressed block */ 23738c2ecf20Sopenharmony_ci if (remaining < blockSize) 23748c2ecf20Sopenharmony_ci blockSize = remaining; 23758c2ecf20Sopenharmony_ci 23768c2ecf20Sopenharmony_ci /* preemptive overflow correction */ 23778c2ecf20Sopenharmony_ci if (cctx->lowLimit > (3U << 29)) { 23788c2ecf20Sopenharmony_ci U32 const cycleMask = (1 << ZSTD_cycleLog(cctx->params.cParams.hashLog, cctx->params.cParams.strategy)) - 1; 23798c2ecf20Sopenharmony_ci U32 const curr = (U32)(ip - cctx->base); 23808c2ecf20Sopenharmony_ci U32 const newCurr = (curr & cycleMask) + (1 << cctx->params.cParams.windowLog); 23818c2ecf20Sopenharmony_ci U32 const correction = curr - newCurr; 23828c2ecf20Sopenharmony_ci ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_64 <= 30); 23838c2ecf20Sopenharmony_ci ZSTD_reduceIndex(cctx, correction); 23848c2ecf20Sopenharmony_ci cctx->base += correction; 23858c2ecf20Sopenharmony_ci cctx->dictBase += correction; 23868c2ecf20Sopenharmony_ci cctx->lowLimit -= correction; 23878c2ecf20Sopenharmony_ci cctx->dictLimit -= correction; 23888c2ecf20Sopenharmony_ci if (cctx->nextToUpdate < correction) 23898c2ecf20Sopenharmony_ci cctx->nextToUpdate = 0; 23908c2ecf20Sopenharmony_ci else 23918c2ecf20Sopenharmony_ci cctx->nextToUpdate -= correction; 23928c2ecf20Sopenharmony_ci } 23938c2ecf20Sopenharmony_ci 23948c2ecf20Sopenharmony_ci if ((U32)(ip + blockSize - cctx->base) > cctx->loadedDictEnd + maxDist) { 23958c2ecf20Sopenharmony_ci /* enforce maxDist */ 23968c2ecf20Sopenharmony_ci U32 const newLowLimit = (U32)(ip + blockSize - cctx->base) - maxDist; 23978c2ecf20Sopenharmony_ci if (cctx->lowLimit < newLowLimit) 23988c2ecf20Sopenharmony_ci cctx->lowLimit = newLowLimit; 23998c2ecf20Sopenharmony_ci if (cctx->dictLimit < cctx->lowLimit) 24008c2ecf20Sopenharmony_ci cctx->dictLimit = cctx->lowLimit; 24018c2ecf20Sopenharmony_ci } 24028c2ecf20Sopenharmony_ci 24038c2ecf20Sopenharmony_ci cSize = ZSTD_compressBlock_internal(cctx, op + ZSTD_blockHeaderSize, dstCapacity - ZSTD_blockHeaderSize, ip, blockSize); 24048c2ecf20Sopenharmony_ci if (ZSTD_isError(cSize)) 24058c2ecf20Sopenharmony_ci return cSize; 24068c2ecf20Sopenharmony_ci 24078c2ecf20Sopenharmony_ci if (cSize == 0) { /* block is not compressible */ 24088c2ecf20Sopenharmony_ci U32 const cBlockHeader24 = lastBlock + (((U32)bt_raw) << 1) + (U32)(blockSize << 3); 24098c2ecf20Sopenharmony_ci if (blockSize + ZSTD_blockHeaderSize > dstCapacity) 24108c2ecf20Sopenharmony_ci return ERROR(dstSize_tooSmall); 24118c2ecf20Sopenharmony_ci ZSTD_writeLE32(op, cBlockHeader24); /* no pb, 4th byte will be overwritten */ 24128c2ecf20Sopenharmony_ci memcpy(op + ZSTD_blockHeaderSize, ip, blockSize); 24138c2ecf20Sopenharmony_ci cSize = ZSTD_blockHeaderSize + blockSize; 24148c2ecf20Sopenharmony_ci } else { 24158c2ecf20Sopenharmony_ci U32 const cBlockHeader24 = lastBlock + (((U32)bt_compressed) << 1) + (U32)(cSize << 3); 24168c2ecf20Sopenharmony_ci ZSTD_writeLE24(op, cBlockHeader24); 24178c2ecf20Sopenharmony_ci cSize += ZSTD_blockHeaderSize; 24188c2ecf20Sopenharmony_ci } 24198c2ecf20Sopenharmony_ci 24208c2ecf20Sopenharmony_ci remaining -= blockSize; 24218c2ecf20Sopenharmony_ci dstCapacity -= cSize; 24228c2ecf20Sopenharmony_ci ip += blockSize; 24238c2ecf20Sopenharmony_ci op += cSize; 24248c2ecf20Sopenharmony_ci } 24258c2ecf20Sopenharmony_ci 24268c2ecf20Sopenharmony_ci if (lastFrameChunk && (op > ostart)) 24278c2ecf20Sopenharmony_ci cctx->stage = ZSTDcs_ending; 24288c2ecf20Sopenharmony_ci return op - ostart; 24298c2ecf20Sopenharmony_ci} 24308c2ecf20Sopenharmony_ci 24318c2ecf20Sopenharmony_cistatic size_t ZSTD_writeFrameHeader(void *dst, size_t dstCapacity, ZSTD_parameters params, U64 pledgedSrcSize, U32 dictID) 24328c2ecf20Sopenharmony_ci{ 24338c2ecf20Sopenharmony_ci BYTE *const op = (BYTE *)dst; 24348c2ecf20Sopenharmony_ci U32 const dictIDSizeCode = (dictID > 0) + (dictID >= 256) + (dictID >= 65536); /* 0-3 */ 24358c2ecf20Sopenharmony_ci U32 const checksumFlag = params.fParams.checksumFlag > 0; 24368c2ecf20Sopenharmony_ci U32 const windowSize = 1U << params.cParams.windowLog; 24378c2ecf20Sopenharmony_ci U32 const singleSegment = params.fParams.contentSizeFlag && (windowSize >= pledgedSrcSize); 24388c2ecf20Sopenharmony_ci BYTE const windowLogByte = (BYTE)((params.cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN) << 3); 24398c2ecf20Sopenharmony_ci U32 const fcsCode = 24408c2ecf20Sopenharmony_ci params.fParams.contentSizeFlag ? (pledgedSrcSize >= 256) + (pledgedSrcSize >= 65536 + 256) + (pledgedSrcSize >= 0xFFFFFFFFU) : 0; /* 0-3 */ 24418c2ecf20Sopenharmony_ci BYTE const frameHeaderDecriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag << 2) + (singleSegment << 5) + (fcsCode << 6)); 24428c2ecf20Sopenharmony_ci size_t pos; 24438c2ecf20Sopenharmony_ci 24448c2ecf20Sopenharmony_ci if (dstCapacity < ZSTD_frameHeaderSize_max) 24458c2ecf20Sopenharmony_ci return ERROR(dstSize_tooSmall); 24468c2ecf20Sopenharmony_ci 24478c2ecf20Sopenharmony_ci ZSTD_writeLE32(dst, ZSTD_MAGICNUMBER); 24488c2ecf20Sopenharmony_ci op[4] = frameHeaderDecriptionByte; 24498c2ecf20Sopenharmony_ci pos = 5; 24508c2ecf20Sopenharmony_ci if (!singleSegment) 24518c2ecf20Sopenharmony_ci op[pos++] = windowLogByte; 24528c2ecf20Sopenharmony_ci switch (dictIDSizeCode) { 24538c2ecf20Sopenharmony_ci default: /* impossible */ 24548c2ecf20Sopenharmony_ci case 0: break; 24558c2ecf20Sopenharmony_ci case 1: 24568c2ecf20Sopenharmony_ci op[pos] = (BYTE)(dictID); 24578c2ecf20Sopenharmony_ci pos++; 24588c2ecf20Sopenharmony_ci break; 24598c2ecf20Sopenharmony_ci case 2: 24608c2ecf20Sopenharmony_ci ZSTD_writeLE16(op + pos, (U16)dictID); 24618c2ecf20Sopenharmony_ci pos += 2; 24628c2ecf20Sopenharmony_ci break; 24638c2ecf20Sopenharmony_ci case 3: 24648c2ecf20Sopenharmony_ci ZSTD_writeLE32(op + pos, dictID); 24658c2ecf20Sopenharmony_ci pos += 4; 24668c2ecf20Sopenharmony_ci break; 24678c2ecf20Sopenharmony_ci } 24688c2ecf20Sopenharmony_ci switch (fcsCode) { 24698c2ecf20Sopenharmony_ci default: /* impossible */ 24708c2ecf20Sopenharmony_ci case 0: 24718c2ecf20Sopenharmony_ci if (singleSegment) 24728c2ecf20Sopenharmony_ci op[pos++] = (BYTE)(pledgedSrcSize); 24738c2ecf20Sopenharmony_ci break; 24748c2ecf20Sopenharmony_ci case 1: 24758c2ecf20Sopenharmony_ci ZSTD_writeLE16(op + pos, (U16)(pledgedSrcSize - 256)); 24768c2ecf20Sopenharmony_ci pos += 2; 24778c2ecf20Sopenharmony_ci break; 24788c2ecf20Sopenharmony_ci case 2: 24798c2ecf20Sopenharmony_ci ZSTD_writeLE32(op + pos, (U32)(pledgedSrcSize)); 24808c2ecf20Sopenharmony_ci pos += 4; 24818c2ecf20Sopenharmony_ci break; 24828c2ecf20Sopenharmony_ci case 3: 24838c2ecf20Sopenharmony_ci ZSTD_writeLE64(op + pos, (U64)(pledgedSrcSize)); 24848c2ecf20Sopenharmony_ci pos += 8; 24858c2ecf20Sopenharmony_ci break; 24868c2ecf20Sopenharmony_ci } 24878c2ecf20Sopenharmony_ci return pos; 24888c2ecf20Sopenharmony_ci} 24898c2ecf20Sopenharmony_ci 24908c2ecf20Sopenharmony_cistatic size_t ZSTD_compressContinue_internal(ZSTD_CCtx *cctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize, U32 frame, U32 lastFrameChunk) 24918c2ecf20Sopenharmony_ci{ 24928c2ecf20Sopenharmony_ci const BYTE *const ip = (const BYTE *)src; 24938c2ecf20Sopenharmony_ci size_t fhSize = 0; 24948c2ecf20Sopenharmony_ci 24958c2ecf20Sopenharmony_ci if (cctx->stage == ZSTDcs_created) 24968c2ecf20Sopenharmony_ci return ERROR(stage_wrong); /* missing init (ZSTD_compressBegin) */ 24978c2ecf20Sopenharmony_ci 24988c2ecf20Sopenharmony_ci if (frame && (cctx->stage == ZSTDcs_init)) { 24998c2ecf20Sopenharmony_ci fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, cctx->params, cctx->frameContentSize, cctx->dictID); 25008c2ecf20Sopenharmony_ci if (ZSTD_isError(fhSize)) 25018c2ecf20Sopenharmony_ci return fhSize; 25028c2ecf20Sopenharmony_ci dstCapacity -= fhSize; 25038c2ecf20Sopenharmony_ci dst = (char *)dst + fhSize; 25048c2ecf20Sopenharmony_ci cctx->stage = ZSTDcs_ongoing; 25058c2ecf20Sopenharmony_ci } 25068c2ecf20Sopenharmony_ci 25078c2ecf20Sopenharmony_ci /* Check if blocks follow each other */ 25088c2ecf20Sopenharmony_ci if (src != cctx->nextSrc) { 25098c2ecf20Sopenharmony_ci /* not contiguous */ 25108c2ecf20Sopenharmony_ci ptrdiff_t const delta = cctx->nextSrc - ip; 25118c2ecf20Sopenharmony_ci cctx->lowLimit = cctx->dictLimit; 25128c2ecf20Sopenharmony_ci cctx->dictLimit = (U32)(cctx->nextSrc - cctx->base); 25138c2ecf20Sopenharmony_ci cctx->dictBase = cctx->base; 25148c2ecf20Sopenharmony_ci cctx->base -= delta; 25158c2ecf20Sopenharmony_ci cctx->nextToUpdate = cctx->dictLimit; 25168c2ecf20Sopenharmony_ci if (cctx->dictLimit - cctx->lowLimit < HASH_READ_SIZE) 25178c2ecf20Sopenharmony_ci cctx->lowLimit = cctx->dictLimit; /* too small extDict */ 25188c2ecf20Sopenharmony_ci } 25198c2ecf20Sopenharmony_ci 25208c2ecf20Sopenharmony_ci /* if input and dictionary overlap : reduce dictionary (area presumed modified by input) */ 25218c2ecf20Sopenharmony_ci if ((ip + srcSize > cctx->dictBase + cctx->lowLimit) & (ip < cctx->dictBase + cctx->dictLimit)) { 25228c2ecf20Sopenharmony_ci ptrdiff_t const highInputIdx = (ip + srcSize) - cctx->dictBase; 25238c2ecf20Sopenharmony_ci U32 const lowLimitMax = (highInputIdx > (ptrdiff_t)cctx->dictLimit) ? cctx->dictLimit : (U32)highInputIdx; 25248c2ecf20Sopenharmony_ci cctx->lowLimit = lowLimitMax; 25258c2ecf20Sopenharmony_ci } 25268c2ecf20Sopenharmony_ci 25278c2ecf20Sopenharmony_ci cctx->nextSrc = ip + srcSize; 25288c2ecf20Sopenharmony_ci 25298c2ecf20Sopenharmony_ci if (srcSize) { 25308c2ecf20Sopenharmony_ci size_t const cSize = frame ? ZSTD_compress_generic(cctx, dst, dstCapacity, src, srcSize, lastFrameChunk) 25318c2ecf20Sopenharmony_ci : ZSTD_compressBlock_internal(cctx, dst, dstCapacity, src, srcSize); 25328c2ecf20Sopenharmony_ci if (ZSTD_isError(cSize)) 25338c2ecf20Sopenharmony_ci return cSize; 25348c2ecf20Sopenharmony_ci return cSize + fhSize; 25358c2ecf20Sopenharmony_ci } else 25368c2ecf20Sopenharmony_ci return fhSize; 25378c2ecf20Sopenharmony_ci} 25388c2ecf20Sopenharmony_ci 25398c2ecf20Sopenharmony_cisize_t ZSTD_compressContinue(ZSTD_CCtx *cctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize) 25408c2ecf20Sopenharmony_ci{ 25418c2ecf20Sopenharmony_ci return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 1, 0); 25428c2ecf20Sopenharmony_ci} 25438c2ecf20Sopenharmony_ci 25448c2ecf20Sopenharmony_cisize_t ZSTD_getBlockSizeMax(ZSTD_CCtx *cctx) { return MIN(ZSTD_BLOCKSIZE_ABSOLUTEMAX, 1 << cctx->params.cParams.windowLog); } 25458c2ecf20Sopenharmony_ci 25468c2ecf20Sopenharmony_cisize_t ZSTD_compressBlock(ZSTD_CCtx *cctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize) 25478c2ecf20Sopenharmony_ci{ 25488c2ecf20Sopenharmony_ci size_t const blockSizeMax = ZSTD_getBlockSizeMax(cctx); 25498c2ecf20Sopenharmony_ci if (srcSize > blockSizeMax) 25508c2ecf20Sopenharmony_ci return ERROR(srcSize_wrong); 25518c2ecf20Sopenharmony_ci return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 0, 0); 25528c2ecf20Sopenharmony_ci} 25538c2ecf20Sopenharmony_ci 25548c2ecf20Sopenharmony_ci/*! ZSTD_loadDictionaryContent() : 25558c2ecf20Sopenharmony_ci * @return : 0, or an error code 25568c2ecf20Sopenharmony_ci */ 25578c2ecf20Sopenharmony_cistatic size_t ZSTD_loadDictionaryContent(ZSTD_CCtx *zc, const void *src, size_t srcSize) 25588c2ecf20Sopenharmony_ci{ 25598c2ecf20Sopenharmony_ci const BYTE *const ip = (const BYTE *)src; 25608c2ecf20Sopenharmony_ci const BYTE *const iend = ip + srcSize; 25618c2ecf20Sopenharmony_ci 25628c2ecf20Sopenharmony_ci /* input becomes curr prefix */ 25638c2ecf20Sopenharmony_ci zc->lowLimit = zc->dictLimit; 25648c2ecf20Sopenharmony_ci zc->dictLimit = (U32)(zc->nextSrc - zc->base); 25658c2ecf20Sopenharmony_ci zc->dictBase = zc->base; 25668c2ecf20Sopenharmony_ci zc->base += ip - zc->nextSrc; 25678c2ecf20Sopenharmony_ci zc->nextToUpdate = zc->dictLimit; 25688c2ecf20Sopenharmony_ci zc->loadedDictEnd = zc->forceWindow ? 0 : (U32)(iend - zc->base); 25698c2ecf20Sopenharmony_ci 25708c2ecf20Sopenharmony_ci zc->nextSrc = iend; 25718c2ecf20Sopenharmony_ci if (srcSize <= HASH_READ_SIZE) 25728c2ecf20Sopenharmony_ci return 0; 25738c2ecf20Sopenharmony_ci 25748c2ecf20Sopenharmony_ci switch (zc->params.cParams.strategy) { 25758c2ecf20Sopenharmony_ci case ZSTD_fast: ZSTD_fillHashTable(zc, iend, zc->params.cParams.searchLength); break; 25768c2ecf20Sopenharmony_ci 25778c2ecf20Sopenharmony_ci case ZSTD_dfast: ZSTD_fillDoubleHashTable(zc, iend, zc->params.cParams.searchLength); break; 25788c2ecf20Sopenharmony_ci 25798c2ecf20Sopenharmony_ci case ZSTD_greedy: 25808c2ecf20Sopenharmony_ci case ZSTD_lazy: 25818c2ecf20Sopenharmony_ci case ZSTD_lazy2: 25828c2ecf20Sopenharmony_ci if (srcSize >= HASH_READ_SIZE) 25838c2ecf20Sopenharmony_ci ZSTD_insertAndFindFirstIndex(zc, iend - HASH_READ_SIZE, zc->params.cParams.searchLength); 25848c2ecf20Sopenharmony_ci break; 25858c2ecf20Sopenharmony_ci 25868c2ecf20Sopenharmony_ci case ZSTD_btlazy2: 25878c2ecf20Sopenharmony_ci case ZSTD_btopt: 25888c2ecf20Sopenharmony_ci case ZSTD_btopt2: 25898c2ecf20Sopenharmony_ci if (srcSize >= HASH_READ_SIZE) 25908c2ecf20Sopenharmony_ci ZSTD_updateTree(zc, iend - HASH_READ_SIZE, iend, 1 << zc->params.cParams.searchLog, zc->params.cParams.searchLength); 25918c2ecf20Sopenharmony_ci break; 25928c2ecf20Sopenharmony_ci 25938c2ecf20Sopenharmony_ci default: 25948c2ecf20Sopenharmony_ci return ERROR(GENERIC); /* strategy doesn't exist; impossible */ 25958c2ecf20Sopenharmony_ci } 25968c2ecf20Sopenharmony_ci 25978c2ecf20Sopenharmony_ci zc->nextToUpdate = (U32)(iend - zc->base); 25988c2ecf20Sopenharmony_ci return 0; 25998c2ecf20Sopenharmony_ci} 26008c2ecf20Sopenharmony_ci 26018c2ecf20Sopenharmony_ci/* Dictionaries that assign zero probability to symbols that show up causes problems 26028c2ecf20Sopenharmony_ci when FSE encoding. Refuse dictionaries that assign zero probability to symbols 26038c2ecf20Sopenharmony_ci that we may encounter during compression. 26048c2ecf20Sopenharmony_ci NOTE: This behavior is not standard and could be improved in the future. */ 26058c2ecf20Sopenharmony_cistatic size_t ZSTD_checkDictNCount(short *normalizedCounter, unsigned dictMaxSymbolValue, unsigned maxSymbolValue) 26068c2ecf20Sopenharmony_ci{ 26078c2ecf20Sopenharmony_ci U32 s; 26088c2ecf20Sopenharmony_ci if (dictMaxSymbolValue < maxSymbolValue) 26098c2ecf20Sopenharmony_ci return ERROR(dictionary_corrupted); 26108c2ecf20Sopenharmony_ci for (s = 0; s <= maxSymbolValue; ++s) { 26118c2ecf20Sopenharmony_ci if (normalizedCounter[s] == 0) 26128c2ecf20Sopenharmony_ci return ERROR(dictionary_corrupted); 26138c2ecf20Sopenharmony_ci } 26148c2ecf20Sopenharmony_ci return 0; 26158c2ecf20Sopenharmony_ci} 26168c2ecf20Sopenharmony_ci 26178c2ecf20Sopenharmony_ci/* Dictionary format : 26188c2ecf20Sopenharmony_ci * See : 26198c2ecf20Sopenharmony_ci * https://github.com/facebook/zstd/blob/master/doc/zstd_compression_format.md#dictionary-format 26208c2ecf20Sopenharmony_ci */ 26218c2ecf20Sopenharmony_ci/*! ZSTD_loadZstdDictionary() : 26228c2ecf20Sopenharmony_ci * @return : 0, or an error code 26238c2ecf20Sopenharmony_ci * assumptions : magic number supposed already checked 26248c2ecf20Sopenharmony_ci * dictSize supposed > 8 26258c2ecf20Sopenharmony_ci */ 26268c2ecf20Sopenharmony_cistatic size_t ZSTD_loadZstdDictionary(ZSTD_CCtx *cctx, const void *dict, size_t dictSize) 26278c2ecf20Sopenharmony_ci{ 26288c2ecf20Sopenharmony_ci const BYTE *dictPtr = (const BYTE *)dict; 26298c2ecf20Sopenharmony_ci const BYTE *const dictEnd = dictPtr + dictSize; 26308c2ecf20Sopenharmony_ci short offcodeNCount[MaxOff + 1]; 26318c2ecf20Sopenharmony_ci unsigned offcodeMaxValue = MaxOff; 26328c2ecf20Sopenharmony_ci 26338c2ecf20Sopenharmony_ci dictPtr += 4; /* skip magic number */ 26348c2ecf20Sopenharmony_ci cctx->dictID = cctx->params.fParams.noDictIDFlag ? 0 : ZSTD_readLE32(dictPtr); 26358c2ecf20Sopenharmony_ci dictPtr += 4; 26368c2ecf20Sopenharmony_ci 26378c2ecf20Sopenharmony_ci { 26388c2ecf20Sopenharmony_ci size_t const hufHeaderSize = HUF_readCTable_wksp(cctx->hufTable, 255, dictPtr, dictEnd - dictPtr, cctx->tmpCounters, sizeof(cctx->tmpCounters)); 26398c2ecf20Sopenharmony_ci if (HUF_isError(hufHeaderSize)) 26408c2ecf20Sopenharmony_ci return ERROR(dictionary_corrupted); 26418c2ecf20Sopenharmony_ci dictPtr += hufHeaderSize; 26428c2ecf20Sopenharmony_ci } 26438c2ecf20Sopenharmony_ci 26448c2ecf20Sopenharmony_ci { 26458c2ecf20Sopenharmony_ci unsigned offcodeLog; 26468c2ecf20Sopenharmony_ci size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd - dictPtr); 26478c2ecf20Sopenharmony_ci if (FSE_isError(offcodeHeaderSize)) 26488c2ecf20Sopenharmony_ci return ERROR(dictionary_corrupted); 26498c2ecf20Sopenharmony_ci if (offcodeLog > OffFSELog) 26508c2ecf20Sopenharmony_ci return ERROR(dictionary_corrupted); 26518c2ecf20Sopenharmony_ci /* Defer checking offcodeMaxValue because we need to know the size of the dictionary content */ 26528c2ecf20Sopenharmony_ci CHECK_E(FSE_buildCTable_wksp(cctx->offcodeCTable, offcodeNCount, offcodeMaxValue, offcodeLog, cctx->tmpCounters, sizeof(cctx->tmpCounters)), 26538c2ecf20Sopenharmony_ci dictionary_corrupted); 26548c2ecf20Sopenharmony_ci dictPtr += offcodeHeaderSize; 26558c2ecf20Sopenharmony_ci } 26568c2ecf20Sopenharmony_ci 26578c2ecf20Sopenharmony_ci { 26588c2ecf20Sopenharmony_ci short matchlengthNCount[MaxML + 1]; 26598c2ecf20Sopenharmony_ci unsigned matchlengthMaxValue = MaxML, matchlengthLog; 26608c2ecf20Sopenharmony_ci size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd - dictPtr); 26618c2ecf20Sopenharmony_ci if (FSE_isError(matchlengthHeaderSize)) 26628c2ecf20Sopenharmony_ci return ERROR(dictionary_corrupted); 26638c2ecf20Sopenharmony_ci if (matchlengthLog > MLFSELog) 26648c2ecf20Sopenharmony_ci return ERROR(dictionary_corrupted); 26658c2ecf20Sopenharmony_ci /* Every match length code must have non-zero probability */ 26668c2ecf20Sopenharmony_ci CHECK_F(ZSTD_checkDictNCount(matchlengthNCount, matchlengthMaxValue, MaxML)); 26678c2ecf20Sopenharmony_ci CHECK_E( 26688c2ecf20Sopenharmony_ci FSE_buildCTable_wksp(cctx->matchlengthCTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog, cctx->tmpCounters, sizeof(cctx->tmpCounters)), 26698c2ecf20Sopenharmony_ci dictionary_corrupted); 26708c2ecf20Sopenharmony_ci dictPtr += matchlengthHeaderSize; 26718c2ecf20Sopenharmony_ci } 26728c2ecf20Sopenharmony_ci 26738c2ecf20Sopenharmony_ci { 26748c2ecf20Sopenharmony_ci short litlengthNCount[MaxLL + 1]; 26758c2ecf20Sopenharmony_ci unsigned litlengthMaxValue = MaxLL, litlengthLog; 26768c2ecf20Sopenharmony_ci size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd - dictPtr); 26778c2ecf20Sopenharmony_ci if (FSE_isError(litlengthHeaderSize)) 26788c2ecf20Sopenharmony_ci return ERROR(dictionary_corrupted); 26798c2ecf20Sopenharmony_ci if (litlengthLog > LLFSELog) 26808c2ecf20Sopenharmony_ci return ERROR(dictionary_corrupted); 26818c2ecf20Sopenharmony_ci /* Every literal length code must have non-zero probability */ 26828c2ecf20Sopenharmony_ci CHECK_F(ZSTD_checkDictNCount(litlengthNCount, litlengthMaxValue, MaxLL)); 26838c2ecf20Sopenharmony_ci CHECK_E(FSE_buildCTable_wksp(cctx->litlengthCTable, litlengthNCount, litlengthMaxValue, litlengthLog, cctx->tmpCounters, sizeof(cctx->tmpCounters)), 26848c2ecf20Sopenharmony_ci dictionary_corrupted); 26858c2ecf20Sopenharmony_ci dictPtr += litlengthHeaderSize; 26868c2ecf20Sopenharmony_ci } 26878c2ecf20Sopenharmony_ci 26888c2ecf20Sopenharmony_ci if (dictPtr + 12 > dictEnd) 26898c2ecf20Sopenharmony_ci return ERROR(dictionary_corrupted); 26908c2ecf20Sopenharmony_ci cctx->rep[0] = ZSTD_readLE32(dictPtr + 0); 26918c2ecf20Sopenharmony_ci cctx->rep[1] = ZSTD_readLE32(dictPtr + 4); 26928c2ecf20Sopenharmony_ci cctx->rep[2] = ZSTD_readLE32(dictPtr + 8); 26938c2ecf20Sopenharmony_ci dictPtr += 12; 26948c2ecf20Sopenharmony_ci 26958c2ecf20Sopenharmony_ci { 26968c2ecf20Sopenharmony_ci size_t const dictContentSize = (size_t)(dictEnd - dictPtr); 26978c2ecf20Sopenharmony_ci U32 offcodeMax = MaxOff; 26988c2ecf20Sopenharmony_ci if (dictContentSize <= ((U32)-1) - 128 KB) { 26998c2ecf20Sopenharmony_ci U32 const maxOffset = (U32)dictContentSize + 128 KB; /* The maximum offset that must be supported */ 27008c2ecf20Sopenharmony_ci offcodeMax = ZSTD_highbit32(maxOffset); /* Calculate minimum offset code required to represent maxOffset */ 27018c2ecf20Sopenharmony_ci } 27028c2ecf20Sopenharmony_ci /* All offset values <= dictContentSize + 128 KB must be representable */ 27038c2ecf20Sopenharmony_ci CHECK_F(ZSTD_checkDictNCount(offcodeNCount, offcodeMaxValue, MIN(offcodeMax, MaxOff))); 27048c2ecf20Sopenharmony_ci /* All repCodes must be <= dictContentSize and != 0*/ 27058c2ecf20Sopenharmony_ci { 27068c2ecf20Sopenharmony_ci U32 u; 27078c2ecf20Sopenharmony_ci for (u = 0; u < 3; u++) { 27088c2ecf20Sopenharmony_ci if (cctx->rep[u] == 0) 27098c2ecf20Sopenharmony_ci return ERROR(dictionary_corrupted); 27108c2ecf20Sopenharmony_ci if (cctx->rep[u] > dictContentSize) 27118c2ecf20Sopenharmony_ci return ERROR(dictionary_corrupted); 27128c2ecf20Sopenharmony_ci } 27138c2ecf20Sopenharmony_ci } 27148c2ecf20Sopenharmony_ci 27158c2ecf20Sopenharmony_ci cctx->flagStaticTables = 1; 27168c2ecf20Sopenharmony_ci cctx->flagStaticHufTable = HUF_repeat_valid; 27178c2ecf20Sopenharmony_ci return ZSTD_loadDictionaryContent(cctx, dictPtr, dictContentSize); 27188c2ecf20Sopenharmony_ci } 27198c2ecf20Sopenharmony_ci} 27208c2ecf20Sopenharmony_ci 27218c2ecf20Sopenharmony_ci/** ZSTD_compress_insertDictionary() : 27228c2ecf20Sopenharmony_ci* @return : 0, or an error code */ 27238c2ecf20Sopenharmony_cistatic size_t ZSTD_compress_insertDictionary(ZSTD_CCtx *cctx, const void *dict, size_t dictSize) 27248c2ecf20Sopenharmony_ci{ 27258c2ecf20Sopenharmony_ci if ((dict == NULL) || (dictSize <= 8)) 27268c2ecf20Sopenharmony_ci return 0; 27278c2ecf20Sopenharmony_ci 27288c2ecf20Sopenharmony_ci /* dict as pure content */ 27298c2ecf20Sopenharmony_ci if ((ZSTD_readLE32(dict) != ZSTD_DICT_MAGIC) || (cctx->forceRawDict)) 27308c2ecf20Sopenharmony_ci return ZSTD_loadDictionaryContent(cctx, dict, dictSize); 27318c2ecf20Sopenharmony_ci 27328c2ecf20Sopenharmony_ci /* dict as zstd dictionary */ 27338c2ecf20Sopenharmony_ci return ZSTD_loadZstdDictionary(cctx, dict, dictSize); 27348c2ecf20Sopenharmony_ci} 27358c2ecf20Sopenharmony_ci 27368c2ecf20Sopenharmony_ci/*! ZSTD_compressBegin_internal() : 27378c2ecf20Sopenharmony_ci* @return : 0, or an error code */ 27388c2ecf20Sopenharmony_cistatic size_t ZSTD_compressBegin_internal(ZSTD_CCtx *cctx, const void *dict, size_t dictSize, ZSTD_parameters params, U64 pledgedSrcSize) 27398c2ecf20Sopenharmony_ci{ 27408c2ecf20Sopenharmony_ci ZSTD_compResetPolicy_e const crp = dictSize ? ZSTDcrp_fullReset : ZSTDcrp_continue; 27418c2ecf20Sopenharmony_ci CHECK_F(ZSTD_resetCCtx_advanced(cctx, params, pledgedSrcSize, crp)); 27428c2ecf20Sopenharmony_ci return ZSTD_compress_insertDictionary(cctx, dict, dictSize); 27438c2ecf20Sopenharmony_ci} 27448c2ecf20Sopenharmony_ci 27458c2ecf20Sopenharmony_ci/*! ZSTD_compressBegin_advanced() : 27468c2ecf20Sopenharmony_ci* @return : 0, or an error code */ 27478c2ecf20Sopenharmony_cisize_t ZSTD_compressBegin_advanced(ZSTD_CCtx *cctx, const void *dict, size_t dictSize, ZSTD_parameters params, unsigned long long pledgedSrcSize) 27488c2ecf20Sopenharmony_ci{ 27498c2ecf20Sopenharmony_ci /* compression parameters verification and optimization */ 27508c2ecf20Sopenharmony_ci CHECK_F(ZSTD_checkCParams(params.cParams)); 27518c2ecf20Sopenharmony_ci return ZSTD_compressBegin_internal(cctx, dict, dictSize, params, pledgedSrcSize); 27528c2ecf20Sopenharmony_ci} 27538c2ecf20Sopenharmony_ci 27548c2ecf20Sopenharmony_cisize_t ZSTD_compressBegin_usingDict(ZSTD_CCtx *cctx, const void *dict, size_t dictSize, int compressionLevel) 27558c2ecf20Sopenharmony_ci{ 27568c2ecf20Sopenharmony_ci ZSTD_parameters const params = ZSTD_getParams(compressionLevel, 0, dictSize); 27578c2ecf20Sopenharmony_ci return ZSTD_compressBegin_internal(cctx, dict, dictSize, params, 0); 27588c2ecf20Sopenharmony_ci} 27598c2ecf20Sopenharmony_ci 27608c2ecf20Sopenharmony_cisize_t ZSTD_compressBegin(ZSTD_CCtx *cctx, int compressionLevel) { return ZSTD_compressBegin_usingDict(cctx, NULL, 0, compressionLevel); } 27618c2ecf20Sopenharmony_ci 27628c2ecf20Sopenharmony_ci/*! ZSTD_writeEpilogue() : 27638c2ecf20Sopenharmony_ci* Ends a frame. 27648c2ecf20Sopenharmony_ci* @return : nb of bytes written into dst (or an error code) */ 27658c2ecf20Sopenharmony_cistatic size_t ZSTD_writeEpilogue(ZSTD_CCtx *cctx, void *dst, size_t dstCapacity) 27668c2ecf20Sopenharmony_ci{ 27678c2ecf20Sopenharmony_ci BYTE *const ostart = (BYTE *)dst; 27688c2ecf20Sopenharmony_ci BYTE *op = ostart; 27698c2ecf20Sopenharmony_ci size_t fhSize = 0; 27708c2ecf20Sopenharmony_ci 27718c2ecf20Sopenharmony_ci if (cctx->stage == ZSTDcs_created) 27728c2ecf20Sopenharmony_ci return ERROR(stage_wrong); /* init missing */ 27738c2ecf20Sopenharmony_ci 27748c2ecf20Sopenharmony_ci /* special case : empty frame */ 27758c2ecf20Sopenharmony_ci if (cctx->stage == ZSTDcs_init) { 27768c2ecf20Sopenharmony_ci fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, cctx->params, 0, 0); 27778c2ecf20Sopenharmony_ci if (ZSTD_isError(fhSize)) 27788c2ecf20Sopenharmony_ci return fhSize; 27798c2ecf20Sopenharmony_ci dstCapacity -= fhSize; 27808c2ecf20Sopenharmony_ci op += fhSize; 27818c2ecf20Sopenharmony_ci cctx->stage = ZSTDcs_ongoing; 27828c2ecf20Sopenharmony_ci } 27838c2ecf20Sopenharmony_ci 27848c2ecf20Sopenharmony_ci if (cctx->stage != ZSTDcs_ending) { 27858c2ecf20Sopenharmony_ci /* write one last empty block, make it the "last" block */ 27868c2ecf20Sopenharmony_ci U32 const cBlockHeader24 = 1 /* last block */ + (((U32)bt_raw) << 1) + 0; 27878c2ecf20Sopenharmony_ci if (dstCapacity < 4) 27888c2ecf20Sopenharmony_ci return ERROR(dstSize_tooSmall); 27898c2ecf20Sopenharmony_ci ZSTD_writeLE32(op, cBlockHeader24); 27908c2ecf20Sopenharmony_ci op += ZSTD_blockHeaderSize; 27918c2ecf20Sopenharmony_ci dstCapacity -= ZSTD_blockHeaderSize; 27928c2ecf20Sopenharmony_ci } 27938c2ecf20Sopenharmony_ci 27948c2ecf20Sopenharmony_ci if (cctx->params.fParams.checksumFlag) { 27958c2ecf20Sopenharmony_ci U32 const checksum = (U32)xxh64_digest(&cctx->xxhState); 27968c2ecf20Sopenharmony_ci if (dstCapacity < 4) 27978c2ecf20Sopenharmony_ci return ERROR(dstSize_tooSmall); 27988c2ecf20Sopenharmony_ci ZSTD_writeLE32(op, checksum); 27998c2ecf20Sopenharmony_ci op += 4; 28008c2ecf20Sopenharmony_ci } 28018c2ecf20Sopenharmony_ci 28028c2ecf20Sopenharmony_ci cctx->stage = ZSTDcs_created; /* return to "created but no init" status */ 28038c2ecf20Sopenharmony_ci return op - ostart; 28048c2ecf20Sopenharmony_ci} 28058c2ecf20Sopenharmony_ci 28068c2ecf20Sopenharmony_cisize_t ZSTD_compressEnd(ZSTD_CCtx *cctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize) 28078c2ecf20Sopenharmony_ci{ 28088c2ecf20Sopenharmony_ci size_t endResult; 28098c2ecf20Sopenharmony_ci size_t const cSize = ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 1, 1); 28108c2ecf20Sopenharmony_ci if (ZSTD_isError(cSize)) 28118c2ecf20Sopenharmony_ci return cSize; 28128c2ecf20Sopenharmony_ci endResult = ZSTD_writeEpilogue(cctx, (char *)dst + cSize, dstCapacity - cSize); 28138c2ecf20Sopenharmony_ci if (ZSTD_isError(endResult)) 28148c2ecf20Sopenharmony_ci return endResult; 28158c2ecf20Sopenharmony_ci return cSize + endResult; 28168c2ecf20Sopenharmony_ci} 28178c2ecf20Sopenharmony_ci 28188c2ecf20Sopenharmony_cistatic size_t ZSTD_compress_internal(ZSTD_CCtx *cctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize, const void *dict, size_t dictSize, 28198c2ecf20Sopenharmony_ci ZSTD_parameters params) 28208c2ecf20Sopenharmony_ci{ 28218c2ecf20Sopenharmony_ci CHECK_F(ZSTD_compressBegin_internal(cctx, dict, dictSize, params, srcSize)); 28228c2ecf20Sopenharmony_ci return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize); 28238c2ecf20Sopenharmony_ci} 28248c2ecf20Sopenharmony_ci 28258c2ecf20Sopenharmony_cisize_t ZSTD_compress_usingDict(ZSTD_CCtx *ctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize, const void *dict, size_t dictSize, 28268c2ecf20Sopenharmony_ci ZSTD_parameters params) 28278c2ecf20Sopenharmony_ci{ 28288c2ecf20Sopenharmony_ci return ZSTD_compress_internal(ctx, dst, dstCapacity, src, srcSize, dict, dictSize, params); 28298c2ecf20Sopenharmony_ci} 28308c2ecf20Sopenharmony_ci 28318c2ecf20Sopenharmony_cisize_t ZSTD_compressCCtx(ZSTD_CCtx *ctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize, ZSTD_parameters params) 28328c2ecf20Sopenharmony_ci{ 28338c2ecf20Sopenharmony_ci return ZSTD_compress_internal(ctx, dst, dstCapacity, src, srcSize, NULL, 0, params); 28348c2ecf20Sopenharmony_ci} 28358c2ecf20Sopenharmony_ci 28368c2ecf20Sopenharmony_ci/* ===== Dictionary API ===== */ 28378c2ecf20Sopenharmony_ci 28388c2ecf20Sopenharmony_cistruct ZSTD_CDict_s { 28398c2ecf20Sopenharmony_ci void *dictBuffer; 28408c2ecf20Sopenharmony_ci const void *dictContent; 28418c2ecf20Sopenharmony_ci size_t dictContentSize; 28428c2ecf20Sopenharmony_ci ZSTD_CCtx *refContext; 28438c2ecf20Sopenharmony_ci}; /* typedef'd tp ZSTD_CDict within "zstd.h" */ 28448c2ecf20Sopenharmony_ci 28458c2ecf20Sopenharmony_cisize_t ZSTD_CDictWorkspaceBound(ZSTD_compressionParameters cParams) { return ZSTD_CCtxWorkspaceBound(cParams) + ZSTD_ALIGN(sizeof(ZSTD_CDict)); } 28468c2ecf20Sopenharmony_ci 28478c2ecf20Sopenharmony_cistatic ZSTD_CDict *ZSTD_createCDict_advanced(const void *dictBuffer, size_t dictSize, unsigned byReference, ZSTD_parameters params, ZSTD_customMem customMem) 28488c2ecf20Sopenharmony_ci{ 28498c2ecf20Sopenharmony_ci if (!customMem.customAlloc || !customMem.customFree) 28508c2ecf20Sopenharmony_ci return NULL; 28518c2ecf20Sopenharmony_ci 28528c2ecf20Sopenharmony_ci { 28538c2ecf20Sopenharmony_ci ZSTD_CDict *const cdict = (ZSTD_CDict *)ZSTD_malloc(sizeof(ZSTD_CDict), customMem); 28548c2ecf20Sopenharmony_ci ZSTD_CCtx *const cctx = ZSTD_createCCtx_advanced(customMem); 28558c2ecf20Sopenharmony_ci 28568c2ecf20Sopenharmony_ci if (!cdict || !cctx) { 28578c2ecf20Sopenharmony_ci ZSTD_free(cdict, customMem); 28588c2ecf20Sopenharmony_ci ZSTD_freeCCtx(cctx); 28598c2ecf20Sopenharmony_ci return NULL; 28608c2ecf20Sopenharmony_ci } 28618c2ecf20Sopenharmony_ci 28628c2ecf20Sopenharmony_ci if ((byReference) || (!dictBuffer) || (!dictSize)) { 28638c2ecf20Sopenharmony_ci cdict->dictBuffer = NULL; 28648c2ecf20Sopenharmony_ci cdict->dictContent = dictBuffer; 28658c2ecf20Sopenharmony_ci } else { 28668c2ecf20Sopenharmony_ci void *const internalBuffer = ZSTD_malloc(dictSize, customMem); 28678c2ecf20Sopenharmony_ci if (!internalBuffer) { 28688c2ecf20Sopenharmony_ci ZSTD_free(cctx, customMem); 28698c2ecf20Sopenharmony_ci ZSTD_free(cdict, customMem); 28708c2ecf20Sopenharmony_ci return NULL; 28718c2ecf20Sopenharmony_ci } 28728c2ecf20Sopenharmony_ci memcpy(internalBuffer, dictBuffer, dictSize); 28738c2ecf20Sopenharmony_ci cdict->dictBuffer = internalBuffer; 28748c2ecf20Sopenharmony_ci cdict->dictContent = internalBuffer; 28758c2ecf20Sopenharmony_ci } 28768c2ecf20Sopenharmony_ci 28778c2ecf20Sopenharmony_ci { 28788c2ecf20Sopenharmony_ci size_t const errorCode = ZSTD_compressBegin_advanced(cctx, cdict->dictContent, dictSize, params, 0); 28798c2ecf20Sopenharmony_ci if (ZSTD_isError(errorCode)) { 28808c2ecf20Sopenharmony_ci ZSTD_free(cdict->dictBuffer, customMem); 28818c2ecf20Sopenharmony_ci ZSTD_free(cdict, customMem); 28828c2ecf20Sopenharmony_ci ZSTD_freeCCtx(cctx); 28838c2ecf20Sopenharmony_ci return NULL; 28848c2ecf20Sopenharmony_ci } 28858c2ecf20Sopenharmony_ci } 28868c2ecf20Sopenharmony_ci 28878c2ecf20Sopenharmony_ci cdict->refContext = cctx; 28888c2ecf20Sopenharmony_ci cdict->dictContentSize = dictSize; 28898c2ecf20Sopenharmony_ci return cdict; 28908c2ecf20Sopenharmony_ci } 28918c2ecf20Sopenharmony_ci} 28928c2ecf20Sopenharmony_ci 28938c2ecf20Sopenharmony_ciZSTD_CDict *ZSTD_initCDict(const void *dict, size_t dictSize, ZSTD_parameters params, void *workspace, size_t workspaceSize) 28948c2ecf20Sopenharmony_ci{ 28958c2ecf20Sopenharmony_ci ZSTD_customMem const stackMem = ZSTD_initStack(workspace, workspaceSize); 28968c2ecf20Sopenharmony_ci return ZSTD_createCDict_advanced(dict, dictSize, 1, params, stackMem); 28978c2ecf20Sopenharmony_ci} 28988c2ecf20Sopenharmony_ci 28998c2ecf20Sopenharmony_cisize_t ZSTD_freeCDict(ZSTD_CDict *cdict) 29008c2ecf20Sopenharmony_ci{ 29018c2ecf20Sopenharmony_ci if (cdict == NULL) 29028c2ecf20Sopenharmony_ci return 0; /* support free on NULL */ 29038c2ecf20Sopenharmony_ci { 29048c2ecf20Sopenharmony_ci ZSTD_customMem const cMem = cdict->refContext->customMem; 29058c2ecf20Sopenharmony_ci ZSTD_freeCCtx(cdict->refContext); 29068c2ecf20Sopenharmony_ci ZSTD_free(cdict->dictBuffer, cMem); 29078c2ecf20Sopenharmony_ci ZSTD_free(cdict, cMem); 29088c2ecf20Sopenharmony_ci return 0; 29098c2ecf20Sopenharmony_ci } 29108c2ecf20Sopenharmony_ci} 29118c2ecf20Sopenharmony_ci 29128c2ecf20Sopenharmony_cistatic ZSTD_parameters ZSTD_getParamsFromCDict(const ZSTD_CDict *cdict) { return ZSTD_getParamsFromCCtx(cdict->refContext); } 29138c2ecf20Sopenharmony_ci 29148c2ecf20Sopenharmony_cisize_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx *cctx, const ZSTD_CDict *cdict, unsigned long long pledgedSrcSize) 29158c2ecf20Sopenharmony_ci{ 29168c2ecf20Sopenharmony_ci if (cdict->dictContentSize) 29178c2ecf20Sopenharmony_ci CHECK_F(ZSTD_copyCCtx(cctx, cdict->refContext, pledgedSrcSize)) 29188c2ecf20Sopenharmony_ci else { 29198c2ecf20Sopenharmony_ci ZSTD_parameters params = cdict->refContext->params; 29208c2ecf20Sopenharmony_ci params.fParams.contentSizeFlag = (pledgedSrcSize > 0); 29218c2ecf20Sopenharmony_ci CHECK_F(ZSTD_compressBegin_advanced(cctx, NULL, 0, params, pledgedSrcSize)); 29228c2ecf20Sopenharmony_ci } 29238c2ecf20Sopenharmony_ci return 0; 29248c2ecf20Sopenharmony_ci} 29258c2ecf20Sopenharmony_ci 29268c2ecf20Sopenharmony_ci/*! ZSTD_compress_usingCDict() : 29278c2ecf20Sopenharmony_ci* Compression using a digested Dictionary. 29288c2ecf20Sopenharmony_ci* Faster startup than ZSTD_compress_usingDict(), recommended when same dictionary is used multiple times. 29298c2ecf20Sopenharmony_ci* Note that compression level is decided during dictionary creation */ 29308c2ecf20Sopenharmony_cisize_t ZSTD_compress_usingCDict(ZSTD_CCtx *cctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize, const ZSTD_CDict *cdict) 29318c2ecf20Sopenharmony_ci{ 29328c2ecf20Sopenharmony_ci CHECK_F(ZSTD_compressBegin_usingCDict(cctx, cdict, srcSize)); 29338c2ecf20Sopenharmony_ci 29348c2ecf20Sopenharmony_ci if (cdict->refContext->params.fParams.contentSizeFlag == 1) { 29358c2ecf20Sopenharmony_ci cctx->params.fParams.contentSizeFlag = 1; 29368c2ecf20Sopenharmony_ci cctx->frameContentSize = srcSize; 29378c2ecf20Sopenharmony_ci } else { 29388c2ecf20Sopenharmony_ci cctx->params.fParams.contentSizeFlag = 0; 29398c2ecf20Sopenharmony_ci } 29408c2ecf20Sopenharmony_ci 29418c2ecf20Sopenharmony_ci return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize); 29428c2ecf20Sopenharmony_ci} 29438c2ecf20Sopenharmony_ci 29448c2ecf20Sopenharmony_ci/* ****************************************************************** 29458c2ecf20Sopenharmony_ci* Streaming 29468c2ecf20Sopenharmony_ci********************************************************************/ 29478c2ecf20Sopenharmony_ci 29488c2ecf20Sopenharmony_citypedef enum { zcss_init, zcss_load, zcss_flush, zcss_final } ZSTD_cStreamStage; 29498c2ecf20Sopenharmony_ci 29508c2ecf20Sopenharmony_cistruct ZSTD_CStream_s { 29518c2ecf20Sopenharmony_ci ZSTD_CCtx *cctx; 29528c2ecf20Sopenharmony_ci ZSTD_CDict *cdictLocal; 29538c2ecf20Sopenharmony_ci const ZSTD_CDict *cdict; 29548c2ecf20Sopenharmony_ci char *inBuff; 29558c2ecf20Sopenharmony_ci size_t inBuffSize; 29568c2ecf20Sopenharmony_ci size_t inToCompress; 29578c2ecf20Sopenharmony_ci size_t inBuffPos; 29588c2ecf20Sopenharmony_ci size_t inBuffTarget; 29598c2ecf20Sopenharmony_ci size_t blockSize; 29608c2ecf20Sopenharmony_ci char *outBuff; 29618c2ecf20Sopenharmony_ci size_t outBuffSize; 29628c2ecf20Sopenharmony_ci size_t outBuffContentSize; 29638c2ecf20Sopenharmony_ci size_t outBuffFlushedSize; 29648c2ecf20Sopenharmony_ci ZSTD_cStreamStage stage; 29658c2ecf20Sopenharmony_ci U32 checksum; 29668c2ecf20Sopenharmony_ci U32 frameEnded; 29678c2ecf20Sopenharmony_ci U64 pledgedSrcSize; 29688c2ecf20Sopenharmony_ci U64 inputProcessed; 29698c2ecf20Sopenharmony_ci ZSTD_parameters params; 29708c2ecf20Sopenharmony_ci ZSTD_customMem customMem; 29718c2ecf20Sopenharmony_ci}; /* typedef'd to ZSTD_CStream within "zstd.h" */ 29728c2ecf20Sopenharmony_ci 29738c2ecf20Sopenharmony_cisize_t ZSTD_CStreamWorkspaceBound(ZSTD_compressionParameters cParams) 29748c2ecf20Sopenharmony_ci{ 29758c2ecf20Sopenharmony_ci size_t const inBuffSize = (size_t)1 << cParams.windowLog; 29768c2ecf20Sopenharmony_ci size_t const blockSize = MIN(ZSTD_BLOCKSIZE_ABSOLUTEMAX, inBuffSize); 29778c2ecf20Sopenharmony_ci size_t const outBuffSize = ZSTD_compressBound(blockSize) + 1; 29788c2ecf20Sopenharmony_ci 29798c2ecf20Sopenharmony_ci return ZSTD_CCtxWorkspaceBound(cParams) + ZSTD_ALIGN(sizeof(ZSTD_CStream)) + ZSTD_ALIGN(inBuffSize) + ZSTD_ALIGN(outBuffSize); 29808c2ecf20Sopenharmony_ci} 29818c2ecf20Sopenharmony_ci 29828c2ecf20Sopenharmony_ciZSTD_CStream *ZSTD_createCStream_advanced(ZSTD_customMem customMem) 29838c2ecf20Sopenharmony_ci{ 29848c2ecf20Sopenharmony_ci ZSTD_CStream *zcs; 29858c2ecf20Sopenharmony_ci 29868c2ecf20Sopenharmony_ci if (!customMem.customAlloc || !customMem.customFree) 29878c2ecf20Sopenharmony_ci return NULL; 29888c2ecf20Sopenharmony_ci 29898c2ecf20Sopenharmony_ci zcs = (ZSTD_CStream *)ZSTD_malloc(sizeof(ZSTD_CStream), customMem); 29908c2ecf20Sopenharmony_ci if (zcs == NULL) 29918c2ecf20Sopenharmony_ci return NULL; 29928c2ecf20Sopenharmony_ci memset(zcs, 0, sizeof(ZSTD_CStream)); 29938c2ecf20Sopenharmony_ci memcpy(&zcs->customMem, &customMem, sizeof(ZSTD_customMem)); 29948c2ecf20Sopenharmony_ci zcs->cctx = ZSTD_createCCtx_advanced(customMem); 29958c2ecf20Sopenharmony_ci if (zcs->cctx == NULL) { 29968c2ecf20Sopenharmony_ci ZSTD_freeCStream(zcs); 29978c2ecf20Sopenharmony_ci return NULL; 29988c2ecf20Sopenharmony_ci } 29998c2ecf20Sopenharmony_ci return zcs; 30008c2ecf20Sopenharmony_ci} 30018c2ecf20Sopenharmony_ci 30028c2ecf20Sopenharmony_cisize_t ZSTD_freeCStream(ZSTD_CStream *zcs) 30038c2ecf20Sopenharmony_ci{ 30048c2ecf20Sopenharmony_ci if (zcs == NULL) 30058c2ecf20Sopenharmony_ci return 0; /* support free on NULL */ 30068c2ecf20Sopenharmony_ci { 30078c2ecf20Sopenharmony_ci ZSTD_customMem const cMem = zcs->customMem; 30088c2ecf20Sopenharmony_ci ZSTD_freeCCtx(zcs->cctx); 30098c2ecf20Sopenharmony_ci zcs->cctx = NULL; 30108c2ecf20Sopenharmony_ci ZSTD_freeCDict(zcs->cdictLocal); 30118c2ecf20Sopenharmony_ci zcs->cdictLocal = NULL; 30128c2ecf20Sopenharmony_ci ZSTD_free(zcs->inBuff, cMem); 30138c2ecf20Sopenharmony_ci zcs->inBuff = NULL; 30148c2ecf20Sopenharmony_ci ZSTD_free(zcs->outBuff, cMem); 30158c2ecf20Sopenharmony_ci zcs->outBuff = NULL; 30168c2ecf20Sopenharmony_ci ZSTD_free(zcs, cMem); 30178c2ecf20Sopenharmony_ci return 0; 30188c2ecf20Sopenharmony_ci } 30198c2ecf20Sopenharmony_ci} 30208c2ecf20Sopenharmony_ci 30218c2ecf20Sopenharmony_ci/*====== Initialization ======*/ 30228c2ecf20Sopenharmony_ci 30238c2ecf20Sopenharmony_cisize_t ZSTD_CStreamInSize(void) { return ZSTD_BLOCKSIZE_ABSOLUTEMAX; } 30248c2ecf20Sopenharmony_cisize_t ZSTD_CStreamOutSize(void) { return ZSTD_compressBound(ZSTD_BLOCKSIZE_ABSOLUTEMAX) + ZSTD_blockHeaderSize + 4 /* 32-bits hash */; } 30258c2ecf20Sopenharmony_ci 30268c2ecf20Sopenharmony_cistatic size_t ZSTD_resetCStream_internal(ZSTD_CStream *zcs, unsigned long long pledgedSrcSize) 30278c2ecf20Sopenharmony_ci{ 30288c2ecf20Sopenharmony_ci if (zcs->inBuffSize == 0) 30298c2ecf20Sopenharmony_ci return ERROR(stage_wrong); /* zcs has not been init at least once => can't reset */ 30308c2ecf20Sopenharmony_ci 30318c2ecf20Sopenharmony_ci if (zcs->cdict) 30328c2ecf20Sopenharmony_ci CHECK_F(ZSTD_compressBegin_usingCDict(zcs->cctx, zcs->cdict, pledgedSrcSize)) 30338c2ecf20Sopenharmony_ci else 30348c2ecf20Sopenharmony_ci CHECK_F(ZSTD_compressBegin_advanced(zcs->cctx, NULL, 0, zcs->params, pledgedSrcSize)); 30358c2ecf20Sopenharmony_ci 30368c2ecf20Sopenharmony_ci zcs->inToCompress = 0; 30378c2ecf20Sopenharmony_ci zcs->inBuffPos = 0; 30388c2ecf20Sopenharmony_ci zcs->inBuffTarget = zcs->blockSize; 30398c2ecf20Sopenharmony_ci zcs->outBuffContentSize = zcs->outBuffFlushedSize = 0; 30408c2ecf20Sopenharmony_ci zcs->stage = zcss_load; 30418c2ecf20Sopenharmony_ci zcs->frameEnded = 0; 30428c2ecf20Sopenharmony_ci zcs->pledgedSrcSize = pledgedSrcSize; 30438c2ecf20Sopenharmony_ci zcs->inputProcessed = 0; 30448c2ecf20Sopenharmony_ci return 0; /* ready to go */ 30458c2ecf20Sopenharmony_ci} 30468c2ecf20Sopenharmony_ci 30478c2ecf20Sopenharmony_cisize_t ZSTD_resetCStream(ZSTD_CStream *zcs, unsigned long long pledgedSrcSize) 30488c2ecf20Sopenharmony_ci{ 30498c2ecf20Sopenharmony_ci 30508c2ecf20Sopenharmony_ci zcs->params.fParams.contentSizeFlag = (pledgedSrcSize > 0); 30518c2ecf20Sopenharmony_ci 30528c2ecf20Sopenharmony_ci return ZSTD_resetCStream_internal(zcs, pledgedSrcSize); 30538c2ecf20Sopenharmony_ci} 30548c2ecf20Sopenharmony_ci 30558c2ecf20Sopenharmony_cistatic size_t ZSTD_initCStream_advanced(ZSTD_CStream *zcs, const void *dict, size_t dictSize, ZSTD_parameters params, unsigned long long pledgedSrcSize) 30568c2ecf20Sopenharmony_ci{ 30578c2ecf20Sopenharmony_ci /* allocate buffers */ 30588c2ecf20Sopenharmony_ci { 30598c2ecf20Sopenharmony_ci size_t const neededInBuffSize = (size_t)1 << params.cParams.windowLog; 30608c2ecf20Sopenharmony_ci if (zcs->inBuffSize < neededInBuffSize) { 30618c2ecf20Sopenharmony_ci zcs->inBuffSize = neededInBuffSize; 30628c2ecf20Sopenharmony_ci ZSTD_free(zcs->inBuff, zcs->customMem); 30638c2ecf20Sopenharmony_ci zcs->inBuff = (char *)ZSTD_malloc(neededInBuffSize, zcs->customMem); 30648c2ecf20Sopenharmony_ci if (zcs->inBuff == NULL) 30658c2ecf20Sopenharmony_ci return ERROR(memory_allocation); 30668c2ecf20Sopenharmony_ci } 30678c2ecf20Sopenharmony_ci zcs->blockSize = MIN(ZSTD_BLOCKSIZE_ABSOLUTEMAX, neededInBuffSize); 30688c2ecf20Sopenharmony_ci } 30698c2ecf20Sopenharmony_ci if (zcs->outBuffSize < ZSTD_compressBound(zcs->blockSize) + 1) { 30708c2ecf20Sopenharmony_ci zcs->outBuffSize = ZSTD_compressBound(zcs->blockSize) + 1; 30718c2ecf20Sopenharmony_ci ZSTD_free(zcs->outBuff, zcs->customMem); 30728c2ecf20Sopenharmony_ci zcs->outBuff = (char *)ZSTD_malloc(zcs->outBuffSize, zcs->customMem); 30738c2ecf20Sopenharmony_ci if (zcs->outBuff == NULL) 30748c2ecf20Sopenharmony_ci return ERROR(memory_allocation); 30758c2ecf20Sopenharmony_ci } 30768c2ecf20Sopenharmony_ci 30778c2ecf20Sopenharmony_ci if (dict && dictSize >= 8) { 30788c2ecf20Sopenharmony_ci ZSTD_freeCDict(zcs->cdictLocal); 30798c2ecf20Sopenharmony_ci zcs->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize, 0, params, zcs->customMem); 30808c2ecf20Sopenharmony_ci if (zcs->cdictLocal == NULL) 30818c2ecf20Sopenharmony_ci return ERROR(memory_allocation); 30828c2ecf20Sopenharmony_ci zcs->cdict = zcs->cdictLocal; 30838c2ecf20Sopenharmony_ci } else 30848c2ecf20Sopenharmony_ci zcs->cdict = NULL; 30858c2ecf20Sopenharmony_ci 30868c2ecf20Sopenharmony_ci zcs->checksum = params.fParams.checksumFlag > 0; 30878c2ecf20Sopenharmony_ci zcs->params = params; 30888c2ecf20Sopenharmony_ci 30898c2ecf20Sopenharmony_ci return ZSTD_resetCStream_internal(zcs, pledgedSrcSize); 30908c2ecf20Sopenharmony_ci} 30918c2ecf20Sopenharmony_ci 30928c2ecf20Sopenharmony_ciZSTD_CStream *ZSTD_initCStream(ZSTD_parameters params, unsigned long long pledgedSrcSize, void *workspace, size_t workspaceSize) 30938c2ecf20Sopenharmony_ci{ 30948c2ecf20Sopenharmony_ci ZSTD_customMem const stackMem = ZSTD_initStack(workspace, workspaceSize); 30958c2ecf20Sopenharmony_ci ZSTD_CStream *const zcs = ZSTD_createCStream_advanced(stackMem); 30968c2ecf20Sopenharmony_ci if (zcs) { 30978c2ecf20Sopenharmony_ci size_t const code = ZSTD_initCStream_advanced(zcs, NULL, 0, params, pledgedSrcSize); 30988c2ecf20Sopenharmony_ci if (ZSTD_isError(code)) { 30998c2ecf20Sopenharmony_ci return NULL; 31008c2ecf20Sopenharmony_ci } 31018c2ecf20Sopenharmony_ci } 31028c2ecf20Sopenharmony_ci return zcs; 31038c2ecf20Sopenharmony_ci} 31048c2ecf20Sopenharmony_ci 31058c2ecf20Sopenharmony_ciZSTD_CStream *ZSTD_initCStream_usingCDict(const ZSTD_CDict *cdict, unsigned long long pledgedSrcSize, void *workspace, size_t workspaceSize) 31068c2ecf20Sopenharmony_ci{ 31078c2ecf20Sopenharmony_ci ZSTD_parameters const params = ZSTD_getParamsFromCDict(cdict); 31088c2ecf20Sopenharmony_ci ZSTD_CStream *const zcs = ZSTD_initCStream(params, pledgedSrcSize, workspace, workspaceSize); 31098c2ecf20Sopenharmony_ci if (zcs) { 31108c2ecf20Sopenharmony_ci zcs->cdict = cdict; 31118c2ecf20Sopenharmony_ci if (ZSTD_isError(ZSTD_resetCStream_internal(zcs, pledgedSrcSize))) { 31128c2ecf20Sopenharmony_ci return NULL; 31138c2ecf20Sopenharmony_ci } 31148c2ecf20Sopenharmony_ci } 31158c2ecf20Sopenharmony_ci return zcs; 31168c2ecf20Sopenharmony_ci} 31178c2ecf20Sopenharmony_ci 31188c2ecf20Sopenharmony_ci/*====== Compression ======*/ 31198c2ecf20Sopenharmony_ci 31208c2ecf20Sopenharmony_citypedef enum { zsf_gather, zsf_flush, zsf_end } ZSTD_flush_e; 31218c2ecf20Sopenharmony_ci 31228c2ecf20Sopenharmony_ciZSTD_STATIC size_t ZSTD_limitCopy(void *dst, size_t dstCapacity, const void *src, size_t srcSize) 31238c2ecf20Sopenharmony_ci{ 31248c2ecf20Sopenharmony_ci size_t const length = MIN(dstCapacity, srcSize); 31258c2ecf20Sopenharmony_ci memcpy(dst, src, length); 31268c2ecf20Sopenharmony_ci return length; 31278c2ecf20Sopenharmony_ci} 31288c2ecf20Sopenharmony_ci 31298c2ecf20Sopenharmony_cistatic size_t ZSTD_compressStream_generic(ZSTD_CStream *zcs, void *dst, size_t *dstCapacityPtr, const void *src, size_t *srcSizePtr, ZSTD_flush_e const flush) 31308c2ecf20Sopenharmony_ci{ 31318c2ecf20Sopenharmony_ci U32 someMoreWork = 1; 31328c2ecf20Sopenharmony_ci const char *const istart = (const char *)src; 31338c2ecf20Sopenharmony_ci const char *const iend = istart + *srcSizePtr; 31348c2ecf20Sopenharmony_ci const char *ip = istart; 31358c2ecf20Sopenharmony_ci char *const ostart = (char *)dst; 31368c2ecf20Sopenharmony_ci char *const oend = ostart + *dstCapacityPtr; 31378c2ecf20Sopenharmony_ci char *op = ostart; 31388c2ecf20Sopenharmony_ci 31398c2ecf20Sopenharmony_ci while (someMoreWork) { 31408c2ecf20Sopenharmony_ci switch (zcs->stage) { 31418c2ecf20Sopenharmony_ci case zcss_init: 31428c2ecf20Sopenharmony_ci return ERROR(init_missing); /* call ZBUFF_compressInit() first ! */ 31438c2ecf20Sopenharmony_ci 31448c2ecf20Sopenharmony_ci case zcss_load: 31458c2ecf20Sopenharmony_ci /* complete inBuffer */ 31468c2ecf20Sopenharmony_ci { 31478c2ecf20Sopenharmony_ci size_t const toLoad = zcs->inBuffTarget - zcs->inBuffPos; 31488c2ecf20Sopenharmony_ci size_t const loaded = ZSTD_limitCopy(zcs->inBuff + zcs->inBuffPos, toLoad, ip, iend - ip); 31498c2ecf20Sopenharmony_ci zcs->inBuffPos += loaded; 31508c2ecf20Sopenharmony_ci ip += loaded; 31518c2ecf20Sopenharmony_ci if ((zcs->inBuffPos == zcs->inToCompress) || (!flush && (toLoad != loaded))) { 31528c2ecf20Sopenharmony_ci someMoreWork = 0; 31538c2ecf20Sopenharmony_ci break; /* not enough input to get a full block : stop there, wait for more */ 31548c2ecf20Sopenharmony_ci } 31558c2ecf20Sopenharmony_ci } 31568c2ecf20Sopenharmony_ci /* compress curr block (note : this stage cannot be stopped in the middle) */ 31578c2ecf20Sopenharmony_ci { 31588c2ecf20Sopenharmony_ci void *cDst; 31598c2ecf20Sopenharmony_ci size_t cSize; 31608c2ecf20Sopenharmony_ci size_t const iSize = zcs->inBuffPos - zcs->inToCompress; 31618c2ecf20Sopenharmony_ci size_t oSize = oend - op; 31628c2ecf20Sopenharmony_ci if (oSize >= ZSTD_compressBound(iSize)) 31638c2ecf20Sopenharmony_ci cDst = op; /* compress directly into output buffer (avoid flush stage) */ 31648c2ecf20Sopenharmony_ci else 31658c2ecf20Sopenharmony_ci cDst = zcs->outBuff, oSize = zcs->outBuffSize; 31668c2ecf20Sopenharmony_ci cSize = (flush == zsf_end) ? ZSTD_compressEnd(zcs->cctx, cDst, oSize, zcs->inBuff + zcs->inToCompress, iSize) 31678c2ecf20Sopenharmony_ci : ZSTD_compressContinue(zcs->cctx, cDst, oSize, zcs->inBuff + zcs->inToCompress, iSize); 31688c2ecf20Sopenharmony_ci if (ZSTD_isError(cSize)) 31698c2ecf20Sopenharmony_ci return cSize; 31708c2ecf20Sopenharmony_ci if (flush == zsf_end) 31718c2ecf20Sopenharmony_ci zcs->frameEnded = 1; 31728c2ecf20Sopenharmony_ci /* prepare next block */ 31738c2ecf20Sopenharmony_ci zcs->inBuffTarget = zcs->inBuffPos + zcs->blockSize; 31748c2ecf20Sopenharmony_ci if (zcs->inBuffTarget > zcs->inBuffSize) 31758c2ecf20Sopenharmony_ci zcs->inBuffPos = 0, zcs->inBuffTarget = zcs->blockSize; /* note : inBuffSize >= blockSize */ 31768c2ecf20Sopenharmony_ci zcs->inToCompress = zcs->inBuffPos; 31778c2ecf20Sopenharmony_ci if (cDst == op) { 31788c2ecf20Sopenharmony_ci op += cSize; 31798c2ecf20Sopenharmony_ci break; 31808c2ecf20Sopenharmony_ci } /* no need to flush */ 31818c2ecf20Sopenharmony_ci zcs->outBuffContentSize = cSize; 31828c2ecf20Sopenharmony_ci zcs->outBuffFlushedSize = 0; 31838c2ecf20Sopenharmony_ci zcs->stage = zcss_flush; /* pass-through to flush stage */ 31848c2ecf20Sopenharmony_ci } 31858c2ecf20Sopenharmony_ci /* fall through */ 31868c2ecf20Sopenharmony_ci 31878c2ecf20Sopenharmony_ci case zcss_flush: { 31888c2ecf20Sopenharmony_ci size_t const toFlush = zcs->outBuffContentSize - zcs->outBuffFlushedSize; 31898c2ecf20Sopenharmony_ci size_t const flushed = ZSTD_limitCopy(op, oend - op, zcs->outBuff + zcs->outBuffFlushedSize, toFlush); 31908c2ecf20Sopenharmony_ci op += flushed; 31918c2ecf20Sopenharmony_ci zcs->outBuffFlushedSize += flushed; 31928c2ecf20Sopenharmony_ci if (toFlush != flushed) { 31938c2ecf20Sopenharmony_ci someMoreWork = 0; 31948c2ecf20Sopenharmony_ci break; 31958c2ecf20Sopenharmony_ci } /* dst too small to store flushed data : stop there */ 31968c2ecf20Sopenharmony_ci zcs->outBuffContentSize = zcs->outBuffFlushedSize = 0; 31978c2ecf20Sopenharmony_ci zcs->stage = zcss_load; 31988c2ecf20Sopenharmony_ci break; 31998c2ecf20Sopenharmony_ci } 32008c2ecf20Sopenharmony_ci 32018c2ecf20Sopenharmony_ci case zcss_final: 32028c2ecf20Sopenharmony_ci someMoreWork = 0; /* do nothing */ 32038c2ecf20Sopenharmony_ci break; 32048c2ecf20Sopenharmony_ci 32058c2ecf20Sopenharmony_ci default: 32068c2ecf20Sopenharmony_ci return ERROR(GENERIC); /* impossible */ 32078c2ecf20Sopenharmony_ci } 32088c2ecf20Sopenharmony_ci } 32098c2ecf20Sopenharmony_ci 32108c2ecf20Sopenharmony_ci *srcSizePtr = ip - istart; 32118c2ecf20Sopenharmony_ci *dstCapacityPtr = op - ostart; 32128c2ecf20Sopenharmony_ci zcs->inputProcessed += *srcSizePtr; 32138c2ecf20Sopenharmony_ci if (zcs->frameEnded) 32148c2ecf20Sopenharmony_ci return 0; 32158c2ecf20Sopenharmony_ci { 32168c2ecf20Sopenharmony_ci size_t hintInSize = zcs->inBuffTarget - zcs->inBuffPos; 32178c2ecf20Sopenharmony_ci if (hintInSize == 0) 32188c2ecf20Sopenharmony_ci hintInSize = zcs->blockSize; 32198c2ecf20Sopenharmony_ci return hintInSize; 32208c2ecf20Sopenharmony_ci } 32218c2ecf20Sopenharmony_ci} 32228c2ecf20Sopenharmony_ci 32238c2ecf20Sopenharmony_cisize_t ZSTD_compressStream(ZSTD_CStream *zcs, ZSTD_outBuffer *output, ZSTD_inBuffer *input) 32248c2ecf20Sopenharmony_ci{ 32258c2ecf20Sopenharmony_ci size_t sizeRead = input->size - input->pos; 32268c2ecf20Sopenharmony_ci size_t sizeWritten = output->size - output->pos; 32278c2ecf20Sopenharmony_ci size_t const result = 32288c2ecf20Sopenharmony_ci ZSTD_compressStream_generic(zcs, (char *)(output->dst) + output->pos, &sizeWritten, (const char *)(input->src) + input->pos, &sizeRead, zsf_gather); 32298c2ecf20Sopenharmony_ci input->pos += sizeRead; 32308c2ecf20Sopenharmony_ci output->pos += sizeWritten; 32318c2ecf20Sopenharmony_ci return result; 32328c2ecf20Sopenharmony_ci} 32338c2ecf20Sopenharmony_ci 32348c2ecf20Sopenharmony_ci/*====== Finalize ======*/ 32358c2ecf20Sopenharmony_ci 32368c2ecf20Sopenharmony_ci/*! ZSTD_flushStream() : 32378c2ecf20Sopenharmony_ci* @return : amount of data remaining to flush */ 32388c2ecf20Sopenharmony_cisize_t ZSTD_flushStream(ZSTD_CStream *zcs, ZSTD_outBuffer *output) 32398c2ecf20Sopenharmony_ci{ 32408c2ecf20Sopenharmony_ci size_t srcSize = 0; 32418c2ecf20Sopenharmony_ci size_t sizeWritten = output->size - output->pos; 32428c2ecf20Sopenharmony_ci size_t const result = ZSTD_compressStream_generic(zcs, (char *)(output->dst) + output->pos, &sizeWritten, &srcSize, 32438c2ecf20Sopenharmony_ci &srcSize, /* use a valid src address instead of NULL */ 32448c2ecf20Sopenharmony_ci zsf_flush); 32458c2ecf20Sopenharmony_ci output->pos += sizeWritten; 32468c2ecf20Sopenharmony_ci if (ZSTD_isError(result)) 32478c2ecf20Sopenharmony_ci return result; 32488c2ecf20Sopenharmony_ci return zcs->outBuffContentSize - zcs->outBuffFlushedSize; /* remaining to flush */ 32498c2ecf20Sopenharmony_ci} 32508c2ecf20Sopenharmony_ci 32518c2ecf20Sopenharmony_cisize_t ZSTD_endStream(ZSTD_CStream *zcs, ZSTD_outBuffer *output) 32528c2ecf20Sopenharmony_ci{ 32538c2ecf20Sopenharmony_ci BYTE *const ostart = (BYTE *)(output->dst) + output->pos; 32548c2ecf20Sopenharmony_ci BYTE *const oend = (BYTE *)(output->dst) + output->size; 32558c2ecf20Sopenharmony_ci BYTE *op = ostart; 32568c2ecf20Sopenharmony_ci 32578c2ecf20Sopenharmony_ci if ((zcs->pledgedSrcSize) && (zcs->inputProcessed != zcs->pledgedSrcSize)) 32588c2ecf20Sopenharmony_ci return ERROR(srcSize_wrong); /* pledgedSrcSize not respected */ 32598c2ecf20Sopenharmony_ci 32608c2ecf20Sopenharmony_ci if (zcs->stage != zcss_final) { 32618c2ecf20Sopenharmony_ci /* flush whatever remains */ 32628c2ecf20Sopenharmony_ci size_t srcSize = 0; 32638c2ecf20Sopenharmony_ci size_t sizeWritten = output->size - output->pos; 32648c2ecf20Sopenharmony_ci size_t const notEnded = 32658c2ecf20Sopenharmony_ci ZSTD_compressStream_generic(zcs, ostart, &sizeWritten, &srcSize, &srcSize, zsf_end); /* use a valid src address instead of NULL */ 32668c2ecf20Sopenharmony_ci size_t const remainingToFlush = zcs->outBuffContentSize - zcs->outBuffFlushedSize; 32678c2ecf20Sopenharmony_ci op += sizeWritten; 32688c2ecf20Sopenharmony_ci if (remainingToFlush) { 32698c2ecf20Sopenharmony_ci output->pos += sizeWritten; 32708c2ecf20Sopenharmony_ci return remainingToFlush + ZSTD_BLOCKHEADERSIZE /* final empty block */ + (zcs->checksum * 4); 32718c2ecf20Sopenharmony_ci } 32728c2ecf20Sopenharmony_ci /* create epilogue */ 32738c2ecf20Sopenharmony_ci zcs->stage = zcss_final; 32748c2ecf20Sopenharmony_ci zcs->outBuffContentSize = !notEnded ? 0 : ZSTD_compressEnd(zcs->cctx, zcs->outBuff, zcs->outBuffSize, NULL, 32758c2ecf20Sopenharmony_ci 0); /* write epilogue, including final empty block, into outBuff */ 32768c2ecf20Sopenharmony_ci } 32778c2ecf20Sopenharmony_ci 32788c2ecf20Sopenharmony_ci /* flush epilogue */ 32798c2ecf20Sopenharmony_ci { 32808c2ecf20Sopenharmony_ci size_t const toFlush = zcs->outBuffContentSize - zcs->outBuffFlushedSize; 32818c2ecf20Sopenharmony_ci size_t const flushed = ZSTD_limitCopy(op, oend - op, zcs->outBuff + zcs->outBuffFlushedSize, toFlush); 32828c2ecf20Sopenharmony_ci op += flushed; 32838c2ecf20Sopenharmony_ci zcs->outBuffFlushedSize += flushed; 32848c2ecf20Sopenharmony_ci output->pos += op - ostart; 32858c2ecf20Sopenharmony_ci if (toFlush == flushed) 32868c2ecf20Sopenharmony_ci zcs->stage = zcss_init; /* end reached */ 32878c2ecf20Sopenharmony_ci return toFlush - flushed; 32888c2ecf20Sopenharmony_ci } 32898c2ecf20Sopenharmony_ci} 32908c2ecf20Sopenharmony_ci 32918c2ecf20Sopenharmony_ci/*-===== Pre-defined compression levels =====-*/ 32928c2ecf20Sopenharmony_ci 32938c2ecf20Sopenharmony_ci#define ZSTD_DEFAULT_CLEVEL 1 32948c2ecf20Sopenharmony_ci#define ZSTD_MAX_CLEVEL 22 32958c2ecf20Sopenharmony_ciint ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; } 32968c2ecf20Sopenharmony_ci 32978c2ecf20Sopenharmony_cistatic const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL + 1] = { 32988c2ecf20Sopenharmony_ci { 32998c2ecf20Sopenharmony_ci /* "default" */ 33008c2ecf20Sopenharmony_ci /* W, C, H, S, L, TL, strat */ 33018c2ecf20Sopenharmony_ci {18, 12, 12, 1, 7, 16, ZSTD_fast}, /* level 0 - never used */ 33028c2ecf20Sopenharmony_ci {19, 13, 14, 1, 7, 16, ZSTD_fast}, /* level 1 */ 33038c2ecf20Sopenharmony_ci {19, 15, 16, 1, 6, 16, ZSTD_fast}, /* level 2 */ 33048c2ecf20Sopenharmony_ci {20, 16, 17, 1, 5, 16, ZSTD_dfast}, /* level 3.*/ 33058c2ecf20Sopenharmony_ci {20, 18, 18, 1, 5, 16, ZSTD_dfast}, /* level 4.*/ 33068c2ecf20Sopenharmony_ci {20, 15, 18, 3, 5, 16, ZSTD_greedy}, /* level 5 */ 33078c2ecf20Sopenharmony_ci {21, 16, 19, 2, 5, 16, ZSTD_lazy}, /* level 6 */ 33088c2ecf20Sopenharmony_ci {21, 17, 20, 3, 5, 16, ZSTD_lazy}, /* level 7 */ 33098c2ecf20Sopenharmony_ci {21, 18, 20, 3, 5, 16, ZSTD_lazy2}, /* level 8 */ 33108c2ecf20Sopenharmony_ci {21, 20, 20, 3, 5, 16, ZSTD_lazy2}, /* level 9 */ 33118c2ecf20Sopenharmony_ci {21, 19, 21, 4, 5, 16, ZSTD_lazy2}, /* level 10 */ 33128c2ecf20Sopenharmony_ci {22, 20, 22, 4, 5, 16, ZSTD_lazy2}, /* level 11 */ 33138c2ecf20Sopenharmony_ci {22, 20, 22, 5, 5, 16, ZSTD_lazy2}, /* level 12 */ 33148c2ecf20Sopenharmony_ci {22, 21, 22, 5, 5, 16, ZSTD_lazy2}, /* level 13 */ 33158c2ecf20Sopenharmony_ci {22, 21, 22, 6, 5, 16, ZSTD_lazy2}, /* level 14 */ 33168c2ecf20Sopenharmony_ci {22, 21, 21, 5, 5, 16, ZSTD_btlazy2}, /* level 15 */ 33178c2ecf20Sopenharmony_ci {23, 22, 22, 5, 5, 16, ZSTD_btlazy2}, /* level 16 */ 33188c2ecf20Sopenharmony_ci {23, 21, 22, 4, 5, 24, ZSTD_btopt}, /* level 17 */ 33198c2ecf20Sopenharmony_ci {23, 23, 22, 6, 5, 32, ZSTD_btopt}, /* level 18 */ 33208c2ecf20Sopenharmony_ci {23, 23, 22, 6, 3, 48, ZSTD_btopt}, /* level 19 */ 33218c2ecf20Sopenharmony_ci {25, 25, 23, 7, 3, 64, ZSTD_btopt2}, /* level 20 */ 33228c2ecf20Sopenharmony_ci {26, 26, 23, 7, 3, 256, ZSTD_btopt2}, /* level 21 */ 33238c2ecf20Sopenharmony_ci {27, 27, 25, 9, 3, 512, ZSTD_btopt2}, /* level 22 */ 33248c2ecf20Sopenharmony_ci }, 33258c2ecf20Sopenharmony_ci { 33268c2ecf20Sopenharmony_ci /* for srcSize <= 256 KB */ 33278c2ecf20Sopenharmony_ci /* W, C, H, S, L, T, strat */ 33288c2ecf20Sopenharmony_ci {0, 0, 0, 0, 0, 0, ZSTD_fast}, /* level 0 - not used */ 33298c2ecf20Sopenharmony_ci {18, 13, 14, 1, 6, 8, ZSTD_fast}, /* level 1 */ 33308c2ecf20Sopenharmony_ci {18, 14, 13, 1, 5, 8, ZSTD_dfast}, /* level 2 */ 33318c2ecf20Sopenharmony_ci {18, 16, 15, 1, 5, 8, ZSTD_dfast}, /* level 3 */ 33328c2ecf20Sopenharmony_ci {18, 15, 17, 1, 5, 8, ZSTD_greedy}, /* level 4.*/ 33338c2ecf20Sopenharmony_ci {18, 16, 17, 4, 5, 8, ZSTD_greedy}, /* level 5.*/ 33348c2ecf20Sopenharmony_ci {18, 16, 17, 3, 5, 8, ZSTD_lazy}, /* level 6.*/ 33358c2ecf20Sopenharmony_ci {18, 17, 17, 4, 4, 8, ZSTD_lazy}, /* level 7 */ 33368c2ecf20Sopenharmony_ci {18, 17, 17, 4, 4, 8, ZSTD_lazy2}, /* level 8 */ 33378c2ecf20Sopenharmony_ci {18, 17, 17, 5, 4, 8, ZSTD_lazy2}, /* level 9 */ 33388c2ecf20Sopenharmony_ci {18, 17, 17, 6, 4, 8, ZSTD_lazy2}, /* level 10 */ 33398c2ecf20Sopenharmony_ci {18, 18, 17, 6, 4, 8, ZSTD_lazy2}, /* level 11.*/ 33408c2ecf20Sopenharmony_ci {18, 18, 17, 7, 4, 8, ZSTD_lazy2}, /* level 12.*/ 33418c2ecf20Sopenharmony_ci {18, 19, 17, 6, 4, 8, ZSTD_btlazy2}, /* level 13 */ 33428c2ecf20Sopenharmony_ci {18, 18, 18, 4, 4, 16, ZSTD_btopt}, /* level 14.*/ 33438c2ecf20Sopenharmony_ci {18, 18, 18, 4, 3, 16, ZSTD_btopt}, /* level 15.*/ 33448c2ecf20Sopenharmony_ci {18, 19, 18, 6, 3, 32, ZSTD_btopt}, /* level 16.*/ 33458c2ecf20Sopenharmony_ci {18, 19, 18, 8, 3, 64, ZSTD_btopt}, /* level 17.*/ 33468c2ecf20Sopenharmony_ci {18, 19, 18, 9, 3, 128, ZSTD_btopt}, /* level 18.*/ 33478c2ecf20Sopenharmony_ci {18, 19, 18, 10, 3, 256, ZSTD_btopt}, /* level 19.*/ 33488c2ecf20Sopenharmony_ci {18, 19, 18, 11, 3, 512, ZSTD_btopt2}, /* level 20.*/ 33498c2ecf20Sopenharmony_ci {18, 19, 18, 12, 3, 512, ZSTD_btopt2}, /* level 21.*/ 33508c2ecf20Sopenharmony_ci {18, 19, 18, 13, 3, 512, ZSTD_btopt2}, /* level 22.*/ 33518c2ecf20Sopenharmony_ci }, 33528c2ecf20Sopenharmony_ci { 33538c2ecf20Sopenharmony_ci /* for srcSize <= 128 KB */ 33548c2ecf20Sopenharmony_ci /* W, C, H, S, L, T, strat */ 33558c2ecf20Sopenharmony_ci {17, 12, 12, 1, 7, 8, ZSTD_fast}, /* level 0 - not used */ 33568c2ecf20Sopenharmony_ci {17, 12, 13, 1, 6, 8, ZSTD_fast}, /* level 1 */ 33578c2ecf20Sopenharmony_ci {17, 13, 16, 1, 5, 8, ZSTD_fast}, /* level 2 */ 33588c2ecf20Sopenharmony_ci {17, 16, 16, 2, 5, 8, ZSTD_dfast}, /* level 3 */ 33598c2ecf20Sopenharmony_ci {17, 13, 15, 3, 4, 8, ZSTD_greedy}, /* level 4 */ 33608c2ecf20Sopenharmony_ci {17, 15, 17, 4, 4, 8, ZSTD_greedy}, /* level 5 */ 33618c2ecf20Sopenharmony_ci {17, 16, 17, 3, 4, 8, ZSTD_lazy}, /* level 6 */ 33628c2ecf20Sopenharmony_ci {17, 15, 17, 4, 4, 8, ZSTD_lazy2}, /* level 7 */ 33638c2ecf20Sopenharmony_ci {17, 17, 17, 4, 4, 8, ZSTD_lazy2}, /* level 8 */ 33648c2ecf20Sopenharmony_ci {17, 17, 17, 5, 4, 8, ZSTD_lazy2}, /* level 9 */ 33658c2ecf20Sopenharmony_ci {17, 17, 17, 6, 4, 8, ZSTD_lazy2}, /* level 10 */ 33668c2ecf20Sopenharmony_ci {17, 17, 17, 7, 4, 8, ZSTD_lazy2}, /* level 11 */ 33678c2ecf20Sopenharmony_ci {17, 17, 17, 8, 4, 8, ZSTD_lazy2}, /* level 12 */ 33688c2ecf20Sopenharmony_ci {17, 18, 17, 6, 4, 8, ZSTD_btlazy2}, /* level 13.*/ 33698c2ecf20Sopenharmony_ci {17, 17, 17, 7, 3, 8, ZSTD_btopt}, /* level 14.*/ 33708c2ecf20Sopenharmony_ci {17, 17, 17, 7, 3, 16, ZSTD_btopt}, /* level 15.*/ 33718c2ecf20Sopenharmony_ci {17, 18, 17, 7, 3, 32, ZSTD_btopt}, /* level 16.*/ 33728c2ecf20Sopenharmony_ci {17, 18, 17, 7, 3, 64, ZSTD_btopt}, /* level 17.*/ 33738c2ecf20Sopenharmony_ci {17, 18, 17, 7, 3, 256, ZSTD_btopt}, /* level 18.*/ 33748c2ecf20Sopenharmony_ci {17, 18, 17, 8, 3, 256, ZSTD_btopt}, /* level 19.*/ 33758c2ecf20Sopenharmony_ci {17, 18, 17, 9, 3, 256, ZSTD_btopt2}, /* level 20.*/ 33768c2ecf20Sopenharmony_ci {17, 18, 17, 10, 3, 256, ZSTD_btopt2}, /* level 21.*/ 33778c2ecf20Sopenharmony_ci {17, 18, 17, 11, 3, 512, ZSTD_btopt2}, /* level 22.*/ 33788c2ecf20Sopenharmony_ci }, 33798c2ecf20Sopenharmony_ci { 33808c2ecf20Sopenharmony_ci /* for srcSize <= 16 KB */ 33818c2ecf20Sopenharmony_ci /* W, C, H, S, L, T, strat */ 33828c2ecf20Sopenharmony_ci {14, 12, 12, 1, 7, 6, ZSTD_fast}, /* level 0 - not used */ 33838c2ecf20Sopenharmony_ci {14, 14, 14, 1, 6, 6, ZSTD_fast}, /* level 1 */ 33848c2ecf20Sopenharmony_ci {14, 14, 14, 1, 4, 6, ZSTD_fast}, /* level 2 */ 33858c2ecf20Sopenharmony_ci {14, 14, 14, 1, 4, 6, ZSTD_dfast}, /* level 3.*/ 33868c2ecf20Sopenharmony_ci {14, 14, 14, 4, 4, 6, ZSTD_greedy}, /* level 4.*/ 33878c2ecf20Sopenharmony_ci {14, 14, 14, 3, 4, 6, ZSTD_lazy}, /* level 5.*/ 33888c2ecf20Sopenharmony_ci {14, 14, 14, 4, 4, 6, ZSTD_lazy2}, /* level 6 */ 33898c2ecf20Sopenharmony_ci {14, 14, 14, 5, 4, 6, ZSTD_lazy2}, /* level 7 */ 33908c2ecf20Sopenharmony_ci {14, 14, 14, 6, 4, 6, ZSTD_lazy2}, /* level 8.*/ 33918c2ecf20Sopenharmony_ci {14, 15, 14, 6, 4, 6, ZSTD_btlazy2}, /* level 9.*/ 33928c2ecf20Sopenharmony_ci {14, 15, 14, 3, 3, 6, ZSTD_btopt}, /* level 10.*/ 33938c2ecf20Sopenharmony_ci {14, 15, 14, 6, 3, 8, ZSTD_btopt}, /* level 11.*/ 33948c2ecf20Sopenharmony_ci {14, 15, 14, 6, 3, 16, ZSTD_btopt}, /* level 12.*/ 33958c2ecf20Sopenharmony_ci {14, 15, 14, 6, 3, 24, ZSTD_btopt}, /* level 13.*/ 33968c2ecf20Sopenharmony_ci {14, 15, 15, 6, 3, 48, ZSTD_btopt}, /* level 14.*/ 33978c2ecf20Sopenharmony_ci {14, 15, 15, 6, 3, 64, ZSTD_btopt}, /* level 15.*/ 33988c2ecf20Sopenharmony_ci {14, 15, 15, 6, 3, 96, ZSTD_btopt}, /* level 16.*/ 33998c2ecf20Sopenharmony_ci {14, 15, 15, 6, 3, 128, ZSTD_btopt}, /* level 17.*/ 34008c2ecf20Sopenharmony_ci {14, 15, 15, 6, 3, 256, ZSTD_btopt}, /* level 18.*/ 34018c2ecf20Sopenharmony_ci {14, 15, 15, 7, 3, 256, ZSTD_btopt}, /* level 19.*/ 34028c2ecf20Sopenharmony_ci {14, 15, 15, 8, 3, 256, ZSTD_btopt2}, /* level 20.*/ 34038c2ecf20Sopenharmony_ci {14, 15, 15, 9, 3, 256, ZSTD_btopt2}, /* level 21.*/ 34048c2ecf20Sopenharmony_ci {14, 15, 15, 10, 3, 256, ZSTD_btopt2}, /* level 22.*/ 34058c2ecf20Sopenharmony_ci }, 34068c2ecf20Sopenharmony_ci}; 34078c2ecf20Sopenharmony_ci 34088c2ecf20Sopenharmony_ci/*! ZSTD_getCParams() : 34098c2ecf20Sopenharmony_ci* @return ZSTD_compressionParameters structure for a selected compression level, `srcSize` and `dictSize`. 34108c2ecf20Sopenharmony_ci* Size values are optional, provide 0 if not known or unused */ 34118c2ecf20Sopenharmony_ciZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long srcSize, size_t dictSize) 34128c2ecf20Sopenharmony_ci{ 34138c2ecf20Sopenharmony_ci ZSTD_compressionParameters cp; 34148c2ecf20Sopenharmony_ci size_t const addedSize = srcSize ? 0 : 500; 34158c2ecf20Sopenharmony_ci U64 const rSize = srcSize + dictSize ? srcSize + dictSize + addedSize : (U64)-1; 34168c2ecf20Sopenharmony_ci U32 const tableID = (rSize <= 256 KB) + (rSize <= 128 KB) + (rSize <= 16 KB); /* intentional underflow for srcSizeHint == 0 */ 34178c2ecf20Sopenharmony_ci if (compressionLevel <= 0) 34188c2ecf20Sopenharmony_ci compressionLevel = ZSTD_DEFAULT_CLEVEL; /* 0 == default; no negative compressionLevel yet */ 34198c2ecf20Sopenharmony_ci if (compressionLevel > ZSTD_MAX_CLEVEL) 34208c2ecf20Sopenharmony_ci compressionLevel = ZSTD_MAX_CLEVEL; 34218c2ecf20Sopenharmony_ci cp = ZSTD_defaultCParameters[tableID][compressionLevel]; 34228c2ecf20Sopenharmony_ci if (ZSTD_32bits()) { /* auto-correction, for 32-bits mode */ 34238c2ecf20Sopenharmony_ci if (cp.windowLog > ZSTD_WINDOWLOG_MAX) 34248c2ecf20Sopenharmony_ci cp.windowLog = ZSTD_WINDOWLOG_MAX; 34258c2ecf20Sopenharmony_ci if (cp.chainLog > ZSTD_CHAINLOG_MAX) 34268c2ecf20Sopenharmony_ci cp.chainLog = ZSTD_CHAINLOG_MAX; 34278c2ecf20Sopenharmony_ci if (cp.hashLog > ZSTD_HASHLOG_MAX) 34288c2ecf20Sopenharmony_ci cp.hashLog = ZSTD_HASHLOG_MAX; 34298c2ecf20Sopenharmony_ci } 34308c2ecf20Sopenharmony_ci cp = ZSTD_adjustCParams(cp, srcSize, dictSize); 34318c2ecf20Sopenharmony_ci return cp; 34328c2ecf20Sopenharmony_ci} 34338c2ecf20Sopenharmony_ci 34348c2ecf20Sopenharmony_ci/*! ZSTD_getParams() : 34358c2ecf20Sopenharmony_ci* same as ZSTD_getCParams(), but @return a `ZSTD_parameters` object (instead of `ZSTD_compressionParameters`). 34368c2ecf20Sopenharmony_ci* All fields of `ZSTD_frameParameters` are set to default (0) */ 34378c2ecf20Sopenharmony_ciZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSize, size_t dictSize) 34388c2ecf20Sopenharmony_ci{ 34398c2ecf20Sopenharmony_ci ZSTD_parameters params; 34408c2ecf20Sopenharmony_ci ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, srcSize, dictSize); 34418c2ecf20Sopenharmony_ci memset(¶ms, 0, sizeof(params)); 34428c2ecf20Sopenharmony_ci params.cParams = cParams; 34438c2ecf20Sopenharmony_ci return params; 34448c2ecf20Sopenharmony_ci} 34458c2ecf20Sopenharmony_ci 34468c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_maxCLevel); 34478c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_compressBound); 34488c2ecf20Sopenharmony_ci 34498c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_CCtxWorkspaceBound); 34508c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_initCCtx); 34518c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_compressCCtx); 34528c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_compress_usingDict); 34538c2ecf20Sopenharmony_ci 34548c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_CDictWorkspaceBound); 34558c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_initCDict); 34568c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_compress_usingCDict); 34578c2ecf20Sopenharmony_ci 34588c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_CStreamWorkspaceBound); 34598c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_initCStream); 34608c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_initCStream_usingCDict); 34618c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_resetCStream); 34628c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_compressStream); 34638c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_flushStream); 34648c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_endStream); 34658c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_CStreamInSize); 34668c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_CStreamOutSize); 34678c2ecf20Sopenharmony_ci 34688c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_getCParams); 34698c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_getParams); 34708c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_checkCParams); 34718c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_adjustCParams); 34728c2ecf20Sopenharmony_ci 34738c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_compressBegin); 34748c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_compressBegin_usingDict); 34758c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_compressBegin_advanced); 34768c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_copyCCtx); 34778c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_compressBegin_usingCDict); 34788c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_compressContinue); 34798c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_compressEnd); 34808c2ecf20Sopenharmony_ci 34818c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_getBlockSizeMax); 34828c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_compressBlock); 34838c2ecf20Sopenharmony_ci 34848c2ecf20Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL"); 34858c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Zstd Compressor"); 3486