bireader 1.0.13 → 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.
@@ -43,7 +43,8 @@ class biwriter {
43
43
  this.extendArray(dif);
44
44
  }
45
45
  else {
46
- throw new Error("Location outside of size of data: " + this.size);
46
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
47
+ throw new Error(`Reader reached end of data: reading to ` + needed_size + " at " + this.offset + " of " + this.size);
47
48
  }
48
49
  this.size = this.data.length;
49
50
  }
@@ -65,6 +66,7 @@ class biwriter {
65
66
  this.bitoffset = 0;
66
67
  this.size = 0;
67
68
  this.strict = false;
69
+ this.errorDump = true;
68
70
  this.data = [];
69
71
  if (endianness != undefined && typeof endianness != "string") {
70
72
  throw new Error("endianness must be big or little");
@@ -196,7 +198,8 @@ class biwriter {
196
198
  this.extendArray(new_size - this.size);
197
199
  }
198
200
  else {
199
- throw new Error("Outside of range of data: " + this.size);
201
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
202
+ throw new Error("Outside of range of data: goto " + new_size + " of " + this.size);
200
203
  }
201
204
  this.offset = byte;
202
205
  this.bitoffset = (bit || 0) % 8;
@@ -333,7 +336,8 @@ class biwriter {
333
336
  this.extendArray((endOffset || this.offset) - this.size);
334
337
  }
335
338
  else {
336
- throw new Error("End offset outside of data: " + this.size);
339
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
340
+ throw new Error("End offset outside of data: endOffset" + endOffset + " of " + this.size);
337
341
  }
338
342
  }
339
343
  return this.data.slice(Math.abs(startOffset || 0), endOffset || this.offset);
@@ -351,7 +355,8 @@ class biwriter {
351
355
  this.extendArray((endOffset || this.offset) - this.size);
352
356
  }
353
357
  else {
354
- throw new Error("End offset outside of data: " + this.size);
358
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
359
+ throw new Error("End offset outside of data: endOffset" + endOffset + " of " + this.size);
355
360
  }
356
361
  }
357
362
  return this.data.slice(Math.abs(startOffset || 0), endOffset || this.offset);
@@ -369,7 +374,8 @@ class biwriter {
369
374
  this.extendArray((endOffset || this.offset) - this.size);
370
375
  }
371
376
  else {
372
- throw new Error("End offset outside of data: " + this.size);
377
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
378
+ throw new Error("End offset outside of data: endOffset" + endOffset + " of " + this.size);
373
379
  }
374
380
  }
375
381
  return this.data.slice(Math.abs(startOffset || 0), endOffset || this.offset);
@@ -388,7 +394,8 @@ class biwriter {
388
394
  this.extendArray((endOffset || this.offset) - this.size);
389
395
  }
390
396
  else {
391
- throw new Error("End offset outside of data: " + this.size);
397
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
398
+ throw new Error("End offset outside of data: endOffset" + endOffset + " of " + this.size);
392
399
  }
393
400
  }
394
401
  return this.data.slice(Math.abs(startOffset || 0), endOffset || this.offset);
@@ -398,38 +405,46 @@ class biwriter {
398
405
  * Note: Does not affect supplied data
399
406
  * Note: Will extend array if strict mode is off
400
407
  * @param {number} length - length of data to copy from current offset
408
+ * @param {number} consume - moves offset to end of length
401
409
  * @returns {Buffer|Uint8Array} ``Buffer`` or ``Uint8Array``
402
410
  */
403
- extract(length) {
411
+ extract(length, consume) {
404
412
  if (this.offset + (length || 0) > this.size) {
405
413
  if (this.strict == false) {
406
414
  this.extendArray(this.offset + (length || 0) - this.size);
407
415
  }
408
416
  else {
409
- throw new Error("End offset outside of data: " + this.size);
417
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
418
+ throw new Error("End offset outside of data: at " + this.offset + " reading " + length + " of" + this.size);
410
419
  }
411
420
  }
412
- return this.data.slice(this.offset, this.offset + (length || 0));
421
+ const extract = this.data.slice(this.offset, this.offset + (length || 0));
422
+ if (consume) {
423
+ this.offset += length;
424
+ }
425
+ return extract;
413
426
  }
414
427
  /**
415
428
  * Extract array from current position to length supplied
416
429
  * Note: Does not affect supplied data
417
430
  * Note: Will extend array if strict mode is off
418
431
  * @param {number} length - length of data to copy from current offset
432
+ * @param {number} consume - moves offset to end of length
419
433
  * @returns {Buffer|Uint8Array} ``Buffer`` or ``Uint8Array``
420
434
  */
421
- wrap(length) {
422
- return this.extract(length);
435
+ wrap(length, consume) {
436
+ return this.extract(length, consume);
423
437
  }
424
438
  /**
425
439
  * Extract array from current position to length supplied
426
440
  * Note: Does not affect supplied data
427
441
  * Note: Will extend array if strict mode is off
428
442
  * @param {number} length - length of data to copy from current offset
443
+ * @param {number} consume - moves offset to end of length
429
444
  * @returns {Buffer|Uint8Array} ``Buffer`` or ``Uint8Array``
430
445
  */
431
- lift(length) {
432
- return this.extract(length);
446
+ lift(length, consume) {
447
+ return this.extract(length, consume);
433
448
  }
434
449
  /**
435
450
  * Returns current data
@@ -469,6 +484,212 @@ class biwriter {
469
484
  finished() {
470
485
  this.data = undefined;
471
486
  }
487
+ /**
488
+ * Turn hexdump on error off, default on
489
+ */
490
+ errorDumpOff() {
491
+ this.errorDump = false;
492
+ }
493
+ /**
494
+ * Turn hexdump on error on, default on
495
+ */
496
+ errorDumpOn() {
497
+ this.errorDump = true;
498
+ }
499
+ /**
500
+ * Console logs data as hex dump
501
+ *
502
+ * @param {object} options - options object
503
+ * ```javascript
504
+ * {
505
+ * length: 192, // number of bytes to log, default 192 or end of data
506
+ * startByte: 0, // byte to start dump, default current position
507
+ * supressUnicode: false // Supress unicode character preview for cleaner columns
508
+ * }
509
+ * ```
510
+ */
511
+ hexdump(options) {
512
+ var length = options && options.length;
513
+ var startByte = options && options.startByte;
514
+ var supressUnicode = options && options.supressUnicode || false;
515
+ if ((startByte || 0) > this.size) {
516
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
517
+ throw new Error("Hexdump start is outside of data size: " + startByte + " of " + this.size);
518
+ }
519
+ const start = startByte || this.offset;
520
+ const end = Math.min(start + (length || 192), this.size);
521
+ if (start + (length || 0) > this.size) {
522
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
523
+ throw new Error("Hexdump amount is outside of data size: " + (start + (length || 0)) + " of " + end);
524
+ }
525
+ function hex_check(byte, bits) {
526
+ var value = 0;
527
+ for (var i = 0; i < bits;) {
528
+ var remaining = bits - i;
529
+ var bitOffset = 0;
530
+ var currentByte = byte;
531
+ var read = Math.min(remaining, 8 - bitOffset);
532
+ var mask, readBits;
533
+ mask = ~(0xFF << read);
534
+ readBits = (currentByte >> (8 - read - bitOffset)) & mask;
535
+ value <<= read;
536
+ value |= readBits;
537
+ i += read;
538
+ }
539
+ value = value >>> 0;
540
+ return value;
541
+ }
542
+ const rows = [];
543
+ var header = " 0 1 2 3 4 5 6 7 8 9 A B C D E F ";
544
+ var ending = "0123456789ABCDEF";
545
+ var addr = "";
546
+ for (let i = start; i < end; i += 16) {
547
+ addr = i.toString(16).padStart(5, '0');
548
+ var row = this.data?.slice(i, i + 16) || [];
549
+ var hex = Array.from(row, (byte) => byte.toString(16).padStart(2, '0')).join(' ');
550
+ rows.push(`${addr} ${hex.padEnd(47)} `);
551
+ }
552
+ let result = '';
553
+ let make_wide = false;
554
+ let i = start;
555
+ while (i < end) {
556
+ const byte = this.data[i];
557
+ if (byte < 32 || byte == 127) {
558
+ result += '.';
559
+ }
560
+ else if (byte < 127) {
561
+ // Valid UTF-8 start byte or single-byte character
562
+ // Convert the byte to a character and add it to the result
563
+ result += String.fromCharCode(byte);
564
+ }
565
+ else if (supressUnicode) {
566
+ result += '.';
567
+ }
568
+ else if (hex_check(byte, 1) == 0) {
569
+ //Byte 1
570
+ result += String.fromCharCode(byte);
571
+ }
572
+ else if (hex_check(byte, 3) == 6) {
573
+ //Byte 2
574
+ if (i + 1 <= end) {
575
+ //check second byte
576
+ const byte2 = this.data[i + 1];
577
+ if (hex_check(byte2, 2) == 2) {
578
+ const charCode = ((byte & 0x1f) << 6) | (byte2 & 0x3f);
579
+ i++;
580
+ make_wide = true;
581
+ const read = " " + String.fromCharCode(charCode);
582
+ result += read;
583
+ }
584
+ else {
585
+ result += ".";
586
+ }
587
+ }
588
+ else {
589
+ result += ".";
590
+ }
591
+ }
592
+ else if (hex_check(byte, 4) == 14) {
593
+ //Byte 3
594
+ if (i + 1 <= end) {
595
+ //check second byte
596
+ const byte2 = this.data[i + 1];
597
+ if (hex_check(byte2, 2) == 2) {
598
+ if (i + 2 <= end) {
599
+ //check third byte
600
+ const byte3 = this.data[i + 2];
601
+ if (hex_check(byte3, 2) == 2) {
602
+ const charCode = ((byte & 0x0f) << 12) |
603
+ ((byte2 & 0x3f) << 6) |
604
+ (byte3 & 0x3f);
605
+ i += 2;
606
+ make_wide = true;
607
+ const read = " " + String.fromCharCode(charCode);
608
+ result += read;
609
+ }
610
+ else {
611
+ i++;
612
+ result += " .";
613
+ }
614
+ }
615
+ else {
616
+ i++;
617
+ result += " .";
618
+ }
619
+ }
620
+ else {
621
+ result += ".";
622
+ }
623
+ }
624
+ else {
625
+ result += ".";
626
+ }
627
+ }
628
+ else if (hex_check(byte, 5) == 28) {
629
+ //Byte 4
630
+ if (i + 1 <= end) {
631
+ //check second byte
632
+ const byte2 = this.data[i + 1];
633
+ if (hex_check(byte2, 2) == 2) {
634
+ if (i + 2 <= end) {
635
+ //check third byte
636
+ const byte3 = this.data[i + 2];
637
+ if (hex_check(byte3, 2) == 2) {
638
+ if (i + 3 <= end) {
639
+ //check fourth byte
640
+ const byte4 = this.data[i + 2];
641
+ if (hex_check(byte4, 2) == 2) {
642
+ const charCode = (((byte4 & 0xFF) << 24) | ((byte3 & 0xFF) << 16) | ((byte2 & 0xFF) << 8) | (byte & 0xFF));
643
+ i += 3;
644
+ make_wide = true;
645
+ const read = " " + String.fromCharCode(charCode);
646
+ result += read;
647
+ }
648
+ else {
649
+ i += 2;
650
+ result += " .";
651
+ }
652
+ }
653
+ else {
654
+ i += 2;
655
+ result += " .";
656
+ }
657
+ }
658
+ else {
659
+ i++;
660
+ result += " .";
661
+ }
662
+ }
663
+ else {
664
+ i++;
665
+ result += " .";
666
+ }
667
+ }
668
+ else {
669
+ result += ".";
670
+ }
671
+ }
672
+ else {
673
+ result += ".";
674
+ }
675
+ }
676
+ else {
677
+ // Invalid UTF-8 byte, add a period to the result
678
+ result += '.';
679
+ }
680
+ i++;
681
+ }
682
+ const chunks = result.match(new RegExp(`.{1,${16}}`, 'g'));
683
+ chunks?.forEach((self, i) => {
684
+ rows[i] = rows[i] + (make_wide ? "|" + self + "|" : self);
685
+ });
686
+ header = "".padStart(addr.length) + header + (make_wide ? "" : ending);
687
+ rows.unshift(header);
688
+ if (make_wide) {
689
+ rows.push("*Removed character byte header on unicode detection");
690
+ }
691
+ console.log(rows.join("\n"));
692
+ }
472
693
  //
473
694
  //bit writer
474
695
  //
@@ -497,6 +718,7 @@ class biwriter {
497
718
  }
498
719
  if (unsigned == true) {
499
720
  if (value < 0 || value > Math.pow(2, bits)) {
721
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
500
722
  throw new Error(`Value is out of range for the specified ${bits}bit length.` + " min: " + 0 + " max: " + Math.pow(2, bits) + " value: " + value);
501
723
  }
502
724
  }
@@ -504,6 +726,7 @@ class biwriter {
504
726
  const maxValue = Math.pow(2, bits - 1) - 1;
505
727
  const minValue = -maxValue - 1;
506
728
  if (value < minValue || value > maxValue) {
729
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
507
730
  throw new Error(`Value is out of range for the specified ${bits}bit length.` + " min: " + minValue + " max: " + maxValue + " value: " + value);
508
731
  }
509
732
  }
@@ -3029,6 +3252,7 @@ class biwriter {
3029
3252
  this.check_size(1, 0, offset);
3030
3253
  if (unsigned == true) {
3031
3254
  if (value < 0 || value > 255) {
3255
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
3032
3256
  throw new Error('Value is out of range for the specified 8bit length.' + " min: " + 0 + " max: " + 255 + " value: " + value);
3033
3257
  }
3034
3258
  }
@@ -3036,6 +3260,7 @@ class biwriter {
3036
3260
  const maxValue = Math.pow(2, 8 - 1) - 1;
3037
3261
  const minValue = -maxValue - 1;
3038
3262
  if (value < minValue || value > maxValue) {
3263
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
3039
3264
  throw new Error('Value is out of range for the specified 8bit length.' + " min: " + minValue + " max: " + maxValue + " value: " + value);
3040
3265
  }
3041
3266
  }
@@ -3104,6 +3329,7 @@ class biwriter {
3104
3329
  this.check_size(2, 0, offset);
3105
3330
  if (unsigned == true) {
3106
3331
  if (value < 0 || value > 65535) {
3332
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
3107
3333
  throw new Error('Value is out of range for the specified 16bit length.' + " min: " + 0 + " max: " + 65535 + " value: " + value);
3108
3334
  }
3109
3335
  }
@@ -3111,6 +3337,7 @@ class biwriter {
3111
3337
  const maxValue = Math.pow(2, 16 - 1) - 1;
3112
3338
  const minValue = -maxValue - 1;
3113
3339
  if (value < minValue || value > maxValue) {
3340
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
3114
3341
  throw new Error('Value is out of range for the specified 16bit length.' + " min: " + minValue + " max: " + maxValue + " value: " + value);
3115
3342
  }
3116
3343
  }
@@ -3356,6 +3583,7 @@ class biwriter {
3356
3583
  const maxValue = 65504;
3357
3584
  const minValue = 5.96e-08;
3358
3585
  if (value < minValue || value > maxValue) {
3586
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
3359
3587
  throw new Error('Value is out of range for the specified half float length.' + " min: " + minValue + " max: " + maxValue + " value: " + value);
3360
3588
  }
3361
3589
  const signMask = 0x8000;
@@ -3481,6 +3709,7 @@ class biwriter {
3481
3709
  this.check_size(4, 0, offset);
3482
3710
  if (unsigned == true) {
3483
3711
  if (value < 0 || value > 4294967295) {
3712
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
3484
3713
  throw new Error('Value is out of range for the specified 32bit length.' + " min: " + 0 + " max: " + 4294967295 + " value: " + value);
3485
3714
  }
3486
3715
  }
@@ -3488,6 +3717,7 @@ class biwriter {
3488
3717
  const maxValue = Math.pow(2, 32 - 1) - 1;
3489
3718
  const minValue = -maxValue - 1;
3490
3719
  if (value < minValue || value > maxValue) {
3720
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
3491
3721
  throw new Error('Value is out of range for the specified 32bit length.' + " min: " + minValue + " max: " + maxValue + " value: " + value);
3492
3722
  }
3493
3723
  }
@@ -3794,6 +4024,7 @@ class biwriter {
3794
4024
  const maxValue = 3.402823466e+38;
3795
4025
  const minValue = 1.175494351e-38;
3796
4026
  if (value < minValue || value > maxValue) {
4027
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
3797
4028
  throw new Error('Value is out of range for the specified float length.' + " min: " + minValue + " max: " + maxValue + " value: " + value);
3798
4029
  }
3799
4030
  let intValue = Float32Array.from([value])[0]; // Convert float to 32-bit integer representation
@@ -3870,6 +4101,7 @@ class biwriter {
3870
4101
  this.check_size(8, 0, offset);
3871
4102
  if (unsigned == true) {
3872
4103
  if (value < 0 || value > Math.pow(2, 64) - 1) {
4104
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
3873
4105
  throw new Error('Value is out of range for the specified 64bit length.' + " min: " + 0 + " max: " + (Math.pow(2, 64) - 1) + " value: " + value);
3874
4106
  }
3875
4107
  }
@@ -3877,6 +4109,7 @@ class biwriter {
3877
4109
  const maxValue = Math.pow(2, 63) - 1;
3878
4110
  const minValue = -Math.pow(2, 63);
3879
4111
  if (value < minValue || value > maxValue) {
4112
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
3880
4113
  throw new Error('Value is out of range for the specified 64bit length.' + " min: " + minValue + " max: " + maxValue + " value: " + value);
3881
4114
  }
3882
4115
  }
@@ -4149,6 +4382,7 @@ class biwriter {
4149
4382
  const maxValue = 1.7976931348623158e308;
4150
4383
  const minValue = 2.2250738585072014e-308;
4151
4384
  if (value < minValue || value > maxValue) {
4385
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
4152
4386
  throw new Error('Value is out of range for the specified 64bit length.' + " min: " + minValue + " max: " + maxValue + " value: " + value);
4153
4387
  }
4154
4388
  const intArray = new Int32Array(2);
@@ -4339,9 +4573,11 @@ class biwriter {
4339
4573
  maxLength = 4294967295;
4340
4574
  }
4341
4575
  else {
4576
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
4342
4577
  throw new Error("Invalid length read size: " + lengthWriteSize);
4343
4578
  }
4344
4579
  if (string.length > maxLength || (length || 0) > maxLength) {
4580
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
4345
4581
  throw new Error("String outsize of max write length: " + maxLength);
4346
4582
  }
4347
4583
  var maxBytes = Math.min(string.length, maxLength);