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.
@@ -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;
@@ -330,7 +333,8 @@ export class biwriter {
330
333
  this.extendArray((endOffset || this.offset) - this.size);
331
334
  }
332
335
  else {
333
- 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);
334
338
  }
335
339
  }
336
340
  return this.data.slice(Math.abs(startOffset || 0), endOffset || this.offset);
@@ -348,7 +352,8 @@ export class biwriter {
348
352
  this.extendArray((endOffset || this.offset) - this.size);
349
353
  }
350
354
  else {
351
- 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);
352
357
  }
353
358
  }
354
359
  return this.data.slice(Math.abs(startOffset || 0), endOffset || this.offset);
@@ -366,7 +371,8 @@ export class biwriter {
366
371
  this.extendArray((endOffset || this.offset) - this.size);
367
372
  }
368
373
  else {
369
- 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);
370
376
  }
371
377
  }
372
378
  return this.data.slice(Math.abs(startOffset || 0), endOffset || this.offset);
@@ -385,7 +391,8 @@ export class biwriter {
385
391
  this.extendArray((endOffset || this.offset) - this.size);
386
392
  }
387
393
  else {
388
- 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);
389
396
  }
390
397
  }
391
398
  return this.data.slice(Math.abs(startOffset || 0), endOffset || this.offset);
@@ -395,38 +402,46 @@ export class biwriter {
395
402
  * Note: Does not affect supplied data
396
403
  * Note: Will extend array if strict mode is off
397
404
  * @param {number} length - length of data to copy from current offset
405
+ * @param {number} consume - moves offset to end of length
398
406
  * @returns {Buffer|Uint8Array} ``Buffer`` or ``Uint8Array``
399
407
  */
400
- extract(length) {
408
+ extract(length, consume) {
401
409
  if (this.offset + (length || 0) > this.size) {
402
410
  if (this.strict == false) {
403
411
  this.extendArray(this.offset + (length || 0) - this.size);
404
412
  }
405
413
  else {
406
- 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);
407
416
  }
408
417
  }
409
- 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;
410
423
  }
411
424
  /**
412
425
  * Extract array from current position to length supplied
413
426
  * Note: Does not affect supplied data
414
427
  * Note: Will extend array if strict mode is off
415
428
  * @param {number} length - length of data to copy from current offset
429
+ * @param {number} consume - moves offset to end of length
416
430
  * @returns {Buffer|Uint8Array} ``Buffer`` or ``Uint8Array``
417
431
  */
418
- wrap(length) {
419
- return this.extract(length);
432
+ wrap(length, consume) {
433
+ return this.extract(length, consume);
420
434
  }
421
435
  /**
422
436
  * Extract array from current position to length supplied
423
437
  * Note: Does not affect supplied data
424
438
  * Note: Will extend array if strict mode is off
425
439
  * @param {number} length - length of data to copy from current offset
440
+ * @param {number} consume - moves offset to end of length
426
441
  * @returns {Buffer|Uint8Array} ``Buffer`` or ``Uint8Array``
427
442
  */
428
- lift(length) {
429
- return this.extract(length);
443
+ lift(length, consume) {
444
+ return this.extract(length, consume);
430
445
  }
431
446
  /**
432
447
  * Returns current data
@@ -466,6 +481,212 @@ export class biwriter {
466
481
  finished() {
467
482
  this.data = undefined;
468
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
+ }
469
690
  //
470
691
  //bit writer
471
692
  //
@@ -494,6 +715,7 @@ export class biwriter {
494
715
  }
495
716
  if (unsigned == true) {
496
717
  if (value < 0 || value > Math.pow(2, bits)) {
718
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
497
719
  throw new Error(`Value is out of range for the specified ${bits}bit length.` + " min: " + 0 + " max: " + Math.pow(2, bits) + " value: " + value);
498
720
  }
499
721
  }
@@ -501,6 +723,7 @@ export class biwriter {
501
723
  const maxValue = Math.pow(2, bits - 1) - 1;
502
724
  const minValue = -maxValue - 1;
503
725
  if (value < minValue || value > maxValue) {
726
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
504
727
  throw new Error(`Value is out of range for the specified ${bits}bit length.` + " min: " + minValue + " max: " + maxValue + " value: " + value);
505
728
  }
506
729
  }
@@ -3026,6 +3249,7 @@ export class biwriter {
3026
3249
  this.check_size(1, 0, offset);
3027
3250
  if (unsigned == true) {
3028
3251
  if (value < 0 || value > 255) {
3252
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
3029
3253
  throw new Error('Value is out of range for the specified 8bit length.' + " min: " + 0 + " max: " + 255 + " value: " + value);
3030
3254
  }
3031
3255
  }
@@ -3033,6 +3257,7 @@ export class biwriter {
3033
3257
  const maxValue = Math.pow(2, 8 - 1) - 1;
3034
3258
  const minValue = -maxValue - 1;
3035
3259
  if (value < minValue || value > maxValue) {
3260
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
3036
3261
  throw new Error('Value is out of range for the specified 8bit length.' + " min: " + minValue + " max: " + maxValue + " value: " + value);
3037
3262
  }
3038
3263
  }
@@ -3101,6 +3326,7 @@ export class biwriter {
3101
3326
  this.check_size(2, 0, offset);
3102
3327
  if (unsigned == true) {
3103
3328
  if (value < 0 || value > 65535) {
3329
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
3104
3330
  throw new Error('Value is out of range for the specified 16bit length.' + " min: " + 0 + " max: " + 65535 + " value: " + value);
3105
3331
  }
3106
3332
  }
@@ -3108,6 +3334,7 @@ export class biwriter {
3108
3334
  const maxValue = Math.pow(2, 16 - 1) - 1;
3109
3335
  const minValue = -maxValue - 1;
3110
3336
  if (value < minValue || value > maxValue) {
3337
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
3111
3338
  throw new Error('Value is out of range for the specified 16bit length.' + " min: " + minValue + " max: " + maxValue + " value: " + value);
3112
3339
  }
3113
3340
  }
@@ -3353,6 +3580,7 @@ export class biwriter {
3353
3580
  const maxValue = 65504;
3354
3581
  const minValue = 5.96e-08;
3355
3582
  if (value < minValue || value > maxValue) {
3583
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
3356
3584
  throw new Error('Value is out of range for the specified half float length.' + " min: " + minValue + " max: " + maxValue + " value: " + value);
3357
3585
  }
3358
3586
  const signMask = 0x8000;
@@ -3478,6 +3706,7 @@ export class biwriter {
3478
3706
  this.check_size(4, 0, offset);
3479
3707
  if (unsigned == true) {
3480
3708
  if (value < 0 || value > 4294967295) {
3709
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
3481
3710
  throw new Error('Value is out of range for the specified 32bit length.' + " min: " + 0 + " max: " + 4294967295 + " value: " + value);
3482
3711
  }
3483
3712
  }
@@ -3485,6 +3714,7 @@ export class biwriter {
3485
3714
  const maxValue = Math.pow(2, 32 - 1) - 1;
3486
3715
  const minValue = -maxValue - 1;
3487
3716
  if (value < minValue || value > maxValue) {
3717
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
3488
3718
  throw new Error('Value is out of range for the specified 32bit length.' + " min: " + minValue + " max: " + maxValue + " value: " + value);
3489
3719
  }
3490
3720
  }
@@ -3791,6 +4021,7 @@ export class biwriter {
3791
4021
  const maxValue = 3.402823466e+38;
3792
4022
  const minValue = 1.175494351e-38;
3793
4023
  if (value < minValue || value > maxValue) {
4024
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
3794
4025
  throw new Error('Value is out of range for the specified float length.' + " min: " + minValue + " max: " + maxValue + " value: " + value);
3795
4026
  }
3796
4027
  let intValue = Float32Array.from([value])[0]; // Convert float to 32-bit integer representation
@@ -3867,6 +4098,7 @@ export class biwriter {
3867
4098
  this.check_size(8, 0, offset);
3868
4099
  if (unsigned == true) {
3869
4100
  if (value < 0 || value > Math.pow(2, 64) - 1) {
4101
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
3870
4102
  throw new Error('Value is out of range for the specified 64bit length.' + " min: " + 0 + " max: " + (Math.pow(2, 64) - 1) + " value: " + value);
3871
4103
  }
3872
4104
  }
@@ -3874,6 +4106,7 @@ export class biwriter {
3874
4106
  const maxValue = Math.pow(2, 63) - 1;
3875
4107
  const minValue = -Math.pow(2, 63);
3876
4108
  if (value < minValue || value > maxValue) {
4109
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
3877
4110
  throw new Error('Value is out of range for the specified 64bit length.' + " min: " + minValue + " max: " + maxValue + " value: " + value);
3878
4111
  }
3879
4112
  }
@@ -4146,6 +4379,7 @@ export class biwriter {
4146
4379
  const maxValue = 1.7976931348623158e308;
4147
4380
  const minValue = 2.2250738585072014e-308;
4148
4381
  if (value < minValue || value > maxValue) {
4382
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
4149
4383
  throw new Error('Value is out of range for the specified 64bit length.' + " min: " + minValue + " max: " + maxValue + " value: " + value);
4150
4384
  }
4151
4385
  const intArray = new Int32Array(2);
@@ -4336,9 +4570,11 @@ export class biwriter {
4336
4570
  maxLength = 4294967295;
4337
4571
  }
4338
4572
  else {
4573
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
4339
4574
  throw new Error("Invalid length read size: " + lengthWriteSize);
4340
4575
  }
4341
4576
  if (string.length > maxLength || (length || 0) > maxLength) {
4577
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
4342
4578
  throw new Error("String outsize of max write length: " + maxLength);
4343
4579
  }
4344
4580
  var maxBytes = Math.min(string.length, maxLength);