bireader 1.0.12 → 1.0.14

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.
@@ -40,7 +40,8 @@ export class biwriter {
40
40
  this.extendArray(dif);
41
41
  }
42
42
  else {
43
- throw new Error("Location outside of size of data: " + this.size);
43
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
44
+ throw new Error(`Reader reached end of data: reading to ` + needed_size + " at " + this.offset + " of " + this.size);
44
45
  }
45
46
  this.size = this.data.length;
46
47
  }
@@ -62,6 +63,7 @@ export class biwriter {
62
63
  this.bitoffset = 0;
63
64
  this.size = 0;
64
65
  this.strict = false;
66
+ this.errorDump = true;
65
67
  this.data = [];
66
68
  if (endianness != undefined && typeof endianness != "string") {
67
69
  throw new Error("endianness must be big or little");
@@ -193,7 +195,8 @@ export class biwriter {
193
195
  this.extendArray(new_size - this.size);
194
196
  }
195
197
  else {
196
- throw new Error("Outside of range of data: " + this.size);
198
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
199
+ throw new Error("Outside of range of data: goto " + new_size + " of " + this.size);
197
200
  }
198
201
  this.offset = byte;
199
202
  this.bitoffset = (bit || 0) % 8;
@@ -298,6 +301,14 @@ export class biwriter {
298
301
  return this.offset;
299
302
  }
300
303
  /**
304
+ * Get the current byte position
305
+ *
306
+ * @return {number} current byte position
307
+ */
308
+ saveOffset() {
309
+ return this.offset;
310
+ }
311
+ /**
301
312
  * Disallows extending array if writing outside of max size
302
313
  */
303
314
  restrict() {
@@ -322,7 +333,8 @@ export class biwriter {
322
333
  this.extendArray((endOffset || this.offset) - this.size);
323
334
  }
324
335
  else {
325
- throw new Error("End offset outside of data: " + this.size);
336
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
337
+ throw new Error("End offset outside of data: endOffset" + endOffset + " of " + this.size);
326
338
  }
327
339
  }
328
340
  return this.data.slice(Math.abs(startOffset || 0), endOffset || this.offset);
@@ -340,7 +352,8 @@ export class biwriter {
340
352
  this.extendArray((endOffset || this.offset) - this.size);
341
353
  }
342
354
  else {
343
- throw new Error("End offset outside of data: " + this.size);
355
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
356
+ throw new Error("End offset outside of data: endOffset" + endOffset + " of " + this.size);
344
357
  }
345
358
  }
346
359
  return this.data.slice(Math.abs(startOffset || 0), endOffset || this.offset);
@@ -358,7 +371,8 @@ export class biwriter {
358
371
  this.extendArray((endOffset || this.offset) - this.size);
359
372
  }
360
373
  else {
361
- throw new Error("End offset outside of data: " + this.size);
374
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
375
+ throw new Error("End offset outside of data: endOffset" + endOffset + " of " + this.size);
362
376
  }
363
377
  }
364
378
  return this.data.slice(Math.abs(startOffset || 0), endOffset || this.offset);
@@ -377,7 +391,8 @@ export class biwriter {
377
391
  this.extendArray((endOffset || this.offset) - this.size);
378
392
  }
379
393
  else {
380
- throw new Error("End offset outside of data: " + this.size);
394
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
395
+ throw new Error("End offset outside of data: endOffset" + endOffset + " of " + this.size);
381
396
  }
382
397
  }
383
398
  return this.data.slice(Math.abs(startOffset || 0), endOffset || this.offset);
@@ -387,38 +402,46 @@ export class biwriter {
387
402
  * Note: Does not affect supplied data
388
403
  * Note: Will extend array if strict mode is off
389
404
  * @param {number} length - length of data to copy from current offset
405
+ * @param {number} consume - moves offset to end of length
390
406
  * @returns {Buffer|Uint8Array} ``Buffer`` or ``Uint8Array``
391
407
  */
392
- extract(length) {
408
+ extract(length, consume) {
393
409
  if (this.offset + (length || 0) > this.size) {
394
410
  if (this.strict == false) {
395
411
  this.extendArray(this.offset + (length || 0) - this.size);
396
412
  }
397
413
  else {
398
- throw new Error("End offset outside of data: " + this.size);
414
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
415
+ throw new Error("End offset outside of data: at " + this.offset + " reading " + length + " of" + this.size);
399
416
  }
400
417
  }
401
- return this.data.slice(this.offset, this.offset + (length || 0));
418
+ const extract = this.data.slice(this.offset, this.offset + (length || 0));
419
+ if (consume) {
420
+ this.offset += length;
421
+ }
422
+ return extract;
402
423
  }
403
424
  /**
404
425
  * Extract array from current position to length supplied
405
426
  * Note: Does not affect supplied data
406
427
  * Note: Will extend array if strict mode is off
407
428
  * @param {number} length - length of data to copy from current offset
429
+ * @param {number} consume - moves offset to end of length
408
430
  * @returns {Buffer|Uint8Array} ``Buffer`` or ``Uint8Array``
409
431
  */
410
- wrap(length) {
411
- return this.extract(length);
432
+ wrap(length, consume) {
433
+ return this.extract(length, consume);
412
434
  }
413
435
  /**
414
436
  * Extract array from current position to length supplied
415
437
  * Note: Does not affect supplied data
416
438
  * Note: Will extend array if strict mode is off
417
439
  * @param {number} length - length of data to copy from current offset
440
+ * @param {number} consume - moves offset to end of length
418
441
  * @returns {Buffer|Uint8Array} ``Buffer`` or ``Uint8Array``
419
442
  */
420
- lift(length) {
421
- return this.extract(length);
443
+ lift(length, consume) {
444
+ return this.extract(length, consume);
422
445
  }
423
446
  /**
424
447
  * Returns current data
@@ -458,6 +481,212 @@ export class biwriter {
458
481
  finished() {
459
482
  this.data = undefined;
460
483
  }
484
+ /**
485
+ * Turn hexdump on error off, default on
486
+ */
487
+ errorDumpOff() {
488
+ this.errorDump = false;
489
+ }
490
+ /**
491
+ * Turn hexdump on error on, default on
492
+ */
493
+ errorDumpOn() {
494
+ this.errorDump = true;
495
+ }
496
+ /**
497
+ * Console logs data as hex dump
498
+ *
499
+ * @param {object} options - options object
500
+ * ```javascript
501
+ * {
502
+ * length: 192, // number of bytes to log, default 192 or end of data
503
+ * startByte: 0, // byte to start dump, default current position
504
+ * supressUnicode: false // Supress unicode character preview for cleaner columns
505
+ * }
506
+ * ```
507
+ */
508
+ hexdump(options) {
509
+ var length = options && options.length;
510
+ var startByte = options && options.startByte;
511
+ var supressUnicode = options && options.supressUnicode || false;
512
+ if ((startByte || 0) > this.size) {
513
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
514
+ throw new Error("Hexdump start is outside of data size: " + startByte + " of " + this.size);
515
+ }
516
+ const start = startByte || this.offset;
517
+ const end = Math.min(start + (length || 192), this.size);
518
+ if (start + (length || 0) > this.size) {
519
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
520
+ throw new Error("Hexdump amount is outside of data size: " + (start + (length || 0)) + " of " + end);
521
+ }
522
+ function hex_check(byte, bits) {
523
+ var value = 0;
524
+ for (var i = 0; i < bits;) {
525
+ var remaining = bits - i;
526
+ var bitOffset = 0;
527
+ var currentByte = byte;
528
+ var read = Math.min(remaining, 8 - bitOffset);
529
+ var mask, readBits;
530
+ mask = ~(0xFF << read);
531
+ readBits = (currentByte >> (8 - read - bitOffset)) & mask;
532
+ value <<= read;
533
+ value |= readBits;
534
+ i += read;
535
+ }
536
+ value = value >>> 0;
537
+ return value;
538
+ }
539
+ const rows = [];
540
+ var header = " 0 1 2 3 4 5 6 7 8 9 A B C D E F ";
541
+ var ending = "0123456789ABCDEF";
542
+ var addr = "";
543
+ for (let i = start; i < end; i += 16) {
544
+ addr = i.toString(16).padStart(5, '0');
545
+ var row = this.data?.slice(i, i + 16) || [];
546
+ var hex = Array.from(row, (byte) => byte.toString(16).padStart(2, '0')).join(' ');
547
+ rows.push(`${addr} ${hex.padEnd(47)} `);
548
+ }
549
+ let result = '';
550
+ let make_wide = false;
551
+ let i = start;
552
+ while (i < end) {
553
+ const byte = this.data[i];
554
+ if (byte < 32 || byte == 127) {
555
+ result += '.';
556
+ }
557
+ else if (byte < 127) {
558
+ // Valid UTF-8 start byte or single-byte character
559
+ // Convert the byte to a character and add it to the result
560
+ result += String.fromCharCode(byte);
561
+ }
562
+ else if (supressUnicode) {
563
+ result += '.';
564
+ }
565
+ else if (hex_check(byte, 1) == 0) {
566
+ //Byte 1
567
+ result += String.fromCharCode(byte);
568
+ }
569
+ else if (hex_check(byte, 3) == 6) {
570
+ //Byte 2
571
+ if (i + 1 <= end) {
572
+ //check second byte
573
+ const byte2 = this.data[i + 1];
574
+ if (hex_check(byte2, 2) == 2) {
575
+ const charCode = ((byte & 0x1f) << 6) | (byte2 & 0x3f);
576
+ i++;
577
+ make_wide = true;
578
+ const read = " " + String.fromCharCode(charCode);
579
+ result += read;
580
+ }
581
+ else {
582
+ result += ".";
583
+ }
584
+ }
585
+ else {
586
+ result += ".";
587
+ }
588
+ }
589
+ else if (hex_check(byte, 4) == 14) {
590
+ //Byte 3
591
+ if (i + 1 <= end) {
592
+ //check second byte
593
+ const byte2 = this.data[i + 1];
594
+ if (hex_check(byte2, 2) == 2) {
595
+ if (i + 2 <= end) {
596
+ //check third byte
597
+ const byte3 = this.data[i + 2];
598
+ if (hex_check(byte3, 2) == 2) {
599
+ const charCode = ((byte & 0x0f) << 12) |
600
+ ((byte2 & 0x3f) << 6) |
601
+ (byte3 & 0x3f);
602
+ i += 2;
603
+ make_wide = true;
604
+ const read = " " + String.fromCharCode(charCode);
605
+ result += read;
606
+ }
607
+ else {
608
+ i++;
609
+ result += " .";
610
+ }
611
+ }
612
+ else {
613
+ i++;
614
+ result += " .";
615
+ }
616
+ }
617
+ else {
618
+ result += ".";
619
+ }
620
+ }
621
+ else {
622
+ result += ".";
623
+ }
624
+ }
625
+ else if (hex_check(byte, 5) == 28) {
626
+ //Byte 4
627
+ if (i + 1 <= end) {
628
+ //check second byte
629
+ const byte2 = this.data[i + 1];
630
+ if (hex_check(byte2, 2) == 2) {
631
+ if (i + 2 <= end) {
632
+ //check third byte
633
+ const byte3 = this.data[i + 2];
634
+ if (hex_check(byte3, 2) == 2) {
635
+ if (i + 3 <= end) {
636
+ //check fourth byte
637
+ const byte4 = this.data[i + 2];
638
+ if (hex_check(byte4, 2) == 2) {
639
+ const charCode = (((byte4 & 0xFF) << 24) | ((byte3 & 0xFF) << 16) | ((byte2 & 0xFF) << 8) | (byte & 0xFF));
640
+ i += 3;
641
+ make_wide = true;
642
+ const read = " " + String.fromCharCode(charCode);
643
+ result += read;
644
+ }
645
+ else {
646
+ i += 2;
647
+ result += " .";
648
+ }
649
+ }
650
+ else {
651
+ i += 2;
652
+ result += " .";
653
+ }
654
+ }
655
+ else {
656
+ i++;
657
+ result += " .";
658
+ }
659
+ }
660
+ else {
661
+ i++;
662
+ result += " .";
663
+ }
664
+ }
665
+ else {
666
+ result += ".";
667
+ }
668
+ }
669
+ else {
670
+ result += ".";
671
+ }
672
+ }
673
+ else {
674
+ // Invalid UTF-8 byte, add a period to the result
675
+ result += '.';
676
+ }
677
+ i++;
678
+ }
679
+ const chunks = result.match(new RegExp(`.{1,${16}}`, 'g'));
680
+ chunks?.forEach((self, i) => {
681
+ rows[i] = rows[i] + (make_wide ? "|" + self + "|" : self);
682
+ });
683
+ header = "".padStart(addr.length) + header + (make_wide ? "" : ending);
684
+ rows.unshift(header);
685
+ if (make_wide) {
686
+ rows.push("*Removed character byte header on unicode detection");
687
+ }
688
+ console.log(rows.join("\n"));
689
+ }
461
690
  //
462
691
  //bit writer
463
692
  //
@@ -486,6 +715,7 @@ export class biwriter {
486
715
  }
487
716
  if (unsigned == true) {
488
717
  if (value < 0 || value > Math.pow(2, bits)) {
718
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
489
719
  throw new Error(`Value is out of range for the specified ${bits}bit length.` + " min: " + 0 + " max: " + Math.pow(2, bits) + " value: " + value);
490
720
  }
491
721
  }
@@ -493,6 +723,7 @@ export class biwriter {
493
723
  const maxValue = Math.pow(2, bits - 1) - 1;
494
724
  const minValue = -maxValue - 1;
495
725
  if (value < minValue || value > maxValue) {
726
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
496
727
  throw new Error(`Value is out of range for the specified ${bits}bit length.` + " min: " + minValue + " max: " + maxValue + " value: " + value);
497
728
  }
498
729
  }
@@ -3018,6 +3249,7 @@ export class biwriter {
3018
3249
  this.check_size(1, 0, offset);
3019
3250
  if (unsigned == true) {
3020
3251
  if (value < 0 || value > 255) {
3252
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
3021
3253
  throw new Error('Value is out of range for the specified 8bit length.' + " min: " + 0 + " max: " + 255 + " value: " + value);
3022
3254
  }
3023
3255
  }
@@ -3025,6 +3257,7 @@ export class biwriter {
3025
3257
  const maxValue = Math.pow(2, 8 - 1) - 1;
3026
3258
  const minValue = -maxValue - 1;
3027
3259
  if (value < minValue || value > maxValue) {
3260
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
3028
3261
  throw new Error('Value is out of range for the specified 8bit length.' + " min: " + minValue + " max: " + maxValue + " value: " + value);
3029
3262
  }
3030
3263
  }
@@ -3093,6 +3326,7 @@ export class biwriter {
3093
3326
  this.check_size(2, 0, offset);
3094
3327
  if (unsigned == true) {
3095
3328
  if (value < 0 || value > 65535) {
3329
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
3096
3330
  throw new Error('Value is out of range for the specified 16bit length.' + " min: " + 0 + " max: " + 65535 + " value: " + value);
3097
3331
  }
3098
3332
  }
@@ -3100,6 +3334,7 @@ export class biwriter {
3100
3334
  const maxValue = Math.pow(2, 16 - 1) - 1;
3101
3335
  const minValue = -maxValue - 1;
3102
3336
  if (value < minValue || value > maxValue) {
3337
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
3103
3338
  throw new Error('Value is out of range for the specified 16bit length.' + " min: " + minValue + " max: " + maxValue + " value: " + value);
3104
3339
  }
3105
3340
  }
@@ -3345,6 +3580,7 @@ export class biwriter {
3345
3580
  const maxValue = 65504;
3346
3581
  const minValue = 5.96e-08;
3347
3582
  if (value < minValue || value > maxValue) {
3583
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
3348
3584
  throw new Error('Value is out of range for the specified half float length.' + " min: " + minValue + " max: " + maxValue + " value: " + value);
3349
3585
  }
3350
3586
  const signMask = 0x8000;
@@ -3470,6 +3706,7 @@ export class biwriter {
3470
3706
  this.check_size(4, 0, offset);
3471
3707
  if (unsigned == true) {
3472
3708
  if (value < 0 || value > 4294967295) {
3709
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
3473
3710
  throw new Error('Value is out of range for the specified 32bit length.' + " min: " + 0 + " max: " + 4294967295 + " value: " + value);
3474
3711
  }
3475
3712
  }
@@ -3477,6 +3714,7 @@ export class biwriter {
3477
3714
  const maxValue = Math.pow(2, 32 - 1) - 1;
3478
3715
  const minValue = -maxValue - 1;
3479
3716
  if (value < minValue || value > maxValue) {
3717
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
3480
3718
  throw new Error('Value is out of range for the specified 32bit length.' + " min: " + minValue + " max: " + maxValue + " value: " + value);
3481
3719
  }
3482
3720
  }
@@ -3783,6 +4021,7 @@ export class biwriter {
3783
4021
  const maxValue = 3.402823466e+38;
3784
4022
  const minValue = 1.175494351e-38;
3785
4023
  if (value < minValue || value > maxValue) {
4024
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
3786
4025
  throw new Error('Value is out of range for the specified float length.' + " min: " + minValue + " max: " + maxValue + " value: " + value);
3787
4026
  }
3788
4027
  let intValue = Float32Array.from([value])[0]; // Convert float to 32-bit integer representation
@@ -3859,6 +4098,7 @@ export class biwriter {
3859
4098
  this.check_size(8, 0, offset);
3860
4099
  if (unsigned == true) {
3861
4100
  if (value < 0 || value > Math.pow(2, 64) - 1) {
4101
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
3862
4102
  throw new Error('Value is out of range for the specified 64bit length.' + " min: " + 0 + " max: " + (Math.pow(2, 64) - 1) + " value: " + value);
3863
4103
  }
3864
4104
  }
@@ -3866,6 +4106,7 @@ export class biwriter {
3866
4106
  const maxValue = Math.pow(2, 63) - 1;
3867
4107
  const minValue = -Math.pow(2, 63);
3868
4108
  if (value < minValue || value > maxValue) {
4109
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
3869
4110
  throw new Error('Value is out of range for the specified 64bit length.' + " min: " + minValue + " max: " + maxValue + " value: " + value);
3870
4111
  }
3871
4112
  }
@@ -4138,6 +4379,7 @@ export class biwriter {
4138
4379
  const maxValue = 1.7976931348623158e308;
4139
4380
  const minValue = 2.2250738585072014e-308;
4140
4381
  if (value < minValue || value > maxValue) {
4382
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
4141
4383
  throw new Error('Value is out of range for the specified 64bit length.' + " min: " + minValue + " max: " + maxValue + " value: " + value);
4142
4384
  }
4143
4385
  const intArray = new Int32Array(2);
@@ -4328,9 +4570,11 @@ export class biwriter {
4328
4570
  maxLength = 4294967295;
4329
4571
  }
4330
4572
  else {
4573
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
4331
4574
  throw new Error("Invalid length read size: " + lengthWriteSize);
4332
4575
  }
4333
4576
  if (string.length > maxLength || (length || 0) > maxLength) {
4577
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
4334
4578
  throw new Error("String outsize of max write length: " + maxLength);
4335
4579
  }
4336
4580
  var maxBytes = Math.min(string.length, maxLength);