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
package/test/testenc.js
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
// a basic script to test that raw yEnc works as expected
|
|
2
|
+
|
|
3
|
+
var assert = require('assert');
|
|
4
|
+
var y = (function() {
|
|
5
|
+
try {
|
|
6
|
+
return require('../build/Debug/yencode.node');
|
|
7
|
+
} catch(x) {}
|
|
8
|
+
return require('../build/Release/yencode.node');
|
|
9
|
+
})();
|
|
10
|
+
var maxSize = require('./_maxsize');
|
|
11
|
+
|
|
12
|
+
// slow reference yEnc implementation
|
|
13
|
+
var refYEnc = function(src, line_size, col) {
|
|
14
|
+
var ret = [];
|
|
15
|
+
for (var i = 0; i < src.length; i++) {
|
|
16
|
+
var c = (src[i] + 42) & 0xFF;
|
|
17
|
+
switch(String.fromCharCode(c)) {
|
|
18
|
+
case '.':
|
|
19
|
+
if(col > 0) break;
|
|
20
|
+
case '\t': case ' ':
|
|
21
|
+
if(col > 0 && col < line_size-1) break;
|
|
22
|
+
case '\0': case '\r': case '\n': case '=':
|
|
23
|
+
ret.push('='.charCodeAt(0));
|
|
24
|
+
c += 64;
|
|
25
|
+
col++;
|
|
26
|
+
}
|
|
27
|
+
ret.push(c);
|
|
28
|
+
col++;
|
|
29
|
+
if(col >= line_size) {
|
|
30
|
+
ret.push('\r'.charCodeAt(0));
|
|
31
|
+
ret.push('\n'.charCodeAt(0));
|
|
32
|
+
col = 0;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// if there's a trailing newline, trim it
|
|
37
|
+
if(ret[ret.length-2] == '\r'.charCodeAt(0) && ret[ret.length-1] == '\n'.charCodeAt(0)) {
|
|
38
|
+
ret.pop();
|
|
39
|
+
ret.pop();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// if the last character is tab/space, escape it
|
|
43
|
+
if(ret[ret.length-1] == '\t'.charCodeAt(0) || ret[ret.length-1] == ' '.charCodeAt(0)) {
|
|
44
|
+
var c = ret[ret.length-1];
|
|
45
|
+
ret.pop();
|
|
46
|
+
ret.push('='.charCodeAt(0));
|
|
47
|
+
ret.push((c+64) & 0xFF);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return new Buffer(ret);
|
|
51
|
+
};
|
|
52
|
+
var doTest = function(msg, test, expected) {
|
|
53
|
+
test[0] = new Buffer(test[0]);
|
|
54
|
+
if(!test[1]) test[1] = 128; // line size
|
|
55
|
+
if(!test[2]) test[2] = 0; // column offset
|
|
56
|
+
|
|
57
|
+
if(!expected && expected !== '') expected = refYEnc.apply(null, test).toString('hex');
|
|
58
|
+
else expected = expected.replace(/ /g, '');
|
|
59
|
+
var actual = y.encode.apply(null, test).toString('hex');
|
|
60
|
+
if(actual != expected) {
|
|
61
|
+
console.log('Actual:', actual);
|
|
62
|
+
console.log('Expect:', expected);
|
|
63
|
+
console.log('Source:', test[0].toString('hex'));
|
|
64
|
+
assert.equal(actual, expected, msg);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
var buf = new Buffer(maxSize(test[0].length, test[1]));
|
|
68
|
+
var len = y.encodeTo.apply(null, [test[0], buf].concat(test.slice(1)));
|
|
69
|
+
assert.equal(buf.slice(0, len).toString('hex'), expected, msg);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
var range = function(start, end) {
|
|
73
|
+
var ret = Array(end-start);
|
|
74
|
+
for(var i=start; i<end; i++)
|
|
75
|
+
ret[i-start] = i;
|
|
76
|
+
return ret;
|
|
77
|
+
}
|
|
78
|
+
var multiRange = function(list) {
|
|
79
|
+
var ret = [];
|
|
80
|
+
for(var i=0; i<list.length; i+=2) {
|
|
81
|
+
ret = ret.concat(range(list[i], list[i+1]));
|
|
82
|
+
}
|
|
83
|
+
return ret;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
var lineSizes = // 48 sizes to test
|
|
87
|
+
range(1, 18).concat(range(23, 26)).concat(range(30, 35)).concat(range(46, 51)).concat(range(62, 67)).concat(range(126, 131)).concat([136, 145, 159]).concat(range(254, 259));
|
|
88
|
+
var runLineSizes = function(fn) {
|
|
89
|
+
lineSizes.forEach(function(ls) {
|
|
90
|
+
lineSizes.forEach(function(offs) {
|
|
91
|
+
if(offs >= ls) return;
|
|
92
|
+
fn(ls, offs);
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
// simple tests
|
|
98
|
+
runLineSizes(function(ls, offs) {
|
|
99
|
+
var infoStr = ' [ls='+ls+', offs='+offs+']';
|
|
100
|
+
var b = new Buffer(256);
|
|
101
|
+
b.fill(0);
|
|
102
|
+
doTest('Long no escaping' + infoStr, [b, ls]);
|
|
103
|
+
b.fill(227);
|
|
104
|
+
doTest('Long all escaping' + infoStr, [b, ls]);
|
|
105
|
+
b.fill(4);
|
|
106
|
+
doTest('Long all dots' + infoStr, [b, ls]);
|
|
107
|
+
b.fill(223);
|
|
108
|
+
doTest('Long all tabs' + infoStr, [b, ls]);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
// case tests
|
|
112
|
+
var padLens = range(0, 35).concat(range(46, 51)).concat(range(62, 67));
|
|
113
|
+
var padding = new Buffer(128);
|
|
114
|
+
padding.fill(97); // 'a'
|
|
115
|
+
[ ['Empty test', [[]], ''],
|
|
116
|
+
['Simple test', [[0,1,2,3,224,4]]],
|
|
117
|
+
['Partial tab line', [[223, 223, 223]]],
|
|
118
|
+
['Dot first should escape', [[4,3,224,2,1,0]]],
|
|
119
|
+
['Short line', [[0,1,2,3,4], 2]],
|
|
120
|
+
['Short line (2)', [[0,1,224,3,4], 2]],
|
|
121
|
+
['Short line + offset', [[0,1,2,3,4], 2, 1]],
|
|
122
|
+
['Short line (2) + offset', [[0,1,224,3,4], 2, 1]],
|
|
123
|
+
['Tab & lf around line break', [[223,224], 128, 127], '3d 49 0d 0a 3d 4a'],
|
|
124
|
+
].forEach(function(test) {
|
|
125
|
+
doTest.apply(null, test);
|
|
126
|
+
if(test.length == 2) {
|
|
127
|
+
// if no defined result, try padding the data to make it long enough to invoke SIMD behaviour
|
|
128
|
+
padLens.forEach(function(prepad) {
|
|
129
|
+
padLens.forEach(function(postpad) {
|
|
130
|
+
var newBuf = Buffer.concat([padding.slice(0, prepad), new Buffer(test[1][0]), padding.slice(0, postpad)]);
|
|
131
|
+
var newTest = test.slice();
|
|
132
|
+
newTest[1] = [newBuf].concat(newTest[1].slice(1));
|
|
133
|
+
doTest.apply(null, newTest);
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// random tests
|
|
140
|
+
for(var i=0; i<32; i++) {
|
|
141
|
+
var rand = require('crypto').pseudoRandomBytes(4*1024);
|
|
142
|
+
runLineSizes(function(ls, offs) {
|
|
143
|
+
doTest('Random [ls='+ls+', offs='+offs+']', [rand, ls, offs]);
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// targeted random tests
|
|
148
|
+
var charset = 'a\xd6\xdf\xe0\xe3\xf6\x04\x13';
|
|
149
|
+
var randStr = function(n) {
|
|
150
|
+
var ret = new Buffer(n);
|
|
151
|
+
for(var i=0; i<n; i++)
|
|
152
|
+
ret[i] = charset[(Math.random() * charset.length) | 0].charCodeAt(0);
|
|
153
|
+
return ret;
|
|
154
|
+
};
|
|
155
|
+
for(var i=0; i<32; i++) {
|
|
156
|
+
var rand = randStr(2048);
|
|
157
|
+
runLineSizes(function(ls, offs) {
|
|
158
|
+
doTest('Random2 [ls='+ls+', offs='+offs+']', [rand, ls, offs]);
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
console.log('All tests passed');
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
|
|
2
|
+
var assert = require('assert');
|
|
3
|
+
var y = require('../index.js');
|
|
4
|
+
|
|
5
|
+
var assertObjectHas = function(obj, required) {
|
|
6
|
+
for(var k in required) {
|
|
7
|
+
if(required[k] === undefined || required[k] === null)
|
|
8
|
+
assert(obj[k] === required[k]);
|
|
9
|
+
else if(typeof required[k] === 'object') // recurse to sub-objects
|
|
10
|
+
assertObjectHas(obj[k], required[k]);
|
|
11
|
+
else
|
|
12
|
+
assert.equal(obj[k], required[k], k);
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
var post, postData;
|
|
17
|
+
|
|
18
|
+
// test basic post
|
|
19
|
+
postData = [
|
|
20
|
+
'=ybegin part=5 line=128 size=500000 name=myBinary.dat',
|
|
21
|
+
'=ypart begin=499991 end=500000',
|
|
22
|
+
'..... data',
|
|
23
|
+
'=yend size=10 part=5 pcrc32=97f4bd52',
|
|
24
|
+
''
|
|
25
|
+
].join('\r\n');
|
|
26
|
+
post = y.from_post(new Buffer(postData));
|
|
27
|
+
assertObjectHas(post, {
|
|
28
|
+
yencStart: 0,
|
|
29
|
+
dataStart: postData.indexOf('...'),
|
|
30
|
+
dataEnd: postData.indexOf('\r\n=yend'),
|
|
31
|
+
yencEnd: postData.length,
|
|
32
|
+
props: {
|
|
33
|
+
begin: {
|
|
34
|
+
part: '5',
|
|
35
|
+
line: '128',
|
|
36
|
+
size: '500000',
|
|
37
|
+
name: 'myBinary.dat'
|
|
38
|
+
},
|
|
39
|
+
part: {
|
|
40
|
+
begin: '499991',
|
|
41
|
+
end: '500000'
|
|
42
|
+
},
|
|
43
|
+
end: {
|
|
44
|
+
size: '10',
|
|
45
|
+
part: '5',
|
|
46
|
+
pcrc32: '97f4bd52'
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
warnings: undefined
|
|
50
|
+
});
|
|
51
|
+
assert.equal(post.data.length, post.dataEnd - post.dataStart); // there's no escaped characters in this post, so length should equal input length
|
|
52
|
+
// won't bother testing actual encoding or CRC32 (leave this to other tests)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
// test post with extra data
|
|
56
|
+
postData = [
|
|
57
|
+
'ignored data',
|
|
58
|
+
'=ybegin part=5a some_prop=hello line=0 size=0 name=name with space and = chars',
|
|
59
|
+
'.... data',
|
|
60
|
+
'=yend size=2 pcrc32=invalid pcrc32=invalid invalid_prop',
|
|
61
|
+
].join('\r\n');
|
|
62
|
+
post = y.from_post(new Buffer(postData));
|
|
63
|
+
assertObjectHas(post, {
|
|
64
|
+
yencStart: postData.indexOf('=ybegin'),
|
|
65
|
+
dataStart: postData.indexOf('...'),
|
|
66
|
+
dataEnd: postData.indexOf('\r\n=yend'),
|
|
67
|
+
yencEnd: postData.length,
|
|
68
|
+
props: {
|
|
69
|
+
begin: {
|
|
70
|
+
part: '5a',
|
|
71
|
+
line: '0',
|
|
72
|
+
some_prop: 'hello',
|
|
73
|
+
name: 'name with space and = chars'
|
|
74
|
+
},
|
|
75
|
+
end: {
|
|
76
|
+
pcrc32: 'invalid'
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
assert.equal(post.data.length, post.dataEnd - post.dataStart);
|
|
81
|
+
// check that expected warnings are there
|
|
82
|
+
var seenWarnings = {};
|
|
83
|
+
post.warnings.forEach(function(warn) {
|
|
84
|
+
seenWarnings[warn.code] = warn.message;
|
|
85
|
+
});
|
|
86
|
+
assert(seenWarnings['ignored_line_data']);
|
|
87
|
+
assert(seenWarnings['duplicate_property']);
|
|
88
|
+
assert(seenWarnings['missing_yend_newline']);
|
|
89
|
+
assert(seenWarnings['invalid_prop_part']);
|
|
90
|
+
assert(seenWarnings['zero_prop_line']);
|
|
91
|
+
assert(seenWarnings['invalid_prop_pcrc32']);
|
|
92
|
+
assert(seenWarnings['size_mismatch']);
|
|
93
|
+
|
|
94
|
+
// empty post
|
|
95
|
+
postData = [
|
|
96
|
+
'=ybegin size=0 line=1 name=',
|
|
97
|
+
'=yend size=0',
|
|
98
|
+
''
|
|
99
|
+
].join('\r\n');
|
|
100
|
+
post = y.from_post(new Buffer(postData));
|
|
101
|
+
assertObjectHas(post, {
|
|
102
|
+
yencStart: 0,
|
|
103
|
+
dataStart: undefined,
|
|
104
|
+
dataEnd: undefined,
|
|
105
|
+
yencEnd: postData.length,
|
|
106
|
+
data: undefined,
|
|
107
|
+
warnings: undefined,
|
|
108
|
+
props: {
|
|
109
|
+
begin: {
|
|
110
|
+
size: '0',
|
|
111
|
+
line: '1',
|
|
112
|
+
name: ''
|
|
113
|
+
},
|
|
114
|
+
end: { size: '0' }
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
// test parse errors
|
|
120
|
+
post = y.from_post(new Buffer('invalid post'));
|
|
121
|
+
assert.equal(post.code, 'no_start_found');
|
|
122
|
+
post = y.from_post(new Buffer('=ybegin abc=def'));
|
|
123
|
+
assert.equal(post.code, 'no_end_found');
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
console.log('All tests passed');
|
package/test.js
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
// a basic script to test that raw yEnc works as expected
|
|
2
|
-
|
|
3
|
-
var assert = require('assert');
|
|
4
|
-
var y = require('./build/Release/yencode.node');
|
|
5
|
-
|
|
6
|
-
// slow reference yEnc implementation
|
|
7
|
-
var refYEnc = function(src, line_size, col) {
|
|
8
|
-
var ret = [];
|
|
9
|
-
for (var i = 0; i < src.length; i++) {
|
|
10
|
-
var c = (src[i] + 42) & 0xFF;
|
|
11
|
-
switch(String.fromCharCode(c)) {
|
|
12
|
-
case '.':
|
|
13
|
-
if(col > 0) break;
|
|
14
|
-
case '\t': case ' ':
|
|
15
|
-
if(col > 0 && col < line_size-1) break;
|
|
16
|
-
case '\0': case '\r': case '\n': case '=':
|
|
17
|
-
ret.push('='.charCodeAt(0));
|
|
18
|
-
c += 64;
|
|
19
|
-
col++;
|
|
20
|
-
}
|
|
21
|
-
ret.push(c);
|
|
22
|
-
col++;
|
|
23
|
-
if(col >= line_size) {
|
|
24
|
-
ret.push('\r'.charCodeAt(0));
|
|
25
|
-
ret.push('\n'.charCodeAt(0));
|
|
26
|
-
col = 0;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// if there's a trailing newline, trim it
|
|
31
|
-
if(ret[ret.length-2] == '\r'.charCodeAt(0) && ret[ret.length-1] == '\n'.charCodeAt(0)) {
|
|
32
|
-
ret.pop();
|
|
33
|
-
ret.pop();
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// if the last character is tab/space, escape it
|
|
37
|
-
if(ret[ret.length-1] == '\t'.charCodeAt(0) || ret[ret.length-1] == ' '.charCodeAt(0)) {
|
|
38
|
-
var c = ret[ret.length-1];
|
|
39
|
-
ret.pop();
|
|
40
|
-
ret.push('='.charCodeAt(0));
|
|
41
|
-
ret.push((c+64) & 0xFF);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return new Buffer(ret);
|
|
45
|
-
};
|
|
46
|
-
var doTest = function(msg, test, expected) {
|
|
47
|
-
test[0] = new Buffer(test[0]);
|
|
48
|
-
if(!test[1]) test[1] = 128; // line size
|
|
49
|
-
if(!test[2]) test[2] = 0; // column offset
|
|
50
|
-
|
|
51
|
-
if(!expected) expected = refYEnc.apply(null, test).toString('hex');
|
|
52
|
-
else expected = expected.replace(/ /g, '');
|
|
53
|
-
assert.equal(y.encode.apply(null, test).toString('hex'), expected, msg);
|
|
54
|
-
var buf = new Buffer(require('./').maxSize(test[0].length, test[1]));
|
|
55
|
-
var len = y.encodeTo.apply(null, [test[0], buf].concat(test.slice(1)));
|
|
56
|
-
assert.equal(buf.slice(0, len).toString('hex'), expected, msg);
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
doTest('Empty test', [[]], '');
|
|
61
|
-
doTest('Simple test', [[0,1,2,3,224,4]]);
|
|
62
|
-
doTest('Partial tab line', [[223, 223, 223]]);
|
|
63
|
-
doTest('Dot first should escape', [[4,3,224,2,1,0]]);
|
|
64
|
-
doTest('Short line', [[0,1,2,3,4], 2]);
|
|
65
|
-
doTest('Short line (2)', [[0,1,224,3,4], 2]);
|
|
66
|
-
doTest('Short line + offset', [[0,1,2,3,4], 2, 1]);
|
|
67
|
-
doTest('Short line (2) + offset', [[0,1,224,3,4], 2, 1]);
|
|
68
|
-
doTest('Tab & lf around line break', [[223,224], 128, 127], '3d 49 0d 0a 3d 4a');
|
|
69
|
-
|
|
70
|
-
// longer tests
|
|
71
|
-
var b = new Buffer(256);
|
|
72
|
-
b.fill(0);
|
|
73
|
-
doTest('Long no escaping', [b]);
|
|
74
|
-
b.fill(227);
|
|
75
|
-
doTest('Long all escaping', [b]);
|
|
76
|
-
b.fill(4);
|
|
77
|
-
doTest('Long all dots', [b]);
|
|
78
|
-
b.fill(223);
|
|
79
|
-
doTest('Long all tabs', [b]);
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
// random tests
|
|
83
|
-
for(var i=0; i<32; i++) {
|
|
84
|
-
var rand = require('crypto').pseudoRandomBytes(128*1024);
|
|
85
|
-
doTest('Random', [rand]);
|
|
86
|
-
doTest('Random + short line', [rand, 3]);
|
|
87
|
-
doTest('Random + offset', [rand, 128, 1]);
|
|
88
|
-
doTest('Random + offset (end)', [rand, 128, 127]);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
console.log('All tests passed');
|