1
0
Fork 0
mirror of https://github.com/codedread/bitjs synced 2025-10-04 10:09:16 +02:00

Added a getData() method to ByteBuffer.

This commit is contained in:
Jeff Schiller 2024-02-04 15:02:17 -08:00
parent 1852dc6509
commit abcf593d4f
5 changed files with 48 additions and 4 deletions

View file

@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file.
### Added ### Added
- archive: Support semantic methods for subscribing to unarchive events (onExtract), [Issue #47](https://github.com/codedread/bitjs/issues/47). - archive: Support semantic methods for subscribing to unarchive events (onExtract), [Issue #47](https://github.com/codedread/bitjs/issues/47).
- io: Added a getData() method to ByteBuffer to retrieve a copy of the bytes that have been written.
### Changed ### Changed

View file

@ -20,7 +20,7 @@ const BITMASK = [0, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF];
* *
* Bit reading always proceeds from the first byte in the buffer, to the * Bit reading always proceeds from the first byte in the buffer, to the
* second byte, and so on. The MTL flag controls which bit is considered * second byte, and so on. The MTL flag controls which bit is considered
* first *inside* the byte. * first *inside* the byte. The default is least-to-most direction.
* *
* An Example for how Most-To-Least vs Least-to-Most mode works: * An Example for how Most-To-Least vs Least-to-Most mode works:
* *

View file

@ -30,17 +30,31 @@ export class ByteBuffer {
this.data = new Uint8Array(numBytes); this.data = new Uint8Array(numBytes);
/** /**
* Points to the byte that will next be written.
* @type {number} * @type {number}
* @public * @public
*/ */
this.ptr = 0; this.ptr = 0;
} }
/**
* Returns an exact copy of all the data that has been written to the ByteBuffer.
* @returns {Uint8Array}
*/
getData() {
const dataCopy = new Uint8Array(this.ptr);
dataCopy.set(this.data.subarray(0, this.ptr));
return dataCopy;
}
/** /**
* @param {number} b The byte to insert. * @param {number} b The byte to insert.
*/ */
insertByte(b) { insertByte(b) {
if (this.ptr + 1 > this.data.byteLength) {
throw `Cannot insert a byte, the buffer is full.`;
}
// TODO: throw if byte is invalid? // TODO: throw if byte is invalid?
this.data[this.ptr++] = b; this.data[this.ptr++] = b;
} }
@ -49,6 +63,10 @@ export class ByteBuffer {
* @param {Array.<number>|Uint8Array|Int8Array} bytes The bytes to insert. * @param {Array.<number>|Uint8Array|Int8Array} bytes The bytes to insert.
*/ */
insertBytes(bytes) { insertBytes(bytes) {
if (this.ptr + bytes.length > this.data.byteLength) {
throw `Cannot insert ${bytes.length} bytes, the buffer is full.`;
}
// TODO: throw if bytes is invalid? // TODO: throw if bytes is invalid?
this.data.set(bytes, this.ptr); this.data.set(bytes, this.ptr);
this.ptr += bytes.length; this.ptr += bytes.length;

View file

@ -66,13 +66,13 @@ export class ByteStream {
this.littleEndian_ = true; this.littleEndian_ = true;
} }
/** @returns {boolean} Whether the stream is little-endian. */ /** @returns {boolean} Whether the stream is little-endian (least significant byte is first). */
isLittleEndian() { isLittleEndian() {
return this.littleEndian_; return this.littleEndian_;
} }
/** /**
* Big-Endian is sometimes called Motorola-style. * Big-Endian means the most significant byte is first. it is sometimes called Motorola-style.
* @param {boolean=} val The value to set. If not present, the stream is set to big-endian. * @param {boolean=} val The value to set. If not present, the stream is set to big-endian.
*/ */
setBigEndian(val = true) { setBigEndian(val = true) {
@ -80,7 +80,7 @@ export class ByteStream {
} }
/** /**
* Little-Endian is sometimes called Intel-style. * Little-Endian means the least significant byte is ifrst. is sometimes called Intel-style.
* @param {boolean=} val The value to set. If not present, the stream is set to little-endian. * @param {boolean=} val The value to set. If not present, the stream is set to little-endian.
*/ */
setLittleEndian(val = true) { setLittleEndian(val = true) {

View file

@ -18,10 +18,35 @@ describe('bitjs.io.ByteBuffer', () => {
buffer = new ByteBuffer(4); buffer = new ByteBuffer(4);
}); });
describe('getData()', () => {
it('returns an empty array when nothing has been written', () => {
expect(buffer.getData().byteLength).equals(0);
});
it('is sized correctly', () => {
buffer.insertByte(42);
buffer.insertByte(81);
const data = buffer.getData();
expect(data.byteLength).equals(2);
expect(data[0]).equals(42);
expect(data[1]).equals(81);
});
});
it('throws when initialized incorrectly', () => { it('throws when initialized incorrectly', () => {
expect(() => new ByteBuffer()).throws(); expect(() => new ByteBuffer()).throws();
}); });
describe('Buffer overflow', () => {
it('insertByte() throws when buffer exceeded', () => {
buffer.insertBytes([0, 2, 4, 6]);
expect(() => buffer.insertByte(1)).throws();
});
it('insertBytes() throws when buffer exceeded', () => {
expect(() => buffer.insertBytes([0, 2, 4, 6, 8])).throws();
});
});
it('insertByte()', () => { it('insertByte()', () => {
buffer.insertByte(192); buffer.insertByte(192);
expect(buffer.ptr).equals(1); expect(buffer.ptr).equals(1);