zstd-ruby 0.1.2 → 1.1.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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