zstd-ruby 1.4.5.0 → 1.5.5.0
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/.gitignore +2 -0
- data/README.md +78 -5
- data/Rakefile +8 -2
- data/ext/zstdruby/common.h +15 -0
- data/ext/zstdruby/extconf.rb +3 -2
- data/ext/zstdruby/libzstd/common/allocations.h +55 -0
- data/ext/zstdruby/libzstd/common/bits.h +200 -0
- data/ext/zstdruby/libzstd/common/bitstream.h +45 -62
- data/ext/zstdruby/libzstd/common/compiler.h +205 -22
- data/ext/zstdruby/libzstd/common/cpu.h +1 -3
- data/ext/zstdruby/libzstd/common/debug.c +1 -1
- data/ext/zstdruby/libzstd/common/debug.h +12 -19
- data/ext/zstdruby/libzstd/common/entropy_common.c +172 -48
- data/ext/zstdruby/libzstd/common/error_private.c +10 -2
- data/ext/zstdruby/libzstd/common/error_private.h +82 -3
- data/ext/zstdruby/libzstd/common/fse.h +37 -86
- data/ext/zstdruby/libzstd/common/fse_decompress.c +117 -92
- data/ext/zstdruby/libzstd/common/huf.h +99 -166
- data/ext/zstdruby/libzstd/common/mem.h +124 -142
- data/ext/zstdruby/libzstd/common/pool.c +54 -27
- data/ext/zstdruby/libzstd/common/pool.h +10 -4
- data/ext/zstdruby/libzstd/common/portability_macros.h +156 -0
- data/ext/zstdruby/libzstd/common/threading.c +74 -19
- data/ext/zstdruby/libzstd/common/threading.h +5 -10
- data/ext/zstdruby/libzstd/common/xxhash.c +7 -847
- data/ext/zstdruby/libzstd/common/xxhash.h +5568 -167
- data/ext/zstdruby/libzstd/common/zstd_common.c +2 -37
- data/ext/zstdruby/libzstd/common/zstd_deps.h +111 -0
- data/ext/zstdruby/libzstd/common/zstd_internal.h +132 -187
- data/ext/zstdruby/libzstd/common/zstd_trace.h +163 -0
- data/ext/zstdruby/libzstd/compress/clevels.h +134 -0
- data/ext/zstdruby/libzstd/compress/fse_compress.c +83 -157
- data/ext/zstdruby/libzstd/compress/hist.c +27 -29
- data/ext/zstdruby/libzstd/compress/hist.h +2 -2
- data/ext/zstdruby/libzstd/compress/huf_compress.c +916 -279
- data/ext/zstdruby/libzstd/compress/zstd_compress.c +3773 -1019
- data/ext/zstdruby/libzstd/compress/zstd_compress_internal.h +610 -203
- data/ext/zstdruby/libzstd/compress/zstd_compress_literals.c +119 -42
- data/ext/zstdruby/libzstd/compress/zstd_compress_literals.h +16 -6
- data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.c +42 -19
- data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.h +1 -1
- data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.c +49 -317
- data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.h +1 -1
- data/ext/zstdruby/libzstd/compress/zstd_cwksp.h +320 -103
- data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +388 -151
- data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +3 -2
- data/ext/zstdruby/libzstd/compress/zstd_fast.c +729 -265
- data/ext/zstdruby/libzstd/compress/zstd_fast.h +3 -2
- data/ext/zstdruby/libzstd/compress/zstd_lazy.c +1270 -251
- data/ext/zstdruby/libzstd/compress/zstd_lazy.h +61 -1
- data/ext/zstdruby/libzstd/compress/zstd_ldm.c +324 -219
- data/ext/zstdruby/libzstd/compress/zstd_ldm.h +9 -2
- data/ext/zstdruby/libzstd/compress/zstd_ldm_geartab.h +106 -0
- data/ext/zstdruby/libzstd/compress/zstd_opt.c +481 -209
- data/ext/zstdruby/libzstd/compress/zstd_opt.h +1 -1
- data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +181 -457
- data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +34 -113
- data/ext/zstdruby/libzstd/decompress/huf_decompress.c +1199 -565
- data/ext/zstdruby/libzstd/decompress/huf_decompress_amd64.S +576 -0
- data/ext/zstdruby/libzstd/decompress/zstd_ddict.c +12 -12
- data/ext/zstdruby/libzstd/decompress/zstd_ddict.h +2 -2
- data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +627 -157
- data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.c +1086 -326
- data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.h +19 -5
- data/ext/zstdruby/libzstd/decompress/zstd_decompress_internal.h +62 -13
- data/ext/zstdruby/libzstd/dictBuilder/cover.c +73 -52
- data/ext/zstdruby/libzstd/dictBuilder/cover.h +7 -6
- data/ext/zstdruby/libzstd/dictBuilder/divsufsort.c +1 -1
- data/ext/zstdruby/libzstd/dictBuilder/fastcover.c +44 -35
- data/ext/zstdruby/libzstd/dictBuilder/zdict.c +103 -111
- data/ext/zstdruby/libzstd/{dictBuilder/zdict.h → zdict.h} +203 -34
- data/ext/zstdruby/libzstd/zstd.h +1217 -287
- data/ext/zstdruby/libzstd/{common/zstd_errors.h → zstd_errors.h} +28 -8
- data/ext/zstdruby/main.c +20 -0
- data/ext/zstdruby/skippable_frame.c +63 -0
- data/ext/zstdruby/streaming_compress.c +177 -0
- data/ext/zstdruby/streaming_compress.h +5 -0
- data/ext/zstdruby/streaming_decompress.c +123 -0
- data/ext/zstdruby/zstdruby.c +114 -32
- data/lib/zstd-ruby/version.rb +1 -1
- data/lib/zstd-ruby.rb +0 -1
- data/zstd-ruby.gemspec +1 -1
- metadata +19 -36
- data/.travis.yml +0 -14
- data/ext/zstdruby/libzstd/.gitignore +0 -3
- data/ext/zstdruby/libzstd/BUCK +0 -234
- data/ext/zstdruby/libzstd/Makefile +0 -354
- data/ext/zstdruby/libzstd/README.md +0 -179
- data/ext/zstdruby/libzstd/deprecated/zbuff.h +0 -214
- data/ext/zstdruby/libzstd/deprecated/zbuff_common.c +0 -26
- data/ext/zstdruby/libzstd/deprecated/zbuff_compress.c +0 -147
- data/ext/zstdruby/libzstd/deprecated/zbuff_decompress.c +0 -75
- data/ext/zstdruby/libzstd/dll/example/Makefile +0 -48
- data/ext/zstdruby/libzstd/dll/example/README.md +0 -69
- data/ext/zstdruby/libzstd/dll/example/build_package.bat +0 -20
- data/ext/zstdruby/libzstd/dll/example/fullbench-dll.sln +0 -25
- data/ext/zstdruby/libzstd/dll/example/fullbench-dll.vcxproj +0 -181
- data/ext/zstdruby/libzstd/legacy/zstd_legacy.h +0 -415
- data/ext/zstdruby/libzstd/legacy/zstd_v01.c +0 -2158
- data/ext/zstdruby/libzstd/legacy/zstd_v01.h +0 -94
- data/ext/zstdruby/libzstd/legacy/zstd_v02.c +0 -3518
- data/ext/zstdruby/libzstd/legacy/zstd_v02.h +0 -93
- data/ext/zstdruby/libzstd/legacy/zstd_v03.c +0 -3160
- data/ext/zstdruby/libzstd/legacy/zstd_v03.h +0 -93
- data/ext/zstdruby/libzstd/legacy/zstd_v04.c +0 -3647
- data/ext/zstdruby/libzstd/legacy/zstd_v04.h +0 -142
- data/ext/zstdruby/libzstd/legacy/zstd_v05.c +0 -4050
- data/ext/zstdruby/libzstd/legacy/zstd_v05.h +0 -162
- data/ext/zstdruby/libzstd/legacy/zstd_v06.c +0 -4154
- data/ext/zstdruby/libzstd/legacy/zstd_v06.h +0 -172
- data/ext/zstdruby/libzstd/legacy/zstd_v07.c +0 -4541
- data/ext/zstdruby/libzstd/legacy/zstd_v07.h +0 -187
- data/ext/zstdruby/libzstd/libzstd.pc.in +0 -15
- data/ext/zstdruby/zstdruby.h +0 -6
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright (c)
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
3
|
* All rights reserved.
|
|
4
4
|
*
|
|
5
5
|
* This source code is licensed under both the BSD-style license (found in the
|
|
@@ -55,23 +55,165 @@
|
|
|
55
55
|
/*-*******************************************************
|
|
56
56
|
* Dependencies
|
|
57
57
|
*********************************************************/
|
|
58
|
-
#include
|
|
59
|
-
#include "../common/
|
|
58
|
+
#include "../common/allocations.h" /* ZSTD_customMalloc, ZSTD_customCalloc, ZSTD_customFree */
|
|
59
|
+
#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */
|
|
60
60
|
#include "../common/mem.h" /* low level memory routines */
|
|
61
61
|
#define FSE_STATIC_LINKING_ONLY
|
|
62
62
|
#include "../common/fse.h"
|
|
63
|
-
#define HUF_STATIC_LINKING_ONLY
|
|
64
63
|
#include "../common/huf.h"
|
|
64
|
+
#include "../common/xxhash.h" /* XXH64_reset, XXH64_update, XXH64_digest, XXH64 */
|
|
65
65
|
#include "../common/zstd_internal.h" /* blockProperties_t */
|
|
66
66
|
#include "zstd_decompress_internal.h" /* ZSTD_DCtx */
|
|
67
67
|
#include "zstd_ddict.h" /* ZSTD_DDictDictContent */
|
|
68
68
|
#include "zstd_decompress_block.h" /* ZSTD_decompressBlock_internal */
|
|
69
|
+
#include "../common/bits.h" /* ZSTD_highbit32 */
|
|
69
70
|
|
|
70
71
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
|
71
72
|
# include "../legacy/zstd_legacy.h"
|
|
72
73
|
#endif
|
|
73
74
|
|
|
74
75
|
|
|
76
|
+
|
|
77
|
+
/*************************************
|
|
78
|
+
* Multiple DDicts Hashset internals *
|
|
79
|
+
*************************************/
|
|
80
|
+
|
|
81
|
+
#define DDICT_HASHSET_MAX_LOAD_FACTOR_COUNT_MULT 4
|
|
82
|
+
#define DDICT_HASHSET_MAX_LOAD_FACTOR_SIZE_MULT 3 /* These two constants represent SIZE_MULT/COUNT_MULT load factor without using a float.
|
|
83
|
+
* Currently, that means a 0.75 load factor.
|
|
84
|
+
* So, if count * COUNT_MULT / size * SIZE_MULT != 0, then we've exceeded
|
|
85
|
+
* the load factor of the ddict hash set.
|
|
86
|
+
*/
|
|
87
|
+
|
|
88
|
+
#define DDICT_HASHSET_TABLE_BASE_SIZE 64
|
|
89
|
+
#define DDICT_HASHSET_RESIZE_FACTOR 2
|
|
90
|
+
|
|
91
|
+
/* Hash function to determine starting position of dict insertion within the table
|
|
92
|
+
* Returns an index between [0, hashSet->ddictPtrTableSize]
|
|
93
|
+
*/
|
|
94
|
+
static size_t ZSTD_DDictHashSet_getIndex(const ZSTD_DDictHashSet* hashSet, U32 dictID) {
|
|
95
|
+
const U64 hash = XXH64(&dictID, sizeof(U32), 0);
|
|
96
|
+
/* DDict ptr table size is a multiple of 2, use size - 1 as mask to get index within [0, hashSet->ddictPtrTableSize) */
|
|
97
|
+
return hash & (hashSet->ddictPtrTableSize - 1);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/* Adds DDict to a hashset without resizing it.
|
|
101
|
+
* If inserting a DDict with a dictID that already exists in the set, replaces the one in the set.
|
|
102
|
+
* Returns 0 if successful, or a zstd error code if something went wrong.
|
|
103
|
+
*/
|
|
104
|
+
static size_t ZSTD_DDictHashSet_emplaceDDict(ZSTD_DDictHashSet* hashSet, const ZSTD_DDict* ddict) {
|
|
105
|
+
const U32 dictID = ZSTD_getDictID_fromDDict(ddict);
|
|
106
|
+
size_t idx = ZSTD_DDictHashSet_getIndex(hashSet, dictID);
|
|
107
|
+
const size_t idxRangeMask = hashSet->ddictPtrTableSize - 1;
|
|
108
|
+
RETURN_ERROR_IF(hashSet->ddictPtrCount == hashSet->ddictPtrTableSize, GENERIC, "Hash set is full!");
|
|
109
|
+
DEBUGLOG(4, "Hashed index: for dictID: %u is %zu", dictID, idx);
|
|
110
|
+
while (hashSet->ddictPtrTable[idx] != NULL) {
|
|
111
|
+
/* Replace existing ddict if inserting ddict with same dictID */
|
|
112
|
+
if (ZSTD_getDictID_fromDDict(hashSet->ddictPtrTable[idx]) == dictID) {
|
|
113
|
+
DEBUGLOG(4, "DictID already exists, replacing rather than adding");
|
|
114
|
+
hashSet->ddictPtrTable[idx] = ddict;
|
|
115
|
+
return 0;
|
|
116
|
+
}
|
|
117
|
+
idx &= idxRangeMask;
|
|
118
|
+
idx++;
|
|
119
|
+
}
|
|
120
|
+
DEBUGLOG(4, "Final idx after probing for dictID %u is: %zu", dictID, idx);
|
|
121
|
+
hashSet->ddictPtrTable[idx] = ddict;
|
|
122
|
+
hashSet->ddictPtrCount++;
|
|
123
|
+
return 0;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/* Expands hash table by factor of DDICT_HASHSET_RESIZE_FACTOR and
|
|
127
|
+
* rehashes all values, allocates new table, frees old table.
|
|
128
|
+
* Returns 0 on success, otherwise a zstd error code.
|
|
129
|
+
*/
|
|
130
|
+
static size_t ZSTD_DDictHashSet_expand(ZSTD_DDictHashSet* hashSet, ZSTD_customMem customMem) {
|
|
131
|
+
size_t newTableSize = hashSet->ddictPtrTableSize * DDICT_HASHSET_RESIZE_FACTOR;
|
|
132
|
+
const ZSTD_DDict** newTable = (const ZSTD_DDict**)ZSTD_customCalloc(sizeof(ZSTD_DDict*) * newTableSize, customMem);
|
|
133
|
+
const ZSTD_DDict** oldTable = hashSet->ddictPtrTable;
|
|
134
|
+
size_t oldTableSize = hashSet->ddictPtrTableSize;
|
|
135
|
+
size_t i;
|
|
136
|
+
|
|
137
|
+
DEBUGLOG(4, "Expanding DDict hash table! Old size: %zu new size: %zu", oldTableSize, newTableSize);
|
|
138
|
+
RETURN_ERROR_IF(!newTable, memory_allocation, "Expanded hashset allocation failed!");
|
|
139
|
+
hashSet->ddictPtrTable = newTable;
|
|
140
|
+
hashSet->ddictPtrTableSize = newTableSize;
|
|
141
|
+
hashSet->ddictPtrCount = 0;
|
|
142
|
+
for (i = 0; i < oldTableSize; ++i) {
|
|
143
|
+
if (oldTable[i] != NULL) {
|
|
144
|
+
FORWARD_IF_ERROR(ZSTD_DDictHashSet_emplaceDDict(hashSet, oldTable[i]), "");
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
ZSTD_customFree((void*)oldTable, customMem);
|
|
148
|
+
DEBUGLOG(4, "Finished re-hash");
|
|
149
|
+
return 0;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/* Fetches a DDict with the given dictID
|
|
153
|
+
* Returns the ZSTD_DDict* with the requested dictID. If it doesn't exist, then returns NULL.
|
|
154
|
+
*/
|
|
155
|
+
static const ZSTD_DDict* ZSTD_DDictHashSet_getDDict(ZSTD_DDictHashSet* hashSet, U32 dictID) {
|
|
156
|
+
size_t idx = ZSTD_DDictHashSet_getIndex(hashSet, dictID);
|
|
157
|
+
const size_t idxRangeMask = hashSet->ddictPtrTableSize - 1;
|
|
158
|
+
DEBUGLOG(4, "Hashed index: for dictID: %u is %zu", dictID, idx);
|
|
159
|
+
for (;;) {
|
|
160
|
+
size_t currDictID = ZSTD_getDictID_fromDDict(hashSet->ddictPtrTable[idx]);
|
|
161
|
+
if (currDictID == dictID || currDictID == 0) {
|
|
162
|
+
/* currDictID == 0 implies a NULL ddict entry */
|
|
163
|
+
break;
|
|
164
|
+
} else {
|
|
165
|
+
idx &= idxRangeMask; /* Goes to start of table when we reach the end */
|
|
166
|
+
idx++;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
DEBUGLOG(4, "Final idx after probing for dictID %u is: %zu", dictID, idx);
|
|
170
|
+
return hashSet->ddictPtrTable[idx];
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/* Allocates space for and returns a ddict hash set
|
|
174
|
+
* The hash set's ZSTD_DDict* table has all values automatically set to NULL to begin with.
|
|
175
|
+
* Returns NULL if allocation failed.
|
|
176
|
+
*/
|
|
177
|
+
static ZSTD_DDictHashSet* ZSTD_createDDictHashSet(ZSTD_customMem customMem) {
|
|
178
|
+
ZSTD_DDictHashSet* ret = (ZSTD_DDictHashSet*)ZSTD_customMalloc(sizeof(ZSTD_DDictHashSet), customMem);
|
|
179
|
+
DEBUGLOG(4, "Allocating new hash set");
|
|
180
|
+
if (!ret)
|
|
181
|
+
return NULL;
|
|
182
|
+
ret->ddictPtrTable = (const ZSTD_DDict**)ZSTD_customCalloc(DDICT_HASHSET_TABLE_BASE_SIZE * sizeof(ZSTD_DDict*), customMem);
|
|
183
|
+
if (!ret->ddictPtrTable) {
|
|
184
|
+
ZSTD_customFree(ret, customMem);
|
|
185
|
+
return NULL;
|
|
186
|
+
}
|
|
187
|
+
ret->ddictPtrTableSize = DDICT_HASHSET_TABLE_BASE_SIZE;
|
|
188
|
+
ret->ddictPtrCount = 0;
|
|
189
|
+
return ret;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/* Frees the table of ZSTD_DDict* within a hashset, then frees the hashset itself.
|
|
193
|
+
* Note: The ZSTD_DDict* within the table are NOT freed.
|
|
194
|
+
*/
|
|
195
|
+
static void ZSTD_freeDDictHashSet(ZSTD_DDictHashSet* hashSet, ZSTD_customMem customMem) {
|
|
196
|
+
DEBUGLOG(4, "Freeing ddict hash set");
|
|
197
|
+
if (hashSet && hashSet->ddictPtrTable) {
|
|
198
|
+
ZSTD_customFree((void*)hashSet->ddictPtrTable, customMem);
|
|
199
|
+
}
|
|
200
|
+
if (hashSet) {
|
|
201
|
+
ZSTD_customFree(hashSet, customMem);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/* Public function: Adds a DDict into the ZSTD_DDictHashSet, possibly triggering a resize of the hash set.
|
|
206
|
+
* Returns 0 on success, or a ZSTD error.
|
|
207
|
+
*/
|
|
208
|
+
static size_t ZSTD_DDictHashSet_addDDict(ZSTD_DDictHashSet* hashSet, const ZSTD_DDict* ddict, ZSTD_customMem customMem) {
|
|
209
|
+
DEBUGLOG(4, "Adding dict ID: %u to hashset with - Count: %zu Tablesize: %zu", ZSTD_getDictID_fromDDict(ddict), hashSet->ddictPtrCount, hashSet->ddictPtrTableSize);
|
|
210
|
+
if (hashSet->ddictPtrCount * DDICT_HASHSET_MAX_LOAD_FACTOR_COUNT_MULT / hashSet->ddictPtrTableSize * DDICT_HASHSET_MAX_LOAD_FACTOR_SIZE_MULT != 0) {
|
|
211
|
+
FORWARD_IF_ERROR(ZSTD_DDictHashSet_expand(hashSet, customMem), "");
|
|
212
|
+
}
|
|
213
|
+
FORWARD_IF_ERROR(ZSTD_DDictHashSet_emplaceDDict(hashSet, ddict), "");
|
|
214
|
+
return 0;
|
|
215
|
+
}
|
|
216
|
+
|
|
75
217
|
/*-*************************************************************
|
|
76
218
|
* Context management
|
|
77
219
|
***************************************************************/
|
|
@@ -94,11 +236,20 @@ static size_t ZSTD_startingInputLength(ZSTD_format_e format)
|
|
|
94
236
|
return startingInputLength;
|
|
95
237
|
}
|
|
96
238
|
|
|
239
|
+
static void ZSTD_DCtx_resetParameters(ZSTD_DCtx* dctx)
|
|
240
|
+
{
|
|
241
|
+
assert(dctx->streamStage == zdss_init);
|
|
242
|
+
dctx->format = ZSTD_f_zstd1;
|
|
243
|
+
dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
|
|
244
|
+
dctx->outBufferMode = ZSTD_bm_buffered;
|
|
245
|
+
dctx->forceIgnoreChecksum = ZSTD_d_validateChecksum;
|
|
246
|
+
dctx->refMultipleDDicts = ZSTD_rmd_refSingleDDict;
|
|
247
|
+
dctx->disableHufAsm = 0;
|
|
248
|
+
}
|
|
249
|
+
|
|
97
250
|
static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
|
|
98
251
|
{
|
|
99
|
-
dctx->format = ZSTD_f_zstd1; /* ZSTD_decompressBegin() invokes ZSTD_startingInputLength() with argument dctx->format */
|
|
100
252
|
dctx->staticSize = 0;
|
|
101
|
-
dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
|
|
102
253
|
dctx->ddict = NULL;
|
|
103
254
|
dctx->ddictLocal = NULL;
|
|
104
255
|
dctx->dictEnd = NULL;
|
|
@@ -108,12 +259,17 @@ static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
|
|
|
108
259
|
dctx->inBuffSize = 0;
|
|
109
260
|
dctx->outBuffSize = 0;
|
|
110
261
|
dctx->streamStage = zdss_init;
|
|
262
|
+
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
|
111
263
|
dctx->legacyContext = NULL;
|
|
112
264
|
dctx->previousLegacyVersion = 0;
|
|
265
|
+
#endif
|
|
113
266
|
dctx->noForwardProgress = 0;
|
|
114
267
|
dctx->oversizedDuration = 0;
|
|
115
|
-
|
|
116
|
-
dctx->
|
|
268
|
+
#if DYNAMIC_BMI2
|
|
269
|
+
dctx->bmi2 = ZSTD_cpuSupportsBmi2();
|
|
270
|
+
#endif
|
|
271
|
+
dctx->ddictSet = NULL;
|
|
272
|
+
ZSTD_DCtx_resetParameters(dctx);
|
|
117
273
|
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
|
118
274
|
dctx->dictContentEndForFuzzing = NULL;
|
|
119
275
|
#endif
|
|
@@ -132,11 +288,10 @@ ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
|
|
|
132
288
|
return dctx;
|
|
133
289
|
}
|
|
134
290
|
|
|
135
|
-
ZSTD_DCtx*
|
|
136
|
-
|
|
137
|
-
if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
|
|
291
|
+
static ZSTD_DCtx* ZSTD_createDCtx_internal(ZSTD_customMem customMem) {
|
|
292
|
+
if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;
|
|
138
293
|
|
|
139
|
-
{ ZSTD_DCtx* const dctx = (ZSTD_DCtx*)
|
|
294
|
+
{ ZSTD_DCtx* const dctx = (ZSTD_DCtx*)ZSTD_customMalloc(sizeof(*dctx), customMem);
|
|
140
295
|
if (!dctx) return NULL;
|
|
141
296
|
dctx->customMem = customMem;
|
|
142
297
|
ZSTD_initDCtx_internal(dctx);
|
|
@@ -144,10 +299,15 @@ ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
|
|
|
144
299
|
}
|
|
145
300
|
}
|
|
146
301
|
|
|
302
|
+
ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
|
|
303
|
+
{
|
|
304
|
+
return ZSTD_createDCtx_internal(customMem);
|
|
305
|
+
}
|
|
306
|
+
|
|
147
307
|
ZSTD_DCtx* ZSTD_createDCtx(void)
|
|
148
308
|
{
|
|
149
309
|
DEBUGLOG(3, "ZSTD_createDCtx");
|
|
150
|
-
return
|
|
310
|
+
return ZSTD_createDCtx_internal(ZSTD_defaultCMem);
|
|
151
311
|
}
|
|
152
312
|
|
|
153
313
|
static void ZSTD_clearDict(ZSTD_DCtx* dctx)
|
|
@@ -164,13 +324,17 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)
|
|
|
164
324
|
RETURN_ERROR_IF(dctx->staticSize, memory_allocation, "not compatible with static DCtx");
|
|
165
325
|
{ ZSTD_customMem const cMem = dctx->customMem;
|
|
166
326
|
ZSTD_clearDict(dctx);
|
|
167
|
-
|
|
327
|
+
ZSTD_customFree(dctx->inBuff, cMem);
|
|
168
328
|
dctx->inBuff = NULL;
|
|
169
329
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
|
|
170
330
|
if (dctx->legacyContext)
|
|
171
331
|
ZSTD_freeLegacyStreamContext(dctx->legacyContext, dctx->previousLegacyVersion);
|
|
172
332
|
#endif
|
|
173
|
-
|
|
333
|
+
if (dctx->ddictSet) {
|
|
334
|
+
ZSTD_freeDDictHashSet(dctx->ddictSet, cMem);
|
|
335
|
+
dctx->ddictSet = NULL;
|
|
336
|
+
}
|
|
337
|
+
ZSTD_customFree(dctx, cMem);
|
|
174
338
|
return 0;
|
|
175
339
|
}
|
|
176
340
|
}
|
|
@@ -179,7 +343,30 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)
|
|
|
179
343
|
void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
|
|
180
344
|
{
|
|
181
345
|
size_t const toCopy = (size_t)((char*)(&dstDCtx->inBuff) - (char*)dstDCtx);
|
|
182
|
-
|
|
346
|
+
ZSTD_memcpy(dstDCtx, srcDCtx, toCopy); /* no need to copy workspace */
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/* Given a dctx with a digested frame params, re-selects the correct ZSTD_DDict based on
|
|
350
|
+
* the requested dict ID from the frame. If there exists a reference to the correct ZSTD_DDict, then
|
|
351
|
+
* accordingly sets the ddict to be used to decompress the frame.
|
|
352
|
+
*
|
|
353
|
+
* If no DDict is found, then no action is taken, and the ZSTD_DCtx::ddict remains as-is.
|
|
354
|
+
*
|
|
355
|
+
* ZSTD_d_refMultipleDDicts must be enabled for this function to be called.
|
|
356
|
+
*/
|
|
357
|
+
static void ZSTD_DCtx_selectFrameDDict(ZSTD_DCtx* dctx) {
|
|
358
|
+
assert(dctx->refMultipleDDicts && dctx->ddictSet);
|
|
359
|
+
DEBUGLOG(4, "Adjusting DDict based on requested dict ID from frame");
|
|
360
|
+
if (dctx->ddict) {
|
|
361
|
+
const ZSTD_DDict* frameDDict = ZSTD_DDictHashSet_getDDict(dctx->ddictSet, dctx->fParams.dictID);
|
|
362
|
+
if (frameDDict) {
|
|
363
|
+
DEBUGLOG(4, "DDict found!");
|
|
364
|
+
ZSTD_clearDict(dctx);
|
|
365
|
+
dctx->dictID = dctx->fParams.dictID;
|
|
366
|
+
dctx->ddict = frameDDict;
|
|
367
|
+
dctx->dictUses = ZSTD_use_indefinitely;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
183
370
|
}
|
|
184
371
|
|
|
185
372
|
|
|
@@ -205,6 +392,19 @@ unsigned ZSTD_isFrame(const void* buffer, size_t size)
|
|
|
205
392
|
return 0;
|
|
206
393
|
}
|
|
207
394
|
|
|
395
|
+
/*! ZSTD_isSkippableFrame() :
|
|
396
|
+
* Tells if the content of `buffer` starts with a valid Frame Identifier for a skippable frame.
|
|
397
|
+
* Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0.
|
|
398
|
+
*/
|
|
399
|
+
unsigned ZSTD_isSkippableFrame(const void* buffer, size_t size)
|
|
400
|
+
{
|
|
401
|
+
if (size < ZSTD_FRAMEIDSIZE) return 0;
|
|
402
|
+
{ U32 const magic = MEM_readLE32(buffer);
|
|
403
|
+
if ((magic & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) return 1;
|
|
404
|
+
}
|
|
405
|
+
return 0;
|
|
406
|
+
}
|
|
407
|
+
|
|
208
408
|
/** ZSTD_frameHeaderSize_internal() :
|
|
209
409
|
* srcSize must be large enough to reach header size fields.
|
|
210
410
|
* note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless.
|
|
@@ -240,23 +440,47 @@ size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize)
|
|
|
240
440
|
* note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless
|
|
241
441
|
* @return : 0, `zfhPtr` is correctly filled,
|
|
242
442
|
* >0, `srcSize` is too small, value is wanted `srcSize` amount,
|
|
243
|
-
|
|
443
|
+
** or an error code, which can be tested using ZSTD_isError() */
|
|
244
444
|
size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format)
|
|
245
445
|
{
|
|
246
446
|
const BYTE* ip = (const BYTE*)src;
|
|
247
447
|
size_t const minInputSize = ZSTD_startingInputLength(format);
|
|
248
448
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
449
|
+
DEBUGLOG(5, "ZSTD_getFrameHeader_advanced: minInputSize = %zu, srcSize = %zu", minInputSize, srcSize);
|
|
450
|
+
|
|
451
|
+
if (srcSize > 0) {
|
|
452
|
+
/* note : technically could be considered an assert(), since it's an invalid entry */
|
|
453
|
+
RETURN_ERROR_IF(src==NULL, GENERIC, "invalid parameter : src==NULL, but srcSize>0");
|
|
454
|
+
}
|
|
455
|
+
if (srcSize < minInputSize) {
|
|
456
|
+
if (srcSize > 0 && format != ZSTD_f_zstd1_magicless) {
|
|
457
|
+
/* when receiving less than @minInputSize bytes,
|
|
458
|
+
* control these bytes at least correspond to a supported magic number
|
|
459
|
+
* in order to error out early if they don't.
|
|
460
|
+
**/
|
|
461
|
+
size_t const toCopy = MIN(4, srcSize);
|
|
462
|
+
unsigned char hbuf[4]; MEM_writeLE32(hbuf, ZSTD_MAGICNUMBER);
|
|
463
|
+
assert(src != NULL);
|
|
464
|
+
ZSTD_memcpy(hbuf, src, toCopy);
|
|
465
|
+
if ( MEM_readLE32(hbuf) != ZSTD_MAGICNUMBER ) {
|
|
466
|
+
/* not a zstd frame : let's check if it's a skippable frame */
|
|
467
|
+
MEM_writeLE32(hbuf, ZSTD_MAGIC_SKIPPABLE_START);
|
|
468
|
+
ZSTD_memcpy(hbuf, src, toCopy);
|
|
469
|
+
if ((MEM_readLE32(hbuf) & ZSTD_MAGIC_SKIPPABLE_MASK) != ZSTD_MAGIC_SKIPPABLE_START) {
|
|
470
|
+
RETURN_ERROR(prefix_unknown,
|
|
471
|
+
"first bytes don't correspond to any supported magic number");
|
|
472
|
+
} } }
|
|
473
|
+
return minInputSize;
|
|
474
|
+
}
|
|
252
475
|
|
|
476
|
+
ZSTD_memset(zfhPtr, 0, sizeof(*zfhPtr)); /* not strictly necessary, but static analyzers may not understand that zfhPtr will be read only if return value is zero, since they are 2 different signals */
|
|
253
477
|
if ( (format != ZSTD_f_zstd1_magicless)
|
|
254
478
|
&& (MEM_readLE32(src) != ZSTD_MAGICNUMBER) ) {
|
|
255
479
|
if ((MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
|
|
256
480
|
/* skippable frame */
|
|
257
481
|
if (srcSize < ZSTD_SKIPPABLEHEADERSIZE)
|
|
258
482
|
return ZSTD_SKIPPABLEHEADERSIZE; /* magic number + frame length */
|
|
259
|
-
|
|
483
|
+
ZSTD_memset(zfhPtr, 0, sizeof(*zfhPtr));
|
|
260
484
|
zfhPtr->frameContentSize = MEM_readLE32((const char *)src + ZSTD_FRAMEIDSIZE);
|
|
261
485
|
zfhPtr->frameType = ZSTD_skippableFrame;
|
|
262
486
|
return 0;
|
|
@@ -291,7 +515,9 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
|
|
|
291
515
|
}
|
|
292
516
|
switch(dictIDSizeCode)
|
|
293
517
|
{
|
|
294
|
-
default:
|
|
518
|
+
default:
|
|
519
|
+
assert(0); /* impossible */
|
|
520
|
+
ZSTD_FALLTHROUGH;
|
|
295
521
|
case 0 : break;
|
|
296
522
|
case 1 : dictID = ip[pos]; pos++; break;
|
|
297
523
|
case 2 : dictID = MEM_readLE16(ip+pos); pos+=2; break;
|
|
@@ -299,7 +525,9 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
|
|
|
299
525
|
}
|
|
300
526
|
switch(fcsID)
|
|
301
527
|
{
|
|
302
|
-
default:
|
|
528
|
+
default:
|
|
529
|
+
assert(0); /* impossible */
|
|
530
|
+
ZSTD_FALLTHROUGH;
|
|
303
531
|
case 0 : if (singleSegment) frameContentSize = ip[pos]; break;
|
|
304
532
|
case 1 : frameContentSize = MEM_readLE16(ip+pos)+256; break;
|
|
305
533
|
case 2 : frameContentSize = MEM_readLE32(ip+pos); break;
|
|
@@ -328,7 +556,6 @@ size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t src
|
|
|
328
556
|
return ZSTD_getFrameHeader_advanced(zfhPtr, src, srcSize, ZSTD_f_zstd1);
|
|
329
557
|
}
|
|
330
558
|
|
|
331
|
-
|
|
332
559
|
/** ZSTD_getFrameContentSize() :
|
|
333
560
|
* compatible with legacy mode
|
|
334
561
|
* @return : decompressed size of the single frame pointed to be `src` if known, otherwise
|
|
@@ -362,18 +589,52 @@ static size_t readSkippableFrameSize(void const* src, size_t srcSize)
|
|
|
362
589
|
sizeU32 = MEM_readLE32((BYTE const*)src + ZSTD_FRAMEIDSIZE);
|
|
363
590
|
RETURN_ERROR_IF((U32)(sizeU32 + ZSTD_SKIPPABLEHEADERSIZE) < sizeU32,
|
|
364
591
|
frameParameter_unsupported, "");
|
|
365
|
-
{
|
|
366
|
-
size_t const skippableSize = skippableHeaderSize + sizeU32;
|
|
592
|
+
{ size_t const skippableSize = skippableHeaderSize + sizeU32;
|
|
367
593
|
RETURN_ERROR_IF(skippableSize > srcSize, srcSize_wrong, "");
|
|
368
594
|
return skippableSize;
|
|
369
595
|
}
|
|
370
596
|
}
|
|
371
597
|
|
|
598
|
+
/*! ZSTD_readSkippableFrame() :
|
|
599
|
+
* Retrieves content of a skippable frame, and writes it to dst buffer.
|
|
600
|
+
*
|
|
601
|
+
* The parameter magicVariant will receive the magicVariant that was supplied when the frame was written,
|
|
602
|
+
* i.e. magicNumber - ZSTD_MAGIC_SKIPPABLE_START. This can be NULL if the caller is not interested
|
|
603
|
+
* in the magicVariant.
|
|
604
|
+
*
|
|
605
|
+
* Returns an error if destination buffer is not large enough, or if this is not a valid skippable frame.
|
|
606
|
+
*
|
|
607
|
+
* @return : number of bytes written or a ZSTD error.
|
|
608
|
+
*/
|
|
609
|
+
size_t ZSTD_readSkippableFrame(void* dst, size_t dstCapacity,
|
|
610
|
+
unsigned* magicVariant, /* optional, can be NULL */
|
|
611
|
+
const void* src, size_t srcSize)
|
|
612
|
+
{
|
|
613
|
+
RETURN_ERROR_IF(srcSize < ZSTD_SKIPPABLEHEADERSIZE, srcSize_wrong, "");
|
|
614
|
+
|
|
615
|
+
{ U32 const magicNumber = MEM_readLE32(src);
|
|
616
|
+
size_t skippableFrameSize = readSkippableFrameSize(src, srcSize);
|
|
617
|
+
size_t skippableContentSize = skippableFrameSize - ZSTD_SKIPPABLEHEADERSIZE;
|
|
618
|
+
|
|
619
|
+
/* check input validity */
|
|
620
|
+
RETURN_ERROR_IF(!ZSTD_isSkippableFrame(src, srcSize), frameParameter_unsupported, "");
|
|
621
|
+
RETURN_ERROR_IF(skippableFrameSize < ZSTD_SKIPPABLEHEADERSIZE || skippableFrameSize > srcSize, srcSize_wrong, "");
|
|
622
|
+
RETURN_ERROR_IF(skippableContentSize > dstCapacity, dstSize_tooSmall, "");
|
|
623
|
+
|
|
624
|
+
/* deliver payload */
|
|
625
|
+
if (skippableContentSize > 0 && dst != NULL)
|
|
626
|
+
ZSTD_memcpy(dst, (const BYTE *)src + ZSTD_SKIPPABLEHEADERSIZE, skippableContentSize);
|
|
627
|
+
if (magicVariant != NULL)
|
|
628
|
+
*magicVariant = magicNumber - ZSTD_MAGIC_SKIPPABLE_START;
|
|
629
|
+
return skippableContentSize;
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
|
|
372
633
|
/** ZSTD_findDecompressedSize() :
|
|
373
|
-
* compatible with legacy mode
|
|
374
634
|
* `srcSize` must be the exact length of some number of ZSTD compressed and/or
|
|
375
635
|
* skippable frames
|
|
376
|
-
*
|
|
636
|
+
* note: compatible with legacy mode
|
|
637
|
+
* @return : decompressed size of the frames contained */
|
|
377
638
|
unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
|
|
378
639
|
{
|
|
379
640
|
unsigned long long totalDstSize = 0;
|
|
@@ -383,9 +644,7 @@ unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
|
|
|
383
644
|
|
|
384
645
|
if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
|
|
385
646
|
size_t const skippableSize = readSkippableFrameSize(src, srcSize);
|
|
386
|
-
if (ZSTD_isError(skippableSize))
|
|
387
|
-
return ZSTD_CONTENTSIZE_ERROR;
|
|
388
|
-
}
|
|
647
|
+
if (ZSTD_isError(skippableSize)) return ZSTD_CONTENTSIZE_ERROR;
|
|
389
648
|
assert(skippableSize <= srcSize);
|
|
390
649
|
|
|
391
650
|
src = (const BYTE *)src + skippableSize;
|
|
@@ -393,17 +652,17 @@ unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
|
|
|
393
652
|
continue;
|
|
394
653
|
}
|
|
395
654
|
|
|
396
|
-
{ unsigned long long const
|
|
397
|
-
if (
|
|
655
|
+
{ unsigned long long const fcs = ZSTD_getFrameContentSize(src, srcSize);
|
|
656
|
+
if (fcs >= ZSTD_CONTENTSIZE_ERROR) return fcs;
|
|
398
657
|
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
totalDstSize +=
|
|
658
|
+
if (totalDstSize + fcs < totalDstSize)
|
|
659
|
+
return ZSTD_CONTENTSIZE_ERROR; /* check for overflow */
|
|
660
|
+
totalDstSize += fcs;
|
|
402
661
|
}
|
|
662
|
+
/* skip to next frame */
|
|
403
663
|
{ size_t const frameSrcSize = ZSTD_findFrameCompressedSize(src, srcSize);
|
|
404
|
-
if (ZSTD_isError(frameSrcSize))
|
|
405
|
-
|
|
406
|
-
}
|
|
664
|
+
if (ZSTD_isError(frameSrcSize)) return ZSTD_CONTENTSIZE_ERROR;
|
|
665
|
+
assert(frameSrcSize <= srcSize);
|
|
407
666
|
|
|
408
667
|
src = (const BYTE *)src + frameSrcSize;
|
|
409
668
|
srcSize -= frameSrcSize;
|
|
@@ -433,12 +692,19 @@ unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize)
|
|
|
433
692
|
|
|
434
693
|
/** ZSTD_decodeFrameHeader() :
|
|
435
694
|
* `headerSize` must be the size provided by ZSTD_frameHeaderSize().
|
|
695
|
+
* If multiple DDict references are enabled, also will choose the correct DDict to use.
|
|
436
696
|
* @return : 0 if success, or an error code, which can be tested using ZSTD_isError() */
|
|
437
697
|
static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t headerSize)
|
|
438
698
|
{
|
|
439
699
|
size_t const result = ZSTD_getFrameHeader_advanced(&(dctx->fParams), src, headerSize, dctx->format);
|
|
440
700
|
if (ZSTD_isError(result)) return result; /* invalid header */
|
|
441
701
|
RETURN_ERROR_IF(result>0, srcSize_wrong, "headerSize too small");
|
|
702
|
+
|
|
703
|
+
/* Reference DDict requested by frame if dctx references multiple ddicts */
|
|
704
|
+
if (dctx->refMultipleDDicts == ZSTD_rmd_refMultipleDDicts && dctx->ddictSet) {
|
|
705
|
+
ZSTD_DCtx_selectFrameDDict(dctx);
|
|
706
|
+
}
|
|
707
|
+
|
|
442
708
|
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
|
443
709
|
/* Skip the dictID check in fuzzing mode, because it makes the search
|
|
444
710
|
* harder.
|
|
@@ -446,7 +712,9 @@ static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t he
|
|
|
446
712
|
RETURN_ERROR_IF(dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID),
|
|
447
713
|
dictionary_wrong, "");
|
|
448
714
|
#endif
|
|
449
|
-
|
|
715
|
+
dctx->validateChecksum = (dctx->fParams.checksumFlag && !dctx->forceIgnoreChecksum) ? 1 : 0;
|
|
716
|
+
if (dctx->validateChecksum) XXH64_reset(&dctx->xxhState, 0);
|
|
717
|
+
dctx->processedCSize += headerSize;
|
|
450
718
|
return 0;
|
|
451
719
|
}
|
|
452
720
|
|
|
@@ -461,7 +729,7 @@ static ZSTD_frameSizeInfo ZSTD_errorFrameSizeInfo(size_t ret)
|
|
|
461
729
|
static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize)
|
|
462
730
|
{
|
|
463
731
|
ZSTD_frameSizeInfo frameSizeInfo;
|
|
464
|
-
|
|
732
|
+
ZSTD_memset(&frameSizeInfo, 0, sizeof(ZSTD_frameSizeInfo));
|
|
465
733
|
|
|
466
734
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
|
|
467
735
|
if (ZSTD_isLegacy(src, srcSize))
|
|
@@ -516,10 +784,11 @@ static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize
|
|
|
516
784
|
ip += 4;
|
|
517
785
|
}
|
|
518
786
|
|
|
519
|
-
frameSizeInfo.
|
|
787
|
+
frameSizeInfo.nbBlocks = nbBlocks;
|
|
788
|
+
frameSizeInfo.compressedSize = (size_t)(ip - ipstart);
|
|
520
789
|
frameSizeInfo.decompressedBound = (zfh.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN)
|
|
521
790
|
? zfh.frameContentSize
|
|
522
|
-
: nbBlocks * zfh.blockSizeMax;
|
|
791
|
+
: (unsigned long long)nbBlocks * zfh.blockSizeMax;
|
|
523
792
|
return frameSizeInfo;
|
|
524
793
|
}
|
|
525
794
|
}
|
|
@@ -559,6 +828,48 @@ unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize)
|
|
|
559
828
|
return bound;
|
|
560
829
|
}
|
|
561
830
|
|
|
831
|
+
size_t ZSTD_decompressionMargin(void const* src, size_t srcSize)
|
|
832
|
+
{
|
|
833
|
+
size_t margin = 0;
|
|
834
|
+
unsigned maxBlockSize = 0;
|
|
835
|
+
|
|
836
|
+
/* Iterate over each frame */
|
|
837
|
+
while (srcSize > 0) {
|
|
838
|
+
ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize);
|
|
839
|
+
size_t const compressedSize = frameSizeInfo.compressedSize;
|
|
840
|
+
unsigned long long const decompressedBound = frameSizeInfo.decompressedBound;
|
|
841
|
+
ZSTD_frameHeader zfh;
|
|
842
|
+
|
|
843
|
+
FORWARD_IF_ERROR(ZSTD_getFrameHeader(&zfh, src, srcSize), "");
|
|
844
|
+
if (ZSTD_isError(compressedSize) || decompressedBound == ZSTD_CONTENTSIZE_ERROR)
|
|
845
|
+
return ERROR(corruption_detected);
|
|
846
|
+
|
|
847
|
+
if (zfh.frameType == ZSTD_frame) {
|
|
848
|
+
/* Add the frame header to our margin */
|
|
849
|
+
margin += zfh.headerSize;
|
|
850
|
+
/* Add the checksum to our margin */
|
|
851
|
+
margin += zfh.checksumFlag ? 4 : 0;
|
|
852
|
+
/* Add 3 bytes per block */
|
|
853
|
+
margin += 3 * frameSizeInfo.nbBlocks;
|
|
854
|
+
|
|
855
|
+
/* Compute the max block size */
|
|
856
|
+
maxBlockSize = MAX(maxBlockSize, zfh.blockSizeMax);
|
|
857
|
+
} else {
|
|
858
|
+
assert(zfh.frameType == ZSTD_skippableFrame);
|
|
859
|
+
/* Add the entire skippable frame size to our margin. */
|
|
860
|
+
margin += compressedSize;
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
assert(srcSize >= compressedSize);
|
|
864
|
+
src = (const BYTE*)src + compressedSize;
|
|
865
|
+
srcSize -= compressedSize;
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
/* Add the max block size back to the margin. */
|
|
869
|
+
margin += maxBlockSize;
|
|
870
|
+
|
|
871
|
+
return margin;
|
|
872
|
+
}
|
|
562
873
|
|
|
563
874
|
/*-*************************************************************
|
|
564
875
|
* Frame decoding
|
|
@@ -569,7 +880,7 @@ unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize)
|
|
|
569
880
|
size_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize)
|
|
570
881
|
{
|
|
571
882
|
DEBUGLOG(5, "ZSTD_insertBlock: %u bytes", (unsigned)blockSize);
|
|
572
|
-
ZSTD_checkContinuity(dctx, blockStart);
|
|
883
|
+
ZSTD_checkContinuity(dctx, blockStart, blockSize);
|
|
573
884
|
dctx->previousDstEnd = (const char*)blockStart + blockSize;
|
|
574
885
|
return blockSize;
|
|
575
886
|
}
|
|
@@ -579,12 +890,12 @@ static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity,
|
|
|
579
890
|
const void* src, size_t srcSize)
|
|
580
891
|
{
|
|
581
892
|
DEBUGLOG(5, "ZSTD_copyRawBlock");
|
|
893
|
+
RETURN_ERROR_IF(srcSize > dstCapacity, dstSize_tooSmall, "");
|
|
582
894
|
if (dst == NULL) {
|
|
583
895
|
if (srcSize == 0) return 0;
|
|
584
896
|
RETURN_ERROR(dstBuffer_null, "");
|
|
585
897
|
}
|
|
586
|
-
|
|
587
|
-
memcpy(dst, src, srcSize);
|
|
898
|
+
ZSTD_memmove(dst, src, srcSize);
|
|
588
899
|
return srcSize;
|
|
589
900
|
}
|
|
590
901
|
|
|
@@ -592,15 +903,41 @@ static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity,
|
|
|
592
903
|
BYTE b,
|
|
593
904
|
size_t regenSize)
|
|
594
905
|
{
|
|
906
|
+
RETURN_ERROR_IF(regenSize > dstCapacity, dstSize_tooSmall, "");
|
|
595
907
|
if (dst == NULL) {
|
|
596
908
|
if (regenSize == 0) return 0;
|
|
597
909
|
RETURN_ERROR(dstBuffer_null, "");
|
|
598
910
|
}
|
|
599
|
-
|
|
600
|
-
memset(dst, b, regenSize);
|
|
911
|
+
ZSTD_memset(dst, b, regenSize);
|
|
601
912
|
return regenSize;
|
|
602
913
|
}
|
|
603
914
|
|
|
915
|
+
static void ZSTD_DCtx_trace_end(ZSTD_DCtx const* dctx, U64 uncompressedSize, U64 compressedSize, unsigned streaming)
|
|
916
|
+
{
|
|
917
|
+
#if ZSTD_TRACE
|
|
918
|
+
if (dctx->traceCtx && ZSTD_trace_decompress_end != NULL) {
|
|
919
|
+
ZSTD_Trace trace;
|
|
920
|
+
ZSTD_memset(&trace, 0, sizeof(trace));
|
|
921
|
+
trace.version = ZSTD_VERSION_NUMBER;
|
|
922
|
+
trace.streaming = streaming;
|
|
923
|
+
if (dctx->ddict) {
|
|
924
|
+
trace.dictionaryID = ZSTD_getDictID_fromDDict(dctx->ddict);
|
|
925
|
+
trace.dictionarySize = ZSTD_DDict_dictSize(dctx->ddict);
|
|
926
|
+
trace.dictionaryIsCold = dctx->ddictIsCold;
|
|
927
|
+
}
|
|
928
|
+
trace.uncompressedSize = (size_t)uncompressedSize;
|
|
929
|
+
trace.compressedSize = (size_t)compressedSize;
|
|
930
|
+
trace.dctx = dctx;
|
|
931
|
+
ZSTD_trace_decompress_end(dctx->traceCtx, &trace);
|
|
932
|
+
}
|
|
933
|
+
#else
|
|
934
|
+
(void)dctx;
|
|
935
|
+
(void)uncompressedSize;
|
|
936
|
+
(void)compressedSize;
|
|
937
|
+
(void)streaming;
|
|
938
|
+
#endif
|
|
939
|
+
}
|
|
940
|
+
|
|
604
941
|
|
|
605
942
|
/*! ZSTD_decompressFrame() :
|
|
606
943
|
* @dctx must be properly initialized
|
|
@@ -610,8 +947,9 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|
|
610
947
|
void* dst, size_t dstCapacity,
|
|
611
948
|
const void** srcPtr, size_t *srcSizePtr)
|
|
612
949
|
{
|
|
613
|
-
const BYTE*
|
|
614
|
-
BYTE*
|
|
950
|
+
const BYTE* const istart = (const BYTE*)(*srcPtr);
|
|
951
|
+
const BYTE* ip = istart;
|
|
952
|
+
BYTE* const ostart = (BYTE*)dst;
|
|
615
953
|
BYTE* const oend = dstCapacity != 0 ? ostart + dstCapacity : ostart;
|
|
616
954
|
BYTE* op = ostart;
|
|
617
955
|
size_t remainingSrcSize = *srcSizePtr;
|
|
@@ -635,6 +973,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|
|
635
973
|
|
|
636
974
|
/* Loop on each block */
|
|
637
975
|
while (1) {
|
|
976
|
+
BYTE* oBlockEnd = oend;
|
|
638
977
|
size_t decodedSize;
|
|
639
978
|
blockProperties_t blockProperties;
|
|
640
979
|
size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSrcSize, &blockProperties);
|
|
@@ -644,16 +983,34 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|
|
644
983
|
remainingSrcSize -= ZSTD_blockHeaderSize;
|
|
645
984
|
RETURN_ERROR_IF(cBlockSize > remainingSrcSize, srcSize_wrong, "");
|
|
646
985
|
|
|
986
|
+
if (ip >= op && ip < oBlockEnd) {
|
|
987
|
+
/* We are decompressing in-place. Limit the output pointer so that we
|
|
988
|
+
* don't overwrite the block that we are currently reading. This will
|
|
989
|
+
* fail decompression if the input & output pointers aren't spaced
|
|
990
|
+
* far enough apart.
|
|
991
|
+
*
|
|
992
|
+
* This is important to set, even when the pointers are far enough
|
|
993
|
+
* apart, because ZSTD_decompressBlock_internal() can decide to store
|
|
994
|
+
* literals in the output buffer, after the block it is decompressing.
|
|
995
|
+
* Since we don't want anything to overwrite our input, we have to tell
|
|
996
|
+
* ZSTD_decompressBlock_internal to never write past ip.
|
|
997
|
+
*
|
|
998
|
+
* See ZSTD_allocateLiteralsBuffer() for reference.
|
|
999
|
+
*/
|
|
1000
|
+
oBlockEnd = op + (ip - op);
|
|
1001
|
+
}
|
|
1002
|
+
|
|
647
1003
|
switch(blockProperties.blockType)
|
|
648
1004
|
{
|
|
649
1005
|
case bt_compressed:
|
|
650
|
-
decodedSize = ZSTD_decompressBlock_internal(dctx, op,
|
|
1006
|
+
decodedSize = ZSTD_decompressBlock_internal(dctx, op, (size_t)(oBlockEnd-op), ip, cBlockSize, /* frame */ 1, not_streaming);
|
|
651
1007
|
break;
|
|
652
1008
|
case bt_raw :
|
|
653
|
-
|
|
1009
|
+
/* Use oend instead of oBlockEnd because this function is safe to overlap. It uses memmove. */
|
|
1010
|
+
decodedSize = ZSTD_copyRawBlock(op, (size_t)(oend-op), ip, cBlockSize);
|
|
654
1011
|
break;
|
|
655
1012
|
case bt_rle :
|
|
656
|
-
decodedSize = ZSTD_setRleBlock(op,
|
|
1013
|
+
decodedSize = ZSTD_setRleBlock(op, (size_t)(oBlockEnd-op), *ip, blockProperties.origSize);
|
|
657
1014
|
break;
|
|
658
1015
|
case bt_reserved :
|
|
659
1016
|
default:
|
|
@@ -661,7 +1018,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|
|
661
1018
|
}
|
|
662
1019
|
|
|
663
1020
|
if (ZSTD_isError(decodedSize)) return decodedSize;
|
|
664
|
-
if (dctx->
|
|
1021
|
+
if (dctx->validateChecksum)
|
|
665
1022
|
XXH64_update(&dctx->xxhState, op, decodedSize);
|
|
666
1023
|
if (decodedSize != 0)
|
|
667
1024
|
op += decodedSize;
|
|
@@ -676,19 +1033,22 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|
|
676
1033
|
corruption_detected, "");
|
|
677
1034
|
}
|
|
678
1035
|
if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */
|
|
679
|
-
U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState);
|
|
680
|
-
U32 checkRead;
|
|
681
1036
|
RETURN_ERROR_IF(remainingSrcSize<4, checksum_wrong, "");
|
|
682
|
-
|
|
683
|
-
|
|
1037
|
+
if (!dctx->forceIgnoreChecksum) {
|
|
1038
|
+
U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState);
|
|
1039
|
+
U32 checkRead;
|
|
1040
|
+
checkRead = MEM_readLE32(ip);
|
|
1041
|
+
RETURN_ERROR_IF(checkRead != checkCalc, checksum_wrong, "");
|
|
1042
|
+
}
|
|
684
1043
|
ip += 4;
|
|
685
1044
|
remainingSrcSize -= 4;
|
|
686
1045
|
}
|
|
687
|
-
|
|
1046
|
+
ZSTD_DCtx_trace_end(dctx, (U64)(op-ostart), (U64)(ip-istart), /* streaming */ 0);
|
|
688
1047
|
/* Allow caller to get size read */
|
|
1048
|
+
DEBUGLOG(4, "ZSTD_decompressFrame: decompressed frame of size %zi, consuming %zi bytes of input", op-ostart, ip - (const BYTE*)*srcPtr);
|
|
689
1049
|
*srcPtr = ip;
|
|
690
1050
|
*srcSizePtr = remainingSrcSize;
|
|
691
|
-
return op-ostart;
|
|
1051
|
+
return (size_t)(op-ostart);
|
|
692
1052
|
}
|
|
693
1053
|
|
|
694
1054
|
static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|
@@ -721,7 +1081,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|
|
721
1081
|
decodedSize = ZSTD_decompressLegacy(dst, dstCapacity, src, frameSize, dict, dictSize);
|
|
722
1082
|
if (ZSTD_isError(decodedSize)) return decodedSize;
|
|
723
1083
|
|
|
724
|
-
assert(decodedSize
|
|
1084
|
+
assert(decodedSize <= dstCapacity);
|
|
725
1085
|
dst = (BYTE*)dst + decodedSize;
|
|
726
1086
|
dstCapacity -= decodedSize;
|
|
727
1087
|
|
|
@@ -732,17 +1092,18 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|
|
732
1092
|
}
|
|
733
1093
|
#endif
|
|
734
1094
|
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
1095
|
+
if (srcSize >= 4) {
|
|
1096
|
+
U32 const magicNumber = MEM_readLE32(src);
|
|
1097
|
+
DEBUGLOG(5, "reading magic number %08X", (unsigned)magicNumber);
|
|
738
1098
|
if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
|
|
1099
|
+
/* skippable frame detected : skip it */
|
|
739
1100
|
size_t const skippableSize = readSkippableFrameSize(src, srcSize);
|
|
740
|
-
FORWARD_IF_ERROR(skippableSize, "
|
|
1101
|
+
FORWARD_IF_ERROR(skippableSize, "invalid skippable frame");
|
|
741
1102
|
assert(skippableSize <= srcSize);
|
|
742
1103
|
|
|
743
1104
|
src = (const BYTE *)src + skippableSize;
|
|
744
1105
|
srcSize -= skippableSize;
|
|
745
|
-
continue;
|
|
1106
|
+
continue; /* check next frame */
|
|
746
1107
|
} }
|
|
747
1108
|
|
|
748
1109
|
if (ddict) {
|
|
@@ -753,7 +1114,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|
|
753
1114
|
* use this in all cases but ddict */
|
|
754
1115
|
FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize), "");
|
|
755
1116
|
}
|
|
756
|
-
ZSTD_checkContinuity(dctx, dst);
|
|
1117
|
+
ZSTD_checkContinuity(dctx, dst, dstCapacity);
|
|
757
1118
|
|
|
758
1119
|
{ const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity,
|
|
759
1120
|
&src, &srcSize);
|
|
@@ -761,15 +1122,13 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|
|
761
1122
|
(ZSTD_getErrorCode(res) == ZSTD_error_prefix_unknown)
|
|
762
1123
|
&& (moreThan1Frame==1),
|
|
763
1124
|
srcSize_wrong,
|
|
764
|
-
"
|
|
765
|
-
"bytes are garbage:
|
|
766
|
-
"
|
|
767
|
-
"
|
|
768
|
-
"
|
|
769
|
-
"
|
|
770
|
-
"
|
|
771
|
-
"bytes. But this is _much_ less likely than a srcSize field "
|
|
772
|
-
"error.");
|
|
1125
|
+
"At least one frame successfully completed, "
|
|
1126
|
+
"but following bytes are garbage: "
|
|
1127
|
+
"it's more likely to be a srcSize error, "
|
|
1128
|
+
"specifying more input bytes than size of frame(s). "
|
|
1129
|
+
"Note: one could be unlucky, it might be a corruption error instead, "
|
|
1130
|
+
"happening right at the place where we expect zstd magic bytes. "
|
|
1131
|
+
"But this is _much_ less likely than a srcSize field error.");
|
|
773
1132
|
if (ZSTD_isError(res)) return res;
|
|
774
1133
|
assert(res <= dstCapacity);
|
|
775
1134
|
if (res != 0)
|
|
@@ -781,7 +1140,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|
|
781
1140
|
|
|
782
1141
|
RETURN_ERROR_IF(srcSize, srcSize_wrong, "input not entirely consumed");
|
|
783
1142
|
|
|
784
|
-
return (BYTE*)dst - (BYTE*)dststart;
|
|
1143
|
+
return (size_t)((BYTE*)dst - (BYTE*)dststart);
|
|
785
1144
|
}
|
|
786
1145
|
|
|
787
1146
|
size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
|
|
@@ -798,7 +1157,7 @@ static ZSTD_DDict const* ZSTD_getDDict(ZSTD_DCtx* dctx)
|
|
|
798
1157
|
switch (dctx->dictUses) {
|
|
799
1158
|
default:
|
|
800
1159
|
assert(0 /* Impossible */);
|
|
801
|
-
|
|
1160
|
+
ZSTD_FALLTHROUGH;
|
|
802
1161
|
case ZSTD_dont_use:
|
|
803
1162
|
ZSTD_clearDict(dctx);
|
|
804
1163
|
return NULL;
|
|
@@ -820,7 +1179,7 @@ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t sr
|
|
|
820
1179
|
{
|
|
821
1180
|
#if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE>=1)
|
|
822
1181
|
size_t regenSize;
|
|
823
|
-
ZSTD_DCtx* const dctx =
|
|
1182
|
+
ZSTD_DCtx* const dctx = ZSTD_createDCtx_internal(ZSTD_defaultCMem);
|
|
824
1183
|
RETURN_ERROR_IF(dctx==NULL, memory_allocation, "NULL pointer!");
|
|
825
1184
|
regenSize = ZSTD_decompressDCtx(dctx, dst, dstCapacity, src, srcSize);
|
|
826
1185
|
ZSTD_freeDCtx(dctx);
|
|
@@ -840,8 +1199,8 @@ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t sr
|
|
|
840
1199
|
size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx) { return dctx->expected; }
|
|
841
1200
|
|
|
842
1201
|
/**
|
|
843
|
-
* Similar to ZSTD_nextSrcSizeToDecompress(), but when
|
|
844
|
-
*
|
|
1202
|
+
* Similar to ZSTD_nextSrcSizeToDecompress(), but when a block input can be streamed, we
|
|
1203
|
+
* allow taking a partial block as the input. Currently only raw uncompressed blocks can
|
|
845
1204
|
* be streamed.
|
|
846
1205
|
*
|
|
847
1206
|
* For blocks that can be streamed, this allows us to reduce the latency until we produce
|
|
@@ -854,7 +1213,7 @@ static size_t ZSTD_nextSrcSizeToDecompressWithInputSize(ZSTD_DCtx* dctx, size_t
|
|
|
854
1213
|
return dctx->expected;
|
|
855
1214
|
if (dctx->bType != bt_raw)
|
|
856
1215
|
return dctx->expected;
|
|
857
|
-
return
|
|
1216
|
+
return BOUNDED(1, inputSize, dctx->expected);
|
|
858
1217
|
}
|
|
859
1218
|
|
|
860
1219
|
ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {
|
|
@@ -862,7 +1221,9 @@ ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {
|
|
|
862
1221
|
{
|
|
863
1222
|
default: /* should not happen */
|
|
864
1223
|
assert(0);
|
|
1224
|
+
ZSTD_FALLTHROUGH;
|
|
865
1225
|
case ZSTDds_getFrameHeaderSize:
|
|
1226
|
+
ZSTD_FALLTHROUGH;
|
|
866
1227
|
case ZSTDds_decodeFrameHeader:
|
|
867
1228
|
return ZSTDnit_frameHeader;
|
|
868
1229
|
case ZSTDds_decodeBlockHeader:
|
|
@@ -874,6 +1235,7 @@ ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {
|
|
|
874
1235
|
case ZSTDds_checkChecksum:
|
|
875
1236
|
return ZSTDnit_checksum;
|
|
876
1237
|
case ZSTDds_decodeSkippableHeader:
|
|
1238
|
+
ZSTD_FALLTHROUGH;
|
|
877
1239
|
case ZSTDds_skipFrame:
|
|
878
1240
|
return ZSTDnit_skippableFrame;
|
|
879
1241
|
}
|
|
@@ -890,7 +1252,9 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
|
890
1252
|
DEBUGLOG(5, "ZSTD_decompressContinue (srcSize:%u)", (unsigned)srcSize);
|
|
891
1253
|
/* Sanity check */
|
|
892
1254
|
RETURN_ERROR_IF(srcSize != ZSTD_nextSrcSizeToDecompressWithInputSize(dctx, srcSize), srcSize_wrong, "not allowed");
|
|
893
|
-
|
|
1255
|
+
ZSTD_checkContinuity(dctx, dst, dstCapacity);
|
|
1256
|
+
|
|
1257
|
+
dctx->processedCSize += srcSize;
|
|
894
1258
|
|
|
895
1259
|
switch (dctx->stage)
|
|
896
1260
|
{
|
|
@@ -899,21 +1263,21 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
|
899
1263
|
if (dctx->format == ZSTD_f_zstd1) { /* allows header */
|
|
900
1264
|
assert(srcSize >= ZSTD_FRAMEIDSIZE); /* to read skippable magic number */
|
|
901
1265
|
if ((MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
|
|
902
|
-
|
|
1266
|
+
ZSTD_memcpy(dctx->headerBuffer, src, srcSize);
|
|
903
1267
|
dctx->expected = ZSTD_SKIPPABLEHEADERSIZE - srcSize; /* remaining to load to get full skippable frame header */
|
|
904
1268
|
dctx->stage = ZSTDds_decodeSkippableHeader;
|
|
905
1269
|
return 0;
|
|
906
1270
|
} }
|
|
907
1271
|
dctx->headerSize = ZSTD_frameHeaderSize_internal(src, srcSize, dctx->format);
|
|
908
1272
|
if (ZSTD_isError(dctx->headerSize)) return dctx->headerSize;
|
|
909
|
-
|
|
1273
|
+
ZSTD_memcpy(dctx->headerBuffer, src, srcSize);
|
|
910
1274
|
dctx->expected = dctx->headerSize - srcSize;
|
|
911
1275
|
dctx->stage = ZSTDds_decodeFrameHeader;
|
|
912
1276
|
return 0;
|
|
913
1277
|
|
|
914
1278
|
case ZSTDds_decodeFrameHeader:
|
|
915
1279
|
assert(src != NULL);
|
|
916
|
-
|
|
1280
|
+
ZSTD_memcpy(dctx->headerBuffer + (dctx->headerSize - srcSize), src, srcSize);
|
|
917
1281
|
FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize), "");
|
|
918
1282
|
dctx->expected = ZSTD_blockHeaderSize;
|
|
919
1283
|
dctx->stage = ZSTDds_decodeBlockHeader;
|
|
@@ -955,7 +1319,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
|
955
1319
|
{
|
|
956
1320
|
case bt_compressed:
|
|
957
1321
|
DEBUGLOG(5, "ZSTD_decompressContinue: case bt_compressed");
|
|
958
|
-
rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 1);
|
|
1322
|
+
rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 1, is_streaming);
|
|
959
1323
|
dctx->expected = 0; /* Streaming not supported */
|
|
960
1324
|
break;
|
|
961
1325
|
case bt_raw :
|
|
@@ -977,7 +1341,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
|
977
1341
|
RETURN_ERROR_IF(rSize > dctx->fParams.blockSizeMax, corruption_detected, "Decompressed Block Size Exceeds Maximum");
|
|
978
1342
|
DEBUGLOG(5, "ZSTD_decompressContinue: decoded size from block : %u", (unsigned)rSize);
|
|
979
1343
|
dctx->decodedSize += rSize;
|
|
980
|
-
if (dctx->
|
|
1344
|
+
if (dctx->validateChecksum) XXH64_update(&dctx->xxhState, dst, rSize);
|
|
981
1345
|
dctx->previousDstEnd = (char*)dst + rSize;
|
|
982
1346
|
|
|
983
1347
|
/* Stay on the same stage until we are finished streaming the block. */
|
|
@@ -995,6 +1359,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
|
995
1359
|
dctx->expected = 4;
|
|
996
1360
|
dctx->stage = ZSTDds_checkChecksum;
|
|
997
1361
|
} else {
|
|
1362
|
+
ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1);
|
|
998
1363
|
dctx->expected = 0; /* ends here */
|
|
999
1364
|
dctx->stage = ZSTDds_getFrameHeaderSize;
|
|
1000
1365
|
}
|
|
@@ -1007,10 +1372,14 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
|
1007
1372
|
|
|
1008
1373
|
case ZSTDds_checkChecksum:
|
|
1009
1374
|
assert(srcSize == 4); /* guaranteed by dctx->expected */
|
|
1010
|
-
{
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1375
|
+
{
|
|
1376
|
+
if (dctx->validateChecksum) {
|
|
1377
|
+
U32 const h32 = (U32)XXH64_digest(&dctx->xxhState);
|
|
1378
|
+
U32 const check32 = MEM_readLE32(src);
|
|
1379
|
+
DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", (unsigned)h32, (unsigned)check32);
|
|
1380
|
+
RETURN_ERROR_IF(check32 != h32, checksum_wrong, "");
|
|
1381
|
+
}
|
|
1382
|
+
ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1);
|
|
1014
1383
|
dctx->expected = 0;
|
|
1015
1384
|
dctx->stage = ZSTDds_getFrameHeaderSize;
|
|
1016
1385
|
return 0;
|
|
@@ -1019,7 +1388,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
|
1019
1388
|
case ZSTDds_decodeSkippableHeader:
|
|
1020
1389
|
assert(src != NULL);
|
|
1021
1390
|
assert(srcSize <= ZSTD_SKIPPABLEHEADERSIZE);
|
|
1022
|
-
|
|
1391
|
+
ZSTD_memcpy(dctx->headerBuffer + (ZSTD_SKIPPABLEHEADERSIZE - srcSize), src, srcSize); /* complete skippable header */
|
|
1023
1392
|
dctx->expected = MEM_readLE32(dctx->headerBuffer + ZSTD_FRAMEIDSIZE); /* note : dctx->expected can grow seriously large, beyond local buffer size */
|
|
1024
1393
|
dctx->stage = ZSTDds_skipFrame;
|
|
1025
1394
|
return 0;
|
|
@@ -1031,7 +1400,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
|
1031
1400
|
|
|
1032
1401
|
default:
|
|
1033
1402
|
assert(0); /* impossible */
|
|
1034
|
-
RETURN_ERROR(GENERIC, "impossible to reach"); /* some
|
|
1403
|
+
RETURN_ERROR(GENERIC, "impossible to reach"); /* some compilers require default to do something */
|
|
1035
1404
|
}
|
|
1036
1405
|
}
|
|
1037
1406
|
|
|
@@ -1072,11 +1441,11 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
|
|
|
1072
1441
|
/* in minimal huffman, we always use X1 variants */
|
|
1073
1442
|
size_t const hSize = HUF_readDTableX1_wksp(entropy->hufTable,
|
|
1074
1443
|
dictPtr, dictEnd - dictPtr,
|
|
1075
|
-
workspace, workspaceSize);
|
|
1444
|
+
workspace, workspaceSize, /* flags */ 0);
|
|
1076
1445
|
#else
|
|
1077
1446
|
size_t const hSize = HUF_readDTableX2_wksp(entropy->hufTable,
|
|
1078
|
-
dictPtr, dictEnd - dictPtr,
|
|
1079
|
-
workspace, workspaceSize);
|
|
1447
|
+
dictPtr, (size_t)(dictEnd - dictPtr),
|
|
1448
|
+
workspace, workspaceSize, /* flags */ 0);
|
|
1080
1449
|
#endif
|
|
1081
1450
|
RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted, "");
|
|
1082
1451
|
dictPtr += hSize;
|
|
@@ -1084,40 +1453,46 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
|
|
|
1084
1453
|
|
|
1085
1454
|
{ short offcodeNCount[MaxOff+1];
|
|
1086
1455
|
unsigned offcodeMaxValue = MaxOff, offcodeLog;
|
|
1087
|
-
size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
|
|
1456
|
+
size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, (size_t)(dictEnd-dictPtr));
|
|
1088
1457
|
RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted, "");
|
|
1089
1458
|
RETURN_ERROR_IF(offcodeMaxValue > MaxOff, dictionary_corrupted, "");
|
|
1090
1459
|
RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted, "");
|
|
1091
1460
|
ZSTD_buildFSETable( entropy->OFTable,
|
|
1092
1461
|
offcodeNCount, offcodeMaxValue,
|
|
1093
1462
|
OF_base, OF_bits,
|
|
1094
|
-
offcodeLog
|
|
1463
|
+
offcodeLog,
|
|
1464
|
+
entropy->workspace, sizeof(entropy->workspace),
|
|
1465
|
+
/* bmi2 */0);
|
|
1095
1466
|
dictPtr += offcodeHeaderSize;
|
|
1096
1467
|
}
|
|
1097
1468
|
|
|
1098
1469
|
{ short matchlengthNCount[MaxML+1];
|
|
1099
1470
|
unsigned matchlengthMaxValue = MaxML, matchlengthLog;
|
|
1100
|
-
size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);
|
|
1471
|
+
size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, (size_t)(dictEnd-dictPtr));
|
|
1101
1472
|
RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted, "");
|
|
1102
1473
|
RETURN_ERROR_IF(matchlengthMaxValue > MaxML, dictionary_corrupted, "");
|
|
1103
1474
|
RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted, "");
|
|
1104
1475
|
ZSTD_buildFSETable( entropy->MLTable,
|
|
1105
1476
|
matchlengthNCount, matchlengthMaxValue,
|
|
1106
1477
|
ML_base, ML_bits,
|
|
1107
|
-
matchlengthLog
|
|
1478
|
+
matchlengthLog,
|
|
1479
|
+
entropy->workspace, sizeof(entropy->workspace),
|
|
1480
|
+
/* bmi2 */ 0);
|
|
1108
1481
|
dictPtr += matchlengthHeaderSize;
|
|
1109
1482
|
}
|
|
1110
1483
|
|
|
1111
1484
|
{ short litlengthNCount[MaxLL+1];
|
|
1112
1485
|
unsigned litlengthMaxValue = MaxLL, litlengthLog;
|
|
1113
|
-
size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);
|
|
1486
|
+
size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, (size_t)(dictEnd-dictPtr));
|
|
1114
1487
|
RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted, "");
|
|
1115
1488
|
RETURN_ERROR_IF(litlengthMaxValue > MaxLL, dictionary_corrupted, "");
|
|
1116
1489
|
RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted, "");
|
|
1117
1490
|
ZSTD_buildFSETable( entropy->LLTable,
|
|
1118
1491
|
litlengthNCount, litlengthMaxValue,
|
|
1119
1492
|
LL_base, LL_bits,
|
|
1120
|
-
litlengthLog
|
|
1493
|
+
litlengthLog,
|
|
1494
|
+
entropy->workspace, sizeof(entropy->workspace),
|
|
1495
|
+
/* bmi2 */ 0);
|
|
1121
1496
|
dictPtr += litlengthHeaderSize;
|
|
1122
1497
|
}
|
|
1123
1498
|
|
|
@@ -1131,7 +1506,7 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
|
|
|
1131
1506
|
entropy->rep[i] = rep;
|
|
1132
1507
|
} }
|
|
1133
1508
|
|
|
1134
|
-
return dictPtr - (const BYTE*)dict;
|
|
1509
|
+
return (size_t)(dictPtr - (const BYTE*)dict);
|
|
1135
1510
|
}
|
|
1136
1511
|
|
|
1137
1512
|
static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
|
|
@@ -1158,19 +1533,23 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
|
|
|
1158
1533
|
size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
|
|
1159
1534
|
{
|
|
1160
1535
|
assert(dctx != NULL);
|
|
1536
|
+
#if ZSTD_TRACE
|
|
1537
|
+
dctx->traceCtx = (ZSTD_trace_decompress_begin != NULL) ? ZSTD_trace_decompress_begin(dctx) : 0;
|
|
1538
|
+
#endif
|
|
1161
1539
|
dctx->expected = ZSTD_startingInputLength(dctx->format); /* dctx->format must be properly set */
|
|
1162
1540
|
dctx->stage = ZSTDds_getFrameHeaderSize;
|
|
1541
|
+
dctx->processedCSize = 0;
|
|
1163
1542
|
dctx->decodedSize = 0;
|
|
1164
1543
|
dctx->previousDstEnd = NULL;
|
|
1165
1544
|
dctx->prefixStart = NULL;
|
|
1166
1545
|
dctx->virtualStart = NULL;
|
|
1167
1546
|
dctx->dictEnd = NULL;
|
|
1168
|
-
dctx->entropy.hufTable[0] = (HUF_DTable)((
|
|
1547
|
+
dctx->entropy.hufTable[0] = (HUF_DTable)((ZSTD_HUFFDTABLE_CAPACITY_LOG)*0x1000001); /* cover both little and big endian */
|
|
1169
1548
|
dctx->litEntropy = dctx->fseEntropy = 0;
|
|
1170
1549
|
dctx->dictID = 0;
|
|
1171
1550
|
dctx->bType = bt_reserved;
|
|
1172
1551
|
ZSTD_STATIC_ASSERT(sizeof(dctx->entropy.rep) == sizeof(repStartValue));
|
|
1173
|
-
|
|
1552
|
+
ZSTD_memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */
|
|
1174
1553
|
dctx->LLTptr = dctx->entropy.LLTable;
|
|
1175
1554
|
dctx->MLTptr = dctx->entropy.MLTable;
|
|
1176
1555
|
dctx->OFTptr = dctx->entropy.OFTable;
|
|
@@ -1227,7 +1606,7 @@ unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize)
|
|
|
1227
1606
|
* This could for one of the following reasons :
|
|
1228
1607
|
* - The frame does not require a dictionary (most common case).
|
|
1229
1608
|
* - The frame was built with dictID intentionally removed.
|
|
1230
|
-
* Needed dictionary is a hidden information.
|
|
1609
|
+
* Needed dictionary is a hidden piece of information.
|
|
1231
1610
|
* Note : this use case also happens when using a non-conformant dictionary.
|
|
1232
1611
|
* - `srcSize` is too small, and as a result, frame header could not be decoded.
|
|
1233
1612
|
* Note : possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`.
|
|
@@ -1236,7 +1615,7 @@ unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize)
|
|
|
1236
1615
|
* ZSTD_getFrameHeader(), which will provide a more precise error code. */
|
|
1237
1616
|
unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize)
|
|
1238
1617
|
{
|
|
1239
|
-
ZSTD_frameHeader zfp = { 0, 0, 0, ZSTD_frame, 0, 0, 0 };
|
|
1618
|
+
ZSTD_frameHeader zfp = { 0, 0, 0, ZSTD_frame, 0, 0, 0, 0, 0 };
|
|
1240
1619
|
size_t const hError = ZSTD_getFrameHeader(&zfp, src, srcSize);
|
|
1241
1620
|
if (ZSTD_isError(hError)) return 0;
|
|
1242
1621
|
return zfp.dictID;
|
|
@@ -1265,7 +1644,7 @@ size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,
|
|
|
1265
1644
|
ZSTD_DStream* ZSTD_createDStream(void)
|
|
1266
1645
|
{
|
|
1267
1646
|
DEBUGLOG(3, "ZSTD_createDStream");
|
|
1268
|
-
return
|
|
1647
|
+
return ZSTD_createDCtx_internal(ZSTD_defaultCMem);
|
|
1269
1648
|
}
|
|
1270
1649
|
|
|
1271
1650
|
ZSTD_DStream* ZSTD_initStaticDStream(void *workspace, size_t workspaceSize)
|
|
@@ -1275,7 +1654,7 @@ ZSTD_DStream* ZSTD_initStaticDStream(void *workspace, size_t workspaceSize)
|
|
|
1275
1654
|
|
|
1276
1655
|
ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem)
|
|
1277
1656
|
{
|
|
1278
|
-
return
|
|
1657
|
+
return ZSTD_createDCtx_internal(customMem);
|
|
1279
1658
|
}
|
|
1280
1659
|
|
|
1281
1660
|
size_t ZSTD_freeDStream(ZSTD_DStream* zds)
|
|
@@ -1343,7 +1722,9 @@ size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t di
|
|
|
1343
1722
|
size_t ZSTD_initDStream(ZSTD_DStream* zds)
|
|
1344
1723
|
{
|
|
1345
1724
|
DEBUGLOG(4, "ZSTD_initDStream");
|
|
1346
|
-
|
|
1725
|
+
FORWARD_IF_ERROR(ZSTD_DCtx_reset(zds, ZSTD_reset_session_only), "");
|
|
1726
|
+
FORWARD_IF_ERROR(ZSTD_DCtx_refDDict(zds, NULL), "");
|
|
1727
|
+
return ZSTD_startingInputLength(zds->format);
|
|
1347
1728
|
}
|
|
1348
1729
|
|
|
1349
1730
|
/* ZSTD_initDStream_usingDDict() :
|
|
@@ -1351,6 +1732,7 @@ size_t ZSTD_initDStream(ZSTD_DStream* zds)
|
|
|
1351
1732
|
* this function cannot fail */
|
|
1352
1733
|
size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
|
|
1353
1734
|
{
|
|
1735
|
+
DEBUGLOG(4, "ZSTD_initDStream_usingDDict");
|
|
1354
1736
|
FORWARD_IF_ERROR( ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only) , "");
|
|
1355
1737
|
FORWARD_IF_ERROR( ZSTD_DCtx_refDDict(dctx, ddict) , "");
|
|
1356
1738
|
return ZSTD_startingInputLength(dctx->format);
|
|
@@ -1361,6 +1743,7 @@ size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
|
|
|
1361
1743
|
* this function cannot fail */
|
|
1362
1744
|
size_t ZSTD_resetDStream(ZSTD_DStream* dctx)
|
|
1363
1745
|
{
|
|
1746
|
+
DEBUGLOG(4, "ZSTD_resetDStream");
|
|
1364
1747
|
FORWARD_IF_ERROR(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only), "");
|
|
1365
1748
|
return ZSTD_startingInputLength(dctx->format);
|
|
1366
1749
|
}
|
|
@@ -1373,6 +1756,16 @@ size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
|
|
|
1373
1756
|
if (ddict) {
|
|
1374
1757
|
dctx->ddict = ddict;
|
|
1375
1758
|
dctx->dictUses = ZSTD_use_indefinitely;
|
|
1759
|
+
if (dctx->refMultipleDDicts == ZSTD_rmd_refMultipleDDicts) {
|
|
1760
|
+
if (dctx->ddictSet == NULL) {
|
|
1761
|
+
dctx->ddictSet = ZSTD_createDDictHashSet(dctx->customMem);
|
|
1762
|
+
if (!dctx->ddictSet) {
|
|
1763
|
+
RETURN_ERROR(memory_allocation, "Failed to allocate memory for hash set!");
|
|
1764
|
+
}
|
|
1765
|
+
}
|
|
1766
|
+
assert(!dctx->staticSize); /* Impossible: ddictSet cannot have been allocated if static dctx */
|
|
1767
|
+
FORWARD_IF_ERROR(ZSTD_DDictHashSet_addDDict(dctx->ddictSet, ddict, dctx->customMem), "");
|
|
1768
|
+
}
|
|
1376
1769
|
}
|
|
1377
1770
|
return 0;
|
|
1378
1771
|
}
|
|
@@ -1394,7 +1787,7 @@ size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize)
|
|
|
1394
1787
|
|
|
1395
1788
|
size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format)
|
|
1396
1789
|
{
|
|
1397
|
-
return ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, format);
|
|
1790
|
+
return ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, (int)format);
|
|
1398
1791
|
}
|
|
1399
1792
|
|
|
1400
1793
|
ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)
|
|
@@ -1411,9 +1804,22 @@ ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)
|
|
|
1411
1804
|
ZSTD_STATIC_ASSERT(ZSTD_f_zstd1 < ZSTD_f_zstd1_magicless);
|
|
1412
1805
|
return bounds;
|
|
1413
1806
|
case ZSTD_d_stableOutBuffer:
|
|
1414
|
-
bounds.lowerBound = (int)
|
|
1415
|
-
bounds.upperBound = (int)
|
|
1807
|
+
bounds.lowerBound = (int)ZSTD_bm_buffered;
|
|
1808
|
+
bounds.upperBound = (int)ZSTD_bm_stable;
|
|
1416
1809
|
return bounds;
|
|
1810
|
+
case ZSTD_d_forceIgnoreChecksum:
|
|
1811
|
+
bounds.lowerBound = (int)ZSTD_d_validateChecksum;
|
|
1812
|
+
bounds.upperBound = (int)ZSTD_d_ignoreChecksum;
|
|
1813
|
+
return bounds;
|
|
1814
|
+
case ZSTD_d_refMultipleDDicts:
|
|
1815
|
+
bounds.lowerBound = (int)ZSTD_rmd_refSingleDDict;
|
|
1816
|
+
bounds.upperBound = (int)ZSTD_rmd_refMultipleDDicts;
|
|
1817
|
+
return bounds;
|
|
1818
|
+
case ZSTD_d_disableHuffmanAssembly:
|
|
1819
|
+
bounds.lowerBound = 0;
|
|
1820
|
+
bounds.upperBound = 1;
|
|
1821
|
+
return bounds;
|
|
1822
|
+
|
|
1417
1823
|
default:;
|
|
1418
1824
|
}
|
|
1419
1825
|
bounds.error = ERROR(parameter_unsupported);
|
|
@@ -1436,6 +1842,32 @@ static int ZSTD_dParam_withinBounds(ZSTD_dParameter dParam, int value)
|
|
|
1436
1842
|
RETURN_ERROR_IF(!ZSTD_dParam_withinBounds(p, v), parameter_outOfBound, ""); \
|
|
1437
1843
|
}
|
|
1438
1844
|
|
|
1845
|
+
size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value)
|
|
1846
|
+
{
|
|
1847
|
+
switch (param) {
|
|
1848
|
+
case ZSTD_d_windowLogMax:
|
|
1849
|
+
*value = (int)ZSTD_highbit32((U32)dctx->maxWindowSize);
|
|
1850
|
+
return 0;
|
|
1851
|
+
case ZSTD_d_format:
|
|
1852
|
+
*value = (int)dctx->format;
|
|
1853
|
+
return 0;
|
|
1854
|
+
case ZSTD_d_stableOutBuffer:
|
|
1855
|
+
*value = (int)dctx->outBufferMode;
|
|
1856
|
+
return 0;
|
|
1857
|
+
case ZSTD_d_forceIgnoreChecksum:
|
|
1858
|
+
*value = (int)dctx->forceIgnoreChecksum;
|
|
1859
|
+
return 0;
|
|
1860
|
+
case ZSTD_d_refMultipleDDicts:
|
|
1861
|
+
*value = (int)dctx->refMultipleDDicts;
|
|
1862
|
+
return 0;
|
|
1863
|
+
case ZSTD_d_disableHuffmanAssembly:
|
|
1864
|
+
*value = (int)dctx->disableHufAsm;
|
|
1865
|
+
return 0;
|
|
1866
|
+
default:;
|
|
1867
|
+
}
|
|
1868
|
+
RETURN_ERROR(parameter_unsupported, "");
|
|
1869
|
+
}
|
|
1870
|
+
|
|
1439
1871
|
size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value)
|
|
1440
1872
|
{
|
|
1441
1873
|
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
|
|
@@ -1451,7 +1883,22 @@ size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value
|
|
|
1451
1883
|
return 0;
|
|
1452
1884
|
case ZSTD_d_stableOutBuffer:
|
|
1453
1885
|
CHECK_DBOUNDS(ZSTD_d_stableOutBuffer, value);
|
|
1454
|
-
dctx->outBufferMode = (
|
|
1886
|
+
dctx->outBufferMode = (ZSTD_bufferMode_e)value;
|
|
1887
|
+
return 0;
|
|
1888
|
+
case ZSTD_d_forceIgnoreChecksum:
|
|
1889
|
+
CHECK_DBOUNDS(ZSTD_d_forceIgnoreChecksum, value);
|
|
1890
|
+
dctx->forceIgnoreChecksum = (ZSTD_forceIgnoreChecksum_e)value;
|
|
1891
|
+
return 0;
|
|
1892
|
+
case ZSTD_d_refMultipleDDicts:
|
|
1893
|
+
CHECK_DBOUNDS(ZSTD_d_refMultipleDDicts, value);
|
|
1894
|
+
if (dctx->staticSize != 0) {
|
|
1895
|
+
RETURN_ERROR(parameter_unsupported, "Static dctx does not support multiple DDicts!");
|
|
1896
|
+
}
|
|
1897
|
+
dctx->refMultipleDDicts = (ZSTD_refMultipleDDicts_e)value;
|
|
1898
|
+
return 0;
|
|
1899
|
+
case ZSTD_d_disableHuffmanAssembly:
|
|
1900
|
+
CHECK_DBOUNDS(ZSTD_d_disableHuffmanAssembly, value);
|
|
1901
|
+
dctx->disableHufAsm = value != 0;
|
|
1455
1902
|
return 0;
|
|
1456
1903
|
default:;
|
|
1457
1904
|
}
|
|
@@ -1469,8 +1916,7 @@ size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset)
|
|
|
1469
1916
|
|| (reset == ZSTD_reset_session_and_parameters) ) {
|
|
1470
1917
|
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
|
|
1471
1918
|
ZSTD_clearDict(dctx);
|
|
1472
|
-
dctx
|
|
1473
|
-
dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
|
|
1919
|
+
ZSTD_DCtx_resetParameters(dctx);
|
|
1474
1920
|
}
|
|
1475
1921
|
return 0;
|
|
1476
1922
|
}
|
|
@@ -1484,7 +1930,8 @@ size_t ZSTD_sizeof_DStream(const ZSTD_DStream* dctx)
|
|
|
1484
1930
|
size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize)
|
|
1485
1931
|
{
|
|
1486
1932
|
size_t const blockSize = (size_t) MIN(windowSize, ZSTD_BLOCKSIZE_MAX);
|
|
1487
|
-
|
|
1933
|
+
/* space is needed to store the litbuffer after the output of a given block without stomping the extDict of a previous run, as well as to cover both windows against wildcopy*/
|
|
1934
|
+
unsigned long long const neededRBSize = windowSize + blockSize + ZSTD_BLOCKSIZE_MAX + (WILDCOPY_OVERLENGTH * 2);
|
|
1488
1935
|
unsigned long long const neededSize = MIN(frameContentSize, neededRBSize);
|
|
1489
1936
|
size_t const minRBSize = (size_t) neededSize;
|
|
1490
1937
|
RETURN_ERROR_IF((unsigned long long)minRBSize != neededSize,
|
|
@@ -1524,7 +1971,7 @@ static void ZSTD_DCtx_updateOversizedDuration(ZSTD_DStream* zds, size_t const ne
|
|
|
1524
1971
|
{
|
|
1525
1972
|
if (ZSTD_DCtx_isOverflow(zds, neededInBuffSize, neededOutBuffSize))
|
|
1526
1973
|
zds->oversizedDuration++;
|
|
1527
|
-
else
|
|
1974
|
+
else
|
|
1528
1975
|
zds->oversizedDuration = 0;
|
|
1529
1976
|
}
|
|
1530
1977
|
|
|
@@ -1538,7 +1985,7 @@ static size_t ZSTD_checkOutBuffer(ZSTD_DStream const* zds, ZSTD_outBuffer const*
|
|
|
1538
1985
|
{
|
|
1539
1986
|
ZSTD_outBuffer const expect = zds->expectedOutBuffer;
|
|
1540
1987
|
/* No requirement when ZSTD_obm_stable is not enabled. */
|
|
1541
|
-
if (zds->outBufferMode !=
|
|
1988
|
+
if (zds->outBufferMode != ZSTD_bm_stable)
|
|
1542
1989
|
return 0;
|
|
1543
1990
|
/* Any buffer is allowed in zdss_init, this must be the same for every other call until
|
|
1544
1991
|
* the context is reset.
|
|
@@ -1548,7 +1995,7 @@ static size_t ZSTD_checkOutBuffer(ZSTD_DStream const* zds, ZSTD_outBuffer const*
|
|
|
1548
1995
|
/* The buffer must match our expectation exactly. */
|
|
1549
1996
|
if (expect.dst == output->dst && expect.pos == output->pos && expect.size == output->size)
|
|
1550
1997
|
return 0;
|
|
1551
|
-
RETURN_ERROR(dstBuffer_wrong, "
|
|
1998
|
+
RETURN_ERROR(dstBuffer_wrong, "ZSTD_d_stableOutBuffer enabled but output differs!");
|
|
1552
1999
|
}
|
|
1553
2000
|
|
|
1554
2001
|
/* Calls ZSTD_decompressContinue() with the right parameters for ZSTD_decompressStream()
|
|
@@ -1560,7 +2007,7 @@ static size_t ZSTD_decompressContinueStream(
|
|
|
1560
2007
|
ZSTD_DStream* zds, char** op, char* oend,
|
|
1561
2008
|
void const* src, size_t srcSize) {
|
|
1562
2009
|
int const isSkipFrame = ZSTD_isSkipFrame(zds);
|
|
1563
|
-
if (zds->outBufferMode ==
|
|
2010
|
+
if (zds->outBufferMode == ZSTD_bm_buffered) {
|
|
1564
2011
|
size_t const dstSize = isSkipFrame ? 0 : zds->outBuffSize - zds->outStart;
|
|
1565
2012
|
size_t const decodedSize = ZSTD_decompressContinue(zds,
|
|
1566
2013
|
zds->outBuff + zds->outStart, dstSize, src, srcSize);
|
|
@@ -1573,14 +2020,14 @@ static size_t ZSTD_decompressContinueStream(
|
|
|
1573
2020
|
}
|
|
1574
2021
|
} else {
|
|
1575
2022
|
/* Write directly into the output buffer */
|
|
1576
|
-
size_t const dstSize = isSkipFrame ? 0 : oend - *op;
|
|
2023
|
+
size_t const dstSize = isSkipFrame ? 0 : (size_t)(oend - *op);
|
|
1577
2024
|
size_t const decodedSize = ZSTD_decompressContinue(zds, *op, dstSize, src, srcSize);
|
|
1578
2025
|
FORWARD_IF_ERROR(decodedSize, "");
|
|
1579
2026
|
*op += decodedSize;
|
|
1580
2027
|
/* Flushing is not needed. */
|
|
1581
2028
|
zds->streamStage = zdss_read;
|
|
1582
2029
|
assert(*op <= oend);
|
|
1583
|
-
assert(zds->outBufferMode ==
|
|
2030
|
+
assert(zds->outBufferMode == ZSTD_bm_stable);
|
|
1584
2031
|
}
|
|
1585
2032
|
return 0;
|
|
1586
2033
|
}
|
|
@@ -1618,10 +2065,12 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1618
2065
|
DEBUGLOG(5, "stage zdss_init => transparent reset ");
|
|
1619
2066
|
zds->streamStage = zdss_loadHeader;
|
|
1620
2067
|
zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
|
|
2068
|
+
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
|
1621
2069
|
zds->legacyVersion = 0;
|
|
2070
|
+
#endif
|
|
1622
2071
|
zds->hostageByte = 0;
|
|
1623
2072
|
zds->expectedOutBuffer = *output;
|
|
1624
|
-
|
|
2073
|
+
ZSTD_FALLTHROUGH;
|
|
1625
2074
|
|
|
1626
2075
|
case zdss_loadHeader :
|
|
1627
2076
|
DEBUGLOG(5, "stage zdss_loadHeader (srcSize : %u)", (U32)(iend - ip));
|
|
@@ -1635,7 +2084,9 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1635
2084
|
} }
|
|
1636
2085
|
#endif
|
|
1637
2086
|
{ size_t const hSize = ZSTD_getFrameHeader_advanced(&zds->fParams, zds->headerBuffer, zds->lhSize, zds->format);
|
|
1638
|
-
|
|
2087
|
+
if (zds->refMultipleDDicts && zds->ddictSet) {
|
|
2088
|
+
ZSTD_DCtx_selectFrameDDict(zds);
|
|
2089
|
+
}
|
|
1639
2090
|
if (ZSTD_isError(hSize)) {
|
|
1640
2091
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
|
1641
2092
|
U32 const legacyVersion = ZSTD_isLegacy(istart, iend-istart);
|
|
@@ -1663,14 +2114,19 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1663
2114
|
assert(iend >= ip);
|
|
1664
2115
|
if (toLoad > remainingInput) { /* not enough input to load full header */
|
|
1665
2116
|
if (remainingInput > 0) {
|
|
1666
|
-
|
|
2117
|
+
ZSTD_memcpy(zds->headerBuffer + zds->lhSize, ip, remainingInput);
|
|
1667
2118
|
zds->lhSize += remainingInput;
|
|
1668
2119
|
}
|
|
1669
2120
|
input->pos = input->size;
|
|
2121
|
+
/* check first few bytes */
|
|
2122
|
+
FORWARD_IF_ERROR(
|
|
2123
|
+
ZSTD_getFrameHeader_advanced(&zds->fParams, zds->headerBuffer, zds->lhSize, zds->format),
|
|
2124
|
+
"First few bytes detected incorrect" );
|
|
2125
|
+
/* return hint input size */
|
|
1670
2126
|
return (MAX((size_t)ZSTD_FRAMEHEADERSIZE_MIN(zds->format), hSize) - zds->lhSize) + ZSTD_blockHeaderSize; /* remaining header bytes + next block header */
|
|
1671
2127
|
}
|
|
1672
2128
|
assert(ip != NULL);
|
|
1673
|
-
|
|
2129
|
+
ZSTD_memcpy(zds->headerBuffer + zds->lhSize, ip, toLoad); zds->lhSize = hSize; ip += toLoad;
|
|
1674
2130
|
break;
|
|
1675
2131
|
} }
|
|
1676
2132
|
|
|
@@ -1678,14 +2134,15 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1678
2134
|
if (zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
|
|
1679
2135
|
&& zds->fParams.frameType != ZSTD_skippableFrame
|
|
1680
2136
|
&& (U64)(size_t)(oend-op) >= zds->fParams.frameContentSize) {
|
|
1681
|
-
size_t const cSize = ZSTD_findFrameCompressedSize(istart, iend-istart);
|
|
2137
|
+
size_t const cSize = ZSTD_findFrameCompressedSize(istart, (size_t)(iend-istart));
|
|
1682
2138
|
if (cSize <= (size_t)(iend-istart)) {
|
|
1683
2139
|
/* shortcut : using single-pass mode */
|
|
1684
|
-
size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, oend-op, istart, cSize, ZSTD_getDDict(zds));
|
|
2140
|
+
size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, (size_t)(oend-op), istart, cSize, ZSTD_getDDict(zds));
|
|
1685
2141
|
if (ZSTD_isError(decompressedSize)) return decompressedSize;
|
|
1686
2142
|
DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()")
|
|
2143
|
+
assert(istart != NULL);
|
|
1687
2144
|
ip = istart + cSize;
|
|
1688
|
-
op
|
|
2145
|
+
op = op ? op + decompressedSize : op; /* can occur if frameContentSize = 0 (empty frame) */
|
|
1689
2146
|
zds->expected = 0;
|
|
1690
2147
|
zds->streamStage = zdss_init;
|
|
1691
2148
|
someMoreWork = 0;
|
|
@@ -1693,7 +2150,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1693
2150
|
} }
|
|
1694
2151
|
|
|
1695
2152
|
/* Check output buffer is large enough for ZSTD_odm_stable. */
|
|
1696
|
-
if (zds->outBufferMode ==
|
|
2153
|
+
if (zds->outBufferMode == ZSTD_bm_stable
|
|
1697
2154
|
&& zds->fParams.frameType != ZSTD_skippableFrame
|
|
1698
2155
|
&& zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
|
|
1699
2156
|
&& (U64)(size_t)(oend-op) < zds->fParams.frameContentSize) {
|
|
@@ -1723,7 +2180,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1723
2180
|
|
|
1724
2181
|
/* Adapt buffer sizes to frame header instructions */
|
|
1725
2182
|
{ size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */);
|
|
1726
|
-
size_t const neededOutBuffSize = zds->outBufferMode ==
|
|
2183
|
+
size_t const neededOutBuffSize = zds->outBufferMode == ZSTD_bm_buffered
|
|
1727
2184
|
? ZSTD_decodingBufferSize_min(zds->fParams.windowSize, zds->fParams.frameContentSize)
|
|
1728
2185
|
: 0;
|
|
1729
2186
|
|
|
@@ -1731,7 +2188,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1731
2188
|
|
|
1732
2189
|
{ int const tooSmall = (zds->inBuffSize < neededInBuffSize) || (zds->outBuffSize < neededOutBuffSize);
|
|
1733
2190
|
int const tooLarge = ZSTD_DCtx_isOversizedTooLong(zds);
|
|
1734
|
-
|
|
2191
|
+
|
|
1735
2192
|
if (tooSmall || tooLarge) {
|
|
1736
2193
|
size_t const bufferSize = neededInBuffSize + neededOutBuffSize;
|
|
1737
2194
|
DEBUGLOG(4, "inBuff : from %u to %u",
|
|
@@ -1745,10 +2202,10 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1745
2202
|
bufferSize > zds->staticSize - sizeof(ZSTD_DCtx),
|
|
1746
2203
|
memory_allocation, "");
|
|
1747
2204
|
} else {
|
|
1748
|
-
|
|
2205
|
+
ZSTD_customFree(zds->inBuff, zds->customMem);
|
|
1749
2206
|
zds->inBuffSize = 0;
|
|
1750
2207
|
zds->outBuffSize = 0;
|
|
1751
|
-
zds->inBuff = (char*)
|
|
2208
|
+
zds->inBuff = (char*)ZSTD_customMalloc(bufferSize, zds->customMem);
|
|
1752
2209
|
RETURN_ERROR_IF(zds->inBuff == NULL, memory_allocation, "");
|
|
1753
2210
|
}
|
|
1754
2211
|
zds->inBuffSize = neededInBuffSize;
|
|
@@ -1756,11 +2213,11 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1756
2213
|
zds->outBuffSize = neededOutBuffSize;
|
|
1757
2214
|
} } }
|
|
1758
2215
|
zds->streamStage = zdss_read;
|
|
1759
|
-
|
|
2216
|
+
ZSTD_FALLTHROUGH;
|
|
1760
2217
|
|
|
1761
2218
|
case zdss_read:
|
|
1762
2219
|
DEBUGLOG(5, "stage zdss_read");
|
|
1763
|
-
{ size_t const neededInSize = ZSTD_nextSrcSizeToDecompressWithInputSize(zds, iend - ip);
|
|
2220
|
+
{ size_t const neededInSize = ZSTD_nextSrcSizeToDecompressWithInputSize(zds, (size_t)(iend - ip));
|
|
1764
2221
|
DEBUGLOG(5, "neededInSize = %u", (U32)neededInSize);
|
|
1765
2222
|
if (neededInSize==0) { /* end of frame */
|
|
1766
2223
|
zds->streamStage = zdss_init;
|
|
@@ -1769,13 +2226,14 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1769
2226
|
}
|
|
1770
2227
|
if ((size_t)(iend-ip) >= neededInSize) { /* decode directly from src */
|
|
1771
2228
|
FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, ip, neededInSize), "");
|
|
2229
|
+
assert(ip != NULL);
|
|
1772
2230
|
ip += neededInSize;
|
|
1773
2231
|
/* Function modifies the stage so we must break */
|
|
1774
2232
|
break;
|
|
1775
2233
|
} }
|
|
1776
2234
|
if (ip==iend) { someMoreWork = 0; break; } /* no more input */
|
|
1777
2235
|
zds->streamStage = zdss_load;
|
|
1778
|
-
|
|
2236
|
+
ZSTD_FALLTHROUGH;
|
|
1779
2237
|
|
|
1780
2238
|
case zdss_load:
|
|
1781
2239
|
{ size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds);
|
|
@@ -1783,17 +2241,20 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1783
2241
|
int const isSkipFrame = ZSTD_isSkipFrame(zds);
|
|
1784
2242
|
size_t loadedSize;
|
|
1785
2243
|
/* At this point we shouldn't be decompressing a block that we can stream. */
|
|
1786
|
-
assert(neededInSize == ZSTD_nextSrcSizeToDecompressWithInputSize(zds, iend - ip));
|
|
2244
|
+
assert(neededInSize == ZSTD_nextSrcSizeToDecompressWithInputSize(zds, (size_t)(iend - ip)));
|
|
1787
2245
|
if (isSkipFrame) {
|
|
1788
2246
|
loadedSize = MIN(toLoad, (size_t)(iend-ip));
|
|
1789
2247
|
} else {
|
|
1790
2248
|
RETURN_ERROR_IF(toLoad > zds->inBuffSize - zds->inPos,
|
|
1791
2249
|
corruption_detected,
|
|
1792
2250
|
"should never happen");
|
|
1793
|
-
loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, iend-ip);
|
|
2251
|
+
loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, (size_t)(iend-ip));
|
|
2252
|
+
}
|
|
2253
|
+
if (loadedSize != 0) {
|
|
2254
|
+
/* ip may be NULL */
|
|
2255
|
+
ip += loadedSize;
|
|
2256
|
+
zds->inPos += loadedSize;
|
|
1794
2257
|
}
|
|
1795
|
-
ip += loadedSize;
|
|
1796
|
-
zds->inPos += loadedSize;
|
|
1797
2258
|
if (loadedSize < toLoad) { someMoreWork = 0; break; } /* not enough input, wait for more */
|
|
1798
2259
|
|
|
1799
2260
|
/* decode loaded input */
|
|
@@ -1803,14 +2264,17 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1803
2264
|
break;
|
|
1804
2265
|
}
|
|
1805
2266
|
case zdss_flush:
|
|
1806
|
-
{
|
|
1807
|
-
size_t const
|
|
1808
|
-
op
|
|
2267
|
+
{
|
|
2268
|
+
size_t const toFlushSize = zds->outEnd - zds->outStart;
|
|
2269
|
+
size_t const flushedSize = ZSTD_limitCopy(op, (size_t)(oend-op), zds->outBuff + zds->outStart, toFlushSize);
|
|
2270
|
+
|
|
2271
|
+
op = op ? op + flushedSize : op;
|
|
2272
|
+
|
|
1809
2273
|
zds->outStart += flushedSize;
|
|
1810
2274
|
if (flushedSize == toFlushSize) { /* flush completed */
|
|
1811
2275
|
zds->streamStage = zdss_read;
|
|
1812
2276
|
if ( (zds->outBuffSize < zds->fParams.frameContentSize)
|
|
1813
|
-
|
|
2277
|
+
&& (zds->outStart + zds->fParams.blockSizeMax > zds->outBuffSize) ) {
|
|
1814
2278
|
DEBUGLOG(5, "restart filling outBuff from beginning (left:%i, needed:%u)",
|
|
1815
2279
|
(int)(zds->outBuffSize - zds->outStart),
|
|
1816
2280
|
(U32)zds->fParams.blockSizeMax);
|
|
@@ -1824,7 +2288,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1824
2288
|
|
|
1825
2289
|
default:
|
|
1826
2290
|
assert(0); /* impossible */
|
|
1827
|
-
RETURN_ERROR(GENERIC, "impossible to reach"); /* some
|
|
2291
|
+
RETURN_ERROR(GENERIC, "impossible to reach"); /* some compilers require default to do something */
|
|
1828
2292
|
} }
|
|
1829
2293
|
|
|
1830
2294
|
/* result */
|
|
@@ -1837,8 +2301,8 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1837
2301
|
if ((ip==istart) && (op==ostart)) { /* no forward progress */
|
|
1838
2302
|
zds->noForwardProgress ++;
|
|
1839
2303
|
if (zds->noForwardProgress >= ZSTD_NO_FORWARD_PROGRESS_MAX) {
|
|
1840
|
-
RETURN_ERROR_IF(op==oend,
|
|
1841
|
-
RETURN_ERROR_IF(ip==iend,
|
|
2304
|
+
RETURN_ERROR_IF(op==oend, noForwardProgress_destFull, "");
|
|
2305
|
+
RETURN_ERROR_IF(ip==iend, noForwardProgress_inputEmpty, "");
|
|
1842
2306
|
assert(0);
|
|
1843
2307
|
}
|
|
1844
2308
|
} else {
|
|
@@ -1875,11 +2339,17 @@ size_t ZSTD_decompressStream_simpleArgs (
|
|
|
1875
2339
|
void* dst, size_t dstCapacity, size_t* dstPos,
|
|
1876
2340
|
const void* src, size_t srcSize, size_t* srcPos)
|
|
1877
2341
|
{
|
|
1878
|
-
ZSTD_outBuffer output
|
|
1879
|
-
ZSTD_inBuffer input
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
2342
|
+
ZSTD_outBuffer output;
|
|
2343
|
+
ZSTD_inBuffer input;
|
|
2344
|
+
output.dst = dst;
|
|
2345
|
+
output.size = dstCapacity;
|
|
2346
|
+
output.pos = *dstPos;
|
|
2347
|
+
input.src = src;
|
|
2348
|
+
input.size = srcSize;
|
|
2349
|
+
input.pos = *srcPos;
|
|
2350
|
+
{ size_t const cErr = ZSTD_decompressStream(dctx, &output, &input);
|
|
2351
|
+
*dstPos = output.pos;
|
|
2352
|
+
*srcPos = input.pos;
|
|
2353
|
+
return cErr;
|
|
2354
|
+
}
|
|
1885
2355
|
}
|