extzstd 0.0.1.CONCEPT → 0.0.2.CONCEPT
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +27 -15
- data/Rakefile +19 -8
- data/contrib/zstd/Makefile +5 -4
- data/contrib/zstd/fse.c +1528 -583
- data/contrib/zstd/fse.h +167 -227
- data/contrib/zstd/fse_static.h +197 -23
- data/contrib/zstd/zstd.c +594 -627
- data/contrib/zstd/zstd.h +7 -16
- data/contrib/zstd/zstd_static.h +24 -15
- data/ext/extconf.rb +6 -1
- data/ext/extzstd-stream.c +238 -59
- data/ext/extzstd.c +77 -18
- data/ext/extzstd.h +29 -2
- data/gemstub.rb +3 -3
- data/lib/extzstd.rb +127 -1
- data/lib/extzstd/version.rb +1 -3
- metadata +13 -7
data/contrib/zstd/fse.h
CHANGED
@@ -42,7 +42,7 @@ extern "C" {
|
|
42
42
|
/******************************************
|
43
43
|
* Includes
|
44
44
|
******************************************/
|
45
|
-
#include <stddef.h>
|
45
|
+
#include <stddef.h> /* size_t, ptrdiff_t */
|
46
46
|
|
47
47
|
|
48
48
|
/******************************************
|
@@ -50,37 +50,52 @@ extern "C" {
|
|
50
50
|
******************************************/
|
51
51
|
size_t FSE_compress(void* dst, size_t maxDstSize,
|
52
52
|
const void* src, size_t srcSize);
|
53
|
-
size_t FSE_decompress(void* dst,
|
53
|
+
size_t FSE_decompress(void* dst, size_t maxDstSize,
|
54
54
|
const void* cSrc, size_t cSrcSize);
|
55
55
|
/*
|
56
56
|
FSE_compress():
|
57
57
|
Compress content of buffer 'src', of size 'srcSize', into destination buffer 'dst'.
|
58
|
-
'dst' buffer must be already allocated
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
if
|
63
|
-
if FSE_isError(result), it's an error code.
|
58
|
+
'dst' buffer must be already allocated. Compression runs faster is maxDstSize >= FSE_compressBound(srcSize)
|
59
|
+
return : size of compressed data (<= maxDstSize)
|
60
|
+
Special values : if return == 0, srcData is not compressible => Nothing is stored within dst !!!
|
61
|
+
if return == 1, srcData is a single byte symbol * srcSize times. Use RLE compression instead.
|
62
|
+
if FSE_isError(return), compression failed (more details using FSE_getErrorName())
|
64
63
|
|
65
64
|
FSE_decompress():
|
66
65
|
Decompress FSE data from buffer 'cSrc', of size 'cSrcSize',
|
67
66
|
into already allocated destination buffer 'dst', of size 'maxDstSize'.
|
68
|
-
** Important ** : This function doesn't decompress uncompressed nor RLE data !
|
69
67
|
return : size of regenerated data (<= maxDstSize)
|
70
68
|
or an error code, which can be tested using FSE_isError()
|
69
|
+
|
70
|
+
** Important ** : FSE_decompress() doesn't decompress non-compressible nor RLE data !!!
|
71
|
+
Why ? : making this distinction requires a header.
|
72
|
+
Header management is intentionally delegated to the user layer, which can better manage special cases.
|
71
73
|
*/
|
72
74
|
|
73
75
|
|
74
|
-
|
75
|
-
|
76
|
+
/******************************************
|
77
|
+
* Huff0 simple functions
|
78
|
+
******************************************/
|
79
|
+
size_t HUF_compress(void* dst, size_t maxDstSize,
|
80
|
+
const void* src, size_t srcSize);
|
81
|
+
size_t HUF_decompress(void* dst, size_t maxDstSize,
|
82
|
+
const void* cSrc, size_t cSrcSize);
|
76
83
|
/*
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
return : size of
|
84
|
+
HUF_compress():
|
85
|
+
Compress content of buffer 'src', of size 'srcSize', into destination buffer 'dst'.
|
86
|
+
'dst' buffer must be already allocated. Compression runs faster is maxDstSize >= HUF_compressBound(srcSize)
|
87
|
+
return : size of compressed data (<= maxDstSize)
|
88
|
+
Special values : if return == 0, srcData is not compressible => Nothing is stored within dst !!!
|
89
|
+
if return == 1, srcData is a single byte symbol * srcSize times. Use RLE compression.
|
90
|
+
if FSE_isError(return), compression failed (more details using FSE_getErrorName())
|
91
|
+
|
92
|
+
HUF_decompress():
|
93
|
+
Decompress Huff0 data from buffer 'cSrc', of size 'cSrcSize',
|
94
|
+
into already allocated destination buffer 'dst', of size 'maxDstSize'.
|
95
|
+
return : size of regenerated data (<= maxDstSize)
|
81
96
|
or an error code, which can be tested using FSE_isError()
|
82
97
|
|
83
|
-
|
98
|
+
** Important ** : HUF_decompress() doesn't decompress non-compressible nor RLE data !!!
|
84
99
|
*/
|
85
100
|
|
86
101
|
|
@@ -102,59 +117,115 @@ FSE_compress2():
|
|
102
117
|
Same as FSE_compress(), but allows the selection of 'maxSymbolValue' and 'tableLog'
|
103
118
|
Both parameters can be defined as '0' to mean : use default value
|
104
119
|
return : size of compressed data
|
105
|
-
|
120
|
+
Special values : if return == 0, srcData is not compressible => Nothing is stored within cSrc !!!
|
121
|
+
if return == 1, srcData is a single byte symbol * srcSize times. Use RLE compression.
|
122
|
+
if FSE_isError(return), it's an error code.
|
106
123
|
*/
|
107
124
|
size_t FSE_compress2 (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog);
|
108
125
|
|
126
|
+
size_t HUF_compress2 (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog);
|
127
|
+
|
109
128
|
|
110
129
|
/******************************************
|
111
|
-
|
130
|
+
* FSE detailed API
|
112
131
|
******************************************/
|
113
132
|
/*
|
114
|
-
|
133
|
+
FSE_compress() does the following:
|
115
134
|
1. count symbol occurrence from source[] into table count[]
|
116
135
|
2. normalize counters so that sum(count[]) == Power_of_2 (2^tableLog)
|
117
|
-
3. save normalized counters to memory buffer using
|
136
|
+
3. save normalized counters to memory buffer using writeNCount()
|
118
137
|
4. build encoding table 'CTable' from normalized counters
|
119
|
-
5. encode the data stream using encoding table
|
138
|
+
5. encode the data stream using encoding table 'CTable'
|
120
139
|
|
121
|
-
|
122
|
-
1. read normalized counters with
|
140
|
+
FSE_decompress() does the following:
|
141
|
+
1. read normalized counters with readNCount()
|
123
142
|
2. build decoding table 'DTable' from normalized counters
|
124
|
-
3. decode the data stream using decoding table
|
143
|
+
3. decode the data stream using decoding table 'DTable'
|
125
144
|
|
126
|
-
The following API allows
|
145
|
+
The following API allows targeting specific sub-functions for advanced tasks.
|
146
|
+
For example, it's possible to compress several blocks using the same 'CTable',
|
147
|
+
or to save and provide normalized distribution using external method.
|
127
148
|
*/
|
128
149
|
|
129
150
|
/* *** COMPRESSION *** */
|
130
151
|
|
131
|
-
|
152
|
+
/*
|
153
|
+
FSE_count():
|
154
|
+
Provides the precise count of each symbol within a table 'count'
|
155
|
+
'count' is a table of unsigned int, of minimum size (maxSymbolValuePtr[0]+1).
|
156
|
+
maxSymbolValuePtr[0] will be updated if detected smaller than initially expected
|
157
|
+
return : the count of the most frequent symbol (which is not identified)
|
158
|
+
if return == srcSize, there is only one symbol.
|
159
|
+
if FSE_isError(return), it's an error code. */
|
160
|
+
size_t FSE_count(unsigned* count, unsigned* maxSymbolValuePtr, const unsigned char* src, size_t srcSize);
|
132
161
|
|
162
|
+
/*
|
163
|
+
FSE_optimalTableLog():
|
164
|
+
dynamically downsize 'tableLog' when conditions are met.
|
165
|
+
It saves CPU time, by using smaller tables, while preserving or even improving compression ratio.
|
166
|
+
return : recommended tableLog (necessarily <= initial 'tableLog') */
|
133
167
|
unsigned FSE_optimalTableLog(unsigned tableLog, size_t srcSize, unsigned maxSymbolValue);
|
134
|
-
size_t FSE_normalizeCount(short* normalizedCounter, unsigned tableLog, const unsigned* count, size_t total, unsigned maxSymbolValue);
|
135
168
|
|
136
|
-
|
137
|
-
|
169
|
+
/*
|
170
|
+
FSE_normalizeCount():
|
171
|
+
normalize counters so that sum(count[]) == Power_of_2 (2^tableLog)
|
172
|
+
'normalizedCounter' is a table of short, of minimum size (maxSymbolValue+1).
|
173
|
+
return : tableLog,
|
174
|
+
or an errorCode, which can be tested using FSE_isError() */
|
175
|
+
size_t FSE_normalizeCount(short* normalizedCounter, unsigned tableLog, const unsigned* count, size_t srcSize, unsigned maxSymbolValue);
|
176
|
+
|
177
|
+
/*
|
178
|
+
FSE_NCountWriteBound():
|
179
|
+
Provides the maximum possible size of an FSE normalized table, given 'maxSymbolValue' and 'tableLog'
|
180
|
+
Typically useful for allocation purpose. */
|
181
|
+
size_t FSE_NCountWriteBound(unsigned maxSymbolValue, unsigned tableLog);
|
182
|
+
|
183
|
+
/*
|
184
|
+
FSE_writeNCount():
|
185
|
+
Compactly save 'normalizedCounter' into 'buffer'.
|
186
|
+
return : size of the compressed table
|
187
|
+
or an errorCode, which can be tested using FSE_isError() */
|
188
|
+
size_t FSE_writeNCount (void* buffer, size_t bufferSize, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog);
|
189
|
+
|
190
|
+
|
191
|
+
/*
|
192
|
+
Constructor and Destructor of type FSE_CTable
|
193
|
+
Note that its size depends on 'tableLog' and 'maxSymbolValue' */
|
194
|
+
typedef unsigned FSE_CTable; /* don't allocate that. It's just a way to be more restrictive than void* */
|
195
|
+
FSE_CTable* FSE_createCTable (unsigned tableLog, unsigned maxSymbolValue);
|
196
|
+
void FSE_freeCTable (FSE_CTable* ct);
|
138
197
|
|
139
|
-
|
140
|
-
|
141
|
-
|
198
|
+
/*
|
199
|
+
FSE_buildCTable():
|
200
|
+
Builds 'ct', which must be already allocated, using FSE_createCTable()
|
201
|
+
return : 0
|
202
|
+
or an errorCode, which can be tested using FSE_isError() */
|
203
|
+
size_t FSE_buildCTable(FSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog);
|
142
204
|
|
143
|
-
|
205
|
+
/*
|
206
|
+
FSE_compress_usingCTable():
|
207
|
+
Compress 'src' using 'ct' into 'dst' which must be already allocated
|
208
|
+
return : size of compressed data (<= maxDstSize)
|
209
|
+
or 0 if compressed data could not fit into 'dst'
|
210
|
+
or an errorCode, which can be tested using FSE_isError() */
|
211
|
+
size_t FSE_compress_usingCTable (void* dst, size_t maxDstSize, const void* src, size_t srcSize, const FSE_CTable* ct);
|
144
212
|
|
145
213
|
/*
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
214
|
+
Tutorial :
|
215
|
+
----------
|
216
|
+
The first step is to count all symbols. FSE_count() does this job very fast.
|
217
|
+
Result will be saved into 'count', a table of unsigned int, which must be already allocated, and have 'maxSymbolValuePtr[0]+1' cells.
|
218
|
+
'src' is a table of bytes of size 'srcSize'. All values within 'src' MUST be <= maxSymbolValuePtr[0]
|
219
|
+
maxSymbolValuePtr[0] will be updated, with its real value (necessarily <= original value)
|
150
220
|
FSE_count() will return the number of occurrence of the most frequent symbol.
|
221
|
+
This can be used to know if there is a single symbol within 'src', and to quickly evaluate its compressibility.
|
151
222
|
If there is an error, the function will return an ErrorCode (which can be tested using FSE_isError()).
|
152
223
|
|
153
224
|
The next step is to normalize the frequencies.
|
154
225
|
FSE_normalizeCount() will ensure that sum of frequencies is == 2 ^'tableLog'.
|
155
|
-
It also guarantees a minimum of 1 to any Symbol
|
156
|
-
You can use
|
157
|
-
If you are unsure of which tableLog value to use, you can
|
226
|
+
It also guarantees a minimum of 1 to any Symbol with frequency >= 1.
|
227
|
+
You can use 'tableLog'==0 to mean "use default tableLog value".
|
228
|
+
If you are unsure of which tableLog value to use, you can ask FSE_optimalTableLog(),
|
158
229
|
which will provide the optimal valid tableLog given sourceSize, maxSymbolValue, and a user-defined maximum (0 means "default").
|
159
230
|
|
160
231
|
The result of FSE_normalizeCount() will be saved into a table,
|
@@ -162,216 +233,85 @@ called 'normalizedCounter', which is a table of signed short.
|
|
162
233
|
'normalizedCounter' must be already allocated, and have at least 'maxSymbolValue+1' cells.
|
163
234
|
The return value is tableLog if everything proceeded as expected.
|
164
235
|
It is 0 if there is a single symbol within distribution.
|
165
|
-
If there is an error(
|
236
|
+
If there is an error (ex: invalid tableLog value), the function will return an ErrorCode (which can be tested using FSE_isError()).
|
166
237
|
|
167
|
-
'normalizedCounter' can be saved in a compact manner to a memory area using
|
168
|
-
'
|
238
|
+
'normalizedCounter' can be saved in a compact manner to a memory area using FSE_writeNCount().
|
239
|
+
'buffer' must be already allocated.
|
169
240
|
For guaranteed success, buffer size must be at least FSE_headerBound().
|
170
|
-
The result of the function is the number of bytes written into '
|
171
|
-
If there is an error, the function will return an ErrorCode (which can be tested using FSE_isError()
|
241
|
+
The result of the function is the number of bytes written into 'buffer'.
|
242
|
+
If there is an error, the function will return an ErrorCode (which can be tested using FSE_isError(); ex : buffer size too small).
|
172
243
|
|
173
|
-
'normalizedCounter' can then be used to create the compression
|
174
|
-
The space required by 'CTable' must be already allocated
|
175
|
-
'CTable' must be aligned of 4 bytes boundaries.
|
244
|
+
'normalizedCounter' can then be used to create the compression table 'CTable'.
|
245
|
+
The space required by 'CTable' must be already allocated, using FSE_createCTable().
|
176
246
|
You can then use FSE_buildCTable() to fill 'CTable'.
|
177
|
-
|
247
|
+
If there is an error, both functions will return an ErrorCode (which can be tested using FSE_isError()).
|
178
248
|
|
179
|
-
'CTable' can then be used to compress '
|
180
|
-
Similar to FSE_count(), the convention is that '
|
181
|
-
The function returns the size of compressed data (without header),
|
249
|
+
'CTable' can then be used to compress 'src', with FSE_compress_usingCTable().
|
250
|
+
Similar to FSE_count(), the convention is that 'src' is assumed to be a table of char of size 'srcSize'
|
251
|
+
The function returns the size of compressed data (without header), necessarily <= maxDstSize.
|
252
|
+
If it returns '0', compressed data could not fit into 'dst'.
|
253
|
+
If there is an error, the function will return an ErrorCode (which can be tested using FSE_isError()).
|
182
254
|
*/
|
183
255
|
|
184
256
|
|
185
257
|
/* *** DECOMPRESSION *** */
|
186
258
|
|
187
|
-
|
259
|
+
/*
|
260
|
+
FSE_readNCount():
|
261
|
+
Read compactly saved 'normalizedCounter' from 'rBuffer'.
|
262
|
+
return : size read from 'rBuffer'
|
263
|
+
or an errorCode, which can be tested using FSE_isError()
|
264
|
+
maxSymbolValuePtr[0] and tableLogPtr[0] will also be updated with their respective values */
|
265
|
+
size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSymbolValuePtr, unsigned* tableLogPtr, const void* rBuffer, size_t rBuffSize);
|
188
266
|
|
189
|
-
|
190
|
-
|
191
|
-
|
267
|
+
/*
|
268
|
+
Constructor and Destructor of type FSE_DTable
|
269
|
+
Note that its size depends on 'tableLog' */
|
270
|
+
typedef unsigned FSE_DTable; /* don't allocate that. It's just a way to be more restrictive than void* */
|
271
|
+
FSE_DTable* FSE_createDTable(unsigned tableLog);
|
272
|
+
void FSE_freeDTable(FSE_DTable* dt);
|
192
273
|
|
193
|
-
|
274
|
+
/*
|
275
|
+
FSE_buildDTable():
|
276
|
+
Builds 'dt', which must be already allocated, using FSE_createDTable()
|
277
|
+
return : 0,
|
278
|
+
or an errorCode, which can be tested using FSE_isError() */
|
279
|
+
size_t FSE_buildDTable (FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog);
|
194
280
|
|
195
281
|
/*
|
196
|
-
|
282
|
+
FSE_decompress_usingDTable():
|
283
|
+
Decompress compressed source 'cSrc' of size 'cSrcSize' using 'dt'
|
284
|
+
into 'dst' which must be already allocated.
|
285
|
+
return : size of regenerated data (necessarily <= maxDstSize)
|
286
|
+
or an errorCode, which can be tested using FSE_isError() */
|
287
|
+
size_t FSE_decompress_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const FSE_DTable* dt);
|
288
|
+
|
289
|
+
/*
|
290
|
+
Tutorial :
|
291
|
+
----------
|
292
|
+
(Note : these functions only decompress FSE-compressed blocks.
|
293
|
+
If block is uncompressed, use memcpy() instead
|
294
|
+
If block is a single repeated byte, use memset() instead )
|
197
295
|
|
198
296
|
The first step is to obtain the normalized frequencies of symbols.
|
199
|
-
This can be performed by
|
200
|
-
'normalizedCounter' must be already allocated, and have at least '
|
297
|
+
This can be performed by FSE_readNCount() if it was saved using FSE_writeNCount().
|
298
|
+
'normalizedCounter' must be already allocated, and have at least 'maxSymbolValuePtr[0]+1' cells of signed short.
|
201
299
|
In practice, that means it's necessary to know 'maxSymbolValue' beforehand,
|
202
300
|
or size the table to handle worst case situations (typically 256).
|
203
|
-
|
204
|
-
The result of
|
205
|
-
|
206
|
-
return 2 : there is only a single symbol value. The value is provided into the second byte of header.
|
207
|
-
return 1 : data is uncompressed
|
301
|
+
FSE_readNCount() will provide 'tableLog' and 'maxSymbolValue'.
|
302
|
+
The result of FSE_readNCount() is the number of bytes read from 'rBuffer'.
|
303
|
+
Note that 'rBufferSize' must be at least 4 bytes, even if useful information is less than that.
|
208
304
|
If there is an error, the function will return an error code, which can be tested using FSE_isError().
|
209
305
|
|
210
|
-
The next step is to
|
306
|
+
The next step is to build the decompression tables 'FSE_DTable' from 'normalizedCounter'.
|
211
307
|
This is performed by the function FSE_buildDTable().
|
212
|
-
The space required by '
|
213
|
-
One can create a DTable using FSE_createDTable().
|
214
|
-
The function will return 1 if DTable is compatible with fastMode, 0 otherwise.
|
308
|
+
The space required by 'FSE_DTable' must be already allocated using FSE_createDTable().
|
215
309
|
If there is an error, the function will return an error code, which can be tested using FSE_isError().
|
216
310
|
|
217
|
-
'
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
If there is an error, the function will return an error code, which can be tested using FSE_isError().
|
222
|
-
*/
|
223
|
-
|
224
|
-
|
225
|
-
/******************************************
|
226
|
-
* FSE streaming compression API
|
227
|
-
******************************************/
|
228
|
-
typedef struct
|
229
|
-
{
|
230
|
-
size_t bitContainer;
|
231
|
-
int bitPos;
|
232
|
-
char* startPtr;
|
233
|
-
char* ptr;
|
234
|
-
} FSE_CStream_t;
|
235
|
-
|
236
|
-
typedef struct
|
237
|
-
{
|
238
|
-
ptrdiff_t value;
|
239
|
-
const void* stateTable;
|
240
|
-
const void* symbolTT;
|
241
|
-
unsigned stateLog;
|
242
|
-
} FSE_CState_t;
|
243
|
-
|
244
|
-
void FSE_initCStream(FSE_CStream_t* bitC, void* dstBuffer);
|
245
|
-
void FSE_initCState(FSE_CState_t* CStatePtr, const void* CTable);
|
246
|
-
|
247
|
-
void FSE_encodeByte(FSE_CStream_t* bitC, FSE_CState_t* CStatePtr, unsigned char symbol);
|
248
|
-
void FSE_addBits(FSE_CStream_t* bitC, size_t value, unsigned nbBits);
|
249
|
-
void FSE_flushBits(FSE_CStream_t* bitC);
|
250
|
-
|
251
|
-
void FSE_flushCState(FSE_CStream_t* bitC, const FSE_CState_t* CStatePtr);
|
252
|
-
size_t FSE_closeCStream(FSE_CStream_t* bitC);
|
253
|
-
|
254
|
-
/*
|
255
|
-
These functions are inner components of FSE_compress_usingCTable().
|
256
|
-
They allow creation of custom streams, mixing multiple tables and bit sources.
|
257
|
-
|
258
|
-
A key property to keep in mind is that encoding and decoding are done **in reverse direction**.
|
259
|
-
So the first symbol you will encode is the last you will decode, like a lifo stack.
|
260
|
-
|
261
|
-
You will need a few variables to track your CStream. They are :
|
262
|
-
|
263
|
-
void* CTable; // Provided by FSE_buildCTable()
|
264
|
-
FSE_CStream_t bitC; // bitStream tracking structure
|
265
|
-
FSE_CState_t state; // State tracking structure
|
266
|
-
|
267
|
-
|
268
|
-
The first thing to do is to init the bitStream, and the state.
|
269
|
-
FSE_initCStream(&bitC, dstBuffer);
|
270
|
-
FSE_initState(&state, CTable);
|
271
|
-
|
272
|
-
You can then encode your input data, byte after byte.
|
273
|
-
FSE_encodeByte() outputs a maximum of 'tableLog' bits at a time.
|
274
|
-
Remember decoding will be done in reverse direction.
|
275
|
-
FSE_encodeByte(&bitStream, &state, symbol);
|
276
|
-
|
277
|
-
At any time, you can add any bit sequence.
|
278
|
-
Note : maximum allowed nbBits is 25, for compatibility with 32-bits decoders
|
279
|
-
FSE_addBits(&bitStream, bitField, nbBits);
|
280
|
-
|
281
|
-
The above methods don't commit data to memory, they just store it into local register, for speed.
|
282
|
-
Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (size_t).
|
283
|
-
Writing data to memory is a manual operation, performed by the flushBits function.
|
284
|
-
FSE_flushBits(&bitStream);
|
285
|
-
|
286
|
-
Your last FSE encoding operation shall be to flush your last state value(s).
|
287
|
-
FSE_flushState(&bitStream, &state);
|
288
|
-
|
289
|
-
You must then close the bitStream if you opened it with FSE_initCStream().
|
290
|
-
It's possible to embed some user-info into the header, as an optionalId [0-31].
|
291
|
-
The function returns the size in bytes of CStream.
|
292
|
-
If there is an error, it returns an errorCode (which can be tested using FSE_isError()).
|
293
|
-
size_t size = FSE_closeCStream(&bitStream, optionalId);
|
294
|
-
*/
|
295
|
-
|
296
|
-
|
297
|
-
/******************************************
|
298
|
-
* FSE streaming decompression API
|
299
|
-
******************************************/
|
300
|
-
//typedef unsigned int bitD_t;
|
301
|
-
typedef size_t bitD_t;
|
302
|
-
|
303
|
-
typedef struct
|
304
|
-
{
|
305
|
-
bitD_t bitContainer;
|
306
|
-
unsigned bitsConsumed;
|
307
|
-
const char* ptr;
|
308
|
-
const char* start;
|
309
|
-
} FSE_DStream_t;
|
310
|
-
|
311
|
-
typedef struct
|
312
|
-
{
|
313
|
-
bitD_t state;
|
314
|
-
const void* table;
|
315
|
-
} FSE_DState_t;
|
316
|
-
|
317
|
-
|
318
|
-
size_t FSE_initDStream(FSE_DStream_t* bitD, const void* srcBuffer, size_t srcSize);
|
319
|
-
void FSE_initDState(FSE_DState_t* DStatePtr, FSE_DStream_t* bitD, const void* DTable);
|
320
|
-
|
321
|
-
unsigned char FSE_decodeSymbol(FSE_DState_t* DStatePtr, FSE_DStream_t* bitD);
|
322
|
-
bitD_t FSE_readBits(FSE_DStream_t* bitD, unsigned nbBits);
|
323
|
-
unsigned int FSE_reloadDStream(FSE_DStream_t* bitD);
|
324
|
-
|
325
|
-
unsigned FSE_endOfDStream(const FSE_DStream_t* bitD);
|
326
|
-
unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr);
|
327
|
-
|
328
|
-
/*
|
329
|
-
Let's now decompose FSE_decompress_usingDTable() into its unitary elements.
|
330
|
-
You will decode FSE-encoded symbols from the bitStream,
|
331
|
-
and also any other bitFields you put in, **in reverse order**.
|
332
|
-
|
333
|
-
You will need a few variables to track your bitStream. They are :
|
334
|
-
|
335
|
-
FSE_DStream_t DStream; // Stream context
|
336
|
-
FSE_DState_t DState; // State context. Multiple ones are possible
|
337
|
-
const void* DTable; // Decoding table, provided by FSE_buildDTable()
|
338
|
-
U32 tableLog; // Provided by FSE_readHeader()
|
339
|
-
|
340
|
-
The first thing to do is to init the bitStream.
|
341
|
-
errorCode = FSE_initDStream(&DStream, &optionalId, srcBuffer, srcSize);
|
342
|
-
|
343
|
-
You should then retrieve your initial state(s) (multiple ones are possible) :
|
344
|
-
errorCode = FSE_initDState(&DState, &DStream, DTable, tableLog);
|
345
|
-
|
346
|
-
You can then decode your data, symbol after symbol.
|
347
|
-
For information the maximum number of bits read by FSE_decodeSymbol() is 'tableLog'.
|
348
|
-
Keep in mind that symbols are decoded in reverse order, like a lifo stack (last in, first out).
|
349
|
-
unsigned char symbol = FSE_decodeSymbol(&DState, &DStream);
|
350
|
-
|
351
|
-
You can retrieve any bitfield you eventually stored into the bitStream (in reverse order)
|
352
|
-
Note : maximum allowed nbBits is 25
|
353
|
-
unsigned int bitField = FSE_readBits(&DStream, nbBits);
|
354
|
-
|
355
|
-
All above operations only read from local register (which size is controlled by bitD_t==32 bits).
|
356
|
-
Reading data from memory is manually performed by the reload method.
|
357
|
-
endSignal = FSE_reloadDStream(&DStream);
|
358
|
-
|
359
|
-
FSE_reloadDStream() result tells if there is still some more data to read from DStream.
|
360
|
-
0 : there is still some data left into the DStream.
|
361
|
-
1 Dstream reached end of buffer, but is not yet fully extracted. It will not load data from memory any more.
|
362
|
-
2 Dstream reached its exact end, corresponding in general to decompression completed.
|
363
|
-
3 Dstream went too far. Decompression result is corrupted.
|
364
|
-
|
365
|
-
When reaching end of buffer(1), progress slowly if you decode multiple symbols per loop,
|
366
|
-
to properly detect the exact end of stream.
|
367
|
-
After each decoded symbol, check if DStream is fully consumed using this simple test :
|
368
|
-
FSE_reloadDStream(&DStream) >= 2
|
369
|
-
|
370
|
-
When it's done, verify decompression is fully completed, by checking both DStream and the relevant states.
|
371
|
-
Checking if DStream has reached its end is performed by :
|
372
|
-
FSE_endOfDStream(&DStream);
|
373
|
-
Check also the states. There might be some entropy left there, still able to decode some high probability symbol.
|
374
|
-
FSE_endOfDState(&DState);
|
311
|
+
'FSE_DTable' can then be used to decompress 'cSrc', with FSE_decompress_usingDTable().
|
312
|
+
'cSrcSize' must be strictly correct, otherwise decompression will fail.
|
313
|
+
FSE_decompress_usingDTable() result will tell how many bytes were regenerated (<=maxDstSize).
|
314
|
+
If there is an error, the function will return an error code, which can be tested using FSE_isError(). (ex: dst buffer too small)
|
375
315
|
*/
|
376
316
|
|
377
317
|
|