yencode 1.0.8 → 1.1.2
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.
- package/README.md +339 -231
- package/binding.gyp +292 -39
- package/crcutil-1.0/code/multiword_64_64_gcc_amd64_asm.cc +7 -7
- package/crcutil-1.0/code/multiword_64_64_gcc_i386_mmx.cc +14 -14
- package/crcutil-1.0/code/multiword_64_64_intrinsic_i386_mmx.cc +1 -1
- package/crcutil-1.0/code/uint128_sse2.h +2 -0
- package/index.js +329 -22
- package/package.json +2 -2
- package/src/common.h +299 -0
- package/src/crc.cc +95 -0
- package/src/crc.h +23 -0
- package/src/crc_arm.cc +175 -0
- package/src/crc_common.h +4 -0
- package/{crc_folding.c → src/crc_folding.cc} +175 -185
- package/src/decoder.cc +61 -0
- package/src/decoder.h +53 -0
- package/src/decoder_avx.cc +18 -0
- package/src/decoder_avx2.cc +18 -0
- package/src/decoder_avx2_base.h +615 -0
- package/src/decoder_common.h +512 -0
- package/src/decoder_neon.cc +474 -0
- package/src/decoder_neon64.cc +451 -0
- package/src/decoder_sse2.cc +16 -0
- package/src/decoder_sse_base.h +711 -0
- package/src/decoder_ssse3.cc +18 -0
- package/src/encoder.cc +170 -0
- package/src/encoder.h +21 -0
- package/src/encoder_avx.cc +16 -0
- package/src/encoder_avx2.cc +16 -0
- package/src/encoder_avx_base.h +564 -0
- package/src/encoder_common.h +109 -0
- package/src/encoder_neon.cc +547 -0
- package/src/encoder_sse2.cc +13 -0
- package/src/encoder_sse_base.h +724 -0
- package/src/encoder_ssse3.cc +18 -0
- package/src/hedley.h +1899 -0
- package/src/platform.cc +147 -0
- package/src/yencode.cc +449 -0
- package/test/_maxsize.js +9 -0
- package/test/_speedbase.js +147 -0
- package/test/speedcrc.js +20 -0
- package/test/speeddec.js +92 -0
- package/test/speedenc.js +44 -0
- package/{testcrc.js → test/testcrc.js} +53 -39
- package/test/testdec.js +183 -0
- package/test/testenc.js +163 -0
- package/test/testpostdec.js +126 -0
- package/test.js +0 -91
- package/yencode.cc +0 -1622
|
@@ -0,0 +1,512 @@
|
|
|
1
|
+
#include "decoder.h"
|
|
2
|
+
|
|
3
|
+
// TODO: need to support max output length somehow
|
|
4
|
+
// TODO: add branch probabilities
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
// state var: refers to the previous state - only used for incremental processing
|
|
8
|
+
template<bool isRaw>
|
|
9
|
+
size_t do_decode_noend_scalar(const unsigned char* HEDLEY_RESTRICT src, unsigned char* HEDLEY_RESTRICT dest, size_t len, YencDecoderState* state) {
|
|
10
|
+
const unsigned char *es = src + len; // end source pointer
|
|
11
|
+
unsigned char *p = dest; // destination pointer
|
|
12
|
+
long i = -(long)len; // input position
|
|
13
|
+
unsigned char c; // input character
|
|
14
|
+
|
|
15
|
+
if(len < 1) return 0;
|
|
16
|
+
|
|
17
|
+
if(isRaw) {
|
|
18
|
+
|
|
19
|
+
if(state) switch(*state) {
|
|
20
|
+
case YDEC_STATE_EQ:
|
|
21
|
+
c = es[i];
|
|
22
|
+
*p++ = c - 42 - 64;
|
|
23
|
+
i++;
|
|
24
|
+
if(c == '\r') {
|
|
25
|
+
*state = YDEC_STATE_CR;
|
|
26
|
+
if(i >= 0) return 0;
|
|
27
|
+
} else {
|
|
28
|
+
*state = YDEC_STATE_NONE;
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
// fall-thru
|
|
32
|
+
case YDEC_STATE_CR:
|
|
33
|
+
if(es[i] != '\n') break;
|
|
34
|
+
i++;
|
|
35
|
+
*state = YDEC_STATE_CRLF;
|
|
36
|
+
if(i >= 0) return 0;
|
|
37
|
+
// Else fall-thru
|
|
38
|
+
case YDEC_STATE_CRLF:
|
|
39
|
+
// skip past first dot
|
|
40
|
+
if(es[i] == '.') i++;
|
|
41
|
+
// fall-thru
|
|
42
|
+
default: break; // silence compiler warnings
|
|
43
|
+
} else // treat as YDEC_STATE_CRLF
|
|
44
|
+
if(es[i] == '.') i++;
|
|
45
|
+
|
|
46
|
+
for(; i < -2; i++) {
|
|
47
|
+
c = es[i];
|
|
48
|
+
switch(c) {
|
|
49
|
+
case '\r':
|
|
50
|
+
// skip past \r\n. sequences
|
|
51
|
+
//i += (es[i+1] == '\n' && es[i+2] == '.') << 1;
|
|
52
|
+
if(es[i+1] == '\n' && es[i+2] == '.')
|
|
53
|
+
i += 2;
|
|
54
|
+
// fall-thru
|
|
55
|
+
case '\n':
|
|
56
|
+
continue;
|
|
57
|
+
case '=':
|
|
58
|
+
c = es[i+1];
|
|
59
|
+
*p++ = c - 42 - 64;
|
|
60
|
+
i += (c != '\r'); // if we have a \r, reprocess character to deal with \r\n. case
|
|
61
|
+
continue;
|
|
62
|
+
default:
|
|
63
|
+
*p++ = c - 42;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if(state) *state = YDEC_STATE_NONE;
|
|
67
|
+
|
|
68
|
+
if(i == -2) { // 2nd last char
|
|
69
|
+
c = es[i];
|
|
70
|
+
switch(c) {
|
|
71
|
+
case '\r':
|
|
72
|
+
if(state && es[i+1] == '\n') {
|
|
73
|
+
*state = YDEC_STATE_CRLF;
|
|
74
|
+
return p - dest;
|
|
75
|
+
}
|
|
76
|
+
// Else fall-thru
|
|
77
|
+
case '\n':
|
|
78
|
+
break;
|
|
79
|
+
case '=':
|
|
80
|
+
c = es[i+1];
|
|
81
|
+
*p++ = c - 42 - 64;
|
|
82
|
+
i += (c != '\r');
|
|
83
|
+
break;
|
|
84
|
+
default:
|
|
85
|
+
*p++ = c - 42;
|
|
86
|
+
}
|
|
87
|
+
i++;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// do final char; we process this separately to prevent an overflow if the final char is '='
|
|
91
|
+
if(i == -1) {
|
|
92
|
+
c = es[i];
|
|
93
|
+
if(c != '\n' && c != '\r' && c != '=') {
|
|
94
|
+
*p++ = c - 42;
|
|
95
|
+
} else if(state) {
|
|
96
|
+
if(c == '=') *state = YDEC_STATE_EQ;
|
|
97
|
+
else if(c == '\r') *state = YDEC_STATE_CR;
|
|
98
|
+
else *state = YDEC_STATE_NONE;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
} else {
|
|
103
|
+
|
|
104
|
+
if(state && *state == YDEC_STATE_EQ) {
|
|
105
|
+
*p++ = es[i] - 42 - 64;
|
|
106
|
+
i++;
|
|
107
|
+
*state = YDEC_STATE_NONE;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/*for(i = 0; i < len - 1; i++) {
|
|
111
|
+
c = src[i];
|
|
112
|
+
if(c == '\n' || c == '\r') continue;
|
|
113
|
+
unsigned char isEquals = (c == '=');
|
|
114
|
+
i += isEquals;
|
|
115
|
+
*p++ = src[i] - (42 + (isEquals << 6));
|
|
116
|
+
}*/
|
|
117
|
+
for(; i < -1; i++) {
|
|
118
|
+
c = es[i];
|
|
119
|
+
switch(c) {
|
|
120
|
+
case '\n': case '\r': continue;
|
|
121
|
+
case '=':
|
|
122
|
+
i++;
|
|
123
|
+
c = es[i] - 64;
|
|
124
|
+
}
|
|
125
|
+
*p++ = c - 42;
|
|
126
|
+
}
|
|
127
|
+
if(state) *state = YDEC_STATE_NONE;
|
|
128
|
+
// do final char; we process this separately to prevent an overflow if the final char is '='
|
|
129
|
+
if(i == -1) {
|
|
130
|
+
c = es[i];
|
|
131
|
+
if(c != '\n' && c != '\r' && c != '=') {
|
|
132
|
+
*p++ = c - 42;
|
|
133
|
+
} else
|
|
134
|
+
if(state) *state = (c == '=' ? YDEC_STATE_EQ : YDEC_STATE_NONE);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return p - dest;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
template<bool isRaw>
|
|
143
|
+
YencDecoderEnd do_decode_end_scalar(const unsigned char* HEDLEY_RESTRICT* src, unsigned char* HEDLEY_RESTRICT* dest, size_t len, YencDecoderState* state) {
|
|
144
|
+
const unsigned char *es = (*src) + len; // end source pointer
|
|
145
|
+
unsigned char *p = *dest; // destination pointer
|
|
146
|
+
long i = -(long)len; // input position
|
|
147
|
+
unsigned char c; // input character
|
|
148
|
+
|
|
149
|
+
if(len < 1) return YDEC_END_NONE;
|
|
150
|
+
|
|
151
|
+
#define YDEC_CHECK_END(s) if(i == 0) { \
|
|
152
|
+
*state = s; \
|
|
153
|
+
*src = es; \
|
|
154
|
+
*dest = p; \
|
|
155
|
+
return YDEC_END_NONE; \
|
|
156
|
+
}
|
|
157
|
+
if(state) switch(*state) {
|
|
158
|
+
case YDEC_STATE_CRLFEQ: do_decode_endable_scalar_ceq:
|
|
159
|
+
if(es[i] == 'y') {
|
|
160
|
+
*state = YDEC_STATE_NONE;
|
|
161
|
+
*src = es+i+1;
|
|
162
|
+
*dest = p;
|
|
163
|
+
return YDEC_END_CONTROL;
|
|
164
|
+
} // Else fall-thru
|
|
165
|
+
case YDEC_STATE_EQ:
|
|
166
|
+
c = es[i];
|
|
167
|
+
*p++ = c - 42 - 64;
|
|
168
|
+
i++;
|
|
169
|
+
if(c != '\r') break;
|
|
170
|
+
YDEC_CHECK_END(YDEC_STATE_CR)
|
|
171
|
+
// fall-through
|
|
172
|
+
case YDEC_STATE_CR:
|
|
173
|
+
if(es[i] != '\n') break;
|
|
174
|
+
i++;
|
|
175
|
+
YDEC_CHECK_END(YDEC_STATE_CRLF)
|
|
176
|
+
// fall-through
|
|
177
|
+
case YDEC_STATE_CRLF: do_decode_endable_scalar_c0:
|
|
178
|
+
if(es[i] == '.' && isRaw) {
|
|
179
|
+
i++;
|
|
180
|
+
YDEC_CHECK_END(YDEC_STATE_CRLFDT)
|
|
181
|
+
// fall-through
|
|
182
|
+
} else if(es[i] == '=') {
|
|
183
|
+
i++;
|
|
184
|
+
YDEC_CHECK_END(YDEC_STATE_CRLFEQ)
|
|
185
|
+
goto do_decode_endable_scalar_ceq;
|
|
186
|
+
} else
|
|
187
|
+
break;
|
|
188
|
+
case YDEC_STATE_CRLFDT:
|
|
189
|
+
if(isRaw && es[i] == '\r') {
|
|
190
|
+
i++;
|
|
191
|
+
YDEC_CHECK_END(YDEC_STATE_CRLFDTCR)
|
|
192
|
+
// fall-through
|
|
193
|
+
} else if(isRaw && es[i] == '=') { // check for dot-stuffed ending: \r\n.=y
|
|
194
|
+
i++;
|
|
195
|
+
YDEC_CHECK_END(YDEC_STATE_CRLFEQ)
|
|
196
|
+
goto do_decode_endable_scalar_ceq;
|
|
197
|
+
} else
|
|
198
|
+
break;
|
|
199
|
+
case YDEC_STATE_CRLFDTCR:
|
|
200
|
+
if(es[i] == '\n') {
|
|
201
|
+
if(isRaw) {
|
|
202
|
+
*state = YDEC_STATE_CRLF;
|
|
203
|
+
*src = es + i + 1;
|
|
204
|
+
*dest = p;
|
|
205
|
+
return YDEC_END_ARTICLE;
|
|
206
|
+
} else {
|
|
207
|
+
i++;
|
|
208
|
+
YDEC_CHECK_END(YDEC_STATE_CRLF)
|
|
209
|
+
goto do_decode_endable_scalar_c0; // handle as CRLF
|
|
210
|
+
}
|
|
211
|
+
} else
|
|
212
|
+
break;
|
|
213
|
+
case YDEC_STATE_NONE: break; // silence compiler warning
|
|
214
|
+
} else // treat as YDEC_STATE_CRLF
|
|
215
|
+
goto do_decode_endable_scalar_c0;
|
|
216
|
+
|
|
217
|
+
for(; i < -2; i++) {
|
|
218
|
+
c = es[i];
|
|
219
|
+
switch(c) {
|
|
220
|
+
case '\r': if(es[i+1] == '\n') {
|
|
221
|
+
if(isRaw && es[i+2] == '.') {
|
|
222
|
+
// skip past \r\n. sequences
|
|
223
|
+
i += 3;
|
|
224
|
+
YDEC_CHECK_END(YDEC_STATE_CRLFDT)
|
|
225
|
+
// check for end
|
|
226
|
+
if(es[i] == '\r') {
|
|
227
|
+
i++;
|
|
228
|
+
YDEC_CHECK_END(YDEC_STATE_CRLFDTCR)
|
|
229
|
+
if(es[i] == '\n') {
|
|
230
|
+
*src = es + i + 1;
|
|
231
|
+
*dest = p;
|
|
232
|
+
*state = YDEC_STATE_CRLF;
|
|
233
|
+
return YDEC_END_ARTICLE;
|
|
234
|
+
} else i--;
|
|
235
|
+
} else if(es[i] == '=') {
|
|
236
|
+
i++;
|
|
237
|
+
YDEC_CHECK_END(YDEC_STATE_CRLFEQ)
|
|
238
|
+
if(es[i] == 'y') {
|
|
239
|
+
*src = es + i + 1;
|
|
240
|
+
*dest = p;
|
|
241
|
+
*state = YDEC_STATE_NONE;
|
|
242
|
+
return YDEC_END_CONTROL;
|
|
243
|
+
} else {
|
|
244
|
+
// escape char & continue
|
|
245
|
+
c = es[i];
|
|
246
|
+
*p++ = c - 42 - 64;
|
|
247
|
+
i -= (c == '\r');
|
|
248
|
+
}
|
|
249
|
+
} else i--;
|
|
250
|
+
}
|
|
251
|
+
else if(es[i+2] == '=') {
|
|
252
|
+
i += 3;
|
|
253
|
+
YDEC_CHECK_END(YDEC_STATE_CRLFEQ)
|
|
254
|
+
if(es[i] == 'y') {
|
|
255
|
+
// ended
|
|
256
|
+
*src = es + i + 1;
|
|
257
|
+
*dest = p;
|
|
258
|
+
*state = YDEC_STATE_NONE;
|
|
259
|
+
return YDEC_END_CONTROL;
|
|
260
|
+
} else {
|
|
261
|
+
// escape char & continue
|
|
262
|
+
c = es[i];
|
|
263
|
+
*p++ = c - 42 - 64;
|
|
264
|
+
i -= (c == '\r');
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
} // fall-thru
|
|
268
|
+
case '\n':
|
|
269
|
+
continue;
|
|
270
|
+
case '=':
|
|
271
|
+
c = es[i+1];
|
|
272
|
+
*p++ = c - 42 - 64;
|
|
273
|
+
i += (c != '\r'); // if we have a \r, reprocess character to deal with \r\n. case
|
|
274
|
+
continue;
|
|
275
|
+
default:
|
|
276
|
+
*p++ = c - 42;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
if(state) *state = YDEC_STATE_NONE;
|
|
280
|
+
|
|
281
|
+
if(i == -2) { // 2nd last char
|
|
282
|
+
c = es[i];
|
|
283
|
+
switch(c) {
|
|
284
|
+
case '\r':
|
|
285
|
+
if(state && es[i+1] == '\n') {
|
|
286
|
+
*state = YDEC_STATE_CRLF;
|
|
287
|
+
*src = es;
|
|
288
|
+
*dest = p;
|
|
289
|
+
return YDEC_END_NONE;
|
|
290
|
+
}
|
|
291
|
+
// Else fall-thru
|
|
292
|
+
case '\n':
|
|
293
|
+
break;
|
|
294
|
+
case '=':
|
|
295
|
+
c = es[i+1];
|
|
296
|
+
*p++ = c - 42 - 64;
|
|
297
|
+
i += (c != '\r');
|
|
298
|
+
break;
|
|
299
|
+
default:
|
|
300
|
+
*p++ = c - 42;
|
|
301
|
+
}
|
|
302
|
+
i++;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// do final char; we process this separately to prevent an overflow if the final char is '='
|
|
306
|
+
if(i == -1) {
|
|
307
|
+
c = es[i];
|
|
308
|
+
if(c != '\n' && c != '\r' && c != '=') {
|
|
309
|
+
*p++ = c - 42;
|
|
310
|
+
} else if(state) {
|
|
311
|
+
if(c == '=') *state = YDEC_STATE_EQ;
|
|
312
|
+
else if(c == '\r') *state = YDEC_STATE_CR;
|
|
313
|
+
else *state = YDEC_STATE_NONE;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
#undef YDEC_CHECK_END
|
|
317
|
+
|
|
318
|
+
*src = es;
|
|
319
|
+
*dest = p;
|
|
320
|
+
return YDEC_END_NONE;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
template<bool isRaw, bool searchEnd>
|
|
324
|
+
YencDecoderEnd do_decode_scalar(const unsigned char* HEDLEY_RESTRICT* src, unsigned char* HEDLEY_RESTRICT* dest, size_t len, YencDecoderState* state) {
|
|
325
|
+
if(searchEnd)
|
|
326
|
+
return do_decode_end_scalar<isRaw>(src, dest, len, state);
|
|
327
|
+
*dest += do_decode_noend_scalar<isRaw>(*src, *dest, len, state);
|
|
328
|
+
*src += len;
|
|
329
|
+
return YDEC_END_NONE;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
template<bool isRaw, bool searchEnd, int width, void(&kernel)(const uint8_t* HEDLEY_RESTRICT, long&, unsigned char* HEDLEY_RESTRICT &, unsigned char&, uint16_t&)>
|
|
335
|
+
YencDecoderEnd do_decode_simd(const unsigned char* HEDLEY_RESTRICT* src, unsigned char* HEDLEY_RESTRICT* dest, size_t len, YencDecoderState* state) {
|
|
336
|
+
if(len <= width*2) return do_decode_scalar<isRaw, searchEnd>(src, dest, len, state);
|
|
337
|
+
|
|
338
|
+
YencDecoderState tState = YDEC_STATE_CRLF;
|
|
339
|
+
YencDecoderState* pState = state ? state : &tState;
|
|
340
|
+
if((uintptr_t)(*src) & ((width-1))) {
|
|
341
|
+
// find source memory alignment
|
|
342
|
+
unsigned char* aSrc = (unsigned char*)(((uintptr_t)(*src) + (width-1)) & ~(width-1));
|
|
343
|
+
int amount = (int)(aSrc - *src);
|
|
344
|
+
len -= amount;
|
|
345
|
+
YencDecoderEnd ended = do_decode_scalar<isRaw, searchEnd>(src, dest, amount, pState);
|
|
346
|
+
if(ended) return ended;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
size_t lenBuffer = width -1;
|
|
350
|
+
if(searchEnd) lenBuffer += 3 + (isRaw?1:0);
|
|
351
|
+
else if(isRaw) lenBuffer += 2;
|
|
352
|
+
|
|
353
|
+
if(len > lenBuffer) {
|
|
354
|
+
unsigned char *p = *dest; // destination pointer
|
|
355
|
+
unsigned char escFirst = 0; // input character; first char needs escaping
|
|
356
|
+
uint16_t nextMask = 0;
|
|
357
|
+
// handle finicky case of special sequences straddled across initial boundary
|
|
358
|
+
switch(*pState) {
|
|
359
|
+
case YDEC_STATE_CRLF:
|
|
360
|
+
if(isRaw && **src == '.') {
|
|
361
|
+
nextMask = 1;
|
|
362
|
+
if(searchEnd && *(uint16_t*)(*src +1) == UINT16_PACK('\r','\n')) {
|
|
363
|
+
(*src) += 3;
|
|
364
|
+
*pState = YDEC_STATE_CRLF;
|
|
365
|
+
return YDEC_END_ARTICLE;
|
|
366
|
+
}
|
|
367
|
+
if(searchEnd && *(uint16_t*)(*src +1) == UINT16_PACK('=','y')) {
|
|
368
|
+
(*src) += 3;
|
|
369
|
+
*pState = YDEC_STATE_NONE;
|
|
370
|
+
return YDEC_END_CONTROL;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
else if(searchEnd && *(uint16_t*)(*src) == UINT16_PACK('=','y')) {
|
|
374
|
+
(*src) += 2;
|
|
375
|
+
*pState = YDEC_STATE_NONE;
|
|
376
|
+
return YDEC_END_CONTROL;
|
|
377
|
+
}
|
|
378
|
+
break;
|
|
379
|
+
case YDEC_STATE_CR:
|
|
380
|
+
if(isRaw && *(uint16_t*)(*src) == UINT16_PACK('\n','.')) {
|
|
381
|
+
nextMask = 2;
|
|
382
|
+
if(searchEnd && *(uint16_t*)(*src +2) == UINT16_PACK('\r','\n')) {
|
|
383
|
+
(*src) += 4;
|
|
384
|
+
*pState = YDEC_STATE_CRLF;
|
|
385
|
+
return YDEC_END_ARTICLE;
|
|
386
|
+
}
|
|
387
|
+
if(searchEnd && *(uint16_t*)(*src +2) == UINT16_PACK('=','y')) {
|
|
388
|
+
(*src) += 4;
|
|
389
|
+
*pState = YDEC_STATE_NONE;
|
|
390
|
+
return YDEC_END_CONTROL;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
else if(searchEnd && (*(uint32_t*)(*src) & 0xffffff) == UINT32_PACK('\n','=','y',0)) {
|
|
394
|
+
(*src) += 3;
|
|
395
|
+
*pState = YDEC_STATE_NONE;
|
|
396
|
+
return YDEC_END_CONTROL;
|
|
397
|
+
}
|
|
398
|
+
break;
|
|
399
|
+
case YDEC_STATE_CRLFDT:
|
|
400
|
+
if(searchEnd && isRaw && *(uint16_t*)(*src) == UINT16_PACK('\r','\n')) {
|
|
401
|
+
(*src) += 2;
|
|
402
|
+
*pState = YDEC_STATE_CRLF;
|
|
403
|
+
return YDEC_END_ARTICLE;
|
|
404
|
+
}
|
|
405
|
+
if(searchEnd && isRaw && *(uint16_t*)(*src) == UINT16_PACK('=','y')) {
|
|
406
|
+
(*src) += 2;
|
|
407
|
+
*pState = YDEC_STATE_NONE;
|
|
408
|
+
return YDEC_END_CONTROL;
|
|
409
|
+
}
|
|
410
|
+
break;
|
|
411
|
+
case YDEC_STATE_CRLFDTCR:
|
|
412
|
+
if(searchEnd && isRaw && **src == '\n') {
|
|
413
|
+
(*src) += 1;
|
|
414
|
+
*pState = YDEC_STATE_CRLF;
|
|
415
|
+
return YDEC_END_ARTICLE;
|
|
416
|
+
}
|
|
417
|
+
break;
|
|
418
|
+
case YDEC_STATE_CRLFEQ:
|
|
419
|
+
if(searchEnd && **src == 'y') {
|
|
420
|
+
(*src) += 1;
|
|
421
|
+
*pState = YDEC_STATE_NONE;
|
|
422
|
+
return YDEC_END_CONTROL;
|
|
423
|
+
}
|
|
424
|
+
break;
|
|
425
|
+
default: break; // silence compiler warning
|
|
426
|
+
}
|
|
427
|
+
escFirst = (*pState == YDEC_STATE_EQ || *pState == YDEC_STATE_CRLFEQ);
|
|
428
|
+
|
|
429
|
+
// our algorithm may perform an aligned load on the next part, of which we consider 2 bytes (for \r\n. sequence checking)
|
|
430
|
+
long dLen = (long)(len - lenBuffer);
|
|
431
|
+
dLen = (dLen + (width-1)) & ~(width-1);
|
|
432
|
+
|
|
433
|
+
kernel((const uint8_t*)(*src) + dLen, dLen, p, escFirst, nextMask);
|
|
434
|
+
|
|
435
|
+
if(escFirst) *pState = YDEC_STATE_EQ; // escape next character
|
|
436
|
+
else if(nextMask == 1) *pState = YDEC_STATE_CRLF; // next character is '.', where previous two were \r\n
|
|
437
|
+
else if(nextMask == 2) *pState = YDEC_STATE_CR; // next characters are '\n.', previous is \r
|
|
438
|
+
else *pState = YDEC_STATE_NONE;
|
|
439
|
+
|
|
440
|
+
*src += dLen;
|
|
441
|
+
len -= dLen;
|
|
442
|
+
*dest = p;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
// end alignment
|
|
446
|
+
if(len)
|
|
447
|
+
return do_decode_scalar<isRaw, searchEnd>(src, dest, len, pState);
|
|
448
|
+
/** for debugging: ensure that the SIMD routine doesn't exit early
|
|
449
|
+
if(len && !searchEnd) {
|
|
450
|
+
const uint8_t* s = *src;
|
|
451
|
+
unsigned char* p = *dest;
|
|
452
|
+
int ended = do_decode_scalar<isRaw, searchEnd>(src, dest, len, pState);
|
|
453
|
+
if(*src - s > width*2) {
|
|
454
|
+
// this shouldn't happen, corrupt some data to fail the test
|
|
455
|
+
while(p < *dest)
|
|
456
|
+
*p++ = 0;
|
|
457
|
+
}
|
|
458
|
+
return ended;
|
|
459
|
+
}
|
|
460
|
+
*/
|
|
461
|
+
return YDEC_END_NONE;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
static inline void decoder_init_lut(uint8_t* eqFixLUT, void* compactLUT) {
|
|
465
|
+
for(int i=0; i<256; i++) {
|
|
466
|
+
int k = i;
|
|
467
|
+
int p = 0;
|
|
468
|
+
|
|
469
|
+
// fix LUT
|
|
470
|
+
k = i;
|
|
471
|
+
p = 0;
|
|
472
|
+
for(int j=0; j<8; j++) {
|
|
473
|
+
k = i >> j;
|
|
474
|
+
if(k & 1) {
|
|
475
|
+
p |= 1 << j;
|
|
476
|
+
j++;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
eqFixLUT[i] = p;
|
|
480
|
+
|
|
481
|
+
#ifdef YENC_DEC_USE_THINTABLE
|
|
482
|
+
uint8_t* res = (uint8_t*)compactLUT + i*8;
|
|
483
|
+
k = i;
|
|
484
|
+
p = 0;
|
|
485
|
+
for(int j=0; j<8; j++) {
|
|
486
|
+
if(!(k & 1)) {
|
|
487
|
+
res[p++] = j;
|
|
488
|
+
}
|
|
489
|
+
k >>= 1;
|
|
490
|
+
}
|
|
491
|
+
for(; p<8; p++)
|
|
492
|
+
res[p] = 0x80;
|
|
493
|
+
#endif
|
|
494
|
+
}
|
|
495
|
+
#ifndef YENC_DEC_USE_THINTABLE
|
|
496
|
+
for(int i=0; i<32768; i++) {
|
|
497
|
+
int k = i;
|
|
498
|
+
uint8_t* res = (uint8_t*)compactLUT + i*16;
|
|
499
|
+
int p = 0;
|
|
500
|
+
|
|
501
|
+
for(int j=0; j<16; j++) {
|
|
502
|
+
if(!(k & 1)) {
|
|
503
|
+
res[p++] = j;
|
|
504
|
+
}
|
|
505
|
+
k >>= 1;
|
|
506
|
+
}
|
|
507
|
+
for(; p<16; p++)
|
|
508
|
+
res[p] = 0x80;
|
|
509
|
+
}
|
|
510
|
+
#endif
|
|
511
|
+
}
|
|
512
|
+
|