extzstd 0.0.3.CONCEPT → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (138) hide show
  1. checksums.yaml +5 -5
  2. data/HISTORY.ja.md +39 -0
  3. data/LICENSE +6 -6
  4. data/README.md +26 -45
  5. data/contrib/zstd/CHANGELOG +555 -0
  6. data/contrib/zstd/CODE_OF_CONDUCT.md +5 -0
  7. data/contrib/zstd/CONTRIBUTING.md +392 -0
  8. data/contrib/zstd/COPYING +339 -0
  9. data/contrib/zstd/LICENSE +13 -9
  10. data/contrib/zstd/Makefile +414 -0
  11. data/contrib/zstd/README.md +170 -45
  12. data/contrib/zstd/TESTING.md +44 -0
  13. data/contrib/zstd/appveyor.yml +289 -0
  14. data/contrib/zstd/lib/BUCK +234 -0
  15. data/contrib/zstd/lib/Makefile +354 -0
  16. data/contrib/zstd/lib/README.md +179 -0
  17. data/contrib/zstd/{common → lib/common}/bitstream.h +170 -130
  18. data/contrib/zstd/lib/common/compiler.h +175 -0
  19. data/contrib/zstd/lib/common/cpu.h +215 -0
  20. data/contrib/zstd/lib/common/debug.c +24 -0
  21. data/contrib/zstd/lib/common/debug.h +114 -0
  22. data/contrib/zstd/{common → lib/common}/entropy_common.c +79 -94
  23. data/contrib/zstd/lib/common/error_private.c +55 -0
  24. data/contrib/zstd/lib/common/error_private.h +80 -0
  25. data/contrib/zstd/{common → lib/common}/fse.h +153 -93
  26. data/contrib/zstd/{common → lib/common}/fse_decompress.c +37 -82
  27. data/contrib/zstd/lib/common/huf.h +340 -0
  28. data/contrib/zstd/{common → lib/common}/mem.h +154 -78
  29. data/contrib/zstd/lib/common/pool.c +344 -0
  30. data/contrib/zstd/lib/common/pool.h +84 -0
  31. data/contrib/zstd/lib/common/threading.c +121 -0
  32. data/contrib/zstd/lib/common/threading.h +155 -0
  33. data/contrib/zstd/{common → lib/common}/xxhash.c +85 -75
  34. data/contrib/zstd/{common → lib/common}/xxhash.h +85 -73
  35. data/contrib/zstd/lib/common/zstd_common.c +83 -0
  36. data/contrib/zstd/lib/common/zstd_errors.h +94 -0
  37. data/contrib/zstd/lib/common/zstd_internal.h +447 -0
  38. data/contrib/zstd/{compress → lib/compress}/fse_compress.c +194 -303
  39. data/contrib/zstd/lib/compress/hist.c +183 -0
  40. data/contrib/zstd/lib/compress/hist.h +75 -0
  41. data/contrib/zstd/lib/compress/huf_compress.c +798 -0
  42. data/contrib/zstd/lib/compress/zstd_compress.c +4278 -0
  43. data/contrib/zstd/lib/compress/zstd_compress_internal.h +1125 -0
  44. data/contrib/zstd/lib/compress/zstd_compress_literals.c +158 -0
  45. data/contrib/zstd/lib/compress/zstd_compress_literals.h +29 -0
  46. data/contrib/zstd/lib/compress/zstd_compress_sequences.c +419 -0
  47. data/contrib/zstd/lib/compress/zstd_compress_sequences.h +54 -0
  48. data/contrib/zstd/lib/compress/zstd_compress_superblock.c +845 -0
  49. data/contrib/zstd/lib/compress/zstd_compress_superblock.h +32 -0
  50. data/contrib/zstd/lib/compress/zstd_cwksp.h +525 -0
  51. data/contrib/zstd/lib/compress/zstd_double_fast.c +521 -0
  52. data/contrib/zstd/lib/compress/zstd_double_fast.h +38 -0
  53. data/contrib/zstd/lib/compress/zstd_fast.c +496 -0
  54. data/contrib/zstd/lib/compress/zstd_fast.h +37 -0
  55. data/contrib/zstd/lib/compress/zstd_lazy.c +1138 -0
  56. data/contrib/zstd/lib/compress/zstd_lazy.h +67 -0
  57. data/contrib/zstd/lib/compress/zstd_ldm.c +619 -0
  58. data/contrib/zstd/lib/compress/zstd_ldm.h +110 -0
  59. data/contrib/zstd/lib/compress/zstd_opt.c +1200 -0
  60. data/contrib/zstd/lib/compress/zstd_opt.h +56 -0
  61. data/contrib/zstd/lib/compress/zstdmt_compress.c +2143 -0
  62. data/contrib/zstd/lib/compress/zstdmt_compress.h +192 -0
  63. data/contrib/zstd/lib/decompress/huf_decompress.c +1248 -0
  64. data/contrib/zstd/lib/decompress/zstd_ddict.c +244 -0
  65. data/contrib/zstd/lib/decompress/zstd_ddict.h +44 -0
  66. data/contrib/zstd/lib/decompress/zstd_decompress.c +1885 -0
  67. data/contrib/zstd/lib/decompress/zstd_decompress_block.c +1432 -0
  68. data/contrib/zstd/lib/decompress/zstd_decompress_block.h +59 -0
  69. data/contrib/zstd/lib/decompress/zstd_decompress_internal.h +189 -0
  70. data/contrib/zstd/{common → lib/deprecated}/zbuff.h +86 -69
  71. data/contrib/zstd/lib/deprecated/zbuff_common.c +26 -0
  72. data/contrib/zstd/lib/deprecated/zbuff_compress.c +147 -0
  73. data/contrib/zstd/lib/deprecated/zbuff_decompress.c +75 -0
  74. data/contrib/zstd/lib/dictBuilder/cover.c +1236 -0
  75. data/contrib/zstd/lib/dictBuilder/cover.h +157 -0
  76. data/contrib/zstd/{dictBuilder → lib/dictBuilder}/divsufsort.c +3 -3
  77. data/contrib/zstd/{dictBuilder → lib/dictBuilder}/divsufsort.h +5 -5
  78. data/contrib/zstd/lib/dictBuilder/fastcover.c +757 -0
  79. data/contrib/zstd/{dictBuilder → lib/dictBuilder}/zdict.c +437 -347
  80. data/contrib/zstd/lib/dictBuilder/zdict.h +305 -0
  81. data/contrib/zstd/lib/legacy/zstd_legacy.h +415 -0
  82. data/contrib/zstd/{legacy → lib/legacy}/zstd_v01.c +272 -292
  83. data/contrib/zstd/{legacy → lib/legacy}/zstd_v01.h +26 -32
  84. data/contrib/zstd/{legacy → lib/legacy}/zstd_v02.c +162 -392
  85. data/contrib/zstd/{legacy → lib/legacy}/zstd_v02.h +26 -32
  86. data/contrib/zstd/{legacy → lib/legacy}/zstd_v03.c +162 -391
  87. data/contrib/zstd/{legacy → lib/legacy}/zstd_v03.h +27 -33
  88. data/contrib/zstd/{legacy → lib/legacy}/zstd_v04.c +195 -604
  89. data/contrib/zstd/{legacy → lib/legacy}/zstd_v04.h +26 -32
  90. data/contrib/zstd/{legacy → lib/legacy}/zstd_v05.c +300 -575
  91. data/contrib/zstd/{legacy → lib/legacy}/zstd_v05.h +22 -31
  92. data/contrib/zstd/{legacy → lib/legacy}/zstd_v06.c +165 -592
  93. data/contrib/zstd/{legacy → lib/legacy}/zstd_v06.h +54 -67
  94. data/contrib/zstd/lib/legacy/zstd_v07.c +4541 -0
  95. data/contrib/zstd/lib/legacy/zstd_v07.h +187 -0
  96. data/contrib/zstd/lib/libzstd.pc.in +15 -0
  97. data/contrib/zstd/lib/zstd.h +2090 -0
  98. data/ext/depend +2 -0
  99. data/ext/extconf.rb +18 -5
  100. data/ext/extzstd.c +296 -214
  101. data/ext/extzstd.h +81 -36
  102. data/ext/extzstd_nogvls.h +0 -117
  103. data/ext/extzstd_stream.c +622 -0
  104. data/ext/libzstd_conf.h +8 -0
  105. data/ext/zstd_common.c +11 -0
  106. data/ext/zstd_compress.c +15 -0
  107. data/ext/zstd_decompress.c +6 -0
  108. data/ext/zstd_dictbuilder.c +10 -0
  109. data/ext/zstd_dictbuilder_fastcover.c +3 -0
  110. data/ext/zstd_legacy_v01.c +3 -1
  111. data/ext/zstd_legacy_v02.c +3 -1
  112. data/ext/zstd_legacy_v03.c +3 -1
  113. data/ext/zstd_legacy_v04.c +3 -1
  114. data/ext/zstd_legacy_v05.c +3 -1
  115. data/ext/zstd_legacy_v06.c +3 -1
  116. data/ext/zstd_legacy_v07.c +3 -0
  117. data/gemstub.rb +27 -21
  118. data/lib/extzstd.rb +82 -161
  119. data/lib/extzstd/version.rb +1 -1
  120. data/test/test_basic.rb +19 -6
  121. metadata +127 -59
  122. data/contrib/zstd/common/error_private.h +0 -125
  123. data/contrib/zstd/common/error_public.h +0 -77
  124. data/contrib/zstd/common/huf.h +0 -228
  125. data/contrib/zstd/common/zstd.h +0 -475
  126. data/contrib/zstd/common/zstd_common.c +0 -91
  127. data/contrib/zstd/common/zstd_internal.h +0 -238
  128. data/contrib/zstd/compress/huf_compress.c +0 -577
  129. data/contrib/zstd/compress/zbuff_compress.c +0 -327
  130. data/contrib/zstd/compress/zstd_compress.c +0 -3074
  131. data/contrib/zstd/compress/zstd_opt.h +0 -1046
  132. data/contrib/zstd/decompress/huf_decompress.c +0 -894
  133. data/contrib/zstd/decompress/zbuff_decompress.c +0 -294
  134. data/contrib/zstd/decompress/zstd_decompress.c +0 -1362
  135. data/contrib/zstd/dictBuilder/zdict.h +0 -113
  136. data/contrib/zstd/legacy/zstd_legacy.h +0 -140
  137. data/ext/extzstd_buffered.c +0 -265
  138. data/ext/zstd_amalgam.c +0 -18
@@ -1,34 +1,13 @@
1
1
  /*
2
- zstd_v06 - decoder for 0.6 format
3
- Header File
4
- Copyright (C) 2014-2016, Yann Collet.
5
-
6
- BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
7
-
8
- Redistribution and use in source and binary forms, with or without
9
- modification, are permitted provided that the following conditions are
10
- met:
11
- * Redistributions of source code must retain the above copyright
12
- notice, this list of conditions and the following disclaimer.
13
- * Redistributions in binary form must reproduce the above
14
- copyright notice, this list of conditions and the following disclaimer
15
- in the documentation and/or other materials provided with the
16
- distribution.
17
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18
- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21
- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24
- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25
- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
-
29
- You can contact the author at :
30
- - zstd source repository : https://github.com/Cyan4973/zstd
31
- */
2
+ * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
3
+ * All rights reserved.
4
+ *
5
+ * This source code is licensed under both the BSD-style license (found in the
6
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7
+ * in the COPYING file in the root directory of this source tree).
8
+ * You may select, at your option, one of the above-listed licenses.
9
+ */
10
+
32
11
  #ifndef ZSTDv06_H
33
12
  #define ZSTDv06_H
34
13
 
@@ -36,23 +15,19 @@
36
15
  extern "C" {
37
16
  #endif
38
17
 
39
- /*-*************************************
40
- * Dependencies
41
- ***************************************/
18
+ /*====== Dependency ======*/
42
19
  #include <stddef.h> /* size_t */
43
20
 
44
21
 
45
- /*-***************************************************************
46
- * Export parameters
47
- *****************************************************************/
22
+ /*====== Export for Windows ======*/
48
23
  /*!
49
24
  * ZSTDv06_DLL_EXPORT :
50
25
  * Enable exporting of functions when building a Windows DLL
51
26
  */
52
27
  #if defined(_WIN32) && defined(ZSTDv06_DLL_EXPORT) && (ZSTDv06_DLL_EXPORT==1)
53
- # define ZSTDLIB_API __declspec(dllexport)
28
+ # define ZSTDLIBv06_API __declspec(dllexport)
54
29
  #else
55
- # define ZSTDLIB_API
30
+ # define ZSTDLIBv06_API
56
31
  #endif
57
32
 
58
33
 
@@ -64,18 +39,30 @@ extern "C" {
64
39
  `dstCapacity` must be large enough, equal or larger than originalSize.
65
40
  @return : the number of bytes decompressed into `dst` (<= `dstCapacity`),
66
41
  or an errorCode if it fails (which can be tested using ZSTDv06_isError()) */
67
- ZSTDLIB_API size_t ZSTDv06_decompress( void* dst, size_t dstCapacity,
68
- const void* src, size_t compressedSize);
69
-
42
+ ZSTDLIBv06_API size_t ZSTDv06_decompress( void* dst, size_t dstCapacity,
43
+ const void* src, size_t compressedSize);
44
+
45
+ /**
46
+ ZSTDv06_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.6.x format
47
+ srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'
48
+ cSize (output parameter) : the number of bytes that would be read to decompress this frame
49
+ or an error code if it fails (which can be tested using ZSTDv01_isError())
50
+ dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame
51
+ or ZSTD_CONTENTSIZE_ERROR if an error occurs
52
+
53
+ note : assumes `cSize` and `dBound` are _not_ NULL.
54
+ */
55
+ void ZSTDv06_findFrameSizeInfoLegacy(const void *src, size_t srcSize,
56
+ size_t* cSize, unsigned long long* dBound);
70
57
 
71
58
  /* *************************************
72
59
  * Helper functions
73
60
  ***************************************/
74
- ZSTDLIB_API size_t ZSTDv06_compressBound(size_t srcSize); /*!< maximum compressed size (worst case scenario) */
61
+ ZSTDLIBv06_API size_t ZSTDv06_compressBound(size_t srcSize); /*!< maximum compressed size (worst case scenario) */
75
62
 
76
63
  /* Error Management */
77
- ZSTDLIB_API unsigned ZSTDv06_isError(size_t code); /*!< tells if a `size_t` function result is an error code */
78
- ZSTDLIB_API const char* ZSTDv06_getErrorName(size_t code); /*!< provides readable string for an error code */
64
+ ZSTDLIBv06_API unsigned ZSTDv06_isError(size_t code); /*!< tells if a `size_t` function result is an error code */
65
+ ZSTDLIBv06_API const char* ZSTDv06_getErrorName(size_t code); /*!< provides readable string for an error code */
79
66
 
80
67
 
81
68
  /* *************************************
@@ -83,12 +70,12 @@ ZSTDLIB_API const char* ZSTDv06_getErrorName(size_t code); /*!< provides rea
83
70
  ***************************************/
84
71
  /** Decompression context */
85
72
  typedef struct ZSTDv06_DCtx_s ZSTDv06_DCtx;
86
- ZSTDLIB_API ZSTDv06_DCtx* ZSTDv06_createDCtx(void);
87
- ZSTDLIB_API size_t ZSTDv06_freeDCtx(ZSTDv06_DCtx* dctx); /*!< @return : errorCode */
73
+ ZSTDLIBv06_API ZSTDv06_DCtx* ZSTDv06_createDCtx(void);
74
+ ZSTDLIBv06_API size_t ZSTDv06_freeDCtx(ZSTDv06_DCtx* dctx); /*!< @return : errorCode */
88
75
 
89
76
  /** ZSTDv06_decompressDCtx() :
90
77
  * Same as ZSTDv06_decompress(), but requires an already allocated ZSTDv06_DCtx (see ZSTDv06_createDCtx()) */
91
- ZSTDLIB_API size_t ZSTDv06_decompressDCtx(ZSTDv06_DCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
78
+ ZSTDLIBv06_API size_t ZSTDv06_decompressDCtx(ZSTDv06_DCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
92
79
 
93
80
 
94
81
  /*-***********************
@@ -98,10 +85,10 @@ ZSTDLIB_API size_t ZSTDv06_decompressDCtx(ZSTDv06_DCtx* ctx, void* dst, size_t d
98
85
  * Decompression using a pre-defined Dictionary content (see dictBuilder).
99
86
  * Dictionary must be identical to the one used during compression, otherwise regenerated data will be corrupted.
100
87
  * Note : dict can be NULL, in which case, it's equivalent to ZSTDv06_decompressDCtx() */
101
- ZSTDLIB_API size_t ZSTDv06_decompress_usingDict(ZSTDv06_DCtx* dctx,
102
- void* dst, size_t dstCapacity,
103
- const void* src, size_t srcSize,
104
- const void* dict,size_t dictSize);
88
+ ZSTDLIBv06_API size_t ZSTDv06_decompress_usingDict(ZSTDv06_DCtx* dctx,
89
+ void* dst, size_t dstCapacity,
90
+ const void* src, size_t srcSize,
91
+ const void* dict,size_t dictSize);
105
92
 
106
93
 
107
94
  /*-************************
@@ -110,12 +97,12 @@ ZSTDLIB_API size_t ZSTDv06_decompress_usingDict(ZSTDv06_DCtx* dctx,
110
97
  struct ZSTDv06_frameParams_s { unsigned long long frameContentSize; unsigned windowLog; };
111
98
  typedef struct ZSTDv06_frameParams_s ZSTDv06_frameParams;
112
99
 
113
- ZSTDLIB_API size_t ZSTDv06_getFrameParams(ZSTDv06_frameParams* fparamsPtr, const void* src, size_t srcSize); /**< doesn't consume input */
114
- ZSTDLIB_API size_t ZSTDv06_decompressBegin_usingDict(ZSTDv06_DCtx* dctx, const void* dict, size_t dictSize);
115
- ZSTDLIB_API void ZSTDv06_copyDCtx(ZSTDv06_DCtx* dctx, const ZSTDv06_DCtx* preparedDCtx);
100
+ ZSTDLIBv06_API size_t ZSTDv06_getFrameParams(ZSTDv06_frameParams* fparamsPtr, const void* src, size_t srcSize); /**< doesn't consume input */
101
+ ZSTDLIBv06_API size_t ZSTDv06_decompressBegin_usingDict(ZSTDv06_DCtx* dctx, const void* dict, size_t dictSize);
102
+ ZSTDLIBv06_API void ZSTDv06_copyDCtx(ZSTDv06_DCtx* dctx, const ZSTDv06_DCtx* preparedDCtx);
116
103
 
117
- ZSTDLIB_API size_t ZSTDv06_nextSrcSizeToDecompress(ZSTDv06_DCtx* dctx);
118
- ZSTDLIB_API size_t ZSTDv06_decompressContinue(ZSTDv06_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
104
+ ZSTDLIBv06_API size_t ZSTDv06_nextSrcSizeToDecompress(ZSTDv06_DCtx* dctx);
105
+ ZSTDLIBv06_API size_t ZSTDv06_decompressContinue(ZSTDv06_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
119
106
 
120
107
 
121
108
 
@@ -124,15 +111,15 @@ ZSTDLIB_API size_t ZSTDv06_decompressContinue(ZSTDv06_DCtx* dctx, void* dst, siz
124
111
  ***************************************/
125
112
 
126
113
  typedef struct ZBUFFv06_DCtx_s ZBUFFv06_DCtx;
127
- ZSTDLIB_API ZBUFFv06_DCtx* ZBUFFv06_createDCtx(void);
128
- ZSTDLIB_API size_t ZBUFFv06_freeDCtx(ZBUFFv06_DCtx* dctx);
114
+ ZSTDLIBv06_API ZBUFFv06_DCtx* ZBUFFv06_createDCtx(void);
115
+ ZSTDLIBv06_API size_t ZBUFFv06_freeDCtx(ZBUFFv06_DCtx* dctx);
129
116
 
130
- ZSTDLIB_API size_t ZBUFFv06_decompressInit(ZBUFFv06_DCtx* dctx);
131
- ZSTDLIB_API size_t ZBUFFv06_decompressInitDictionary(ZBUFFv06_DCtx* dctx, const void* dict, size_t dictSize);
117
+ ZSTDLIBv06_API size_t ZBUFFv06_decompressInit(ZBUFFv06_DCtx* dctx);
118
+ ZSTDLIBv06_API size_t ZBUFFv06_decompressInitDictionary(ZBUFFv06_DCtx* dctx, const void* dict, size_t dictSize);
132
119
 
133
- ZSTDLIB_API size_t ZBUFFv06_decompressContinue(ZBUFFv06_DCtx* dctx,
134
- void* dst, size_t* dstCapacityPtr,
135
- const void* src, size_t* srcSizePtr);
120
+ ZSTDLIBv06_API size_t ZBUFFv06_decompressContinue(ZBUFFv06_DCtx* dctx,
121
+ void* dst, size_t* dstCapacityPtr,
122
+ const void* src, size_t* srcSizePtr);
136
123
 
137
124
  /*-***************************************************************************
138
125
  * Streaming decompression howto
@@ -162,13 +149,13 @@ ZSTDLIB_API size_t ZBUFFv06_decompressContinue(ZBUFFv06_DCtx* dctx,
162
149
  /* *************************************
163
150
  * Tool functions
164
151
  ***************************************/
165
- ZSTDLIB_API unsigned ZBUFFv06_isError(size_t errorCode);
166
- ZSTDLIB_API const char* ZBUFFv06_getErrorName(size_t errorCode);
152
+ ZSTDLIBv06_API unsigned ZBUFFv06_isError(size_t errorCode);
153
+ ZSTDLIBv06_API const char* ZBUFFv06_getErrorName(size_t errorCode);
167
154
 
168
155
  /** Functions below provide recommended buffer sizes for Compression or Decompression operations.
169
156
  * These sizes are just hints, they tend to offer better latency */
170
- ZSTDLIB_API size_t ZBUFFv06_recommendedDInSize(void);
171
- ZSTDLIB_API size_t ZBUFFv06_recommendedDOutSize(void);
157
+ ZSTDLIBv06_API size_t ZBUFFv06_recommendedDInSize(void);
158
+ ZSTDLIBv06_API size_t ZBUFFv06_recommendedDOutSize(void);
172
159
 
173
160
 
174
161
  /*-*************************************
@@ -0,0 +1,4541 @@
1
+ /*
2
+ * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
3
+ * All rights reserved.
4
+ *
5
+ * This source code is licensed under both the BSD-style license (found in the
6
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7
+ * in the COPYING file in the root directory of this source tree).
8
+ * You may select, at your option, one of the above-listed licenses.
9
+ */
10
+
11
+
12
+ /*- Dependencies -*/
13
+ #include <stddef.h> /* size_t, ptrdiff_t */
14
+ #include <string.h> /* memcpy */
15
+ #include <stdlib.h> /* malloc, free, qsort */
16
+
17
+ #ifndef XXH_STATIC_LINKING_ONLY
18
+ # define XXH_STATIC_LINKING_ONLY /* XXH64_state_t */
19
+ #endif
20
+ #include "../common/xxhash.h" /* XXH64_* */
21
+ #include "zstd_v07.h"
22
+
23
+ #define FSEv07_STATIC_LINKING_ONLY /* FSEv07_MIN_TABLELOG */
24
+ #define HUFv07_STATIC_LINKING_ONLY /* HUFv07_TABLELOG_ABSOLUTEMAX */
25
+ #define ZSTDv07_STATIC_LINKING_ONLY
26
+
27
+ #include "../common/error_private.h"
28
+
29
+
30
+ #ifdef ZSTDv07_STATIC_LINKING_ONLY
31
+
32
+ /* ====================================================================================
33
+ * The definitions in this section are considered experimental.
34
+ * They should never be used with a dynamic library, as they may change in the future.
35
+ * They are provided for advanced usages.
36
+ * Use them only in association with static linking.
37
+ * ==================================================================================== */
38
+
39
+ /*--- Constants ---*/
40
+ #define ZSTDv07_MAGIC_SKIPPABLE_START 0x184D2A50U
41
+
42
+ #define ZSTDv07_WINDOWLOG_MAX_32 25
43
+ #define ZSTDv07_WINDOWLOG_MAX_64 27
44
+ #define ZSTDv07_WINDOWLOG_MAX ((U32)(MEM_32bits() ? ZSTDv07_WINDOWLOG_MAX_32 : ZSTDv07_WINDOWLOG_MAX_64))
45
+ #define ZSTDv07_WINDOWLOG_MIN 18
46
+ #define ZSTDv07_CHAINLOG_MAX (ZSTDv07_WINDOWLOG_MAX+1)
47
+ #define ZSTDv07_CHAINLOG_MIN 4
48
+ #define ZSTDv07_HASHLOG_MAX ZSTDv07_WINDOWLOG_MAX
49
+ #define ZSTDv07_HASHLOG_MIN 12
50
+ #define ZSTDv07_HASHLOG3_MAX 17
51
+ #define ZSTDv07_SEARCHLOG_MAX (ZSTDv07_WINDOWLOG_MAX-1)
52
+ #define ZSTDv07_SEARCHLOG_MIN 1
53
+ #define ZSTDv07_SEARCHLENGTH_MAX 7
54
+ #define ZSTDv07_SEARCHLENGTH_MIN 3
55
+ #define ZSTDv07_TARGETLENGTH_MIN 4
56
+ #define ZSTDv07_TARGETLENGTH_MAX 999
57
+
58
+ #define ZSTDv07_FRAMEHEADERSIZE_MAX 18 /* for static allocation */
59
+ static const size_t ZSTDv07_frameHeaderSize_min = 5;
60
+ static const size_t ZSTDv07_frameHeaderSize_max = ZSTDv07_FRAMEHEADERSIZE_MAX;
61
+ static const size_t ZSTDv07_skippableHeaderSize = 8; /* magic number + skippable frame length */
62
+
63
+
64
+ /* custom memory allocation functions */
65
+ typedef void* (*ZSTDv07_allocFunction) (void* opaque, size_t size);
66
+ typedef void (*ZSTDv07_freeFunction) (void* opaque, void* address);
67
+ typedef struct { ZSTDv07_allocFunction customAlloc; ZSTDv07_freeFunction customFree; void* opaque; } ZSTDv07_customMem;
68
+
69
+
70
+ /*--- Advanced Decompression functions ---*/
71
+
72
+ /*! ZSTDv07_estimateDCtxSize() :
73
+ * Gives the potential amount of memory allocated to create a ZSTDv07_DCtx */
74
+ ZSTDLIBv07_API size_t ZSTDv07_estimateDCtxSize(void);
75
+
76
+ /*! ZSTDv07_createDCtx_advanced() :
77
+ * Create a ZSTD decompression context using external alloc and free functions */
78
+ ZSTDLIBv07_API ZSTDv07_DCtx* ZSTDv07_createDCtx_advanced(ZSTDv07_customMem customMem);
79
+
80
+ /*! ZSTDv07_sizeofDCtx() :
81
+ * Gives the amount of memory used by a given ZSTDv07_DCtx */
82
+ ZSTDLIBv07_API size_t ZSTDv07_sizeofDCtx(const ZSTDv07_DCtx* dctx);
83
+
84
+
85
+ /* ******************************************************************
86
+ * Buffer-less streaming functions (synchronous mode)
87
+ ********************************************************************/
88
+
89
+ ZSTDLIBv07_API size_t ZSTDv07_decompressBegin(ZSTDv07_DCtx* dctx);
90
+ ZSTDLIBv07_API size_t ZSTDv07_decompressBegin_usingDict(ZSTDv07_DCtx* dctx, const void* dict, size_t dictSize);
91
+ ZSTDLIBv07_API void ZSTDv07_copyDCtx(ZSTDv07_DCtx* dctx, const ZSTDv07_DCtx* preparedDCtx);
92
+
93
+ ZSTDLIBv07_API size_t ZSTDv07_nextSrcSizeToDecompress(ZSTDv07_DCtx* dctx);
94
+ ZSTDLIBv07_API size_t ZSTDv07_decompressContinue(ZSTDv07_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
95
+
96
+ /*
97
+ Buffer-less streaming decompression (synchronous mode)
98
+
99
+ A ZSTDv07_DCtx object is required to track streaming operations.
100
+ Use ZSTDv07_createDCtx() / ZSTDv07_freeDCtx() to manage it.
101
+ A ZSTDv07_DCtx object can be re-used multiple times.
102
+
103
+ First optional operation is to retrieve frame parameters, using ZSTDv07_getFrameParams(), which doesn't consume the input.
104
+ It can provide the minimum size of rolling buffer required to properly decompress data (`windowSize`),
105
+ and optionally the final size of uncompressed content.
106
+ (Note : content size is an optional info that may not be present. 0 means : content size unknown)
107
+ Frame parameters are extracted from the beginning of compressed frame.
108
+ The amount of data to read is variable, from ZSTDv07_frameHeaderSize_min to ZSTDv07_frameHeaderSize_max (so if `srcSize` >= ZSTDv07_frameHeaderSize_max, it will always work)
109
+ If `srcSize` is too small for operation to succeed, function will return the minimum size it requires to produce a result.
110
+ Result : 0 when successful, it means the ZSTDv07_frameParams structure has been filled.
111
+ >0 : means there is not enough data into `src`. Provides the expected size to successfully decode header.
112
+ errorCode, which can be tested using ZSTDv07_isError()
113
+
114
+ Start decompression, with ZSTDv07_decompressBegin() or ZSTDv07_decompressBegin_usingDict().
115
+ Alternatively, you can copy a prepared context, using ZSTDv07_copyDCtx().
116
+
117
+ Then use ZSTDv07_nextSrcSizeToDecompress() and ZSTDv07_decompressContinue() alternatively.
118
+ ZSTDv07_nextSrcSizeToDecompress() tells how much bytes to provide as 'srcSize' to ZSTDv07_decompressContinue().
119
+ ZSTDv07_decompressContinue() requires this exact amount of bytes, or it will fail.
120
+
121
+ @result of ZSTDv07_decompressContinue() is the number of bytes regenerated within 'dst' (necessarily <= dstCapacity).
122
+ It can be zero, which is not an error; it just means ZSTDv07_decompressContinue() has decoded some header.
123
+
124
+ ZSTDv07_decompressContinue() needs previous data blocks during decompression, up to `windowSize`.
125
+ They should preferably be located contiguously, prior to current block.
126
+ Alternatively, a round buffer of sufficient size is also possible. Sufficient size is determined by frame parameters.
127
+ ZSTDv07_decompressContinue() is very sensitive to contiguity,
128
+ if 2 blocks don't follow each other, make sure that either the compressor breaks contiguity at the same place,
129
+ or that previous contiguous segment is large enough to properly handle maximum back-reference.
130
+
131
+ A frame is fully decoded when ZSTDv07_nextSrcSizeToDecompress() returns zero.
132
+ Context can then be reset to start a new decompression.
133
+
134
+
135
+ == Special case : skippable frames ==
136
+
137
+ Skippable frames allow the integration of user-defined data into a flow of concatenated frames.
138
+ Skippable frames will be ignored (skipped) by a decompressor. The format of skippable frame is following:
139
+ a) Skippable frame ID - 4 Bytes, Little endian format, any value from 0x184D2A50 to 0x184D2A5F
140
+ b) Frame Size - 4 Bytes, Little endian format, unsigned 32-bits
141
+ c) Frame Content - any content (User Data) of length equal to Frame Size
142
+ For skippable frames ZSTDv07_decompressContinue() always returns 0.
143
+ For skippable frames ZSTDv07_getFrameParams() returns fparamsPtr->windowLog==0 what means that a frame is skippable.
144
+ It also returns Frame Size as fparamsPtr->frameContentSize.
145
+ */
146
+
147
+
148
+ /* **************************************
149
+ * Block functions
150
+ ****************************************/
151
+ /*! Block functions produce and decode raw zstd blocks, without frame metadata.
152
+ Frame metadata cost is typically ~18 bytes, which can be non-negligible for very small blocks (< 100 bytes).
153
+ User will have to take in charge required information to regenerate data, such as compressed and content sizes.
154
+
155
+ A few rules to respect :
156
+ - Compressing and decompressing require a context structure
157
+ + Use ZSTDv07_createCCtx() and ZSTDv07_createDCtx()
158
+ - It is necessary to init context before starting
159
+ + compression : ZSTDv07_compressBegin()
160
+ + decompression : ZSTDv07_decompressBegin()
161
+ + variants _usingDict() are also allowed
162
+ + copyCCtx() and copyDCtx() work too
163
+ - Block size is limited, it must be <= ZSTDv07_getBlockSizeMax()
164
+ + If you need to compress more, cut data into multiple blocks
165
+ + Consider using the regular ZSTDv07_compress() instead, as frame metadata costs become negligible when source size is large.
166
+ - When a block is considered not compressible enough, ZSTDv07_compressBlock() result will be zero.
167
+ In which case, nothing is produced into `dst`.
168
+ + User must test for such outcome and deal directly with uncompressed data
169
+ + ZSTDv07_decompressBlock() doesn't accept uncompressed data as input !!!
170
+ + In case of multiple successive blocks, decoder must be informed of uncompressed block existence to follow proper history.
171
+ Use ZSTDv07_insertBlock() in such a case.
172
+ */
173
+
174
+ #define ZSTDv07_BLOCKSIZE_ABSOLUTEMAX (128 * 1024) /* define, for static allocation */
175
+ ZSTDLIBv07_API size_t ZSTDv07_decompressBlock(ZSTDv07_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
176
+ ZSTDLIBv07_API size_t ZSTDv07_insertBlock(ZSTDv07_DCtx* dctx, const void* blockStart, size_t blockSize); /**< insert block into `dctx` history. Useful for uncompressed blocks */
177
+
178
+
179
+ #endif /* ZSTDv07_STATIC_LINKING_ONLY */
180
+
181
+
182
+ /* ******************************************************************
183
+ mem.h
184
+ low-level memory access routines
185
+ Copyright (C) 2013-2015, Yann Collet.
186
+
187
+ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
188
+
189
+ Redistribution and use in source and binary forms, with or without
190
+ modification, are permitted provided that the following conditions are
191
+ met:
192
+
193
+ * Redistributions of source code must retain the above copyright
194
+ notice, this list of conditions and the following disclaimer.
195
+ * Redistributions in binary form must reproduce the above
196
+ copyright notice, this list of conditions and the following disclaimer
197
+ in the documentation and/or other materials provided with the
198
+ distribution.
199
+
200
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
201
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
202
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
203
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
204
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
205
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
206
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
207
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
208
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
209
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
210
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
211
+
212
+ You can contact the author at :
213
+ - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy
214
+ - Public forum : https://groups.google.com/forum/#!forum/lz4c
215
+ ****************************************************************** */
216
+ #ifndef MEM_H_MODULE
217
+ #define MEM_H_MODULE
218
+
219
+ #if defined (__cplusplus)
220
+ extern "C" {
221
+ #endif
222
+
223
+ /*-****************************************
224
+ * Compiler specifics
225
+ ******************************************/
226
+ #if defined(_MSC_VER) /* Visual Studio */
227
+ # include <stdlib.h> /* _byteswap_ulong */
228
+ # include <intrin.h> /* _byteswap_* */
229
+ #endif
230
+ #if defined(__GNUC__)
231
+ # define MEM_STATIC static __attribute__((unused))
232
+ #elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
233
+ # define MEM_STATIC static inline
234
+ #elif defined(_MSC_VER)
235
+ # define MEM_STATIC static __inline
236
+ #else
237
+ # define MEM_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */
238
+ #endif
239
+
240
+
241
+ /*-**************************************************************
242
+ * Basic Types
243
+ *****************************************************************/
244
+ #if !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )
245
+ # include <stdint.h>
246
+ typedef uint8_t BYTE;
247
+ typedef uint16_t U16;
248
+ typedef int16_t S16;
249
+ typedef uint32_t U32;
250
+ typedef int32_t S32;
251
+ typedef uint64_t U64;
252
+ typedef int64_t S64;
253
+ #else
254
+ typedef unsigned char BYTE;
255
+ typedef unsigned short U16;
256
+ typedef signed short S16;
257
+ typedef unsigned int U32;
258
+ typedef signed int S32;
259
+ typedef unsigned long long U64;
260
+ typedef signed long long S64;
261
+ #endif
262
+
263
+
264
+ /*-**************************************************************
265
+ * Memory I/O
266
+ *****************************************************************/
267
+ /* MEM_FORCE_MEMORY_ACCESS :
268
+ * By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable.
269
+ * Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal.
270
+ * The below switch allow to select different access method for improved performance.
271
+ * Method 0 (default) : use `memcpy()`. Safe and portable.
272
+ * Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable).
273
+ * This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`.
274
+ * Method 2 : direct access. This method is portable but violate C standard.
275
+ * It can generate buggy code on targets depending on alignment.
276
+ * In some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6)
277
+ * See http://fastcompression.blogspot.fr/2015/08/accessing-unaligned-memory.html for details.
278
+ * Prefer these methods in priority order (0 > 1 > 2)
279
+ */
280
+ #ifndef MEM_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */
281
+ # if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) )
282
+ # define MEM_FORCE_MEMORY_ACCESS 2
283
+ # elif (defined(__INTEL_COMPILER) && !defined(WIN32)) || \
284
+ (defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) ))
285
+ # define MEM_FORCE_MEMORY_ACCESS 1
286
+ # endif
287
+ #endif
288
+
289
+ MEM_STATIC unsigned MEM_32bits(void) { return sizeof(size_t)==4; }
290
+ MEM_STATIC unsigned MEM_64bits(void) { return sizeof(size_t)==8; }
291
+
292
+ MEM_STATIC unsigned MEM_isLittleEndian(void)
293
+ {
294
+ const union { U32 u; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */
295
+ return one.c[0];
296
+ }
297
+
298
+ #if defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==2)
299
+
300
+ /* violates C standard, by lying on structure alignment.
301
+ Only use if no other choice to achieve best performance on target platform */
302
+ MEM_STATIC U16 MEM_read16(const void* memPtr) { return *(const U16*) memPtr; }
303
+ MEM_STATIC U32 MEM_read32(const void* memPtr) { return *(const U32*) memPtr; }
304
+ MEM_STATIC U64 MEM_read64(const void* memPtr) { return *(const U64*) memPtr; }
305
+
306
+ MEM_STATIC void MEM_write16(void* memPtr, U16 value) { *(U16*)memPtr = value; }
307
+
308
+ #elif defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==1)
309
+
310
+ /* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */
311
+ /* currently only defined for gcc and icc */
312
+ typedef union { U16 u16; U32 u32; U64 u64; size_t st; } __attribute__((packed)) unalign;
313
+
314
+ MEM_STATIC U16 MEM_read16(const void* ptr) { return ((const unalign*)ptr)->u16; }
315
+ MEM_STATIC U32 MEM_read32(const void* ptr) { return ((const unalign*)ptr)->u32; }
316
+ MEM_STATIC U64 MEM_read64(const void* ptr) { return ((const unalign*)ptr)->u64; }
317
+
318
+ MEM_STATIC void MEM_write16(void* memPtr, U16 value) { ((unalign*)memPtr)->u16 = value; }
319
+
320
+ #else
321
+
322
+ /* default method, safe and standard.
323
+ can sometimes prove slower */
324
+
325
+ MEM_STATIC U16 MEM_read16(const void* memPtr)
326
+ {
327
+ U16 val; memcpy(&val, memPtr, sizeof(val)); return val;
328
+ }
329
+
330
+ MEM_STATIC U32 MEM_read32(const void* memPtr)
331
+ {
332
+ U32 val; memcpy(&val, memPtr, sizeof(val)); return val;
333
+ }
334
+
335
+ MEM_STATIC U64 MEM_read64(const void* memPtr)
336
+ {
337
+ U64 val; memcpy(&val, memPtr, sizeof(val)); return val;
338
+ }
339
+
340
+ MEM_STATIC void MEM_write16(void* memPtr, U16 value)
341
+ {
342
+ memcpy(memPtr, &value, sizeof(value));
343
+ }
344
+
345
+ #endif /* MEM_FORCE_MEMORY_ACCESS */
346
+
347
+ MEM_STATIC U32 MEM_swap32(U32 in)
348
+ {
349
+ #if defined(_MSC_VER) /* Visual Studio */
350
+ return _byteswap_ulong(in);
351
+ #elif defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)
352
+ return __builtin_bswap32(in);
353
+ #else
354
+ return ((in << 24) & 0xff000000 ) |
355
+ ((in << 8) & 0x00ff0000 ) |
356
+ ((in >> 8) & 0x0000ff00 ) |
357
+ ((in >> 24) & 0x000000ff );
358
+ #endif
359
+ }
360
+
361
+ MEM_STATIC U64 MEM_swap64(U64 in)
362
+ {
363
+ #if defined(_MSC_VER) /* Visual Studio */
364
+ return _byteswap_uint64(in);
365
+ #elif defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)
366
+ return __builtin_bswap64(in);
367
+ #else
368
+ return ((in << 56) & 0xff00000000000000ULL) |
369
+ ((in << 40) & 0x00ff000000000000ULL) |
370
+ ((in << 24) & 0x0000ff0000000000ULL) |
371
+ ((in << 8) & 0x000000ff00000000ULL) |
372
+ ((in >> 8) & 0x00000000ff000000ULL) |
373
+ ((in >> 24) & 0x0000000000ff0000ULL) |
374
+ ((in >> 40) & 0x000000000000ff00ULL) |
375
+ ((in >> 56) & 0x00000000000000ffULL);
376
+ #endif
377
+ }
378
+
379
+
380
+ /*=== Little endian r/w ===*/
381
+
382
+ MEM_STATIC U16 MEM_readLE16(const void* memPtr)
383
+ {
384
+ if (MEM_isLittleEndian())
385
+ return MEM_read16(memPtr);
386
+ else {
387
+ const BYTE* p = (const BYTE*)memPtr;
388
+ return (U16)(p[0] + (p[1]<<8));
389
+ }
390
+ }
391
+
392
+ MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val)
393
+ {
394
+ if (MEM_isLittleEndian()) {
395
+ MEM_write16(memPtr, val);
396
+ } else {
397
+ BYTE* p = (BYTE*)memPtr;
398
+ p[0] = (BYTE)val;
399
+ p[1] = (BYTE)(val>>8);
400
+ }
401
+ }
402
+
403
+ MEM_STATIC U32 MEM_readLE32(const void* memPtr)
404
+ {
405
+ if (MEM_isLittleEndian())
406
+ return MEM_read32(memPtr);
407
+ else
408
+ return MEM_swap32(MEM_read32(memPtr));
409
+ }
410
+
411
+
412
+ MEM_STATIC U64 MEM_readLE64(const void* memPtr)
413
+ {
414
+ if (MEM_isLittleEndian())
415
+ return MEM_read64(memPtr);
416
+ else
417
+ return MEM_swap64(MEM_read64(memPtr));
418
+ }
419
+
420
+ MEM_STATIC size_t MEM_readLEST(const void* memPtr)
421
+ {
422
+ if (MEM_32bits())
423
+ return (size_t)MEM_readLE32(memPtr);
424
+ else
425
+ return (size_t)MEM_readLE64(memPtr);
426
+ }
427
+
428
+
429
+
430
+ #if defined (__cplusplus)
431
+ }
432
+ #endif
433
+
434
+ #endif /* MEM_H_MODULE */
435
+ /* ******************************************************************
436
+ bitstream
437
+ Part of FSE library
438
+ header file (to include)
439
+ Copyright (C) 2013-2016, Yann Collet.
440
+
441
+ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
442
+
443
+ Redistribution and use in source and binary forms, with or without
444
+ modification, are permitted provided that the following conditions are
445
+ met:
446
+
447
+ * Redistributions of source code must retain the above copyright
448
+ notice, this list of conditions and the following disclaimer.
449
+ * Redistributions in binary form must reproduce the above
450
+ copyright notice, this list of conditions and the following disclaimer
451
+ in the documentation and/or other materials provided with the
452
+ distribution.
453
+
454
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
455
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
456
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
457
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
458
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
459
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
460
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
461
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
462
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
463
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
464
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
465
+
466
+ You can contact the author at :
467
+ - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
468
+ ****************************************************************** */
469
+ #ifndef BITSTREAM_H_MODULE
470
+ #define BITSTREAM_H_MODULE
471
+
472
+ #if defined (__cplusplus)
473
+ extern "C" {
474
+ #endif
475
+
476
+
477
+ /*
478
+ * This API consists of small unitary functions, which must be inlined for best performance.
479
+ * Since link-time-optimization is not available for all compilers,
480
+ * these functions are defined into a .h to be included.
481
+ */
482
+
483
+
484
+ /*=========================================
485
+ * Target specific
486
+ =========================================*/
487
+ #if defined(__BMI__) && defined(__GNUC__)
488
+ # include <immintrin.h> /* support for bextr (experimental) */
489
+ #endif
490
+
491
+ /*-********************************************
492
+ * bitStream decoding API (read backward)
493
+ **********************************************/
494
+ typedef struct
495
+ {
496
+ size_t bitContainer;
497
+ unsigned bitsConsumed;
498
+ const char* ptr;
499
+ const char* start;
500
+ } BITv07_DStream_t;
501
+
502
+ typedef enum { BITv07_DStream_unfinished = 0,
503
+ BITv07_DStream_endOfBuffer = 1,
504
+ BITv07_DStream_completed = 2,
505
+ BITv07_DStream_overflow = 3 } BITv07_DStream_status; /* result of BITv07_reloadDStream() */
506
+ /* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */
507
+
508
+ MEM_STATIC size_t BITv07_initDStream(BITv07_DStream_t* bitD, const void* srcBuffer, size_t srcSize);
509
+ MEM_STATIC size_t BITv07_readBits(BITv07_DStream_t* bitD, unsigned nbBits);
510
+ MEM_STATIC BITv07_DStream_status BITv07_reloadDStream(BITv07_DStream_t* bitD);
511
+ MEM_STATIC unsigned BITv07_endOfDStream(const BITv07_DStream_t* bitD);
512
+
513
+
514
+
515
+ /*-****************************************
516
+ * unsafe API
517
+ ******************************************/
518
+ MEM_STATIC size_t BITv07_readBitsFast(BITv07_DStream_t* bitD, unsigned nbBits);
519
+ /* faster, but works only if nbBits >= 1 */
520
+
521
+
522
+
523
+ /*-**************************************************************
524
+ * Internal functions
525
+ ****************************************************************/
526
+ MEM_STATIC unsigned BITv07_highbit32 (U32 val)
527
+ {
528
+ # if defined(_MSC_VER) /* Visual */
529
+ unsigned long r=0;
530
+ _BitScanReverse ( &r, val );
531
+ return (unsigned) r;
532
+ # elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */
533
+ return __builtin_clz (val) ^ 31;
534
+ # else /* Software version */
535
+ static const unsigned DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 };
536
+ U32 v = val;
537
+ v |= v >> 1;
538
+ v |= v >> 2;
539
+ v |= v >> 4;
540
+ v |= v >> 8;
541
+ v |= v >> 16;
542
+ return DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27];
543
+ # endif
544
+ }
545
+
546
+
547
+
548
+ /*-********************************************************
549
+ * bitStream decoding
550
+ **********************************************************/
551
+ /*! BITv07_initDStream() :
552
+ * Initialize a BITv07_DStream_t.
553
+ * `bitD` : a pointer to an already allocated BITv07_DStream_t structure.
554
+ * `srcSize` must be the *exact* size of the bitStream, in bytes.
555
+ * @return : size of stream (== srcSize) or an errorCode if a problem is detected
556
+ */
557
+ MEM_STATIC size_t BITv07_initDStream(BITv07_DStream_t* bitD, const void* srcBuffer, size_t srcSize)
558
+ {
559
+ if (srcSize < 1) { memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); }
560
+
561
+ if (srcSize >= sizeof(bitD->bitContainer)) { /* normal case */
562
+ bitD->start = (const char*)srcBuffer;
563
+ bitD->ptr = (const char*)srcBuffer + srcSize - sizeof(bitD->bitContainer);
564
+ bitD->bitContainer = MEM_readLEST(bitD->ptr);
565
+ { BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];
566
+ bitD->bitsConsumed = lastByte ? 8 - BITv07_highbit32(lastByte) : 0;
567
+ if (lastByte == 0) return ERROR(GENERIC); /* endMark not present */ }
568
+ } else {
569
+ bitD->start = (const char*)srcBuffer;
570
+ bitD->ptr = bitD->start;
571
+ bitD->bitContainer = *(const BYTE*)(bitD->start);
572
+ switch(srcSize)
573
+ {
574
+ case 7: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[6]) << (sizeof(bitD->bitContainer)*8 - 16);/* fall-through */
575
+ case 6: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[5]) << (sizeof(bitD->bitContainer)*8 - 24);/* fall-through */
576
+ case 5: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[4]) << (sizeof(bitD->bitContainer)*8 - 32);/* fall-through */
577
+ case 4: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[3]) << 24; /* fall-through */
578
+ case 3: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[2]) << 16; /* fall-through */
579
+ case 2: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[1]) << 8; /* fall-through */
580
+ default: break;
581
+ }
582
+ { BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];
583
+ bitD->bitsConsumed = lastByte ? 8 - BITv07_highbit32(lastByte) : 0;
584
+ if (lastByte == 0) return ERROR(GENERIC); /* endMark not present */ }
585
+ bitD->bitsConsumed += (U32)(sizeof(bitD->bitContainer) - srcSize)*8;
586
+ }
587
+
588
+ return srcSize;
589
+ }
590
+
591
+
592
+ MEM_STATIC size_t BITv07_lookBits(const BITv07_DStream_t* bitD, U32 nbBits)
593
+ {
594
+ U32 const bitMask = sizeof(bitD->bitContainer)*8 - 1;
595
+ return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask-nbBits) & bitMask);
596
+ }
597
+
598
+ /*! BITv07_lookBitsFast() :
599
+ * unsafe version; only works only if nbBits >= 1 */
600
+ MEM_STATIC size_t BITv07_lookBitsFast(const BITv07_DStream_t* bitD, U32 nbBits)
601
+ {
602
+ U32 const bitMask = sizeof(bitD->bitContainer)*8 - 1;
603
+ return (bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> (((bitMask+1)-nbBits) & bitMask);
604
+ }
605
+
606
+ MEM_STATIC void BITv07_skipBits(BITv07_DStream_t* bitD, U32 nbBits)
607
+ {
608
+ bitD->bitsConsumed += nbBits;
609
+ }
610
+
611
+ MEM_STATIC size_t BITv07_readBits(BITv07_DStream_t* bitD, U32 nbBits)
612
+ {
613
+ size_t const value = BITv07_lookBits(bitD, nbBits);
614
+ BITv07_skipBits(bitD, nbBits);
615
+ return value;
616
+ }
617
+
618
+ /*! BITv07_readBitsFast() :
619
+ * unsafe version; only works only if nbBits >= 1 */
620
+ MEM_STATIC size_t BITv07_readBitsFast(BITv07_DStream_t* bitD, U32 nbBits)
621
+ {
622
+ size_t const value = BITv07_lookBitsFast(bitD, nbBits);
623
+ BITv07_skipBits(bitD, nbBits);
624
+ return value;
625
+ }
626
+
627
+ MEM_STATIC BITv07_DStream_status BITv07_reloadDStream(BITv07_DStream_t* bitD)
628
+ {
629
+ if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8)) /* should not happen => corruption detected */
630
+ return BITv07_DStream_overflow;
631
+
632
+ if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer)) {
633
+ bitD->ptr -= bitD->bitsConsumed >> 3;
634
+ bitD->bitsConsumed &= 7;
635
+ bitD->bitContainer = MEM_readLEST(bitD->ptr);
636
+ return BITv07_DStream_unfinished;
637
+ }
638
+ if (bitD->ptr == bitD->start) {
639
+ if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BITv07_DStream_endOfBuffer;
640
+ return BITv07_DStream_completed;
641
+ }
642
+ { U32 nbBytes = bitD->bitsConsumed >> 3;
643
+ BITv07_DStream_status result = BITv07_DStream_unfinished;
644
+ if (bitD->ptr - nbBytes < bitD->start) {
645
+ nbBytes = (U32)(bitD->ptr - bitD->start); /* ptr > start */
646
+ result = BITv07_DStream_endOfBuffer;
647
+ }
648
+ bitD->ptr -= nbBytes;
649
+ bitD->bitsConsumed -= nbBytes*8;
650
+ bitD->bitContainer = MEM_readLEST(bitD->ptr); /* reminder : srcSize > sizeof(bitD) */
651
+ return result;
652
+ }
653
+ }
654
+
655
+ /*! BITv07_endOfDStream() :
656
+ * @return Tells if DStream has exactly reached its end (all bits consumed).
657
+ */
658
+ MEM_STATIC unsigned BITv07_endOfDStream(const BITv07_DStream_t* DStream)
659
+ {
660
+ return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer)*8));
661
+ }
662
+
663
+ #if defined (__cplusplus)
664
+ }
665
+ #endif
666
+
667
+ #endif /* BITSTREAM_H_MODULE */
668
+ /* ******************************************************************
669
+ FSE : Finite State Entropy codec
670
+ Public Prototypes declaration
671
+ Copyright (C) 2013-2016, Yann Collet.
672
+
673
+ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
674
+
675
+ Redistribution and use in source and binary forms, with or without
676
+ modification, are permitted provided that the following conditions are
677
+ met:
678
+
679
+ * Redistributions of source code must retain the above copyright
680
+ notice, this list of conditions and the following disclaimer.
681
+ * Redistributions in binary form must reproduce the above
682
+ copyright notice, this list of conditions and the following disclaimer
683
+ in the documentation and/or other materials provided with the
684
+ distribution.
685
+
686
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
687
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
688
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
689
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
690
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
691
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
692
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
693
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
694
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
695
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
696
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
697
+
698
+ You can contact the author at :
699
+ - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
700
+ ****************************************************************** */
701
+ #ifndef FSEv07_H
702
+ #define FSEv07_H
703
+
704
+ #if defined (__cplusplus)
705
+ extern "C" {
706
+ #endif
707
+
708
+
709
+
710
+ /*-****************************************
711
+ * FSE simple functions
712
+ ******************************************/
713
+
714
+ /*! FSEv07_decompress():
715
+ Decompress FSE data from buffer 'cSrc', of size 'cSrcSize',
716
+ into already allocated destination buffer 'dst', of size 'dstCapacity'.
717
+ @return : size of regenerated data (<= maxDstSize),
718
+ or an error code, which can be tested using FSEv07_isError() .
719
+
720
+ ** Important ** : FSEv07_decompress() does not decompress non-compressible nor RLE data !!!
721
+ Why ? : making this distinction requires a header.
722
+ Header management is intentionally delegated to the user layer, which can better manage special cases.
723
+ */
724
+ size_t FSEv07_decompress(void* dst, size_t dstCapacity,
725
+ const void* cSrc, size_t cSrcSize);
726
+
727
+
728
+ /* Error Management */
729
+ unsigned FSEv07_isError(size_t code); /* tells if a return value is an error code */
730
+ const char* FSEv07_getErrorName(size_t code); /* provides error code string (useful for debugging) */
731
+
732
+
733
+ /*-*****************************************
734
+ * FSE detailed API
735
+ ******************************************/
736
+ /*!
737
+ FSEv07_decompress() does the following:
738
+ 1. read normalized counters with readNCount()
739
+ 2. build decoding table 'DTable' from normalized counters
740
+ 3. decode the data stream using decoding table 'DTable'
741
+
742
+ The following API allows targeting specific sub-functions for advanced tasks.
743
+ For example, it's possible to compress several blocks using the same 'CTable',
744
+ or to save and provide normalized distribution using external method.
745
+ */
746
+
747
+
748
+ /* *** DECOMPRESSION *** */
749
+
750
+ /*! FSEv07_readNCount():
751
+ Read compactly saved 'normalizedCounter' from 'rBuffer'.
752
+ @return : size read from 'rBuffer',
753
+ or an errorCode, which can be tested using FSEv07_isError().
754
+ maxSymbolValuePtr[0] and tableLogPtr[0] will also be updated with their respective values */
755
+ size_t FSEv07_readNCount (short* normalizedCounter, unsigned* maxSymbolValuePtr, unsigned* tableLogPtr, const void* rBuffer, size_t rBuffSize);
756
+
757
+ /*! Constructor and Destructor of FSEv07_DTable.
758
+ Note that its size depends on 'tableLog' */
759
+ typedef unsigned FSEv07_DTable; /* don't allocate that. It's just a way to be more restrictive than void* */
760
+ FSEv07_DTable* FSEv07_createDTable(unsigned tableLog);
761
+ void FSEv07_freeDTable(FSEv07_DTable* dt);
762
+
763
+ /*! FSEv07_buildDTable():
764
+ Builds 'dt', which must be already allocated, using FSEv07_createDTable().
765
+ return : 0, or an errorCode, which can be tested using FSEv07_isError() */
766
+ size_t FSEv07_buildDTable (FSEv07_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog);
767
+
768
+ /*! FSEv07_decompress_usingDTable():
769
+ Decompress compressed source `cSrc` of size `cSrcSize` using `dt`
770
+ into `dst` which must be already allocated.
771
+ @return : size of regenerated data (necessarily <= `dstCapacity`),
772
+ or an errorCode, which can be tested using FSEv07_isError() */
773
+ size_t FSEv07_decompress_usingDTable(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, const FSEv07_DTable* dt);
774
+
775
+ /*!
776
+ Tutorial :
777
+ ----------
778
+ (Note : these functions only decompress FSE-compressed blocks.
779
+ If block is uncompressed, use memcpy() instead
780
+ If block is a single repeated byte, use memset() instead )
781
+
782
+ The first step is to obtain the normalized frequencies of symbols.
783
+ This can be performed by FSEv07_readNCount() if it was saved using FSEv07_writeNCount().
784
+ 'normalizedCounter' must be already allocated, and have at least 'maxSymbolValuePtr[0]+1' cells of signed short.
785
+ In practice, that means it's necessary to know 'maxSymbolValue' beforehand,
786
+ or size the table to handle worst case situations (typically 256).
787
+ FSEv07_readNCount() will provide 'tableLog' and 'maxSymbolValue'.
788
+ The result of FSEv07_readNCount() is the number of bytes read from 'rBuffer'.
789
+ Note that 'rBufferSize' must be at least 4 bytes, even if useful information is less than that.
790
+ If there is an error, the function will return an error code, which can be tested using FSEv07_isError().
791
+
792
+ The next step is to build the decompression tables 'FSEv07_DTable' from 'normalizedCounter'.
793
+ This is performed by the function FSEv07_buildDTable().
794
+ The space required by 'FSEv07_DTable' must be already allocated using FSEv07_createDTable().
795
+ If there is an error, the function will return an error code, which can be tested using FSEv07_isError().
796
+
797
+ `FSEv07_DTable` can then be used to decompress `cSrc`, with FSEv07_decompress_usingDTable().
798
+ `cSrcSize` must be strictly correct, otherwise decompression will fail.
799
+ FSEv07_decompress_usingDTable() result will tell how many bytes were regenerated (<=`dstCapacity`).
800
+ If there is an error, the function will return an error code, which can be tested using FSEv07_isError(). (ex: dst buffer too small)
801
+ */
802
+
803
+
804
+ #ifdef FSEv07_STATIC_LINKING_ONLY
805
+
806
+
807
+ /* *****************************************
808
+ * Static allocation
809
+ *******************************************/
810
+ /* FSE buffer bounds */
811
+ #define FSEv07_NCOUNTBOUND 512
812
+ #define FSEv07_BLOCKBOUND(size) (size + (size>>7))
813
+
814
+ /* It is possible to statically allocate FSE CTable/DTable as a table of unsigned using below macros */
815
+ #define FSEv07_DTABLE_SIZE_U32(maxTableLog) (1 + (1<<maxTableLog))
816
+
817
+
818
+ /* *****************************************
819
+ * FSE advanced API
820
+ *******************************************/
821
+ size_t FSEv07_countFast(unsigned* count, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize);
822
+ /**< same as FSEv07_count(), but blindly trusts that all byte values within src are <= *maxSymbolValuePtr */
823
+
824
+ unsigned FSEv07_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, unsigned minus);
825
+ /**< same as FSEv07_optimalTableLog(), which used `minus==2` */
826
+
827
+ size_t FSEv07_buildDTable_raw (FSEv07_DTable* dt, unsigned nbBits);
828
+ /**< build a fake FSEv07_DTable, designed to read an uncompressed bitstream where each symbol uses nbBits */
829
+
830
+ size_t FSEv07_buildDTable_rle (FSEv07_DTable* dt, unsigned char symbolValue);
831
+ /**< build a fake FSEv07_DTable, designed to always generate the same symbolValue */
832
+
833
+
834
+
835
+ /* *****************************************
836
+ * FSE symbol decompression API
837
+ *******************************************/
838
+ typedef struct
839
+ {
840
+ size_t state;
841
+ const void* table; /* precise table may vary, depending on U16 */
842
+ } FSEv07_DState_t;
843
+
844
+
845
+ static void FSEv07_initDState(FSEv07_DState_t* DStatePtr, BITv07_DStream_t* bitD, const FSEv07_DTable* dt);
846
+
847
+ static unsigned char FSEv07_decodeSymbol(FSEv07_DState_t* DStatePtr, BITv07_DStream_t* bitD);
848
+
849
+
850
+
851
+ /* *****************************************
852
+ * FSE unsafe API
853
+ *******************************************/
854
+ static unsigned char FSEv07_decodeSymbolFast(FSEv07_DState_t* DStatePtr, BITv07_DStream_t* bitD);
855
+ /* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */
856
+
857
+
858
+ /* ====== Decompression ====== */
859
+
860
+ typedef struct {
861
+ U16 tableLog;
862
+ U16 fastMode;
863
+ } FSEv07_DTableHeader; /* sizeof U32 */
864
+
865
+ typedef struct
866
+ {
867
+ unsigned short newState;
868
+ unsigned char symbol;
869
+ unsigned char nbBits;
870
+ } FSEv07_decode_t; /* size == U32 */
871
+
872
+ MEM_STATIC void FSEv07_initDState(FSEv07_DState_t* DStatePtr, BITv07_DStream_t* bitD, const FSEv07_DTable* dt)
873
+ {
874
+ const void* ptr = dt;
875
+ const FSEv07_DTableHeader* const DTableH = (const FSEv07_DTableHeader*)ptr;
876
+ DStatePtr->state = BITv07_readBits(bitD, DTableH->tableLog);
877
+ BITv07_reloadDStream(bitD);
878
+ DStatePtr->table = dt + 1;
879
+ }
880
+
881
+ MEM_STATIC BYTE FSEv07_peekSymbol(const FSEv07_DState_t* DStatePtr)
882
+ {
883
+ FSEv07_decode_t const DInfo = ((const FSEv07_decode_t*)(DStatePtr->table))[DStatePtr->state];
884
+ return DInfo.symbol;
885
+ }
886
+
887
+ MEM_STATIC void FSEv07_updateState(FSEv07_DState_t* DStatePtr, BITv07_DStream_t* bitD)
888
+ {
889
+ FSEv07_decode_t const DInfo = ((const FSEv07_decode_t*)(DStatePtr->table))[DStatePtr->state];
890
+ U32 const nbBits = DInfo.nbBits;
891
+ size_t const lowBits = BITv07_readBits(bitD, nbBits);
892
+ DStatePtr->state = DInfo.newState + lowBits;
893
+ }
894
+
895
+ MEM_STATIC BYTE FSEv07_decodeSymbol(FSEv07_DState_t* DStatePtr, BITv07_DStream_t* bitD)
896
+ {
897
+ FSEv07_decode_t const DInfo = ((const FSEv07_decode_t*)(DStatePtr->table))[DStatePtr->state];
898
+ U32 const nbBits = DInfo.nbBits;
899
+ BYTE const symbol = DInfo.symbol;
900
+ size_t const lowBits = BITv07_readBits(bitD, nbBits);
901
+
902
+ DStatePtr->state = DInfo.newState + lowBits;
903
+ return symbol;
904
+ }
905
+
906
+ /*! FSEv07_decodeSymbolFast() :
907
+ unsafe, only works if no symbol has a probability > 50% */
908
+ MEM_STATIC BYTE FSEv07_decodeSymbolFast(FSEv07_DState_t* DStatePtr, BITv07_DStream_t* bitD)
909
+ {
910
+ FSEv07_decode_t const DInfo = ((const FSEv07_decode_t*)(DStatePtr->table))[DStatePtr->state];
911
+ U32 const nbBits = DInfo.nbBits;
912
+ BYTE const symbol = DInfo.symbol;
913
+ size_t const lowBits = BITv07_readBitsFast(bitD, nbBits);
914
+
915
+ DStatePtr->state = DInfo.newState + lowBits;
916
+ return symbol;
917
+ }
918
+
919
+
920
+
921
+ #ifndef FSEv07_COMMONDEFS_ONLY
922
+
923
+ /* **************************************************************
924
+ * Tuning parameters
925
+ ****************************************************************/
926
+ /*!MEMORY_USAGE :
927
+ * Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)
928
+ * Increasing memory usage improves compression ratio
929
+ * Reduced memory usage can improve speed, due to cache effect
930
+ * Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */
931
+ #define FSEv07_MAX_MEMORY_USAGE 14
932
+ #define FSEv07_DEFAULT_MEMORY_USAGE 13
933
+
934
+ /*!FSEv07_MAX_SYMBOL_VALUE :
935
+ * Maximum symbol value authorized.
936
+ * Required for proper stack allocation */
937
+ #define FSEv07_MAX_SYMBOL_VALUE 255
938
+
939
+
940
+ /* **************************************************************
941
+ * template functions type & suffix
942
+ ****************************************************************/
943
+ #define FSEv07_FUNCTION_TYPE BYTE
944
+ #define FSEv07_FUNCTION_EXTENSION
945
+ #define FSEv07_DECODE_TYPE FSEv07_decode_t
946
+
947
+
948
+ #endif /* !FSEv07_COMMONDEFS_ONLY */
949
+
950
+
951
+ /* ***************************************************************
952
+ * Constants
953
+ *****************************************************************/
954
+ #define FSEv07_MAX_TABLELOG (FSEv07_MAX_MEMORY_USAGE-2)
955
+ #define FSEv07_MAX_TABLESIZE (1U<<FSEv07_MAX_TABLELOG)
956
+ #define FSEv07_MAXTABLESIZE_MASK (FSEv07_MAX_TABLESIZE-1)
957
+ #define FSEv07_DEFAULT_TABLELOG (FSEv07_DEFAULT_MEMORY_USAGE-2)
958
+ #define FSEv07_MIN_TABLELOG 5
959
+
960
+ #define FSEv07_TABLELOG_ABSOLUTE_MAX 15
961
+ #if FSEv07_MAX_TABLELOG > FSEv07_TABLELOG_ABSOLUTE_MAX
962
+ # error "FSEv07_MAX_TABLELOG > FSEv07_TABLELOG_ABSOLUTE_MAX is not supported"
963
+ #endif
964
+
965
+ #define FSEv07_TABLESTEP(tableSize) ((tableSize>>1) + (tableSize>>3) + 3)
966
+
967
+
968
+ #endif /* FSEv07_STATIC_LINKING_ONLY */
969
+
970
+
971
+ #if defined (__cplusplus)
972
+ }
973
+ #endif
974
+
975
+ #endif /* FSEv07_H */
976
+ /* ******************************************************************
977
+ Huffman coder, part of New Generation Entropy library
978
+ header file
979
+ Copyright (C) 2013-2016, Yann Collet.
980
+
981
+ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
982
+
983
+ Redistribution and use in source and binary forms, with or without
984
+ modification, are permitted provided that the following conditions are
985
+ met:
986
+
987
+ * Redistributions of source code must retain the above copyright
988
+ notice, this list of conditions and the following disclaimer.
989
+ * Redistributions in binary form must reproduce the above
990
+ copyright notice, this list of conditions and the following disclaimer
991
+ in the documentation and/or other materials provided with the
992
+ distribution.
993
+
994
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
995
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
996
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
997
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
998
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
999
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
1000
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1001
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
1002
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1003
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1004
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1005
+
1006
+ You can contact the author at :
1007
+ - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
1008
+ ****************************************************************** */
1009
+ #ifndef HUFv07_H_298734234
1010
+ #define HUFv07_H_298734234
1011
+
1012
+ #if defined (__cplusplus)
1013
+ extern "C" {
1014
+ #endif
1015
+
1016
+
1017
+
1018
+ /* *** simple functions *** */
1019
+ /**
1020
+ HUFv07_decompress() :
1021
+ Decompress HUF data from buffer 'cSrc', of size 'cSrcSize',
1022
+ into already allocated buffer 'dst', of minimum size 'dstSize'.
1023
+ `dstSize` : **must** be the ***exact*** size of original (uncompressed) data.
1024
+ Note : in contrast with FSE, HUFv07_decompress can regenerate
1025
+ RLE (cSrcSize==1) and uncompressed (cSrcSize==dstSize) data,
1026
+ because it knows size to regenerate.
1027
+ @return : size of regenerated data (== dstSize),
1028
+ or an error code, which can be tested using HUFv07_isError()
1029
+ */
1030
+ size_t HUFv07_decompress(void* dst, size_t dstSize,
1031
+ const void* cSrc, size_t cSrcSize);
1032
+
1033
+
1034
+ /* ****************************************
1035
+ * Tool functions
1036
+ ******************************************/
1037
+ #define HUFv07_BLOCKSIZE_MAX (128 * 1024)
1038
+
1039
+ /* Error Management */
1040
+ unsigned HUFv07_isError(size_t code); /**< tells if a return value is an error code */
1041
+ const char* HUFv07_getErrorName(size_t code); /**< provides error code string (useful for debugging) */
1042
+
1043
+
1044
+ /* *** Advanced function *** */
1045
+
1046
+
1047
+ #ifdef HUFv07_STATIC_LINKING_ONLY
1048
+
1049
+
1050
+ /* *** Constants *** */
1051
+ #define HUFv07_TABLELOG_ABSOLUTEMAX 16 /* absolute limit of HUFv07_MAX_TABLELOG. Beyond that value, code does not work */
1052
+ #define HUFv07_TABLELOG_MAX 12 /* max configured tableLog (for static allocation); can be modified up to HUFv07_ABSOLUTEMAX_TABLELOG */
1053
+ #define HUFv07_TABLELOG_DEFAULT 11 /* tableLog by default, when not specified */
1054
+ #define HUFv07_SYMBOLVALUE_MAX 255
1055
+ #if (HUFv07_TABLELOG_MAX > HUFv07_TABLELOG_ABSOLUTEMAX)
1056
+ # error "HUFv07_TABLELOG_MAX is too large !"
1057
+ #endif
1058
+
1059
+
1060
+ /* ****************************************
1061
+ * Static allocation
1062
+ ******************************************/
1063
+ /* HUF buffer bounds */
1064
+ #define HUFv07_BLOCKBOUND(size) (size + (size>>8) + 8) /* only true if incompressible pre-filtered with fast heuristic */
1065
+
1066
+ /* static allocation of HUF's DTable */
1067
+ typedef U32 HUFv07_DTable;
1068
+ #define HUFv07_DTABLE_SIZE(maxTableLog) (1 + (1<<(maxTableLog)))
1069
+ #define HUFv07_CREATE_STATIC_DTABLEX2(DTable, maxTableLog) \
1070
+ HUFv07_DTable DTable[HUFv07_DTABLE_SIZE((maxTableLog)-1)] = { ((U32)((maxTableLog)-1)*0x1000001) }
1071
+ #define HUFv07_CREATE_STATIC_DTABLEX4(DTable, maxTableLog) \
1072
+ HUFv07_DTable DTable[HUFv07_DTABLE_SIZE(maxTableLog)] = { ((U32)(maxTableLog)*0x1000001) }
1073
+
1074
+
1075
+ /* ****************************************
1076
+ * Advanced decompression functions
1077
+ ******************************************/
1078
+ size_t HUFv07_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< single-symbol decoder */
1079
+ size_t HUFv07_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< double-symbols decoder */
1080
+
1081
+ size_t HUFv07_decompress4X_DCtx (HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< decodes RLE and uncompressed */
1082
+ size_t HUFv07_decompress4X_hufOnly(HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< considers RLE and uncompressed as errors */
1083
+ size_t HUFv07_decompress4X2_DCtx(HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< single-symbol decoder */
1084
+ size_t HUFv07_decompress4X4_DCtx(HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< double-symbols decoder */
1085
+
1086
+ size_t HUFv07_decompress1X_DCtx (HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);
1087
+ size_t HUFv07_decompress1X2_DCtx(HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< single-symbol decoder */
1088
+ size_t HUFv07_decompress1X4_DCtx(HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< double-symbols decoder */
1089
+
1090
+
1091
+ /* ****************************************
1092
+ * HUF detailed API
1093
+ ******************************************/
1094
+ /*!
1095
+ The following API allows targeting specific sub-functions for advanced tasks.
1096
+ For example, it's possible to compress several blocks using the same 'CTable',
1097
+ or to save and regenerate 'CTable' using external methods.
1098
+ */
1099
+ /* FSEv07_count() : find it within "fse.h" */
1100
+
1101
+ /*! HUFv07_readStats() :
1102
+ Read compact Huffman tree, saved by HUFv07_writeCTable().
1103
+ `huffWeight` is destination buffer.
1104
+ @return : size read from `src` , or an error Code .
1105
+ Note : Needed by HUFv07_readCTable() and HUFv07_readDTableXn() . */
1106
+ size_t HUFv07_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,
1107
+ U32* nbSymbolsPtr, U32* tableLogPtr,
1108
+ const void* src, size_t srcSize);
1109
+
1110
+
1111
+ /*
1112
+ HUFv07_decompress() does the following:
1113
+ 1. select the decompression algorithm (X2, X4) based on pre-computed heuristics
1114
+ 2. build Huffman table from save, using HUFv07_readDTableXn()
1115
+ 3. decode 1 or 4 segments in parallel using HUFv07_decompressSXn_usingDTable
1116
+ */
1117
+
1118
+ /** HUFv07_selectDecoder() :
1119
+ * Tells which decoder is likely to decode faster,
1120
+ * based on a set of pre-determined metrics.
1121
+ * @return : 0==HUFv07_decompress4X2, 1==HUFv07_decompress4X4 .
1122
+ * Assumption : 0 < cSrcSize < dstSize <= 128 KB */
1123
+ U32 HUFv07_selectDecoder (size_t dstSize, size_t cSrcSize);
1124
+
1125
+ size_t HUFv07_readDTableX2 (HUFv07_DTable* DTable, const void* src, size_t srcSize);
1126
+ size_t HUFv07_readDTableX4 (HUFv07_DTable* DTable, const void* src, size_t srcSize);
1127
+
1128
+ size_t HUFv07_decompress4X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUFv07_DTable* DTable);
1129
+ size_t HUFv07_decompress4X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUFv07_DTable* DTable);
1130
+ size_t HUFv07_decompress4X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUFv07_DTable* DTable);
1131
+
1132
+
1133
+ /* single stream variants */
1134
+ size_t HUFv07_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* single-symbol decoder */
1135
+ size_t HUFv07_decompress1X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* double-symbol decoder */
1136
+
1137
+ size_t HUFv07_decompress1X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUFv07_DTable* DTable);
1138
+ size_t HUFv07_decompress1X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUFv07_DTable* DTable);
1139
+ size_t HUFv07_decompress1X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUFv07_DTable* DTable);
1140
+
1141
+
1142
+ #endif /* HUFv07_STATIC_LINKING_ONLY */
1143
+
1144
+
1145
+ #if defined (__cplusplus)
1146
+ }
1147
+ #endif
1148
+
1149
+ #endif /* HUFv07_H_298734234 */
1150
+ /*
1151
+ Common functions of New Generation Entropy library
1152
+ Copyright (C) 2016, Yann Collet.
1153
+
1154
+ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
1155
+
1156
+ Redistribution and use in source and binary forms, with or without
1157
+ modification, are permitted provided that the following conditions are
1158
+ met:
1159
+
1160
+ * Redistributions of source code must retain the above copyright
1161
+ notice, this list of conditions and the following disclaimer.
1162
+ * Redistributions in binary form must reproduce the above
1163
+ copyright notice, this list of conditions and the following disclaimer
1164
+ in the documentation and/or other materials provided with the
1165
+ distribution.
1166
+
1167
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1168
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1169
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1170
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
1171
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
1172
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
1173
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1174
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
1175
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1176
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1177
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1178
+
1179
+ You can contact the author at :
1180
+ - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy
1181
+ - Public forum : https://groups.google.com/forum/#!forum/lz4c
1182
+ *************************************************************************** */
1183
+
1184
+
1185
+
1186
+ /*-****************************************
1187
+ * FSE Error Management
1188
+ ******************************************/
1189
+ unsigned FSEv07_isError(size_t code) { return ERR_isError(code); }
1190
+
1191
+ const char* FSEv07_getErrorName(size_t code) { return ERR_getErrorName(code); }
1192
+
1193
+
1194
+ /* **************************************************************
1195
+ * HUF Error Management
1196
+ ****************************************************************/
1197
+ unsigned HUFv07_isError(size_t code) { return ERR_isError(code); }
1198
+
1199
+ const char* HUFv07_getErrorName(size_t code) { return ERR_getErrorName(code); }
1200
+
1201
+
1202
+ /*-**************************************************************
1203
+ * FSE NCount encoding-decoding
1204
+ ****************************************************************/
1205
+ static short FSEv07_abs(short a) { return (short)(a<0 ? -a : a); }
1206
+
1207
+ size_t FSEv07_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,
1208
+ const void* headerBuffer, size_t hbSize)
1209
+ {
1210
+ const BYTE* const istart = (const BYTE*) headerBuffer;
1211
+ const BYTE* const iend = istart + hbSize;
1212
+ const BYTE* ip = istart;
1213
+ int nbBits;
1214
+ int remaining;
1215
+ int threshold;
1216
+ U32 bitStream;
1217
+ int bitCount;
1218
+ unsigned charnum = 0;
1219
+ int previous0 = 0;
1220
+
1221
+ if (hbSize < 4) return ERROR(srcSize_wrong);
1222
+ bitStream = MEM_readLE32(ip);
1223
+ nbBits = (bitStream & 0xF) + FSEv07_MIN_TABLELOG; /* extract tableLog */
1224
+ if (nbBits > FSEv07_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge);
1225
+ bitStream >>= 4;
1226
+ bitCount = 4;
1227
+ *tableLogPtr = nbBits;
1228
+ remaining = (1<<nbBits)+1;
1229
+ threshold = 1<<nbBits;
1230
+ nbBits++;
1231
+
1232
+ while ((remaining>1) && (charnum<=*maxSVPtr)) {
1233
+ if (previous0) {
1234
+ unsigned n0 = charnum;
1235
+ while ((bitStream & 0xFFFF) == 0xFFFF) {
1236
+ n0+=24;
1237
+ if (ip < iend-5) {
1238
+ ip+=2;
1239
+ bitStream = MEM_readLE32(ip) >> bitCount;
1240
+ } else {
1241
+ bitStream >>= 16;
1242
+ bitCount+=16;
1243
+ } }
1244
+ while ((bitStream & 3) == 3) {
1245
+ n0+=3;
1246
+ bitStream>>=2;
1247
+ bitCount+=2;
1248
+ }
1249
+ n0 += bitStream & 3;
1250
+ bitCount += 2;
1251
+ if (n0 > *maxSVPtr) return ERROR(maxSymbolValue_tooSmall);
1252
+ while (charnum < n0) normalizedCounter[charnum++] = 0;
1253
+ if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {
1254
+ ip += bitCount>>3;
1255
+ bitCount &= 7;
1256
+ bitStream = MEM_readLE32(ip) >> bitCount;
1257
+ }
1258
+ else
1259
+ bitStream >>= 2;
1260
+ }
1261
+ { short const max = (short)((2*threshold-1)-remaining);
1262
+ short count;
1263
+
1264
+ if ((bitStream & (threshold-1)) < (U32)max) {
1265
+ count = (short)(bitStream & (threshold-1));
1266
+ bitCount += nbBits-1;
1267
+ } else {
1268
+ count = (short)(bitStream & (2*threshold-1));
1269
+ if (count >= threshold) count -= max;
1270
+ bitCount += nbBits;
1271
+ }
1272
+
1273
+ count--; /* extra accuracy */
1274
+ remaining -= FSEv07_abs(count);
1275
+ normalizedCounter[charnum++] = count;
1276
+ previous0 = !count;
1277
+ while (remaining < threshold) {
1278
+ nbBits--;
1279
+ threshold >>= 1;
1280
+ }
1281
+
1282
+ if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {
1283
+ ip += bitCount>>3;
1284
+ bitCount &= 7;
1285
+ } else {
1286
+ bitCount -= (int)(8 * (iend - 4 - ip));
1287
+ ip = iend - 4;
1288
+ }
1289
+ bitStream = MEM_readLE32(ip) >> (bitCount & 31);
1290
+ } } /* while ((remaining>1) && (charnum<=*maxSVPtr)) */
1291
+ if (remaining != 1) return ERROR(GENERIC);
1292
+ *maxSVPtr = charnum-1;
1293
+
1294
+ ip += (bitCount+7)>>3;
1295
+ if ((size_t)(ip-istart) > hbSize) return ERROR(srcSize_wrong);
1296
+ return ip-istart;
1297
+ }
1298
+
1299
+
1300
+ /*! HUFv07_readStats() :
1301
+ Read compact Huffman tree, saved by HUFv07_writeCTable().
1302
+ `huffWeight` is destination buffer.
1303
+ @return : size read from `src` , or an error Code .
1304
+ Note : Needed by HUFv07_readCTable() and HUFv07_readDTableXn() .
1305
+ */
1306
+ size_t HUFv07_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,
1307
+ U32* nbSymbolsPtr, U32* tableLogPtr,
1308
+ const void* src, size_t srcSize)
1309
+ {
1310
+ U32 weightTotal;
1311
+ const BYTE* ip = (const BYTE*) src;
1312
+ size_t iSize;
1313
+ size_t oSize;
1314
+
1315
+ if (!srcSize) return ERROR(srcSize_wrong);
1316
+ iSize = ip[0];
1317
+ /* memset(huffWeight, 0, hwSize); */ /* is not necessary, even though some analyzer complain ... */
1318
+
1319
+ if (iSize >= 128) { /* special header */
1320
+ if (iSize >= (242)) { /* RLE */
1321
+ static U32 l[14] = { 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 127, 128 };
1322
+ oSize = l[iSize-242];
1323
+ memset(huffWeight, 1, hwSize);
1324
+ iSize = 0;
1325
+ }
1326
+ else { /* Incompressible */
1327
+ oSize = iSize - 127;
1328
+ iSize = ((oSize+1)/2);
1329
+ if (iSize+1 > srcSize) return ERROR(srcSize_wrong);
1330
+ if (oSize >= hwSize) return ERROR(corruption_detected);
1331
+ ip += 1;
1332
+ { U32 n;
1333
+ for (n=0; n<oSize; n+=2) {
1334
+ huffWeight[n] = ip[n/2] >> 4;
1335
+ huffWeight[n+1] = ip[n/2] & 15;
1336
+ } } } }
1337
+ else { /* header compressed with FSE (normal case) */
1338
+ if (iSize+1 > srcSize) return ERROR(srcSize_wrong);
1339
+ oSize = FSEv07_decompress(huffWeight, hwSize-1, ip+1, iSize); /* max (hwSize-1) values decoded, as last one is implied */
1340
+ if (FSEv07_isError(oSize)) return oSize;
1341
+ }
1342
+
1343
+ /* collect weight stats */
1344
+ memset(rankStats, 0, (HUFv07_TABLELOG_ABSOLUTEMAX + 1) * sizeof(U32));
1345
+ weightTotal = 0;
1346
+ { U32 n; for (n=0; n<oSize; n++) {
1347
+ if (huffWeight[n] >= HUFv07_TABLELOG_ABSOLUTEMAX) return ERROR(corruption_detected);
1348
+ rankStats[huffWeight[n]]++;
1349
+ weightTotal += (1 << huffWeight[n]) >> 1;
1350
+ } }
1351
+ if (weightTotal == 0) return ERROR(corruption_detected);
1352
+
1353
+ /* get last non-null symbol weight (implied, total must be 2^n) */
1354
+ { U32 const tableLog = BITv07_highbit32(weightTotal) + 1;
1355
+ if (tableLog > HUFv07_TABLELOG_ABSOLUTEMAX) return ERROR(corruption_detected);
1356
+ *tableLogPtr = tableLog;
1357
+ /* determine last weight */
1358
+ { U32 const total = 1 << tableLog;
1359
+ U32 const rest = total - weightTotal;
1360
+ U32 const verif = 1 << BITv07_highbit32(rest);
1361
+ U32 const lastWeight = BITv07_highbit32(rest) + 1;
1362
+ if (verif != rest) return ERROR(corruption_detected); /* last value must be a clean power of 2 */
1363
+ huffWeight[oSize] = (BYTE)lastWeight;
1364
+ rankStats[lastWeight]++;
1365
+ } }
1366
+
1367
+ /* check tree construction validity */
1368
+ if ((rankStats[1] < 2) || (rankStats[1] & 1)) return ERROR(corruption_detected); /* by construction : at least 2 elts of rank 1, must be even */
1369
+
1370
+ /* results */
1371
+ *nbSymbolsPtr = (U32)(oSize+1);
1372
+ return iSize+1;
1373
+ }
1374
+ /* ******************************************************************
1375
+ FSE : Finite State Entropy decoder
1376
+ Copyright (C) 2013-2015, Yann Collet.
1377
+
1378
+ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
1379
+
1380
+ Redistribution and use in source and binary forms, with or without
1381
+ modification, are permitted provided that the following conditions are
1382
+ met:
1383
+
1384
+ * Redistributions of source code must retain the above copyright
1385
+ notice, this list of conditions and the following disclaimer.
1386
+ * Redistributions in binary form must reproduce the above
1387
+ copyright notice, this list of conditions and the following disclaimer
1388
+ in the documentation and/or other materials provided with the
1389
+ distribution.
1390
+
1391
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1392
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1393
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1394
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
1395
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
1396
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
1397
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1398
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
1399
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1400
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1401
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1402
+
1403
+ You can contact the author at :
1404
+ - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy
1405
+ - Public forum : https://groups.google.com/forum/#!forum/lz4c
1406
+ ****************************************************************** */
1407
+
1408
+
1409
+ /* **************************************************************
1410
+ * Compiler specifics
1411
+ ****************************************************************/
1412
+ #ifdef _MSC_VER /* Visual Studio */
1413
+ # define FORCE_INLINE static __forceinline
1414
+ # include <intrin.h> /* For Visual 2005 */
1415
+ # pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
1416
+ # pragma warning(disable : 4214) /* disable: C4214: non-int bitfields */
1417
+ #else
1418
+ # if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */
1419
+ # ifdef __GNUC__
1420
+ # define FORCE_INLINE static inline __attribute__((always_inline))
1421
+ # else
1422
+ # define FORCE_INLINE static inline
1423
+ # endif
1424
+ # else
1425
+ # define FORCE_INLINE static
1426
+ # endif /* __STDC_VERSION__ */
1427
+ #endif
1428
+
1429
+
1430
+ /* **************************************************************
1431
+ * Error Management
1432
+ ****************************************************************/
1433
+ #define FSEv07_isError ERR_isError
1434
+ #define FSEv07_STATIC_ASSERT(c) { enum { FSEv07_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */
1435
+
1436
+
1437
+ /* **************************************************************
1438
+ * Complex types
1439
+ ****************************************************************/
1440
+ typedef U32 DTable_max_t[FSEv07_DTABLE_SIZE_U32(FSEv07_MAX_TABLELOG)];
1441
+
1442
+
1443
+ /* **************************************************************
1444
+ * Templates
1445
+ ****************************************************************/
1446
+ /*
1447
+ designed to be included
1448
+ for type-specific functions (template emulation in C)
1449
+ Objective is to write these functions only once, for improved maintenance
1450
+ */
1451
+
1452
+ /* safety checks */
1453
+ #ifndef FSEv07_FUNCTION_EXTENSION
1454
+ # error "FSEv07_FUNCTION_EXTENSION must be defined"
1455
+ #endif
1456
+ #ifndef FSEv07_FUNCTION_TYPE
1457
+ # error "FSEv07_FUNCTION_TYPE must be defined"
1458
+ #endif
1459
+
1460
+ /* Function names */
1461
+ #define FSEv07_CAT(X,Y) X##Y
1462
+ #define FSEv07_FUNCTION_NAME(X,Y) FSEv07_CAT(X,Y)
1463
+ #define FSEv07_TYPE_NAME(X,Y) FSEv07_CAT(X,Y)
1464
+
1465
+
1466
+ /* Function templates */
1467
+ FSEv07_DTable* FSEv07_createDTable (unsigned tableLog)
1468
+ {
1469
+ if (tableLog > FSEv07_TABLELOG_ABSOLUTE_MAX) tableLog = FSEv07_TABLELOG_ABSOLUTE_MAX;
1470
+ return (FSEv07_DTable*)malloc( FSEv07_DTABLE_SIZE_U32(tableLog) * sizeof (U32) );
1471
+ }
1472
+
1473
+ void FSEv07_freeDTable (FSEv07_DTable* dt)
1474
+ {
1475
+ free(dt);
1476
+ }
1477
+
1478
+ size_t FSEv07_buildDTable(FSEv07_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)
1479
+ {
1480
+ void* const tdPtr = dt+1; /* because *dt is unsigned, 32-bits aligned on 32-bits */
1481
+ FSEv07_DECODE_TYPE* const tableDecode = (FSEv07_DECODE_TYPE*) (tdPtr);
1482
+ U16 symbolNext[FSEv07_MAX_SYMBOL_VALUE+1];
1483
+
1484
+ U32 const maxSV1 = maxSymbolValue + 1;
1485
+ U32 const tableSize = 1 << tableLog;
1486
+ U32 highThreshold = tableSize-1;
1487
+
1488
+ /* Sanity Checks */
1489
+ if (maxSymbolValue > FSEv07_MAX_SYMBOL_VALUE) return ERROR(maxSymbolValue_tooLarge);
1490
+ if (tableLog > FSEv07_MAX_TABLELOG) return ERROR(tableLog_tooLarge);
1491
+
1492
+ /* Init, lay down lowprob symbols */
1493
+ { FSEv07_DTableHeader DTableH;
1494
+ DTableH.tableLog = (U16)tableLog;
1495
+ DTableH.fastMode = 1;
1496
+ { S16 const largeLimit= (S16)(1 << (tableLog-1));
1497
+ U32 s;
1498
+ for (s=0; s<maxSV1; s++) {
1499
+ if (normalizedCounter[s]==-1) {
1500
+ tableDecode[highThreshold--].symbol = (FSEv07_FUNCTION_TYPE)s;
1501
+ symbolNext[s] = 1;
1502
+ } else {
1503
+ if (normalizedCounter[s] >= largeLimit) DTableH.fastMode=0;
1504
+ symbolNext[s] = normalizedCounter[s];
1505
+ } } }
1506
+ memcpy(dt, &DTableH, sizeof(DTableH));
1507
+ }
1508
+
1509
+ /* Spread symbols */
1510
+ { U32 const tableMask = tableSize-1;
1511
+ U32 const step = FSEv07_TABLESTEP(tableSize);
1512
+ U32 s, position = 0;
1513
+ for (s=0; s<maxSV1; s++) {
1514
+ int i;
1515
+ for (i=0; i<normalizedCounter[s]; i++) {
1516
+ tableDecode[position].symbol = (FSEv07_FUNCTION_TYPE)s;
1517
+ position = (position + step) & tableMask;
1518
+ while (position > highThreshold) position = (position + step) & tableMask; /* lowprob area */
1519
+ } }
1520
+
1521
+ if (position!=0) return ERROR(GENERIC); /* position must reach all cells once, otherwise normalizedCounter is incorrect */
1522
+ }
1523
+
1524
+ /* Build Decoding table */
1525
+ { U32 u;
1526
+ for (u=0; u<tableSize; u++) {
1527
+ FSEv07_FUNCTION_TYPE const symbol = (FSEv07_FUNCTION_TYPE)(tableDecode[u].symbol);
1528
+ U16 nextState = symbolNext[symbol]++;
1529
+ tableDecode[u].nbBits = (BYTE) (tableLog - BITv07_highbit32 ((U32)nextState) );
1530
+ tableDecode[u].newState = (U16) ( (nextState << tableDecode[u].nbBits) - tableSize);
1531
+ } }
1532
+
1533
+ return 0;
1534
+ }
1535
+
1536
+
1537
+
1538
+ #ifndef FSEv07_COMMONDEFS_ONLY
1539
+
1540
+ /*-*******************************************************
1541
+ * Decompression (Byte symbols)
1542
+ *********************************************************/
1543
+ size_t FSEv07_buildDTable_rle (FSEv07_DTable* dt, BYTE symbolValue)
1544
+ {
1545
+ void* ptr = dt;
1546
+ FSEv07_DTableHeader* const DTableH = (FSEv07_DTableHeader*)ptr;
1547
+ void* dPtr = dt + 1;
1548
+ FSEv07_decode_t* const cell = (FSEv07_decode_t*)dPtr;
1549
+
1550
+ DTableH->tableLog = 0;
1551
+ DTableH->fastMode = 0;
1552
+
1553
+ cell->newState = 0;
1554
+ cell->symbol = symbolValue;
1555
+ cell->nbBits = 0;
1556
+
1557
+ return 0;
1558
+ }
1559
+
1560
+
1561
+ size_t FSEv07_buildDTable_raw (FSEv07_DTable* dt, unsigned nbBits)
1562
+ {
1563
+ void* ptr = dt;
1564
+ FSEv07_DTableHeader* const DTableH = (FSEv07_DTableHeader*)ptr;
1565
+ void* dPtr = dt + 1;
1566
+ FSEv07_decode_t* const dinfo = (FSEv07_decode_t*)dPtr;
1567
+ const unsigned tableSize = 1 << nbBits;
1568
+ const unsigned tableMask = tableSize - 1;
1569
+ const unsigned maxSV1 = tableMask+1;
1570
+ unsigned s;
1571
+
1572
+ /* Sanity checks */
1573
+ if (nbBits < 1) return ERROR(GENERIC); /* min size */
1574
+
1575
+ /* Build Decoding Table */
1576
+ DTableH->tableLog = (U16)nbBits;
1577
+ DTableH->fastMode = 1;
1578
+ for (s=0; s<maxSV1; s++) {
1579
+ dinfo[s].newState = 0;
1580
+ dinfo[s].symbol = (BYTE)s;
1581
+ dinfo[s].nbBits = (BYTE)nbBits;
1582
+ }
1583
+
1584
+ return 0;
1585
+ }
1586
+
1587
+ FORCE_INLINE size_t FSEv07_decompress_usingDTable_generic(
1588
+ void* dst, size_t maxDstSize,
1589
+ const void* cSrc, size_t cSrcSize,
1590
+ const FSEv07_DTable* dt, const unsigned fast)
1591
+ {
1592
+ BYTE* const ostart = (BYTE*) dst;
1593
+ BYTE* op = ostart;
1594
+ BYTE* const omax = op + maxDstSize;
1595
+ BYTE* const olimit = omax-3;
1596
+
1597
+ BITv07_DStream_t bitD;
1598
+ FSEv07_DState_t state1;
1599
+ FSEv07_DState_t state2;
1600
+
1601
+ /* Init */
1602
+ { size_t const errorCode = BITv07_initDStream(&bitD, cSrc, cSrcSize); /* replaced last arg by maxCompressed Size */
1603
+ if (FSEv07_isError(errorCode)) return errorCode; }
1604
+
1605
+ FSEv07_initDState(&state1, &bitD, dt);
1606
+ FSEv07_initDState(&state2, &bitD, dt);
1607
+
1608
+ #define FSEv07_GETSYMBOL(statePtr) fast ? FSEv07_decodeSymbolFast(statePtr, &bitD) : FSEv07_decodeSymbol(statePtr, &bitD)
1609
+
1610
+ /* 4 symbols per loop */
1611
+ for ( ; (BITv07_reloadDStream(&bitD)==BITv07_DStream_unfinished) && (op<olimit) ; op+=4) {
1612
+ op[0] = FSEv07_GETSYMBOL(&state1);
1613
+
1614
+ if (FSEv07_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */
1615
+ BITv07_reloadDStream(&bitD);
1616
+
1617
+ op[1] = FSEv07_GETSYMBOL(&state2);
1618
+
1619
+ if (FSEv07_MAX_TABLELOG*4+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */
1620
+ { if (BITv07_reloadDStream(&bitD) > BITv07_DStream_unfinished) { op+=2; break; } }
1621
+
1622
+ op[2] = FSEv07_GETSYMBOL(&state1);
1623
+
1624
+ if (FSEv07_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */
1625
+ BITv07_reloadDStream(&bitD);
1626
+
1627
+ op[3] = FSEv07_GETSYMBOL(&state2);
1628
+ }
1629
+
1630
+ /* tail */
1631
+ /* note : BITv07_reloadDStream(&bitD) >= FSEv07_DStream_partiallyFilled; Ends at exactly BITv07_DStream_completed */
1632
+ while (1) {
1633
+ if (op>(omax-2)) return ERROR(dstSize_tooSmall);
1634
+
1635
+ *op++ = FSEv07_GETSYMBOL(&state1);
1636
+
1637
+ if (BITv07_reloadDStream(&bitD)==BITv07_DStream_overflow) {
1638
+ *op++ = FSEv07_GETSYMBOL(&state2);
1639
+ break;
1640
+ }
1641
+
1642
+ if (op>(omax-2)) return ERROR(dstSize_tooSmall);
1643
+
1644
+ *op++ = FSEv07_GETSYMBOL(&state2);
1645
+
1646
+ if (BITv07_reloadDStream(&bitD)==BITv07_DStream_overflow) {
1647
+ *op++ = FSEv07_GETSYMBOL(&state1);
1648
+ break;
1649
+ } }
1650
+
1651
+ return op-ostart;
1652
+ }
1653
+
1654
+
1655
+ size_t FSEv07_decompress_usingDTable(void* dst, size_t originalSize,
1656
+ const void* cSrc, size_t cSrcSize,
1657
+ const FSEv07_DTable* dt)
1658
+ {
1659
+ const void* ptr = dt;
1660
+ const FSEv07_DTableHeader* DTableH = (const FSEv07_DTableHeader*)ptr;
1661
+ const U32 fastMode = DTableH->fastMode;
1662
+
1663
+ /* select fast mode (static) */
1664
+ if (fastMode) return FSEv07_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1);
1665
+ return FSEv07_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0);
1666
+ }
1667
+
1668
+
1669
+ size_t FSEv07_decompress(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize)
1670
+ {
1671
+ const BYTE* const istart = (const BYTE*)cSrc;
1672
+ const BYTE* ip = istart;
1673
+ short counting[FSEv07_MAX_SYMBOL_VALUE+1];
1674
+ DTable_max_t dt; /* Static analyzer seems unable to understand this table will be properly initialized later */
1675
+ unsigned tableLog;
1676
+ unsigned maxSymbolValue = FSEv07_MAX_SYMBOL_VALUE;
1677
+
1678
+ if (cSrcSize<2) return ERROR(srcSize_wrong); /* too small input size */
1679
+
1680
+ /* normal FSE decoding mode */
1681
+ { size_t const NCountLength = FSEv07_readNCount (counting, &maxSymbolValue, &tableLog, istart, cSrcSize);
1682
+ if (FSEv07_isError(NCountLength)) return NCountLength;
1683
+ if (NCountLength >= cSrcSize) return ERROR(srcSize_wrong); /* too small input size */
1684
+ ip += NCountLength;
1685
+ cSrcSize -= NCountLength;
1686
+ }
1687
+
1688
+ { size_t const errorCode = FSEv07_buildDTable (dt, counting, maxSymbolValue, tableLog);
1689
+ if (FSEv07_isError(errorCode)) return errorCode; }
1690
+
1691
+ return FSEv07_decompress_usingDTable (dst, maxDstSize, ip, cSrcSize, dt); /* always return, even if it is an error code */
1692
+ }
1693
+
1694
+
1695
+
1696
+ #endif /* FSEv07_COMMONDEFS_ONLY */
1697
+
1698
+ /* ******************************************************************
1699
+ Huffman decoder, part of New Generation Entropy library
1700
+ Copyright (C) 2013-2016, Yann Collet.
1701
+
1702
+ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
1703
+
1704
+ Redistribution and use in source and binary forms, with or without
1705
+ modification, are permitted provided that the following conditions are
1706
+ met:
1707
+
1708
+ * Redistributions of source code must retain the above copyright
1709
+ notice, this list of conditions and the following disclaimer.
1710
+ * Redistributions in binary form must reproduce the above
1711
+ copyright notice, this list of conditions and the following disclaimer
1712
+ in the documentation and/or other materials provided with the
1713
+ distribution.
1714
+
1715
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1716
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1717
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1718
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
1719
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
1720
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
1721
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1722
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
1723
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1724
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1725
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1726
+
1727
+ You can contact the author at :
1728
+ - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy
1729
+ - Public forum : https://groups.google.com/forum/#!forum/lz4c
1730
+ ****************************************************************** */
1731
+
1732
+ /* **************************************************************
1733
+ * Compiler specifics
1734
+ ****************************************************************/
1735
+ #if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
1736
+ /* inline is defined */
1737
+ #elif defined(_MSC_VER)
1738
+ # define inline __inline
1739
+ #else
1740
+ # define inline /* disable inline */
1741
+ #endif
1742
+
1743
+
1744
+ #ifdef _MSC_VER /* Visual Studio */
1745
+ # pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
1746
+ #endif
1747
+
1748
+
1749
+
1750
+ /* **************************************************************
1751
+ * Error Management
1752
+ ****************************************************************/
1753
+ #define HUFv07_STATIC_ASSERT(c) { enum { HUFv07_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */
1754
+
1755
+
1756
+ /*-***************************/
1757
+ /* generic DTableDesc */
1758
+ /*-***************************/
1759
+
1760
+ typedef struct { BYTE maxTableLog; BYTE tableType; BYTE tableLog; BYTE reserved; } DTableDesc;
1761
+
1762
+ static DTableDesc HUFv07_getDTableDesc(const HUFv07_DTable* table)
1763
+ {
1764
+ DTableDesc dtd;
1765
+ memcpy(&dtd, table, sizeof(dtd));
1766
+ return dtd;
1767
+ }
1768
+
1769
+
1770
+ /*-***************************/
1771
+ /* single-symbol decoding */
1772
+ /*-***************************/
1773
+
1774
+ typedef struct { BYTE byte; BYTE nbBits; } HUFv07_DEltX2; /* single-symbol decoding */
1775
+
1776
+ size_t HUFv07_readDTableX2 (HUFv07_DTable* DTable, const void* src, size_t srcSize)
1777
+ {
1778
+ BYTE huffWeight[HUFv07_SYMBOLVALUE_MAX + 1];
1779
+ U32 rankVal[HUFv07_TABLELOG_ABSOLUTEMAX + 1]; /* large enough for values from 0 to 16 */
1780
+ U32 tableLog = 0;
1781
+ U32 nbSymbols = 0;
1782
+ size_t iSize;
1783
+ void* const dtPtr = DTable + 1;
1784
+ HUFv07_DEltX2* const dt = (HUFv07_DEltX2*)dtPtr;
1785
+
1786
+ HUFv07_STATIC_ASSERT(sizeof(DTableDesc) == sizeof(HUFv07_DTable));
1787
+ /* memset(huffWeight, 0, sizeof(huffWeight)); */ /* is not necessary, even though some analyzer complain ... */
1788
+
1789
+ iSize = HUFv07_readStats(huffWeight, HUFv07_SYMBOLVALUE_MAX + 1, rankVal, &nbSymbols, &tableLog, src, srcSize);
1790
+ if (HUFv07_isError(iSize)) return iSize;
1791
+
1792
+ /* Table header */
1793
+ { DTableDesc dtd = HUFv07_getDTableDesc(DTable);
1794
+ if (tableLog > (U32)(dtd.maxTableLog+1)) return ERROR(tableLog_tooLarge); /* DTable too small, huffman tree cannot fit in */
1795
+ dtd.tableType = 0;
1796
+ dtd.tableLog = (BYTE)tableLog;
1797
+ memcpy(DTable, &dtd, sizeof(dtd));
1798
+ }
1799
+
1800
+ /* Prepare ranks */
1801
+ { U32 n, nextRankStart = 0;
1802
+ for (n=1; n<tableLog+1; n++) {
1803
+ U32 current = nextRankStart;
1804
+ nextRankStart += (rankVal[n] << (n-1));
1805
+ rankVal[n] = current;
1806
+ } }
1807
+
1808
+ /* fill DTable */
1809
+ { U32 n;
1810
+ for (n=0; n<nbSymbols; n++) {
1811
+ U32 const w = huffWeight[n];
1812
+ U32 const length = (1 << w) >> 1;
1813
+ U32 i;
1814
+ HUFv07_DEltX2 D;
1815
+ D.byte = (BYTE)n; D.nbBits = (BYTE)(tableLog + 1 - w);
1816
+ for (i = rankVal[w]; i < rankVal[w] + length; i++)
1817
+ dt[i] = D;
1818
+ rankVal[w] += length;
1819
+ } }
1820
+
1821
+ return iSize;
1822
+ }
1823
+
1824
+
1825
+ static BYTE HUFv07_decodeSymbolX2(BITv07_DStream_t* Dstream, const HUFv07_DEltX2* dt, const U32 dtLog)
1826
+ {
1827
+ size_t const val = BITv07_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */
1828
+ BYTE const c = dt[val].byte;
1829
+ BITv07_skipBits(Dstream, dt[val].nbBits);
1830
+ return c;
1831
+ }
1832
+
1833
+ #define HUFv07_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \
1834
+ *ptr++ = HUFv07_decodeSymbolX2(DStreamPtr, dt, dtLog)
1835
+
1836
+ #define HUFv07_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \
1837
+ if (MEM_64bits() || (HUFv07_TABLELOG_MAX<=12)) \
1838
+ HUFv07_DECODE_SYMBOLX2_0(ptr, DStreamPtr)
1839
+
1840
+ #define HUFv07_DECODE_SYMBOLX2_2(ptr, DStreamPtr) \
1841
+ if (MEM_64bits()) \
1842
+ HUFv07_DECODE_SYMBOLX2_0(ptr, DStreamPtr)
1843
+
1844
+ static inline size_t HUFv07_decodeStreamX2(BYTE* p, BITv07_DStream_t* const bitDPtr, BYTE* const pEnd, const HUFv07_DEltX2* const dt, const U32 dtLog)
1845
+ {
1846
+ BYTE* const pStart = p;
1847
+
1848
+ /* up to 4 symbols at a time */
1849
+ while ((BITv07_reloadDStream(bitDPtr) == BITv07_DStream_unfinished) && (p <= pEnd-4)) {
1850
+ HUFv07_DECODE_SYMBOLX2_2(p, bitDPtr);
1851
+ HUFv07_DECODE_SYMBOLX2_1(p, bitDPtr);
1852
+ HUFv07_DECODE_SYMBOLX2_2(p, bitDPtr);
1853
+ HUFv07_DECODE_SYMBOLX2_0(p, bitDPtr);
1854
+ }
1855
+
1856
+ /* closer to the end */
1857
+ while ((BITv07_reloadDStream(bitDPtr) == BITv07_DStream_unfinished) && (p < pEnd))
1858
+ HUFv07_DECODE_SYMBOLX2_0(p, bitDPtr);
1859
+
1860
+ /* no more data to retrieve from bitstream, hence no need to reload */
1861
+ while (p < pEnd)
1862
+ HUFv07_DECODE_SYMBOLX2_0(p, bitDPtr);
1863
+
1864
+ return pEnd-pStart;
1865
+ }
1866
+
1867
+ static size_t HUFv07_decompress1X2_usingDTable_internal(
1868
+ void* dst, size_t dstSize,
1869
+ const void* cSrc, size_t cSrcSize,
1870
+ const HUFv07_DTable* DTable)
1871
+ {
1872
+ BYTE* op = (BYTE*)dst;
1873
+ BYTE* const oend = op + dstSize;
1874
+ const void* dtPtr = DTable + 1;
1875
+ const HUFv07_DEltX2* const dt = (const HUFv07_DEltX2*)dtPtr;
1876
+ BITv07_DStream_t bitD;
1877
+ DTableDesc const dtd = HUFv07_getDTableDesc(DTable);
1878
+ U32 const dtLog = dtd.tableLog;
1879
+
1880
+ { size_t const errorCode = BITv07_initDStream(&bitD, cSrc, cSrcSize);
1881
+ if (HUFv07_isError(errorCode)) return errorCode; }
1882
+
1883
+ HUFv07_decodeStreamX2(op, &bitD, oend, dt, dtLog);
1884
+
1885
+ /* check */
1886
+ if (!BITv07_endOfDStream(&bitD)) return ERROR(corruption_detected);
1887
+
1888
+ return dstSize;
1889
+ }
1890
+
1891
+ size_t HUFv07_decompress1X2_usingDTable(
1892
+ void* dst, size_t dstSize,
1893
+ const void* cSrc, size_t cSrcSize,
1894
+ const HUFv07_DTable* DTable)
1895
+ {
1896
+ DTableDesc dtd = HUFv07_getDTableDesc(DTable);
1897
+ if (dtd.tableType != 0) return ERROR(GENERIC);
1898
+ return HUFv07_decompress1X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);
1899
+ }
1900
+
1901
+ size_t HUFv07_decompress1X2_DCtx (HUFv07_DTable* DCtx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
1902
+ {
1903
+ const BYTE* ip = (const BYTE*) cSrc;
1904
+
1905
+ size_t const hSize = HUFv07_readDTableX2 (DCtx, cSrc, cSrcSize);
1906
+ if (HUFv07_isError(hSize)) return hSize;
1907
+ if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
1908
+ ip += hSize; cSrcSize -= hSize;
1909
+
1910
+ return HUFv07_decompress1X2_usingDTable_internal (dst, dstSize, ip, cSrcSize, DCtx);
1911
+ }
1912
+
1913
+ size_t HUFv07_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
1914
+ {
1915
+ HUFv07_CREATE_STATIC_DTABLEX2(DTable, HUFv07_TABLELOG_MAX);
1916
+ return HUFv07_decompress1X2_DCtx (DTable, dst, dstSize, cSrc, cSrcSize);
1917
+ }
1918
+
1919
+
1920
+ static size_t HUFv07_decompress4X2_usingDTable_internal(
1921
+ void* dst, size_t dstSize,
1922
+ const void* cSrc, size_t cSrcSize,
1923
+ const HUFv07_DTable* DTable)
1924
+ {
1925
+ /* Check */
1926
+ if (cSrcSize < 10) return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */
1927
+
1928
+ { const BYTE* const istart = (const BYTE*) cSrc;
1929
+ BYTE* const ostart = (BYTE*) dst;
1930
+ BYTE* const oend = ostart + dstSize;
1931
+ const void* const dtPtr = DTable + 1;
1932
+ const HUFv07_DEltX2* const dt = (const HUFv07_DEltX2*)dtPtr;
1933
+
1934
+ /* Init */
1935
+ BITv07_DStream_t bitD1;
1936
+ BITv07_DStream_t bitD2;
1937
+ BITv07_DStream_t bitD3;
1938
+ BITv07_DStream_t bitD4;
1939
+ size_t const length1 = MEM_readLE16(istart);
1940
+ size_t const length2 = MEM_readLE16(istart+2);
1941
+ size_t const length3 = MEM_readLE16(istart+4);
1942
+ size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6);
1943
+ const BYTE* const istart1 = istart + 6; /* jumpTable */
1944
+ const BYTE* const istart2 = istart1 + length1;
1945
+ const BYTE* const istart3 = istart2 + length2;
1946
+ const BYTE* const istart4 = istart3 + length3;
1947
+ const size_t segmentSize = (dstSize+3) / 4;
1948
+ BYTE* const opStart2 = ostart + segmentSize;
1949
+ BYTE* const opStart3 = opStart2 + segmentSize;
1950
+ BYTE* const opStart4 = opStart3 + segmentSize;
1951
+ BYTE* op1 = ostart;
1952
+ BYTE* op2 = opStart2;
1953
+ BYTE* op3 = opStart3;
1954
+ BYTE* op4 = opStart4;
1955
+ U32 endSignal;
1956
+ DTableDesc const dtd = HUFv07_getDTableDesc(DTable);
1957
+ U32 const dtLog = dtd.tableLog;
1958
+
1959
+ if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */
1960
+ { size_t const errorCode = BITv07_initDStream(&bitD1, istart1, length1);
1961
+ if (HUFv07_isError(errorCode)) return errorCode; }
1962
+ { size_t const errorCode = BITv07_initDStream(&bitD2, istart2, length2);
1963
+ if (HUFv07_isError(errorCode)) return errorCode; }
1964
+ { size_t const errorCode = BITv07_initDStream(&bitD3, istart3, length3);
1965
+ if (HUFv07_isError(errorCode)) return errorCode; }
1966
+ { size_t const errorCode = BITv07_initDStream(&bitD4, istart4, length4);
1967
+ if (HUFv07_isError(errorCode)) return errorCode; }
1968
+
1969
+ /* 16-32 symbols per loop (4-8 symbols per stream) */
1970
+ endSignal = BITv07_reloadDStream(&bitD1) | BITv07_reloadDStream(&bitD2) | BITv07_reloadDStream(&bitD3) | BITv07_reloadDStream(&bitD4);
1971
+ for ( ; (endSignal==BITv07_DStream_unfinished) && (op4<(oend-7)) ; ) {
1972
+ HUFv07_DECODE_SYMBOLX2_2(op1, &bitD1);
1973
+ HUFv07_DECODE_SYMBOLX2_2(op2, &bitD2);
1974
+ HUFv07_DECODE_SYMBOLX2_2(op3, &bitD3);
1975
+ HUFv07_DECODE_SYMBOLX2_2(op4, &bitD4);
1976
+ HUFv07_DECODE_SYMBOLX2_1(op1, &bitD1);
1977
+ HUFv07_DECODE_SYMBOLX2_1(op2, &bitD2);
1978
+ HUFv07_DECODE_SYMBOLX2_1(op3, &bitD3);
1979
+ HUFv07_DECODE_SYMBOLX2_1(op4, &bitD4);
1980
+ HUFv07_DECODE_SYMBOLX2_2(op1, &bitD1);
1981
+ HUFv07_DECODE_SYMBOLX2_2(op2, &bitD2);
1982
+ HUFv07_DECODE_SYMBOLX2_2(op3, &bitD3);
1983
+ HUFv07_DECODE_SYMBOLX2_2(op4, &bitD4);
1984
+ HUFv07_DECODE_SYMBOLX2_0(op1, &bitD1);
1985
+ HUFv07_DECODE_SYMBOLX2_0(op2, &bitD2);
1986
+ HUFv07_DECODE_SYMBOLX2_0(op3, &bitD3);
1987
+ HUFv07_DECODE_SYMBOLX2_0(op4, &bitD4);
1988
+ endSignal = BITv07_reloadDStream(&bitD1) | BITv07_reloadDStream(&bitD2) | BITv07_reloadDStream(&bitD3) | BITv07_reloadDStream(&bitD4);
1989
+ }
1990
+
1991
+ /* check corruption */
1992
+ if (op1 > opStart2) return ERROR(corruption_detected);
1993
+ if (op2 > opStart3) return ERROR(corruption_detected);
1994
+ if (op3 > opStart4) return ERROR(corruption_detected);
1995
+ /* note : op4 supposed already verified within main loop */
1996
+
1997
+ /* finish bitStreams one by one */
1998
+ HUFv07_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog);
1999
+ HUFv07_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog);
2000
+ HUFv07_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog);
2001
+ HUFv07_decodeStreamX2(op4, &bitD4, oend, dt, dtLog);
2002
+
2003
+ /* check */
2004
+ endSignal = BITv07_endOfDStream(&bitD1) & BITv07_endOfDStream(&bitD2) & BITv07_endOfDStream(&bitD3) & BITv07_endOfDStream(&bitD4);
2005
+ if (!endSignal) return ERROR(corruption_detected);
2006
+
2007
+ /* decoded size */
2008
+ return dstSize;
2009
+ }
2010
+ }
2011
+
2012
+
2013
+ size_t HUFv07_decompress4X2_usingDTable(
2014
+ void* dst, size_t dstSize,
2015
+ const void* cSrc, size_t cSrcSize,
2016
+ const HUFv07_DTable* DTable)
2017
+ {
2018
+ DTableDesc dtd = HUFv07_getDTableDesc(DTable);
2019
+ if (dtd.tableType != 0) return ERROR(GENERIC);
2020
+ return HUFv07_decompress4X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);
2021
+ }
2022
+
2023
+
2024
+ size_t HUFv07_decompress4X2_DCtx (HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
2025
+ {
2026
+ const BYTE* ip = (const BYTE*) cSrc;
2027
+
2028
+ size_t const hSize = HUFv07_readDTableX2 (dctx, cSrc, cSrcSize);
2029
+ if (HUFv07_isError(hSize)) return hSize;
2030
+ if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
2031
+ ip += hSize; cSrcSize -= hSize;
2032
+
2033
+ return HUFv07_decompress4X2_usingDTable_internal (dst, dstSize, ip, cSrcSize, dctx);
2034
+ }
2035
+
2036
+ size_t HUFv07_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
2037
+ {
2038
+ HUFv07_CREATE_STATIC_DTABLEX2(DTable, HUFv07_TABLELOG_MAX);
2039
+ return HUFv07_decompress4X2_DCtx(DTable, dst, dstSize, cSrc, cSrcSize);
2040
+ }
2041
+
2042
+
2043
+ /* *************************/
2044
+ /* double-symbols decoding */
2045
+ /* *************************/
2046
+ typedef struct { U16 sequence; BYTE nbBits; BYTE length; } HUFv07_DEltX4; /* double-symbols decoding */
2047
+
2048
+ typedef struct { BYTE symbol; BYTE weight; } sortedSymbol_t;
2049
+
2050
+ static void HUFv07_fillDTableX4Level2(HUFv07_DEltX4* DTable, U32 sizeLog, const U32 consumed,
2051
+ const U32* rankValOrigin, const int minWeight,
2052
+ const sortedSymbol_t* sortedSymbols, const U32 sortedListSize,
2053
+ U32 nbBitsBaseline, U16 baseSeq)
2054
+ {
2055
+ HUFv07_DEltX4 DElt;
2056
+ U32 rankVal[HUFv07_TABLELOG_ABSOLUTEMAX + 1];
2057
+
2058
+ /* get pre-calculated rankVal */
2059
+ memcpy(rankVal, rankValOrigin, sizeof(rankVal));
2060
+
2061
+ /* fill skipped values */
2062
+ if (minWeight>1) {
2063
+ U32 i, skipSize = rankVal[minWeight];
2064
+ MEM_writeLE16(&(DElt.sequence), baseSeq);
2065
+ DElt.nbBits = (BYTE)(consumed);
2066
+ DElt.length = 1;
2067
+ for (i = 0; i < skipSize; i++)
2068
+ DTable[i] = DElt;
2069
+ }
2070
+
2071
+ /* fill DTable */
2072
+ { U32 s; for (s=0; s<sortedListSize; s++) { /* note : sortedSymbols already skipped */
2073
+ const U32 symbol = sortedSymbols[s].symbol;
2074
+ const U32 weight = sortedSymbols[s].weight;
2075
+ const U32 nbBits = nbBitsBaseline - weight;
2076
+ const U32 length = 1 << (sizeLog-nbBits);
2077
+ const U32 start = rankVal[weight];
2078
+ U32 i = start;
2079
+ const U32 end = start + length;
2080
+
2081
+ MEM_writeLE16(&(DElt.sequence), (U16)(baseSeq + (symbol << 8)));
2082
+ DElt.nbBits = (BYTE)(nbBits + consumed);
2083
+ DElt.length = 2;
2084
+ do { DTable[i++] = DElt; } while (i<end); /* since length >= 1 */
2085
+
2086
+ rankVal[weight] += length;
2087
+ }}
2088
+ }
2089
+
2090
+ typedef U32 rankVal_t[HUFv07_TABLELOG_ABSOLUTEMAX][HUFv07_TABLELOG_ABSOLUTEMAX + 1];
2091
+
2092
+ static void HUFv07_fillDTableX4(HUFv07_DEltX4* DTable, const U32 targetLog,
2093
+ const sortedSymbol_t* sortedList, const U32 sortedListSize,
2094
+ const U32* rankStart, rankVal_t rankValOrigin, const U32 maxWeight,
2095
+ const U32 nbBitsBaseline)
2096
+ {
2097
+ U32 rankVal[HUFv07_TABLELOG_ABSOLUTEMAX + 1];
2098
+ const int scaleLog = nbBitsBaseline - targetLog; /* note : targetLog >= srcLog, hence scaleLog <= 1 */
2099
+ const U32 minBits = nbBitsBaseline - maxWeight;
2100
+ U32 s;
2101
+
2102
+ memcpy(rankVal, rankValOrigin, sizeof(rankVal));
2103
+
2104
+ /* fill DTable */
2105
+ for (s=0; s<sortedListSize; s++) {
2106
+ const U16 symbol = sortedList[s].symbol;
2107
+ const U32 weight = sortedList[s].weight;
2108
+ const U32 nbBits = nbBitsBaseline - weight;
2109
+ const U32 start = rankVal[weight];
2110
+ const U32 length = 1 << (targetLog-nbBits);
2111
+
2112
+ if (targetLog-nbBits >= minBits) { /* enough room for a second symbol */
2113
+ U32 sortedRank;
2114
+ int minWeight = nbBits + scaleLog;
2115
+ if (minWeight < 1) minWeight = 1;
2116
+ sortedRank = rankStart[minWeight];
2117
+ HUFv07_fillDTableX4Level2(DTable+start, targetLog-nbBits, nbBits,
2118
+ rankValOrigin[nbBits], minWeight,
2119
+ sortedList+sortedRank, sortedListSize-sortedRank,
2120
+ nbBitsBaseline, symbol);
2121
+ } else {
2122
+ HUFv07_DEltX4 DElt;
2123
+ MEM_writeLE16(&(DElt.sequence), symbol);
2124
+ DElt.nbBits = (BYTE)(nbBits);
2125
+ DElt.length = 1;
2126
+ { U32 u;
2127
+ const U32 end = start + length;
2128
+ for (u = start; u < end; u++) DTable[u] = DElt;
2129
+ } }
2130
+ rankVal[weight] += length;
2131
+ }
2132
+ }
2133
+
2134
+ size_t HUFv07_readDTableX4 (HUFv07_DTable* DTable, const void* src, size_t srcSize)
2135
+ {
2136
+ BYTE weightList[HUFv07_SYMBOLVALUE_MAX + 1];
2137
+ sortedSymbol_t sortedSymbol[HUFv07_SYMBOLVALUE_MAX + 1];
2138
+ U32 rankStats[HUFv07_TABLELOG_ABSOLUTEMAX + 1] = { 0 };
2139
+ U32 rankStart0[HUFv07_TABLELOG_ABSOLUTEMAX + 2] = { 0 };
2140
+ U32* const rankStart = rankStart0+1;
2141
+ rankVal_t rankVal;
2142
+ U32 tableLog, maxW, sizeOfSort, nbSymbols;
2143
+ DTableDesc dtd = HUFv07_getDTableDesc(DTable);
2144
+ U32 const maxTableLog = dtd.maxTableLog;
2145
+ size_t iSize;
2146
+ void* dtPtr = DTable+1; /* force compiler to avoid strict-aliasing */
2147
+ HUFv07_DEltX4* const dt = (HUFv07_DEltX4*)dtPtr;
2148
+
2149
+ HUFv07_STATIC_ASSERT(sizeof(HUFv07_DEltX4) == sizeof(HUFv07_DTable)); /* if compilation fails here, assertion is false */
2150
+ if (maxTableLog > HUFv07_TABLELOG_ABSOLUTEMAX) return ERROR(tableLog_tooLarge);
2151
+ /* memset(weightList, 0, sizeof(weightList)); */ /* is not necessary, even though some analyzer complain ... */
2152
+
2153
+ iSize = HUFv07_readStats(weightList, HUFv07_SYMBOLVALUE_MAX + 1, rankStats, &nbSymbols, &tableLog, src, srcSize);
2154
+ if (HUFv07_isError(iSize)) return iSize;
2155
+
2156
+ /* check result */
2157
+ if (tableLog > maxTableLog) return ERROR(tableLog_tooLarge); /* DTable can't fit code depth */
2158
+
2159
+ /* find maxWeight */
2160
+ for (maxW = tableLog; rankStats[maxW]==0; maxW--) {} /* necessarily finds a solution before 0 */
2161
+
2162
+ /* Get start index of each weight */
2163
+ { U32 w, nextRankStart = 0;
2164
+ for (w=1; w<maxW+1; w++) {
2165
+ U32 current = nextRankStart;
2166
+ nextRankStart += rankStats[w];
2167
+ rankStart[w] = current;
2168
+ }
2169
+ rankStart[0] = nextRankStart; /* put all 0w symbols at the end of sorted list*/
2170
+ sizeOfSort = nextRankStart;
2171
+ }
2172
+
2173
+ /* sort symbols by weight */
2174
+ { U32 s;
2175
+ for (s=0; s<nbSymbols; s++) {
2176
+ U32 const w = weightList[s];
2177
+ U32 const r = rankStart[w]++;
2178
+ sortedSymbol[r].symbol = (BYTE)s;
2179
+ sortedSymbol[r].weight = (BYTE)w;
2180
+ }
2181
+ rankStart[0] = 0; /* forget 0w symbols; this is beginning of weight(1) */
2182
+ }
2183
+
2184
+ /* Build rankVal */
2185
+ { U32* const rankVal0 = rankVal[0];
2186
+ { int const rescale = (maxTableLog-tableLog) - 1; /* tableLog <= maxTableLog */
2187
+ U32 nextRankVal = 0;
2188
+ U32 w;
2189
+ for (w=1; w<maxW+1; w++) {
2190
+ U32 current = nextRankVal;
2191
+ nextRankVal += rankStats[w] << (w+rescale);
2192
+ rankVal0[w] = current;
2193
+ } }
2194
+ { U32 const minBits = tableLog+1 - maxW;
2195
+ U32 consumed;
2196
+ for (consumed = minBits; consumed < maxTableLog - minBits + 1; consumed++) {
2197
+ U32* const rankValPtr = rankVal[consumed];
2198
+ U32 w;
2199
+ for (w = 1; w < maxW+1; w++) {
2200
+ rankValPtr[w] = rankVal0[w] >> consumed;
2201
+ } } } }
2202
+
2203
+ HUFv07_fillDTableX4(dt, maxTableLog,
2204
+ sortedSymbol, sizeOfSort,
2205
+ rankStart0, rankVal, maxW,
2206
+ tableLog+1);
2207
+
2208
+ dtd.tableLog = (BYTE)maxTableLog;
2209
+ dtd.tableType = 1;
2210
+ memcpy(DTable, &dtd, sizeof(dtd));
2211
+ return iSize;
2212
+ }
2213
+
2214
+
2215
+ static U32 HUFv07_decodeSymbolX4(void* op, BITv07_DStream_t* DStream, const HUFv07_DEltX4* dt, const U32 dtLog)
2216
+ {
2217
+ const size_t val = BITv07_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */
2218
+ memcpy(op, dt+val, 2);
2219
+ BITv07_skipBits(DStream, dt[val].nbBits);
2220
+ return dt[val].length;
2221
+ }
2222
+
2223
+ static U32 HUFv07_decodeLastSymbolX4(void* op, BITv07_DStream_t* DStream, const HUFv07_DEltX4* dt, const U32 dtLog)
2224
+ {
2225
+ const size_t val = BITv07_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */
2226
+ memcpy(op, dt+val, 1);
2227
+ if (dt[val].length==1) BITv07_skipBits(DStream, dt[val].nbBits);
2228
+ else {
2229
+ if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8)) {
2230
+ BITv07_skipBits(DStream, dt[val].nbBits);
2231
+ if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8))
2232
+ DStream->bitsConsumed = (sizeof(DStream->bitContainer)*8); /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */
2233
+ } }
2234
+ return 1;
2235
+ }
2236
+
2237
+
2238
+ #define HUFv07_DECODE_SYMBOLX4_0(ptr, DStreamPtr) \
2239
+ ptr += HUFv07_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)
2240
+
2241
+ #define HUFv07_DECODE_SYMBOLX4_1(ptr, DStreamPtr) \
2242
+ if (MEM_64bits() || (HUFv07_TABLELOG_MAX<=12)) \
2243
+ ptr += HUFv07_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)
2244
+
2245
+ #define HUFv07_DECODE_SYMBOLX4_2(ptr, DStreamPtr) \
2246
+ if (MEM_64bits()) \
2247
+ ptr += HUFv07_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)
2248
+
2249
+ static inline size_t HUFv07_decodeStreamX4(BYTE* p, BITv07_DStream_t* bitDPtr, BYTE* const pEnd, const HUFv07_DEltX4* const dt, const U32 dtLog)
2250
+ {
2251
+ BYTE* const pStart = p;
2252
+
2253
+ /* up to 8 symbols at a time */
2254
+ while ((BITv07_reloadDStream(bitDPtr) == BITv07_DStream_unfinished) && (p < pEnd-7)) {
2255
+ HUFv07_DECODE_SYMBOLX4_2(p, bitDPtr);
2256
+ HUFv07_DECODE_SYMBOLX4_1(p, bitDPtr);
2257
+ HUFv07_DECODE_SYMBOLX4_2(p, bitDPtr);
2258
+ HUFv07_DECODE_SYMBOLX4_0(p, bitDPtr);
2259
+ }
2260
+
2261
+ /* closer to end : up to 2 symbols at a time */
2262
+ while ((BITv07_reloadDStream(bitDPtr) == BITv07_DStream_unfinished) && (p <= pEnd-2))
2263
+ HUFv07_DECODE_SYMBOLX4_0(p, bitDPtr);
2264
+
2265
+ while (p <= pEnd-2)
2266
+ HUFv07_DECODE_SYMBOLX4_0(p, bitDPtr); /* no need to reload : reached the end of DStream */
2267
+
2268
+ if (p < pEnd)
2269
+ p += HUFv07_decodeLastSymbolX4(p, bitDPtr, dt, dtLog);
2270
+
2271
+ return p-pStart;
2272
+ }
2273
+
2274
+
2275
+ static size_t HUFv07_decompress1X4_usingDTable_internal(
2276
+ void* dst, size_t dstSize,
2277
+ const void* cSrc, size_t cSrcSize,
2278
+ const HUFv07_DTable* DTable)
2279
+ {
2280
+ BITv07_DStream_t bitD;
2281
+
2282
+ /* Init */
2283
+ { size_t const errorCode = BITv07_initDStream(&bitD, cSrc, cSrcSize);
2284
+ if (HUFv07_isError(errorCode)) return errorCode;
2285
+ }
2286
+
2287
+ /* decode */
2288
+ { BYTE* const ostart = (BYTE*) dst;
2289
+ BYTE* const oend = ostart + dstSize;
2290
+ const void* const dtPtr = DTable+1; /* force compiler to not use strict-aliasing */
2291
+ const HUFv07_DEltX4* const dt = (const HUFv07_DEltX4*)dtPtr;
2292
+ DTableDesc const dtd = HUFv07_getDTableDesc(DTable);
2293
+ HUFv07_decodeStreamX4(ostart, &bitD, oend, dt, dtd.tableLog);
2294
+ }
2295
+
2296
+ /* check */
2297
+ if (!BITv07_endOfDStream(&bitD)) return ERROR(corruption_detected);
2298
+
2299
+ /* decoded size */
2300
+ return dstSize;
2301
+ }
2302
+
2303
+ size_t HUFv07_decompress1X4_usingDTable(
2304
+ void* dst, size_t dstSize,
2305
+ const void* cSrc, size_t cSrcSize,
2306
+ const HUFv07_DTable* DTable)
2307
+ {
2308
+ DTableDesc dtd = HUFv07_getDTableDesc(DTable);
2309
+ if (dtd.tableType != 1) return ERROR(GENERIC);
2310
+ return HUFv07_decompress1X4_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);
2311
+ }
2312
+
2313
+ size_t HUFv07_decompress1X4_DCtx (HUFv07_DTable* DCtx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
2314
+ {
2315
+ const BYTE* ip = (const BYTE*) cSrc;
2316
+
2317
+ size_t const hSize = HUFv07_readDTableX4 (DCtx, cSrc, cSrcSize);
2318
+ if (HUFv07_isError(hSize)) return hSize;
2319
+ if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
2320
+ ip += hSize; cSrcSize -= hSize;
2321
+
2322
+ return HUFv07_decompress1X4_usingDTable_internal (dst, dstSize, ip, cSrcSize, DCtx);
2323
+ }
2324
+
2325
+ size_t HUFv07_decompress1X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
2326
+ {
2327
+ HUFv07_CREATE_STATIC_DTABLEX4(DTable, HUFv07_TABLELOG_MAX);
2328
+ return HUFv07_decompress1X4_DCtx(DTable, dst, dstSize, cSrc, cSrcSize);
2329
+ }
2330
+
2331
+ static size_t HUFv07_decompress4X4_usingDTable_internal(
2332
+ void* dst, size_t dstSize,
2333
+ const void* cSrc, size_t cSrcSize,
2334
+ const HUFv07_DTable* DTable)
2335
+ {
2336
+ if (cSrcSize < 10) return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */
2337
+
2338
+ { const BYTE* const istart = (const BYTE*) cSrc;
2339
+ BYTE* const ostart = (BYTE*) dst;
2340
+ BYTE* const oend = ostart + dstSize;
2341
+ const void* const dtPtr = DTable+1;
2342
+ const HUFv07_DEltX4* const dt = (const HUFv07_DEltX4*)dtPtr;
2343
+
2344
+ /* Init */
2345
+ BITv07_DStream_t bitD1;
2346
+ BITv07_DStream_t bitD2;
2347
+ BITv07_DStream_t bitD3;
2348
+ BITv07_DStream_t bitD4;
2349
+ size_t const length1 = MEM_readLE16(istart);
2350
+ size_t const length2 = MEM_readLE16(istart+2);
2351
+ size_t const length3 = MEM_readLE16(istart+4);
2352
+ size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6);
2353
+ const BYTE* const istart1 = istart + 6; /* jumpTable */
2354
+ const BYTE* const istart2 = istart1 + length1;
2355
+ const BYTE* const istart3 = istart2 + length2;
2356
+ const BYTE* const istart4 = istart3 + length3;
2357
+ size_t const segmentSize = (dstSize+3) / 4;
2358
+ BYTE* const opStart2 = ostart + segmentSize;
2359
+ BYTE* const opStart3 = opStart2 + segmentSize;
2360
+ BYTE* const opStart4 = opStart3 + segmentSize;
2361
+ BYTE* op1 = ostart;
2362
+ BYTE* op2 = opStart2;
2363
+ BYTE* op3 = opStart3;
2364
+ BYTE* op4 = opStart4;
2365
+ U32 endSignal;
2366
+ DTableDesc const dtd = HUFv07_getDTableDesc(DTable);
2367
+ U32 const dtLog = dtd.tableLog;
2368
+
2369
+ if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */
2370
+ { size_t const errorCode = BITv07_initDStream(&bitD1, istart1, length1);
2371
+ if (HUFv07_isError(errorCode)) return errorCode; }
2372
+ { size_t const errorCode = BITv07_initDStream(&bitD2, istart2, length2);
2373
+ if (HUFv07_isError(errorCode)) return errorCode; }
2374
+ { size_t const errorCode = BITv07_initDStream(&bitD3, istart3, length3);
2375
+ if (HUFv07_isError(errorCode)) return errorCode; }
2376
+ { size_t const errorCode = BITv07_initDStream(&bitD4, istart4, length4);
2377
+ if (HUFv07_isError(errorCode)) return errorCode; }
2378
+
2379
+ /* 16-32 symbols per loop (4-8 symbols per stream) */
2380
+ endSignal = BITv07_reloadDStream(&bitD1) | BITv07_reloadDStream(&bitD2) | BITv07_reloadDStream(&bitD3) | BITv07_reloadDStream(&bitD4);
2381
+ for ( ; (endSignal==BITv07_DStream_unfinished) && (op4<(oend-7)) ; ) {
2382
+ HUFv07_DECODE_SYMBOLX4_2(op1, &bitD1);
2383
+ HUFv07_DECODE_SYMBOLX4_2(op2, &bitD2);
2384
+ HUFv07_DECODE_SYMBOLX4_2(op3, &bitD3);
2385
+ HUFv07_DECODE_SYMBOLX4_2(op4, &bitD4);
2386
+ HUFv07_DECODE_SYMBOLX4_1(op1, &bitD1);
2387
+ HUFv07_DECODE_SYMBOLX4_1(op2, &bitD2);
2388
+ HUFv07_DECODE_SYMBOLX4_1(op3, &bitD3);
2389
+ HUFv07_DECODE_SYMBOLX4_1(op4, &bitD4);
2390
+ HUFv07_DECODE_SYMBOLX4_2(op1, &bitD1);
2391
+ HUFv07_DECODE_SYMBOLX4_2(op2, &bitD2);
2392
+ HUFv07_DECODE_SYMBOLX4_2(op3, &bitD3);
2393
+ HUFv07_DECODE_SYMBOLX4_2(op4, &bitD4);
2394
+ HUFv07_DECODE_SYMBOLX4_0(op1, &bitD1);
2395
+ HUFv07_DECODE_SYMBOLX4_0(op2, &bitD2);
2396
+ HUFv07_DECODE_SYMBOLX4_0(op3, &bitD3);
2397
+ HUFv07_DECODE_SYMBOLX4_0(op4, &bitD4);
2398
+
2399
+ endSignal = BITv07_reloadDStream(&bitD1) | BITv07_reloadDStream(&bitD2) | BITv07_reloadDStream(&bitD3) | BITv07_reloadDStream(&bitD4);
2400
+ }
2401
+
2402
+ /* check corruption */
2403
+ if (op1 > opStart2) return ERROR(corruption_detected);
2404
+ if (op2 > opStart3) return ERROR(corruption_detected);
2405
+ if (op3 > opStart4) return ERROR(corruption_detected);
2406
+ /* note : op4 supposed already verified within main loop */
2407
+
2408
+ /* finish bitStreams one by one */
2409
+ HUFv07_decodeStreamX4(op1, &bitD1, opStart2, dt, dtLog);
2410
+ HUFv07_decodeStreamX4(op2, &bitD2, opStart3, dt, dtLog);
2411
+ HUFv07_decodeStreamX4(op3, &bitD3, opStart4, dt, dtLog);
2412
+ HUFv07_decodeStreamX4(op4, &bitD4, oend, dt, dtLog);
2413
+
2414
+ /* check */
2415
+ { U32 const endCheck = BITv07_endOfDStream(&bitD1) & BITv07_endOfDStream(&bitD2) & BITv07_endOfDStream(&bitD3) & BITv07_endOfDStream(&bitD4);
2416
+ if (!endCheck) return ERROR(corruption_detected); }
2417
+
2418
+ /* decoded size */
2419
+ return dstSize;
2420
+ }
2421
+ }
2422
+
2423
+
2424
+ size_t HUFv07_decompress4X4_usingDTable(
2425
+ void* dst, size_t dstSize,
2426
+ const void* cSrc, size_t cSrcSize,
2427
+ const HUFv07_DTable* DTable)
2428
+ {
2429
+ DTableDesc dtd = HUFv07_getDTableDesc(DTable);
2430
+ if (dtd.tableType != 1) return ERROR(GENERIC);
2431
+ return HUFv07_decompress4X4_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);
2432
+ }
2433
+
2434
+
2435
+ size_t HUFv07_decompress4X4_DCtx (HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
2436
+ {
2437
+ const BYTE* ip = (const BYTE*) cSrc;
2438
+
2439
+ size_t hSize = HUFv07_readDTableX4 (dctx, cSrc, cSrcSize);
2440
+ if (HUFv07_isError(hSize)) return hSize;
2441
+ if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
2442
+ ip += hSize; cSrcSize -= hSize;
2443
+
2444
+ return HUFv07_decompress4X4_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx);
2445
+ }
2446
+
2447
+ size_t HUFv07_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
2448
+ {
2449
+ HUFv07_CREATE_STATIC_DTABLEX4(DTable, HUFv07_TABLELOG_MAX);
2450
+ return HUFv07_decompress4X4_DCtx(DTable, dst, dstSize, cSrc, cSrcSize);
2451
+ }
2452
+
2453
+
2454
+ /* ********************************/
2455
+ /* Generic decompression selector */
2456
+ /* ********************************/
2457
+
2458
+ size_t HUFv07_decompress1X_usingDTable(void* dst, size_t maxDstSize,
2459
+ const void* cSrc, size_t cSrcSize,
2460
+ const HUFv07_DTable* DTable)
2461
+ {
2462
+ DTableDesc const dtd = HUFv07_getDTableDesc(DTable);
2463
+ return dtd.tableType ? HUFv07_decompress1X4_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable) :
2464
+ HUFv07_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable);
2465
+ }
2466
+
2467
+ size_t HUFv07_decompress4X_usingDTable(void* dst, size_t maxDstSize,
2468
+ const void* cSrc, size_t cSrcSize,
2469
+ const HUFv07_DTable* DTable)
2470
+ {
2471
+ DTableDesc const dtd = HUFv07_getDTableDesc(DTable);
2472
+ return dtd.tableType ? HUFv07_decompress4X4_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable) :
2473
+ HUFv07_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable);
2474
+ }
2475
+
2476
+
2477
+ typedef struct { U32 tableTime; U32 decode256Time; } algo_time_t;
2478
+ static const algo_time_t algoTime[16 /* Quantization */][3 /* single, double, quad */] =
2479
+ {
2480
+ /* single, double, quad */
2481
+ {{0,0}, {1,1}, {2,2}}, /* Q==0 : impossible */
2482
+ {{0,0}, {1,1}, {2,2}}, /* Q==1 : impossible */
2483
+ {{ 38,130}, {1313, 74}, {2151, 38}}, /* Q == 2 : 12-18% */
2484
+ {{ 448,128}, {1353, 74}, {2238, 41}}, /* Q == 3 : 18-25% */
2485
+ {{ 556,128}, {1353, 74}, {2238, 47}}, /* Q == 4 : 25-32% */
2486
+ {{ 714,128}, {1418, 74}, {2436, 53}}, /* Q == 5 : 32-38% */
2487
+ {{ 883,128}, {1437, 74}, {2464, 61}}, /* Q == 6 : 38-44% */
2488
+ {{ 897,128}, {1515, 75}, {2622, 68}}, /* Q == 7 : 44-50% */
2489
+ {{ 926,128}, {1613, 75}, {2730, 75}}, /* Q == 8 : 50-56% */
2490
+ {{ 947,128}, {1729, 77}, {3359, 77}}, /* Q == 9 : 56-62% */
2491
+ {{1107,128}, {2083, 81}, {4006, 84}}, /* Q ==10 : 62-69% */
2492
+ {{1177,128}, {2379, 87}, {4785, 88}}, /* Q ==11 : 69-75% */
2493
+ {{1242,128}, {2415, 93}, {5155, 84}}, /* Q ==12 : 75-81% */
2494
+ {{1349,128}, {2644,106}, {5260,106}}, /* Q ==13 : 81-87% */
2495
+ {{1455,128}, {2422,124}, {4174,124}}, /* Q ==14 : 87-93% */
2496
+ {{ 722,128}, {1891,145}, {1936,146}}, /* Q ==15 : 93-99% */
2497
+ };
2498
+
2499
+ /** HUFv07_selectDecoder() :
2500
+ * Tells which decoder is likely to decode faster,
2501
+ * based on a set of pre-determined metrics.
2502
+ * @return : 0==HUFv07_decompress4X2, 1==HUFv07_decompress4X4 .
2503
+ * Assumption : 0 < cSrcSize < dstSize <= 128 KB */
2504
+ U32 HUFv07_selectDecoder (size_t dstSize, size_t cSrcSize)
2505
+ {
2506
+ /* decoder timing evaluation */
2507
+ U32 const Q = (U32)(cSrcSize * 16 / dstSize); /* Q < 16 since dstSize > cSrcSize */
2508
+ U32 const D256 = (U32)(dstSize >> 8);
2509
+ U32 const DTime0 = algoTime[Q][0].tableTime + (algoTime[Q][0].decode256Time * D256);
2510
+ U32 DTime1 = algoTime[Q][1].tableTime + (algoTime[Q][1].decode256Time * D256);
2511
+ DTime1 += DTime1 >> 3; /* advantage to algorithm using less memory, for cache eviction */
2512
+
2513
+ return DTime1 < DTime0;
2514
+ }
2515
+
2516
+
2517
+ typedef size_t (*decompressionAlgo)(void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);
2518
+
2519
+ size_t HUFv07_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
2520
+ {
2521
+ static const decompressionAlgo decompress[2] = { HUFv07_decompress4X2, HUFv07_decompress4X4 };
2522
+
2523
+ /* validation checks */
2524
+ if (dstSize == 0) return ERROR(dstSize_tooSmall);
2525
+ if (cSrcSize > dstSize) return ERROR(corruption_detected); /* invalid */
2526
+ if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; } /* not compressed */
2527
+ if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */
2528
+
2529
+ { U32 const algoNb = HUFv07_selectDecoder(dstSize, cSrcSize);
2530
+ return decompress[algoNb](dst, dstSize, cSrc, cSrcSize);
2531
+ }
2532
+
2533
+ /* return HUFv07_decompress4X2(dst, dstSize, cSrc, cSrcSize); */ /* multi-streams single-symbol decoding */
2534
+ /* return HUFv07_decompress4X4(dst, dstSize, cSrc, cSrcSize); */ /* multi-streams double-symbols decoding */
2535
+ }
2536
+
2537
+ size_t HUFv07_decompress4X_DCtx (HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
2538
+ {
2539
+ /* validation checks */
2540
+ if (dstSize == 0) return ERROR(dstSize_tooSmall);
2541
+ if (cSrcSize > dstSize) return ERROR(corruption_detected); /* invalid */
2542
+ if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; } /* not compressed */
2543
+ if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */
2544
+
2545
+ { U32 const algoNb = HUFv07_selectDecoder(dstSize, cSrcSize);
2546
+ return algoNb ? HUFv07_decompress4X4_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) :
2547
+ HUFv07_decompress4X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) ;
2548
+ }
2549
+ }
2550
+
2551
+ size_t HUFv07_decompress4X_hufOnly (HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
2552
+ {
2553
+ /* validation checks */
2554
+ if (dstSize == 0) return ERROR(dstSize_tooSmall);
2555
+ if ((cSrcSize >= dstSize) || (cSrcSize <= 1)) return ERROR(corruption_detected); /* invalid */
2556
+
2557
+ { U32 const algoNb = HUFv07_selectDecoder(dstSize, cSrcSize);
2558
+ return algoNb ? HUFv07_decompress4X4_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) :
2559
+ HUFv07_decompress4X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) ;
2560
+ }
2561
+ }
2562
+
2563
+ size_t HUFv07_decompress1X_DCtx (HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
2564
+ {
2565
+ /* validation checks */
2566
+ if (dstSize == 0) return ERROR(dstSize_tooSmall);
2567
+ if (cSrcSize > dstSize) return ERROR(corruption_detected); /* invalid */
2568
+ if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; } /* not compressed */
2569
+ if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */
2570
+
2571
+ { U32 const algoNb = HUFv07_selectDecoder(dstSize, cSrcSize);
2572
+ return algoNb ? HUFv07_decompress1X4_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) :
2573
+ HUFv07_decompress1X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) ;
2574
+ }
2575
+ }
2576
+ /*
2577
+ Common functions of Zstd compression library
2578
+ Copyright (C) 2015-2016, Yann Collet.
2579
+
2580
+ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
2581
+
2582
+ Redistribution and use in source and binary forms, with or without
2583
+ modification, are permitted provided that the following conditions are
2584
+ met:
2585
+ * Redistributions of source code must retain the above copyright
2586
+ notice, this list of conditions and the following disclaimer.
2587
+ * Redistributions in binary form must reproduce the above
2588
+ copyright notice, this list of conditions and the following disclaimer
2589
+ in the documentation and/or other materials provided with the
2590
+ distribution.
2591
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2592
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2593
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2594
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2595
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2596
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2597
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2598
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2599
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2600
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2601
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2602
+
2603
+ You can contact the author at :
2604
+ - zstd homepage : http://www.zstd.net/
2605
+ */
2606
+
2607
+
2608
+
2609
+ /*-****************************************
2610
+ * ZSTD Error Management
2611
+ ******************************************/
2612
+ /*! ZSTDv07_isError() :
2613
+ * tells if a return value is an error code */
2614
+ unsigned ZSTDv07_isError(size_t code) { return ERR_isError(code); }
2615
+
2616
+ /*! ZSTDv07_getErrorName() :
2617
+ * provides error code string from function result (useful for debugging) */
2618
+ const char* ZSTDv07_getErrorName(size_t code) { return ERR_getErrorName(code); }
2619
+
2620
+
2621
+
2622
+ /* **************************************************************
2623
+ * ZBUFF Error Management
2624
+ ****************************************************************/
2625
+ unsigned ZBUFFv07_isError(size_t errorCode) { return ERR_isError(errorCode); }
2626
+
2627
+ const char* ZBUFFv07_getErrorName(size_t errorCode) { return ERR_getErrorName(errorCode); }
2628
+
2629
+
2630
+
2631
+ static void* ZSTDv07_defaultAllocFunction(void* opaque, size_t size)
2632
+ {
2633
+ void* address = malloc(size);
2634
+ (void)opaque;
2635
+ /* printf("alloc %p, %d opaque=%p \n", address, (int)size, opaque); */
2636
+ return address;
2637
+ }
2638
+
2639
+ static void ZSTDv07_defaultFreeFunction(void* opaque, void* address)
2640
+ {
2641
+ (void)opaque;
2642
+ /* if (address) printf("free %p opaque=%p \n", address, opaque); */
2643
+ free(address);
2644
+ }
2645
+ /*
2646
+ zstd_internal - common functions to include
2647
+ Header File for include
2648
+ Copyright (C) 2014-2016, Yann Collet.
2649
+
2650
+ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
2651
+
2652
+ Redistribution and use in source and binary forms, with or without
2653
+ modification, are permitted provided that the following conditions are
2654
+ met:
2655
+ * Redistributions of source code must retain the above copyright
2656
+ notice, this list of conditions and the following disclaimer.
2657
+ * Redistributions in binary form must reproduce the above
2658
+ copyright notice, this list of conditions and the following disclaimer
2659
+ in the documentation and/or other materials provided with the
2660
+ distribution.
2661
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2662
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2663
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2664
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2665
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2666
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2667
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2668
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2669
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2670
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2671
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2672
+
2673
+ You can contact the author at :
2674
+ - zstd homepage : https://www.zstd.net
2675
+ */
2676
+ #ifndef ZSTDv07_CCOMMON_H_MODULE
2677
+ #define ZSTDv07_CCOMMON_H_MODULE
2678
+
2679
+
2680
+ /*-*************************************
2681
+ * Common macros
2682
+ ***************************************/
2683
+ #define MIN(a,b) ((a)<(b) ? (a) : (b))
2684
+ #define MAX(a,b) ((a)>(b) ? (a) : (b))
2685
+
2686
+
2687
+ /*-*************************************
2688
+ * Common constants
2689
+ ***************************************/
2690
+ #define ZSTDv07_OPT_NUM (1<<12)
2691
+ #define ZSTDv07_DICT_MAGIC 0xEC30A437 /* v0.7 */
2692
+
2693
+ #define ZSTDv07_REP_NUM 3
2694
+ #define ZSTDv07_REP_INIT ZSTDv07_REP_NUM
2695
+ #define ZSTDv07_REP_MOVE (ZSTDv07_REP_NUM-1)
2696
+ static const U32 repStartValue[ZSTDv07_REP_NUM] = { 1, 4, 8 };
2697
+
2698
+ #define KB *(1 <<10)
2699
+ #define MB *(1 <<20)
2700
+ #define GB *(1U<<30)
2701
+
2702
+ #define BIT7 128
2703
+ #define BIT6 64
2704
+ #define BIT5 32
2705
+ #define BIT4 16
2706
+ #define BIT1 2
2707
+ #define BIT0 1
2708
+
2709
+ #define ZSTDv07_WINDOWLOG_ABSOLUTEMIN 10
2710
+ static const size_t ZSTDv07_fcs_fieldSize[4] = { 0, 2, 4, 8 };
2711
+ static const size_t ZSTDv07_did_fieldSize[4] = { 0, 1, 2, 4 };
2712
+
2713
+ #define ZSTDv07_BLOCKHEADERSIZE 3 /* C standard doesn't allow `static const` variable to be init using another `static const` variable */
2714
+ static const size_t ZSTDv07_blockHeaderSize = ZSTDv07_BLOCKHEADERSIZE;
2715
+ typedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t;
2716
+
2717
+ #define MIN_SEQUENCES_SIZE 1 /* nbSeq==0 */
2718
+ #define MIN_CBLOCK_SIZE (1 /*litCSize*/ + 1 /* RLE or RAW */ + MIN_SEQUENCES_SIZE /* nbSeq==0 */) /* for a non-null block */
2719
+
2720
+ #define HufLog 12
2721
+ typedef enum { lbt_huffman, lbt_repeat, lbt_raw, lbt_rle } litBlockType_t;
2722
+
2723
+ #define LONGNBSEQ 0x7F00
2724
+
2725
+ #define MINMATCH 3
2726
+ #define EQUAL_READ32 4
2727
+
2728
+ #define Litbits 8
2729
+ #define MaxLit ((1<<Litbits) - 1)
2730
+ #define MaxML 52
2731
+ #define MaxLL 35
2732
+ #define MaxOff 28
2733
+ #define MaxSeq MAX(MaxLL, MaxML) /* Assumption : MaxOff < MaxLL,MaxML */
2734
+ #define MLFSELog 9
2735
+ #define LLFSELog 9
2736
+ #define OffFSELog 8
2737
+
2738
+ #define FSEv07_ENCODING_RAW 0
2739
+ #define FSEv07_ENCODING_RLE 1
2740
+ #define FSEv07_ENCODING_STATIC 2
2741
+ #define FSEv07_ENCODING_DYNAMIC 3
2742
+
2743
+ #define ZSTD_CONTENTSIZE_ERROR (0ULL - 2)
2744
+
2745
+ static const U32 LL_bits[MaxLL+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2746
+ 1, 1, 1, 1, 2, 2, 3, 3, 4, 6, 7, 8, 9,10,11,12,
2747
+ 13,14,15,16 };
2748
+ static const S16 LL_defaultNorm[MaxLL+1] = { 4, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1,
2749
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 1, 1, 1, 1, 1,
2750
+ -1,-1,-1,-1 };
2751
+ static const U32 LL_defaultNormLog = 6;
2752
+
2753
+ static const U32 ML_bits[MaxML+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2754
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2755
+ 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 7, 8, 9,10,11,
2756
+ 12,13,14,15,16 };
2757
+ static const S16 ML_defaultNorm[MaxML+1] = { 1, 4, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
2758
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2759
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,-1,-1,
2760
+ -1,-1,-1,-1,-1 };
2761
+ static const U32 ML_defaultNormLog = 6;
2762
+
2763
+ static const S16 OF_defaultNorm[MaxOff+1] = { 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
2764
+ 1, 1, 1, 1, 1, 1, 1, 1,-1,-1,-1,-1,-1 };
2765
+ static const U32 OF_defaultNormLog = 5;
2766
+
2767
+
2768
+ /*-*******************************************
2769
+ * Shared functions to include for inlining
2770
+ *********************************************/
2771
+ static void ZSTDv07_copy8(void* dst, const void* src) { memcpy(dst, src, 8); }
2772
+ #define COPY8(d,s) { ZSTDv07_copy8(d,s); d+=8; s+=8; }
2773
+
2774
+ /*! ZSTDv07_wildcopy() :
2775
+ * custom version of memcpy(), can copy up to 7 bytes too many (8 bytes if length==0) */
2776
+ #define WILDCOPY_OVERLENGTH 8
2777
+ MEM_STATIC void ZSTDv07_wildcopy(void* dst, const void* src, ptrdiff_t length)
2778
+ {
2779
+ const BYTE* ip = (const BYTE*)src;
2780
+ BYTE* op = (BYTE*)dst;
2781
+ BYTE* const oend = op + length;
2782
+ do
2783
+ COPY8(op, ip)
2784
+ while (op < oend);
2785
+ }
2786
+
2787
+
2788
+ /*-*******************************************
2789
+ * Private interfaces
2790
+ *********************************************/
2791
+ typedef struct ZSTDv07_stats_s ZSTDv07_stats_t;
2792
+
2793
+ typedef struct {
2794
+ U32 off;
2795
+ U32 len;
2796
+ } ZSTDv07_match_t;
2797
+
2798
+ typedef struct {
2799
+ U32 price;
2800
+ U32 off;
2801
+ U32 mlen;
2802
+ U32 litlen;
2803
+ U32 rep[ZSTDv07_REP_INIT];
2804
+ } ZSTDv07_optimal_t;
2805
+
2806
+ struct ZSTDv07_stats_s { U32 unused; };
2807
+
2808
+ typedef struct {
2809
+ void* buffer;
2810
+ U32* offsetStart;
2811
+ U32* offset;
2812
+ BYTE* offCodeStart;
2813
+ BYTE* litStart;
2814
+ BYTE* lit;
2815
+ U16* litLengthStart;
2816
+ U16* litLength;
2817
+ BYTE* llCodeStart;
2818
+ U16* matchLengthStart;
2819
+ U16* matchLength;
2820
+ BYTE* mlCodeStart;
2821
+ U32 longLengthID; /* 0 == no longLength; 1 == Lit.longLength; 2 == Match.longLength; */
2822
+ U32 longLengthPos;
2823
+ /* opt */
2824
+ ZSTDv07_optimal_t* priceTable;
2825
+ ZSTDv07_match_t* matchTable;
2826
+ U32* matchLengthFreq;
2827
+ U32* litLengthFreq;
2828
+ U32* litFreq;
2829
+ U32* offCodeFreq;
2830
+ U32 matchLengthSum;
2831
+ U32 matchSum;
2832
+ U32 litLengthSum;
2833
+ U32 litSum;
2834
+ U32 offCodeSum;
2835
+ U32 log2matchLengthSum;
2836
+ U32 log2matchSum;
2837
+ U32 log2litLengthSum;
2838
+ U32 log2litSum;
2839
+ U32 log2offCodeSum;
2840
+ U32 factor;
2841
+ U32 cachedPrice;
2842
+ U32 cachedLitLength;
2843
+ const BYTE* cachedLiterals;
2844
+ ZSTDv07_stats_t stats;
2845
+ } seqStore_t;
2846
+
2847
+ void ZSTDv07_seqToCodes(const seqStore_t* seqStorePtr, size_t const nbSeq);
2848
+
2849
+ /* custom memory allocation functions */
2850
+ static const ZSTDv07_customMem defaultCustomMem = { ZSTDv07_defaultAllocFunction, ZSTDv07_defaultFreeFunction, NULL };
2851
+
2852
+ #endif /* ZSTDv07_CCOMMON_H_MODULE */
2853
+ /*
2854
+ zstd - standard compression library
2855
+ Copyright (C) 2014-2016, Yann Collet.
2856
+
2857
+ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
2858
+
2859
+ Redistribution and use in source and binary forms, with or without
2860
+ modification, are permitted provided that the following conditions are
2861
+ met:
2862
+ * Redistributions of source code must retain the above copyright
2863
+ notice, this list of conditions and the following disclaimer.
2864
+ * Redistributions in binary form must reproduce the above
2865
+ copyright notice, this list of conditions and the following disclaimer
2866
+ in the documentation and/or other materials provided with the
2867
+ distribution.
2868
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2869
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2870
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2871
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2872
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2873
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2874
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2875
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2876
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2877
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2878
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2879
+
2880
+ You can contact the author at :
2881
+ - zstd homepage : http://www.zstd.net
2882
+ */
2883
+
2884
+ /* ***************************************************************
2885
+ * Tuning parameters
2886
+ *****************************************************************/
2887
+ /*!
2888
+ * HEAPMODE :
2889
+ * Select how default decompression function ZSTDv07_decompress() will allocate memory,
2890
+ * in memory stack (0), or in memory heap (1, requires malloc())
2891
+ */
2892
+ #ifndef ZSTDv07_HEAPMODE
2893
+ # define ZSTDv07_HEAPMODE 1
2894
+ #endif
2895
+
2896
+
2897
+ /*-*******************************************************
2898
+ * Compiler specifics
2899
+ *********************************************************/
2900
+ #ifdef _MSC_VER /* Visual Studio */
2901
+ # include <intrin.h> /* For Visual 2005 */
2902
+ # pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
2903
+ # pragma warning(disable : 4324) /* disable: C4324: padded structure */
2904
+ # pragma warning(disable : 4100) /* disable: C4100: unreferenced formal parameter */
2905
+ #endif
2906
+
2907
+
2908
+ /*-*************************************
2909
+ * Macros
2910
+ ***************************************/
2911
+ #define ZSTDv07_isError ERR_isError /* for inlining */
2912
+ #define FSEv07_isError ERR_isError
2913
+ #define HUFv07_isError ERR_isError
2914
+
2915
+
2916
+ /*_*******************************************************
2917
+ * Memory operations
2918
+ **********************************************************/
2919
+ static void ZSTDv07_copy4(void* dst, const void* src) { memcpy(dst, src, 4); }
2920
+
2921
+
2922
+ /*-*************************************************************
2923
+ * Context management
2924
+ ***************************************************************/
2925
+ typedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader,
2926
+ ZSTDds_decodeBlockHeader, ZSTDds_decompressBlock,
2927
+ ZSTDds_decodeSkippableHeader, ZSTDds_skipFrame } ZSTDv07_dStage;
2928
+
2929
+ struct ZSTDv07_DCtx_s
2930
+ {
2931
+ FSEv07_DTable LLTable[FSEv07_DTABLE_SIZE_U32(LLFSELog)];
2932
+ FSEv07_DTable OffTable[FSEv07_DTABLE_SIZE_U32(OffFSELog)];
2933
+ FSEv07_DTable MLTable[FSEv07_DTABLE_SIZE_U32(MLFSELog)];
2934
+ HUFv07_DTable hufTable[HUFv07_DTABLE_SIZE(HufLog)]; /* can accommodate HUFv07_decompress4X */
2935
+ const void* previousDstEnd;
2936
+ const void* base;
2937
+ const void* vBase;
2938
+ const void* dictEnd;
2939
+ size_t expected;
2940
+ U32 rep[3];
2941
+ ZSTDv07_frameParams fParams;
2942
+ blockType_t bType; /* used in ZSTDv07_decompressContinue(), to transfer blockType between header decoding and block decoding stages */
2943
+ ZSTDv07_dStage stage;
2944
+ U32 litEntropy;
2945
+ U32 fseEntropy;
2946
+ XXH64_state_t xxhState;
2947
+ size_t headerSize;
2948
+ U32 dictID;
2949
+ const BYTE* litPtr;
2950
+ ZSTDv07_customMem customMem;
2951
+ size_t litSize;
2952
+ BYTE litBuffer[ZSTDv07_BLOCKSIZE_ABSOLUTEMAX + WILDCOPY_OVERLENGTH];
2953
+ BYTE headerBuffer[ZSTDv07_FRAMEHEADERSIZE_MAX];
2954
+ }; /* typedef'd to ZSTDv07_DCtx within "zstd_static.h" */
2955
+
2956
+ int ZSTDv07_isSkipFrame(ZSTDv07_DCtx* dctx);
2957
+
2958
+ size_t ZSTDv07_sizeofDCtx (const ZSTDv07_DCtx* dctx) { return sizeof(*dctx); }
2959
+
2960
+ size_t ZSTDv07_estimateDCtxSize(void) { return sizeof(ZSTDv07_DCtx); }
2961
+
2962
+ size_t ZSTDv07_decompressBegin(ZSTDv07_DCtx* dctx)
2963
+ {
2964
+ dctx->expected = ZSTDv07_frameHeaderSize_min;
2965
+ dctx->stage = ZSTDds_getFrameHeaderSize;
2966
+ dctx->previousDstEnd = NULL;
2967
+ dctx->base = NULL;
2968
+ dctx->vBase = NULL;
2969
+ dctx->dictEnd = NULL;
2970
+ dctx->hufTable[0] = (HUFv07_DTable)((HufLog)*0x1000001);
2971
+ dctx->litEntropy = dctx->fseEntropy = 0;
2972
+ dctx->dictID = 0;
2973
+ { int i; for (i=0; i<ZSTDv07_REP_NUM; i++) dctx->rep[i] = repStartValue[i]; }
2974
+ return 0;
2975
+ }
2976
+
2977
+ ZSTDv07_DCtx* ZSTDv07_createDCtx_advanced(ZSTDv07_customMem customMem)
2978
+ {
2979
+ ZSTDv07_DCtx* dctx;
2980
+
2981
+ if (!customMem.customAlloc && !customMem.customFree)
2982
+ customMem = defaultCustomMem;
2983
+
2984
+ if (!customMem.customAlloc || !customMem.customFree)
2985
+ return NULL;
2986
+
2987
+ dctx = (ZSTDv07_DCtx*) customMem.customAlloc(customMem.opaque, sizeof(ZSTDv07_DCtx));
2988
+ if (!dctx) return NULL;
2989
+ memcpy(&dctx->customMem, &customMem, sizeof(ZSTDv07_customMem));
2990
+ ZSTDv07_decompressBegin(dctx);
2991
+ return dctx;
2992
+ }
2993
+
2994
+ ZSTDv07_DCtx* ZSTDv07_createDCtx(void)
2995
+ {
2996
+ return ZSTDv07_createDCtx_advanced(defaultCustomMem);
2997
+ }
2998
+
2999
+ size_t ZSTDv07_freeDCtx(ZSTDv07_DCtx* dctx)
3000
+ {
3001
+ if (dctx==NULL) return 0; /* support free on NULL */
3002
+ dctx->customMem.customFree(dctx->customMem.opaque, dctx);
3003
+ return 0; /* reserved as a potential error code in the future */
3004
+ }
3005
+
3006
+ void ZSTDv07_copyDCtx(ZSTDv07_DCtx* dstDCtx, const ZSTDv07_DCtx* srcDCtx)
3007
+ {
3008
+ memcpy(dstDCtx, srcDCtx,
3009
+ sizeof(ZSTDv07_DCtx) - (ZSTDv07_BLOCKSIZE_ABSOLUTEMAX+WILDCOPY_OVERLENGTH + ZSTDv07_frameHeaderSize_max)); /* no need to copy workspace */
3010
+ }
3011
+
3012
+
3013
+ /*-*************************************************************
3014
+ * Decompression section
3015
+ ***************************************************************/
3016
+
3017
+ /* Frame format description
3018
+ Frame Header - [ Block Header - Block ] - Frame End
3019
+ 1) Frame Header
3020
+ - 4 bytes - Magic Number : ZSTDv07_MAGICNUMBER (defined within zstd.h)
3021
+ - 1 byte - Frame Descriptor
3022
+ 2) Block Header
3023
+ - 3 bytes, starting with a 2-bits descriptor
3024
+ Uncompressed, Compressed, Frame End, unused
3025
+ 3) Block
3026
+ See Block Format Description
3027
+ 4) Frame End
3028
+ - 3 bytes, compatible with Block Header
3029
+ */
3030
+
3031
+
3032
+ /* Frame Header :
3033
+
3034
+ 1 byte - FrameHeaderDescription :
3035
+ bit 0-1 : dictID (0, 1, 2 or 4 bytes)
3036
+ bit 2 : checksumFlag
3037
+ bit 3 : reserved (must be zero)
3038
+ bit 4 : reserved (unused, can be any value)
3039
+ bit 5 : Single Segment (if 1, WindowLog byte is not present)
3040
+ bit 6-7 : FrameContentFieldSize (0, 2, 4, or 8)
3041
+ if (SkippedWindowLog && !FrameContentFieldsize) FrameContentFieldsize=1;
3042
+
3043
+ Optional : WindowLog (0 or 1 byte)
3044
+ bit 0-2 : octal Fractional (1/8th)
3045
+ bit 3-7 : Power of 2, with 0 = 1 KB (up to 2 TB)
3046
+
3047
+ Optional : dictID (0, 1, 2 or 4 bytes)
3048
+ Automatic adaptation
3049
+ 0 : no dictID
3050
+ 1 : 1 - 255
3051
+ 2 : 256 - 65535
3052
+ 4 : all other values
3053
+
3054
+ Optional : content size (0, 1, 2, 4 or 8 bytes)
3055
+ 0 : unknown (fcfs==0 and swl==0)
3056
+ 1 : 0-255 bytes (fcfs==0 and swl==1)
3057
+ 2 : 256 - 65535+256 (fcfs==1)
3058
+ 4 : 0 - 4GB-1 (fcfs==2)
3059
+ 8 : 0 - 16EB-1 (fcfs==3)
3060
+ */
3061
+
3062
+
3063
+ /* Compressed Block, format description
3064
+
3065
+ Block = Literal Section - Sequences Section
3066
+ Prerequisite : size of (compressed) block, maximum size of regenerated data
3067
+
3068
+ 1) Literal Section
3069
+
3070
+ 1.1) Header : 1-5 bytes
3071
+ flags: 2 bits
3072
+ 00 compressed by Huff0
3073
+ 01 unused
3074
+ 10 is Raw (uncompressed)
3075
+ 11 is Rle
3076
+ Note : using 01 => Huff0 with precomputed table ?
3077
+ Note : delta map ? => compressed ?
3078
+
3079
+ 1.1.1) Huff0-compressed literal block : 3-5 bytes
3080
+ srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream
3081
+ srcSize < 1 KB => 3 bytes (2-2-10-10)
3082
+ srcSize < 16KB => 4 bytes (2-2-14-14)
3083
+ else => 5 bytes (2-2-18-18)
3084
+ big endian convention
3085
+
3086
+ 1.1.2) Raw (uncompressed) literal block header : 1-3 bytes
3087
+ size : 5 bits: (IS_RAW<<6) + (0<<4) + size
3088
+ 12 bits: (IS_RAW<<6) + (2<<4) + (size>>8)
3089
+ size&255
3090
+ 20 bits: (IS_RAW<<6) + (3<<4) + (size>>16)
3091
+ size>>8&255
3092
+ size&255
3093
+
3094
+ 1.1.3) Rle (repeated single byte) literal block header : 1-3 bytes
3095
+ size : 5 bits: (IS_RLE<<6) + (0<<4) + size
3096
+ 12 bits: (IS_RLE<<6) + (2<<4) + (size>>8)
3097
+ size&255
3098
+ 20 bits: (IS_RLE<<6) + (3<<4) + (size>>16)
3099
+ size>>8&255
3100
+ size&255
3101
+
3102
+ 1.1.4) Huff0-compressed literal block, using precomputed CTables : 3-5 bytes
3103
+ srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream
3104
+ srcSize < 1 KB => 3 bytes (2-2-10-10)
3105
+ srcSize < 16KB => 4 bytes (2-2-14-14)
3106
+ else => 5 bytes (2-2-18-18)
3107
+ big endian convention
3108
+
3109
+ 1- CTable available (stored into workspace ?)
3110
+ 2- Small input (fast heuristic ? Full comparison ? depend on clevel ?)
3111
+
3112
+
3113
+ 1.2) Literal block content
3114
+
3115
+ 1.2.1) Huff0 block, using sizes from header
3116
+ See Huff0 format
3117
+
3118
+ 1.2.2) Huff0 block, using prepared table
3119
+
3120
+ 1.2.3) Raw content
3121
+
3122
+ 1.2.4) single byte
3123
+
3124
+
3125
+ 2) Sequences section
3126
+ TO DO
3127
+ */
3128
+
3129
+ /** ZSTDv07_frameHeaderSize() :
3130
+ * srcSize must be >= ZSTDv07_frameHeaderSize_min.
3131
+ * @return : size of the Frame Header */
3132
+ static size_t ZSTDv07_frameHeaderSize(const void* src, size_t srcSize)
3133
+ {
3134
+ if (srcSize < ZSTDv07_frameHeaderSize_min) return ERROR(srcSize_wrong);
3135
+ { BYTE const fhd = ((const BYTE*)src)[4];
3136
+ U32 const dictID= fhd & 3;
3137
+ U32 const directMode = (fhd >> 5) & 1;
3138
+ U32 const fcsId = fhd >> 6;
3139
+ return ZSTDv07_frameHeaderSize_min + !directMode + ZSTDv07_did_fieldSize[dictID] + ZSTDv07_fcs_fieldSize[fcsId]
3140
+ + (directMode && !ZSTDv07_fcs_fieldSize[fcsId]);
3141
+ }
3142
+ }
3143
+
3144
+
3145
+ /** ZSTDv07_getFrameParams() :
3146
+ * decode Frame Header, or require larger `srcSize`.
3147
+ * @return : 0, `fparamsPtr` is correctly filled,
3148
+ * >0, `srcSize` is too small, result is expected `srcSize`,
3149
+ * or an error code, which can be tested using ZSTDv07_isError() */
3150
+ size_t ZSTDv07_getFrameParams(ZSTDv07_frameParams* fparamsPtr, const void* src, size_t srcSize)
3151
+ {
3152
+ const BYTE* ip = (const BYTE*)src;
3153
+
3154
+ if (srcSize < ZSTDv07_frameHeaderSize_min) return ZSTDv07_frameHeaderSize_min;
3155
+ memset(fparamsPtr, 0, sizeof(*fparamsPtr));
3156
+ if (MEM_readLE32(src) != ZSTDv07_MAGICNUMBER) {
3157
+ if ((MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTDv07_MAGIC_SKIPPABLE_START) {
3158
+ if (srcSize < ZSTDv07_skippableHeaderSize) return ZSTDv07_skippableHeaderSize; /* magic number + skippable frame length */
3159
+ fparamsPtr->frameContentSize = MEM_readLE32((const char *)src + 4);
3160
+ fparamsPtr->windowSize = 0; /* windowSize==0 means a frame is skippable */
3161
+ return 0;
3162
+ }
3163
+ return ERROR(prefix_unknown);
3164
+ }
3165
+
3166
+ /* ensure there is enough `srcSize` to fully read/decode frame header */
3167
+ { size_t const fhsize = ZSTDv07_frameHeaderSize(src, srcSize);
3168
+ if (srcSize < fhsize) return fhsize; }
3169
+
3170
+ { BYTE const fhdByte = ip[4];
3171
+ size_t pos = 5;
3172
+ U32 const dictIDSizeCode = fhdByte&3;
3173
+ U32 const checksumFlag = (fhdByte>>2)&1;
3174
+ U32 const directMode = (fhdByte>>5)&1;
3175
+ U32 const fcsID = fhdByte>>6;
3176
+ U32 const windowSizeMax = 1U << ZSTDv07_WINDOWLOG_MAX;
3177
+ U32 windowSize = 0;
3178
+ U32 dictID = 0;
3179
+ U64 frameContentSize = 0;
3180
+ if ((fhdByte & 0x08) != 0) /* reserved bits, which must be zero */
3181
+ return ERROR(frameParameter_unsupported);
3182
+ if (!directMode) {
3183
+ BYTE const wlByte = ip[pos++];
3184
+ U32 const windowLog = (wlByte >> 3) + ZSTDv07_WINDOWLOG_ABSOLUTEMIN;
3185
+ if (windowLog > ZSTDv07_WINDOWLOG_MAX)
3186
+ return ERROR(frameParameter_unsupported);
3187
+ windowSize = (1U << windowLog);
3188
+ windowSize += (windowSize >> 3) * (wlByte&7);
3189
+ }
3190
+
3191
+ switch(dictIDSizeCode)
3192
+ {
3193
+ default: /* impossible */
3194
+ case 0 : break;
3195
+ case 1 : dictID = ip[pos]; pos++; break;
3196
+ case 2 : dictID = MEM_readLE16(ip+pos); pos+=2; break;
3197
+ case 3 : dictID = MEM_readLE32(ip+pos); pos+=4; break;
3198
+ }
3199
+ switch(fcsID)
3200
+ {
3201
+ default: /* impossible */
3202
+ case 0 : if (directMode) frameContentSize = ip[pos]; break;
3203
+ case 1 : frameContentSize = MEM_readLE16(ip+pos)+256; break;
3204
+ case 2 : frameContentSize = MEM_readLE32(ip+pos); break;
3205
+ case 3 : frameContentSize = MEM_readLE64(ip+pos); break;
3206
+ }
3207
+ if (!windowSize) windowSize = (U32)frameContentSize;
3208
+ if (windowSize > windowSizeMax)
3209
+ return ERROR(frameParameter_unsupported);
3210
+ fparamsPtr->frameContentSize = frameContentSize;
3211
+ fparamsPtr->windowSize = windowSize;
3212
+ fparamsPtr->dictID = dictID;
3213
+ fparamsPtr->checksumFlag = checksumFlag;
3214
+ }
3215
+ return 0;
3216
+ }
3217
+
3218
+
3219
+ /** ZSTDv07_getDecompressedSize() :
3220
+ * compatible with legacy mode
3221
+ * @return : decompressed size if known, 0 otherwise
3222
+ note : 0 can mean any of the following :
3223
+ - decompressed size is not provided within frame header
3224
+ - frame header unknown / not supported
3225
+ - frame header not completely provided (`srcSize` too small) */
3226
+ unsigned long long ZSTDv07_getDecompressedSize(const void* src, size_t srcSize)
3227
+ {
3228
+ ZSTDv07_frameParams fparams;
3229
+ size_t const frResult = ZSTDv07_getFrameParams(&fparams, src, srcSize);
3230
+ if (frResult!=0) return 0;
3231
+ return fparams.frameContentSize;
3232
+ }
3233
+
3234
+
3235
+ /** ZSTDv07_decodeFrameHeader() :
3236
+ * `srcSize` must be the size provided by ZSTDv07_frameHeaderSize().
3237
+ * @return : 0 if success, or an error code, which can be tested using ZSTDv07_isError() */
3238
+ static size_t ZSTDv07_decodeFrameHeader(ZSTDv07_DCtx* dctx, const void* src, size_t srcSize)
3239
+ {
3240
+ size_t const result = ZSTDv07_getFrameParams(&(dctx->fParams), src, srcSize);
3241
+ if (dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID)) return ERROR(dictionary_wrong);
3242
+ if (dctx->fParams.checksumFlag) XXH64_reset(&dctx->xxhState, 0);
3243
+ return result;
3244
+ }
3245
+
3246
+
3247
+ typedef struct
3248
+ {
3249
+ blockType_t blockType;
3250
+ U32 origSize;
3251
+ } blockProperties_t;
3252
+
3253
+ /*! ZSTDv07_getcBlockSize() :
3254
+ * Provides the size of compressed block from block header `src` */
3255
+ static size_t ZSTDv07_getcBlockSize(const void* src, size_t srcSize, blockProperties_t* bpPtr)
3256
+ {
3257
+ const BYTE* const in = (const BYTE* const)src;
3258
+ U32 cSize;
3259
+
3260
+ if (srcSize < ZSTDv07_blockHeaderSize) return ERROR(srcSize_wrong);
3261
+
3262
+ bpPtr->blockType = (blockType_t)((*in) >> 6);
3263
+ cSize = in[2] + (in[1]<<8) + ((in[0] & 7)<<16);
3264
+ bpPtr->origSize = (bpPtr->blockType == bt_rle) ? cSize : 0;
3265
+
3266
+ if (bpPtr->blockType == bt_end) return 0;
3267
+ if (bpPtr->blockType == bt_rle) return 1;
3268
+ return cSize;
3269
+ }
3270
+
3271
+
3272
+ static size_t ZSTDv07_copyRawBlock(void* dst, size_t dstCapacity, const void* src, size_t srcSize)
3273
+ {
3274
+ if (srcSize > dstCapacity) return ERROR(dstSize_tooSmall);
3275
+ if (srcSize > 0) {
3276
+ memcpy(dst, src, srcSize);
3277
+ }
3278
+ return srcSize;
3279
+ }
3280
+
3281
+
3282
+ /*! ZSTDv07_decodeLiteralsBlock() :
3283
+ @return : nb of bytes read from src (< srcSize ) */
3284
+ static size_t ZSTDv07_decodeLiteralsBlock(ZSTDv07_DCtx* dctx,
3285
+ const void* src, size_t srcSize) /* note : srcSize < BLOCKSIZE */
3286
+ {
3287
+ const BYTE* const istart = (const BYTE*) src;
3288
+
3289
+ if (srcSize < MIN_CBLOCK_SIZE) return ERROR(corruption_detected);
3290
+
3291
+ switch((litBlockType_t)(istart[0]>> 6))
3292
+ {
3293
+ case lbt_huffman:
3294
+ { size_t litSize, litCSize, singleStream=0;
3295
+ U32 lhSize = (istart[0] >> 4) & 3;
3296
+ if (srcSize < 5) return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need up to 5 for lhSize, + cSize (+nbSeq) */
3297
+ switch(lhSize)
3298
+ {
3299
+ case 0: case 1: default: /* note : default is impossible, since lhSize into [0..3] */
3300
+ /* 2 - 2 - 10 - 10 */
3301
+ lhSize=3;
3302
+ singleStream = istart[0] & 16;
3303
+ litSize = ((istart[0] & 15) << 6) + (istart[1] >> 2);
3304
+ litCSize = ((istart[1] & 3) << 8) + istart[2];
3305
+ break;
3306
+ case 2:
3307
+ /* 2 - 2 - 14 - 14 */
3308
+ lhSize=4;
3309
+ litSize = ((istart[0] & 15) << 10) + (istart[1] << 2) + (istart[2] >> 6);
3310
+ litCSize = ((istart[2] & 63) << 8) + istart[3];
3311
+ break;
3312
+ case 3:
3313
+ /* 2 - 2 - 18 - 18 */
3314
+ lhSize=5;
3315
+ litSize = ((istart[0] & 15) << 14) + (istart[1] << 6) + (istart[2] >> 2);
3316
+ litCSize = ((istart[2] & 3) << 16) + (istart[3] << 8) + istart[4];
3317
+ break;
3318
+ }
3319
+ if (litSize > ZSTDv07_BLOCKSIZE_ABSOLUTEMAX) return ERROR(corruption_detected);
3320
+ if (litCSize + lhSize > srcSize) return ERROR(corruption_detected);
3321
+
3322
+ if (HUFv07_isError(singleStream ?
3323
+ HUFv07_decompress1X2_DCtx(dctx->hufTable, dctx->litBuffer, litSize, istart+lhSize, litCSize) :
3324
+ HUFv07_decompress4X_hufOnly (dctx->hufTable, dctx->litBuffer, litSize, istart+lhSize, litCSize) ))
3325
+ return ERROR(corruption_detected);
3326
+
3327
+ dctx->litPtr = dctx->litBuffer;
3328
+ dctx->litSize = litSize;
3329
+ dctx->litEntropy = 1;
3330
+ memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);
3331
+ return litCSize + lhSize;
3332
+ }
3333
+ case lbt_repeat:
3334
+ { size_t litSize, litCSize;
3335
+ U32 lhSize = ((istart[0]) >> 4) & 3;
3336
+ if (lhSize != 1) /* only case supported for now : small litSize, single stream */
3337
+ return ERROR(corruption_detected);
3338
+ if (dctx->litEntropy==0)
3339
+ return ERROR(dictionary_corrupted);
3340
+
3341
+ /* 2 - 2 - 10 - 10 */
3342
+ lhSize=3;
3343
+ litSize = ((istart[0] & 15) << 6) + (istart[1] >> 2);
3344
+ litCSize = ((istart[1] & 3) << 8) + istart[2];
3345
+ if (litCSize + lhSize > srcSize) return ERROR(corruption_detected);
3346
+
3347
+ { size_t const errorCode = HUFv07_decompress1X4_usingDTable(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->hufTable);
3348
+ if (HUFv07_isError(errorCode)) return ERROR(corruption_detected);
3349
+ }
3350
+ dctx->litPtr = dctx->litBuffer;
3351
+ dctx->litSize = litSize;
3352
+ memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);
3353
+ return litCSize + lhSize;
3354
+ }
3355
+ case lbt_raw:
3356
+ { size_t litSize;
3357
+ U32 lhSize = ((istart[0]) >> 4) & 3;
3358
+ switch(lhSize)
3359
+ {
3360
+ case 0: case 1: default: /* note : default is impossible, since lhSize into [0..3] */
3361
+ lhSize=1;
3362
+ litSize = istart[0] & 31;
3363
+ break;
3364
+ case 2:
3365
+ litSize = ((istart[0] & 15) << 8) + istart[1];
3366
+ break;
3367
+ case 3:
3368
+ litSize = ((istart[0] & 15) << 16) + (istart[1] << 8) + istart[2];
3369
+ break;
3370
+ }
3371
+
3372
+ if (lhSize+litSize+WILDCOPY_OVERLENGTH > srcSize) { /* risk reading beyond src buffer with wildcopy */
3373
+ if (litSize+lhSize > srcSize) return ERROR(corruption_detected);
3374
+ memcpy(dctx->litBuffer, istart+lhSize, litSize);
3375
+ dctx->litPtr = dctx->litBuffer;
3376
+ dctx->litSize = litSize;
3377
+ memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);
3378
+ return lhSize+litSize;
3379
+ }
3380
+ /* direct reference into compressed stream */
3381
+ dctx->litPtr = istart+lhSize;
3382
+ dctx->litSize = litSize;
3383
+ return lhSize+litSize;
3384
+ }
3385
+ case lbt_rle:
3386
+ { size_t litSize;
3387
+ U32 lhSize = ((istart[0]) >> 4) & 3;
3388
+ switch(lhSize)
3389
+ {
3390
+ case 0: case 1: default: /* note : default is impossible, since lhSize into [0..3] */
3391
+ lhSize = 1;
3392
+ litSize = istart[0] & 31;
3393
+ break;
3394
+ case 2:
3395
+ litSize = ((istart[0] & 15) << 8) + istart[1];
3396
+ break;
3397
+ case 3:
3398
+ litSize = ((istart[0] & 15) << 16) + (istart[1] << 8) + istart[2];
3399
+ if (srcSize<4) return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need lhSize+1 = 4 */
3400
+ break;
3401
+ }
3402
+ if (litSize > ZSTDv07_BLOCKSIZE_ABSOLUTEMAX) return ERROR(corruption_detected);
3403
+ memset(dctx->litBuffer, istart[lhSize], litSize + WILDCOPY_OVERLENGTH);
3404
+ dctx->litPtr = dctx->litBuffer;
3405
+ dctx->litSize = litSize;
3406
+ return lhSize+1;
3407
+ }
3408
+ default:
3409
+ return ERROR(corruption_detected); /* impossible */
3410
+ }
3411
+ }
3412
+
3413
+
3414
+ /*! ZSTDv07_buildSeqTable() :
3415
+ @return : nb bytes read from src,
3416
+ or an error code if it fails, testable with ZSTDv07_isError()
3417
+ */
3418
+ static size_t ZSTDv07_buildSeqTable(FSEv07_DTable* DTable, U32 type, U32 max, U32 maxLog,
3419
+ const void* src, size_t srcSize,
3420
+ const S16* defaultNorm, U32 defaultLog, U32 flagRepeatTable)
3421
+ {
3422
+ switch(type)
3423
+ {
3424
+ case FSEv07_ENCODING_RLE :
3425
+ if (!srcSize) return ERROR(srcSize_wrong);
3426
+ if ( (*(const BYTE*)src) > max) return ERROR(corruption_detected);
3427
+ FSEv07_buildDTable_rle(DTable, *(const BYTE*)src); /* if *src > max, data is corrupted */
3428
+ return 1;
3429
+ case FSEv07_ENCODING_RAW :
3430
+ FSEv07_buildDTable(DTable, defaultNorm, max, defaultLog);
3431
+ return 0;
3432
+ case FSEv07_ENCODING_STATIC:
3433
+ if (!flagRepeatTable) return ERROR(corruption_detected);
3434
+ return 0;
3435
+ default : /* impossible */
3436
+ case FSEv07_ENCODING_DYNAMIC :
3437
+ { U32 tableLog;
3438
+ S16 norm[MaxSeq+1];
3439
+ size_t const headerSize = FSEv07_readNCount(norm, &max, &tableLog, src, srcSize);
3440
+ if (FSEv07_isError(headerSize)) return ERROR(corruption_detected);
3441
+ if (tableLog > maxLog) return ERROR(corruption_detected);
3442
+ FSEv07_buildDTable(DTable, norm, max, tableLog);
3443
+ return headerSize;
3444
+ } }
3445
+ }
3446
+
3447
+
3448
+ static size_t ZSTDv07_decodeSeqHeaders(int* nbSeqPtr,
3449
+ FSEv07_DTable* DTableLL, FSEv07_DTable* DTableML, FSEv07_DTable* DTableOffb, U32 flagRepeatTable,
3450
+ const void* src, size_t srcSize)
3451
+ {
3452
+ const BYTE* const istart = (const BYTE* const)src;
3453
+ const BYTE* const iend = istart + srcSize;
3454
+ const BYTE* ip = istart;
3455
+
3456
+ /* check */
3457
+ if (srcSize < MIN_SEQUENCES_SIZE) return ERROR(srcSize_wrong);
3458
+
3459
+ /* SeqHead */
3460
+ { int nbSeq = *ip++;
3461
+ if (!nbSeq) { *nbSeqPtr=0; return 1; }
3462
+ if (nbSeq > 0x7F) {
3463
+ if (nbSeq == 0xFF) {
3464
+ if (ip+2 > iend) return ERROR(srcSize_wrong);
3465
+ nbSeq = MEM_readLE16(ip) + LONGNBSEQ, ip+=2;
3466
+ } else {
3467
+ if (ip >= iend) return ERROR(srcSize_wrong);
3468
+ nbSeq = ((nbSeq-0x80)<<8) + *ip++;
3469
+ }
3470
+ }
3471
+ *nbSeqPtr = nbSeq;
3472
+ }
3473
+
3474
+ /* FSE table descriptors */
3475
+ if (ip + 4 > iend) return ERROR(srcSize_wrong); /* min : header byte + all 3 are "raw", hence no header, but at least xxLog bits per type */
3476
+ { U32 const LLtype = *ip >> 6;
3477
+ U32 const OFtype = (*ip >> 4) & 3;
3478
+ U32 const MLtype = (*ip >> 2) & 3;
3479
+ ip++;
3480
+
3481
+ /* Build DTables */
3482
+ { size_t const llhSize = ZSTDv07_buildSeqTable(DTableLL, LLtype, MaxLL, LLFSELog, ip, iend-ip, LL_defaultNorm, LL_defaultNormLog, flagRepeatTable);
3483
+ if (ZSTDv07_isError(llhSize)) return ERROR(corruption_detected);
3484
+ ip += llhSize;
3485
+ }
3486
+ { size_t const ofhSize = ZSTDv07_buildSeqTable(DTableOffb, OFtype, MaxOff, OffFSELog, ip, iend-ip, OF_defaultNorm, OF_defaultNormLog, flagRepeatTable);
3487
+ if (ZSTDv07_isError(ofhSize)) return ERROR(corruption_detected);
3488
+ ip += ofhSize;
3489
+ }
3490
+ { size_t const mlhSize = ZSTDv07_buildSeqTable(DTableML, MLtype, MaxML, MLFSELog, ip, iend-ip, ML_defaultNorm, ML_defaultNormLog, flagRepeatTable);
3491
+ if (ZSTDv07_isError(mlhSize)) return ERROR(corruption_detected);
3492
+ ip += mlhSize;
3493
+ } }
3494
+
3495
+ return ip-istart;
3496
+ }
3497
+
3498
+
3499
+ typedef struct {
3500
+ size_t litLength;
3501
+ size_t matchLength;
3502
+ size_t offset;
3503
+ } seq_t;
3504
+
3505
+ typedef struct {
3506
+ BITv07_DStream_t DStream;
3507
+ FSEv07_DState_t stateLL;
3508
+ FSEv07_DState_t stateOffb;
3509
+ FSEv07_DState_t stateML;
3510
+ size_t prevOffset[ZSTDv07_REP_INIT];
3511
+ } seqState_t;
3512
+
3513
+
3514
+ static seq_t ZSTDv07_decodeSequence(seqState_t* seqState)
3515
+ {
3516
+ seq_t seq;
3517
+
3518
+ U32 const llCode = FSEv07_peekSymbol(&(seqState->stateLL));
3519
+ U32 const mlCode = FSEv07_peekSymbol(&(seqState->stateML));
3520
+ U32 const ofCode = FSEv07_peekSymbol(&(seqState->stateOffb)); /* <= maxOff, by table construction */
3521
+
3522
+ U32 const llBits = LL_bits[llCode];
3523
+ U32 const mlBits = ML_bits[mlCode];
3524
+ U32 const ofBits = ofCode;
3525
+ U32 const totalBits = llBits+mlBits+ofBits;
3526
+
3527
+ static const U32 LL_base[MaxLL+1] = {
3528
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
3529
+ 16, 18, 20, 22, 24, 28, 32, 40, 48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000,
3530
+ 0x2000, 0x4000, 0x8000, 0x10000 };
3531
+
3532
+ static const U32 ML_base[MaxML+1] = {
3533
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
3534
+ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
3535
+ 35, 37, 39, 41, 43, 47, 51, 59, 67, 83, 99, 0x83, 0x103, 0x203, 0x403, 0x803,
3536
+ 0x1003, 0x2003, 0x4003, 0x8003, 0x10003 };
3537
+
3538
+ static const U32 OF_base[MaxOff+1] = {
3539
+ 0, 1, 1, 5, 0xD, 0x1D, 0x3D, 0x7D,
3540
+ 0xFD, 0x1FD, 0x3FD, 0x7FD, 0xFFD, 0x1FFD, 0x3FFD, 0x7FFD,
3541
+ 0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD,
3542
+ 0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD };
3543
+
3544
+ /* sequence */
3545
+ { size_t offset;
3546
+ if (!ofCode)
3547
+ offset = 0;
3548
+ else {
3549
+ offset = OF_base[ofCode] + BITv07_readBits(&(seqState->DStream), ofBits); /* <= (ZSTDv07_WINDOWLOG_MAX-1) bits */
3550
+ if (MEM_32bits()) BITv07_reloadDStream(&(seqState->DStream));
3551
+ }
3552
+
3553
+ if (ofCode <= 1) {
3554
+ if ((llCode == 0) & (offset <= 1)) offset = 1-offset;
3555
+ if (offset) {
3556
+ size_t const temp = seqState->prevOffset[offset];
3557
+ if (offset != 1) seqState->prevOffset[2] = seqState->prevOffset[1];
3558
+ seqState->prevOffset[1] = seqState->prevOffset[0];
3559
+ seqState->prevOffset[0] = offset = temp;
3560
+ } else {
3561
+ offset = seqState->prevOffset[0];
3562
+ }
3563
+ } else {
3564
+ seqState->prevOffset[2] = seqState->prevOffset[1];
3565
+ seqState->prevOffset[1] = seqState->prevOffset[0];
3566
+ seqState->prevOffset[0] = offset;
3567
+ }
3568
+ seq.offset = offset;
3569
+ }
3570
+
3571
+ seq.matchLength = ML_base[mlCode] + ((mlCode>31) ? BITv07_readBits(&(seqState->DStream), mlBits) : 0); /* <= 16 bits */
3572
+ if (MEM_32bits() && (mlBits+llBits>24)) BITv07_reloadDStream(&(seqState->DStream));
3573
+
3574
+ seq.litLength = LL_base[llCode] + ((llCode>15) ? BITv07_readBits(&(seqState->DStream), llBits) : 0); /* <= 16 bits */
3575
+ if (MEM_32bits() ||
3576
+ (totalBits > 64 - 7 - (LLFSELog+MLFSELog+OffFSELog)) ) BITv07_reloadDStream(&(seqState->DStream));
3577
+
3578
+ /* ANS state update */
3579
+ FSEv07_updateState(&(seqState->stateLL), &(seqState->DStream)); /* <= 9 bits */
3580
+ FSEv07_updateState(&(seqState->stateML), &(seqState->DStream)); /* <= 9 bits */
3581
+ if (MEM_32bits()) BITv07_reloadDStream(&(seqState->DStream)); /* <= 18 bits */
3582
+ FSEv07_updateState(&(seqState->stateOffb), &(seqState->DStream)); /* <= 8 bits */
3583
+
3584
+ return seq;
3585
+ }
3586
+
3587
+
3588
+ static
3589
+ size_t ZSTDv07_execSequence(BYTE* op,
3590
+ BYTE* const oend, seq_t sequence,
3591
+ const BYTE** litPtr, const BYTE* const litLimit,
3592
+ const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)
3593
+ {
3594
+ BYTE* const oLitEnd = op + sequence.litLength;
3595
+ size_t const sequenceLength = sequence.litLength + sequence.matchLength;
3596
+ BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
3597
+ BYTE* const oend_w = oend-WILDCOPY_OVERLENGTH;
3598
+ const BYTE* const iLitEnd = *litPtr + sequence.litLength;
3599
+ const BYTE* match = oLitEnd - sequence.offset;
3600
+
3601
+ /* check */
3602
+ if ((oLitEnd>oend_w) | (oMatchEnd>oend)) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */
3603
+ if (iLitEnd > litLimit) return ERROR(corruption_detected); /* over-read beyond lit buffer */
3604
+
3605
+ /* copy Literals */
3606
+ ZSTDv07_wildcopy(op, *litPtr, sequence.litLength); /* note : since oLitEnd <= oend-WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */
3607
+ op = oLitEnd;
3608
+ *litPtr = iLitEnd; /* update for next sequence */
3609
+
3610
+ /* copy Match */
3611
+ if (sequence.offset > (size_t)(oLitEnd - base)) {
3612
+ /* offset beyond prefix */
3613
+ if (sequence.offset > (size_t)(oLitEnd - vBase)) return ERROR(corruption_detected);
3614
+ match = dictEnd - (base-match);
3615
+ if (match + sequence.matchLength <= dictEnd) {
3616
+ memmove(oLitEnd, match, sequence.matchLength);
3617
+ return sequenceLength;
3618
+ }
3619
+ /* span extDict & currentPrefixSegment */
3620
+ { size_t const length1 = dictEnd - match;
3621
+ memmove(oLitEnd, match, length1);
3622
+ op = oLitEnd + length1;
3623
+ sequence.matchLength -= length1;
3624
+ match = base;
3625
+ if (op > oend_w || sequence.matchLength < MINMATCH) {
3626
+ while (op < oMatchEnd) *op++ = *match++;
3627
+ return sequenceLength;
3628
+ }
3629
+ } }
3630
+ /* Requirement: op <= oend_w */
3631
+
3632
+ /* match within prefix */
3633
+ if (sequence.offset < 8) {
3634
+ /* close range match, overlap */
3635
+ static const U32 dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */
3636
+ static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* subtracted */
3637
+ int const sub2 = dec64table[sequence.offset];
3638
+ op[0] = match[0];
3639
+ op[1] = match[1];
3640
+ op[2] = match[2];
3641
+ op[3] = match[3];
3642
+ match += dec32table[sequence.offset];
3643
+ ZSTDv07_copy4(op+4, match);
3644
+ match -= sub2;
3645
+ } else {
3646
+ ZSTDv07_copy8(op, match);
3647
+ }
3648
+ op += 8; match += 8;
3649
+
3650
+ if (oMatchEnd > oend-(16-MINMATCH)) {
3651
+ if (op < oend_w) {
3652
+ ZSTDv07_wildcopy(op, match, oend_w - op);
3653
+ match += oend_w - op;
3654
+ op = oend_w;
3655
+ }
3656
+ while (op < oMatchEnd) *op++ = *match++;
3657
+ } else {
3658
+ ZSTDv07_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8); /* works even if matchLength < 8 */
3659
+ }
3660
+ return sequenceLength;
3661
+ }
3662
+
3663
+
3664
+ static size_t ZSTDv07_decompressSequences(
3665
+ ZSTDv07_DCtx* dctx,
3666
+ void* dst, size_t maxDstSize,
3667
+ const void* seqStart, size_t seqSize)
3668
+ {
3669
+ const BYTE* ip = (const BYTE*)seqStart;
3670
+ const BYTE* const iend = ip + seqSize;
3671
+ BYTE* const ostart = (BYTE* const)dst;
3672
+ BYTE* const oend = ostart + maxDstSize;
3673
+ BYTE* op = ostart;
3674
+ const BYTE* litPtr = dctx->litPtr;
3675
+ const BYTE* const litEnd = litPtr + dctx->litSize;
3676
+ FSEv07_DTable* DTableLL = dctx->LLTable;
3677
+ FSEv07_DTable* DTableML = dctx->MLTable;
3678
+ FSEv07_DTable* DTableOffb = dctx->OffTable;
3679
+ const BYTE* const base = (const BYTE*) (dctx->base);
3680
+ const BYTE* const vBase = (const BYTE*) (dctx->vBase);
3681
+ const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);
3682
+ int nbSeq;
3683
+
3684
+ /* Build Decoding Tables */
3685
+ { size_t const seqHSize = ZSTDv07_decodeSeqHeaders(&nbSeq, DTableLL, DTableML, DTableOffb, dctx->fseEntropy, ip, seqSize);
3686
+ if (ZSTDv07_isError(seqHSize)) return seqHSize;
3687
+ ip += seqHSize;
3688
+ }
3689
+
3690
+ /* Regen sequences */
3691
+ if (nbSeq) {
3692
+ seqState_t seqState;
3693
+ dctx->fseEntropy = 1;
3694
+ { U32 i; for (i=0; i<ZSTDv07_REP_INIT; i++) seqState.prevOffset[i] = dctx->rep[i]; }
3695
+ { size_t const errorCode = BITv07_initDStream(&(seqState.DStream), ip, iend-ip);
3696
+ if (ERR_isError(errorCode)) return ERROR(corruption_detected); }
3697
+ FSEv07_initDState(&(seqState.stateLL), &(seqState.DStream), DTableLL);
3698
+ FSEv07_initDState(&(seqState.stateOffb), &(seqState.DStream), DTableOffb);
3699
+ FSEv07_initDState(&(seqState.stateML), &(seqState.DStream), DTableML);
3700
+
3701
+ for ( ; (BITv07_reloadDStream(&(seqState.DStream)) <= BITv07_DStream_completed) && nbSeq ; ) {
3702
+ nbSeq--;
3703
+ { seq_t const sequence = ZSTDv07_decodeSequence(&seqState);
3704
+ size_t const oneSeqSize = ZSTDv07_execSequence(op, oend, sequence, &litPtr, litEnd, base, vBase, dictEnd);
3705
+ if (ZSTDv07_isError(oneSeqSize)) return oneSeqSize;
3706
+ op += oneSeqSize;
3707
+ } }
3708
+
3709
+ /* check if reached exact end */
3710
+ if (nbSeq) return ERROR(corruption_detected);
3711
+ /* save reps for next block */
3712
+ { U32 i; for (i=0; i<ZSTDv07_REP_INIT; i++) dctx->rep[i] = (U32)(seqState.prevOffset[i]); }
3713
+ }
3714
+
3715
+ /* last literal segment */
3716
+ { size_t const lastLLSize = litEnd - litPtr;
3717
+ /* if (litPtr > litEnd) return ERROR(corruption_detected); */ /* too many literals already used */
3718
+ if (lastLLSize > (size_t)(oend-op)) return ERROR(dstSize_tooSmall);
3719
+ if (lastLLSize > 0) {
3720
+ memcpy(op, litPtr, lastLLSize);
3721
+ op += lastLLSize;
3722
+ }
3723
+ }
3724
+
3725
+ return op-ostart;
3726
+ }
3727
+
3728
+
3729
+ static void ZSTDv07_checkContinuity(ZSTDv07_DCtx* dctx, const void* dst)
3730
+ {
3731
+ if (dst != dctx->previousDstEnd) { /* not contiguous */
3732
+ dctx->dictEnd = dctx->previousDstEnd;
3733
+ dctx->vBase = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->base));
3734
+ dctx->base = dst;
3735
+ dctx->previousDstEnd = dst;
3736
+ }
3737
+ }
3738
+
3739
+
3740
+ static size_t ZSTDv07_decompressBlock_internal(ZSTDv07_DCtx* dctx,
3741
+ void* dst, size_t dstCapacity,
3742
+ const void* src, size_t srcSize)
3743
+ { /* blockType == blockCompressed */
3744
+ const BYTE* ip = (const BYTE*)src;
3745
+
3746
+ if (srcSize >= ZSTDv07_BLOCKSIZE_ABSOLUTEMAX) return ERROR(srcSize_wrong);
3747
+
3748
+ /* Decode literals sub-block */
3749
+ { size_t const litCSize = ZSTDv07_decodeLiteralsBlock(dctx, src, srcSize);
3750
+ if (ZSTDv07_isError(litCSize)) return litCSize;
3751
+ ip += litCSize;
3752
+ srcSize -= litCSize;
3753
+ }
3754
+ return ZSTDv07_decompressSequences(dctx, dst, dstCapacity, ip, srcSize);
3755
+ }
3756
+
3757
+
3758
+ size_t ZSTDv07_decompressBlock(ZSTDv07_DCtx* dctx,
3759
+ void* dst, size_t dstCapacity,
3760
+ const void* src, size_t srcSize)
3761
+ {
3762
+ size_t dSize;
3763
+ ZSTDv07_checkContinuity(dctx, dst);
3764
+ dSize = ZSTDv07_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize);
3765
+ dctx->previousDstEnd = (char*)dst + dSize;
3766
+ return dSize;
3767
+ }
3768
+
3769
+
3770
+ /** ZSTDv07_insertBlock() :
3771
+ insert `src` block into `dctx` history. Useful to track uncompressed blocks. */
3772
+ ZSTDLIBv07_API size_t ZSTDv07_insertBlock(ZSTDv07_DCtx* dctx, const void* blockStart, size_t blockSize)
3773
+ {
3774
+ ZSTDv07_checkContinuity(dctx, blockStart);
3775
+ dctx->previousDstEnd = (const char*)blockStart + blockSize;
3776
+ return blockSize;
3777
+ }
3778
+
3779
+
3780
+ static size_t ZSTDv07_generateNxBytes(void* dst, size_t dstCapacity, BYTE byte, size_t length)
3781
+ {
3782
+ if (length > dstCapacity) return ERROR(dstSize_tooSmall);
3783
+ if (length > 0) {
3784
+ memset(dst, byte, length);
3785
+ }
3786
+ return length;
3787
+ }
3788
+
3789
+
3790
+ /*! ZSTDv07_decompressFrame() :
3791
+ * `dctx` must be properly initialized */
3792
+ static size_t ZSTDv07_decompressFrame(ZSTDv07_DCtx* dctx,
3793
+ void* dst, size_t dstCapacity,
3794
+ const void* src, size_t srcSize)
3795
+ {
3796
+ const BYTE* ip = (const BYTE*)src;
3797
+ const BYTE* const iend = ip + srcSize;
3798
+ BYTE* const ostart = (BYTE* const)dst;
3799
+ BYTE* const oend = ostart + dstCapacity;
3800
+ BYTE* op = ostart;
3801
+ size_t remainingSize = srcSize;
3802
+
3803
+ /* check */
3804
+ if (srcSize < ZSTDv07_frameHeaderSize_min+ZSTDv07_blockHeaderSize) return ERROR(srcSize_wrong);
3805
+
3806
+ /* Frame Header */
3807
+ { size_t const frameHeaderSize = ZSTDv07_frameHeaderSize(src, ZSTDv07_frameHeaderSize_min);
3808
+ if (ZSTDv07_isError(frameHeaderSize)) return frameHeaderSize;
3809
+ if (srcSize < frameHeaderSize+ZSTDv07_blockHeaderSize) return ERROR(srcSize_wrong);
3810
+ if (ZSTDv07_decodeFrameHeader(dctx, src, frameHeaderSize)) return ERROR(corruption_detected);
3811
+ ip += frameHeaderSize; remainingSize -= frameHeaderSize;
3812
+ }
3813
+
3814
+ /* Loop on each block */
3815
+ while (1) {
3816
+ size_t decodedSize;
3817
+ blockProperties_t blockProperties;
3818
+ size_t const cBlockSize = ZSTDv07_getcBlockSize(ip, iend-ip, &blockProperties);
3819
+ if (ZSTDv07_isError(cBlockSize)) return cBlockSize;
3820
+
3821
+ ip += ZSTDv07_blockHeaderSize;
3822
+ remainingSize -= ZSTDv07_blockHeaderSize;
3823
+ if (cBlockSize > remainingSize) return ERROR(srcSize_wrong);
3824
+
3825
+ switch(blockProperties.blockType)
3826
+ {
3827
+ case bt_compressed:
3828
+ decodedSize = ZSTDv07_decompressBlock_internal(dctx, op, oend-op, ip, cBlockSize);
3829
+ break;
3830
+ case bt_raw :
3831
+ decodedSize = ZSTDv07_copyRawBlock(op, oend-op, ip, cBlockSize);
3832
+ break;
3833
+ case bt_rle :
3834
+ decodedSize = ZSTDv07_generateNxBytes(op, oend-op, *ip, blockProperties.origSize);
3835
+ break;
3836
+ case bt_end :
3837
+ /* end of frame */
3838
+ if (remainingSize) return ERROR(srcSize_wrong);
3839
+ decodedSize = 0;
3840
+ break;
3841
+ default:
3842
+ return ERROR(GENERIC); /* impossible */
3843
+ }
3844
+ if (blockProperties.blockType == bt_end) break; /* bt_end */
3845
+
3846
+ if (ZSTDv07_isError(decodedSize)) return decodedSize;
3847
+ if (dctx->fParams.checksumFlag) XXH64_update(&dctx->xxhState, op, decodedSize);
3848
+ op += decodedSize;
3849
+ ip += cBlockSize;
3850
+ remainingSize -= cBlockSize;
3851
+ }
3852
+
3853
+ return op-ostart;
3854
+ }
3855
+
3856
+
3857
+ /*! ZSTDv07_decompress_usingPreparedDCtx() :
3858
+ * Same as ZSTDv07_decompress_usingDict, but using a reference context `preparedDCtx`, where dictionary has been loaded.
3859
+ * It avoids reloading the dictionary each time.
3860
+ * `preparedDCtx` must have been properly initialized using ZSTDv07_decompressBegin_usingDict().
3861
+ * Requires 2 contexts : 1 for reference (preparedDCtx), which will not be modified, and 1 to run the decompression operation (dctx) */
3862
+ static size_t ZSTDv07_decompress_usingPreparedDCtx(ZSTDv07_DCtx* dctx, const ZSTDv07_DCtx* refDCtx,
3863
+ void* dst, size_t dstCapacity,
3864
+ const void* src, size_t srcSize)
3865
+ {
3866
+ ZSTDv07_copyDCtx(dctx, refDCtx);
3867
+ ZSTDv07_checkContinuity(dctx, dst);
3868
+ return ZSTDv07_decompressFrame(dctx, dst, dstCapacity, src, srcSize);
3869
+ }
3870
+
3871
+
3872
+ size_t ZSTDv07_decompress_usingDict(ZSTDv07_DCtx* dctx,
3873
+ void* dst, size_t dstCapacity,
3874
+ const void* src, size_t srcSize,
3875
+ const void* dict, size_t dictSize)
3876
+ {
3877
+ ZSTDv07_decompressBegin_usingDict(dctx, dict, dictSize);
3878
+ ZSTDv07_checkContinuity(dctx, dst);
3879
+ return ZSTDv07_decompressFrame(dctx, dst, dstCapacity, src, srcSize);
3880
+ }
3881
+
3882
+
3883
+ size_t ZSTDv07_decompressDCtx(ZSTDv07_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
3884
+ {
3885
+ return ZSTDv07_decompress_usingDict(dctx, dst, dstCapacity, src, srcSize, NULL, 0);
3886
+ }
3887
+
3888
+
3889
+ size_t ZSTDv07_decompress(void* dst, size_t dstCapacity, const void* src, size_t srcSize)
3890
+ {
3891
+ #if defined(ZSTDv07_HEAPMODE) && (ZSTDv07_HEAPMODE==1)
3892
+ size_t regenSize;
3893
+ ZSTDv07_DCtx* const dctx = ZSTDv07_createDCtx();
3894
+ if (dctx==NULL) return ERROR(memory_allocation);
3895
+ regenSize = ZSTDv07_decompressDCtx(dctx, dst, dstCapacity, src, srcSize);
3896
+ ZSTDv07_freeDCtx(dctx);
3897
+ return regenSize;
3898
+ #else /* stack mode */
3899
+ ZSTDv07_DCtx dctx;
3900
+ return ZSTDv07_decompressDCtx(&dctx, dst, dstCapacity, src, srcSize);
3901
+ #endif
3902
+ }
3903
+
3904
+ /* ZSTD_errorFrameSizeInfoLegacy() :
3905
+ assumes `cSize` and `dBound` are _not_ NULL */
3906
+ static void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)
3907
+ {
3908
+ *cSize = ret;
3909
+ *dBound = ZSTD_CONTENTSIZE_ERROR;
3910
+ }
3911
+
3912
+ void ZSTDv07_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)
3913
+ {
3914
+ const BYTE* ip = (const BYTE*)src;
3915
+ size_t remainingSize = srcSize;
3916
+ size_t nbBlocks = 0;
3917
+
3918
+ /* check */
3919
+ if (srcSize < ZSTDv07_frameHeaderSize_min+ZSTDv07_blockHeaderSize) {
3920
+ ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
3921
+ return;
3922
+ }
3923
+
3924
+ /* Frame Header */
3925
+ { size_t const frameHeaderSize = ZSTDv07_frameHeaderSize(src, srcSize);
3926
+ if (ZSTDv07_isError(frameHeaderSize)) {
3927
+ ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, frameHeaderSize);
3928
+ return;
3929
+ }
3930
+ if (MEM_readLE32(src) != ZSTDv07_MAGICNUMBER) {
3931
+ ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));
3932
+ return;
3933
+ }
3934
+ if (srcSize < frameHeaderSize+ZSTDv07_blockHeaderSize) {
3935
+ ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
3936
+ return;
3937
+ }
3938
+ ip += frameHeaderSize; remainingSize -= frameHeaderSize;
3939
+ }
3940
+
3941
+ /* Loop on each block */
3942
+ while (1) {
3943
+ blockProperties_t blockProperties;
3944
+ size_t const cBlockSize = ZSTDv07_getcBlockSize(ip, remainingSize, &blockProperties);
3945
+ if (ZSTDv07_isError(cBlockSize)) {
3946
+ ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize);
3947
+ return;
3948
+ }
3949
+
3950
+ ip += ZSTDv07_blockHeaderSize;
3951
+ remainingSize -= ZSTDv07_blockHeaderSize;
3952
+
3953
+ if (blockProperties.blockType == bt_end) break;
3954
+
3955
+ if (cBlockSize > remainingSize) {
3956
+ ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
3957
+ return;
3958
+ }
3959
+
3960
+ ip += cBlockSize;
3961
+ remainingSize -= cBlockSize;
3962
+ nbBlocks++;
3963
+ }
3964
+
3965
+ *cSize = ip - (const BYTE*)src;
3966
+ *dBound = nbBlocks * ZSTDv07_BLOCKSIZE_ABSOLUTEMAX;
3967
+ }
3968
+
3969
+ /*_******************************
3970
+ * Streaming Decompression API
3971
+ ********************************/
3972
+ size_t ZSTDv07_nextSrcSizeToDecompress(ZSTDv07_DCtx* dctx)
3973
+ {
3974
+ return dctx->expected;
3975
+ }
3976
+
3977
+ int ZSTDv07_isSkipFrame(ZSTDv07_DCtx* dctx)
3978
+ {
3979
+ return dctx->stage == ZSTDds_skipFrame;
3980
+ }
3981
+
3982
+ /** ZSTDv07_decompressContinue() :
3983
+ * @return : nb of bytes generated into `dst` (necessarily <= `dstCapacity)
3984
+ * or an error code, which can be tested using ZSTDv07_isError() */
3985
+ size_t ZSTDv07_decompressContinue(ZSTDv07_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
3986
+ {
3987
+ /* Sanity check */
3988
+ if (srcSize != dctx->expected) return ERROR(srcSize_wrong);
3989
+ if (dstCapacity) ZSTDv07_checkContinuity(dctx, dst);
3990
+
3991
+ switch (dctx->stage)
3992
+ {
3993
+ case ZSTDds_getFrameHeaderSize :
3994
+ if (srcSize != ZSTDv07_frameHeaderSize_min) return ERROR(srcSize_wrong); /* impossible */
3995
+ if ((MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTDv07_MAGIC_SKIPPABLE_START) {
3996
+ memcpy(dctx->headerBuffer, src, ZSTDv07_frameHeaderSize_min);
3997
+ dctx->expected = ZSTDv07_skippableHeaderSize - ZSTDv07_frameHeaderSize_min; /* magic number + skippable frame length */
3998
+ dctx->stage = ZSTDds_decodeSkippableHeader;
3999
+ return 0;
4000
+ }
4001
+ dctx->headerSize = ZSTDv07_frameHeaderSize(src, ZSTDv07_frameHeaderSize_min);
4002
+ if (ZSTDv07_isError(dctx->headerSize)) return dctx->headerSize;
4003
+ memcpy(dctx->headerBuffer, src, ZSTDv07_frameHeaderSize_min);
4004
+ if (dctx->headerSize > ZSTDv07_frameHeaderSize_min) {
4005
+ dctx->expected = dctx->headerSize - ZSTDv07_frameHeaderSize_min;
4006
+ dctx->stage = ZSTDds_decodeFrameHeader;
4007
+ return 0;
4008
+ }
4009
+ dctx->expected = 0; /* not necessary to copy more */
4010
+ /* fall-through */
4011
+ case ZSTDds_decodeFrameHeader:
4012
+ { size_t result;
4013
+ memcpy(dctx->headerBuffer + ZSTDv07_frameHeaderSize_min, src, dctx->expected);
4014
+ result = ZSTDv07_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize);
4015
+ if (ZSTDv07_isError(result)) return result;
4016
+ dctx->expected = ZSTDv07_blockHeaderSize;
4017
+ dctx->stage = ZSTDds_decodeBlockHeader;
4018
+ return 0;
4019
+ }
4020
+ case ZSTDds_decodeBlockHeader:
4021
+ { blockProperties_t bp;
4022
+ size_t const cBlockSize = ZSTDv07_getcBlockSize(src, ZSTDv07_blockHeaderSize, &bp);
4023
+ if (ZSTDv07_isError(cBlockSize)) return cBlockSize;
4024
+ if (bp.blockType == bt_end) {
4025
+ if (dctx->fParams.checksumFlag) {
4026
+ U64 const h64 = XXH64_digest(&dctx->xxhState);
4027
+ U32 const h32 = (U32)(h64>>11) & ((1<<22)-1);
4028
+ const BYTE* const ip = (const BYTE*)src;
4029
+ U32 const check32 = ip[2] + (ip[1] << 8) + ((ip[0] & 0x3F) << 16);
4030
+ if (check32 != h32) return ERROR(checksum_wrong);
4031
+ }
4032
+ dctx->expected = 0;
4033
+ dctx->stage = ZSTDds_getFrameHeaderSize;
4034
+ } else {
4035
+ dctx->expected = cBlockSize;
4036
+ dctx->bType = bp.blockType;
4037
+ dctx->stage = ZSTDds_decompressBlock;
4038
+ }
4039
+ return 0;
4040
+ }
4041
+ case ZSTDds_decompressBlock:
4042
+ { size_t rSize;
4043
+ switch(dctx->bType)
4044
+ {
4045
+ case bt_compressed:
4046
+ rSize = ZSTDv07_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize);
4047
+ break;
4048
+ case bt_raw :
4049
+ rSize = ZSTDv07_copyRawBlock(dst, dstCapacity, src, srcSize);
4050
+ break;
4051
+ case bt_rle :
4052
+ return ERROR(GENERIC); /* not yet handled */
4053
+ break;
4054
+ case bt_end : /* should never happen (filtered at phase 1) */
4055
+ rSize = 0;
4056
+ break;
4057
+ default:
4058
+ return ERROR(GENERIC); /* impossible */
4059
+ }
4060
+ dctx->stage = ZSTDds_decodeBlockHeader;
4061
+ dctx->expected = ZSTDv07_blockHeaderSize;
4062
+ dctx->previousDstEnd = (char*)dst + rSize;
4063
+ if (ZSTDv07_isError(rSize)) return rSize;
4064
+ if (dctx->fParams.checksumFlag) XXH64_update(&dctx->xxhState, dst, rSize);
4065
+ return rSize;
4066
+ }
4067
+ case ZSTDds_decodeSkippableHeader:
4068
+ { memcpy(dctx->headerBuffer + ZSTDv07_frameHeaderSize_min, src, dctx->expected);
4069
+ dctx->expected = MEM_readLE32(dctx->headerBuffer + 4);
4070
+ dctx->stage = ZSTDds_skipFrame;
4071
+ return 0;
4072
+ }
4073
+ case ZSTDds_skipFrame:
4074
+ { dctx->expected = 0;
4075
+ dctx->stage = ZSTDds_getFrameHeaderSize;
4076
+ return 0;
4077
+ }
4078
+ default:
4079
+ return ERROR(GENERIC); /* impossible */
4080
+ }
4081
+ }
4082
+
4083
+
4084
+ static size_t ZSTDv07_refDictContent(ZSTDv07_DCtx* dctx, const void* dict, size_t dictSize)
4085
+ {
4086
+ dctx->dictEnd = dctx->previousDstEnd;
4087
+ dctx->vBase = (const char*)dict - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->base));
4088
+ dctx->base = dict;
4089
+ dctx->previousDstEnd = (const char*)dict + dictSize;
4090
+ return 0;
4091
+ }
4092
+
4093
+ static size_t ZSTDv07_loadEntropy(ZSTDv07_DCtx* dctx, const void* const dict, size_t const dictSize)
4094
+ {
4095
+ const BYTE* dictPtr = (const BYTE*)dict;
4096
+ const BYTE* const dictEnd = dictPtr + dictSize;
4097
+
4098
+ { size_t const hSize = HUFv07_readDTableX4(dctx->hufTable, dict, dictSize);
4099
+ if (HUFv07_isError(hSize)) return ERROR(dictionary_corrupted);
4100
+ dictPtr += hSize;
4101
+ }
4102
+
4103
+ { short offcodeNCount[MaxOff+1];
4104
+ U32 offcodeMaxValue=MaxOff, offcodeLog;
4105
+ size_t const offcodeHeaderSize = FSEv07_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
4106
+ if (FSEv07_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted);
4107
+ if (offcodeLog > OffFSELog) return ERROR(dictionary_corrupted);
4108
+ { size_t const errorCode = FSEv07_buildDTable(dctx->OffTable, offcodeNCount, offcodeMaxValue, offcodeLog);
4109
+ if (FSEv07_isError(errorCode)) return ERROR(dictionary_corrupted); }
4110
+ dictPtr += offcodeHeaderSize;
4111
+ }
4112
+
4113
+ { short matchlengthNCount[MaxML+1];
4114
+ unsigned matchlengthMaxValue = MaxML, matchlengthLog;
4115
+ size_t const matchlengthHeaderSize = FSEv07_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);
4116
+ if (FSEv07_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted);
4117
+ if (matchlengthLog > MLFSELog) return ERROR(dictionary_corrupted);
4118
+ { size_t const errorCode = FSEv07_buildDTable(dctx->MLTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog);
4119
+ if (FSEv07_isError(errorCode)) return ERROR(dictionary_corrupted); }
4120
+ dictPtr += matchlengthHeaderSize;
4121
+ }
4122
+
4123
+ { short litlengthNCount[MaxLL+1];
4124
+ unsigned litlengthMaxValue = MaxLL, litlengthLog;
4125
+ size_t const litlengthHeaderSize = FSEv07_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);
4126
+ if (FSEv07_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted);
4127
+ if (litlengthLog > LLFSELog) return ERROR(dictionary_corrupted);
4128
+ { size_t const errorCode = FSEv07_buildDTable(dctx->LLTable, litlengthNCount, litlengthMaxValue, litlengthLog);
4129
+ if (FSEv07_isError(errorCode)) return ERROR(dictionary_corrupted); }
4130
+ dictPtr += litlengthHeaderSize;
4131
+ }
4132
+
4133
+ if (dictPtr+12 > dictEnd) return ERROR(dictionary_corrupted);
4134
+ dctx->rep[0] = MEM_readLE32(dictPtr+0); if (dctx->rep[0] == 0 || dctx->rep[0] >= dictSize) return ERROR(dictionary_corrupted);
4135
+ dctx->rep[1] = MEM_readLE32(dictPtr+4); if (dctx->rep[1] == 0 || dctx->rep[1] >= dictSize) return ERROR(dictionary_corrupted);
4136
+ dctx->rep[2] = MEM_readLE32(dictPtr+8); if (dctx->rep[2] == 0 || dctx->rep[2] >= dictSize) return ERROR(dictionary_corrupted);
4137
+ dictPtr += 12;
4138
+
4139
+ dctx->litEntropy = dctx->fseEntropy = 1;
4140
+ return dictPtr - (const BYTE*)dict;
4141
+ }
4142
+
4143
+ static size_t ZSTDv07_decompress_insertDictionary(ZSTDv07_DCtx* dctx, const void* dict, size_t dictSize)
4144
+ {
4145
+ if (dictSize < 8) return ZSTDv07_refDictContent(dctx, dict, dictSize);
4146
+ { U32 const magic = MEM_readLE32(dict);
4147
+ if (magic != ZSTDv07_DICT_MAGIC) {
4148
+ return ZSTDv07_refDictContent(dctx, dict, dictSize); /* pure content mode */
4149
+ } }
4150
+ dctx->dictID = MEM_readLE32((const char*)dict + 4);
4151
+
4152
+ /* load entropy tables */
4153
+ dict = (const char*)dict + 8;
4154
+ dictSize -= 8;
4155
+ { size_t const eSize = ZSTDv07_loadEntropy(dctx, dict, dictSize);
4156
+ if (ZSTDv07_isError(eSize)) return ERROR(dictionary_corrupted);
4157
+ dict = (const char*)dict + eSize;
4158
+ dictSize -= eSize;
4159
+ }
4160
+
4161
+ /* reference dictionary content */
4162
+ return ZSTDv07_refDictContent(dctx, dict, dictSize);
4163
+ }
4164
+
4165
+
4166
+ size_t ZSTDv07_decompressBegin_usingDict(ZSTDv07_DCtx* dctx, const void* dict, size_t dictSize)
4167
+ {
4168
+ { size_t const errorCode = ZSTDv07_decompressBegin(dctx);
4169
+ if (ZSTDv07_isError(errorCode)) return errorCode; }
4170
+
4171
+ if (dict && dictSize) {
4172
+ size_t const errorCode = ZSTDv07_decompress_insertDictionary(dctx, dict, dictSize);
4173
+ if (ZSTDv07_isError(errorCode)) return ERROR(dictionary_corrupted);
4174
+ }
4175
+
4176
+ return 0;
4177
+ }
4178
+
4179
+
4180
+ struct ZSTDv07_DDict_s {
4181
+ void* dict;
4182
+ size_t dictSize;
4183
+ ZSTDv07_DCtx* refContext;
4184
+ }; /* typedef'd tp ZSTDv07_CDict within zstd.h */
4185
+
4186
+ static ZSTDv07_DDict* ZSTDv07_createDDict_advanced(const void* dict, size_t dictSize, ZSTDv07_customMem customMem)
4187
+ {
4188
+ if (!customMem.customAlloc && !customMem.customFree)
4189
+ customMem = defaultCustomMem;
4190
+
4191
+ if (!customMem.customAlloc || !customMem.customFree)
4192
+ return NULL;
4193
+
4194
+ { ZSTDv07_DDict* const ddict = (ZSTDv07_DDict*) customMem.customAlloc(customMem.opaque, sizeof(*ddict));
4195
+ void* const dictContent = customMem.customAlloc(customMem.opaque, dictSize);
4196
+ ZSTDv07_DCtx* const dctx = ZSTDv07_createDCtx_advanced(customMem);
4197
+
4198
+ if (!dictContent || !ddict || !dctx) {
4199
+ customMem.customFree(customMem.opaque, dictContent);
4200
+ customMem.customFree(customMem.opaque, ddict);
4201
+ customMem.customFree(customMem.opaque, dctx);
4202
+ return NULL;
4203
+ }
4204
+
4205
+ memcpy(dictContent, dict, dictSize);
4206
+ { size_t const errorCode = ZSTDv07_decompressBegin_usingDict(dctx, dictContent, dictSize);
4207
+ if (ZSTDv07_isError(errorCode)) {
4208
+ customMem.customFree(customMem.opaque, dictContent);
4209
+ customMem.customFree(customMem.opaque, ddict);
4210
+ customMem.customFree(customMem.opaque, dctx);
4211
+ return NULL;
4212
+ } }
4213
+
4214
+ ddict->dict = dictContent;
4215
+ ddict->dictSize = dictSize;
4216
+ ddict->refContext = dctx;
4217
+ return ddict;
4218
+ }
4219
+ }
4220
+
4221
+ /*! ZSTDv07_createDDict() :
4222
+ * Create a digested dictionary, ready to start decompression without startup delay.
4223
+ * `dict` can be released after `ZSTDv07_DDict` creation */
4224
+ ZSTDv07_DDict* ZSTDv07_createDDict(const void* dict, size_t dictSize)
4225
+ {
4226
+ ZSTDv07_customMem const allocator = { NULL, NULL, NULL };
4227
+ return ZSTDv07_createDDict_advanced(dict, dictSize, allocator);
4228
+ }
4229
+
4230
+ size_t ZSTDv07_freeDDict(ZSTDv07_DDict* ddict)
4231
+ {
4232
+ ZSTDv07_freeFunction const cFree = ddict->refContext->customMem.customFree;
4233
+ void* const opaque = ddict->refContext->customMem.opaque;
4234
+ ZSTDv07_freeDCtx(ddict->refContext);
4235
+ cFree(opaque, ddict->dict);
4236
+ cFree(opaque, ddict);
4237
+ return 0;
4238
+ }
4239
+
4240
+ /*! ZSTDv07_decompress_usingDDict() :
4241
+ * Decompression using a pre-digested Dictionary
4242
+ * Use dictionary without significant overhead. */
4243
+ ZSTDLIBv07_API size_t ZSTDv07_decompress_usingDDict(ZSTDv07_DCtx* dctx,
4244
+ void* dst, size_t dstCapacity,
4245
+ const void* src, size_t srcSize,
4246
+ const ZSTDv07_DDict* ddict)
4247
+ {
4248
+ return ZSTDv07_decompress_usingPreparedDCtx(dctx, ddict->refContext,
4249
+ dst, dstCapacity,
4250
+ src, srcSize);
4251
+ }
4252
+ /*
4253
+ Buffered version of Zstd compression library
4254
+ Copyright (C) 2015-2016, Yann Collet.
4255
+
4256
+ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
4257
+
4258
+ Redistribution and use in source and binary forms, with or without
4259
+ modification, are permitted provided that the following conditions are
4260
+ met:
4261
+ * Redistributions of source code must retain the above copyright
4262
+ notice, this list of conditions and the following disclaimer.
4263
+ * Redistributions in binary form must reproduce the above
4264
+ copyright notice, this list of conditions and the following disclaimer
4265
+ in the documentation and/or other materials provided with the
4266
+ distribution.
4267
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4268
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
4269
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
4270
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
4271
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
4272
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
4273
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
4274
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
4275
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
4276
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
4277
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4278
+
4279
+ You can contact the author at :
4280
+ - zstd homepage : http://www.zstd.net/
4281
+ */
4282
+
4283
+
4284
+
4285
+ /*-***************************************************************************
4286
+ * Streaming decompression howto
4287
+ *
4288
+ * A ZBUFFv07_DCtx object is required to track streaming operations.
4289
+ * Use ZBUFFv07_createDCtx() and ZBUFFv07_freeDCtx() to create/release resources.
4290
+ * Use ZBUFFv07_decompressInit() to start a new decompression operation,
4291
+ * or ZBUFFv07_decompressInitDictionary() if decompression requires a dictionary.
4292
+ * Note that ZBUFFv07_DCtx objects can be re-init multiple times.
4293
+ *
4294
+ * Use ZBUFFv07_decompressContinue() repetitively to consume your input.
4295
+ * *srcSizePtr and *dstCapacityPtr can be any size.
4296
+ * The function will report how many bytes were read or written by modifying *srcSizePtr and *dstCapacityPtr.
4297
+ * Note that it may not consume the entire input, in which case it's up to the caller to present remaining input again.
4298
+ * The content of @dst will be overwritten (up to *dstCapacityPtr) at each function call, so save its content if it matters, or change @dst.
4299
+ * @return : a hint to preferred nb of bytes to use as input for next function call (it's only a hint, to help latency),
4300
+ * or 0 when a frame is completely decoded,
4301
+ * or an error code, which can be tested using ZBUFFv07_isError().
4302
+ *
4303
+ * Hint : recommended buffer sizes (not compulsory) : ZBUFFv07_recommendedDInSize() and ZBUFFv07_recommendedDOutSize()
4304
+ * output : ZBUFFv07_recommendedDOutSize==128 KB block size is the internal unit, it ensures it's always possible to write a full block when decoded.
4305
+ * input : ZBUFFv07_recommendedDInSize == 128KB + 3;
4306
+ * just follow indications from ZBUFFv07_decompressContinue() to minimize latency. It should always be <= 128 KB + 3 .
4307
+ * *******************************************************************************/
4308
+
4309
+ typedef enum { ZBUFFds_init, ZBUFFds_loadHeader,
4310
+ ZBUFFds_read, ZBUFFds_load, ZBUFFds_flush } ZBUFFv07_dStage;
4311
+
4312
+ /* *** Resource management *** */
4313
+ struct ZBUFFv07_DCtx_s {
4314
+ ZSTDv07_DCtx* zd;
4315
+ ZSTDv07_frameParams fParams;
4316
+ ZBUFFv07_dStage stage;
4317
+ char* inBuff;
4318
+ size_t inBuffSize;
4319
+ size_t inPos;
4320
+ char* outBuff;
4321
+ size_t outBuffSize;
4322
+ size_t outStart;
4323
+ size_t outEnd;
4324
+ size_t blockSize;
4325
+ BYTE headerBuffer[ZSTDv07_FRAMEHEADERSIZE_MAX];
4326
+ size_t lhSize;
4327
+ ZSTDv07_customMem customMem;
4328
+ }; /* typedef'd to ZBUFFv07_DCtx within "zstd_buffered.h" */
4329
+
4330
+ ZSTDLIBv07_API ZBUFFv07_DCtx* ZBUFFv07_createDCtx_advanced(ZSTDv07_customMem customMem);
4331
+
4332
+ ZBUFFv07_DCtx* ZBUFFv07_createDCtx(void)
4333
+ {
4334
+ return ZBUFFv07_createDCtx_advanced(defaultCustomMem);
4335
+ }
4336
+
4337
+ ZBUFFv07_DCtx* ZBUFFv07_createDCtx_advanced(ZSTDv07_customMem customMem)
4338
+ {
4339
+ ZBUFFv07_DCtx* zbd;
4340
+
4341
+ if (!customMem.customAlloc && !customMem.customFree)
4342
+ customMem = defaultCustomMem;
4343
+
4344
+ if (!customMem.customAlloc || !customMem.customFree)
4345
+ return NULL;
4346
+
4347
+ zbd = (ZBUFFv07_DCtx*)customMem.customAlloc(customMem.opaque, sizeof(ZBUFFv07_DCtx));
4348
+ if (zbd==NULL) return NULL;
4349
+ memset(zbd, 0, sizeof(ZBUFFv07_DCtx));
4350
+ memcpy(&zbd->customMem, &customMem, sizeof(ZSTDv07_customMem));
4351
+ zbd->zd = ZSTDv07_createDCtx_advanced(customMem);
4352
+ if (zbd->zd == NULL) { ZBUFFv07_freeDCtx(zbd); return NULL; }
4353
+ zbd->stage = ZBUFFds_init;
4354
+ return zbd;
4355
+ }
4356
+
4357
+ size_t ZBUFFv07_freeDCtx(ZBUFFv07_DCtx* zbd)
4358
+ {
4359
+ if (zbd==NULL) return 0; /* support free on null */
4360
+ ZSTDv07_freeDCtx(zbd->zd);
4361
+ if (zbd->inBuff) zbd->customMem.customFree(zbd->customMem.opaque, zbd->inBuff);
4362
+ if (zbd->outBuff) zbd->customMem.customFree(zbd->customMem.opaque, zbd->outBuff);
4363
+ zbd->customMem.customFree(zbd->customMem.opaque, zbd);
4364
+ return 0;
4365
+ }
4366
+
4367
+
4368
+ /* *** Initialization *** */
4369
+
4370
+ size_t ZBUFFv07_decompressInitDictionary(ZBUFFv07_DCtx* zbd, const void* dict, size_t dictSize)
4371
+ {
4372
+ zbd->stage = ZBUFFds_loadHeader;
4373
+ zbd->lhSize = zbd->inPos = zbd->outStart = zbd->outEnd = 0;
4374
+ return ZSTDv07_decompressBegin_usingDict(zbd->zd, dict, dictSize);
4375
+ }
4376
+
4377
+ size_t ZBUFFv07_decompressInit(ZBUFFv07_DCtx* zbd)
4378
+ {
4379
+ return ZBUFFv07_decompressInitDictionary(zbd, NULL, 0);
4380
+ }
4381
+
4382
+
4383
+ /* internal util function */
4384
+ MEM_STATIC size_t ZBUFFv07_limitCopy(void* dst, size_t dstCapacity, const void* src, size_t srcSize)
4385
+ {
4386
+ size_t const length = MIN(dstCapacity, srcSize);
4387
+ if (length > 0) {
4388
+ memcpy(dst, src, length);
4389
+ }
4390
+ return length;
4391
+ }
4392
+
4393
+
4394
+ /* *** Decompression *** */
4395
+
4396
+ size_t ZBUFFv07_decompressContinue(ZBUFFv07_DCtx* zbd,
4397
+ void* dst, size_t* dstCapacityPtr,
4398
+ const void* src, size_t* srcSizePtr)
4399
+ {
4400
+ const char* const istart = (const char*)src;
4401
+ const char* const iend = istart + *srcSizePtr;
4402
+ const char* ip = istart;
4403
+ char* const ostart = (char*)dst;
4404
+ char* const oend = ostart + *dstCapacityPtr;
4405
+ char* op = ostart;
4406
+ U32 notDone = 1;
4407
+
4408
+ while (notDone) {
4409
+ switch(zbd->stage)
4410
+ {
4411
+ case ZBUFFds_init :
4412
+ return ERROR(init_missing);
4413
+
4414
+ case ZBUFFds_loadHeader :
4415
+ { size_t const hSize = ZSTDv07_getFrameParams(&(zbd->fParams), zbd->headerBuffer, zbd->lhSize);
4416
+ if (ZSTDv07_isError(hSize)) return hSize;
4417
+ if (hSize != 0) {
4418
+ size_t const toLoad = hSize - zbd->lhSize; /* if hSize!=0, hSize > zbd->lhSize */
4419
+ if (toLoad > (size_t)(iend-ip)) { /* not enough input to load full header */
4420
+ memcpy(zbd->headerBuffer + zbd->lhSize, ip, iend-ip);
4421
+ zbd->lhSize += iend-ip;
4422
+ *dstCapacityPtr = 0;
4423
+ return (hSize - zbd->lhSize) + ZSTDv07_blockHeaderSize; /* remaining header bytes + next block header */
4424
+ }
4425
+ memcpy(zbd->headerBuffer + zbd->lhSize, ip, toLoad); zbd->lhSize = hSize; ip += toLoad;
4426
+ break;
4427
+ } }
4428
+
4429
+ /* Consume header */
4430
+ { size_t const h1Size = ZSTDv07_nextSrcSizeToDecompress(zbd->zd); /* == ZSTDv07_frameHeaderSize_min */
4431
+ size_t const h1Result = ZSTDv07_decompressContinue(zbd->zd, NULL, 0, zbd->headerBuffer, h1Size);
4432
+ if (ZSTDv07_isError(h1Result)) return h1Result;
4433
+ if (h1Size < zbd->lhSize) { /* long header */
4434
+ size_t const h2Size = ZSTDv07_nextSrcSizeToDecompress(zbd->zd);
4435
+ size_t const h2Result = ZSTDv07_decompressContinue(zbd->zd, NULL, 0, zbd->headerBuffer+h1Size, h2Size);
4436
+ if (ZSTDv07_isError(h2Result)) return h2Result;
4437
+ } }
4438
+
4439
+ zbd->fParams.windowSize = MAX(zbd->fParams.windowSize, 1U << ZSTDv07_WINDOWLOG_ABSOLUTEMIN);
4440
+
4441
+ /* Frame header instruct buffer sizes */
4442
+ { size_t const blockSize = MIN(zbd->fParams.windowSize, ZSTDv07_BLOCKSIZE_ABSOLUTEMAX);
4443
+ zbd->blockSize = blockSize;
4444
+ if (zbd->inBuffSize < blockSize) {
4445
+ zbd->customMem.customFree(zbd->customMem.opaque, zbd->inBuff);
4446
+ zbd->inBuffSize = blockSize;
4447
+ zbd->inBuff = (char*)zbd->customMem.customAlloc(zbd->customMem.opaque, blockSize);
4448
+ if (zbd->inBuff == NULL) return ERROR(memory_allocation);
4449
+ }
4450
+ { size_t const neededOutSize = zbd->fParams.windowSize + blockSize + WILDCOPY_OVERLENGTH * 2;
4451
+ if (zbd->outBuffSize < neededOutSize) {
4452
+ zbd->customMem.customFree(zbd->customMem.opaque, zbd->outBuff);
4453
+ zbd->outBuffSize = neededOutSize;
4454
+ zbd->outBuff = (char*)zbd->customMem.customAlloc(zbd->customMem.opaque, neededOutSize);
4455
+ if (zbd->outBuff == NULL) return ERROR(memory_allocation);
4456
+ } } }
4457
+ zbd->stage = ZBUFFds_read;
4458
+ /* pass-through */
4459
+ /* fall-through */
4460
+ case ZBUFFds_read:
4461
+ { size_t const neededInSize = ZSTDv07_nextSrcSizeToDecompress(zbd->zd);
4462
+ if (neededInSize==0) { /* end of frame */
4463
+ zbd->stage = ZBUFFds_init;
4464
+ notDone = 0;
4465
+ break;
4466
+ }
4467
+ if ((size_t)(iend-ip) >= neededInSize) { /* decode directly from src */
4468
+ const int isSkipFrame = ZSTDv07_isSkipFrame(zbd->zd);
4469
+ size_t const decodedSize = ZSTDv07_decompressContinue(zbd->zd,
4470
+ zbd->outBuff + zbd->outStart, (isSkipFrame ? 0 : zbd->outBuffSize - zbd->outStart),
4471
+ ip, neededInSize);
4472
+ if (ZSTDv07_isError(decodedSize)) return decodedSize;
4473
+ ip += neededInSize;
4474
+ if (!decodedSize && !isSkipFrame) break; /* this was just a header */
4475
+ zbd->outEnd = zbd->outStart + decodedSize;
4476
+ zbd->stage = ZBUFFds_flush;
4477
+ break;
4478
+ }
4479
+ if (ip==iend) { notDone = 0; break; } /* no more input */
4480
+ zbd->stage = ZBUFFds_load;
4481
+ }
4482
+ /* fall-through */
4483
+ case ZBUFFds_load:
4484
+ { size_t const neededInSize = ZSTDv07_nextSrcSizeToDecompress(zbd->zd);
4485
+ size_t const toLoad = neededInSize - zbd->inPos; /* should always be <= remaining space within inBuff */
4486
+ size_t loadedSize;
4487
+ if (toLoad > zbd->inBuffSize - zbd->inPos) return ERROR(corruption_detected); /* should never happen */
4488
+ loadedSize = ZBUFFv07_limitCopy(zbd->inBuff + zbd->inPos, toLoad, ip, iend-ip);
4489
+ ip += loadedSize;
4490
+ zbd->inPos += loadedSize;
4491
+ if (loadedSize < toLoad) { notDone = 0; break; } /* not enough input, wait for more */
4492
+
4493
+ /* decode loaded input */
4494
+ { const int isSkipFrame = ZSTDv07_isSkipFrame(zbd->zd);
4495
+ size_t const decodedSize = ZSTDv07_decompressContinue(zbd->zd,
4496
+ zbd->outBuff + zbd->outStart, zbd->outBuffSize - zbd->outStart,
4497
+ zbd->inBuff, neededInSize);
4498
+ if (ZSTDv07_isError(decodedSize)) return decodedSize;
4499
+ zbd->inPos = 0; /* input is consumed */
4500
+ if (!decodedSize && !isSkipFrame) { zbd->stage = ZBUFFds_read; break; } /* this was just a header */
4501
+ zbd->outEnd = zbd->outStart + decodedSize;
4502
+ zbd->stage = ZBUFFds_flush;
4503
+ /* break; */
4504
+ /* pass-through */
4505
+ }
4506
+ }
4507
+ /* fall-through */
4508
+ case ZBUFFds_flush:
4509
+ { size_t const toFlushSize = zbd->outEnd - zbd->outStart;
4510
+ size_t const flushedSize = ZBUFFv07_limitCopy(op, oend-op, zbd->outBuff + zbd->outStart, toFlushSize);
4511
+ op += flushedSize;
4512
+ zbd->outStart += flushedSize;
4513
+ if (flushedSize == toFlushSize) {
4514
+ zbd->stage = ZBUFFds_read;
4515
+ if (zbd->outStart + zbd->blockSize > zbd->outBuffSize)
4516
+ zbd->outStart = zbd->outEnd = 0;
4517
+ break;
4518
+ }
4519
+ /* cannot flush everything */
4520
+ notDone = 0;
4521
+ break;
4522
+ }
4523
+ default: return ERROR(GENERIC); /* impossible */
4524
+ } }
4525
+
4526
+ /* result */
4527
+ *srcSizePtr = ip-istart;
4528
+ *dstCapacityPtr = op-ostart;
4529
+ { size_t nextSrcSizeHint = ZSTDv07_nextSrcSizeToDecompress(zbd->zd);
4530
+ nextSrcSizeHint -= zbd->inPos; /* already loaded*/
4531
+ return nextSrcSizeHint;
4532
+ }
4533
+ }
4534
+
4535
+
4536
+
4537
+ /* *************************************
4538
+ * Tool functions
4539
+ ***************************************/
4540
+ size_t ZBUFFv07_recommendedDInSize(void) { return ZSTDv07_BLOCKSIZE_ABSOLUTEMAX + ZSTDv07_blockHeaderSize /* block header size*/ ; }
4541
+ size_t ZBUFFv07_recommendedDOutSize(void) { return ZSTDv07_BLOCKSIZE_ABSOLUTEMAX; }