zstd-ruby 0.1.2 → 1.1.3.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.
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Copyright (c) 2016-present, Facebook, Inc.
3
+ * All rights reserved.
4
+ *
5
+ * This source code is licensed under the BSD-style license found in the
6
+ * LICENSE file in the root directory of this source tree. An additional grant
7
+ * of patent rights can be found in the PATENTS file in the same directory.
8
+ */
9
+ #ifndef POOL_H
10
+ #define POOL_H
11
+
12
+ #if defined (__cplusplus)
13
+ extern "C" {
14
+ #endif
15
+
16
+
17
+ #include <stddef.h> /* size_t */
18
+
19
+ typedef struct POOL_ctx_s POOL_ctx;
20
+
21
+ /*! POOL_create() :
22
+ Create a thread pool with at most `numThreads` threads.
23
+ `numThreads` must be at least 1.
24
+ The maximum number of queued jobs before blocking is `queueSize`.
25
+ `queueSize` must be at least 1.
26
+ @return : The POOL_ctx pointer on success else NULL.
27
+ */
28
+ POOL_ctx *POOL_create(size_t numThreads, size_t queueSize);
29
+
30
+ /*! POOL_free() :
31
+ Free a thread pool returned by POOL_create().
32
+ */
33
+ void POOL_free(POOL_ctx *ctx);
34
+
35
+ /*! POOL_function :
36
+ The function type that can be added to a thread pool.
37
+ */
38
+ typedef void (*POOL_function)(void *);
39
+ /*! POOL_add_function :
40
+ The function type for a generic thread pool add function.
41
+ */
42
+ typedef void (*POOL_add_function)(void *, POOL_function, void *);
43
+
44
+ /*! POOL_add() :
45
+ Add the job `function(opaque)` to the thread pool.
46
+ Possibly blocks until there is room in the queue.
47
+ Note : The function may be executed asynchronously, so `opaque` must live until the function has been completed.
48
+ */
49
+ void POOL_add(void *ctx, POOL_function function, void *opaque);
50
+
51
+
52
+ #if defined (__cplusplus)
53
+ }
54
+ #endif
55
+
56
+ #endif
@@ -0,0 +1,79 @@
1
+
2
+ /**
3
+ * Copyright (c) 2016 Tino Reichardt
4
+ * All rights reserved.
5
+ *
6
+ * This source code is licensed under the BSD-style license found in the
7
+ * LICENSE file in the root directory of this source tree. An additional grant
8
+ * of patent rights can be found in the PATENTS file in the same directory.
9
+ *
10
+ * You can contact the author at:
11
+ * - zstdmt source repository: https://github.com/mcmilk/zstdmt
12
+ */
13
+
14
+ /**
15
+ * This file will hold wrapper for systems, which do not support pthreads
16
+ */
17
+
18
+ /* ====== Compiler specifics ====== */
19
+ #if defined(_MSC_VER)
20
+ # pragma warning(disable : 4206) /* disable: C4206: translation unit is empty (when ZSTD_MULTITHREAD is not defined) */
21
+ #endif
22
+
23
+
24
+ #if defined(ZSTD_MULTITHREAD) && defined(_WIN32)
25
+
26
+ /**
27
+ * Windows minimalist Pthread Wrapper, based on :
28
+ * http://www.cse.wustl.edu/~schmidt/win32-cv-1.html
29
+ */
30
+
31
+
32
+ /* === Dependencies === */
33
+ #include <process.h>
34
+ #include <errno.h>
35
+ #include "threading.h"
36
+
37
+
38
+ /* === Implementation === */
39
+
40
+ static unsigned __stdcall worker(void *arg)
41
+ {
42
+ pthread_t* const thread = (pthread_t*) arg;
43
+ thread->arg = thread->start_routine(thread->arg);
44
+ return 0;
45
+ }
46
+
47
+ int pthread_create(pthread_t* thread, const void* unused,
48
+ void* (*start_routine) (void*), void* arg)
49
+ {
50
+ (void)unused;
51
+ thread->arg = arg;
52
+ thread->start_routine = start_routine;
53
+ thread->handle = (HANDLE) _beginthreadex(NULL, 0, worker, thread, 0, NULL);
54
+
55
+ if (!thread->handle)
56
+ return errno;
57
+ else
58
+ return 0;
59
+ }
60
+
61
+ int _pthread_join(pthread_t * thread, void **value_ptr)
62
+ {
63
+ DWORD result;
64
+
65
+ if (!thread->handle) return 0;
66
+
67
+ result = WaitForSingleObject(thread->handle, INFINITE);
68
+ switch (result) {
69
+ case WAIT_OBJECT_0:
70
+ if (value_ptr) *value_ptr = thread->arg;
71
+ return 0;
72
+ case WAIT_ABANDONED:
73
+ return EINVAL;
74
+ default:
75
+ return GetLastError();
76
+ }
77
+ }
78
+
79
+ #endif /* ZSTD_MULTITHREAD */
@@ -0,0 +1,104 @@
1
+
2
+ /**
3
+ * Copyright (c) 2016 Tino Reichardt
4
+ * All rights reserved.
5
+ *
6
+ * This source code is licensed under the BSD-style license found in the
7
+ * LICENSE file in the root directory of this source tree. An additional grant
8
+ * of patent rights can be found in the PATENTS file in the same directory.
9
+ *
10
+ * You can contact the author at:
11
+ * - zstdmt source repository: https://github.com/mcmilk/zstdmt
12
+ */
13
+
14
+ #ifndef THREADING_H_938743
15
+ #define THREADING_H_938743
16
+
17
+ #if defined (__cplusplus)
18
+ extern "C" {
19
+ #endif
20
+
21
+ #if defined(ZSTD_MULTITHREAD) && defined(_WIN32)
22
+
23
+ /**
24
+ * Windows minimalist Pthread Wrapper, based on :
25
+ * http://www.cse.wustl.edu/~schmidt/win32-cv-1.html
26
+ */
27
+ #ifdef WINVER
28
+ # undef WINVER
29
+ #endif
30
+ #define WINVER 0x0600
31
+
32
+ #ifdef _WIN32_WINNT
33
+ # undef _WIN32_WINNT
34
+ #endif
35
+ #define _WIN32_WINNT 0x0600
36
+
37
+ #ifndef WIN32_LEAN_AND_MEAN
38
+ # define WIN32_LEAN_AND_MEAN
39
+ #endif
40
+
41
+ #include <windows.h>
42
+
43
+ /* mutex */
44
+ #define pthread_mutex_t CRITICAL_SECTION
45
+ #define pthread_mutex_init(a,b) InitializeCriticalSection((a))
46
+ #define pthread_mutex_destroy(a) DeleteCriticalSection((a))
47
+ #define pthread_mutex_lock(a) EnterCriticalSection((a))
48
+ #define pthread_mutex_unlock(a) LeaveCriticalSection((a))
49
+
50
+ /* condition variable */
51
+ #define pthread_cond_t CONDITION_VARIABLE
52
+ #define pthread_cond_init(a, b) InitializeConditionVariable((a))
53
+ #define pthread_cond_destroy(a) /* No delete */
54
+ #define pthread_cond_wait(a, b) SleepConditionVariableCS((a), (b), INFINITE)
55
+ #define pthread_cond_signal(a) WakeConditionVariable((a))
56
+ #define pthread_cond_broadcast(a) WakeAllConditionVariable((a))
57
+
58
+ /* pthread_create() and pthread_join() */
59
+ typedef struct {
60
+ HANDLE handle;
61
+ void* (*start_routine)(void*);
62
+ void* arg;
63
+ } pthread_t;
64
+
65
+ int pthread_create(pthread_t* thread, const void* unused,
66
+ void* (*start_routine) (void*), void* arg);
67
+
68
+ #define pthread_join(a, b) _pthread_join(&(a), (b))
69
+ int _pthread_join(pthread_t* thread, void** value_ptr);
70
+
71
+ /**
72
+ * add here more wrappers as required
73
+ */
74
+
75
+
76
+ #elif defined(ZSTD_MULTITHREAD) /* posix assumed ; need a better detection mathod */
77
+ /* === POSIX Systems === */
78
+ # include <pthread.h>
79
+
80
+ #else /* ZSTD_MULTITHREAD not defined */
81
+ /* No multithreading support */
82
+
83
+ #define pthread_mutex_t int /* #define rather than typedef, as sometimes pthread support is implicit, resulting in duplicated symbols */
84
+ #define pthread_mutex_init(a,b)
85
+ #define pthread_mutex_destroy(a)
86
+ #define pthread_mutex_lock(a)
87
+ #define pthread_mutex_unlock(a)
88
+
89
+ #define pthread_cond_t int
90
+ #define pthread_cond_init(a,b)
91
+ #define pthread_cond_destroy(a)
92
+ #define pthread_cond_wait(a,b)
93
+ #define pthread_cond_signal(a)
94
+ #define pthread_cond_broadcast(a)
95
+
96
+ /* do not use pthread_t */
97
+
98
+ #endif /* ZSTD_MULTITHREAD */
99
+
100
+ #if defined (__cplusplus)
101
+ }
102
+ #endif
103
+
104
+ #endif /* THREADING_H_938743 */
@@ -43,10 +43,6 @@ ZSTD_ErrorCode ZSTD_getErrorCode(size_t code) { return ERR_getErrorCode(code); }
43
43
  * provides error code string from enum */
44
44
  const char* ZSTD_getErrorString(ZSTD_ErrorCode code) { return ERR_getErrorName(code); }
45
45
 
46
- /* --- ZBUFF Error Management (deprecated) --- */
47
- unsigned ZBUFF_isError(size_t errorCode) { return ERR_isError(errorCode); }
48
- const char* ZBUFF_getErrorName(size_t errorCode) { return ERR_getErrorName(errorCode); }
49
-
50
46
 
51
47
  /*=**************************************************************
52
48
  * Custom allocator
@@ -18,6 +18,20 @@ extern "C" {
18
18
  #include <stddef.h> /* size_t */
19
19
 
20
20
 
21
+ /* ===== ZSTDERRORLIB_API : control library symbols visibility ===== */
22
+ #if defined(__GNUC__) && (__GNUC__ >= 4)
23
+ # define ZSTDERRORLIB_VISIBILITY __attribute__ ((visibility ("default")))
24
+ #else
25
+ # define ZSTDERRORLIB_VISIBILITY
26
+ #endif
27
+ #if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1)
28
+ # define ZSTDERRORLIB_API __declspec(dllexport) ZSTDERRORLIB_VISIBILITY
29
+ #elif defined(ZSTD_DLL_IMPORT) && (ZSTD_DLL_IMPORT==1)
30
+ # define ZSTDERRORLIB_API __declspec(dllimport) ZSTDERRORLIB_VISIBILITY /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/
31
+ #else
32
+ # define ZSTDERRORLIB_API ZSTDERRORLIB_VISIBILITY
33
+ #endif
34
+
21
35
  /*-****************************************
22
36
  * error codes list
23
37
  ******************************************/
@@ -49,8 +63,8 @@ typedef enum {
49
63
  /*! ZSTD_getErrorCode() :
50
64
  convert a `size_t` function result into a `ZSTD_ErrorCode` enum type,
51
65
  which can be used to compare directly with enum list published into "error_public.h" */
52
- ZSTD_ErrorCode ZSTD_getErrorCode(size_t functionResult);
53
- const char* ZSTD_getErrorString(ZSTD_ErrorCode code);
66
+ ZSTDERRORLIB_API ZSTD_ErrorCode ZSTD_getErrorCode(size_t functionResult);
67
+ ZSTDERRORLIB_API const char* ZSTD_getErrorString(ZSTD_ErrorCode code);
54
68
 
55
69
 
56
70
  #if defined (__cplusplus)
@@ -267,4 +267,13 @@ MEM_STATIC U32 ZSTD_highbit32(U32 val)
267
267
  }
268
268
 
269
269
 
270
+ /* hidden functions */
271
+
272
+ /* ZSTD_invalidateRepCodes() :
273
+ * ensures next compression will not use repcodes from previous block.
274
+ * Note : only works with regular variant;
275
+ * do not use with extDict variant ! */
276
+ void ZSTD_invalidateRepCodes(ZSTD_CCtx* cctx);
277
+
278
+
270
279
  #endif /* ZSTD_CCOMMON_H_MODULE */
@@ -51,8 +51,7 @@ static void ZSTD_resetSeqStore(seqStore_t* ssPtr)
51
51
  /*-*************************************
52
52
  * Context memory management
53
53
  ***************************************/
54
- struct ZSTD_CCtx_s
55
- {
54
+ struct ZSTD_CCtx_s {
56
55
  const BYTE* nextSrc; /* next block here to continue on current prefix */
57
56
  const BYTE* base; /* All regular indexes relative to this position */
58
57
  const BYTE* dictBase; /* extDict indexes relative to this position */
@@ -61,10 +60,11 @@ struct ZSTD_CCtx_s
61
60
  U32 nextToUpdate; /* index from which to continue dictionary update */
62
61
  U32 nextToUpdate3; /* index from which to continue dictionary update */
63
62
  U32 hashLog3; /* dispatch table : larger == faster, more memory */
64
- U32 loadedDictEnd;
63
+ U32 loadedDictEnd; /* index of end of dictionary */
64
+ U32 forceWindow; /* force back-references to respect limit of 1<<wLog, even for dictionary */
65
65
  ZSTD_compressionStage_e stage;
66
66
  U32 rep[ZSTD_REP_NUM];
67
- U32 savedRep[ZSTD_REP_NUM];
67
+ U32 repToConfirm[ZSTD_REP_NUM];
68
68
  U32 dictID;
69
69
  ZSTD_parameters params;
70
70
  void* workSpace;
@@ -101,7 +101,7 @@ ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem)
101
101
  cctx = (ZSTD_CCtx*) ZSTD_malloc(sizeof(ZSTD_CCtx), customMem);
102
102
  if (!cctx) return NULL;
103
103
  memset(cctx, 0, sizeof(ZSTD_CCtx));
104
- memcpy(&(cctx->customMem), &customMem, sizeof(customMem));
104
+ cctx->customMem = customMem;
105
105
  return cctx;
106
106
  }
107
107
 
@@ -119,6 +119,15 @@ size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx)
119
119
  return sizeof(*cctx) + cctx->workSpaceSize;
120
120
  }
121
121
 
122
+ size_t ZSTD_setCCtxParameter(ZSTD_CCtx* cctx, ZSTD_CCtxParameter param, unsigned value)
123
+ {
124
+ switch(param)
125
+ {
126
+ case ZSTD_p_forceWindow : cctx->forceWindow = value>0; cctx->loadedDictEnd = 0; return 0;
127
+ default: return ERROR(parameter_unknown);
128
+ }
129
+ }
130
+
122
131
  const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx) /* hidden interface */
123
132
  {
124
133
  return &(ctx->seqStore);
@@ -318,6 +327,14 @@ static size_t ZSTD_resetCCtx_advanced (ZSTD_CCtx* zc,
318
327
  }
319
328
  }
320
329
 
330
+ /* ZSTD_invalidateRepCodes() :
331
+ * ensures next compression will not use repcodes from previous block.
332
+ * Note : only works with regular variant;
333
+ * do not use with extDict variant ! */
334
+ void ZSTD_invalidateRepCodes(ZSTD_CCtx* cctx) {
335
+ int i;
336
+ for (i=0; i<ZSTD_REP_NUM; i++) cctx->rep[i] = 0;
337
+ }
321
338
 
322
339
  /*! ZSTD_copyCCtx() :
323
340
  * Duplicate an existing context `srcCCtx` into another one `dstCCtx`.
@@ -735,12 +752,19 @@ _check_compressibility:
735
752
  if ((size_t)(op-ostart) >= maxCSize) return 0; }
736
753
 
737
754
  /* confirm repcodes */
738
- { int i; for (i=0; i<ZSTD_REP_NUM; i++) zc->rep[i] = zc->savedRep[i]; }
755
+ { int i; for (i=0; i<ZSTD_REP_NUM; i++) zc->rep[i] = zc->repToConfirm[i]; }
739
756
 
740
757
  return op - ostart;
741
758
  }
742
759
 
743
760
 
761
+ #if 0 /* for debug */
762
+ # define STORESEQ_DEBUG
763
+ #include <stdio.h> /* fprintf */
764
+ U32 g_startDebug = 0;
765
+ const BYTE* g_start = NULL;
766
+ #endif
767
+
744
768
  /*! ZSTD_storeSeq() :
745
769
  Store a sequence (literal length, literals, offset code and match length code) into seqStore_t.
746
770
  `offsetCode` : distance to match, or 0 == repCode.
@@ -748,13 +772,14 @@ _check_compressibility:
748
772
  */
749
773
  MEM_STATIC void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const void* literals, U32 offsetCode, size_t matchCode)
750
774
  {
751
- #if 0 /* for debug */
752
- static const BYTE* g_start = NULL;
753
- const U32 pos = (U32)((const BYTE*)literals - g_start);
754
- if (g_start==NULL) g_start = (const BYTE*)literals;
755
- //if ((pos > 1) && (pos < 50000))
756
- printf("Cpos %6u :%5u literals & match %3u bytes at distance %6u \n",
757
- pos, (U32)litLength, (U32)matchCode+MINMATCH, (U32)offsetCode);
775
+ #ifdef STORESEQ_DEBUG
776
+ if (g_startDebug) {
777
+ const U32 pos = (U32)((const BYTE*)literals - g_start);
778
+ if (g_start==NULL) g_start = (const BYTE*)literals;
779
+ if ((pos > 1895000) && (pos < 1895300))
780
+ fprintf(stderr, "Cpos %6u :%5u literals & match %3u bytes at distance %6u \n",
781
+ pos, (U32)litLength, (U32)matchCode+MINMATCH, (U32)offsetCode);
782
+ }
758
783
  #endif
759
784
  /* copy Literals */
760
785
  ZSTD_wildcopy(seqStorePtr->lit, literals, litLength);
@@ -1004,8 +1029,8 @@ void ZSTD_compressBlock_fast_generic(ZSTD_CCtx* cctx,
1004
1029
  } } }
1005
1030
 
1006
1031
  /* save reps for next block */
1007
- cctx->savedRep[0] = offset_1 ? offset_1 : offsetSaved;
1008
- cctx->savedRep[1] = offset_2 ? offset_2 : offsetSaved;
1032
+ cctx->repToConfirm[0] = offset_1 ? offset_1 : offsetSaved;
1033
+ cctx->repToConfirm[1] = offset_2 ? offset_2 : offsetSaved;
1009
1034
 
1010
1035
  /* Last Literals */
1011
1036
  { size_t const lastLLSize = iend - anchor;
@@ -1119,7 +1144,7 @@ static void ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
1119
1144
  } } }
1120
1145
 
1121
1146
  /* save reps for next block */
1122
- ctx->savedRep[0] = offset_1; ctx->savedRep[1] = offset_2;
1147
+ ctx->repToConfirm[0] = offset_1; ctx->repToConfirm[1] = offset_2;
1123
1148
 
1124
1149
  /* Last Literals */
1125
1150
  { size_t const lastLLSize = iend - anchor;
@@ -1273,8 +1298,8 @@ void ZSTD_compressBlock_doubleFast_generic(ZSTD_CCtx* cctx,
1273
1298
  } } }
1274
1299
 
1275
1300
  /* save reps for next block */
1276
- cctx->savedRep[0] = offset_1 ? offset_1 : offsetSaved;
1277
- cctx->savedRep[1] = offset_2 ? offset_2 : offsetSaved;
1301
+ cctx->repToConfirm[0] = offset_1 ? offset_1 : offsetSaved;
1302
+ cctx->repToConfirm[1] = offset_2 ? offset_2 : offsetSaved;
1278
1303
 
1279
1304
  /* Last Literals */
1280
1305
  { size_t const lastLLSize = iend - anchor;
@@ -1423,7 +1448,7 @@ static void ZSTD_compressBlock_doubleFast_extDict_generic(ZSTD_CCtx* ctx,
1423
1448
  } } }
1424
1449
 
1425
1450
  /* save reps for next block */
1426
- ctx->savedRep[0] = offset_1; ctx->savedRep[1] = offset_2;
1451
+ ctx->repToConfirm[0] = offset_1; ctx->repToConfirm[1] = offset_2;
1427
1452
 
1428
1453
  /* Last Literals */
1429
1454
  { size_t const lastLLSize = iend - anchor;
@@ -1955,8 +1980,8 @@ _storeSequence:
1955
1980
  } }
1956
1981
 
1957
1982
  /* Save reps for next block */
1958
- ctx->savedRep[0] = offset_1 ? offset_1 : savedOffset;
1959
- ctx->savedRep[1] = offset_2 ? offset_2 : savedOffset;
1983
+ ctx->repToConfirm[0] = offset_1 ? offset_1 : savedOffset;
1984
+ ctx->repToConfirm[1] = offset_2 ? offset_2 : savedOffset;
1960
1985
 
1961
1986
  /* Last Literals */
1962
1987
  { size_t const lastLLSize = iend - anchor;
@@ -2150,7 +2175,7 @@ _storeSequence:
2150
2175
  } }
2151
2176
 
2152
2177
  /* Save reps for next block */
2153
- ctx->savedRep[0] = offset_1; ctx->savedRep[1] = offset_2;
2178
+ ctx->repToConfirm[0] = offset_1; ctx->repToConfirm[1] = offset_2;
2154
2179
 
2155
2180
  /* Last Literals */
2156
2181
  { size_t const lastLLSize = iend - anchor;
@@ -2409,12 +2434,14 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
2409
2434
 
2410
2435
  cctx->nextSrc = ip + srcSize;
2411
2436
 
2412
- { size_t const cSize = frame ?
2437
+ if (srcSize) {
2438
+ size_t const cSize = frame ?
2413
2439
  ZSTD_compress_generic (cctx, dst, dstCapacity, src, srcSize, lastFrameChunk) :
2414
2440
  ZSTD_compressBlock_internal (cctx, dst, dstCapacity, src, srcSize);
2415
2441
  if (ZSTD_isError(cSize)) return cSize;
2416
2442
  return cSize + fhSize;
2417
- }
2443
+ } else
2444
+ return fhSize;
2418
2445
  }
2419
2446
 
2420
2447
 
@@ -2450,7 +2477,7 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_CCtx* zc, const void* src, size_t
2450
2477
  zc->dictBase = zc->base;
2451
2478
  zc->base += ip - zc->nextSrc;
2452
2479
  zc->nextToUpdate = zc->dictLimit;
2453
- zc->loadedDictEnd = (U32)(iend - zc->base);
2480
+ zc->loadedDictEnd = zc->forceWindow ? 0 : (U32)(iend - zc->base);
2454
2481
 
2455
2482
  zc->nextSrc = iend;
2456
2483
  if (srcSize <= HASH_READ_SIZE) return 0;
@@ -2557,9 +2584,9 @@ static size_t ZSTD_loadDictEntropyStats(ZSTD_CCtx* cctx, const void* dict, size_
2557
2584
  }
2558
2585
 
2559
2586
  if (dictPtr+12 > dictEnd) return ERROR(dictionary_corrupted);
2560
- cctx->rep[0] = MEM_readLE32(dictPtr+0); if (cctx->rep[0] >= dictSize) return ERROR(dictionary_corrupted);
2561
- cctx->rep[1] = MEM_readLE32(dictPtr+4); if (cctx->rep[1] >= dictSize) return ERROR(dictionary_corrupted);
2562
- cctx->rep[2] = MEM_readLE32(dictPtr+8); if (cctx->rep[2] >= dictSize) return ERROR(dictionary_corrupted);
2587
+ cctx->rep[0] = MEM_readLE32(dictPtr+0); if (cctx->rep[0] == 0 || cctx->rep[0] >= dictSize) return ERROR(dictionary_corrupted);
2588
+ cctx->rep[1] = MEM_readLE32(dictPtr+4); if (cctx->rep[1] == 0 || cctx->rep[1] >= dictSize) return ERROR(dictionary_corrupted);
2589
+ cctx->rep[2] = MEM_readLE32(dictPtr+8); if (cctx->rep[2] == 0 || cctx->rep[2] >= dictSize) return ERROR(dictionary_corrupted);
2563
2590
  dictPtr += 12;
2564
2591
 
2565
2592
  { U32 offcodeMax = MaxOff;
@@ -2594,7 +2621,6 @@ static size_t ZSTD_compress_insertDictionary(ZSTD_CCtx* zc, const void* dict, si
2594
2621
  }
2595
2622
  }
2596
2623
 
2597
-
2598
2624
  /*! ZSTD_compressBegin_internal() :
2599
2625
  * @return : 0, or an error code */
2600
2626
  static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
@@ -2626,9 +2652,9 @@ size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t di
2626
2652
  }
2627
2653
 
2628
2654
 
2629
- size_t ZSTD_compressBegin(ZSTD_CCtx* zc, int compressionLevel)
2655
+ size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel)
2630
2656
  {
2631
- return ZSTD_compressBegin_usingDict(zc, NULL, 0, compressionLevel);
2657
+ return ZSTD_compressBegin_usingDict(cctx, NULL, 0, compressionLevel);
2632
2658
  }
2633
2659
 
2634
2660
 
@@ -2733,7 +2759,8 @@ size_t ZSTD_compress(void* dst, size_t dstCapacity, const void* src, size_t srcS
2733
2759
  /* ===== Dictionary API ===== */
2734
2760
 
2735
2761
  struct ZSTD_CDict_s {
2736
- void* dictContent;
2762
+ void* dictBuffer;
2763
+ const void* dictContent;
2737
2764
  size_t dictContentSize;
2738
2765
  ZSTD_CCtx* refContext;
2739
2766
  }; /* typedef'd tp ZSTD_CDict within "zstd.h" */
@@ -2741,39 +2768,45 @@ struct ZSTD_CDict_s {
2741
2768
  size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict)
2742
2769
  {
2743
2770
  if (cdict==NULL) return 0; /* support sizeof on NULL */
2744
- return ZSTD_sizeof_CCtx(cdict->refContext) + cdict->dictContentSize;
2771
+ return ZSTD_sizeof_CCtx(cdict->refContext) + (cdict->dictBuffer ? cdict->dictContentSize : 0) + sizeof(*cdict);
2745
2772
  }
2746
2773
 
2747
- ZSTD_CDict* ZSTD_createCDict_advanced(const void* dict, size_t dictSize, ZSTD_parameters params, ZSTD_customMem customMem)
2774
+ ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize, unsigned byReference,
2775
+ ZSTD_parameters params, ZSTD_customMem customMem)
2748
2776
  {
2749
2777
  if (!customMem.customAlloc && !customMem.customFree) customMem = defaultCustomMem;
2750
2778
  if (!customMem.customAlloc || !customMem.customFree) return NULL;
2751
2779
 
2752
2780
  { ZSTD_CDict* const cdict = (ZSTD_CDict*) ZSTD_malloc(sizeof(ZSTD_CDict), customMem);
2753
- void* const dictContent = ZSTD_malloc(dictSize, customMem);
2754
2781
  ZSTD_CCtx* const cctx = ZSTD_createCCtx_advanced(customMem);
2755
2782
 
2756
- if (!dictContent || !cdict || !cctx) {
2757
- ZSTD_free(dictContent, customMem);
2783
+ if (!cdict || !cctx) {
2758
2784
  ZSTD_free(cdict, customMem);
2759
2785
  ZSTD_free(cctx, customMem);
2760
2786
  return NULL;
2761
2787
  }
2762
2788
 
2763
- if (dictSize) {
2764
- memcpy(dictContent, dict, dictSize);
2789
+ if ((byReference) || (!dictBuffer) || (!dictSize)) {
2790
+ cdict->dictBuffer = NULL;
2791
+ cdict->dictContent = dictBuffer;
2792
+ } else {
2793
+ void* const internalBuffer = ZSTD_malloc(dictSize, customMem);
2794
+ if (!internalBuffer) { ZSTD_free(cctx, customMem); ZSTD_free(cdict, customMem); return NULL; }
2795
+ memcpy(internalBuffer, dictBuffer, dictSize);
2796
+ cdict->dictBuffer = internalBuffer;
2797
+ cdict->dictContent = internalBuffer;
2765
2798
  }
2766
- { size_t const errorCode = ZSTD_compressBegin_advanced(cctx, dictContent, dictSize, params, 0);
2799
+
2800
+ { size_t const errorCode = ZSTD_compressBegin_advanced(cctx, cdict->dictContent, dictSize, params, 0);
2767
2801
  if (ZSTD_isError(errorCode)) {
2768
- ZSTD_free(dictContent, customMem);
2769
- ZSTD_free(cdict, customMem);
2802
+ ZSTD_free(cdict->dictBuffer, customMem);
2770
2803
  ZSTD_free(cctx, customMem);
2804
+ ZSTD_free(cdict, customMem);
2771
2805
  return NULL;
2772
2806
  } }
2773
2807
 
2774
- cdict->dictContent = dictContent;
2775
- cdict->dictContentSize = dictSize;
2776
2808
  cdict->refContext = cctx;
2809
+ cdict->dictContentSize = dictSize;
2777
2810
  return cdict;
2778
2811
  }
2779
2812
  }
@@ -2783,7 +2816,15 @@ ZSTD_CDict* ZSTD_createCDict(const void* dict, size_t dictSize, int compressionL
2783
2816
  ZSTD_customMem const allocator = { NULL, NULL, NULL };
2784
2817
  ZSTD_parameters params = ZSTD_getParams(compressionLevel, 0, dictSize);
2785
2818
  params.fParams.contentSizeFlag = 1;
2786
- return ZSTD_createCDict_advanced(dict, dictSize, params, allocator);
2819
+ return ZSTD_createCDict_advanced(dict, dictSize, 0, params, allocator);
2820
+ }
2821
+
2822
+ ZSTD_CDict* ZSTD_createCDict_byReference(const void* dict, size_t dictSize, int compressionLevel)
2823
+ {
2824
+ ZSTD_customMem const allocator = { NULL, NULL, NULL };
2825
+ ZSTD_parameters params = ZSTD_getParams(compressionLevel, 0, dictSize);
2826
+ params.fParams.contentSizeFlag = 1;
2827
+ return ZSTD_createCDict_advanced(dict, dictSize, 1, params, allocator);
2787
2828
  }
2788
2829
 
2789
2830
  size_t ZSTD_freeCDict(ZSTD_CDict* cdict)
@@ -2791,7 +2832,7 @@ size_t ZSTD_freeCDict(ZSTD_CDict* cdict)
2791
2832
  if (cdict==NULL) return 0; /* support free on NULL */
2792
2833
  { ZSTD_customMem const cMem = cdict->refContext->customMem;
2793
2834
  ZSTD_freeCCtx(cdict->refContext);
2794
- ZSTD_free(cdict->dictContent, cMem);
2835
+ ZSTD_free(cdict->dictBuffer, cMem);
2795
2836
  ZSTD_free(cdict, cMem);
2796
2837
  return 0;
2797
2838
  }
@@ -2801,7 +2842,7 @@ static ZSTD_parameters ZSTD_getParamsFromCDict(const ZSTD_CDict* cdict) {
2801
2842
  return ZSTD_getParamsFromCCtx(cdict->refContext);
2802
2843
  }
2803
2844
 
2804
- size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict, U64 pledgedSrcSize)
2845
+ size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict, unsigned long long pledgedSrcSize)
2805
2846
  {
2806
2847
  if (cdict->dictContentSize) CHECK_F(ZSTD_copyCCtx(cctx, cdict->refContext, pledgedSrcSize))
2807
2848
  else CHECK_F(ZSTD_compressBegin_advanced(cctx, NULL, 0, cdict->refContext->params, pledgedSrcSize));
@@ -2900,7 +2941,7 @@ size_t ZSTD_CStreamOutSize(void) { return ZSTD_compressBound(ZSTD_BLOCKSIZE_ABSO
2900
2941
 
2901
2942
  size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize)
2902
2943
  {
2903
- if (zcs->inBuffSize==0) return ERROR(stage_wrong); /* zcs has not been init at least once */
2944
+ if (zcs->inBuffSize==0) return ERROR(stage_wrong); /* zcs has not been init at least once => can't reset */
2904
2945
 
2905
2946
  if (zcs->cdict) CHECK_F(ZSTD_compressBegin_usingCDict(zcs->cctx, zcs->cdict, pledgedSrcSize))
2906
2947
  else CHECK_F(ZSTD_compressBegin_advanced(zcs->cctx, NULL, 0, zcs->params, pledgedSrcSize));
@@ -2937,9 +2978,9 @@ size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs,
2937
2978
  if (zcs->outBuff == NULL) return ERROR(memory_allocation);
2938
2979
  }
2939
2980
 
2940
- if (dict) {
2981
+ if (dict && dictSize >= 8) {
2941
2982
  ZSTD_freeCDict(zcs->cdictLocal);
2942
- zcs->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize, params, zcs->customMem);
2983
+ zcs->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize, 0, params, zcs->customMem);
2943
2984
  if (zcs->cdictLocal == NULL) return ERROR(memory_allocation);
2944
2985
  zcs->cdict = zcs->cdictLocal;
2945
2986
  } else zcs->cdict = NULL;
@@ -2956,6 +2997,7 @@ size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict)
2956
2997
  ZSTD_parameters const params = ZSTD_getParamsFromCDict(cdict);
2957
2998
  size_t const initError = ZSTD_initCStream_advanced(zcs, NULL, 0, params, 0);
2958
2999
  zcs->cdict = cdict;
3000
+ zcs->cctx->dictID = params.fParams.noDictIDFlag ? 0 : cdict->refContext->dictID;
2959
3001
  return initError;
2960
3002
  }
2961
3003
 
@@ -2967,7 +3009,8 @@ size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t di
2967
3009
 
2968
3010
  size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pledgedSrcSize)
2969
3011
  {
2970
- ZSTD_parameters const params = ZSTD_getParams(compressionLevel, pledgedSrcSize, 0);
3012
+ ZSTD_parameters params = ZSTD_getParams(compressionLevel, pledgedSrcSize, 0);
3013
+ if (pledgedSrcSize) params.fParams.contentSizeFlag = 1;
2971
3014
  return ZSTD_initCStream_advanced(zcs, NULL, 0, params, pledgedSrcSize);
2972
3015
  }
2973
3016