pyxcp 0.21.10__cp311-cp311-win_amd64.whl → 0.22.23__cp311-cp311-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of pyxcp might be problematic. Click here for more details.

Files changed (179) hide show
  1. pyxcp/__init__.py +12 -20
  2. pyxcp/aml/EtasCANMonitoring.a2l +82 -83
  3. pyxcp/aml/XCP_Common.aml +0 -1
  4. pyxcp/aml/XCPonUSB.aml +1 -1
  5. pyxcp/aml/ifdata_CAN.a2l +0 -1
  6. pyxcp/aml/ifdata_Eth.a2l +0 -1
  7. pyxcp/aml/ifdata_Flx.a2l +0 -1
  8. pyxcp/aml/ifdata_SxI.a2l +0 -1
  9. pyxcp/aml/ifdata_USB.a2l +0 -1
  10. pyxcp/asam/types.py +4 -4
  11. pyxcp/asamkeydll.c +0 -1
  12. pyxcp/checksum.py +0 -1
  13. pyxcp/cmdline.py +32 -50
  14. pyxcp/config/__init__.py +1100 -0
  15. pyxcp/config/legacy.py +120 -0
  16. pyxcp/constants.py +12 -13
  17. pyxcp/cpp_ext/__init__.py +0 -0
  18. pyxcp/cpp_ext/bin.hpp +104 -0
  19. pyxcp/cpp_ext/blockmem.hpp +58 -0
  20. pyxcp/cpp_ext/cpp_ext.cp310-win_amd64.pyd +0 -0
  21. pyxcp/cpp_ext/cpp_ext.cp311-win_amd64.pyd +0 -0
  22. pyxcp/cpp_ext/cpp_ext.cp38-win_amd64.pyd +0 -0
  23. pyxcp/cpp_ext/cpp_ext.cp39-win_amd64.pyd +0 -0
  24. pyxcp/cpp_ext/daqlist.hpp +200 -0
  25. pyxcp/cpp_ext/event.hpp +67 -0
  26. pyxcp/cpp_ext/extension_wrapper.cpp +96 -0
  27. pyxcp/cpp_ext/helper.hpp +280 -0
  28. pyxcp/cpp_ext/mcobject.hpp +246 -0
  29. pyxcp/cpp_ext/tsqueue.hpp +46 -0
  30. pyxcp/daq_stim/__init__.py +228 -0
  31. pyxcp/daq_stim/optimize/__init__.py +67 -0
  32. pyxcp/daq_stim/optimize/binpacking.py +41 -0
  33. pyxcp/daq_stim/scheduler.cpp +28 -0
  34. pyxcp/daq_stim/scheduler.hpp +75 -0
  35. pyxcp/daq_stim/stim.cp310-win_amd64.pyd +0 -0
  36. pyxcp/daq_stim/stim.cp311-win_amd64.pyd +0 -0
  37. pyxcp/daq_stim/stim.cp38-win_amd64.pyd +0 -0
  38. pyxcp/daq_stim/stim.cp39-win_amd64.pyd +0 -0
  39. pyxcp/daq_stim/stim.cpp +13 -0
  40. pyxcp/daq_stim/stim.hpp +604 -0
  41. pyxcp/daq_stim/stim_wrapper.cpp +48 -0
  42. pyxcp/dllif.py +21 -18
  43. pyxcp/errormatrix.py +5 -3
  44. pyxcp/examples/conf_can.toml +4 -2
  45. pyxcp/examples/conf_can_vector.json +9 -9
  46. pyxcp/examples/conf_can_vector.toml +4 -2
  47. pyxcp/examples/conf_eth.toml +5 -2
  48. pyxcp/examples/conf_nixnet.json +18 -18
  49. pyxcp/examples/conf_sxi.json +7 -7
  50. pyxcp/examples/ex_arrow.py +109 -0
  51. pyxcp/examples/ex_csv.py +85 -0
  52. pyxcp/examples/ex_excel.py +95 -0
  53. pyxcp/examples/ex_mdf.py +124 -0
  54. pyxcp/examples/ex_sqlite.py +128 -0
  55. pyxcp/examples/run_daq.py +148 -0
  56. pyxcp/examples/xcp_policy.py +6 -7
  57. pyxcp/examples/xcp_read_benchmark.py +8 -6
  58. pyxcp/examples/xcp_skel.py +0 -2
  59. pyxcp/examples/xcp_unlock.py +1 -1
  60. pyxcp/examples/xcp_user_supplied_driver.py +1 -2
  61. pyxcp/examples/xcphello.py +6 -3
  62. pyxcp/examples/xcphello_recorder.py +4 -4
  63. pyxcp/master/__init__.py +1 -2
  64. pyxcp/master/errorhandler.py +107 -74
  65. pyxcp/master/master.py +201 -119
  66. pyxcp/py.typed +0 -0
  67. pyxcp/recorder/__init__.py +27 -6
  68. pyxcp/recorder/converter/__init__.py +37 -0
  69. pyxcp/recorder/lz4.c +129 -51
  70. pyxcp/recorder/lz4.h +45 -28
  71. pyxcp/recorder/lz4hc.c +560 -156
  72. pyxcp/recorder/lz4hc.h +1 -1
  73. pyxcp/recorder/mio.hpp +721 -767
  74. pyxcp/recorder/reader.hpp +139 -0
  75. pyxcp/recorder/reco.py +5 -8
  76. pyxcp/recorder/rekorder.cp310-win_amd64.pyd +0 -0
  77. pyxcp/recorder/rekorder.cp311-win_amd64.pyd +0 -0
  78. pyxcp/recorder/rekorder.cp38-win_amd64.pyd +0 -0
  79. pyxcp/recorder/rekorder.cp39-win_amd64.pyd +0 -0
  80. pyxcp/recorder/rekorder.cpp +18 -22
  81. pyxcp/recorder/rekorder.hpp +200 -587
  82. pyxcp/recorder/setup.py +11 -10
  83. pyxcp/recorder/test_reko.py +2 -3
  84. pyxcp/recorder/unfolder.hpp +1332 -0
  85. pyxcp/recorder/wrap.cpp +171 -9
  86. pyxcp/recorder/writer.hpp +302 -0
  87. pyxcp/scripts/pyxcp_probe_can_drivers.py +0 -2
  88. pyxcp/scripts/xcp_examples.py +64 -0
  89. pyxcp/scripts/xcp_fetch_a2l.py +15 -10
  90. pyxcp/scripts/xcp_id_scanner.py +2 -6
  91. pyxcp/scripts/xcp_info.py +101 -63
  92. pyxcp/scripts/xcp_profile.py +27 -0
  93. pyxcp/stim/__init__.py +0 -0
  94. pyxcp/tests/test_asam_types.py +2 -2
  95. pyxcp/tests/test_binpacking.py +186 -0
  96. pyxcp/tests/test_can.py +1132 -38
  97. pyxcp/tests/test_checksum.py +2 -1
  98. pyxcp/tests/test_daq.py +193 -0
  99. pyxcp/tests/test_frame_padding.py +6 -3
  100. pyxcp/tests/test_master.py +42 -31
  101. pyxcp/tests/test_transport.py +12 -12
  102. pyxcp/tests/test_utils.py +2 -5
  103. pyxcp/timing.py +0 -2
  104. pyxcp/transport/__init__.py +9 -9
  105. pyxcp/transport/base.py +149 -127
  106. pyxcp/transport/base_transport.hpp +0 -0
  107. pyxcp/transport/can.py +194 -167
  108. pyxcp/transport/eth.py +80 -82
  109. pyxcp/transport/sxi.py +106 -60
  110. pyxcp/transport/transport_wrapper.cpp +0 -0
  111. pyxcp/transport/usb_transport.py +65 -83
  112. pyxcp/types.py +69 -20
  113. pyxcp/utils.py +47 -16
  114. pyxcp/vector/map.py +1 -3
  115. {pyxcp-0.21.10.dist-info → pyxcp-0.22.23.dist-info}/METADATA +28 -23
  116. pyxcp-0.22.23.dist-info/RECORD +137 -0
  117. {pyxcp-0.21.10.dist-info → pyxcp-0.22.23.dist-info}/WHEEL +1 -1
  118. {pyxcp-0.21.10.dist-info → pyxcp-0.22.23.dist-info}/entry_points.txt +2 -0
  119. pyxcp/config.py +0 -57
  120. pyxcp/cxx/asynchiofactory.hpp +0 -24
  121. pyxcp/cxx/blocking_client.cpp +0 -44
  122. pyxcp/cxx/blocking_socket.cpp +0 -43
  123. pyxcp/cxx/blocking_socket.hpp +0 -558
  124. pyxcp/cxx/concurrent_queue.hpp +0 -60
  125. pyxcp/cxx/eth.hpp +0 -57
  126. pyxcp/cxx/exceptions.hpp +0 -30
  127. pyxcp/cxx/iasyncioservice.hpp +0 -31
  128. pyxcp/cxx/iresource.hpp +0 -17
  129. pyxcp/cxx/isocket.hpp +0 -22
  130. pyxcp/cxx/linux/epoll.cpp +0 -51
  131. pyxcp/cxx/linux/epoll.hpp +0 -87
  132. pyxcp/cxx/linux/lit_tester.cpp +0 -19
  133. pyxcp/cxx/linux/socket.hpp +0 -234
  134. pyxcp/cxx/linux/timeout.hpp +0 -81
  135. pyxcp/cxx/memoryblock.hpp +0 -42
  136. pyxcp/cxx/pool.hpp +0 -81
  137. pyxcp/cxx/poolmgr.cpp +0 -6
  138. pyxcp/cxx/poolmgr.hpp +0 -31
  139. pyxcp/cxx/test_queue.cpp +0 -69
  140. pyxcp/cxx/timestamp.hpp +0 -84
  141. pyxcp/cxx/utils.cpp +0 -38
  142. pyxcp/cxx/utils.hpp +0 -29
  143. pyxcp/cxx/win/iocp.cpp +0 -242
  144. pyxcp/cxx/win/iocp.hpp +0 -42
  145. pyxcp/cxx/win/perhandledata.hpp +0 -24
  146. pyxcp/cxx/win/periodata.hpp +0 -97
  147. pyxcp/cxx/win/socket.hpp +0 -185
  148. pyxcp/cxx/win/timeout.hpp +0 -83
  149. pyxcp/examples/conf_can.json +0 -20
  150. pyxcp/examples/conf_eth.json +0 -8
  151. pyxcp/logger.py +0 -67
  152. pyxcp/tests/test_config.py +0 -62
  153. pyxcp/transport/candriver/__init__.py +0 -2
  154. pyxcp/transport/candriver/pc_canalystii.py +0 -27
  155. pyxcp/transport/candriver/pc_etas.py +0 -25
  156. pyxcp/transport/candriver/pc_gsusb.py +0 -23
  157. pyxcp/transport/candriver/pc_iscan.py +0 -23
  158. pyxcp/transport/candriver/pc_ixxat.py +0 -27
  159. pyxcp/transport/candriver/pc_kvaser.py +0 -39
  160. pyxcp/transport/candriver/pc_neovi.py +0 -31
  161. pyxcp/transport/candriver/pc_nican.py +0 -23
  162. pyxcp/transport/candriver/pc_nixnet.py +0 -23
  163. pyxcp/transport/candriver/pc_pcan.py +0 -25
  164. pyxcp/transport/candriver/pc_seeed.py +0 -28
  165. pyxcp/transport/candriver/pc_serial.py +0 -27
  166. pyxcp/transport/candriver/pc_slcan.py +0 -29
  167. pyxcp/transport/candriver/pc_socketcan.py +0 -23
  168. pyxcp/transport/candriver/pc_systec.py +0 -29
  169. pyxcp/transport/candriver/pc_usb2can.py +0 -30
  170. pyxcp/transport/candriver/pc_vector.py +0 -34
  171. pyxcp/transport/candriver/python_can.py +0 -101
  172. pyxcp/transport/cxx_ext/CMakeLists.txt +0 -51
  173. pyxcp/transport/cxx_ext/setup.py +0 -49
  174. pyxcp/transport/cxx_ext/tests/test_basic_socket.cpp +0 -39
  175. pyxcp/transport/cxx_ext/tests/test_pool.cpp +0 -39
  176. pyxcp/transport/cxx_ext/tests/test_timestamp.cpp +0 -27
  177. pyxcp-0.21.10.dist-info/RECORD +0 -147
  178. rekorder.cp311-win_amd64.pyd +0 -0
  179. {pyxcp-0.21.10.dist-info/licenses → pyxcp-0.22.23.dist-info}/LICENSE +0 -0
pyxcp/recorder/lz4hc.c CHANGED
@@ -52,19 +52,19 @@
52
52
  /*=== Dependency ===*/
53
53
  #define LZ4_HC_STATIC_LINKING_ONLY
54
54
  #include "lz4hc.h"
55
+ #include <limits.h>
55
56
 
56
57
 
57
- /*=== Common definitions ===*/
58
- #if defined(__GNUC__)
58
+ /*=== Shared lz4.c code ===*/
59
+ #ifndef LZ4_SRC_INCLUDED
60
+ # if defined(__GNUC__)
59
61
  # pragma GCC diagnostic ignored "-Wunused-function"
60
- #endif
61
- #if defined (__clang__)
62
+ # endif
63
+ # if defined (__clang__)
62
64
  # pragma clang diagnostic ignored "-Wunused-function"
63
- #endif
64
-
65
- #define LZ4_COMMONDEFS_ONLY
66
- #ifndef LZ4_SRC_INCLUDED
67
- #include "lz4.c" /* LZ4_count, constants, mem */
65
+ # endif
66
+ # define LZ4_COMMONDEFS_ONLY
67
+ # include "lz4.c" /* LZ4_count, constants, mem */
68
68
  #endif
69
69
 
70
70
 
@@ -80,18 +80,122 @@ typedef enum { noDictCtx, usingDictCtxHc } dictCtx_directive;
80
80
  /*=== Macros ===*/
81
81
  #define MIN(a,b) ( (a) < (b) ? (a) : (b) )
82
82
  #define MAX(a,b) ( (a) > (b) ? (a) : (b) )
83
- #define HASH_FUNCTION(i) (((i) * 2654435761U) >> ((MINMATCH*8)-LZ4HC_HASH_LOG))
84
- #define DELTANEXTMAXD(p) chainTable[(p) & LZ4HC_MAXD_MASK] /* flexible, LZ4HC_MAXD dependent */
85
83
  #define DELTANEXTU16(table, pos) table[(U16)(pos)] /* faster */
86
84
  /* Make fields passed to, and updated by LZ4HC_encodeSequence explicit */
87
85
  #define UPDATABLE(ip, op, anchor) &ip, &op, &anchor
88
86
 
87
+
88
+ /*=== Hashing ===*/
89
89
  #define LZ4HC_HASHSIZE 4
90
+ #define HASH_FUNCTION(i) (((i) * 2654435761U) >> ((MINMATCH*8)-LZ4HC_HASH_LOG))
90
91
  static U32 LZ4HC_hashPtr(const void* ptr) { return HASH_FUNCTION(LZ4_read32(ptr)); }
91
92
 
93
+ #if defined(LZ4_FORCE_MEMORY_ACCESS) && (LZ4_FORCE_MEMORY_ACCESS==2)
94
+ /* lie to the compiler about data alignment; use with caution */
95
+ static U64 LZ4_read64(const void* memPtr) { return *(const U64*) memPtr; }
96
+
97
+ #elif defined(LZ4_FORCE_MEMORY_ACCESS) && (LZ4_FORCE_MEMORY_ACCESS==1)
98
+ /* __pack instructions are safer, but compiler specific */
99
+ LZ4_PACK(typedef struct { U64 u64; }) LZ4_unalign64;
100
+ static U64 LZ4_read64(const void* ptr) { return ((const LZ4_unalign64*)ptr)->u64; }
101
+
102
+ #else /* safe and portable access using memcpy() */
103
+ static U64 LZ4_read64(const void* memPtr)
104
+ {
105
+ U64 val; LZ4_memcpy(&val, memPtr, sizeof(val)); return val;
106
+ }
107
+
108
+ #endif /* LZ4_FORCE_MEMORY_ACCESS */
109
+
110
+ #define LZ4MID_HASHSIZE 8
111
+ #define LZ4MID_HASHLOG (LZ4HC_HASH_LOG-1)
112
+ #define LZ4MID_HASHTABLESIZE (1 << LZ4MID_HASHLOG)
113
+
114
+ static U32 LZ4MID_hash4(U32 v) { return (v * 2654435761U) >> (32-LZ4MID_HASHLOG); }
115
+ static U32 LZ4MID_hash4Ptr(const void* ptr) { return LZ4MID_hash4(LZ4_read32(ptr)); }
116
+ /* note: hash7 hashes the lower 56-bits.
117
+ * It presumes input was read using little endian.*/
118
+ static U32 LZ4MID_hash7(U64 v) { return (U32)(((v << (64-56)) * 58295818150454627ULL) >> (64-LZ4MID_HASHLOG)) ; }
119
+ static U64 LZ4_readLE64(const void* memPtr);
120
+ static U32 LZ4MID_hash8Ptr(const void* ptr) { return LZ4MID_hash7(LZ4_readLE64(ptr)); }
121
+
122
+ static U64 LZ4_readLE64(const void* memPtr)
123
+ {
124
+ if (LZ4_isLittleEndian()) {
125
+ return LZ4_read64(memPtr);
126
+ } else {
127
+ const BYTE* p = (const BYTE*)memPtr;
128
+ /* note: relies on the compiler to simplify this expression */
129
+ return (U64)p[0] | ((U64)p[1]<<8) | ((U64)p[2]<<16) | ((U64)p[3]<<24)
130
+ | ((U64)p[4]<<32) | ((U64)p[5]<<40) | ((U64)p[6]<<48) | ((U64)p[7]<<56);
131
+ }
132
+ }
133
+
134
+
135
+ /*=== Count match length ===*/
136
+ LZ4_FORCE_INLINE
137
+ unsigned LZ4HC_NbCommonBytes32(U32 val)
138
+ {
139
+ assert(val != 0);
140
+ if (LZ4_isLittleEndian()) {
141
+ # if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(LZ4_FORCE_SW_BITCOUNT)
142
+ unsigned long r;
143
+ _BitScanReverse(&r, val);
144
+ return (unsigned)((31 - r) >> 3);
145
+ # elif (defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 3) || \
146
+ ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))))) && \
147
+ !defined(LZ4_FORCE_SW_BITCOUNT)
148
+ return (unsigned)__builtin_clz(val) >> 3;
149
+ # else
150
+ val >>= 8;
151
+ val = ((((val + 0x00FFFF00) | 0x00FFFFFF) + val) |
152
+ (val + 0x00FF0000)) >> 24;
153
+ return (unsigned)val ^ 3;
154
+ # endif
155
+ } else {
156
+ # if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(LZ4_FORCE_SW_BITCOUNT)
157
+ unsigned long r;
158
+ _BitScanForward(&r, val);
159
+ return (unsigned)(r >> 3);
160
+ # elif (defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 3) || \
161
+ ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))))) && \
162
+ !defined(LZ4_FORCE_SW_BITCOUNT)
163
+ return (unsigned)__builtin_ctz(val) >> 3;
164
+ # else
165
+ const U32 m = 0x01010101;
166
+ return (unsigned)((((val - 1) ^ val) & (m - 1)) * m) >> 24;
167
+ # endif
168
+ }
169
+ }
170
+
171
+ /** LZ4HC_countBack() :
172
+ * @return : negative value, nb of common bytes before ip/match */
173
+ LZ4_FORCE_INLINE
174
+ int LZ4HC_countBack(const BYTE* const ip, const BYTE* const match,
175
+ const BYTE* const iMin, const BYTE* const mMin)
176
+ {
177
+ int back = 0;
178
+ int const min = (int)MAX(iMin - ip, mMin - match);
179
+ assert(min <= 0);
180
+ assert(ip >= iMin); assert((size_t)(ip-iMin) < (1U<<31));
181
+ assert(match >= mMin); assert((size_t)(match - mMin) < (1U<<31));
182
+
183
+ while ((back - min) > 3) {
184
+ U32 const v = LZ4_read32(ip + back - 4) ^ LZ4_read32(match + back - 4);
185
+ if (v) {
186
+ return (back - (int)LZ4HC_NbCommonBytes32(v));
187
+ } else back -= 4; /* 4-byte step */
188
+ }
189
+ /* check remainder if any */
190
+ while ( (back > min)
191
+ && (ip[back-1] == match[back-1]) )
192
+ back--;
193
+ return back;
194
+ }
195
+
92
196
 
93
197
  /**************************************
94
- * HC Compression
198
+ * Init
95
199
  **************************************/
96
200
  static void LZ4HC_clearTables (LZ4HC_CCtx_internal* hc4)
97
201
  {
@@ -119,6 +223,394 @@ static void LZ4HC_init_internal (LZ4HC_CCtx_internal* hc4, const BYTE* start)
119
223
  }
120
224
 
121
225
 
226
+ /**************************************
227
+ * Encode
228
+ **************************************/
229
+ /* LZ4HC_encodeSequence() :
230
+ * @return : 0 if ok,
231
+ * 1 if buffer issue detected */
232
+ LZ4_FORCE_INLINE int LZ4HC_encodeSequence (
233
+ const BYTE** _ip,
234
+ BYTE** _op,
235
+ const BYTE** _anchor,
236
+ int matchLength,
237
+ int offset,
238
+ limitedOutput_directive limit,
239
+ BYTE* oend)
240
+ {
241
+ #define ip (*_ip)
242
+ #define op (*_op)
243
+ #define anchor (*_anchor)
244
+
245
+ size_t length;
246
+ BYTE* const token = op++;
247
+
248
+ #if defined(LZ4_DEBUG) && (LZ4_DEBUG >= 6)
249
+ static const BYTE* start = NULL;
250
+ static U32 totalCost = 0;
251
+ U32 const pos = (start==NULL) ? 0 : (U32)(anchor - start);
252
+ U32 const ll = (U32)(ip - anchor);
253
+ U32 const llAdd = (ll>=15) ? ((ll-15) / 255) + 1 : 0;
254
+ U32 const mlAdd = (matchLength>=19) ? ((matchLength-19) / 255) + 1 : 0;
255
+ U32 const cost = 1 + llAdd + ll + 2 + mlAdd;
256
+ if (start==NULL) start = anchor; /* only works for single segment */
257
+ /* g_debuglog_enable = (pos >= 2228) & (pos <= 2262); */
258
+ DEBUGLOG(6, "pos:%7u -- literals:%4u, match:%4i, offset:%5i, cost:%4u + %5u",
259
+ pos,
260
+ (U32)(ip - anchor), matchLength, offset,
261
+ cost, totalCost);
262
+ totalCost += cost;
263
+ #endif
264
+
265
+ /* Encode Literal length */
266
+ length = (size_t)(ip - anchor);
267
+ LZ4_STATIC_ASSERT(notLimited == 0);
268
+ /* Check output limit */
269
+ if (limit && ((op + (length / 255) + length + (2 + 1 + LASTLITERALS)) > oend)) {
270
+ DEBUGLOG(6, "Not enough room to write %i literals (%i bytes remaining)",
271
+ (int)length, (int)(oend - op));
272
+ return 1;
273
+ }
274
+ if (length >= RUN_MASK) {
275
+ size_t len = length - RUN_MASK;
276
+ *token = (RUN_MASK << ML_BITS);
277
+ for(; len >= 255 ; len -= 255) *op++ = 255;
278
+ *op++ = (BYTE)len;
279
+ } else {
280
+ *token = (BYTE)(length << ML_BITS);
281
+ }
282
+
283
+ /* Copy Literals */
284
+ LZ4_wildCopy8(op, anchor, op + length);
285
+ op += length;
286
+
287
+ /* Encode Offset */
288
+ assert(offset <= LZ4_DISTANCE_MAX );
289
+ assert(offset > 0);
290
+ LZ4_writeLE16(op, (U16)(offset)); op += 2;
291
+
292
+ /* Encode MatchLength */
293
+ assert(matchLength >= MINMATCH);
294
+ length = (size_t)matchLength - MINMATCH;
295
+ if (limit && (op + (length / 255) + (1 + LASTLITERALS) > oend)) {
296
+ DEBUGLOG(6, "Not enough room to write match length");
297
+ return 1; /* Check output limit */
298
+ }
299
+ if (length >= ML_MASK) {
300
+ *token += ML_MASK;
301
+ length -= ML_MASK;
302
+ for(; length >= 510 ; length -= 510) { *op++ = 255; *op++ = 255; }
303
+ if (length >= 255) { length -= 255; *op++ = 255; }
304
+ *op++ = (BYTE)length;
305
+ } else {
306
+ *token += (BYTE)(length);
307
+ }
308
+
309
+ /* Prepare next loop */
310
+ ip += matchLength;
311
+ anchor = ip;
312
+
313
+ return 0;
314
+
315
+ #undef ip
316
+ #undef op
317
+ #undef anchor
318
+ }
319
+
320
+
321
+ typedef struct {
322
+ int off;
323
+ int len;
324
+ int back; /* negative value */
325
+ } LZ4HC_match_t;
326
+
327
+ LZ4HC_match_t LZ4HC_searchExtDict(const BYTE* ip, U32 ipIndex,
328
+ const BYTE* const iLowLimit, const BYTE* const iHighLimit,
329
+ const LZ4HC_CCtx_internal* dictCtx, U32 gDictEndIndex,
330
+ int currentBestML, int nbAttempts)
331
+ {
332
+ size_t const lDictEndIndex = (size_t)(dictCtx->end - dictCtx->prefixStart) + dictCtx->dictLimit;
333
+ U32 lDictMatchIndex = dictCtx->hashTable[LZ4HC_hashPtr(ip)];
334
+ U32 matchIndex = lDictMatchIndex + gDictEndIndex - (U32)lDictEndIndex;
335
+ int offset = 0, sBack = 0;
336
+ assert(lDictEndIndex <= 1 GB);
337
+ if (lDictMatchIndex>0)
338
+ DEBUGLOG(7, "lDictEndIndex = %zu, lDictMatchIndex = %u", lDictEndIndex, lDictMatchIndex);
339
+ while (ipIndex - matchIndex <= LZ4_DISTANCE_MAX && nbAttempts--) {
340
+ const BYTE* const matchPtr = dictCtx->prefixStart - dictCtx->dictLimit + lDictMatchIndex;
341
+
342
+ if (LZ4_read32(matchPtr) == LZ4_read32(ip)) {
343
+ int mlt;
344
+ int back = 0;
345
+ const BYTE* vLimit = ip + (lDictEndIndex - lDictMatchIndex);
346
+ if (vLimit > iHighLimit) vLimit = iHighLimit;
347
+ mlt = (int)LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, vLimit) + MINMATCH;
348
+ back = (ip > iLowLimit) ? LZ4HC_countBack(ip, matchPtr, iLowLimit, dictCtx->prefixStart) : 0;
349
+ mlt -= back;
350
+ if (mlt > currentBestML) {
351
+ currentBestML = mlt;
352
+ offset = (int)(ipIndex - matchIndex);
353
+ sBack = back;
354
+ DEBUGLOG(7, "found match of length %i within extDictCtx", currentBestML);
355
+ } }
356
+
357
+ { U32 const nextOffset = DELTANEXTU16(dictCtx->chainTable, lDictMatchIndex);
358
+ lDictMatchIndex -= nextOffset;
359
+ matchIndex -= nextOffset;
360
+ } }
361
+
362
+ { LZ4HC_match_t md;
363
+ md.len = currentBestML;
364
+ md.off = offset;
365
+ md.back = sBack;
366
+ return md;
367
+ }
368
+ }
369
+
370
+ /**************************************
371
+ * Mid Compression (level 2)
372
+ **************************************/
373
+
374
+ LZ4_FORCE_INLINE void
375
+ LZ4MID_addPosition(U32* hTable, U32 hValue, U32 index)
376
+ {
377
+ hTable[hValue] = index;
378
+ }
379
+
380
+ #define ADDPOS8(_p, _idx) LZ4MID_addPosition(hash8Table, LZ4MID_hash8Ptr(_p), _idx)
381
+ #define ADDPOS4(_p, _idx) LZ4MID_addPosition(hash4Table, LZ4MID_hash4Ptr(_p), _idx)
382
+
383
+ static int LZ4HC_compress_2hashes (
384
+ LZ4HC_CCtx_internal* const ctx,
385
+ const char* const src,
386
+ char* const dst,
387
+ int* srcSizePtr,
388
+ int const maxOutputSize,
389
+ const limitedOutput_directive limit,
390
+ const dictCtx_directive dict
391
+ )
392
+ {
393
+ U32* const hash4Table = ctx->hashTable;
394
+ U32* const hash8Table = hash4Table + LZ4MID_HASHTABLESIZE;
395
+ const BYTE* ip = (const BYTE*)src;
396
+ const BYTE* anchor = ip;
397
+ const BYTE* const iend = ip + *srcSizePtr;
398
+ const BYTE* const mflimit = iend - MFLIMIT;
399
+ const BYTE* const matchlimit = (iend - LASTLITERALS);
400
+ const BYTE* const ilimit = (iend - LZ4MID_HASHSIZE);
401
+ BYTE* op = (BYTE*)dst;
402
+ BYTE* oend = op + maxOutputSize;
403
+
404
+ const BYTE* const prefixPtr = ctx->prefixStart;
405
+ const U32 prefixIdx = ctx->dictLimit;
406
+ const U32 ilimitIdx = (U32)(ilimit - prefixPtr) + prefixIdx;
407
+ const U32 gDictEndIndex = ctx->lowLimit;
408
+ unsigned matchLength;
409
+ unsigned matchDistance;
410
+
411
+ /* input sanitization */
412
+ DEBUGLOG(5, "LZ4HC_compress_2hashes (%i bytes)", *srcSizePtr);
413
+ assert(*srcSizePtr >= 0);
414
+ if (*srcSizePtr) assert(src != NULL);
415
+ if (maxOutputSize) assert(dst != NULL);
416
+ if (*srcSizePtr < 0) return 0; /* invalid */
417
+ if (maxOutputSize < 0) return 0; /* invalid */
418
+ if (*srcSizePtr > LZ4_MAX_INPUT_SIZE) {
419
+ /* forbidden: no input is allowed to be that large */
420
+ return 0;
421
+ }
422
+ if (limit == fillOutput) oend -= LASTLITERALS; /* Hack for support LZ4 format restriction */
423
+ if (*srcSizePtr < LZ4_minLength)
424
+ goto _lz4mid_last_literals; /* Input too small, no compression (all literals) */
425
+
426
+ /* main loop */
427
+ while (ip <= mflimit) {
428
+ const U32 ipIndex = (U32)(ip - prefixPtr) + prefixIdx;
429
+ /* search long match */
430
+ { U32 h8 = LZ4MID_hash8Ptr(ip);
431
+ U32 pos8 = hash8Table[h8];
432
+ assert(h8 < LZ4MID_HASHTABLESIZE);
433
+ assert(h8 < ipIndex);
434
+ LZ4MID_addPosition(hash8Table, h8, ipIndex);
435
+ if ( ipIndex - pos8 <= LZ4_DISTANCE_MAX
436
+ && pos8 >= prefixIdx /* note: currently only search within prefix */
437
+ ) {
438
+ /* match candidate found */
439
+ const BYTE* matchPtr = prefixPtr + pos8 - prefixIdx;
440
+ assert(matchPtr < ip);
441
+ matchLength = LZ4_count(ip, matchPtr, matchlimit);
442
+ if (matchLength >= MINMATCH) {
443
+ DEBUGLOG(7, "found candidate match at pos %u (len=%u)", pos8, matchLength);
444
+ matchDistance = ipIndex - pos8;
445
+ goto _lz4mid_encode_sequence;
446
+ }
447
+ } }
448
+ /* search short match */
449
+ { U32 h4 = LZ4MID_hash4Ptr(ip);
450
+ U32 pos4 = hash4Table[h4];
451
+ assert(h4 < LZ4MID_HASHTABLESIZE);
452
+ assert(pos4 < ipIndex);
453
+ LZ4MID_addPosition(hash4Table, h4, ipIndex);
454
+ if (ipIndex - pos4 <= LZ4_DISTANCE_MAX
455
+ && pos4 >= prefixIdx /* only search within prefix */
456
+ ) {
457
+ /* match candidate found */
458
+ const BYTE* const matchPtr = prefixPtr + (pos4 - prefixIdx);
459
+ assert(matchPtr < ip);
460
+ assert(matchPtr >= prefixPtr);
461
+ matchLength = LZ4_count(ip, matchPtr, matchlimit);
462
+ if (matchLength >= MINMATCH) {
463
+ /* short match found, let's just check ip+1 for longer */
464
+ U32 const h8 = LZ4MID_hash8Ptr(ip+1);
465
+ U32 const pos8 = hash8Table[h8];
466
+ U32 const m2Distance = ipIndex + 1 - pos8;
467
+ matchDistance = ipIndex - pos4;
468
+ if ( m2Distance <= LZ4_DISTANCE_MAX
469
+ && pos8 >= prefixIdx /* only search within prefix */
470
+ && likely(ip < mflimit)
471
+ ) {
472
+ const BYTE* const m2Ptr = prefixPtr + (pos8 - prefixIdx);
473
+ unsigned ml2 = LZ4_count(ip+1, m2Ptr, matchlimit);
474
+ if (ml2 > matchLength) {
475
+ LZ4MID_addPosition(hash8Table, h8, ipIndex+1);
476
+ ip++;
477
+ matchLength = ml2;
478
+ matchDistance = m2Distance;
479
+ } }
480
+ goto _lz4mid_encode_sequence;
481
+ }
482
+ } }
483
+ /* no match found in prefix */
484
+ if ( (dict == usingDictCtxHc)
485
+ && (ipIndex - gDictEndIndex < LZ4_DISTANCE_MAX - 8) ) {
486
+ /* search a match in dictionary */
487
+ LZ4HC_match_t dMatch = LZ4HC_searchExtDict(ip, ipIndex,
488
+ anchor, matchlimit,
489
+ ctx->dictCtx, gDictEndIndex,
490
+ 0, 2);
491
+ if (dMatch.len >= MINMATCH) {
492
+ DEBUGLOG(7, "found Dictionary match (offset=%i)", dMatch.off);
493
+ ip += dMatch.back;
494
+ assert(ip >= anchor);
495
+ matchLength = (unsigned)dMatch.len;
496
+ matchDistance = (unsigned)dMatch.off;
497
+ goto _lz4mid_encode_sequence;
498
+ }
499
+ }
500
+ /* no match found */
501
+ ip += 1 + ((ip-anchor) >> 9); /* skip faster over incompressible data */
502
+ continue;
503
+
504
+ _lz4mid_encode_sequence:
505
+ /* catch back */
506
+ while (((ip > anchor) & ((U32)(ip-prefixPtr) > matchDistance)) && (unlikely(ip[-1] == ip[-(int)matchDistance-1]))) {
507
+ ip--; matchLength++;
508
+ };
509
+
510
+ /* fill table with beginning of match */
511
+ ADDPOS8(ip+1, ipIndex+1);
512
+ ADDPOS8(ip+2, ipIndex+2);
513
+ ADDPOS4(ip+1, ipIndex+1);
514
+
515
+ /* encode */
516
+ { BYTE* const saved_op = op;
517
+ /* LZ4HC_encodeSequence always updates @op; on success, it updates @ip and @anchor */
518
+ if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor),
519
+ (int)matchLength, (int)matchDistance,
520
+ limit, oend) ) {
521
+ op = saved_op; /* restore @op value before failed LZ4HC_encodeSequence */
522
+ goto _lz4mid_dest_overflow;
523
+ }
524
+ }
525
+
526
+ /* fill table with end of match */
527
+ { U32 endMatchIdx = (U32)(ip-prefixPtr) + prefixIdx;
528
+ U32 pos_m2 = endMatchIdx - 2;
529
+ if (pos_m2 < ilimitIdx) {
530
+ if (likely(ip - prefixPtr > 5)) {
531
+ ADDPOS8(ip-5, endMatchIdx - 5);
532
+ }
533
+ ADDPOS8(ip-3, endMatchIdx - 3);
534
+ ADDPOS8(ip-2, endMatchIdx - 2);
535
+ ADDPOS4(ip-2, endMatchIdx - 2);
536
+ ADDPOS4(ip-1, endMatchIdx - 1);
537
+ }
538
+ }
539
+ }
540
+
541
+ _lz4mid_last_literals:
542
+ /* Encode Last Literals */
543
+ { size_t lastRunSize = (size_t)(iend - anchor); /* literals */
544
+ size_t llAdd = (lastRunSize + 255 - RUN_MASK) / 255;
545
+ size_t const totalSize = 1 + llAdd + lastRunSize;
546
+ if (limit == fillOutput) oend += LASTLITERALS; /* restore correct value */
547
+ if (limit && (op + totalSize > oend)) {
548
+ if (limit == limitedOutput) return 0; /* not enough space in @dst */
549
+ /* adapt lastRunSize to fill 'dest' */
550
+ lastRunSize = (size_t)(oend - op) - 1 /*token*/;
551
+ llAdd = (lastRunSize + 256 - RUN_MASK) / 256;
552
+ lastRunSize -= llAdd;
553
+ }
554
+ DEBUGLOG(6, "Final literal run : %i literals", (int)lastRunSize);
555
+ ip = anchor + lastRunSize; /* can be != iend if limit==fillOutput */
556
+
557
+ if (lastRunSize >= RUN_MASK) {
558
+ size_t accumulator = lastRunSize - RUN_MASK;
559
+ *op++ = (RUN_MASK << ML_BITS);
560
+ for(; accumulator >= 255 ; accumulator -= 255)
561
+ *op++ = 255;
562
+ *op++ = (BYTE) accumulator;
563
+ } else {
564
+ *op++ = (BYTE)(lastRunSize << ML_BITS);
565
+ }
566
+ assert(lastRunSize <= (size_t)(oend - op));
567
+ LZ4_memcpy(op, anchor, lastRunSize);
568
+ op += lastRunSize;
569
+ }
570
+
571
+ /* End */
572
+ DEBUGLOG(5, "compressed %i bytes into %i bytes", *srcSizePtr, (int)((char*)op - dst));
573
+ assert(ip >= (const BYTE*)src);
574
+ assert(ip <= iend);
575
+ *srcSizePtr = (int)(ip - (const BYTE*)src);
576
+ assert((char*)op >= dst);
577
+ assert(op <= oend);
578
+ assert((char*)op - dst < INT_MAX);
579
+ return (int)((char*)op - dst);
580
+
581
+ _lz4mid_dest_overflow:
582
+ if (limit == fillOutput) {
583
+ /* Assumption : @ip, @anchor, @optr and @matchLength must be set correctly */
584
+ size_t const ll = (size_t)(ip - anchor);
585
+ size_t const ll_addbytes = (ll + 240) / 255;
586
+ size_t const ll_totalCost = 1 + ll_addbytes + ll;
587
+ BYTE* const maxLitPos = oend - 3; /* 2 for offset, 1 for token */
588
+ DEBUGLOG(6, "Last sequence is overflowing : %u literals, %u remaining space",
589
+ (unsigned)ll, (unsigned)(oend-op));
590
+ if (op + ll_totalCost <= maxLitPos) {
591
+ /* ll validated; now adjust match length */
592
+ size_t const bytesLeftForMl = (size_t)(maxLitPos - (op+ll_totalCost));
593
+ size_t const maxMlSize = MINMATCH + (ML_MASK-1) + (bytesLeftForMl * 255);
594
+ assert(maxMlSize < INT_MAX);
595
+ if ((size_t)matchLength > maxMlSize) matchLength= (unsigned)maxMlSize;
596
+ if ((oend + LASTLITERALS) - (op + ll_totalCost + 2) - 1 + matchLength >= MFLIMIT) {
597
+ DEBUGLOG(6, "Let's encode a last sequence (ll=%u, ml=%u)", (unsigned)ll, matchLength);
598
+ LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor),
599
+ (int)matchLength, (int)matchDistance,
600
+ notLimited, oend);
601
+ } }
602
+ DEBUGLOG(6, "Let's finish with a run of literals (%u bytes left)", (unsigned)(oend-op));
603
+ goto _lz4mid_last_literals;
604
+ }
605
+ /* compression failed */
606
+ return 0;
607
+ }
608
+
609
+
610
+ /**************************************
611
+ * HC Compression - Search
612
+ **************************************/
613
+
122
614
  /* Update chains up to ip (excluded) */
123
615
  LZ4_FORCE_INLINE void LZ4HC_Insert (LZ4HC_CCtx_internal* hc4, const BYTE* ip)
124
616
  {
@@ -143,23 +635,6 @@ LZ4_FORCE_INLINE void LZ4HC_Insert (LZ4HC_CCtx_internal* hc4, const BYTE* ip)
143
635
  hc4->nextToUpdate = target;
144
636
  }
145
637
 
146
- /** LZ4HC_countBack() :
147
- * @return : negative value, nb of common bytes before ip/match */
148
- LZ4_FORCE_INLINE
149
- int LZ4HC_countBack(const BYTE* const ip, const BYTE* const match,
150
- const BYTE* const iMin, const BYTE* const mMin)
151
- {
152
- int back = 0;
153
- int const min = (int)MAX(iMin - ip, mMin - match);
154
- assert(min <= 0);
155
- assert(ip >= iMin); assert((size_t)(ip-iMin) < (1U<<31));
156
- assert(match >= mMin); assert((size_t)(match - mMin) < (1U<<31));
157
- while ( (back > min)
158
- && (ip[back-1] == match[back-1]) )
159
- back--;
160
- return back;
161
- }
162
-
163
638
  #if defined(_MSC_VER)
164
639
  # define LZ4HC_rotl32(x,r) _rotl(x,r)
165
640
  #else
@@ -239,10 +714,6 @@ static int LZ4HC_protectDictEnd(U32 const dictLimit, U32 const matchIndex)
239
714
  typedef enum { rep_untested, rep_not, rep_confirmed } repeat_state_e;
240
715
  typedef enum { favorCompressionRatio=0, favorDecompressionSpeed } HCfavor_e;
241
716
 
242
- typedef struct {
243
- int off;
244
- int len;
245
- } LZ4HC_match_t;
246
717
 
247
718
  LZ4_FORCE_INLINE LZ4HC_match_t
248
719
  LZ4HC_InsertAndGetWiderMatch (
@@ -250,7 +721,6 @@ LZ4HC_InsertAndGetWiderMatch (
250
721
  const BYTE* const ip,
251
722
  const BYTE* const iLowLimit, const BYTE* const iHighLimit,
252
723
  int longest,
253
- const BYTE** startpos,
254
724
  const int maxNbAttempts,
255
725
  const int patternAnalysis, const int chainSwap,
256
726
  const dictCtx_directive dict,
@@ -258,7 +728,7 @@ LZ4HC_InsertAndGetWiderMatch (
258
728
  {
259
729
  U16* const chainTable = hc4->chainTable;
260
730
  U32* const hashTable = hc4->hashTable;
261
- const LZ4HC_CCtx_internal * const dictCtx = hc4->dictCtx;
731
+ const LZ4HC_CCtx_internal* const dictCtx = hc4->dictCtx;
262
732
  const BYTE* const prefixPtr = hc4->prefixStart;
263
733
  const U32 prefixIdx = hc4->dictLimit;
264
734
  const U32 ipIndex = (U32)(ip - prefixPtr) + prefixIdx;
@@ -274,11 +744,9 @@ LZ4HC_InsertAndGetWiderMatch (
274
744
  U32 matchIndex;
275
745
  repeat_state_e repeat = rep_untested;
276
746
  size_t srcPatternLength = 0;
277
- int offset = 0;
747
+ int offset = 0, sBack = 0;
278
748
 
279
749
  DEBUGLOG(7, "LZ4HC_InsertAndGetWiderMatch");
280
- assert(startpos != NULL);
281
- *startpos = ip; /* in case there is no solution */
282
750
  /* First Match */
283
751
  LZ4HC_Insert(hc4, ip); /* insert all prior positions up to ip (excluded) */
284
752
  matchIndex = hashTable[LZ4HC_hashPtr(ip)];
@@ -304,7 +772,7 @@ LZ4HC_InsertAndGetWiderMatch (
304
772
  if (matchLength > longest) {
305
773
  longest = matchLength;
306
774
  offset = (int)(ipIndex - matchIndex);
307
- *startpos = ip + back;
775
+ sBack = back;
308
776
  DEBUGLOG(7, "Found match of len=%i within prefix, offset=%i, back=%i", longest, offset, -back);
309
777
  } } }
310
778
  } else { /* lowestMatchIndex <= matchIndex < dictLimit : within Ext Dict */
@@ -323,7 +791,7 @@ LZ4HC_InsertAndGetWiderMatch (
323
791
  if (matchLength > longest) {
324
792
  longest = matchLength;
325
793
  offset = (int)(ipIndex - matchIndex);
326
- *startpos = ip + back;
794
+ sBack = back;
327
795
  DEBUGLOG(7, "Found match of len=%i within dict, offset=%i, back=%i", longest, offset, -back);
328
796
  } } }
329
797
 
@@ -413,7 +881,7 @@ LZ4HC_InsertAndGetWiderMatch (
413
881
  assert(maxML < 2 GB);
414
882
  longest = (int)maxML;
415
883
  offset = (int)(ipIndex - matchIndex);
416
- *startpos = ip;
884
+ assert(sBack == 0);
417
885
  DEBUGLOG(7, "Found repeat pattern match of len=%i, offset=%i", longest, offset);
418
886
  }
419
887
  { U32 const distToNextPattern = DELTANEXTU16(chainTable, matchIndex);
@@ -431,7 +899,7 @@ LZ4HC_InsertAndGetWiderMatch (
431
899
 
432
900
  if ( dict == usingDictCtxHc
433
901
  && nbAttempts > 0
434
- && ipIndex - lowestMatchIndex < LZ4_DISTANCE_MAX) {
902
+ && withinStartDistance) {
435
903
  size_t const dictEndOffset = (size_t)(dictCtx->end - dictCtx->prefixStart) + dictCtx->dictLimit;
436
904
  U32 dictMatchIndex = dictCtx->hashTable[LZ4HC_hashPtr(ip)];
437
905
  assert(dictEndOffset <= 1 GB);
@@ -451,7 +919,7 @@ LZ4HC_InsertAndGetWiderMatch (
451
919
  if (mlt > longest) {
452
920
  longest = mlt;
453
921
  offset = (int)(ipIndex - matchIndex);
454
- *startpos = ip + back;
922
+ sBack = back;
455
923
  DEBUGLOG(7, "found match of length %i within extDictCtx", longest);
456
924
  } }
457
925
 
@@ -464,6 +932,7 @@ LZ4HC_InsertAndGetWiderMatch (
464
932
  assert(longest >= 0);
465
933
  md.len = longest;
466
934
  md.off = offset;
935
+ md.back = sBack;
467
936
  return md;
468
937
  }
469
938
  }
@@ -475,103 +944,13 @@ LZ4HC_InsertAndFindBestMatch(LZ4HC_CCtx_internal* const hc4, /* Index table wi
475
944
  const int patternAnalysis,
476
945
  const dictCtx_directive dict)
477
946
  {
478
- const BYTE* uselessPtr = ip;
479
947
  DEBUGLOG(7, "LZ4HC_InsertAndFindBestMatch");
480
948
  /* note : LZ4HC_InsertAndGetWiderMatch() is able to modify the starting position of a match (*startpos),
481
949
  * but this won't be the case here, as we define iLowLimit==ip,
482
950
  * so LZ4HC_InsertAndGetWiderMatch() won't be allowed to search past ip */
483
- return LZ4HC_InsertAndGetWiderMatch(hc4, ip, ip, iLimit, MINMATCH-1, &uselessPtr, maxNbAttempts, patternAnalysis, 0 /*chainSwap*/, dict, favorCompressionRatio);
951
+ return LZ4HC_InsertAndGetWiderMatch(hc4, ip, ip, iLimit, MINMATCH-1, maxNbAttempts, patternAnalysis, 0 /*chainSwap*/, dict, favorCompressionRatio);
484
952
  }
485
953
 
486
- /* LZ4HC_encodeSequence() :
487
- * @return : 0 if ok,
488
- * 1 if buffer issue detected */
489
- LZ4_FORCE_INLINE int LZ4HC_encodeSequence (
490
- const BYTE** _ip,
491
- BYTE** _op,
492
- const BYTE** _anchor,
493
- int matchLength,
494
- int offset,
495
- limitedOutput_directive limit,
496
- BYTE* oend)
497
- {
498
- #define ip (*_ip)
499
- #define op (*_op)
500
- #define anchor (*_anchor)
501
-
502
- size_t length;
503
- BYTE* const token = op++;
504
-
505
- #if defined(LZ4_DEBUG) && (LZ4_DEBUG >= 6)
506
- static const BYTE* start = NULL;
507
- static U32 totalCost = 0;
508
- U32 const pos = (start==NULL) ? 0 : (U32)(anchor - start);
509
- U32 const ll = (U32)(ip - anchor);
510
- U32 const llAdd = (ll>=15) ? ((ll-15) / 255) + 1 : 0;
511
- U32 const mlAdd = (matchLength>=19) ? ((matchLength-19) / 255) + 1 : 0;
512
- U32 const cost = 1 + llAdd + ll + 2 + mlAdd;
513
- if (start==NULL) start = anchor; /* only works for single segment */
514
- /* g_debuglog_enable = (pos >= 2228) & (pos <= 2262); */
515
- DEBUGLOG(6, "pos:%7u -- literals:%4u, match:%4i, offset:%5i, cost:%4u + %5u",
516
- pos,
517
- (U32)(ip - anchor), matchLength, offset,
518
- cost, totalCost);
519
- totalCost += cost;
520
- #endif
521
-
522
- /* Encode Literal length */
523
- length = (size_t)(ip - anchor);
524
- LZ4_STATIC_ASSERT(notLimited == 0);
525
- /* Check output limit */
526
- if (limit && ((op + (length / 255) + length + (2 + 1 + LASTLITERALS)) > oend)) {
527
- DEBUGLOG(6, "Not enough room to write %i literals (%i bytes remaining)",
528
- (int)length, (int)(oend - op));
529
- return 1;
530
- }
531
- if (length >= RUN_MASK) {
532
- size_t len = length - RUN_MASK;
533
- *token = (RUN_MASK << ML_BITS);
534
- for(; len >= 255 ; len -= 255) *op++ = 255;
535
- *op++ = (BYTE)len;
536
- } else {
537
- *token = (BYTE)(length << ML_BITS);
538
- }
539
-
540
- /* Copy Literals */
541
- LZ4_wildCopy8(op, anchor, op + length);
542
- op += length;
543
-
544
- /* Encode Offset */
545
- assert(offset <= LZ4_DISTANCE_MAX );
546
- assert(offset > 0);
547
- LZ4_writeLE16(op, (U16)(offset)); op += 2;
548
-
549
- /* Encode MatchLength */
550
- assert(matchLength >= MINMATCH);
551
- length = (size_t)matchLength - MINMATCH;
552
- if (limit && (op + (length / 255) + (1 + LASTLITERALS) > oend)) {
553
- DEBUGLOG(6, "Not enough room to write match length");
554
- return 1; /* Check output limit */
555
- }
556
- if (length >= ML_MASK) {
557
- *token += ML_MASK;
558
- length -= ML_MASK;
559
- for(; length >= 510 ; length -= 510) { *op++ = 255; *op++ = 255; }
560
- if (length >= 255) { length -= 255; *op++ = 255; }
561
- *op++ = (BYTE)length;
562
- } else {
563
- *token += (BYTE)(length);
564
- }
565
-
566
- /* Prepare next loop */
567
- ip += matchLength;
568
- anchor = ip;
569
-
570
- return 0;
571
- }
572
- #undef ip
573
- #undef op
574
- #undef anchor
575
954
 
576
955
  LZ4_FORCE_INLINE int LZ4HC_compress_hashChain (
577
956
  LZ4HC_CCtx_internal* const ctx,
@@ -601,7 +980,7 @@ LZ4_FORCE_INLINE int LZ4HC_compress_hashChain (
601
980
  const BYTE* start2 = NULL;
602
981
  const BYTE* start3 = NULL;
603
982
  LZ4HC_match_t m0, m1, m2, m3;
604
- const LZ4HC_match_t nomatch = {0, 0};
983
+ const LZ4HC_match_t nomatch = {0, 0, 0};
605
984
 
606
985
  /* init */
607
986
  DEBUGLOG(5, "LZ4HC_compress_hashChain (dict?=>%i)", dict);
@@ -620,16 +999,21 @@ LZ4_FORCE_INLINE int LZ4HC_compress_hashChain (
620
999
  _Search2:
621
1000
  DEBUGLOG(7, "_Search2 (currently found match of size %i)", m1.len);
622
1001
  if (ip+m1.len <= mflimit) {
1002
+ start2 = ip + m1.len - 2;
623
1003
  m2 = LZ4HC_InsertAndGetWiderMatch(ctx,
624
- ip + m1.len - 2, ip + 0, matchlimit, m1.len, &start2,
1004
+ start2, ip + 0, matchlimit, m1.len,
625
1005
  maxNbAttempts, patternAnalysis, 0, dict, favorCompressionRatio);
1006
+ start2 += m2.back;
626
1007
  } else {
627
1008
  m2 = nomatch; /* do not search further */
628
1009
  }
629
1010
 
630
1011
  if (m2.len <= m1.len) { /* No better match => encode ML1 immediately */
631
1012
  optr = op;
632
- if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), m1.len, m1.off, limit, oend)) goto _dest_overflow;
1013
+ if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor),
1014
+ m1.len, m1.off,
1015
+ limit, oend) )
1016
+ goto _dest_overflow;
633
1017
  continue;
634
1018
  }
635
1019
 
@@ -660,9 +1044,11 @@ _Search3:
660
1044
  }
661
1045
 
662
1046
  if (start2 + m2.len <= mflimit) {
1047
+ start3 = start2 + m2.len - 3;
663
1048
  m3 = LZ4HC_InsertAndGetWiderMatch(ctx,
664
- start2 + m2.len - 3, start2, matchlimit, m2.len, &start3,
1049
+ start3, start2, matchlimit, m2.len,
665
1050
  maxNbAttempts, patternAnalysis, 0, dict, favorCompressionRatio);
1051
+ start3 += m3.back;
666
1052
  } else {
667
1053
  m3 = nomatch; /* do not search further */
668
1054
  }
@@ -672,11 +1058,15 @@ _Search3:
672
1058
  if (start2 < ip+m1.len) m1.len = (int)(start2 - ip);
673
1059
  /* Now, encode 2 sequences */
674
1060
  optr = op;
675
- if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), m1.len, m1.off, limit, oend))
1061
+ if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor),
1062
+ m1.len, m1.off,
1063
+ limit, oend) )
676
1064
  goto _dest_overflow;
677
1065
  ip = start2;
678
1066
  optr = op;
679
- if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), m2.len, m2.off, limit, oend)) {
1067
+ if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor),
1068
+ m2.len, m2.off,
1069
+ limit, oend) ) {
680
1070
  m1 = m2;
681
1071
  goto _dest_overflow;
682
1072
  }
@@ -696,7 +1086,10 @@ _Search3:
696
1086
  }
697
1087
 
698
1088
  optr = op;
699
- if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), m1.len, m1.off, limit, oend)) goto _dest_overflow;
1089
+ if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor),
1090
+ m1.len, m1.off,
1091
+ limit, oend) )
1092
+ goto _dest_overflow;
700
1093
  ip = start3;
701
1094
  m1 = m3;
702
1095
 
@@ -731,7 +1124,10 @@ _Search3:
731
1124
  }
732
1125
  }
733
1126
  optr = op;
734
- if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), m1.len, m1.off, limit, oend)) goto _dest_overflow;
1127
+ if ( LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor),
1128
+ m1.len, m1.off,
1129
+ limit, oend) )
1130
+ goto _dest_overflow;
735
1131
 
736
1132
  /* ML2 becomes ML1 */
737
1133
  ip = start2; m1 = m2;
@@ -777,7 +1173,7 @@ _last_literals:
777
1173
 
778
1174
  _dest_overflow:
779
1175
  if (limit == fillOutput) {
780
- /* Assumption : ip, anchor, ml and ref must be set correctly */
1176
+ /* Assumption : @ip, @anchor, @optr and @m1 must be set correctly */
781
1177
  size_t const ll = (size_t)(ip - anchor);
782
1178
  size_t const ll_addbytes = (ll + 240) / 255;
783
1179
  size_t const ll_totalCost = 1 + ll_addbytes + ll;
@@ -821,16 +1217,16 @@ LZ4HC_compress_generic_internal (
821
1217
  const dictCtx_directive dict
822
1218
  )
823
1219
  {
824
- typedef enum { lz4hc, lz4opt } lz4hc_strat_e;
1220
+ typedef enum { lz4mid, lz4hc, lz4opt } lz4hc_strat_e;
825
1221
  typedef struct {
826
1222
  lz4hc_strat_e strat;
827
1223
  int nbSearches;
828
1224
  U32 targetLength;
829
1225
  } cParams_t;
830
1226
  static const cParams_t clTable[LZ4HC_CLEVEL_MAX+1] = {
831
- { lz4hc, 2, 16 }, /* 0, unused */
832
- { lz4hc, 2, 16 }, /* 1, unused */
833
- { lz4hc, 2, 16 }, /* 2, unused */
1227
+ { lz4mid, 2, 16 }, /* 0, unused */
1228
+ { lz4mid, 2, 16 }, /* 1, unused */
1229
+ { lz4mid, 2, 16 }, /* 2 */
834
1230
  { lz4hc, 4, 16 }, /* 3 */
835
1231
  { lz4hc, 8, 16 }, /* 4 */
836
1232
  { lz4hc, 16, 16 }, /* 5 */
@@ -850,13 +1246,20 @@ LZ4HC_compress_generic_internal (
850
1246
  if ((U32)*srcSizePtr > (U32)LZ4_MAX_INPUT_SIZE) return 0; /* Unsupported input size (too large or negative) */
851
1247
 
852
1248
  ctx->end += *srcSizePtr;
853
- if (cLevel < 1) cLevel = LZ4HC_CLEVEL_DEFAULT; /* note : convention is different from lz4frame, maybe something to review */
1249
+ /* note : clevel convention is a bit different from lz4frame,
1250
+ * possibly something worth revisiting for consistency */
1251
+ if (cLevel < 1)
1252
+ cLevel = LZ4HC_CLEVEL_DEFAULT;
854
1253
  cLevel = MIN(LZ4HC_CLEVEL_MAX, cLevel);
855
1254
  { cParams_t const cParam = clTable[cLevel];
856
1255
  HCfavor_e const favor = ctx->favorDecSpeed ? favorDecompressionSpeed : favorCompressionRatio;
857
1256
  int result;
858
1257
 
859
- if (cParam.strat == lz4hc) {
1258
+ if (cParam.strat == lz4mid) {
1259
+ result = LZ4HC_compress_2hashes(ctx,
1260
+ src, dst, srcSizePtr, dstCapacity,
1261
+ limit, dict);
1262
+ } else if (cParam.strat == lz4hc) {
860
1263
  result = LZ4HC_compress_hashChain(ctx,
861
1264
  src, dst, srcSizePtr, dstCapacity,
862
1265
  cParam.nbSearches, limit, dict);
@@ -1321,14 +1724,15 @@ LZ4HC_FindLongerMatch(LZ4HC_CCtx_internal* const ctx,
1321
1724
  const dictCtx_directive dict,
1322
1725
  const HCfavor_e favorDecSpeed)
1323
1726
  {
1324
- LZ4HC_match_t const match0 = { 0 , 0 };
1727
+ LZ4HC_match_t const match0 = { 0 , 0, 0 };
1325
1728
  /* note : LZ4HC_InsertAndGetWiderMatch() is able to modify the starting position of a match (*startpos),
1326
1729
  * but this won't be the case here, as we define iLowLimit==ip,
1327
1730
  ** so LZ4HC_InsertAndGetWiderMatch() won't be allowed to search past ip */
1328
- LZ4HC_match_t md = LZ4HC_InsertAndGetWiderMatch(ctx, ip, ip, iHighLimit, minLen, &ip, nbSearches, 1 /*patternAnalysis*/, 1 /*chainSwap*/, dict, favorDecSpeed);
1731
+ LZ4HC_match_t md = LZ4HC_InsertAndGetWiderMatch(ctx, ip, ip, iHighLimit, minLen, nbSearches, 1 /*patternAnalysis*/, 1 /*chainSwap*/, dict, favorDecSpeed);
1732
+ assert(md.back == 0);
1329
1733
  if (md.len <= minLen) return match0;
1330
1734
  if (favorDecSpeed) {
1331
- if ((md.len>18) & (md.len<=36)) md.len=18; /* favor shortcut */
1735
+ if ((md.len>18) & (md.len<=36)) md.len=18; /* favor dec.speed (shortcut) */
1332
1736
  }
1333
1737
  return md;
1334
1738
  }
@@ -1407,11 +1811,11 @@ static int LZ4HC_compress_optimal ( LZ4HC_CCtx_internal* ctx,
1407
1811
  rPos, cost, opt[rPos].litlen);
1408
1812
  } }
1409
1813
  /* set prices using initial match */
1410
- { int mlen = MINMATCH;
1411
- int const matchML = firstMatch.len; /* necessarily < sufficient_len < LZ4_OPT_NUM */
1814
+ { int const matchML = firstMatch.len; /* necessarily < sufficient_len < LZ4_OPT_NUM */
1412
1815
  int const offset = firstMatch.off;
1816
+ int mlen;
1413
1817
  assert(matchML < LZ4_OPT_NUM);
1414
- for ( ; mlen <= matchML ; mlen++) {
1818
+ for (mlen = MINMATCH ; mlen <= matchML ; mlen++) {
1415
1819
  int const cost = LZ4HC_sequencePrice(llen, mlen);
1416
1820
  opt[mlen].mlen = mlen;
1417
1821
  opt[mlen].off = offset;
@@ -1631,7 +2035,7 @@ if (limit == fillOutput) {
1631
2035
  }
1632
2036
  _return_label:
1633
2037
  #if defined(LZ4HC_HEAPMODE) && LZ4HC_HEAPMODE==1
1634
- FREEMEM(opt);
2038
+ if (opt) FREEMEM(opt);
1635
2039
  #endif
1636
2040
  return retval;
1637
2041
  }