bireader 1.0.13 → 1.0.15

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.
@@ -1,39 +1,50 @@
1
+ import { skip, goto, remove, checkSize, addData, hexDump } from './common';
1
2
  /**
3
+ * Binary reader, includes bitfields and strings
2
4
  *
3
- * byte reader, includes bitfields and strings
4
- *
5
- * @param {Buffer|Uint8Array} data - ```Buffer``` or ```Uint8Array```
6
- * @param {number} byteOffset - byte offset to start reader, default is 0
7
- * @param {number} bitOffset - bit offset to start reader, 0-7
8
- * @param {string} endianness - endianness ```big``` or ```little``` (default ```little```)
5
+ * @param {Buffer|Uint8Array} data - ```Buffer``` or ```Uint8Array```. Always found in ``biwriter.data``
6
+ * @param {number} byteOffset - Byte offset to start reader (default 0)
7
+ * @param {number} bitOffset - Bit offset 0-7 to start reader (default 0)
8
+ * @param {string} endianness - Endianness ```big``` or ```little``` (default ```little```)
9
+ * @param {boolean} strict - Strict mode: if true does not extend supplied array on outside write (default true)
9
10
  */
10
11
  export class bireader {
11
- check_size(read_size, read_bits) {
12
- const new_off = this.offset + (read_size || 0) + Math.ceil((this.bitoffset + (read_bits || 0)) / 8);
13
- if (new_off > this.size) {
14
- throw new Error(`Reader reached end of data.`);
15
- }
16
- }
17
12
  isBuffer(obj) {
18
13
  return (typeof Buffer !== 'undefined' && obj instanceof Buffer);
19
14
  }
20
15
  isBufferOrUint8Array(obj) {
21
16
  return obj instanceof Uint8Array || this.isBuffer(obj);
22
17
  }
18
+ extendArray(to_padd) {
19
+ if ((typeof Buffer !== 'undefined' && this.data instanceof Buffer)) {
20
+ var paddbuffer = Buffer.alloc(to_padd);
21
+ this.data = Buffer.concat([this.data, paddbuffer]);
22
+ }
23
+ else {
24
+ const addArray = new Array(to_padd);
25
+ this.data = new Uint8Array([...this.data, ...addArray]);
26
+ }
27
+ }
28
+ check_size(read_size, read_bits) {
29
+ return checkSize(this, read_size || 0, read_bits || 0, this.offset);
30
+ }
23
31
  /**
32
+ * Binary reader, includes bitfields and strings
24
33
  *
25
- * byte reader, includes bitfields and strings
26
- *
27
- * @param {Buffer|Uint8Array} data - ```Buffer``` or ```Uint8Array```
28
- * @param {number} byteOffset - byte offset to start reader, default is 0
29
- * @param {number} bitOffset - bit offset to start reader, 0-7
30
- * @param {string} endianness - endianness ```big``` or ```little``` (default ```little```)
34
+ * @param {Buffer|Uint8Array} data - ```Buffer``` or ```Uint8Array```. Always found in ``biwriter.data``
35
+ * @param {number} byteOffset - Byte offset to start reader (default 0)
36
+ * @param {number} bitOffset - Bit offset 0-7 to start reader (default 0)
37
+ * @param {string} endianness - Endianness ```big``` or ```little``` (default ```little```)
38
+ * @param {boolean} strict - Strict mode: if true does not extend supplied array on outside write (default true)
31
39
  */
32
- constructor(data, byteOffset, bitOffset, endianness) {
40
+ constructor(data, byteOffset, bitOffset, endianness, strict) {
33
41
  this.endian = "little";
34
42
  this.offset = 0;
35
43
  this.bitoffset = 0;
36
44
  this.size = 0;
45
+ this.strict = false;
46
+ this.errorDump = true;
47
+ this.data = [];
37
48
  if (endianness != undefined && typeof endianness != "string") {
38
49
  throw new Error("Endian must be big or little");
39
50
  }
@@ -52,6 +63,14 @@ export class bireader {
52
63
  if (bitOffset != undefined) {
53
64
  this.bitoffset = bitOffset % 8;
54
65
  }
66
+ if (typeof strict == "boolean") {
67
+ this.strict = strict;
68
+ }
69
+ else {
70
+ if (strict != undefined) {
71
+ throw new Error("Strict mode must be true of false");
72
+ }
73
+ }
55
74
  if (data == undefined) {
56
75
  throw new Error("Data required");
57
76
  }
@@ -116,123 +135,98 @@ export class bireader {
116
135
  le() {
117
136
  this.endianness("little");
118
137
  }
138
+ //
139
+ // move from current position
140
+ //
119
141
  /**
120
- * Move current read byte or bit position
142
+ * Offset current byte or bit position
143
+ * Note: Will extend array if strict mode is off and outside of max size
121
144
  *
122
- * @param {number} bytes - bytes to skip
123
- * @param {number} bits - bits to skip
145
+ * @param {number} bytes - Bytes to skip
146
+ * @param {number} bits - Bits to skip (0-7)
124
147
  */
125
148
  skip(bytes, bits) {
126
- this.check_size(bytes || 0);
127
- if ((((bytes || 0) + this.offset) + Math.ceil((this.bitoffset + (bits || 0)) / 8)) > this.size) {
128
- throw new Error("Seek outside of size of data: " + this.size);
129
- }
130
- this.bitoffset += (bits || 0) % 8;
131
- this.offset += (bytes || 0);
149
+ return skip(this, bytes, bits);
132
150
  }
133
151
  /**
134
- * Move current read byte or bit position
152
+ * Offset current byte or bit position
153
+ * Note: Will extend array if strict mode is off and outside of max size
135
154
  *
136
- * @param {number} bytes - bytes to skip
137
- * @param {number} bits - bits to skip
155
+ * @param {number} bytes - Bytes to skip
156
+ * @param {number} bits - Bits to skip (0-7)
138
157
  */
139
- fskip(bytes, bits) {
158
+ jump(bytes, bits) {
140
159
  this.skip(bytes, bits);
141
160
  }
161
+ //
162
+ // directly set current position
163
+ //
142
164
  /**
143
- * Change current byte or bit read position
165
+ * Change position directly to address
166
+ * Note: Will extend array if strict mode is off and outside of max size
144
167
  *
145
- * @param {number} byte - byte to jump to
146
- * @param {number} bit - bit to jump to (0-7)
168
+ * @param {number} byte - byte to set to
169
+ * @param {number} bit - bit to set to (0-7)
147
170
  */
148
171
  goto(byte, bit) {
149
- if ((byte + Math.ceil((bit || 0) / 8)) > this.size) {
150
- throw new Error("Goto outside of size of data: " + this.size);
151
- }
152
- this.offset = byte;
153
- this.bitoffset = (bit || 0) % 8;
172
+ return goto(this, byte, bit);
154
173
  }
155
174
  /**
156
- * Change current byte or bit read position
175
+ * Change position directly to address
176
+ * Note: Will extend array if strict mode is off and outside of max size
157
177
  *
158
- * @param {number} byte - byte to jump to
159
- * @param {number} bit - bit to jump to (0-7)
178
+ * @param {number} byte - byte to set to
179
+ * @param {number} bit - bit to set to (0-7)
160
180
  */
161
181
  seek(byte, bit) {
162
- this.goto(byte, bit);
163
- }
164
- /**
165
- * Change current byte or bit read position
166
- *
167
- * @param {number} byte - byte to jump to
168
- * @param {number} bit - bit to jump to (0-7)
169
- */
170
- fseek(byte, bit) {
171
- this.goto(byte, bit);
182
+ return this.goto(byte, bit);
172
183
  }
173
184
  /**
174
- * Change current byte or bit read position
185
+ * Change position directly to address
186
+ * Note: Will extend array if strict mode is off and outside of max size
175
187
  *
176
- * @param {number} byte - byte to jump to
177
- * @param {number} bit - bit to jump to (0-7)
178
- */
179
- jump(byte, bit) {
180
- this.goto(byte, bit);
181
- }
182
- /**
183
- * Change current byte or bit read position
184
- *
185
- * @param {number} byte - byte to jump to
186
- * @param {number} bit - bit to jump to (0-7)
188
+ * @param {number} byte - byte to set to
189
+ * @param {number} bit - bit to set to (0-7)
187
190
  */
188
191
  pointer(byte, bit) {
189
- this.goto(byte, bit);
192
+ return this.goto(byte, bit);
190
193
  }
191
194
  /**
192
- * Change current byte or bit read position
195
+ * Change position directly to address
196
+ * Note: Will extend array if strict mode is off and outside of max size
193
197
  *
194
- * @param {number} byte - byte to jump to
195
- * @param {number} bit - bit to jump to (0-7)
198
+ * @param {number} byte - byte to set to
199
+ * @param {number} bit - bit to set to (0-7)
196
200
  */
197
201
  warp(byte, bit) {
198
- this.goto(byte, bit);
199
- }
200
- /**
201
- * Change current byte or bit read position
202
- *
203
- * @param {number} byte - byte to jump to
204
- * @param {number} bit - bit to jump to (0-7)
205
- */
206
- fsetpos(byte, bit) {
207
- this.goto(byte, bit);
202
+ return this.goto(byte, bit);
208
203
  }
204
+ //
205
+ //go to start
206
+ //
209
207
  /**
210
- * Set offset to start of file
208
+ * Set byte and bit position to start of data
211
209
  */
212
210
  rewind() {
213
211
  this.offset = 0;
214
212
  this.bitoffset = 0;
215
213
  }
216
214
  /**
217
- * Set offset to start of file
215
+ * Set byte and bit position to start of data
218
216
  */
219
217
  gotostart() {
220
218
  this.offset = 0;
221
219
  this.bitoffset = 0;
222
220
  }
223
- /**
224
- * Set offset to start of file
225
- */
226
- tostart() {
227
- this.offset = 0;
228
- this.bitoffset = 0;
229
- }
221
+ //
222
+ //get position
223
+ //
230
224
  /**
231
225
  * Get the current byte position
232
226
  *
233
227
  * @return {number} current byte position
234
228
  */
235
- ftell() {
229
+ tell() {
236
230
  return this.offset;
237
231
  }
238
232
  /**
@@ -240,7 +234,7 @@ export class bireader {
240
234
  *
241
235
  * @return {number} current byte position
242
236
  */
243
- tell() {
237
+ getOffset() {
244
238
  return this.offset;
245
239
  }
246
240
  /**
@@ -248,95 +242,204 @@ export class bireader {
248
242
  *
249
243
  * @return {number} current byte position
250
244
  */
251
- fgetpos() {
245
+ saveOffset() {
252
246
  return this.offset;
253
247
  }
248
+ //
249
+ //strict mode change
250
+ //
254
251
  /**
255
- * Get the current byte position
252
+ * Disallows extending data if position is outside of max size
253
+ */
254
+ restrict() {
255
+ this.strict = true;
256
+ }
257
+ /**
258
+ * Allows extending data if position is outside of max size
259
+ */
260
+ unrestrict() {
261
+ this.strict = false;
262
+ }
263
+ //
264
+ //remove part of data
265
+ //
266
+ /**
267
+ * Deletes part of data from start to current byte position unless supplied, returns removed
268
+ * Note: Errors in strict mode
256
269
  *
257
- * @return {number} current byte position
270
+ * @param {number} startOffset - Start location (default 0)
271
+ * @param {number} endOffset - End location (default current position)
272
+ * @param {boolean} consume - Move position to end of removed data (default false)
273
+ * @returns {Buffer|Uint8Array} Removed data as ``Buffer`` or ``Uint8Array``
258
274
  */
259
- saveOffset() {
260
- return this.offset;
275
+ delete(startOffset, endOffset, consume) {
276
+ return remove(this, startOffset || 0, endOffset || this.offset, consume || false, true);
261
277
  }
262
278
  /**
263
- * Truncates array from start to current position unless supplied
264
- * Note: Does not affect supplied data
265
- * @param {number} startOffset - Start location, default 0
266
- * @param {number} endOffset - end location, default current write position
267
- * @returns {Buffer|Uint8Array} ``Buffer`` or ``Uint8Array``
279
+ * Deletes part of data from start to current byte position unless supplied, returns removed
280
+ * Note: Errors in strict mode
281
+ *
282
+ * @param {number} startOffset - Start location (default 0)
283
+ * @param {number} endOffset - End location (default current position)
284
+ * @param {boolean} consume - Move position to end of removed data (default false)
285
+ * @returns {Buffer|Uint8Array} Removed data as ``Buffer`` or ``Uint8Array``
268
286
  */
269
- clip(startOffset, endOffset) {
270
- return this.data.slice(startOffset || 0, endOffset || this.offset);
287
+ clip(startOffset, endOffset, consume) {
288
+ return remove(this, startOffset || 0, endOffset || this.offset, consume || false, true);
271
289
  }
272
290
  /**
273
- * Truncates array from start to current position unless supplied
274
- * Note: Does not affect supplied data
275
- * @param {number} startOffset - Start location, default 0
276
- * @param {number} endOffset - end location, default current write position
277
- * @returns {Buffer|Uint8Array} ``Buffer`` or ``Uint8Array``
291
+ * Deletes part of data from current byte position to supplied length, returns removed
292
+ * Note: Errors in strict mode
293
+ *
294
+ * @param {number} length - Length of data in bytes to remove
295
+ * @param {boolean} consume - Move position to end of removed data (default false)
296
+ * @returns {Buffer|Uint8Array} Removed data as ``Buffer`` or ``Uint8Array``
278
297
  */
279
- crop(startOffset, endOffset) {
280
- return this.data.slice(startOffset || 0, endOffset || this.offset);
298
+ crop(length, consume) {
299
+ return remove(this, this.offset, this.offset + (length || 0), consume || false, true);
281
300
  }
282
301
  /**
283
- * Truncates array from start to current position unless supplied
284
- * Note: Does not affect supplied data
285
- * @param {number} startOffset - Start location, default 0
286
- * @param {number} endOffset - end location, default current write position
287
- * @returns {Buffer|Uint8Array} ``Buffer`` or ``Uint8Array``
302
+ * Deletes part of data from current position to supplied length, returns removed
303
+ * Note: Only works in strict mode
304
+ *
305
+ * @param {number} length - Length of data in bytes to remove
306
+ * @param {boolean} consume - Move position to end of removed data (default false)
307
+ * @returns {Buffer|Uint8Array} Removed data as ``Buffer`` or ``Uint8Array``
308
+ */
309
+ drop(length, consume) {
310
+ return remove(this, this.offset, this.offset + (length || 0), consume || false, true);
311
+ }
312
+ //
313
+ //copy out
314
+ //
315
+ /**
316
+ * Returns part of data from current byte position to end of data unless supplied
317
+ *
318
+ * @param {number} startOffset - Start location (default current position)
319
+ * @param {number} endOffset - End location (default end of data)
320
+ * @param {boolean} consume - Move position to end of lifted data (default false)
321
+ * @param {number} fillValue - Byte value to to fill returned data (does NOT fill unless supplied)
322
+ * @returns {Buffer|Uint8Array} Selected data as ```Uint8Array``` or ```Buffer```
288
323
  */
289
- truncate(startOffset, endOffset) {
290
- return this.data.slice(startOffset || 0, endOffset || this.offset);
324
+ lift(startOffset, endOffset, consume, fillValue) {
325
+ return remove(this, startOffset || this.offset, endOffset || this.size, consume || false, false, fillValue);
291
326
  }
292
327
  /**
293
- * Truncates array from start to current position unless supplied
294
- * Note: Does not affect supplied data
295
- * @param {number} startOffset - Start location, default 0
296
- * @param {number} endOffset - end location, default current write position
297
- * @returns {Buffer|Uint8Array} ``Buffer`` or ``Uint8Array``
328
+ * Returns part of data from current byte position to end of data unless supplied
329
+ *
330
+ * @param {number} startOffset - Start location (default current position)
331
+ * @param {number} endOffset - End location (default end of data)
332
+ * @param {boolean} consume - Move position to end of lifted data (default false)
333
+ * @param {number} fillValue - Byte value to to fill returned data (does NOT fill unless supplied)
334
+ * @returns {Buffer|Uint8Array} Selected data as ```Uint8Array``` or ```Buffer```
298
335
  */
299
- slice(startOffset, endOffset) {
300
- return this.data.slice(startOffset || 0, endOffset || this.offset);
336
+ fill(startOffset, endOffset, consume, fillValue) {
337
+ return remove(this, startOffset || this.offset, endOffset || this.size, consume || false, false, fillValue);
301
338
  }
302
339
  /**
303
- * Extract array from current position to length supplied
340
+ * Extract data from current position to length supplied
304
341
  * Note: Does not affect supplied data
305
- * @param {number} length - length of data to copy from current offset
306
- * @returns {Buffer|Uint8Array} ``Buffer`` or ``Uint8Array``
342
+ *
343
+ * @param {number} length - Length of data in bytes to copy from current offset
344
+ * @param {number} consume - Moves offset to end of length
345
+ * @returns {Buffer|Uint8Array} Selected data as ```Uint8Array``` or ```Buffer```
307
346
  */
308
- extract(length) {
309
- if (this.offset + (length || 0) > this.size) {
310
- throw new Error("End offset outside of data: " + this.size);
311
- }
312
- return this.data.slice(this.offset, this.offset + (length || 0));
347
+ extract(length, consume) {
348
+ return remove(this, this.offset, length || 0, consume || false, false);
313
349
  }
314
350
  /**
315
- * Extract array from current position to length supplied
351
+ * Extract data from current position to length supplied
316
352
  * Note: Does not affect supplied data
317
- * @param {number} length - length of data to copy from current offset
318
- * @returns {Buffer|Uint8Array} ``Buffer`` or ``Uint8Array``
353
+ *
354
+ * @param {number} length - Length of data in bytes to copy from current offset
355
+ * @param {number} consume - Moves offset to end of length
356
+ * @returns {Buffer|Uint8Array} Selected data as ```Uint8Array``` or ```Buffer```
319
357
  */
320
- wrap(length) {
321
- if (this.offset + (length || 0) > this.size) {
322
- throw new Error("End offset outside of data: " + this.size);
323
- }
324
- return this.data.slice(this.offset, this.offset + (length || 0));
358
+ slice(length, consume) {
359
+ return remove(this, this.offset, length || 0, consume || false, false);
325
360
  }
326
361
  /**
327
- * Extract array from current position to length supplied
362
+ * Extract data from current position to length supplied
328
363
  * Note: Does not affect supplied data
329
- * @param {number} length - length of data to copy from current offset
330
- * @returns {Buffer|Uint8Array} ``Buffer`` or ``Uint8Array``
364
+ *
365
+ * @param {number} length - Length of data in bytes to copy from current offset
366
+ * @param {number} consume - Moves offset to end of length
367
+ * @returns {Buffer|Uint8Array} Selected data as ```Uint8Array``` or ```Buffer```
331
368
  */
332
- lift(length) {
333
- if (this.offset + (length || 0) > this.size) {
334
- throw new Error("End offset outside of data: " + this.size);
335
- }
336
- return this.data.slice(this.offset, this.offset + (length || 0));
369
+ wrap(length, consume) {
370
+ return remove(this, this.offset, length || 0, consume || false, false);
371
+ }
372
+ //
373
+ //insert
374
+ //
375
+ /**
376
+ * Inserts data into data
377
+ * Note: Must be same data type as supplied data. Errors on strict mode.
378
+ *
379
+ * @param {Buffer|Uint8Array} data - ```Uint8Array``` or ```Buffer``` to add to data
380
+ * @param {boolean} consume - Move current write position to end of data (default false)
381
+ * @param {number} offset - Offset to add it at (defaults to current position)
382
+ */
383
+ insert(data, consume, offset) {
384
+ return addData(this, data, consume || false, offset || this.offset);
385
+ }
386
+ /**
387
+ * Inserts data into data
388
+ * Note: Must be same data type as supplied data. Errors on strict mode.
389
+ *
390
+ * @param {Buffer|Uint8Array} data - ```Uint8Array``` or ```Buffer``` to add to data
391
+ * @param {boolean} consume - Move current write position to end of data (default false)
392
+ * @param {number} offset - Offset to add it at (defaults to current position)
393
+ */
394
+ place(data, consume, offset) {
395
+ return addData(this, data, consume || false, offset || this.offset);
396
+ }
397
+ /**
398
+ * Adds data to start of supplied data
399
+ * Note: Must be same data type as supplied data. Errors on strict mode.
400
+ *
401
+ * @param {Buffer|Uint8Array} data - ```Uint8Array``` or ```Buffer``` to add to data
402
+ * @param {boolean} consume - Move current write position to end of data (default false)
403
+ */
404
+ unshift(data, consume) {
405
+ return addData(this, data, consume || false, 0);
337
406
  }
338
407
  /**
408
+ * Adds data to start of supplied data
409
+ * Note: Must be same data type as supplied data. Errors on strict mode.
410
+ *
411
+ * @param {Buffer|Uint8Array} data - ```Uint8Array``` or ```Buffer``` to add to data
412
+ * @param {boolean} consume - Move current write position to end of data (default false)
413
+ */
414
+ prepend(data, consume) {
415
+ return addData(this, data, consume || false, 0);
416
+ }
417
+ /**
418
+ * Adds data to end of supplied data
419
+ * Note: Must be same data type as supplied data. Errors on strict mode.
420
+ *
421
+ * @param {Buffer|Uint8Array} data - ```Uint8Array``` or ```Buffer``` to add to data
422
+ * @param {boolean} consume - Move current write position to end of data (default false)
423
+ */
424
+ push(data, consume) {
425
+ return addData(this, data, consume || false, this.size);
426
+ }
427
+ /**
428
+ * Adds data to end of supplied data
429
+ * Note: Must be same data type as supplied data. Errors on strict mode.
430
+ *
431
+ * @param {Buffer|Uint8Array} data - ```Uint8Array``` or ```Buffer``` to add to data
432
+ * @param {boolean} consume - Move current write position to end of data (default false)
433
+ */
434
+ append(data, consume) {
435
+ return addData(this, data, consume || false, this.size);
436
+ }
437
+ //
438
+ //finishing
439
+ //
440
+ /**
339
441
  * Returns current data
442
+ *
340
443
  * @returns {Buffer|Uint8Array} ``Buffer`` or ``Uint8Array``
341
444
  */
342
445
  get() {
@@ -344,34 +447,62 @@ export class bireader {
344
447
  }
345
448
  /**
346
449
  * Returns current data
450
+ *
347
451
  * @returns {Buffer|Uint8Array} ``Buffer`` or ``Uint8Array``
348
452
  */
349
453
  return() {
350
454
  return this.data;
351
455
  }
352
456
  /**
353
- * removes reading data
457
+ * removes data
354
458
  */
355
459
  end() {
356
- this.data = [];
460
+ this.data = undefined;
357
461
  }
358
462
  /**
359
- * removes reading data
463
+ * removes data
360
464
  */
361
465
  close() {
362
- this.data = [];
466
+ this.data = undefined;
363
467
  }
364
468
  /**
365
- * removes reading data
469
+ * removes data
366
470
  */
367
471
  done() {
368
- this.data = [];
472
+ this.data = undefined;
369
473
  }
370
474
  /**
371
- * removes reading data
475
+ * removes data
372
476
  */
373
477
  finished() {
374
- this.data = [];
478
+ this.data = undefined;
479
+ }
480
+ /**
481
+ * Console logs data as hex dump
482
+ *
483
+ * @param {object} options - options object
484
+ * ```javascript
485
+ * {
486
+ * length: 192, // number of bytes to log, default 192 or end of data
487
+ * startByte: 0, // byte to start dump, default current position
488
+ * supressUnicode: false // Supress unicode character preview for cleaner columns
489
+ * }
490
+ * ```
491
+ */
492
+ hexdump(options) {
493
+ return hexDump(this, options);
494
+ }
495
+ /**
496
+ * Turn hexdump on error off (default on)
497
+ */
498
+ errorDumpOff() {
499
+ this.errorDump = false;
500
+ }
501
+ /**
502
+ * Turn hexdump on error on (default on)
503
+ */
504
+ errorDumpOn() {
505
+ this.errorDump = true;
375
506
  }
376
507
  //
377
508
  //bit reader
@@ -395,6 +526,7 @@ export class bireader {
395
526
  }
396
527
  const size_needed = ((((bits - 1) + this.bitoffset) / 8) + this.offset);
397
528
  if (bits <= 0 || size_needed > this.size) {
529
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
398
530
  throw new Error("Invalid number of bits to read: " + size_needed + " of " + this.size);
399
531
  }
400
532
  var off_in_bits = (this.offset * 8) + this.bitoffset;
@@ -421,7 +553,7 @@ export class bireader {
421
553
  }
422
554
  this.offset = this.offset + Math.floor(((bits) + this.bitoffset) / 8); //end byte
423
555
  this.bitoffset = ((bits) + this.bitoffset) % 8;
424
- if (unsigned == true) {
556
+ if (unsigned == true || bits <= 7) {
425
557
  return value >>> 0;
426
558
  }
427
559
  if (bits !== 32 && value & (1 << (bits - 1))) {
@@ -443,13 +575,13 @@ export class bireader {
443
575
  return this.readBit(bits, unsigned, endian);
444
576
  }
445
577
  /**
446
- * Bit field reader
447
- *
448
- * Note: When returning to a byte read, remaining bits are dropped
449
- *
450
- * @param {boolean} unsigned - if the value is unsigned
451
- * @returns number
452
- */
578
+ * Bit field reader
579
+ *
580
+ * Note: When returning to a byte read, remaining bits are dropped
581
+ *
582
+ * @param {boolean} unsigned - if the value is unsigned
583
+ * @returns number
584
+ */
453
585
  bit1(unsigned) {
454
586
  return this.bit(1, unsigned);
455
587
  }
@@ -3729,6 +3861,7 @@ export class bireader {
3729
3861
  maxBytes = this.readInt32(true, endian);
3730
3862
  }
3731
3863
  else {
3864
+ this.errorDump ? "[Error], hexdump:\n" + this.hexdump() : "";
3732
3865
  throw new Error("Invalid length read size: " + lengthReadSize);
3733
3866
  }
3734
3867
  // Read the string as Pascal or Delphi encoded
@@ -3760,6 +3893,23 @@ export class bireader {
3760
3893
  throw new Error('Unsupported string type: ' + stringType);
3761
3894
  }
3762
3895
  }
3896
+ /**
3897
+ * Reads string, use options object for different types
3898
+ *
3899
+ * @param {object} options
3900
+ * ```javascript
3901
+ * {
3902
+ * length: number, //for fixed length, non-terminate value utf strings
3903
+ * stringType: "utf-8", //utf-8, utf-16, pascal or wide-pascal
3904
+ * terminateValue: 0x00, // only for non-fixed length utf strings
3905
+ * lengthReadSize: 1, //for pascal strings. 1, 2 or 4 byte length read size
3906
+ * stripNull: true, // removes 0x00 characters
3907
+ * encoding: "utf-8", //TextEncoder accepted types
3908
+ * endian: "little", //for wide-pascal and utf-16
3909
+ * }
3910
+ * ```
3911
+ * @return string
3912
+ */
3763
3913
  string(options) {
3764
3914
  return this.readString(options);
3765
3915
  }