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/index.js
CHANGED
|
@@ -2,24 +2,190 @@
|
|
|
2
2
|
|
|
3
3
|
var y = require('./build/Release/yencode.node');
|
|
4
4
|
|
|
5
|
-
var
|
|
5
|
+
var toBuffer = Buffer.alloc ? Buffer.from : Buffer;
|
|
6
|
+
|
|
7
|
+
var nl = toBuffer([13, 10]);
|
|
6
8
|
var RE_BADCHAR = /\r\n\0/g;
|
|
9
|
+
var RE_YPROP = /([a-z_][a-z_0-9]*)=/;
|
|
10
|
+
var RE_NUMBER = /^\d+$/;
|
|
11
|
+
var decodePrev = ['\r\n', '=', '\r', '', '\r\n.', '\r\n.\r', '\r\n='];
|
|
12
|
+
|
|
13
|
+
var DecoderError = function(code, message) {
|
|
14
|
+
var err = new Error(message);
|
|
15
|
+
err.code = code;
|
|
16
|
+
return err;
|
|
17
|
+
}
|
|
18
|
+
var DecoderWarning = function(code, message) {
|
|
19
|
+
if(!this) return new DecoderWarning(code, message);
|
|
20
|
+
this.code = code;
|
|
21
|
+
this.message = message;
|
|
22
|
+
}
|
|
23
|
+
DecoderWarning.prototype = { toString: function() { return this.message; } };
|
|
24
|
+
|
|
25
|
+
var bufferFind, bufferFindRev;
|
|
26
|
+
if(Buffer.prototype.indexOf)
|
|
27
|
+
bufferFind = function(buf, search, start) {
|
|
28
|
+
return buf.indexOf(search, start, module.exports.encoding);
|
|
29
|
+
};
|
|
30
|
+
else
|
|
31
|
+
bufferFind = function(buf, search, start) {
|
|
32
|
+
if(!Buffer.isBuffer(search))
|
|
33
|
+
search = toBuffer(search, module.exports.encoding);
|
|
34
|
+
if(search.length == 0) return -1;
|
|
35
|
+
start = start|0;
|
|
36
|
+
if(search.length > buf.length-start) return -1;
|
|
37
|
+
|
|
38
|
+
for(var i = start; i < buf.length - search.length + 1; i++) {
|
|
39
|
+
var match = true;
|
|
40
|
+
for(var j = 0; j < search.length; j++) {
|
|
41
|
+
if(buf[i+j] != search[j]) {
|
|
42
|
+
match = false;
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if(match) return i;
|
|
47
|
+
}
|
|
48
|
+
return -1;
|
|
49
|
+
};
|
|
50
|
+
if(Buffer.prototype.lastIndexOf)
|
|
51
|
+
bufferFindRev = function(buf, search) {
|
|
52
|
+
return buf.lastIndexOf(search, -1, module.exports.encoding);
|
|
53
|
+
};
|
|
54
|
+
else
|
|
55
|
+
bufferFindRev = function(buf, search) {
|
|
56
|
+
if(!Buffer.isBuffer(search))
|
|
57
|
+
search = toBuffer(search, module.exports.encoding);
|
|
58
|
+
if(search.length == 0) return -1;
|
|
59
|
+
if(search.length > buf.length) return -1;
|
|
60
|
+
|
|
61
|
+
for(var i = buf.length-search.length; i >= 0; i--) {
|
|
62
|
+
var match = true;
|
|
63
|
+
for(var j = 0; j < search.length; j++) {
|
|
64
|
+
if(buf[i+j] != search[j]) {
|
|
65
|
+
match = false;
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if(match) return i;
|
|
70
|
+
}
|
|
71
|
+
return -1;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
var decoderParseLines = function(lines, ydata) {
|
|
75
|
+
var warnings = [];
|
|
76
|
+
for(var i=0; i<lines.length; i++) {
|
|
77
|
+
var yprops = {};
|
|
78
|
+
|
|
79
|
+
var line = lines[i].substr(2); // cut off '=y'
|
|
80
|
+
// parse tag
|
|
81
|
+
var p = line.indexOf(' ');
|
|
82
|
+
var tag = (p<0 ? line : line.substr(0, p));
|
|
83
|
+
line = line.substr(tag.length+1).trim();
|
|
84
|
+
|
|
85
|
+
// parse props
|
|
86
|
+
var m = line.match(RE_YPROP);
|
|
87
|
+
while(m) {
|
|
88
|
+
if(m.index != 0) {
|
|
89
|
+
warnings.push(DecoderWarning('ignored_line_data', 'Unknown additional data ignored: "' + line.substr(0, m.index) + '"'));
|
|
90
|
+
}
|
|
91
|
+
var prop = m[1], val;
|
|
92
|
+
var valPos = m.index + m[0].length;
|
|
93
|
+
if(tag == 'begin' && prop == 'name') {
|
|
94
|
+
// special treatment of filename - the value is the rest of the line (can include spaces)
|
|
95
|
+
val = line.substr(valPos);
|
|
96
|
+
line = '';
|
|
97
|
+
} else {
|
|
98
|
+
p = line.indexOf(' ', valPos);
|
|
99
|
+
val = (p<0 ? line.substr(valPos) : line.substr(valPos, p-valPos));
|
|
100
|
+
line = line.substr(valPos + val.length +1);
|
|
101
|
+
}
|
|
102
|
+
if(prop in yprops) {
|
|
103
|
+
warnings.push(DecoderWarning('duplicate_property', 'Duplicate property encountered: `' + prop + '`'));
|
|
104
|
+
}
|
|
105
|
+
yprops[prop] = val;
|
|
106
|
+
m = line.match(RE_YPROP);
|
|
107
|
+
}
|
|
108
|
+
if(line != '') {
|
|
109
|
+
warnings.push(DecoderWarning('ignored_line_data', 'Unknown additional end-of-line data ignored: "' + line + '"'));
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if(tag in ydata) {
|
|
113
|
+
warnings.push(DecoderWarning('duplicate_line', 'Duplicate line encountered: `' + tag + '`'));
|
|
114
|
+
}
|
|
115
|
+
ydata[tag] = yprops;
|
|
116
|
+
}
|
|
117
|
+
return warnings;
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
var propIsNotValidNumber = function(prop) {
|
|
121
|
+
return prop && !RE_NUMBER.test(prop);
|
|
122
|
+
};
|
|
7
123
|
|
|
8
124
|
module.exports = {
|
|
9
125
|
encoding: 'utf8',
|
|
10
126
|
|
|
11
127
|
encode: y.encode,
|
|
12
128
|
encodeTo: y.encodeTo,
|
|
13
|
-
|
|
129
|
+
decode: y.decode,
|
|
130
|
+
decodeTo: y.decodeTo,
|
|
131
|
+
|
|
132
|
+
decodeChunk: function(data, output, prev) {
|
|
133
|
+
// both output and prev are optional
|
|
134
|
+
if(typeof output !== 'undefined' && !Buffer.isBuffer(output)) {
|
|
135
|
+
prev = output;
|
|
136
|
+
output = null;
|
|
137
|
+
}
|
|
138
|
+
if(prev === null || typeof prev === 'undefined')
|
|
139
|
+
prev = '\r\n';
|
|
140
|
+
|
|
141
|
+
if(Buffer.isBuffer(prev)) prev = prev.toString();
|
|
142
|
+
prev = prev.substr(-4); // only care about the last 4 chars of previous state
|
|
143
|
+
if(prev == '\r\n.=') prev = '\r\n='; // aliased after dot stripped
|
|
144
|
+
if(data.length == 0) return {
|
|
145
|
+
read: 0,
|
|
146
|
+
written: 0,
|
|
147
|
+
output: toBuffer([]),
|
|
148
|
+
ended: 0,
|
|
149
|
+
state: prev
|
|
150
|
+
};
|
|
151
|
+
var state = decodePrev.indexOf(prev);
|
|
152
|
+
if(state < 0) {
|
|
153
|
+
for(var l=-3; l<0; i++) {
|
|
154
|
+
state = decodePrev.indexOf(prev.substr(l));
|
|
155
|
+
if(state >= 0) break;
|
|
156
|
+
}
|
|
157
|
+
if(state < 0) state = decodePrev.indexOf('');
|
|
158
|
+
}
|
|
159
|
+
var ret = y.decodeIncr(data, state, output);
|
|
160
|
+
|
|
161
|
+
return {
|
|
162
|
+
read: ret.read,
|
|
163
|
+
written: ret.written,
|
|
164
|
+
output: ret.output || output,
|
|
165
|
+
ended: !!ret.ended,
|
|
166
|
+
state: [decodePrev[ret.state], '\r\n=y', '\r\n.\r\n'][ret.ended]
|
|
167
|
+
};
|
|
168
|
+
},
|
|
169
|
+
|
|
170
|
+
minSize: function(length, line_size) {
|
|
14
171
|
if(!length) return 0;
|
|
15
|
-
return
|
|
16
|
-
|
|
17
|
-
|
|
172
|
+
return length // no characters escaped
|
|
173
|
+
+ 2 * Math.floor(length / (line_size||128)); // newlines
|
|
174
|
+
},
|
|
175
|
+
maxSize: function(length, line_size, esc_ratio) {
|
|
176
|
+
if(!length) return 0;
|
|
177
|
+
if(!esc_ratio && esc_ratio !== 0)
|
|
178
|
+
esc_ratio = 2;
|
|
179
|
+
else
|
|
180
|
+
esc_ratio++;
|
|
181
|
+
if(esc_ratio < 1 || esc_ratio > 2)
|
|
182
|
+
throw new Error('yEnc escape ratio must be between 0 and 1');
|
|
183
|
+
return Math.ceil(length*esc_ratio) // all characters escaped
|
|
184
|
+
+ 2 * Math.floor((length*esc_ratio) / (line_size||128)) // newlines, considering the possibility of all chars escaped
|
|
18
185
|
+ 2 // allocation for offset and that a newline may occur early
|
|
19
|
-
+
|
|
20
|
-
|
|
186
|
+
+ 64 // extra space just in case things go awry... just kidding, it's just extra padding to make SIMD logic easier
|
|
187
|
+
;
|
|
21
188
|
},
|
|
22
|
-
// TODO: check ordering of CRC32
|
|
23
189
|
crc32: y.crc32,
|
|
24
190
|
crc32_combine: y.crc32_combine,
|
|
25
191
|
crc32_zeroes: y.crc32_zeroes,
|
|
@@ -27,18 +193,159 @@ module.exports = {
|
|
|
27
193
|
post: function(filename, data, line_size) {
|
|
28
194
|
if(!line_size) line_size = 128;
|
|
29
195
|
|
|
30
|
-
if(!Buffer.isBuffer(data)) data =
|
|
196
|
+
if(!Buffer.isBuffer(data)) data = toBuffer(data);
|
|
31
197
|
|
|
32
|
-
filename =
|
|
198
|
+
filename = toBuffer(filename.replace(RE_BADCHAR, '').substr(0, 256), exports.encoding);
|
|
33
199
|
return Buffer.concat([
|
|
34
|
-
|
|
200
|
+
toBuffer('=ybegin line='+line_size+' size='+data.length+' name='),
|
|
35
201
|
filename, nl,
|
|
36
202
|
y.encode(data, line_size),
|
|
37
|
-
|
|
203
|
+
toBuffer('\r\n=yend size='+data.length+' crc32=' + y.crc32(data).toString('hex'))
|
|
38
204
|
]);
|
|
39
205
|
},
|
|
40
206
|
multi_post: function(filename, size, parts, line_size) {
|
|
41
207
|
return new YEncoder(filename, size, parts, line_size);
|
|
208
|
+
},
|
|
209
|
+
from_post: function(data, isRaw) {
|
|
210
|
+
if(!Buffer.isBuffer(data))
|
|
211
|
+
throw new TypeError('Expected string or Buffer');
|
|
212
|
+
|
|
213
|
+
var ret = {};
|
|
214
|
+
|
|
215
|
+
// find '=ybegin' to know where the yEnc data starts
|
|
216
|
+
var yencStart;
|
|
217
|
+
if(data.slice(0, 8).toString('hex') == '3d79626567696e20' /*=ybegin */) {
|
|
218
|
+
// common case: starts right at the beginning
|
|
219
|
+
yencStart = 0;
|
|
220
|
+
} else {
|
|
221
|
+
// otherwise, we have to search for the beginning marker
|
|
222
|
+
yencStart = bufferFind(data, '\r\n=ybegin ');
|
|
223
|
+
if(yencStart < 0)
|
|
224
|
+
return DecoderError('no_start_found', 'yEnc start marker not found');
|
|
225
|
+
yencStart += 2;
|
|
226
|
+
}
|
|
227
|
+
ret.yencStart = yencStart;
|
|
228
|
+
|
|
229
|
+
// find all start lines
|
|
230
|
+
var lines = [];
|
|
231
|
+
var sp = yencStart;
|
|
232
|
+
var p = bufferFind(data, '\r\n', yencStart+8);
|
|
233
|
+
while(p > 0) {
|
|
234
|
+
var line = data.slice(sp, p).toString(this.encoding).trim();
|
|
235
|
+
lines.push(line);
|
|
236
|
+
sp = p+2;
|
|
237
|
+
if(line.substr(0, 6) == '=yend ') { // no data in post
|
|
238
|
+
ret.yencEnd = sp;
|
|
239
|
+
break;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
if(data[sp] != 0x3d /*=*/ || data[sp+1] != 0x79 /*y*/) {
|
|
243
|
+
ret.dataStart = sp;
|
|
244
|
+
break;
|
|
245
|
+
}
|
|
246
|
+
p = bufferFind(data, '\r\n', sp);
|
|
247
|
+
}
|
|
248
|
+
if(!ret.dataStart && !ret.yencEnd) // reached end of data but '=yend' not found
|
|
249
|
+
return DecoderError('no_end_found', 'yEnd end marker not found');
|
|
250
|
+
|
|
251
|
+
var ydata = {};
|
|
252
|
+
var warnings = decoderParseLines(lines, ydata);
|
|
253
|
+
|
|
254
|
+
if(!ret.yencEnd) {
|
|
255
|
+
var yencEnd = bufferFindRev(data.slice(ret.dataStart), '\r\n=yend ');
|
|
256
|
+
if(yencEnd < 0)
|
|
257
|
+
return DecoderError('no_end_found', 'yEnd end marker not found');
|
|
258
|
+
|
|
259
|
+
yencEnd += ret.dataStart;
|
|
260
|
+
ret.dataEnd = yencEnd;
|
|
261
|
+
p = bufferFind(data, '\r\n', yencEnd+8);
|
|
262
|
+
if(p < 0) {
|
|
263
|
+
warnings.push(DecoderWarning('missing_yend_newline', 'No line terminator found for =yend line'));
|
|
264
|
+
p = data.length;
|
|
265
|
+
ret.yencEnd = p;
|
|
266
|
+
} else
|
|
267
|
+
ret.yencEnd = p+2;
|
|
268
|
+
var endLine = data.slice(yencEnd+2, p).toString(this.encoding).trim();
|
|
269
|
+
|
|
270
|
+
warnings = warnings.concat(decoderParseLines([endLine], ydata));
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
ret.props = ydata;
|
|
274
|
+
// check properties
|
|
275
|
+
if(!ydata.begin.line || !ydata.begin.size || !('name' in ydata.begin)) // required properties, according to yEnc 1.2 spec
|
|
276
|
+
return DecoderError('missing_required_properties', 'Could not find line/size/name properties on ybegin line');
|
|
277
|
+
if(!ydata.end.size)
|
|
278
|
+
return DecoderError('missing_required_properties', 'Could not find size properties on yend line');
|
|
279
|
+
|
|
280
|
+
// check numerical fields
|
|
281
|
+
var NUMERICAL_FIELDS = {
|
|
282
|
+
begin: ['line', 'total', 'part', 'size'],
|
|
283
|
+
part: ['begin', 'end'],
|
|
284
|
+
end: ['size', 'part']
|
|
285
|
+
};
|
|
286
|
+
for(var tag in NUMERICAL_FIELDS) {
|
|
287
|
+
if(!ydata[tag]) continue;
|
|
288
|
+
NUMERICAL_FIELDS[tag].forEach(function(key) {
|
|
289
|
+
if(!ydata[tag][key]) return;
|
|
290
|
+
if(!RE_NUMBER.test(ydata[tag][key]))
|
|
291
|
+
warnings.push(DecoderWarning('invalid_prop_'+key, '`'+key+'` is not a number'));
|
|
292
|
+
else if(ydata[tag][key] === '0' && key != 'size') // most fields have to be at least one
|
|
293
|
+
warnings.push(DecoderWarning('zero_prop_'+key, '`'+key+'` cannot be 0'));
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
if(ydata.begin.part && ydata.end.part && ydata.begin.part != ydata.end.part)
|
|
297
|
+
warnings.push(DecoderWarning('part_number_mismatch', 'Part number specified in begin and end do not match'));
|
|
298
|
+
else if(ydata.begin.total && ((ydata.begin.part && +ydata.begin.total < +ydata.begin.part) || (ydata.end.part && +ydata.begin.total < +ydata.end.part)))
|
|
299
|
+
warnings.push(DecoderWarning('part_number_exceeds_total', 'Specified part number exceeds specified total'));
|
|
300
|
+
|
|
301
|
+
var expectedSize = +ydata.end.size;
|
|
302
|
+
if(ydata.part && ydata.part.begin && ydata.part.end) {
|
|
303
|
+
var partBegin = +ydata.part.begin;
|
|
304
|
+
var partEnd = +ydata.part.end;
|
|
305
|
+
if(partBegin > partEnd)
|
|
306
|
+
warnings.push(DecoderWarning('invalid_part_range', 'begin offset cannot exceed end offset'));
|
|
307
|
+
else if(expectedSize != partEnd-partBegin +1)
|
|
308
|
+
warnings.push(DecoderWarning('size_mismatch_part_range', 'Specified size does not match part range'));
|
|
309
|
+
else if(partEnd > +ydata.begin.size)
|
|
310
|
+
warnings.push(DecoderWarning('part_range_exceeds_size', 'Specified part range exceeds total file size'));
|
|
311
|
+
} else if(+ydata.begin.total > 1 || +ydata.begin.part > 1 || +ydata.end.part > 1)
|
|
312
|
+
warnings.push(DecoderWarning('missing_part_range', 'Part range not specified for multi-part post'));
|
|
313
|
+
|
|
314
|
+
['pcrc32','crc32'].forEach(function(prop) {
|
|
315
|
+
if(ydata.end[prop] && !/^[a-fA-F0-9]{8}$/.test(ydata.end[prop]))
|
|
316
|
+
warnings.push(DecoderWarning('invalid_prop_'+prop, '`'+prop+'` is not a valid CRC32 value'));
|
|
317
|
+
});
|
|
318
|
+
if(!ydata.begin.part && ydata.begin.size != ydata.end.size)
|
|
319
|
+
warnings.push(DecoderWarning('size_mismatch', 'Size specified in begin and end do not match'));
|
|
320
|
+
else if(+ydata.begin.size < +ydata.end.size)
|
|
321
|
+
warnings.push(DecoderWarning('size_mismatch', 'Size specified for part exceeds size specified for whole file'));
|
|
322
|
+
|
|
323
|
+
if(ret.dataStart) {
|
|
324
|
+
ret.data = y.decode(data.slice(ret.dataStart, ret.dataEnd), isRaw);
|
|
325
|
+
ret.crc32 = y.crc32(ret.data);
|
|
326
|
+
var hexCrc = ret.crc32.toString('hex');
|
|
327
|
+
|
|
328
|
+
if(expectedSize != ret.data.length)
|
|
329
|
+
warnings.push(DecoderWarning('data_size_mismatch', 'Decoded data length doesn\'t match size specified in yend'));
|
|
330
|
+
if(ydata.end.pcrc32 && hexCrc != ydata.end.pcrc32.toLowerCase())
|
|
331
|
+
warnings.push(DecoderWarning('pcrc32_mismatch', 'Specified pcrc32 is invalid'));
|
|
332
|
+
if(ydata.end.crc32 && !ydata.part && hexCrc != ydata.end.crc32.toLowerCase())
|
|
333
|
+
// if single part, check CRC32 as well
|
|
334
|
+
warnings.push(DecoderWarning('crc32_mismatch', 'Specified crc32 is invalid'));
|
|
335
|
+
} else {
|
|
336
|
+
// empty article
|
|
337
|
+
if(expectedSize != 0)
|
|
338
|
+
warnings.push(DecoderWarning('data_size_mismatch', 'Decoded data length doesn\'t match size specified in yend'));
|
|
339
|
+
if(ydata.end.pcrc32 && ydata.end.pcrc32 != '00000000')
|
|
340
|
+
warnings.push(DecoderWarning('pcrc32_mismatch', 'Specified pcrc32 is invalid'));
|
|
341
|
+
if(ydata.end.crc32 && !ydata.part && ydata.end.crc32 != '00000000')
|
|
342
|
+
warnings.push(DecoderWarning('crc32_mismatch', 'Specified crc32 is invalid'));
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
if(warnings.length)
|
|
346
|
+
ret.warnings = warnings;
|
|
347
|
+
|
|
348
|
+
return ret;
|
|
42
349
|
}
|
|
43
350
|
};
|
|
44
351
|
|
|
@@ -51,17 +358,17 @@ function YEncoder(filename, size, parts, line_size) {
|
|
|
51
358
|
|
|
52
359
|
this.part = 0;
|
|
53
360
|
this.pos = 0;
|
|
54
|
-
this.crc =
|
|
361
|
+
this.crc = toBuffer([0,0,0,0]);
|
|
55
362
|
|
|
56
|
-
filename =
|
|
363
|
+
filename = toBuffer(filename.replace(RE_BADCHAR, '').substr(0, 256), exports.encoding);
|
|
57
364
|
if(parts > 1) {
|
|
58
365
|
this.yInfo = Buffer.concat([
|
|
59
|
-
|
|
366
|
+
toBuffer(' total='+parts+' line='+line_size+' size='+size+' name='),
|
|
60
367
|
filename, nl
|
|
61
368
|
]);
|
|
62
369
|
} else {
|
|
63
370
|
this.yInfo = Buffer.concat([
|
|
64
|
-
|
|
371
|
+
toBuffer('=ybegin line='+line_size+' size='+size+' name='),
|
|
65
372
|
filename, nl
|
|
66
373
|
]);
|
|
67
374
|
this.encode = this._encodeSingle;
|
|
@@ -72,7 +379,7 @@ var singleEncodeError = function() {
|
|
|
72
379
|
};
|
|
73
380
|
YEncoder.prototype = {
|
|
74
381
|
encode: function(data) {
|
|
75
|
-
if(!Buffer.isBuffer(data)) data =
|
|
382
|
+
if(!Buffer.isBuffer(data)) data = toBuffer(data);
|
|
76
383
|
|
|
77
384
|
this.part++;
|
|
78
385
|
if(this.part > this.parts)
|
|
@@ -93,11 +400,11 @@ YEncoder.prototype = {
|
|
|
93
400
|
}
|
|
94
401
|
|
|
95
402
|
var ret = Buffer.concat([
|
|
96
|
-
|
|
403
|
+
toBuffer('=ybegin part='+this.part),
|
|
97
404
|
yInfo,
|
|
98
|
-
|
|
405
|
+
toBuffer('=ypart begin='+( this.pos+1 )+' end='+end+'\r\n'),
|
|
99
406
|
y.encode(data, this.line_size),
|
|
100
|
-
|
|
407
|
+
toBuffer('\r\n=yend size='+data.length+' part='+this.part+' pcrc32='+crc.toString('hex')+fullCrc)
|
|
101
408
|
]);
|
|
102
409
|
|
|
103
410
|
this.pos = end;
|
|
@@ -105,7 +412,7 @@ YEncoder.prototype = {
|
|
|
105
412
|
},
|
|
106
413
|
|
|
107
414
|
_encodeSingle: function(data) {
|
|
108
|
-
if(!Buffer.isBuffer(data)) data =
|
|
415
|
+
if(!Buffer.isBuffer(data)) data = toBuffer(data);
|
|
109
416
|
|
|
110
417
|
if(this.size != data.length)
|
|
111
418
|
throw new Error('File size doesn\'t match total data length');
|
|
@@ -120,7 +427,7 @@ YEncoder.prototype = {
|
|
|
120
427
|
return Buffer.concat([
|
|
121
428
|
yInfo,
|
|
122
429
|
y.encode(data, this.line_size),
|
|
123
|
-
|
|
430
|
+
toBuffer('\r\n=yend size='+data.length+' crc32=' + this.crc.toString('hex'))
|
|
124
431
|
]);
|
|
125
432
|
}
|
|
126
433
|
};
|
package/package.json
CHANGED