18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * FSE : Finite State Entropy decoder 38c2ecf20Sopenharmony_ci * Copyright (C) 2013-2015, Yann Collet. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 88c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions are 98c2ecf20Sopenharmony_ci * met: 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * * Redistributions of source code must retain the above copyright 128c2ecf20Sopenharmony_ci * notice, this list of conditions and the following disclaimer. 138c2ecf20Sopenharmony_ci * * Redistributions in binary form must reproduce the above 148c2ecf20Sopenharmony_ci * copyright notice, this list of conditions and the following disclaimer 158c2ecf20Sopenharmony_ci * in the documentation and/or other materials provided with the 168c2ecf20Sopenharmony_ci * distribution. 178c2ecf20Sopenharmony_ci * 188c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 198c2ecf20Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 208c2ecf20Sopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 218c2ecf20Sopenharmony_ci * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 228c2ecf20Sopenharmony_ci * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 238c2ecf20Sopenharmony_ci * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 248c2ecf20Sopenharmony_ci * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 258c2ecf20Sopenharmony_ci * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 268c2ecf20Sopenharmony_ci * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 278c2ecf20Sopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 288c2ecf20Sopenharmony_ci * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 298c2ecf20Sopenharmony_ci * 308c2ecf20Sopenharmony_ci * This program is free software; you can redistribute it and/or modify it under 318c2ecf20Sopenharmony_ci * the terms of the GNU General Public License version 2 as published by the 328c2ecf20Sopenharmony_ci * Free Software Foundation. This program is dual-licensed; you may select 338c2ecf20Sopenharmony_ci * either version 2 of the GNU General Public License ("GPL") or BSD license 348c2ecf20Sopenharmony_ci * ("BSD"). 358c2ecf20Sopenharmony_ci * 368c2ecf20Sopenharmony_ci * You can contact the author at : 378c2ecf20Sopenharmony_ci * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy 388c2ecf20Sopenharmony_ci */ 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci/* ************************************************************** 418c2ecf20Sopenharmony_ci* Compiler specifics 428c2ecf20Sopenharmony_ci****************************************************************/ 438c2ecf20Sopenharmony_ci#define FORCE_INLINE static __always_inline 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci/* ************************************************************** 468c2ecf20Sopenharmony_ci* Includes 478c2ecf20Sopenharmony_ci****************************************************************/ 488c2ecf20Sopenharmony_ci#include "bitstream.h" 498c2ecf20Sopenharmony_ci#include "fse.h" 508c2ecf20Sopenharmony_ci#include "zstd_internal.h" 518c2ecf20Sopenharmony_ci#include <linux/compiler.h> 528c2ecf20Sopenharmony_ci#include <linux/kernel.h> 538c2ecf20Sopenharmony_ci#include <linux/string.h> /* memcpy, memset */ 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci/* ************************************************************** 568c2ecf20Sopenharmony_ci* Error Management 578c2ecf20Sopenharmony_ci****************************************************************/ 588c2ecf20Sopenharmony_ci#define FSE_isError ERR_isError 598c2ecf20Sopenharmony_ci#define FSE_STATIC_ASSERT(c) \ 608c2ecf20Sopenharmony_ci { \ 618c2ecf20Sopenharmony_ci enum { FSE_static_assert = 1 / (int)(!!(c)) }; \ 628c2ecf20Sopenharmony_ci } /* use only *after* variable declarations */ 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci/* ************************************************************** 658c2ecf20Sopenharmony_ci* Templates 668c2ecf20Sopenharmony_ci****************************************************************/ 678c2ecf20Sopenharmony_ci/* 688c2ecf20Sopenharmony_ci designed to be included 698c2ecf20Sopenharmony_ci for type-specific functions (template emulation in C) 708c2ecf20Sopenharmony_ci Objective is to write these functions only once, for improved maintenance 718c2ecf20Sopenharmony_ci*/ 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci/* safety checks */ 748c2ecf20Sopenharmony_ci#ifndef FSE_FUNCTION_EXTENSION 758c2ecf20Sopenharmony_ci#error "FSE_FUNCTION_EXTENSION must be defined" 768c2ecf20Sopenharmony_ci#endif 778c2ecf20Sopenharmony_ci#ifndef FSE_FUNCTION_TYPE 788c2ecf20Sopenharmony_ci#error "FSE_FUNCTION_TYPE must be defined" 798c2ecf20Sopenharmony_ci#endif 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci/* Function names */ 828c2ecf20Sopenharmony_ci#define FSE_CAT(X, Y) X##Y 838c2ecf20Sopenharmony_ci#define FSE_FUNCTION_NAME(X, Y) FSE_CAT(X, Y) 848c2ecf20Sopenharmony_ci#define FSE_TYPE_NAME(X, Y) FSE_CAT(X, Y) 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci/* Function templates */ 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_cisize_t FSE_buildDTable_wksp(FSE_DTable *dt, const short *normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void *workspace, size_t workspaceSize) 898c2ecf20Sopenharmony_ci{ 908c2ecf20Sopenharmony_ci void *const tdPtr = dt + 1; /* because *dt is unsigned, 32-bits aligned on 32-bits */ 918c2ecf20Sopenharmony_ci FSE_DECODE_TYPE *const tableDecode = (FSE_DECODE_TYPE *)(tdPtr); 928c2ecf20Sopenharmony_ci U16 *symbolNext = (U16 *)workspace; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci U32 const maxSV1 = maxSymbolValue + 1; 958c2ecf20Sopenharmony_ci U32 const tableSize = 1 << tableLog; 968c2ecf20Sopenharmony_ci U32 highThreshold = tableSize - 1; 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci /* Sanity Checks */ 998c2ecf20Sopenharmony_ci if (workspaceSize < sizeof(U16) * (FSE_MAX_SYMBOL_VALUE + 1)) 1008c2ecf20Sopenharmony_ci return ERROR(tableLog_tooLarge); 1018c2ecf20Sopenharmony_ci if (maxSymbolValue > FSE_MAX_SYMBOL_VALUE) 1028c2ecf20Sopenharmony_ci return ERROR(maxSymbolValue_tooLarge); 1038c2ecf20Sopenharmony_ci if (tableLog > FSE_MAX_TABLELOG) 1048c2ecf20Sopenharmony_ci return ERROR(tableLog_tooLarge); 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci /* Init, lay down lowprob symbols */ 1078c2ecf20Sopenharmony_ci { 1088c2ecf20Sopenharmony_ci FSE_DTableHeader DTableH; 1098c2ecf20Sopenharmony_ci DTableH.tableLog = (U16)tableLog; 1108c2ecf20Sopenharmony_ci DTableH.fastMode = 1; 1118c2ecf20Sopenharmony_ci { 1128c2ecf20Sopenharmony_ci S16 const largeLimit = (S16)(1 << (tableLog - 1)); 1138c2ecf20Sopenharmony_ci U32 s; 1148c2ecf20Sopenharmony_ci for (s = 0; s < maxSV1; s++) { 1158c2ecf20Sopenharmony_ci if (normalizedCounter[s] == -1) { 1168c2ecf20Sopenharmony_ci tableDecode[highThreshold--].symbol = (FSE_FUNCTION_TYPE)s; 1178c2ecf20Sopenharmony_ci symbolNext[s] = 1; 1188c2ecf20Sopenharmony_ci } else { 1198c2ecf20Sopenharmony_ci if (normalizedCounter[s] >= largeLimit) 1208c2ecf20Sopenharmony_ci DTableH.fastMode = 0; 1218c2ecf20Sopenharmony_ci symbolNext[s] = normalizedCounter[s]; 1228c2ecf20Sopenharmony_ci } 1238c2ecf20Sopenharmony_ci } 1248c2ecf20Sopenharmony_ci } 1258c2ecf20Sopenharmony_ci memcpy(dt, &DTableH, sizeof(DTableH)); 1268c2ecf20Sopenharmony_ci } 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci /* Spread symbols */ 1298c2ecf20Sopenharmony_ci { 1308c2ecf20Sopenharmony_ci U32 const tableMask = tableSize - 1; 1318c2ecf20Sopenharmony_ci U32 const step = FSE_TABLESTEP(tableSize); 1328c2ecf20Sopenharmony_ci U32 s, position = 0; 1338c2ecf20Sopenharmony_ci for (s = 0; s < maxSV1; s++) { 1348c2ecf20Sopenharmony_ci int i; 1358c2ecf20Sopenharmony_ci for (i = 0; i < normalizedCounter[s]; i++) { 1368c2ecf20Sopenharmony_ci tableDecode[position].symbol = (FSE_FUNCTION_TYPE)s; 1378c2ecf20Sopenharmony_ci position = (position + step) & tableMask; 1388c2ecf20Sopenharmony_ci while (position > highThreshold) 1398c2ecf20Sopenharmony_ci position = (position + step) & tableMask; /* lowprob area */ 1408c2ecf20Sopenharmony_ci } 1418c2ecf20Sopenharmony_ci } 1428c2ecf20Sopenharmony_ci if (position != 0) 1438c2ecf20Sopenharmony_ci return ERROR(GENERIC); /* position must reach all cells once, otherwise normalizedCounter is incorrect */ 1448c2ecf20Sopenharmony_ci } 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci /* Build Decoding table */ 1478c2ecf20Sopenharmony_ci { 1488c2ecf20Sopenharmony_ci U32 u; 1498c2ecf20Sopenharmony_ci for (u = 0; u < tableSize; u++) { 1508c2ecf20Sopenharmony_ci FSE_FUNCTION_TYPE const symbol = (FSE_FUNCTION_TYPE)(tableDecode[u].symbol); 1518c2ecf20Sopenharmony_ci U16 nextState = symbolNext[symbol]++; 1528c2ecf20Sopenharmony_ci tableDecode[u].nbBits = (BYTE)(tableLog - BIT_highbit32((U32)nextState)); 1538c2ecf20Sopenharmony_ci tableDecode[u].newState = (U16)((nextState << tableDecode[u].nbBits) - tableSize); 1548c2ecf20Sopenharmony_ci } 1558c2ecf20Sopenharmony_ci } 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci return 0; 1588c2ecf20Sopenharmony_ci} 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci/*-******************************************************* 1618c2ecf20Sopenharmony_ci* Decompression (Byte symbols) 1628c2ecf20Sopenharmony_ci*********************************************************/ 1638c2ecf20Sopenharmony_cisize_t FSE_buildDTable_rle(FSE_DTable *dt, BYTE symbolValue) 1648c2ecf20Sopenharmony_ci{ 1658c2ecf20Sopenharmony_ci void *ptr = dt; 1668c2ecf20Sopenharmony_ci FSE_DTableHeader *const DTableH = (FSE_DTableHeader *)ptr; 1678c2ecf20Sopenharmony_ci void *dPtr = dt + 1; 1688c2ecf20Sopenharmony_ci FSE_decode_t *const cell = (FSE_decode_t *)dPtr; 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci DTableH->tableLog = 0; 1718c2ecf20Sopenharmony_ci DTableH->fastMode = 0; 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci cell->newState = 0; 1748c2ecf20Sopenharmony_ci cell->symbol = symbolValue; 1758c2ecf20Sopenharmony_ci cell->nbBits = 0; 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci return 0; 1788c2ecf20Sopenharmony_ci} 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_cisize_t FSE_buildDTable_raw(FSE_DTable *dt, unsigned nbBits) 1818c2ecf20Sopenharmony_ci{ 1828c2ecf20Sopenharmony_ci void *ptr = dt; 1838c2ecf20Sopenharmony_ci FSE_DTableHeader *const DTableH = (FSE_DTableHeader *)ptr; 1848c2ecf20Sopenharmony_ci void *dPtr = dt + 1; 1858c2ecf20Sopenharmony_ci FSE_decode_t *const dinfo = (FSE_decode_t *)dPtr; 1868c2ecf20Sopenharmony_ci const unsigned tableSize = 1 << nbBits; 1878c2ecf20Sopenharmony_ci const unsigned tableMask = tableSize - 1; 1888c2ecf20Sopenharmony_ci const unsigned maxSV1 = tableMask + 1; 1898c2ecf20Sopenharmony_ci unsigned s; 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci /* Sanity checks */ 1928c2ecf20Sopenharmony_ci if (nbBits < 1) 1938c2ecf20Sopenharmony_ci return ERROR(GENERIC); /* min size */ 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci /* Build Decoding Table */ 1968c2ecf20Sopenharmony_ci DTableH->tableLog = (U16)nbBits; 1978c2ecf20Sopenharmony_ci DTableH->fastMode = 1; 1988c2ecf20Sopenharmony_ci for (s = 0; s < maxSV1; s++) { 1998c2ecf20Sopenharmony_ci dinfo[s].newState = 0; 2008c2ecf20Sopenharmony_ci dinfo[s].symbol = (BYTE)s; 2018c2ecf20Sopenharmony_ci dinfo[s].nbBits = (BYTE)nbBits; 2028c2ecf20Sopenharmony_ci } 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci return 0; 2058c2ecf20Sopenharmony_ci} 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ciFORCE_INLINE size_t FSE_decompress_usingDTable_generic(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize, const FSE_DTable *dt, 2088c2ecf20Sopenharmony_ci const unsigned fast) 2098c2ecf20Sopenharmony_ci{ 2108c2ecf20Sopenharmony_ci BYTE *const ostart = (BYTE *)dst; 2118c2ecf20Sopenharmony_ci BYTE *op = ostart; 2128c2ecf20Sopenharmony_ci BYTE *const omax = op + maxDstSize; 2138c2ecf20Sopenharmony_ci BYTE *const olimit = omax - 3; 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci BIT_DStream_t bitD; 2168c2ecf20Sopenharmony_ci FSE_DState_t state1; 2178c2ecf20Sopenharmony_ci FSE_DState_t state2; 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci /* Init */ 2208c2ecf20Sopenharmony_ci CHECK_F(BIT_initDStream(&bitD, cSrc, cSrcSize)); 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci FSE_initDState(&state1, &bitD, dt); 2238c2ecf20Sopenharmony_ci FSE_initDState(&state2, &bitD, dt); 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci#define FSE_GETSYMBOL(statePtr) fast ? FSE_decodeSymbolFast(statePtr, &bitD) : FSE_decodeSymbol(statePtr, &bitD) 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci /* 4 symbols per loop */ 2288c2ecf20Sopenharmony_ci for (; (BIT_reloadDStream(&bitD) == BIT_DStream_unfinished) & (op < olimit); op += 4) { 2298c2ecf20Sopenharmony_ci op[0] = FSE_GETSYMBOL(&state1); 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci if (FSE_MAX_TABLELOG * 2 + 7 > sizeof(bitD.bitContainer) * 8) /* This test must be static */ 2328c2ecf20Sopenharmony_ci BIT_reloadDStream(&bitD); 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci op[1] = FSE_GETSYMBOL(&state2); 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci if (FSE_MAX_TABLELOG * 4 + 7 > sizeof(bitD.bitContainer) * 8) /* This test must be static */ 2378c2ecf20Sopenharmony_ci { 2388c2ecf20Sopenharmony_ci if (BIT_reloadDStream(&bitD) > BIT_DStream_unfinished) { 2398c2ecf20Sopenharmony_ci op += 2; 2408c2ecf20Sopenharmony_ci break; 2418c2ecf20Sopenharmony_ci } 2428c2ecf20Sopenharmony_ci } 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci op[2] = FSE_GETSYMBOL(&state1); 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci if (FSE_MAX_TABLELOG * 2 + 7 > sizeof(bitD.bitContainer) * 8) /* This test must be static */ 2478c2ecf20Sopenharmony_ci BIT_reloadDStream(&bitD); 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci op[3] = FSE_GETSYMBOL(&state2); 2508c2ecf20Sopenharmony_ci } 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci /* tail */ 2538c2ecf20Sopenharmony_ci /* note : BIT_reloadDStream(&bitD) >= FSE_DStream_partiallyFilled; Ends at exactly BIT_DStream_completed */ 2548c2ecf20Sopenharmony_ci while (1) { 2558c2ecf20Sopenharmony_ci if (op > (omax - 2)) 2568c2ecf20Sopenharmony_ci return ERROR(dstSize_tooSmall); 2578c2ecf20Sopenharmony_ci *op++ = FSE_GETSYMBOL(&state1); 2588c2ecf20Sopenharmony_ci if (BIT_reloadDStream(&bitD) == BIT_DStream_overflow) { 2598c2ecf20Sopenharmony_ci *op++ = FSE_GETSYMBOL(&state2); 2608c2ecf20Sopenharmony_ci break; 2618c2ecf20Sopenharmony_ci } 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci if (op > (omax - 2)) 2648c2ecf20Sopenharmony_ci return ERROR(dstSize_tooSmall); 2658c2ecf20Sopenharmony_ci *op++ = FSE_GETSYMBOL(&state2); 2668c2ecf20Sopenharmony_ci if (BIT_reloadDStream(&bitD) == BIT_DStream_overflow) { 2678c2ecf20Sopenharmony_ci *op++ = FSE_GETSYMBOL(&state1); 2688c2ecf20Sopenharmony_ci break; 2698c2ecf20Sopenharmony_ci } 2708c2ecf20Sopenharmony_ci } 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci return op - ostart; 2738c2ecf20Sopenharmony_ci} 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_cisize_t FSE_decompress_usingDTable(void *dst, size_t originalSize, const void *cSrc, size_t cSrcSize, const FSE_DTable *dt) 2768c2ecf20Sopenharmony_ci{ 2778c2ecf20Sopenharmony_ci const void *ptr = dt; 2788c2ecf20Sopenharmony_ci const FSE_DTableHeader *DTableH = (const FSE_DTableHeader *)ptr; 2798c2ecf20Sopenharmony_ci const U32 fastMode = DTableH->fastMode; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci /* select fast mode (static) */ 2828c2ecf20Sopenharmony_ci if (fastMode) 2838c2ecf20Sopenharmony_ci return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1); 2848c2ecf20Sopenharmony_ci return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0); 2858c2ecf20Sopenharmony_ci} 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_cisize_t FSE_decompress_wksp(void *dst, size_t dstCapacity, const void *cSrc, size_t cSrcSize, unsigned maxLog, void *workspace, size_t workspaceSize) 2888c2ecf20Sopenharmony_ci{ 2898c2ecf20Sopenharmony_ci const BYTE *const istart = (const BYTE *)cSrc; 2908c2ecf20Sopenharmony_ci const BYTE *ip = istart; 2918c2ecf20Sopenharmony_ci unsigned tableLog; 2928c2ecf20Sopenharmony_ci unsigned maxSymbolValue = FSE_MAX_SYMBOL_VALUE; 2938c2ecf20Sopenharmony_ci size_t NCountLength; 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci FSE_DTable *dt; 2968c2ecf20Sopenharmony_ci short *counting; 2978c2ecf20Sopenharmony_ci size_t spaceUsed32 = 0; 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci FSE_STATIC_ASSERT(sizeof(FSE_DTable) == sizeof(U32)); 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci dt = (FSE_DTable *)((U32 *)workspace + spaceUsed32); 3028c2ecf20Sopenharmony_ci spaceUsed32 += FSE_DTABLE_SIZE_U32(maxLog); 3038c2ecf20Sopenharmony_ci counting = (short *)((U32 *)workspace + spaceUsed32); 3048c2ecf20Sopenharmony_ci spaceUsed32 += ALIGN(sizeof(short) * (FSE_MAX_SYMBOL_VALUE + 1), sizeof(U32)) >> 2; 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci if ((spaceUsed32 << 2) > workspaceSize) 3078c2ecf20Sopenharmony_ci return ERROR(tableLog_tooLarge); 3088c2ecf20Sopenharmony_ci workspace = (U32 *)workspace + spaceUsed32; 3098c2ecf20Sopenharmony_ci workspaceSize -= (spaceUsed32 << 2); 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci /* normal FSE decoding mode */ 3128c2ecf20Sopenharmony_ci NCountLength = FSE_readNCount(counting, &maxSymbolValue, &tableLog, istart, cSrcSize); 3138c2ecf20Sopenharmony_ci if (FSE_isError(NCountLength)) 3148c2ecf20Sopenharmony_ci return NCountLength; 3158c2ecf20Sopenharmony_ci // if (NCountLength >= cSrcSize) return ERROR(srcSize_wrong); /* too small input size; supposed to be already checked in NCountLength, only remaining 3168c2ecf20Sopenharmony_ci // case : NCountLength==cSrcSize */ 3178c2ecf20Sopenharmony_ci if (tableLog > maxLog) 3188c2ecf20Sopenharmony_ci return ERROR(tableLog_tooLarge); 3198c2ecf20Sopenharmony_ci ip += NCountLength; 3208c2ecf20Sopenharmony_ci cSrcSize -= NCountLength; 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci CHECK_F(FSE_buildDTable_wksp(dt, counting, maxSymbolValue, tableLog, workspace, workspaceSize)); 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci return FSE_decompress_usingDTable(dst, dstCapacity, ip, cSrcSize, dt); /* always return, even if it is an error code */ 3258c2ecf20Sopenharmony_ci} 326