2 * Common functions of New Generation Entropy library
3 * Copyright (C) 2016, Yann Collet.
5 * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following disclaimer
15 * in the documentation and/or other materials provided with the
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 * This program is free software; you can redistribute it and/or modify it under
31 * the terms of the GNU General Public License version 2 as published by the
32 * Free Software Foundation. This program is dual-licensed; you may select
33 * either version 2 of the GNU General Public License ("GPL") or BSD license
36 * You can contact the author at :
37 * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
40 /* *************************************
42 ***************************************/
43 #include "error_private.h" /* ERR_*, ERROR */
49 unsigned FSE_versionNumber(void) { return FSE_VERSION_NUMBER
; }
51 /*=== Error Management ===*/
52 unsigned FSE_isError(size_t code
) { return ERR_isError(code
); }
54 unsigned HUF_isError(size_t code
) { return ERR_isError(code
); }
56 /*-**************************************************************
57 * FSE NCount encoding-decoding
58 ****************************************************************/
59 size_t FSE_readNCount(short *normalizedCounter
, unsigned *maxSVPtr
, unsigned *tableLogPtr
, const void *headerBuffer
, size_t hbSize
)
61 const BYTE
*const istart
= (const BYTE
*)headerBuffer
;
62 const BYTE
*const iend
= istart
+ hbSize
;
63 const BYTE
*ip
= istart
;
73 return ERROR(srcSize_wrong
);
74 bitStream
= ZSTD_readLE32(ip
);
75 nbBits
= (bitStream
& 0xF) + FSE_MIN_TABLELOG
; /* extract tableLog */
76 if (nbBits
> FSE_TABLELOG_ABSOLUTE_MAX
)
77 return ERROR(tableLog_tooLarge
);
80 *tableLogPtr
= nbBits
;
81 remaining
= (1 << nbBits
) + 1;
82 threshold
= 1 << nbBits
;
85 while ((remaining
> 1) & (charnum
<= *maxSVPtr
)) {
87 unsigned n0
= charnum
;
88 while ((bitStream
& 0xFFFF) == 0xFFFF) {
92 bitStream
= ZSTD_readLE32(ip
) >> bitCount
;
98 while ((bitStream
& 3) == 3) {
106 return ERROR(maxSymbolValue_tooSmall
);
108 normalizedCounter
[charnum
++] = 0;
109 if ((ip
<= iend
- 7) || (ip
+ (bitCount
>> 3) <= iend
- 4)) {
112 bitStream
= ZSTD_readLE32(ip
) >> bitCount
;
118 int const max
= (2 * threshold
- 1) - remaining
;
121 if ((bitStream
& (threshold
- 1)) < (U32
)max
) {
122 count
= bitStream
& (threshold
- 1);
123 bitCount
+= nbBits
- 1;
125 count
= bitStream
& (2 * threshold
- 1);
126 if (count
>= threshold
)
131 count
--; /* extra accuracy */
132 remaining
-= count
< 0 ? -count
: count
; /* -1 means +1 */
133 normalizedCounter
[charnum
++] = (short)count
;
135 while (remaining
< threshold
) {
140 if ((ip
<= iend
- 7) || (ip
+ (bitCount
>> 3) <= iend
- 4)) {
144 bitCount
-= (int)(8 * (iend
- 4 - ip
));
147 bitStream
= ZSTD_readLE32(ip
) >> (bitCount
& 31);
149 } /* while ((remaining>1) & (charnum<=*maxSVPtr)) */
151 return ERROR(corruption_detected
);
153 return ERROR(corruption_detected
);
154 *maxSVPtr
= charnum
- 1;
156 ip
+= (bitCount
+ 7) >> 3;
160 /*! HUF_readStats() :
161 Read compact Huffman tree, saved by HUF_writeCTable().
162 `huffWeight` is destination buffer.
163 `rankStats` is assumed to be a table of at least HUF_TABLELOG_MAX U32.
164 @return : size read from `src` , or an error Code .
165 Note : Needed by HUF_readCTable() and HUF_readDTableX?() .
167 size_t HUF_readStats_wksp(BYTE
*huffWeight
, size_t hwSize
, U32
*rankStats
, U32
*nbSymbolsPtr
, U32
*tableLogPtr
, const void *src
, size_t srcSize
, void *workspace
, size_t workspaceSize
)
170 const BYTE
*ip
= (const BYTE
*)src
;
175 return ERROR(srcSize_wrong
);
177 /* memset(huffWeight, 0, hwSize); */ /* is not necessary, even though some analyzer complain ... */
179 if (iSize
>= 128) { /* special header */
181 iSize
= ((oSize
+ 1) / 2);
182 if (iSize
+ 1 > srcSize
)
183 return ERROR(srcSize_wrong
);
185 return ERROR(corruption_detected
);
189 for (n
= 0; n
< oSize
; n
+= 2) {
190 huffWeight
[n
] = ip
[n
/ 2] >> 4;
191 huffWeight
[n
+ 1] = ip
[n
/ 2] & 15;
194 } else { /* header compressed with FSE (normal case) */
195 if (iSize
+ 1 > srcSize
)
196 return ERROR(srcSize_wrong
);
197 oSize
= FSE_decompress_wksp(huffWeight
, hwSize
- 1, ip
+ 1, iSize
, 6, workspace
, workspaceSize
); /* max (hwSize-1) values decoded, as last one is implied */
198 if (FSE_isError(oSize
))
202 /* collect weight stats */
203 memset(rankStats
, 0, (HUF_TABLELOG_MAX
+ 1) * sizeof(U32
));
207 for (n
= 0; n
< oSize
; n
++) {
208 if (huffWeight
[n
] >= HUF_TABLELOG_MAX
)
209 return ERROR(corruption_detected
);
210 rankStats
[huffWeight
[n
]]++;
211 weightTotal
+= (1 << huffWeight
[n
]) >> 1;
214 if (weightTotal
== 0)
215 return ERROR(corruption_detected
);
217 /* get last non-null symbol weight (implied, total must be 2^n) */
219 U32
const tableLog
= BIT_highbit32(weightTotal
) + 1;
220 if (tableLog
> HUF_TABLELOG_MAX
)
221 return ERROR(corruption_detected
);
222 *tableLogPtr
= tableLog
;
223 /* determine last weight */
225 U32
const total
= 1 << tableLog
;
226 U32
const rest
= total
- weightTotal
;
227 U32
const verif
= 1 << BIT_highbit32(rest
);
228 U32
const lastWeight
= BIT_highbit32(rest
) + 1;
230 return ERROR(corruption_detected
); /* last value must be a clean power of 2 */
231 huffWeight
[oSize
] = (BYTE
)lastWeight
;
232 rankStats
[lastWeight
]++;
236 /* check tree construction validity */
237 if ((rankStats
[1] < 2) || (rankStats
[1] & 1))
238 return ERROR(corruption_detected
); /* by construction : at least 2 elts of rank 1, must be even */
241 *nbSymbolsPtr
= (U32
)(oSize
+ 1);