pyxcp 0.21.9__cp39-cp39-win_amd64.whl → 0.22.23__cp39-cp39-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.
- pyxcp/__init__.py +12 -20
- pyxcp/aml/EtasCANMonitoring.a2l +82 -83
- pyxcp/aml/XCP_Common.aml +0 -1
- pyxcp/aml/XCPonUSB.aml +1 -1
- pyxcp/aml/ifdata_CAN.a2l +0 -1
- pyxcp/aml/ifdata_Eth.a2l +0 -1
- pyxcp/aml/ifdata_Flx.a2l +0 -1
- pyxcp/aml/ifdata_SxI.a2l +0 -1
- pyxcp/aml/ifdata_USB.a2l +0 -1
- pyxcp/asam/types.py +4 -4
- pyxcp/asamkeydll.c +0 -1
- pyxcp/checksum.py +0 -1
- pyxcp/cmdline.py +32 -50
- pyxcp/config/__init__.py +1100 -0
- pyxcp/config/legacy.py +120 -0
- pyxcp/constants.py +12 -13
- pyxcp/cpp_ext/__init__.py +0 -0
- pyxcp/cpp_ext/bin.hpp +104 -0
- pyxcp/cpp_ext/blockmem.hpp +58 -0
- pyxcp/cpp_ext/cpp_ext.cp38-win_amd64.pyd +0 -0
- pyxcp/cpp_ext/cpp_ext.cp39-win_amd64.pyd +0 -0
- pyxcp/cpp_ext/daqlist.hpp +200 -0
- pyxcp/cpp_ext/event.hpp +67 -0
- pyxcp/cpp_ext/extension_wrapper.cpp +96 -0
- pyxcp/cpp_ext/helper.hpp +280 -0
- pyxcp/cpp_ext/mcobject.hpp +246 -0
- pyxcp/cpp_ext/tsqueue.hpp +46 -0
- pyxcp/daq_stim/__init__.py +228 -0
- pyxcp/daq_stim/optimize/__init__.py +67 -0
- pyxcp/daq_stim/optimize/binpacking.py +41 -0
- pyxcp/daq_stim/scheduler.cpp +28 -0
- pyxcp/daq_stim/scheduler.hpp +75 -0
- pyxcp/daq_stim/stim.cp38-win_amd64.pyd +0 -0
- pyxcp/daq_stim/stim.cp39-win_amd64.pyd +0 -0
- pyxcp/daq_stim/stim.cpp +13 -0
- pyxcp/daq_stim/stim.hpp +604 -0
- pyxcp/daq_stim/stim_wrapper.cpp +48 -0
- pyxcp/dllif.py +21 -18
- pyxcp/errormatrix.py +5 -3
- pyxcp/examples/conf_can.toml +4 -2
- pyxcp/examples/conf_can_vector.json +9 -9
- pyxcp/examples/conf_can_vector.toml +4 -2
- pyxcp/examples/conf_eth.toml +5 -2
- pyxcp/examples/conf_nixnet.json +18 -18
- pyxcp/examples/conf_sxi.json +7 -7
- pyxcp/examples/ex_arrow.py +109 -0
- pyxcp/examples/ex_csv.py +85 -0
- pyxcp/examples/ex_excel.py +95 -0
- pyxcp/examples/ex_mdf.py +124 -0
- pyxcp/examples/ex_sqlite.py +128 -0
- pyxcp/examples/run_daq.py +148 -0
- pyxcp/examples/xcp_policy.py +6 -7
- pyxcp/examples/xcp_read_benchmark.py +8 -6
- pyxcp/examples/xcp_skel.py +0 -2
- pyxcp/examples/xcp_unlock.py +1 -1
- pyxcp/examples/xcp_user_supplied_driver.py +1 -2
- pyxcp/examples/xcphello.py +6 -3
- pyxcp/examples/xcphello_recorder.py +4 -4
- pyxcp/master/__init__.py +1 -2
- pyxcp/master/errorhandler.py +107 -74
- pyxcp/master/master.py +196 -114
- pyxcp/py.typed +0 -0
- pyxcp/recorder/__init__.py +27 -6
- pyxcp/recorder/converter/__init__.py +37 -0
- pyxcp/recorder/lz4.c +129 -51
- pyxcp/recorder/lz4.h +45 -28
- pyxcp/recorder/lz4hc.c +560 -156
- pyxcp/recorder/lz4hc.h +1 -1
- pyxcp/recorder/mio.hpp +721 -767
- pyxcp/recorder/reader.hpp +139 -0
- pyxcp/recorder/reco.py +5 -8
- pyxcp/recorder/rekorder.cp38-win_amd64.pyd +0 -0
- pyxcp/recorder/rekorder.cp39-win_amd64.pyd +0 -0
- pyxcp/recorder/rekorder.cpp +18 -22
- pyxcp/recorder/rekorder.hpp +200 -587
- pyxcp/recorder/setup.py +11 -10
- pyxcp/recorder/test_reko.py +2 -3
- pyxcp/recorder/unfolder.hpp +1332 -0
- pyxcp/recorder/wrap.cpp +171 -9
- pyxcp/recorder/writer.hpp +302 -0
- pyxcp/scripts/pyxcp_probe_can_drivers.py +0 -2
- pyxcp/scripts/xcp_examples.py +64 -0
- pyxcp/scripts/xcp_fetch_a2l.py +15 -10
- pyxcp/scripts/xcp_id_scanner.py +2 -6
- pyxcp/scripts/xcp_info.py +101 -63
- pyxcp/scripts/xcp_profile.py +27 -0
- pyxcp/stim/__init__.py +0 -0
- pyxcp/tests/test_asam_types.py +2 -2
- pyxcp/tests/test_binpacking.py +186 -0
- pyxcp/tests/test_can.py +1132 -38
- pyxcp/tests/test_checksum.py +2 -1
- pyxcp/tests/test_daq.py +193 -0
- pyxcp/tests/test_frame_padding.py +6 -3
- pyxcp/tests/test_master.py +42 -31
- pyxcp/tests/test_transport.py +12 -12
- pyxcp/tests/test_utils.py +2 -5
- pyxcp/timing.py +0 -2
- pyxcp/transport/__init__.py +9 -9
- pyxcp/transport/base.py +149 -127
- pyxcp/transport/base_transport.hpp +0 -0
- pyxcp/transport/can.py +194 -167
- pyxcp/transport/eth.py +80 -82
- pyxcp/transport/sxi.py +106 -60
- pyxcp/transport/transport_wrapper.cpp +0 -0
- pyxcp/transport/usb_transport.py +65 -83
- pyxcp/types.py +69 -20
- pyxcp/utils.py +47 -16
- pyxcp/vector/map.py +1 -3
- {pyxcp-0.21.9.dist-info → pyxcp-0.22.23.dist-info}/METADATA +28 -23
- pyxcp-0.22.23.dist-info/RECORD +131 -0
- {pyxcp-0.21.9.dist-info → pyxcp-0.22.23.dist-info}/WHEEL +1 -1
- {pyxcp-0.21.9.dist-info → pyxcp-0.22.23.dist-info}/entry_points.txt +2 -0
- pyxcp/config.py +0 -57
- pyxcp/cxx/asynchiofactory.hpp +0 -24
- pyxcp/cxx/blocking_client.cpp +0 -44
- pyxcp/cxx/blocking_socket.cpp +0 -43
- pyxcp/cxx/blocking_socket.hpp +0 -558
- pyxcp/cxx/concurrent_queue.hpp +0 -60
- pyxcp/cxx/eth.hpp +0 -57
- pyxcp/cxx/exceptions.hpp +0 -30
- pyxcp/cxx/iasyncioservice.hpp +0 -31
- pyxcp/cxx/iresource.hpp +0 -17
- pyxcp/cxx/isocket.hpp +0 -22
- pyxcp/cxx/linux/epoll.cpp +0 -51
- pyxcp/cxx/linux/epoll.hpp +0 -87
- pyxcp/cxx/linux/lit_tester.cpp +0 -19
- pyxcp/cxx/linux/socket.hpp +0 -234
- pyxcp/cxx/linux/timeout.hpp +0 -81
- pyxcp/cxx/memoryblock.hpp +0 -42
- pyxcp/cxx/pool.hpp +0 -81
- pyxcp/cxx/poolmgr.cpp +0 -6
- pyxcp/cxx/poolmgr.hpp +0 -31
- pyxcp/cxx/test_queue.cpp +0 -69
- pyxcp/cxx/timestamp.hpp +0 -84
- pyxcp/cxx/utils.cpp +0 -38
- pyxcp/cxx/utils.hpp +0 -29
- pyxcp/cxx/win/iocp.cpp +0 -242
- pyxcp/cxx/win/iocp.hpp +0 -42
- pyxcp/cxx/win/perhandledata.hpp +0 -24
- pyxcp/cxx/win/periodata.hpp +0 -97
- pyxcp/cxx/win/socket.hpp +0 -185
- pyxcp/cxx/win/timeout.hpp +0 -83
- pyxcp/examples/conf_can.json +0 -20
- pyxcp/examples/conf_eth.json +0 -8
- pyxcp/logger.py +0 -67
- pyxcp/tests/test_config.py +0 -62
- pyxcp/transport/candriver/__init__.py +0 -2
- pyxcp/transport/candriver/pc_canalystii.py +0 -27
- pyxcp/transport/candriver/pc_etas.py +0 -25
- pyxcp/transport/candriver/pc_gsusb.py +0 -23
- pyxcp/transport/candriver/pc_iscan.py +0 -23
- pyxcp/transport/candriver/pc_ixxat.py +0 -27
- pyxcp/transport/candriver/pc_kvaser.py +0 -39
- pyxcp/transport/candriver/pc_neovi.py +0 -31
- pyxcp/transport/candriver/pc_nican.py +0 -23
- pyxcp/transport/candriver/pc_nixnet.py +0 -23
- pyxcp/transport/candriver/pc_pcan.py +0 -25
- pyxcp/transport/candriver/pc_seeed.py +0 -28
- pyxcp/transport/candriver/pc_serial.py +0 -27
- pyxcp/transport/candriver/pc_slcan.py +0 -29
- pyxcp/transport/candriver/pc_socketcan.py +0 -23
- pyxcp/transport/candriver/pc_systec.py +0 -29
- pyxcp/transport/candriver/pc_usb2can.py +0 -30
- pyxcp/transport/candriver/pc_vector.py +0 -34
- pyxcp/transport/candriver/python_can.py +0 -101
- pyxcp/transport/cxx_ext/CMakeLists.txt +0 -51
- pyxcp/transport/cxx_ext/setup.py +0 -49
- pyxcp/transport/cxx_ext/tests/test_basic_socket.cpp +0 -39
- pyxcp/transport/cxx_ext/tests/test_pool.cpp +0 -39
- pyxcp/transport/cxx_ext/tests/test_timestamp.cpp +0 -27
- pyxcp-0.21.9.dist-info/RECORD +0 -147
- rekorder.cp39-win_amd64.pyd +0 -0
- {pyxcp-0.21.9.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
|
-
/*===
|
|
58
|
-
#
|
|
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
|
-
#
|
|
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
|
-
*
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
&&
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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),
|
|
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
|
-
|
|
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),
|
|
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),
|
|
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),
|
|
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),
|
|
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,
|
|
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
|
-
{
|
|
832
|
-
{
|
|
833
|
-
{
|
|
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
|
-
|
|
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 ==
|
|
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,
|
|
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
|
|
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
|
}
|