@adguard/agtree
Version:
Tool set for working with adblock filter lists
92 lines (90 loc) • 3.64 kB
JavaScript
/*
* AGTree v3.4.3 (build date: Thu, 11 Dec 2025 13:43:19 GMT)
* (c) 2025 Adguard Software Ltd.
* Released under the MIT license
* https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme
*/
/* eslint-disable no-bitwise */
/**
* @file Core ByteBuffer implementation for handling binary data in chunks.
*/
/**
* Core ByteBuffer implementation for handling binary data in chunks.
* This class allows for efficient byte storage and manipulation by organizing data into chunks
* and providing methods to read and write bytes.
*/
class ByteBuffer {
/**
* The size of each chunk in bytes (32 KB).
*/
// ! IMPORTANT: If you ever change this value, make sure to update optimized bitwise operations in the code.
static CHUNK_SIZE = 32768; // 32 * 1024
/**
* An array of Uint8Array chunks that make up the buffer.
*/
chunks;
/**
* The total number of chunks in the buffer.
*/
chunksLength;
/**
* Constructs a new ByteBuffer instance.
*
* @param chunks Optional array of chunks to initialize the ByteBuffer with.
* @param cloneChunks Flag indicating if the chunks should be cloned. For performance reasons,
* its default value is `false`. If the original chunks are guaranteed not to change,
* leave this flag as `false` to avoid unnecessary copying.
*/
constructor(chunks, cloneChunks = false) {
const chunksToUse = chunks ?? [];
this.chunks = cloneChunks ? chunksToUse.map((chunk) => new Uint8Array(chunk)) : chunksToUse;
this.chunksLength = chunks?.length ?? 0;
}
/**
* Ensures that the buffer has enough capacity to accommodate a given position.
* This method adjusts the `chunks` array size to ensure it can hold the specified position.
*
* @param position The position to ensure capacity for.
*/
ensureCapacity(position) {
// same as Math.floor(position / chunk size), just optimized for the 32 KB chunk size
const requiredChunkIndex = position >>> 0x000F;
for (let i = this.chunksLength; i <= requiredChunkIndex; i += 1) {
this.chunks.push(new Uint8Array(ByteBuffer.CHUNK_SIZE));
this.chunksLength += 1;
}
}
/**
* Writes a byte to the buffer at the specified position.
* If the position is outside of the buffer's current size, the buffer is resized to accommodate it.
*
* @param position The position at which to write the byte.
* @param value The byte value to write (0-255).
*/
writeByte(position, value) {
// same as Math.floor(position / chunk size), just optimized for the 32 KB chunk size
const chunkIndex = position >>> 0x000F;
// same as position % chunk size, just optimized for the 32 KB chunk size
const chunkOffset = position & 0x7FFF;
if (chunkIndex >= this.chunksLength) {
this.ensureCapacity(position);
}
this.chunks[chunkIndex][chunkOffset] = value;
}
/**
* Reads a byte from the specified position in the buffer.
* Returns `undefined` if the position is outside of the buffer's current size.
*
* @param position The position from which to read the byte.
* @returns The read byte value, or `undefined` if the position is out of bounds.
*/
readByte(position) {
const chunkIndex = position >>> 0x000F;
const chunkOffset = position & 0x7FFF;
if (chunkIndex >= this.chunksLength) {
return undefined;
}
return this.chunks[chunkIndex][chunkOffset];
}
}
export { ByteBuffer };