Skip to content

Commit d89d578

Browse files
committed
Merge pull request #88 from Cyan4973/dev
Dev
2 parents a174fb1 + 56005e7 commit d89d578

File tree

10 files changed

+263
-72
lines changed

10 files changed

+263
-72
lines changed

Makefile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
# ################################################################
3333

3434
# Version number
35-
export VERSION := 0.4.2
35+
export VERSION := 0.4.3
3636

3737
PRGDIR = programs
3838
ZSTDDIR = lib
@@ -87,8 +87,8 @@ gpptest: clean
8787
$(MAKE) all CC=g++ CFLAGS="-O3 -Wall -Wextra -Wundef -Wshadow -Wcast-align -Werror"
8888

8989
armtest: clean
90-
$(MAKE) -C $(ZSTDDIR) -e all CC=arm-linux-gnueabi-gcc MOREFLAGS="-Werror"
91-
$(MAKE) -C $(PRGDIR) -e CC=arm-linux-gnueabi-gcc MOREFLAGS="-Werror"
90+
$(MAKE) -C $(ZSTDDIR) all CC=arm-linux-gnueabi-gcc MOREFLAGS="-Werror"
91+
$(MAKE) -C $(PRGDIR) CC=arm-linux-gnueabi-gcc MOREFLAGS="-Werror -static"
9292

9393
usan: clean
9494
$(MAKE) test CC=clang MOREFLAGS="-g -fsanitize=undefined"

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
v0.4.3 :
2+
new : external dictionary API
3+
new : zstd-frugal
4+
15
v0.4.2 :
26
Generic minor improvements for small blocks
37
Fixed : big-endian compatibility, by Peter Harris (#85)

images/CSpeed.png

-1.21 KB
Loading

lib/zstd.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ extern "C" {
4848
***************************************/
4949
#define ZSTD_VERSION_MAJOR 0 /* for breaking interface changes */
5050
#define ZSTD_VERSION_MINOR 4 /* for new (non-breaking) interface capabilities */
51-
#define ZSTD_VERSION_RELEASE 2 /* for tweaks, bug-fixes, or development */
51+
#define ZSTD_VERSION_RELEASE 3 /* for tweaks, bug-fixes, or development */
5252
#define ZSTD_VERSION_NUMBER (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE)
5353
unsigned ZSTD_versionNumber (void);
5454

lib/zstd_compress.c

Lines changed: 81 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,7 @@ size_t ZSTD_compressSequences(void* dst, size_t maxDstSize,
488488
BYTE litLength = llTable[i]; /* (7)*/ /* (7)*/
489489
FSE_encodeSymbol(&blockStream, &stateMatchLength, matchLength); /* 17 */ /* 17 */
490490
if (MEM_32bits()) BIT_flushBits(&blockStream); /* 7 */
491-
BIT_addBits(&blockStream, offset, nbBits); /* 32 */ /* 42 */
491+
BIT_addBits(&blockStream, offset, nbBits); /* 31 */ /* 42 */ /* 24 bits max in 32-bits mode */
492492
if (MEM_32bits()) BIT_flushBits(&blockStream); /* 7 */
493493
FSE_encodeSymbol(&blockStream, &stateOffsetBits, offCode); /* 16 */ /* 51 */
494494
FSE_encodeSymbol(&blockStream, &stateLitLength, litLength); /* 26 */ /* 61 */
@@ -730,13 +730,30 @@ static size_t ZSTD_hashPtr(const void* p, U32 hBits, U32 mls)
730730
* Fast Scan
731731
***************************************/
732732

733+
#define FILLHASHSTEP 3
734+
static void ZSTD_fillHashTable (ZSTD_CCtx* zc, const void* end, const U32 mls)
735+
{
736+
U32* const hashTable = zc->hashTable;
737+
const U32 hBits = zc->params.hashLog;
738+
const BYTE* const base = zc->base;
739+
const BYTE* ip = base + zc->nextToUpdate;
740+
const BYTE* const iend = (const BYTE*) end;
741+
742+
while(ip <= iend)
743+
{
744+
hashTable[ZSTD_hashPtr(ip, hBits, mls)] = (U32)(ip - base);
745+
ip += FILLHASHSTEP;
746+
}
747+
}
748+
749+
733750
FORCE_INLINE
734751
size_t ZSTD_compressBlock_fast_generic(ZSTD_CCtx* zc,
735752
void* dst, size_t maxDstSize,
736753
const void* src, size_t srcSize,
737754
const U32 mls)
738755
{
739-
U32* hashTable = zc->hashTable;
756+
U32* const hashTable = zc->hashTable;
740757
const U32 hBits = zc->params.hashLog;
741758
seqStore_t* seqStorePtr = &(zc->seqStore);
742759
const BYTE* const base = zc->base;
@@ -752,12 +769,12 @@ size_t ZSTD_compressBlock_fast_generic(ZSTD_CCtx* zc,
752769

753770
/* init */
754771
ZSTD_resetSeqStore(seqStorePtr);
755-
if (ip < base+4)
772+
if (ip < lowest+4)
756773
{
757-
hashTable[ZSTD_hashPtr(base+1, hBits, mls)] = 1;
758-
hashTable[ZSTD_hashPtr(base+2, hBits, mls)] = 2;
759-
hashTable[ZSTD_hashPtr(base+3, hBits, mls)] = 3;
760-
ip = base+4;
774+
hashTable[ZSTD_hashPtr(lowest+1, hBits, mls)] = zc->dictLimit+1;
775+
hashTable[ZSTD_hashPtr(lowest+2, hBits, mls)] = zc->dictLimit+2;
776+
hashTable[ZSTD_hashPtr(lowest+3, hBits, mls)] = zc->dictLimit+3;
777+
ip = lowest+4;
761778
}
762779

763780
/* Main Search Loop */
@@ -1518,6 +1535,7 @@ size_t ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
15181535
const BYTE* anchor = istart;
15191536
const BYTE* const iend = istart + srcSize;
15201537
const BYTE* const ilimit = iend - 8;
1538+
const BYTE* const base = ctx->base + ctx->dictLimit;
15211539

15221540
size_t offset_2=REPCODE_STARTVALUE, offset_1=REPCODE_STARTVALUE;
15231541
const U32 maxSearches = 1 << ctx->params.searchLog;
@@ -1530,7 +1548,7 @@ size_t ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
15301548

15311549
/* init */
15321550
ZSTD_resetSeqStore(seqStorePtr);
1533-
if (((ip-ctx->base) - ctx->dictLimit) < REPCODE_STARTVALUE) ip += REPCODE_STARTVALUE;
1551+
if ((ip-base) < REPCODE_STARTVALUE) ip = base + REPCODE_STARTVALUE;
15341552

15351553
/* Match Loop */
15361554
while (ip < ilimit)
@@ -1555,7 +1573,7 @@ size_t ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
15551573
matchLength = ml2, start = ip, offset=offsetFound;
15561574
}
15571575

1558-
if (matchLength < MINMATCH)
1576+
if (matchLength < MINMATCH)
15591577
{
15601578
ip += ((ip-anchor) >> g_searchStrength) + 1; /* jump faster over incompressible sections */
15611579
continue;
@@ -1616,7 +1634,7 @@ size_t ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
16161634
/* catch up */
16171635
if (offset)
16181636
{
1619-
while ((start>anchor) && (start>ctx->base+offset) && (start[-1] == start[-1-offset])) /* only search for offset within prefix */
1637+
while ((start>anchor) && (start>base+offset) && (start[-1] == start[-1-offset])) /* only search for offset within prefix */
16201638
{ start--; matchLength++; }
16211639
offset_2 = offset_1; offset_1 = offset;
16221640
}
@@ -1975,8 +1993,21 @@ size_t ZSTD_compressContinue (ZSTD_CCtx* zc,
19751993
{
19761994
const BYTE* const ip = (const BYTE*) src;
19771995

1996+
/* Check if blocks follow each other */
1997+
if (src != zc->nextSrc)
1998+
{
1999+
/* not contiguous */
2000+
size_t delta = zc->nextSrc - ip;
2001+
zc->lowLimit = zc->dictLimit;
2002+
zc->dictLimit = (U32)(zc->nextSrc - zc->base);
2003+
zc->dictBase = zc->base;
2004+
zc->base -= delta;
2005+
zc->nextToUpdate = zc->dictLimit;
2006+
if (zc->dictLimit - zc->lowLimit < 8) zc->lowLimit = zc->dictLimit; /* too small extDict */
2007+
}
2008+
19782009
/* preemptive overflow correction */
1979-
if ((zc->base > (const BYTE*)src) || (zc->lowLimit > (1<<30) ))
2010+
if ((zc->base > ip) || (zc->lowLimit > (1<<30) ))
19802011
{
19812012
U32 correction = zc->lowLimit-1;
19822013
ZSTD_reduceIndex(zc, correction);
@@ -1988,17 +2019,6 @@ size_t ZSTD_compressContinue (ZSTD_CCtx* zc,
19882019
else zc->nextToUpdate -= correction;
19892020
}
19902021

1991-
/* Check if blocks follow each other */
1992-
if (src != zc->nextSrc)
1993-
{
1994-
/* not contiguous */
1995-
zc->lowLimit = zc->dictLimit;
1996-
zc->dictLimit = (U32)(zc->nextSrc - zc->base);
1997-
zc->dictBase = zc->base;
1998-
zc->base += ip - zc->nextSrc;
1999-
zc->nextToUpdate = zc->dictLimit;
2000-
}
2001-
20022022
/* input-dictionary overlap */
20032023
if ((ip+srcSize > zc->dictBase + zc->lowLimit) && (ip < zc->dictBase + zc->dictLimit))
20042024
{
@@ -2011,8 +2031,46 @@ size_t ZSTD_compressContinue (ZSTD_CCtx* zc,
20112031
return ZSTD_compress_generic (zc, dst, dstSize, src, srcSize);
20122032
}
20132033

2034+
size_t ZSTD_compress_insertDictionary(ZSTD_CCtx* zc, const void* src, size_t srcSize)
2035+
{
2036+
const BYTE* const ip = (const BYTE*) src;
2037+
const BYTE* const iend = ip + srcSize;
2038+
2039+
/* input becomes current prefix */
2040+
zc->lowLimit = zc->dictLimit;
2041+
zc->dictLimit = (U32)(zc->nextSrc - zc->base);
2042+
zc->dictBase = zc->base;
2043+
zc->base += ip - zc->nextSrc;
2044+
zc->nextToUpdate = zc->dictLimit;
2045+
2046+
zc->nextSrc = iend;
2047+
if (srcSize <= 8) return 0;
2048+
2049+
switch(zc->params.strategy)
2050+
{
2051+
case ZSTD_fast:
2052+
ZSTD_fillHashTable (zc, iend-8, zc->params.searchLength);
2053+
break;
2054+
2055+
case ZSTD_greedy:
2056+
case ZSTD_lazy:
2057+
case ZSTD_lazy2:
2058+
ZSTD_insertAndFindFirstIndex (zc, iend-8, zc->params.searchLength);
2059+
break;
2060+
2061+
case ZSTD_btlazy2:
2062+
ZSTD_updateTree(zc, iend-8, iend, 1 << zc->params.searchLog, zc->params.searchLength);
2063+
break;
2064+
2065+
default:
2066+
return ERROR(GENERIC); /* strategy doesn't exist; impossible */
2067+
}
2068+
2069+
return 0;
2070+
}
2071+
20142072

2015-
/** ZSTD_compressBegin_advanced
2073+
/*! ZSTD_compressBegin_advanced
20162074
* Write frame header, according to params
20172075
* @return : nb of bytes written */
20182076
size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* ctx,

lib/zstd_decompress.c

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -127,10 +127,10 @@ struct ZSTD_DCtx_s
127127
U32 LLTable[FSE_DTABLE_SIZE_U32(LLFSELog)];
128128
U32 OffTable[FSE_DTABLE_SIZE_U32(OffFSELog)];
129129
U32 MLTable[FSE_DTABLE_SIZE_U32(MLFSELog)];
130-
void* previousDstEnd;
131-
void* base;
132-
void* vBase;
133-
void* dictEnd;
130+
const void* previousDstEnd;
131+
const void* base;
132+
const void* vBase;
133+
const void* dictEnd;
134134
size_t expected;
135135
size_t headerSize;
136136
ZSTD_parameters params;
@@ -141,7 +141,7 @@ struct ZSTD_DCtx_s
141141
size_t litSize;
142142
BYTE litBuffer[BLOCKSIZE + 8 /* margin for wildcopy */];
143143
BYTE headerBuffer[ZSTD_frameHeaderSize_max];
144-
}; /* typedef'd to ZSTD_Dctx within "zstd_static.h" */
144+
}; /* typedef'd to ZSTD_DCtx within "zstd_static.h" */
145145

146146
size_t ZSTD_resetDCtx(ZSTD_DCtx* dctx)
147147
{
@@ -505,7 +505,7 @@ static void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState)
505505
FORCE_INLINE size_t ZSTD_execSequence(BYTE* op,
506506
BYTE* const oend, seq_t sequence,
507507
const BYTE** litPtr, const BYTE* const litLimit_8,
508-
BYTE* const base, BYTE* const vBase, BYTE* const dictEnd)
508+
const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)
509509
{
510510
static const int dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */
511511
static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* substracted */
@@ -538,13 +538,13 @@ FORCE_INLINE size_t ZSTD_execSequence(BYTE* op,
538538
match = dictEnd - (base-match);
539539
if (match + sequence.matchLength <= dictEnd)
540540
{
541-
memcpy(oLitEnd, match, sequence.matchLength);
541+
memmove(oLitEnd, match, sequence.matchLength);
542542
return sequenceLength;
543543
}
544544
/* span extDict & currentPrefixSegment */
545545
{
546546
size_t length1 = dictEnd - match;
547-
memcpy(oLitEnd, match, length1);
547+
memmove(oLitEnd, match, length1);
548548
op = oLitEnd + length1;
549549
sequence.matchLength -= length1;
550550
match = base;
@@ -607,9 +607,9 @@ static size_t ZSTD_decompressSequences(
607607
U32* DTableLL = dctx->LLTable;
608608
U32* DTableML = dctx->MLTable;
609609
U32* DTableOffb = dctx->OffTable;
610-
BYTE* const base = (BYTE*) (dctx->base);
611-
BYTE* const vBase = (BYTE*) (dctx->vBase);
612-
BYTE* const dictEnd = (BYTE*) (dctx->dictEnd);
610+
const BYTE* const base = (const BYTE*) (dctx->base);
611+
const BYTE* const vBase = (const BYTE*) (dctx->vBase);
612+
const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);
613613

614614
/* Build Decoding Tables */
615615
errorCode = ZSTD_decodeSeqHeaders(&nbSeq, &dumps, &dumpsLength,
@@ -691,7 +691,7 @@ size_t ZSTD_decompressDCtx(ZSTD_DCtx* ctx, void* dst, size_t maxDstSize, const v
691691

692692

693693
/* init */
694-
ctx->base = ctx->vBase = ctx->dictEnd = dst;
694+
ctx->vBase = ctx->base = ctx->dictEnd = dst;
695695

696696
/* Frame Header */
697697
{
@@ -776,7 +776,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* ctx, void* dst, size_t maxDstSize, con
776776
if ((dst > ctx->base) && (dst < ctx->previousDstEnd)) /* rolling buffer : new segment into dictionary */
777777
ctx->base = (char*)dst; /* temporary affectation, for vBase calculation */
778778
ctx->dictEnd = ctx->previousDstEnd;
779-
ctx->vBase = (char*)dst - ((char*)(ctx->previousDstEnd) - (char*)(ctx->base));
779+
ctx->vBase = (const char*)dst - ((const char*)(ctx->previousDstEnd) - (const char*)(ctx->base));
780780
ctx->base = dst;
781781
ctx->previousDstEnd = dst;
782782
}
@@ -827,10 +827,9 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* ctx, void* dst, size_t maxDstSize, con
827827
ctx->bType = bp.blockType;
828828
ctx->stage = ZSTDds_decompressBlock;
829829
}
830-
831830
return 0;
832831
}
833-
case 3:
832+
case ZSTDds_decompressBlock:
834833
{
835834
/* Decompress : block content */
836835
size_t rSize;
@@ -862,3 +861,10 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* ctx, void* dst, size_t maxDstSize, con
862861
}
863862

864863

864+
void ZSTD_decompress_insertDictionary(ZSTD_DCtx* ctx, const void* src, size_t srcSize)
865+
{
866+
ctx->dictEnd = ctx->previousDstEnd;
867+
ctx->vBase = (const char*)src - ((const char*)(ctx->previousDstEnd) - (const char*)(ctx->base));
868+
ctx->base = src;
869+
ctx->previousDstEnd = (const char*)src + srcSize;
870+
}

lib/zstd_static.h

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ size_t ZSTD_compress_advanced (ZSTD_CCtx* ctx,
104104
****************************************/
105105
size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, void* dst, size_t maxDstSize, int compressionLevel);
106106
size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* ctx, void* dst, size_t maxDstSize, ZSTD_parameters params);
107+
size_t ZSTD_compress_insertDictionary(ZSTD_CCtx* ctx, const void* src, size_t srcSize);
108+
107109
size_t ZSTD_compressContinue(ZSTD_CCtx* cctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize);
108110
size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t maxDstSize);
109111

@@ -118,6 +120,10 @@ size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t maxDstSize);
118120
Use ZSTD_compressBegin().
119121
You may also prefer the advanced derivative ZSTD_compressBegin_advanced(), for finer parameter control.
120122
123+
It's then possible to add a dictionary with ZSTD_compressDictionary()
124+
Note that dictionary presence is a "hidden" information,
125+
the decoder needs to be aware that it is required for proper decoding, or decoding will fail.
126+
121127
Then, consume your input using ZSTD_compressContinue().
122128
The interface is synchronous, so all input will be consumed.
123129
You must ensure there is enough space in destination buffer to store compressed data under worst case scenario.
@@ -131,12 +137,15 @@ size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t maxDstSize);
131137

132138
typedef struct ZSTD_DCtx_s ZSTD_DCtx;
133139
ZSTD_DCtx* ZSTD_createDCtx(void);
134-
size_t ZSTD_resetDCtx(ZSTD_DCtx* dctx);
135140
size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx);
136141

142+
size_t ZSTD_resetDCtx(ZSTD_DCtx* dctx);
137143
size_t ZSTD_getFrameParams(ZSTD_parameters* params, const void* src, size_t srcSize);
144+
void ZSTD_decompress_insertDictionary(ZSTD_DCtx* ctx, const void* src, size_t srcSize);
145+
138146
size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx);
139147
size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize);
148+
140149
/**
141150
Streaming decompression, bufferless mode
142151
@@ -146,15 +155,17 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize, co
146155
147156
First operation is to retrieve frame parameters, using ZSTD_getFrameParams().
148157
This function doesn't consume its input. It needs enough input data to properly decode the frame header.
149-
The objective is to retrieve *params.windowlog, to know minimum amount of memory required during decoding.
158+
Objective is to retrieve *params.windowlog, to know minimum amount of memory required during decoding.
150159
Result : 0 when successful, it means the ZSTD_parameters structure has been filled.
151160
>0 : means there is not enough data into src. Provides the expected size to successfully decode header.
152161
errorCode, which can be tested using ZSTD_isError() (For example, if it's not a ZSTD header)
153162
163+
Then, you can optionally insert a dictionary. This operation must mimic the compressor behavior, otherwise decompression will fail or be corrupted.
164+
154165
Then it's possible to start decompression.
155166
Use ZSTD_nextSrcSizeToDecompress() and ZSTD_decompressContinue() alternatively.
156167
ZSTD_nextSrcSizeToDecompress() tells how much bytes to provide as 'srcSize' to ZSTD_decompressContinue().
157-
ZSTD_decompressContinue() requires this exact amount of bytes, or just fails.
168+
ZSTD_decompressContinue() requires this exact amount of bytes, or it will fail.
158169
ZSTD_decompressContinue() needs previous data blocks during decompression, up to (1 << windowlog).
159170
They should preferably be located contiguously, prior to current block. Alternatively, a round buffer is also possible.
160171

0 commit comments

Comments
 (0)