1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 | function pack(format) {
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 | var formatPointer = 0,
|
38 | argumentPointer = 1,
|
39 | result = '',
|
40 | argument = '',
|
41 | i = 0,
|
42 | r = [],
|
43 | instruction, quantifier, word, precisionBits, exponentBits, extraNullCount;
|
44 |
|
45 |
|
46 | var bias, minExp, maxExp, minUnnormExp, status, exp, len, bin, signal, n, intPart, floatPart, lastBit, rounded, j,
|
47 | k, tmpResult;
|
48 |
|
49 | while (formatPointer < format.length) {
|
50 | instruction = format.charAt(formatPointer);
|
51 | quantifier = '';
|
52 | formatPointer++;
|
53 | while ((formatPointer < format.length) && (format.charAt(formatPointer)
|
54 | .match(/[\d\*]/) !== null)) {
|
55 | quantifier += format.charAt(formatPointer);
|
56 | formatPointer++;
|
57 | }
|
58 | if (quantifier === '') {
|
59 | quantifier = '1';
|
60 | }
|
61 |
|
62 |
|
63 | switch (instruction) {
|
64 | case 'a':
|
65 |
|
66 | case 'A':
|
67 |
|
68 | if (typeof arguments[argumentPointer] === 'undefined') {
|
69 | throw new Error('Warning: pack() Type ' + instruction + ': not enough arguments');
|
70 | } else {
|
71 | argument = String(arguments[argumentPointer]);
|
72 | }
|
73 | if (quantifier === '*') {
|
74 | quantifier = argument.length;
|
75 | }
|
76 | for (i = 0; i < quantifier; i++) {
|
77 | if (typeof argument[i] === 'undefined') {
|
78 | if (instruction === 'a') {
|
79 | result += String.fromCharCode(0);
|
80 | } else {
|
81 | result += ' ';
|
82 | }
|
83 | } else {
|
84 | result += argument[i];
|
85 | }
|
86 | }
|
87 | argumentPointer++;
|
88 | break;
|
89 | case 'h':
|
90 |
|
91 | case 'H':
|
92 |
|
93 | if (typeof arguments[argumentPointer] === 'undefined') {
|
94 | throw new Error('Warning: pack() Type ' + instruction + ': not enough arguments');
|
95 | } else {
|
96 | argument = arguments[argumentPointer];
|
97 | }
|
98 | if (quantifier === '*') {
|
99 | quantifier = argument.length;
|
100 | }
|
101 | if (quantifier > argument.length) {
|
102 | throw new Error('Warning: pack() Type ' + instruction + ': not enough characters in string');
|
103 | }
|
104 | for (i = 0; i < quantifier; i += 2) {
|
105 |
|
106 | word = argument[i];
|
107 | if (((i + 1) >= quantifier) || typeof argument[i + 1] === 'undefined') {
|
108 | word += '0';
|
109 | } else {
|
110 | word += argument[i + 1];
|
111 | }
|
112 |
|
113 | if (instruction === 'h') {
|
114 | word = word[1] + word[0];
|
115 | }
|
116 | result += String.fromCharCode(parseInt(word, 16));
|
117 | }
|
118 | argumentPointer++;
|
119 | break;
|
120 |
|
121 | case 'c':
|
122 |
|
123 | case 'C':
|
124 |
|
125 |
|
126 | if (quantifier === '*') {
|
127 | quantifier = arguments.length - argumentPointer;
|
128 | }
|
129 | if (quantifier > (arguments.length - argumentPointer)) {
|
130 | throw new Error('Warning: pack() Type ' + instruction + ': too few arguments');
|
131 | }
|
132 |
|
133 | for (i = 0; i < quantifier; i++) {
|
134 | result += String.fromCharCode(arguments[argumentPointer]);
|
135 | argumentPointer++;
|
136 | }
|
137 | break;
|
138 |
|
139 | case 's':
|
140 |
|
141 | case 'S':
|
142 |
|
143 | case 'v':
|
144 |
|
145 | if (quantifier === '*') {
|
146 | quantifier = arguments.length - argumentPointer;
|
147 | }
|
148 | if (quantifier > (arguments.length - argumentPointer)) {
|
149 | throw new Error('Warning: pack() Type ' + instruction + ': too few arguments');
|
150 | }
|
151 |
|
152 | for (i = 0; i < quantifier; i++) {
|
153 | result += String.fromCharCode(arguments[argumentPointer] & 0xFF);
|
154 | result += String.fromCharCode(arguments[argumentPointer] >> 8 & 0xFF);
|
155 | argumentPointer++;
|
156 | }
|
157 | break;
|
158 |
|
159 | case 'n':
|
160 |
|
161 | if (quantifier === '*') {
|
162 | quantifier = arguments.length - argumentPointer;
|
163 | }
|
164 | if (quantifier > (arguments.length - argumentPointer)) {
|
165 | throw new Error('Warning: pack() Type ' + instruction + ': too few arguments');
|
166 | }
|
167 |
|
168 | for (i = 0; i < quantifier; i++) {
|
169 | result += String.fromCharCode(arguments[argumentPointer] >> 8 & 0xFF);
|
170 | result += String.fromCharCode(arguments[argumentPointer] & 0xFF);
|
171 | argumentPointer++;
|
172 | }
|
173 | break;
|
174 |
|
175 | case 'i':
|
176 |
|
177 | case 'I':
|
178 |
|
179 | case 'l':
|
180 |
|
181 | case 'L':
|
182 |
|
183 | case 'V':
|
184 |
|
185 | if (quantifier === '*') {
|
186 | quantifier = arguments.length - argumentPointer;
|
187 | }
|
188 | if (quantifier > (arguments.length - argumentPointer)) {
|
189 | throw new Error('Warning: pack() Type ' + instruction + ': too few arguments');
|
190 | }
|
191 |
|
192 | for (i = 0; i < quantifier; i++) {
|
193 | result += String.fromCharCode(arguments[argumentPointer] & 0xFF);
|
194 | result += String.fromCharCode(arguments[argumentPointer] >> 8 & 0xFF);
|
195 | result += String.fromCharCode(arguments[argumentPointer] >> 16 & 0xFF);
|
196 | result += String.fromCharCode(arguments[argumentPointer] >> 24 & 0xFF);
|
197 | argumentPointer++;
|
198 | }
|
199 |
|
200 | break;
|
201 | case 'N':
|
202 |
|
203 | if (quantifier === '*') {
|
204 | quantifier = arguments.length - argumentPointer;
|
205 | }
|
206 | if (quantifier > (arguments.length - argumentPointer)) {
|
207 | throw new Error('Warning: pack() Type ' + instruction + ': too few arguments');
|
208 | }
|
209 |
|
210 | for (i = 0; i < quantifier; i++) {
|
211 | result += String.fromCharCode(arguments[argumentPointer] >> 24 & 0xFF);
|
212 | result += String.fromCharCode(arguments[argumentPointer] >> 16 & 0xFF);
|
213 | result += String.fromCharCode(arguments[argumentPointer] >> 8 & 0xFF);
|
214 | result += String.fromCharCode(arguments[argumentPointer] & 0xFF);
|
215 | argumentPointer++;
|
216 | }
|
217 | break;
|
218 |
|
219 | case 'f':
|
220 |
|
221 | case 'd':
|
222 |
|
223 |
|
224 | precisionBits = 23;
|
225 | exponentBits = 8;
|
226 | if (instruction === 'd') {
|
227 | precisionBits = 52;
|
228 | exponentBits = 11;
|
229 | }
|
230 |
|
231 | if (quantifier === '*') {
|
232 | quantifier = arguments.length - argumentPointer;
|
233 | }
|
234 | if (quantifier > (arguments.length - argumentPointer)) {
|
235 | throw new Error('Warning: pack() Type ' + instruction + ': too few arguments');
|
236 | }
|
237 | for (i = 0; i < quantifier; i++) {
|
238 | argument = arguments[argumentPointer];
|
239 | bias = Math.pow(2, exponentBits - 1) - 1;
|
240 | minExp = -bias + 1;
|
241 | maxExp = bias;
|
242 | minUnnormExp = minExp - precisionBits;
|
243 | status = isNaN(n = parseFloat(argument)) || n === -Infinity || n === +Infinity ? n : 0;
|
244 | exp = 0;
|
245 | len = 2 * bias + 1 + precisionBits + 3;
|
246 | bin = new Array(len);
|
247 | signal = (n = status !== 0 ? 0 : n) < 0;
|
248 | n = Math.abs(n);
|
249 | intPart = Math.floor(n);
|
250 | floatPart = n - intPart;
|
251 |
|
252 | for (k = len; k;) {
|
253 | bin[--k] = 0;
|
254 | }
|
255 | for (k = bias + 2; intPart && k;) {
|
256 | bin[--k] = intPart % 2;
|
257 | intPart = Math.floor(intPart / 2);
|
258 | }
|
259 | for (k = bias + 1; floatPart > 0 && k; --floatPart) {
|
260 | (bin[++k] = ((floatPart *= 2) >= 1) - 0);
|
261 | }
|
262 | for (k = -1; ++k < len && !bin[k];) {}
|
263 |
|
264 | if (bin[(lastBit = precisionBits - 1 + (k = (exp = bias + 1 - k) >= minExp && exp <= maxExp ? k + 1 :
|
265 | bias + 1 - (exp = minExp - 1))) + 1]) {
|
266 | if (!(rounded = bin[lastBit])) {
|
267 | for (j = lastBit + 2; !rounded && j < len; rounded = bin[j++]) {}
|
268 | }
|
269 | for (j = lastBit + 1; rounded && --j >= 0;
|
270 | (bin[j] = !bin[j] - 0) && (rounded = 0)) {}
|
271 | }
|
272 |
|
273 | for (k = k - 2 < 0 ? -1 : k - 3; ++k < len && !bin[k];) {}
|
274 |
|
275 | if ((exp = bias + 1 - k) >= minExp && exp <= maxExp) {
|
276 | ++k;
|
277 | } else {
|
278 | if (exp < minExp) {
|
279 | if (exp !== bias + 1 - len && exp < minUnnormExp) { }
|
280 | k = bias + 1 - (exp = minExp - 1);
|
281 | }
|
282 | }
|
283 |
|
284 | if (intPart || status !== 0) {
|
285 | exp = maxExp + 1;
|
286 | k = bias + 2;
|
287 | if (status === -Infinity) {
|
288 | signal = 1;
|
289 | } else if (isNaN(status)) {
|
290 | bin[k] = 1;
|
291 | }
|
292 | }
|
293 |
|
294 | n = Math.abs(exp + bias);
|
295 | tmpResult = '';
|
296 |
|
297 | for (j = exponentBits + 1; --j;) {
|
298 | tmpResult = (n % 2) + tmpResult;
|
299 | n = n >>= 1;
|
300 | }
|
301 |
|
302 | n = 0;
|
303 | j = 0;
|
304 | k = (tmpResult = (signal ? '1' : '0') + tmpResult + bin.slice(k, k + precisionBits)
|
305 | .join(''))
|
306 | .length;
|
307 | r = [];
|
308 |
|
309 | for (; k;) {
|
310 | n += (1 << j) * tmpResult.charAt(--k);
|
311 | if (j === 7) {
|
312 | r[r.length] = String.fromCharCode(n);
|
313 | n = 0;
|
314 | }
|
315 | j = (j + 1) % 8;
|
316 | }
|
317 |
|
318 | r[r.length] = n ? String.fromCharCode(n) : '';
|
319 | result += r.join('');
|
320 | argumentPointer++;
|
321 | }
|
322 | break;
|
323 |
|
324 | case 'x':
|
325 |
|
326 | if (quantifier === '*') {
|
327 | throw new Error('Warning: pack(): Type x: \'*\' ignored');
|
328 | }
|
329 | for (i = 0; i < quantifier; i++) {
|
330 | result += String.fromCharCode(0);
|
331 | }
|
332 | break;
|
333 |
|
334 | case 'X':
|
335 |
|
336 | if (quantifier === '*') {
|
337 | throw new Error('Warning: pack(): Type X: \'*\' ignored');
|
338 | }
|
339 | for (i = 0; i < quantifier; i++) {
|
340 | if (result.length === 0) {
|
341 | throw new Error('Warning: pack(): Type X:' + ' outside of string');
|
342 | } else {
|
343 | result = result.substring(0, result.length - 1);
|
344 | }
|
345 | }
|
346 | break;
|
347 |
|
348 | case '@':
|
349 |
|
350 | if (quantifier === '*') {
|
351 | throw new Error('Warning: pack(): Type X: \'*\' ignored');
|
352 | }
|
353 | if (quantifier > result.length) {
|
354 | extraNullCount = quantifier - result.length;
|
355 | for (i = 0; i < extraNullCount; i++) {
|
356 | result += String.fromCharCode(0);
|
357 | }
|
358 | }
|
359 | if (quantifier < result.length) {
|
360 | result = result.substring(0, quantifier);
|
361 | }
|
362 | break;
|
363 |
|
364 | default:
|
365 | throw new Error('Warning: pack() Type ' + instruction + ': unknown format code');
|
366 | }
|
367 | }
|
368 | if (argumentPointer < arguments.length) {
|
369 | throw new Error('Warning: pack(): ' + (arguments.length - argumentPointer) + ' arguments unused');
|
370 | }
|
371 |
|
372 | return result;
|
373 | }
|
374 |
|
375 | function unpack(format, data) {
|
376 |
|
377 |
|
378 |
|
379 |
|
380 |
|
381 |
|
382 |
|
383 |
|
384 |
|
385 |
|
386 |
|
387 |
|
388 |
|
389 |
|
390 |
|
391 | var formatPointer = 0, dataPointer = 0, result = {}, instruction = '',
|
392 | quantifier = '', label = '', currentData = '', i = 0, j = 0,
|
393 | word = '', fbits = 0, ebits = 0, dataByteLength = 0;
|
394 |
|
395 |
|
396 |
|
397 | var fromIEEE754 = function(bytes, ebits, fbits) {
|
398 |
|
399 | var bits = [];
|
400 | for (var i = bytes.length; i; i -= 1) {
|
401 | var byte = bytes[i - 1];
|
402 | for (var j = 8; j; j -= 1) {
|
403 | bits.push(byte % 2 ? 1 : 0); byte = byte >> 1;
|
404 | }
|
405 | }
|
406 | bits.reverse();
|
407 | var str = bits.join('');
|
408 |
|
409 |
|
410 | var bias = (1 << (ebits - 1)) - 1;
|
411 | var s = parseInt(str.substring(0, 1), 2) ? -1 : 1;
|
412 | var e = parseInt(str.substring(1, 1 + ebits), 2);
|
413 | var f = parseInt(str.substring(1 + ebits), 2);
|
414 |
|
415 |
|
416 | if (e === (1 << ebits) - 1) {
|
417 | return f !== 0 ? NaN : s * Infinity;
|
418 | }
|
419 | else if (e > 0) {
|
420 | return s * Math.pow(2, e - bias) * (1 + f / Math.pow(2, fbits));
|
421 | }
|
422 | else if (f !== 0) {
|
423 | return s * Math.pow(2, -(bias-1)) * (f / Math.pow(2, fbits));
|
424 | }
|
425 | else {
|
426 | return s * 0;
|
427 | }
|
428 | }
|
429 |
|
430 | while (formatPointer < format.length) {
|
431 | instruction = format.charAt(formatPointer);
|
432 |
|
433 |
|
434 | quantifier = '';
|
435 | formatPointer++;
|
436 | while ((formatPointer < format.length) &&
|
437 | (format.charAt(formatPointer).match(/[\d\*]/) !== null)) {
|
438 | quantifier += format.charAt(formatPointer);
|
439 | formatPointer++;
|
440 | }
|
441 | if (quantifier === '') {
|
442 | quantifier = '1';
|
443 | }
|
444 |
|
445 |
|
446 |
|
447 | label = '';
|
448 | while ((formatPointer < format.length) &&
|
449 | (format.charAt(formatPointer) !== '/')) {
|
450 | label += format.charAt(formatPointer);
|
451 | formatPointer++;
|
452 | }
|
453 | if (format.charAt(formatPointer) === '/') {
|
454 | formatPointer++;
|
455 | }
|
456 |
|
457 |
|
458 | switch (instruction) {
|
459 | case 'a':
|
460 | case 'A':
|
461 | if (quantifier === '*') {
|
462 | quantifier = data.length - dataPointer;
|
463 | } else {
|
464 | quantifier = parseInt(quantifier, 10);
|
465 | }
|
466 | currentData = data.substr(dataPointer, quantifier);
|
467 | dataPointer += quantifier;
|
468 |
|
469 | if (instruction === 'a') {
|
470 | currentResult = currentData.replace(/\0+$/, '');
|
471 | } else {
|
472 | currentResult = currentData.replace(/ +$/, '');
|
473 | }
|
474 | result[label] = currentResult;
|
475 | break;
|
476 |
|
477 | case 'h':
|
478 | case 'H':
|
479 | if (quantifier === '*') {
|
480 | quantifier = data.length - dataPointer;
|
481 | } else {
|
482 | quantifier = parseInt(quantifier, 10);
|
483 | }
|
484 | currentData = data.substr(dataPointer, quantifier);
|
485 | dataPointer += quantifier;
|
486 |
|
487 | if (quantifier > currentData.length) {
|
488 | throw new Error('Warning: unpack(): Type ' + instruction +
|
489 | ': not enough input, need ' + quantifier);
|
490 | }
|
491 |
|
492 | currentResult = '';
|
493 | for (i = 0; i < currentData.length; i++) {
|
494 | word = currentData.charCodeAt(i).toString(16);
|
495 | if (instruction === 'h') {
|
496 | word = word[1] + word[0];
|
497 | }
|
498 | currentResult += word;
|
499 | }
|
500 | result[label] = currentResult;
|
501 | break;
|
502 |
|
503 | case 'c':
|
504 | case 'C':
|
505 | if (quantifier === '*') {
|
506 | quantifier = data.length - dataPointer;
|
507 | } else {
|
508 | quantifier = parseInt(quantifier, 10);
|
509 | }
|
510 |
|
511 | currentData = data.substr(dataPointer, quantifier);
|
512 | dataPointer += quantifier;
|
513 |
|
514 | for (i = 0; i < currentData.length; i++) {
|
515 | currentResult = currentData.charCodeAt(i);
|
516 | if ((instruction === 'c') && (currentResult >= 128)) {
|
517 | currentResult -= 256;
|
518 | }
|
519 | result[label + (quantifier > 1 ?
|
520 | (i + 1) :
|
521 | '')] = currentResult;
|
522 | }
|
523 | break;
|
524 |
|
525 | case 'S':
|
526 | case 's':
|
527 | case 'v':
|
528 | if (quantifier === '*') {
|
529 | quantifier = (data.length - dataPointer) / 2;
|
530 | } else {
|
531 | quantifier = parseInt(quantifier, 10);
|
532 | }
|
533 |
|
534 | currentData = data.substr(dataPointer, quantifier * 2);
|
535 | dataPointer += quantifier * 2;
|
536 |
|
537 | for (i = 0; i < currentData.length; i += 2) {
|
538 |
|
539 | currentResult = ((currentData.charCodeAt(i + 1) & 0xFF) << 8) +
|
540 | (currentData.charCodeAt(i) & 0xFF);
|
541 | if ((instruction === 's') && (currentResult >= 32768)) {
|
542 | currentResult -= 65536;
|
543 | }
|
544 | result[label + (quantifier > 1 ?
|
545 | ((i / 2) + 1) :
|
546 | '')] = currentResult;
|
547 | }
|
548 | break;
|
549 |
|
550 | case 'n':
|
551 | if (quantifier === '*') {
|
552 | quantifier = (data.length - dataPointer) / 2;
|
553 | } else {
|
554 | quantifier = parseInt(quantifier, 10);
|
555 | }
|
556 |
|
557 | currentData = data.substr(dataPointer, quantifier * 2);
|
558 | dataPointer += quantifier * 2;
|
559 |
|
560 | for (i = 0; i < currentData.length; i += 2) {
|
561 |
|
562 | currentResult = ((currentData.charCodeAt(i) & 0xFF) << 8) +
|
563 | (currentData.charCodeAt(i + 1) & 0xFF);
|
564 | result[label + (quantifier > 1 ?
|
565 | ((i / 2) + 1) :
|
566 | '')] = currentResult;
|
567 | }
|
568 | break;
|
569 |
|
570 | case 'i':
|
571 | case 'I':
|
572 | case 'l':
|
573 | case 'L':
|
574 | case 'V':
|
575 | if (quantifier === '*') {
|
576 | quantifier = (data.length - dataPointer) / 4;
|
577 | } else {
|
578 | quantifier = parseInt(quantifier, 10);
|
579 | }
|
580 |
|
581 | currentData = data.substr(dataPointer, quantifier * 4);
|
582 | dataPointer += quantifier * 4;
|
583 |
|
584 | for (i = 0; i < currentData.length; i += 4) {
|
585 | currentResult =
|
586 | ((currentData.charCodeAt(i + 3) & 0xFF) << 24) +
|
587 | ((currentData.charCodeAt(i + 2) & 0xFF) << 16) +
|
588 | ((currentData.charCodeAt(i + 1) & 0xFF) << 8) +
|
589 | ((currentData.charCodeAt(i) & 0xFF));
|
590 | result[label + (quantifier > 1 ?
|
591 | ((i / 4) + 1) :
|
592 | '')] = currentResult;
|
593 | }
|
594 |
|
595 | break;
|
596 |
|
597 | case 'N':
|
598 | if (quantifier === '*') {
|
599 | quantifier = (data.length - dataPointer) / 4;
|
600 | } else {
|
601 | quantifier = parseInt(quantifier, 10);
|
602 | }
|
603 |
|
604 | currentData = data.substr(dataPointer, quantifier * 4);
|
605 | dataPointer += quantifier * 4;
|
606 |
|
607 | for (i = 0; i < currentData.length; i += 4) {
|
608 | currentResult =
|
609 | ((currentData.charCodeAt(i) & 0xFF) << 24) +
|
610 | ((currentData.charCodeAt(i + 1) & 0xFF) << 16) +
|
611 | ((currentData.charCodeAt(i + 2) & 0xFF) << 8) +
|
612 | ((currentData.charCodeAt(i + 3) & 0xFF));
|
613 | result[label + (quantifier > 1 ?
|
614 | ((i / 4) + 1) :
|
615 | '')] = currentResult;
|
616 | }
|
617 |
|
618 | break;
|
619 |
|
620 | case 'f':
|
621 | case 'd':
|
622 | ebits = 8;
|
623 | fbits = (instruction === 'f') ? 23 : 52;
|
624 | dataByteLength = 4;
|
625 | if (instruction === 'd') {
|
626 | ebits = 11;
|
627 | dataByteLength = 8;
|
628 | }
|
629 |
|
630 | if (quantifier === '*') {
|
631 | quantifier = (data.length - dataPointer) / dataByteLength;
|
632 | } else {
|
633 | quantifier = parseInt(quantifier, 10);
|
634 | }
|
635 |
|
636 | currentData = data.substr(dataPointer, quantifier * dataByteLength);
|
637 | dataPointer += quantifier * dataByteLength;
|
638 |
|
639 | for (i = 0; i < currentData.length; i += dataByteLength) {
|
640 | data = currentData.substr(i, dataByteLength);
|
641 |
|
642 | bytes = [];
|
643 | for (j = data.length - 1; j >= 0; --j) {
|
644 | bytes.push(data.charCodeAt(j));
|
645 | }
|
646 | result[label + (quantifier > 1 ?
|
647 | ((i / 4) + 1) :
|
648 | '')] = fromIEEE754(bytes, ebits, fbits);
|
649 | }
|
650 |
|
651 | break;
|
652 |
|
653 | case 'x':
|
654 | case 'X':
|
655 | case '@':
|
656 | if (quantifier === '*') {
|
657 | quantifier = data.length - dataPointer;
|
658 | } else {
|
659 | quantifier = parseInt(quantifier, 10);
|
660 | }
|
661 |
|
662 | if (quantifier > 0) {
|
663 | if (instruction === 'X') {
|
664 | dataPointer -= quantifier;
|
665 | } else {
|
666 | if (instruction === 'x') {
|
667 | dataPointer += quantifier;
|
668 | } else {
|
669 | dataPointer = quantifier;
|
670 | }
|
671 | }
|
672 | }
|
673 | break;
|
674 |
|
675 | default:
|
676 | throw new Error('Warning: unpack() Type ' + instruction +
|
677 | ': unknown format code');
|
678 | }
|
679 | }
|
680 | return result;
|
681 | }
|
682 |
|
683 | exports.pack = pack;
|
684 | exports.unpack = unpack; |
\ | No newline at end of file |