xcom2charpool
Version:
Library for reading, manipulating, and managing XCOM 2 character pool binary files, supporting both browser and Node.js environments.
153 lines (152 loc) • 7.7 kB
JavaScript
"use strict";
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var _ArrayBufferWriter_length, _ArrayBufferWriter_buffer, _ArrayBufferWriter_dataView;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ArrayBufferWriter = void 0;
/** Implementation based on browser's DataView */
class ArrayBufferWriter {
constructor(initialSize = 1024) {
this.position = 0;
_ArrayBufferWriter_length.set(this, 0); // Actual length of data written
_ArrayBufferWriter_buffer.set(this, void 0);
_ArrayBufferWriter_dataView.set(this, void 0);
__classPrivateFieldSet(this, _ArrayBufferWriter_buffer, new ArrayBuffer(initialSize), "f");
__classPrivateFieldSet(this, _ArrayBufferWriter_dataView, new DataView(__classPrivateFieldGet(this, _ArrayBufferWriter_buffer, "f")), "f");
}
/**
* Ensures the internal buffer has enough capacity to write additional bytes.
*/
ensureCapacity(additionalBytes) {
const requiredLength = this.position + additionalBytes;
if (requiredLength > __classPrivateFieldGet(this, _ArrayBufferWriter_buffer, "f").byteLength) {
// Need to resize buffer
let newBufferLength = __classPrivateFieldGet(this, _ArrayBufferWriter_buffer, "f").byteLength * 2;
while (newBufferLength < requiredLength) {
newBufferLength *= 2;
}
const newBuffer = new ArrayBuffer(newBufferLength);
new Uint8Array(newBuffer).set(new Uint8Array(__classPrivateFieldGet(this, _ArrayBufferWriter_buffer, "f")));
__classPrivateFieldSet(this, _ArrayBufferWriter_buffer, newBuffer, "f");
__classPrivateFieldSet(this, _ArrayBufferWriter_dataView, new DataView(__classPrivateFieldGet(this, _ArrayBufferWriter_buffer, "f")), "f");
}
}
/**
* Writes a 32-bit unsigned integer at the current position.
*/
uint32(value) {
this.ensureCapacity(4);
__classPrivateFieldGet(this, _ArrayBufferWriter_dataView, "f").setUint32(this.position, value, true);
this.position += 4;
__classPrivateFieldSet(this, _ArrayBufferWriter_length, Math.max(__classPrivateFieldGet(this, _ArrayBufferWriter_length, "f"), this.position), "f");
return this;
}
/**
* Writes a 32-bit signed integer at the current position.
*/
int32(value) {
this.ensureCapacity(4);
__classPrivateFieldGet(this, _ArrayBufferWriter_dataView, "f").setInt32(this.position, value, true);
this.position += 4;
__classPrivateFieldSet(this, _ArrayBufferWriter_length, Math.max(__classPrivateFieldGet(this, _ArrayBufferWriter_length, "f"), this.position), "f");
return this;
}
/**
* Writes a byte at the current position.
*/
byte(value) {
this.ensureCapacity(1);
__classPrivateFieldGet(this, _ArrayBufferWriter_dataView, "f").setUint8(this.position, value);
this.position += 1;
__classPrivateFieldSet(this, _ArrayBufferWriter_length, Math.max(__classPrivateFieldGet(this, _ArrayBufferWriter_length, "f"), this.position), "f");
return this;
}
/**
* Writes padding (4 zero bytes) at the current position.
*/
padding() {
this.uint32(0);
return this;
}
/**
* Encodes a string into a Uint8Array using UTF-16LE encoding.
*/
encodeUTF16LE(str) {
const buf = new ArrayBuffer(str.length * 2);
const bufView = new Uint16Array(buf);
for (let i = 0; i < str.length; i++) {
bufView[i] = str.charCodeAt(i);
}
return new Uint8Array(buf);
}
encodeASCII(str) {
const buf = new ArrayBuffer(str.length);
const bufView = new Uint8Array(buf);
for (let i = 0; i < str.length; i++) {
bufView[i] = str.charCodeAt(i);
}
return bufView;
}
/**
* Writes a string with a length prefix and null-termination.
* Automatically detects the encoding based on the characters used.
* Uses UTF-8 for ASCII strings and UTF-16LE for strings with non-ASCII characters.
*/
string(value) {
if (value === '') {
this.int32(0);
return this;
}
// Detect if the string contains any non-ASCII characters
// eslint-disable-next-line no-control-regex
const isAscii = /^[\x00-\xFF]*$/.test(value);
let encoded;
if (isAscii) {
// Use UTF-8 encoding
encoded = this.encodeASCII(value);
// Add null terminator
const totalLength = encoded.length + 1;
this.int32(totalLength);
this.ensureCapacity(totalLength);
const targetArray = new Uint8Array(__classPrivateFieldGet(this, _ArrayBufferWriter_buffer, "f"), this.position, totalLength);
targetArray.set(encoded);
targetArray[encoded.length] = 0x00; // null terminator
this.position += totalLength;
__classPrivateFieldSet(this, _ArrayBufferWriter_length, Math.max(__classPrivateFieldGet(this, _ArrayBufferWriter_length, "f"), this.position), "f");
}
else {
// Use UTF-16LE encoding
encoded = this.encodeUTF16LE(value);
// Add null terminator (two bytes)
const totalLength = encoded.length + 2;
const lengthPrefix = -((encoded.length + 2) / 2); // Negative length in number of 16-bit code units
this.int32(lengthPrefix);
this.ensureCapacity(totalLength);
const targetArray = new Uint8Array(__classPrivateFieldGet(this, _ArrayBufferWriter_buffer, "f"), this.position, totalLength);
targetArray.set(encoded);
targetArray[encoded.length] = 0x00; // null terminator (low byte)
targetArray[encoded.length + 1] = 0x00; // null terminator (high byte)
this.position += totalLength;
__classPrivateFieldSet(this, _ArrayBufferWriter_length, Math.max(__classPrivateFieldGet(this, _ArrayBufferWriter_length, "f"), this.position), "f");
}
return this;
}
/**
* Retrieves the underlying buffer up to the current length of data written.
* @returns A sliced ArrayBuffer containing the written data.
*/
getBuffer() {
return __classPrivateFieldGet(this, _ArrayBufferWriter_buffer, "f").slice(0, __classPrivateFieldGet(this, _ArrayBufferWriter_length, "f"));
}
}
exports.ArrayBufferWriter = ArrayBufferWriter;
_ArrayBufferWriter_length = new WeakMap(), _ArrayBufferWriter_buffer = new WeakMap(), _ArrayBufferWriter_dataView = new WeakMap();