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.
@@ -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;
@@ -301,6 +304,14 @@ class biwriter {
301
304
  return this.offset;
302
305
  }
303
306
  /**
307
+ * Get the current byte position
308
+ *
309
+ * @return {number} current byte position
310
+ */
311
+ saveOffset() {
312
+ return this.offset;
313
+ }
314
+ /**
304
315
  * Disallows extending array if writing outside of max size
305
316
  */
306
317
  restrict() {
@@ -325,7 +336,8 @@ class biwriter {
325
336
  this.extendArray((endOffset || this.offset) - this.size);
326
337
  }
327
338
  else {
328
- 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);
329
341
  }
330
342
  }
331
343
  return this.data.slice(Math.abs(startOffset || 0), endOffset || this.offset);
@@ -343,7 +355,8 @@ class biwriter {
343
355
  this.extendArray((endOffset || this.offset) - this.size);
344
356
  }
345
357
  else {
346
- 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);
347
360
  }
348
361
  }
349
362
  return this.data.slice(Math.abs(startOffset || 0), endOffset || this.offset);
@@ -361,7 +374,8 @@ class biwriter {
361
374
  this.extendArray((endOffset || this.offset) - this.size);
362
375
  }
363
376
  else {
364
- 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);
365
379
  }
366
380
  }
367
381
  return this.data.slice(Math.abs(startOffset || 0), endOffset || this.offset);
@@ -380,7 +394,8 @@ class biwriter {
380
394
  this.extendArray((endOffset || this.offset) - this.size);
381
395
  }
382
396
  else {
383
- 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);
384
399
  }
385
400
  }
386
401
  return this.data.slice(Math.abs(startOffset || 0), endOffset || this.offset);
@@ -390,38 +405,46 @@ class biwriter {
390
405
  * Note: Does not affect supplied data
391
406
  * Note: Will extend array if strict mode is off
392
407
  * @param {number} length - length of data to copy from current offset
408
+ * @param {number} consume - moves offset to end of length
393
409
  * @returns {Buffer|Uint8Array} ``Buffer`` or ``Uint8Array``
394
410
  */
395
- extract(length) {
411
+ extract(length, consume) {
396
412
  if (this.offset + (length || 0) > this.size) {
397
413
  if (this.strict == false) {
398
414
  this.extendArray(this.offset + (length || 0) - this.size);
399
415
  }
400
416
  else {
401
- 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);
402
419
  }
403
420
  }
404
- 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;
405
426
  }
406
427
  /**
407
428
  * Extract array from current position to length supplied
408
429
  * Note: Does not affect supplied data
409
430
  * Note: Will extend array if strict mode is off
410
431
  * @param {number} length - length of data to copy from current offset
432
+ * @param {number} consume - moves offset to end of length
411
433
  * @returns {Buffer|Uint8Array} ``Buffer`` or ``Uint8Array``
412
434
  */
413
- wrap(length) {
414
- return this.extract(length);
435
+ wrap(length, consume) {
436
+ return this.extract(length, consume);
415
437
  }
416
438
  /**
417
439
  * Extract array from current position to length supplied
418
440
  * Note: Does not affect supplied data
419
441
  * Note: Will extend array if strict mode is off
420
442
  * @param {number} length - length of data to copy from current offset
443
+ * @param {number} consume - moves offset to end of length
421
444
  * @returns {Buffer|Uint8Array} ``Buffer`` or ``Uint8Array``
422
445
  */
423
- lift(length) {
424
- return this.extract(length);
446
+ lift(length, consume) {
447
+ return this.extract(length, consume);
425
448
  }
426
449
  /**
427
450
  * Returns current data
@@ -461,6 +484,212 @@ class biwriter {
461
484
  finished() {
462
485
  this.data = undefined;
463
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
+ }
464
693
  //
465
694
  //bit writer
466
695
  //
@@ -489,6 +718,7 @@ class biwriter {
489
718
  }
490
719
  if (unsigned == true) {
491
720
  if (value < 0 || value > Math.pow(2, bits)) {
721
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
492
722
  throw new Error(`Value is out of range for the specified ${bits}bit length.` + " min: " + 0 + " max: " + Math.pow(2, bits) + " value: " + value);
493
723
  }
494
724
  }
@@ -496,6 +726,7 @@ class biwriter {
496
726
  const maxValue = Math.pow(2, bits - 1) - 1;
497
727
  const minValue = -maxValue - 1;
498
728
  if (value < minValue || value > maxValue) {
729
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
499
730
  throw new Error(`Value is out of range for the specified ${bits}bit length.` + " min: " + minValue + " max: " + maxValue + " value: " + value);
500
731
  }
501
732
  }
@@ -3021,6 +3252,7 @@ class biwriter {
3021
3252
  this.check_size(1, 0, offset);
3022
3253
  if (unsigned == true) {
3023
3254
  if (value < 0 || value > 255) {
3255
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
3024
3256
  throw new Error('Value is out of range for the specified 8bit length.' + " min: " + 0 + " max: " + 255 + " value: " + value);
3025
3257
  }
3026
3258
  }
@@ -3028,6 +3260,7 @@ class biwriter {
3028
3260
  const maxValue = Math.pow(2, 8 - 1) - 1;
3029
3261
  const minValue = -maxValue - 1;
3030
3262
  if (value < minValue || value > maxValue) {
3263
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
3031
3264
  throw new Error('Value is out of range for the specified 8bit length.' + " min: " + minValue + " max: " + maxValue + " value: " + value);
3032
3265
  }
3033
3266
  }
@@ -3096,6 +3329,7 @@ class biwriter {
3096
3329
  this.check_size(2, 0, offset);
3097
3330
  if (unsigned == true) {
3098
3331
  if (value < 0 || value > 65535) {
3332
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
3099
3333
  throw new Error('Value is out of range for the specified 16bit length.' + " min: " + 0 + " max: " + 65535 + " value: " + value);
3100
3334
  }
3101
3335
  }
@@ -3103,6 +3337,7 @@ class biwriter {
3103
3337
  const maxValue = Math.pow(2, 16 - 1) - 1;
3104
3338
  const minValue = -maxValue - 1;
3105
3339
  if (value < minValue || value > maxValue) {
3340
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
3106
3341
  throw new Error('Value is out of range for the specified 16bit length.' + " min: " + minValue + " max: " + maxValue + " value: " + value);
3107
3342
  }
3108
3343
  }
@@ -3348,6 +3583,7 @@ class biwriter {
3348
3583
  const maxValue = 65504;
3349
3584
  const minValue = 5.96e-08;
3350
3585
  if (value < minValue || value > maxValue) {
3586
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
3351
3587
  throw new Error('Value is out of range for the specified half float length.' + " min: " + minValue + " max: " + maxValue + " value: " + value);
3352
3588
  }
3353
3589
  const signMask = 0x8000;
@@ -3473,6 +3709,7 @@ class biwriter {
3473
3709
  this.check_size(4, 0, offset);
3474
3710
  if (unsigned == true) {
3475
3711
  if (value < 0 || value > 4294967295) {
3712
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
3476
3713
  throw new Error('Value is out of range for the specified 32bit length.' + " min: " + 0 + " max: " + 4294967295 + " value: " + value);
3477
3714
  }
3478
3715
  }
@@ -3480,6 +3717,7 @@ class biwriter {
3480
3717
  const maxValue = Math.pow(2, 32 - 1) - 1;
3481
3718
  const minValue = -maxValue - 1;
3482
3719
  if (value < minValue || value > maxValue) {
3720
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
3483
3721
  throw new Error('Value is out of range for the specified 32bit length.' + " min: " + minValue + " max: " + maxValue + " value: " + value);
3484
3722
  }
3485
3723
  }
@@ -3786,6 +4024,7 @@ class biwriter {
3786
4024
  const maxValue = 3.402823466e+38;
3787
4025
  const minValue = 1.175494351e-38;
3788
4026
  if (value < minValue || value > maxValue) {
4027
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
3789
4028
  throw new Error('Value is out of range for the specified float length.' + " min: " + minValue + " max: " + maxValue + " value: " + value);
3790
4029
  }
3791
4030
  let intValue = Float32Array.from([value])[0]; // Convert float to 32-bit integer representation
@@ -3862,6 +4101,7 @@ class biwriter {
3862
4101
  this.check_size(8, 0, offset);
3863
4102
  if (unsigned == true) {
3864
4103
  if (value < 0 || value > Math.pow(2, 64) - 1) {
4104
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
3865
4105
  throw new Error('Value is out of range for the specified 64bit length.' + " min: " + 0 + " max: " + (Math.pow(2, 64) - 1) + " value: " + value);
3866
4106
  }
3867
4107
  }
@@ -3869,6 +4109,7 @@ class biwriter {
3869
4109
  const maxValue = Math.pow(2, 63) - 1;
3870
4110
  const minValue = -Math.pow(2, 63);
3871
4111
  if (value < minValue || value > maxValue) {
4112
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
3872
4113
  throw new Error('Value is out of range for the specified 64bit length.' + " min: " + minValue + " max: " + maxValue + " value: " + value);
3873
4114
  }
3874
4115
  }
@@ -4141,6 +4382,7 @@ class biwriter {
4141
4382
  const maxValue = 1.7976931348623158e308;
4142
4383
  const minValue = 2.2250738585072014e-308;
4143
4384
  if (value < minValue || value > maxValue) {
4385
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
4144
4386
  throw new Error('Value is out of range for the specified 64bit length.' + " min: " + minValue + " max: " + maxValue + " value: " + value);
4145
4387
  }
4146
4388
  const intArray = new Int32Array(2);
@@ -4331,9 +4573,11 @@ class biwriter {
4331
4573
  maxLength = 4294967295;
4332
4574
  }
4333
4575
  else {
4576
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
4334
4577
  throw new Error("Invalid length read size: " + lengthWriteSize);
4335
4578
  }
4336
4579
  if (string.length > maxLength || (length || 0) > maxLength) {
4580
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
4337
4581
  throw new Error("String outsize of max write length: " + maxLength);
4338
4582
  }
4339
4583
  var maxBytes = Math.min(string.length, maxLength);