comparison contrib/python-zstandard/zstd/compress/huf_compress.c @ 30822:b54a2984cdd4

zstd: vendor python-zstandard 0.6.0 Commit 63c68d6f5fc8de4afd9bde81b13b537beb4e47e8 from https://github.com/indygreg/python-zstandard is imported without modifications (other than removing unwanted files). This includes minor performance and feature improvements. It also changes the vendored zstd library from 1.1.1 to 1.1.2. # no-check-commit
author Gregory Szorc <gregory.szorc@gmail.com>
date Sat, 14 Jan 2017 19:41:43 -0800
parents 2e484bdea8c4
children b1fb341d8a61
comparison
equal deleted inserted replaced
30821:7005c03f7387 30822:b54a2984cdd4
54 54
55 /* ************************************************************** 55 /* **************************************************************
56 * Error Management 56 * Error Management
57 ****************************************************************/ 57 ****************************************************************/
58 #define HUF_STATIC_ASSERT(c) { enum { HUF_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */ 58 #define HUF_STATIC_ASSERT(c) { enum { HUF_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */
59 #define CHECK_V_F(e, f) size_t const e = f; if (ERR_isError(e)) return f
60 #define CHECK_F(f) { CHECK_V_F(_var_err__, f); }
59 61
60 62
61 /* ************************************************************** 63 /* **************************************************************
62 * Utils 64 * Utils
63 ****************************************************************/ 65 ****************************************************************/
68 70
69 71
70 /* ******************************************************* 72 /* *******************************************************
71 * HUF : Huffman block compression 73 * HUF : Huffman block compression
72 *********************************************************/ 74 *********************************************************/
75 /* HUF_compressWeights() :
76 * Same as FSE_compress(), but dedicated to huff0's weights compression.
77 * The use case needs much less stack memory.
78 * Note : all elements within weightTable are supposed to be <= HUF_TABLELOG_MAX.
79 */
80 #define MAX_FSE_TABLELOG_FOR_HUFF_HEADER 6
81 size_t HUF_compressWeights (void* dst, size_t dstSize, const void* weightTable, size_t wtSize)
82 {
83 BYTE* const ostart = (BYTE*) dst;
84 BYTE* op = ostart;
85 BYTE* const oend = ostart + dstSize;
86
87 U32 maxSymbolValue = HUF_TABLELOG_MAX;
88 U32 tableLog = MAX_FSE_TABLELOG_FOR_HUFF_HEADER;
89
90 FSE_CTable CTable[FSE_CTABLE_SIZE_U32(MAX_FSE_TABLELOG_FOR_HUFF_HEADER, HUF_TABLELOG_MAX)];
91 BYTE scratchBuffer[1<<MAX_FSE_TABLELOG_FOR_HUFF_HEADER];
92
93 U32 count[HUF_TABLELOG_MAX+1];
94 S16 norm[HUF_TABLELOG_MAX+1];
95
96 /* init conditions */
97 if (wtSize <= 1) return 0; /* Not compressible */
98
99 /* Scan input and build symbol stats */
100 { CHECK_V_F(maxCount, FSE_count_simple(count, &maxSymbolValue, weightTable, wtSize) );
101 if (maxCount == wtSize) return 1; /* only a single symbol in src : rle */
102 if (maxCount == 1) return 0; /* each symbol present maximum once => not compressible */
103 }
104
105 tableLog = FSE_optimalTableLog(tableLog, wtSize, maxSymbolValue);
106 CHECK_F( FSE_normalizeCount(norm, tableLog, count, wtSize, maxSymbolValue) );
107
108 /* Write table description header */
109 { CHECK_V_F(hSize, FSE_writeNCount(op, oend-op, norm, maxSymbolValue, tableLog) );
110 op += hSize;
111 }
112
113 /* Compress */
114 CHECK_F( FSE_buildCTable_wksp(CTable, norm, maxSymbolValue, tableLog, scratchBuffer, sizeof(scratchBuffer)) );
115 { CHECK_V_F(cSize, FSE_compress_usingCTable(op, oend - op, weightTable, wtSize, CTable) );
116 if (cSize == 0) return 0; /* not enough space for compressed data */
117 op += cSize;
118 }
119
120 return op-ostart;
121 }
122
123
73 struct HUF_CElt_s { 124 struct HUF_CElt_s {
74 U16 val; 125 U16 val;
75 BYTE nbBits; 126 BYTE nbBits;
76 }; /* typedef'd to HUF_CElt within "huf.h" */ 127 }; /* typedef'd to HUF_CElt within "huf.h" */
77
78 typedef struct nodeElt_s {
79 U32 count;
80 U16 parent;
81 BYTE byte;
82 BYTE nbBits;
83 } nodeElt;
84 128
85 /*! HUF_writeCTable() : 129 /*! HUF_writeCTable() :
86 `CTable` : huffman tree to save, using huf representation. 130 `CTable` : huffman tree to save, using huf representation.
87 @return : size of saved CTable */ 131 @return : size of saved CTable */
88 size_t HUF_writeCTable (void* dst, size_t maxDstSize, 132 size_t HUF_writeCTable (void* dst, size_t maxDstSize,
89 const HUF_CElt* CTable, U32 maxSymbolValue, U32 huffLog) 133 const HUF_CElt* CTable, U32 maxSymbolValue, U32 huffLog)
90 { 134 {
91 BYTE bitsToWeight[HUF_TABLELOG_MAX + 1]; 135 BYTE bitsToWeight[HUF_TABLELOG_MAX + 1]; /* precomputed conversion table */
92 BYTE huffWeight[HUF_SYMBOLVALUE_MAX]; 136 BYTE huffWeight[HUF_SYMBOLVALUE_MAX];
93 BYTE* op = (BYTE*)dst; 137 BYTE* op = (BYTE*)dst;
94 U32 n; 138 U32 n;
95 139
96 /* check conditions */ 140 /* check conditions */
97 if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) return ERROR(GENERIC); 141 if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) return ERROR(maxSymbolValue_tooLarge);
98 142
99 /* convert to weight */ 143 /* convert to weight */
100 bitsToWeight[0] = 0; 144 bitsToWeight[0] = 0;
101 for (n=1; n<huffLog+1; n++) 145 for (n=1; n<huffLog+1; n++)
102 bitsToWeight[n] = (BYTE)(huffLog + 1 - n); 146 bitsToWeight[n] = (BYTE)(huffLog + 1 - n);
103 for (n=0; n<maxSymbolValue; n++) 147 for (n=0; n<maxSymbolValue; n++)
104 huffWeight[n] = bitsToWeight[CTable[n].nbBits]; 148 huffWeight[n] = bitsToWeight[CTable[n].nbBits];
105 149
106 { size_t const size = FSE_compress(op+1, maxDstSize-1, huffWeight, maxSymbolValue); 150 /* attempt weights compression by FSE */
107 if (FSE_isError(size)) return size; 151 { CHECK_V_F(hSize, HUF_compressWeights(op+1, maxDstSize-1, huffWeight, maxSymbolValue) );
108 if ((size>1) & (size < maxSymbolValue/2)) { /* FSE compressed */ 152 if ((hSize>1) & (hSize < maxSymbolValue/2)) { /* FSE compressed */
109 op[0] = (BYTE)size; 153 op[0] = (BYTE)hSize;
110 return size+1; 154 return hSize+1;
111 } 155 } }
112 } 156
113 157 /* write raw values as 4-bits (max : 15) */
114 /* raw values */ 158 if (maxSymbolValue > (256-128)) return ERROR(GENERIC); /* should not happen : likely means source cannot be compressed */
115 if (maxSymbolValue > (256-128)) return ERROR(GENERIC); /* should not happen */
116 if (((maxSymbolValue+1)/2) + 1 > maxDstSize) return ERROR(dstSize_tooSmall); /* not enough space within dst buffer */ 159 if (((maxSymbolValue+1)/2) + 1 > maxDstSize) return ERROR(dstSize_tooSmall); /* not enough space within dst buffer */
117 op[0] = (BYTE)(128 /*special case*/ + (maxSymbolValue-1)); 160 op[0] = (BYTE)(128 /*special case*/ + (maxSymbolValue-1));
118 huffWeight[maxSymbolValue] = 0; /* to be sure it doesn't cause issue in final combination */ 161 huffWeight[maxSymbolValue] = 0; /* to be sure it doesn't cause msan issue in final combination */
119 for (n=0; n<maxSymbolValue; n+=2) 162 for (n=0; n<maxSymbolValue; n+=2)
120 op[(n/2)+1] = (BYTE)((huffWeight[n] << 4) + huffWeight[n+1]); 163 op[(n/2)+1] = (BYTE)((huffWeight[n] << 4) + huffWeight[n+1]);
121 return ((maxSymbolValue+1)/2) + 1; 164 return ((maxSymbolValue+1)/2) + 1;
122
123 } 165 }
124 166
125 167
126 size_t HUF_readCTable (HUF_CElt* CTable, U32 maxSymbolValue, const void* src, size_t srcSize) 168 size_t HUF_readCTable (HUF_CElt* CTable, U32 maxSymbolValue, const void* src, size_t srcSize)
127 { 169 {
128 BYTE huffWeight[HUF_SYMBOLVALUE_MAX + 1]; 170 BYTE huffWeight[HUF_SYMBOLVALUE_MAX + 1]; /* init not required, even though some static analyzer may complain */
129 U32 rankVal[HUF_TABLELOG_ABSOLUTEMAX + 1]; /* large enough for values from 0 to 16 */ 171 U32 rankVal[HUF_TABLELOG_ABSOLUTEMAX + 1]; /* large enough for values from 0 to 16 */
130 U32 tableLog = 0; 172 U32 tableLog = 0;
131 size_t readSize;
132 U32 nbSymbols = 0; 173 U32 nbSymbols = 0;
133 /*memset(huffWeight, 0, sizeof(huffWeight));*/ /* is not necessary, even though some analyzer complain ... */
134 174
135 /* get symbol weights */ 175 /* get symbol weights */
136 readSize = HUF_readStats(huffWeight, HUF_SYMBOLVALUE_MAX+1, rankVal, &nbSymbols, &tableLog, src, srcSize); 176 CHECK_V_F(readSize, HUF_readStats(huffWeight, HUF_SYMBOLVALUE_MAX+1, rankVal, &nbSymbols, &tableLog, src, srcSize));
137 if (HUF_isError(readSize)) return readSize;
138 177
139 /* check result */ 178 /* check result */
140 if (tableLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge); 179 if (tableLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge);
141 if (nbSymbols > maxSymbolValue+1) return ERROR(maxSymbolValue_tooSmall); 180 if (nbSymbols > maxSymbolValue+1) return ERROR(maxSymbolValue_tooSmall);
142 181
171 } 210 }
172 211
173 return readSize; 212 return readSize;
174 } 213 }
175 214
215
216 typedef struct nodeElt_s {
217 U32 count;
218 U16 parent;
219 BYTE byte;
220 BYTE nbBits;
221 } nodeElt;
176 222
177 static U32 HUF_setMaxHeight(nodeElt* huffNode, U32 lastNonNull, U32 maxNbBits) 223 static U32 HUF_setMaxHeight(nodeElt* huffNode, U32 lastNonNull, U32 maxNbBits)
178 { 224 {
179 const U32 largestBits = huffNode[lastNonNull].nbBits; 225 const U32 largestBits = huffNode[lastNonNull].nbBits;
180 if (largestBits <= maxNbBits) return largestBits; /* early exit : no elt > maxNbBits */ 226 if (largestBits <= maxNbBits) return largestBits; /* early exit : no elt > maxNbBits */
277 huffNode[pos].byte = (BYTE)n; 323 huffNode[pos].byte = (BYTE)n;
278 } 324 }
279 } 325 }
280 326
281 327
328 /** HUF_buildCTable_wksp() :
329 * Same as HUF_buildCTable(), but using externally allocated scratch buffer.
330 * `workSpace` must be aligned on 4-bytes boundaries, and be at least as large as a table of 1024 unsigned.
331 */
282 #define STARTNODE (HUF_SYMBOLVALUE_MAX+1) 332 #define STARTNODE (HUF_SYMBOLVALUE_MAX+1)
283 size_t HUF_buildCTable (HUF_CElt* tree, const U32* count, U32 maxSymbolValue, U32 maxNbBits) 333 typedef nodeElt huffNodeTable[2*HUF_SYMBOLVALUE_MAX+1 +1];
284 { 334 size_t HUF_buildCTable_wksp (HUF_CElt* tree, const U32* count, U32 maxSymbolValue, U32 maxNbBits, void* workSpace, size_t wkspSize)
285 nodeElt huffNode0[2*HUF_SYMBOLVALUE_MAX+1 +1]; 335 {
286 nodeElt* huffNode = huffNode0 + 1; 336 nodeElt* const huffNode0 = (nodeElt*)workSpace;
337 nodeElt* const huffNode = huffNode0+1;
287 U32 n, nonNullRank; 338 U32 n, nonNullRank;
288 int lowS, lowN; 339 int lowS, lowN;
289 U16 nodeNb = STARTNODE; 340 U16 nodeNb = STARTNODE;
290 U32 nodeRoot; 341 U32 nodeRoot;
291 342
292 /* safety checks */ 343 /* safety checks */
344 if (wkspSize < sizeof(huffNodeTable)) return ERROR(GENERIC); /* workSpace is not large enough */
293 if (maxNbBits == 0) maxNbBits = HUF_TABLELOG_DEFAULT; 345 if (maxNbBits == 0) maxNbBits = HUF_TABLELOG_DEFAULT;
294 if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) return ERROR(GENERIC); 346 if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) return ERROR(GENERIC);
295 memset(huffNode0, 0, sizeof(huffNode0)); 347 memset(huffNode0, 0, sizeof(huffNodeTable));
296 348
297 /* sort, decreasing order */ 349 /* sort, decreasing order */
298 HUF_sort(huffNode, count, maxSymbolValue); 350 HUF_sort(huffNode, count, maxSymbolValue);
299 351
300 /* init for parents */ 352 /* init for parents */
303 lowS = nonNullRank; nodeRoot = nodeNb + lowS - 1; lowN = nodeNb; 355 lowS = nonNullRank; nodeRoot = nodeNb + lowS - 1; lowN = nodeNb;
304 huffNode[nodeNb].count = huffNode[lowS].count + huffNode[lowS-1].count; 356 huffNode[nodeNb].count = huffNode[lowS].count + huffNode[lowS-1].count;
305 huffNode[lowS].parent = huffNode[lowS-1].parent = nodeNb; 357 huffNode[lowS].parent = huffNode[lowS-1].parent = nodeNb;
306 nodeNb++; lowS-=2; 358 nodeNb++; lowS-=2;
307 for (n=nodeNb; n<=nodeRoot; n++) huffNode[n].count = (U32)(1U<<30); 359 for (n=nodeNb; n<=nodeRoot; n++) huffNode[n].count = (U32)(1U<<30);
308 huffNode0[0].count = (U32)(1U<<31); 360 huffNode0[0].count = (U32)(1U<<31); /* fake entry, strong barrier */
309 361
310 /* create parents */ 362 /* create parents */
311 while (nodeNb <= nodeRoot) { 363 while (nodeNb <= nodeRoot) {
312 U32 n1 = (huffNode[lowS].count < huffNode[lowN].count) ? lowS-- : lowN++; 364 U32 n1 = (huffNode[lowS].count < huffNode[lowN].count) ? lowS-- : lowN++;
313 U32 n2 = (huffNode[lowS].count < huffNode[lowN].count) ? lowS-- : lowN++; 365 U32 n2 = (huffNode[lowS].count < huffNode[lowN].count) ? lowS-- : lowN++;
346 } 398 }
347 399
348 return maxNbBits; 400 return maxNbBits;
349 } 401 }
350 402
403 /** HUF_buildCTable() :
404 * Note : count is used before tree is written, so they can safely overlap
405 */
406 size_t HUF_buildCTable (HUF_CElt* tree, const U32* count, U32 maxSymbolValue, U32 maxNbBits)
407 {
408 huffNodeTable nodeTable;
409 return HUF_buildCTable_wksp(tree, count, maxSymbolValue, maxNbBits, nodeTable, sizeof(nodeTable));
410 }
411
351 static void HUF_encodeSymbol(BIT_CStream_t* bitCPtr, U32 symbol, const HUF_CElt* CTable) 412 static void HUF_encodeSymbol(BIT_CStream_t* bitCPtr, U32 symbol, const HUF_CElt* CTable)
352 { 413 {
353 BIT_addBitsFast(bitCPtr, CTable[symbol].val, CTable[symbol].nbBits); 414 BIT_addBitsFast(bitCPtr, CTable[symbol].val, CTable[symbol].nbBits);
354 } 415 }
355 416
373 const unsigned fast = (dstSize >= HUF_BLOCKBOUND(srcSize)); 434 const unsigned fast = (dstSize >= HUF_BLOCKBOUND(srcSize));
374 BIT_CStream_t bitC; 435 BIT_CStream_t bitC;
375 436
376 /* init */ 437 /* init */
377 if (dstSize < 8) return 0; /* not enough space to compress */ 438 if (dstSize < 8) return 0; /* not enough space to compress */
378 { size_t const errorCode = BIT_initCStream(&bitC, op, oend-op); 439 { size_t const initErr = BIT_initCStream(&bitC, op, oend-op);
379 if (HUF_isError(errorCode)) return 0; } 440 if (HUF_isError(initErr)) return 0; }
380 441
381 n = srcSize & ~3; /* join to mod 4 */ 442 n = srcSize & ~3; /* join to mod 4 */
382 switch (srcSize & 3) 443 switch (srcSize & 3)
383 { 444 {
384 case 3 : HUF_encodeSymbol(&bitC, ip[n+ 2], CTable); 445 case 3 : HUF_encodeSymbol(&bitC, ip[n+ 2], CTable);
417 478
418 if (dstSize < 6 + 1 + 1 + 1 + 8) return 0; /* minimum space to compress successfully */ 479 if (dstSize < 6 + 1 + 1 + 1 + 8) return 0; /* minimum space to compress successfully */
419 if (srcSize < 12) return 0; /* no saving possible : too small input */ 480 if (srcSize < 12) return 0; /* no saving possible : too small input */
420 op += 6; /* jumpTable */ 481 op += 6; /* jumpTable */
421 482
422 { size_t const cSize = HUF_compress1X_usingCTable(op, oend-op, ip, segmentSize, CTable); 483 { CHECK_V_F(cSize, HUF_compress1X_usingCTable(op, oend-op, ip, segmentSize, CTable) );
423 if (HUF_isError(cSize)) return cSize;
424 if (cSize==0) return 0; 484 if (cSize==0) return 0;
425 MEM_writeLE16(ostart, (U16)cSize); 485 MEM_writeLE16(ostart, (U16)cSize);
426 op += cSize; 486 op += cSize;
427 } 487 }
428 488
429 ip += segmentSize; 489 ip += segmentSize;
430 { size_t const cSize = HUF_compress1X_usingCTable(op, oend-op, ip, segmentSize, CTable); 490 { CHECK_V_F(cSize, HUF_compress1X_usingCTable(op, oend-op, ip, segmentSize, CTable) );
431 if (HUF_isError(cSize)) return cSize;
432 if (cSize==0) return 0; 491 if (cSize==0) return 0;
433 MEM_writeLE16(ostart+2, (U16)cSize); 492 MEM_writeLE16(ostart+2, (U16)cSize);
434 op += cSize; 493 op += cSize;
435 } 494 }
436 495
437 ip += segmentSize; 496 ip += segmentSize;
438 { size_t const cSize = HUF_compress1X_usingCTable(op, oend-op, ip, segmentSize, CTable); 497 { CHECK_V_F(cSize, HUF_compress1X_usingCTable(op, oend-op, ip, segmentSize, CTable) );
439 if (HUF_isError(cSize)) return cSize;
440 if (cSize==0) return 0; 498 if (cSize==0) return 0;
441 MEM_writeLE16(ostart+4, (U16)cSize); 499 MEM_writeLE16(ostart+4, (U16)cSize);
442 op += cSize; 500 op += cSize;
443 } 501 }
444 502
445 ip += segmentSize; 503 ip += segmentSize;
446 { size_t const cSize = HUF_compress1X_usingCTable(op, oend-op, ip, iend-ip, CTable); 504 { CHECK_V_F(cSize, HUF_compress1X_usingCTable(op, oend-op, ip, iend-ip, CTable) );
447 if (HUF_isError(cSize)) return cSize;
448 if (cSize==0) return 0; 505 if (cSize==0) return 0;
449 op += cSize; 506 op += cSize;
450 } 507 }
451 508
452 return op-ostart; 509 return op-ostart;
453 } 510 }
454 511
455 512
513 /* `workSpace` must a table of at least 1024 unsigned */
456 static size_t HUF_compress_internal ( 514 static size_t HUF_compress_internal (
457 void* dst, size_t dstSize, 515 void* dst, size_t dstSize,
458 const void* src, size_t srcSize, 516 const void* src, size_t srcSize,
459 unsigned maxSymbolValue, unsigned huffLog, 517 unsigned maxSymbolValue, unsigned huffLog,
460 unsigned singleStream) 518 unsigned singleStream,
519 void* workSpace, size_t wkspSize)
461 { 520 {
462 BYTE* const ostart = (BYTE*)dst; 521 BYTE* const ostart = (BYTE*)dst;
463 BYTE* const oend = ostart + dstSize; 522 BYTE* const oend = ostart + dstSize;
464 BYTE* op = ostart; 523 BYTE* op = ostart;
465 524
466 U32 count[HUF_SYMBOLVALUE_MAX+1]; 525 union {
467 HUF_CElt CTable[HUF_SYMBOLVALUE_MAX+1]; 526 U32 count[HUF_SYMBOLVALUE_MAX+1];
527 HUF_CElt CTable[HUF_SYMBOLVALUE_MAX+1];
528 } table; /* `count` can overlap with `CTable`; saves 1 KB */
468 529
469 /* checks & inits */ 530 /* checks & inits */
531 if (wkspSize < sizeof(huffNodeTable)) return ERROR(GENERIC);
470 if (!srcSize) return 0; /* Uncompressed (note : 1 means rle, so first byte must be correct) */ 532 if (!srcSize) return 0; /* Uncompressed (note : 1 means rle, so first byte must be correct) */
471 if (!dstSize) return 0; /* cannot fit within dst budget */ 533 if (!dstSize) return 0; /* cannot fit within dst budget */
472 if (srcSize > HUF_BLOCKSIZE_MAX) return ERROR(srcSize_wrong); /* current block size limit */ 534 if (srcSize > HUF_BLOCKSIZE_MAX) return ERROR(srcSize_wrong); /* current block size limit */
473 if (huffLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge); 535 if (huffLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge);
474 if (!maxSymbolValue) maxSymbolValue = HUF_SYMBOLVALUE_MAX; 536 if (!maxSymbolValue) maxSymbolValue = HUF_SYMBOLVALUE_MAX;
475 if (!huffLog) huffLog = HUF_TABLELOG_DEFAULT; 537 if (!huffLog) huffLog = HUF_TABLELOG_DEFAULT;
476 538
477 /* Scan input and build symbol stats */ 539 /* Scan input and build symbol stats */
478 { size_t const largest = FSE_count (count, &maxSymbolValue, (const BYTE*)src, srcSize); 540 { CHECK_V_F(largest, FSE_count_wksp (table.count, &maxSymbolValue, (const BYTE*)src, srcSize, (U32*)workSpace) );
479 if (HUF_isError(largest)) return largest;
480 if (largest == srcSize) { *ostart = ((const BYTE*)src)[0]; return 1; } /* single symbol, rle */ 541 if (largest == srcSize) { *ostart = ((const BYTE*)src)[0]; return 1; } /* single symbol, rle */
481 if (largest <= (srcSize >> 7)+1) return 0; /* Fast heuristic : not compressible enough */ 542 if (largest <= (srcSize >> 7)+1) return 0; /* Fast heuristic : not compressible enough */
482 } 543 }
483 544
484 /* Build Huffman Tree */ 545 /* Build Huffman Tree */
485 huffLog = HUF_optimalTableLog(huffLog, srcSize, maxSymbolValue); 546 huffLog = HUF_optimalTableLog(huffLog, srcSize, maxSymbolValue);
486 { size_t const maxBits = HUF_buildCTable (CTable, count, maxSymbolValue, huffLog); 547 { CHECK_V_F(maxBits, HUF_buildCTable_wksp (table.CTable, table.count, maxSymbolValue, huffLog, workSpace, wkspSize) );
487 if (HUF_isError(maxBits)) return maxBits;
488 huffLog = (U32)maxBits; 548 huffLog = (U32)maxBits;
489 } 549 }
490 550
491 /* Write table description header */ 551 /* Write table description header */
492 { size_t const hSize = HUF_writeCTable (op, dstSize, CTable, maxSymbolValue, huffLog); 552 { CHECK_V_F(hSize, HUF_writeCTable (op, dstSize, table.CTable, maxSymbolValue, huffLog) );
493 if (HUF_isError(hSize)) return hSize;
494 if (hSize + 12 >= srcSize) return 0; /* not useful to try compression */ 553 if (hSize + 12 >= srcSize) return 0; /* not useful to try compression */
495 op += hSize; 554 op += hSize;
496 } 555 }
497 556
498 /* Compress */ 557 /* Compress */
499 { size_t const cSize = (singleStream) ? 558 { size_t const cSize = (singleStream) ?
500 HUF_compress1X_usingCTable(op, oend - op, src, srcSize, CTable) : /* single segment */ 559 HUF_compress1X_usingCTable(op, oend - op, src, srcSize, table.CTable) : /* single segment */
501 HUF_compress4X_usingCTable(op, oend - op, src, srcSize, CTable); 560 HUF_compress4X_usingCTable(op, oend - op, src, srcSize, table.CTable);
502 if (HUF_isError(cSize)) return cSize; 561 if (HUF_isError(cSize)) return cSize;
503 if (cSize==0) return 0; /* uncompressible */ 562 if (cSize==0) return 0; /* uncompressible */
504 op += cSize; 563 op += cSize;
505 } 564 }
506 565
510 569
511 return op-ostart; 570 return op-ostart;
512 } 571 }
513 572
514 573
574 size_t HUF_compress1X_wksp (void* dst, size_t dstSize,
575 const void* src, size_t srcSize,
576 unsigned maxSymbolValue, unsigned huffLog,
577 void* workSpace, size_t wkspSize)
578 {
579 return HUF_compress_internal(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, 1 /* single stream */, workSpace, wkspSize);
580 }
581
515 size_t HUF_compress1X (void* dst, size_t dstSize, 582 size_t HUF_compress1X (void* dst, size_t dstSize,
516 const void* src, size_t srcSize, 583 const void* src, size_t srcSize,
517 unsigned maxSymbolValue, unsigned huffLog) 584 unsigned maxSymbolValue, unsigned huffLog)
518 { 585 {
519 return HUF_compress_internal(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, 1); 586 unsigned workSpace[1024];
587 return HUF_compress1X_wksp(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, workSpace, sizeof(workSpace));
588 }
589
590 size_t HUF_compress4X_wksp (void* dst, size_t dstSize,
591 const void* src, size_t srcSize,
592 unsigned maxSymbolValue, unsigned huffLog,
593 void* workSpace, size_t wkspSize)
594 {
595 return HUF_compress_internal(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, 0 /* 4 streams */, workSpace, wkspSize);
520 } 596 }
521 597
522 size_t HUF_compress2 (void* dst, size_t dstSize, 598 size_t HUF_compress2 (void* dst, size_t dstSize,
523 const void* src, size_t srcSize, 599 const void* src, size_t srcSize,
524 unsigned maxSymbolValue, unsigned huffLog) 600 unsigned maxSymbolValue, unsigned huffLog)
525 { 601 {
526 return HUF_compress_internal(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, 0); 602 unsigned workSpace[1024];
527 } 603 return HUF_compress4X_wksp(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, workSpace, sizeof(workSpace));
528 604 }
529 605
530 size_t HUF_compress (void* dst, size_t maxDstSize, const void* src, size_t srcSize) 606 size_t HUF_compress (void* dst, size_t maxDstSize, const void* src, size_t srcSize)
531 { 607 {
532 return HUF_compress2(dst, maxDstSize, src, (U32)srcSize, 255, HUF_TABLELOG_DEFAULT); 608 return HUF_compress2(dst, maxDstSize, src, (U32)srcSize, 255, HUF_TABLELOG_DEFAULT);
533 } 609 }