mirror of
https://github.com/ThatGuySam/doesitarm.git
synced 2026-05-15 06:35:20 -07:00
429 lines
13 KiB
JavaScript
429 lines
13 KiB
JavaScript
//memory.js
|
|
//Written by Sem Voigtländer
|
|
//Licensed under the MIT License
|
|
|
|
/*
|
|
Functionality for geting the memory size of a javascript object
|
|
*/
|
|
|
|
export function free(objectName)
|
|
{
|
|
if(eval(objectName) != 'undefined')
|
|
{
|
|
console.log('Helping the garbage collector a little bit with freeing.');
|
|
eval(objectName + '=undefined;');
|
|
}
|
|
}
|
|
|
|
export function sizeof(object) {
|
|
|
|
var objectList = [];
|
|
var stack = [object];
|
|
var bytes = 0;
|
|
|
|
while (stack.length) {
|
|
var value = stack.pop();
|
|
|
|
if (typeof value === 'boolean') {
|
|
bytes += 4;
|
|
} else if (typeof value === 'string') {
|
|
bytes += value.length * 2;
|
|
} else if (typeof value === 'number') {
|
|
bytes += 8;
|
|
} else if (
|
|
typeof value === 'object' &&
|
|
objectList.indexOf(value) === -1
|
|
) {
|
|
objectList.push(value);
|
|
|
|
for (var i in value) {
|
|
stack.push(value[i]);
|
|
}
|
|
}
|
|
}
|
|
return bytes;
|
|
}
|
|
|
|
/*
|
|
Functions for swapping the endianness of an integer
|
|
Supports 16, 32 and 64 bit integers. (Experimental 128-bits as well)
|
|
Smaller integers are automatically casted to the corresponding size.
|
|
Bigger integers are not casted to smaller integers as they may lose precision.
|
|
*/
|
|
|
|
export function SwapEndian16(integer) {
|
|
|
|
var _hex = '0';
|
|
var _output = '';
|
|
|
|
//Input validation
|
|
if(typeof integer !== 'number')
|
|
throw new Error('Invalid argument. argument provided is not an integer.');
|
|
if(integer < 0)
|
|
throw new Error('Invalid argument. argument provided may not be negative.');
|
|
|
|
_hex = integer.toString(16); //Conver the input to a hexadecimal string
|
|
|
|
//Conver the hexadecimal string to a 16-bit integer hexadecimal string
|
|
while(_hex.length < 4)
|
|
_hex = '0'+_hex;
|
|
|
|
let _arr = _hex.split(''); //Convert the 16-bit integer hexadecimal string to a char array
|
|
|
|
//Sanity check
|
|
if (_arr.length != 4)
|
|
throw new Error('Invalid argument. argument provided is not a 16-bit integer.');
|
|
|
|
|
|
//Swap the endianness
|
|
_output += (_arr[2] + _arr[3]).toString();
|
|
_output += (_arr[0] + _arr[1]).toString();
|
|
|
|
//Output sanity check
|
|
if(_output.length != 4)
|
|
throw new Error('Sanity check failed. Output is not a 16-bit integer');
|
|
|
|
_output = parseInt('0x'+_output); //convert the hexadecimal output string to an integer
|
|
|
|
//Conversion sanity check
|
|
if(_output === NaN)
|
|
throw new Error('Conversion from a hexadecimal string to an integer failed.');
|
|
|
|
return _output;
|
|
}
|
|
|
|
export function SwapEndian32(integer) {
|
|
|
|
var _hex = '0';
|
|
var _output = '';
|
|
|
|
//Input validation
|
|
if(typeof integer !== 'number')
|
|
throw new Error('Invalid argument. argument provided is not an integer.');
|
|
if(integer < 0)
|
|
throw new Error('Invalid argument. argument provided may not be negative.');
|
|
|
|
_hex = integer.toString(16); //Conver the input to a hexadecimal string
|
|
|
|
//Conver the hexadecimal string to a 32-bit integer hexadecimal string
|
|
while(_hex.length < 8)
|
|
_hex = '0'+_hex;
|
|
|
|
let _arr = _hex.split(''); //Convert the 32-bit integer hexadecimal string to a char array
|
|
|
|
//Sanity check
|
|
if (_arr.length != 8)
|
|
throw new Error('Invalid argument. argument provided is not a 32-bit integer.');
|
|
|
|
|
|
//Swap the endianness
|
|
_output += (_arr[6] + _arr[7]).toString();
|
|
_output += (_arr[4] + _arr[5]).toString();
|
|
_output += (_arr[2] + _arr[3]).toString();
|
|
_output += (_arr[0] + _arr[1]).toString();
|
|
|
|
//Output sanity check
|
|
if(_output.length != 8)
|
|
throw new Error('Sanity check failed. Output is not a 32-bit integer');
|
|
|
|
_output = parseInt('0x'+_output); //convert the hexadecimal output string to an integer
|
|
|
|
//Conversion sanity check
|
|
if(_output === NaN)
|
|
throw new Error('Conversion from a hexadecimal string to an integer failed.');
|
|
|
|
//Lets help javascripts garbage collector a bit
|
|
_arr = undefined;
|
|
_hex = undefined;
|
|
|
|
return _output;
|
|
}
|
|
|
|
export function SwapEndian64(integer) {
|
|
|
|
var _hex = '0';
|
|
var _output = '';
|
|
|
|
//Input validation
|
|
if(typeof integer !== 'number')
|
|
throw new Error('Invalid argument. argument provided is not an integer.');
|
|
if(integer < 0)
|
|
throw new Error('Invalid argument. argument provided may not be negative.');
|
|
|
|
_hex = integer.toString(16); //Conver the input to a hexadecimal string
|
|
|
|
//Conver the hexadecimal string to a 64-bit integer hexadecimal string
|
|
while(_hex.length < 16)
|
|
_hex = '0'+_hex;
|
|
|
|
let _arr = _hex.split(''); //Convert the 64-bit integer hexadecimal string to a char array
|
|
|
|
//Sanity check
|
|
if (_arr.length != 16)
|
|
throw new Error('Invalid argument. argument provided is not a 64-bit integer.');
|
|
|
|
|
|
//Swap the endianness
|
|
_output += (_arr[14] + _arr[15]).toString();
|
|
_output += (_arr[12] + _arr[13]).toString();
|
|
_output += (_arr[10] + _arr[11]).toString();
|
|
_output += (_arr[8] + _arr[9]).toString();
|
|
_output += (_arr[6] + _arr[7]).toString();
|
|
_output += (_arr[4] + _arr[5]).toString();
|
|
_output += (_arr[2] + _arr[3]).toString();
|
|
_output += (_arr[0] + _arr[1]).toString();
|
|
|
|
//Output sanity check
|
|
if(_output.length != 16)
|
|
throw new Error('Sanity check failed. Output is not a 64-bit integer');
|
|
|
|
_output = parseInt('0x'+_output); //convert the hexadecimal output string to an integer
|
|
|
|
//Conversion sanity check
|
|
if(_output === NaN)
|
|
throw new Error('Conversion from a hexadecimal string to an integer failed.');
|
|
|
|
//Lets help javascripts garbage collector a bit
|
|
_arr = undefined;
|
|
_hex = undefined;
|
|
|
|
return _output;
|
|
}
|
|
|
|
export function SwapEndian128(integer) {
|
|
|
|
var _hex = '0';
|
|
var _output = '';
|
|
|
|
//Input validation
|
|
if(typeof integer !== 'number')
|
|
throw new Error('Invalid argument. argument provided is not an integer.');
|
|
if(integer < 0)
|
|
throw new Error('Invalid argument. argument provided may not be negative.');
|
|
|
|
_hex = integer.toString(16); //Conver the input to a hexadecimal string
|
|
|
|
//Conver the hexadecimal string to a 128-bit integer hexadecimal string
|
|
while(_hex.length < 32)
|
|
_hex = '0'+_hex;
|
|
|
|
let _arr = _hex.split(''); //Convert the 128-bit integer hexadecimal string to a char array
|
|
|
|
//Sanity check
|
|
if (_arr.length != 32)
|
|
throw new Error('Invalid argument. argument provided is not a 128-bit integer.');
|
|
|
|
|
|
//Swap the endianness
|
|
_output += (_arr[30] + _arr[31]).toString();
|
|
_output += (_arr[28] + _arr[29]).toString();
|
|
_output += (_arr[26] + _arr[27]).toString();
|
|
_output += (_arr[24] + _arr[25]).toString();
|
|
_output += (_arr[22] + _arr[23]).toString();
|
|
_output += (_arr[20] + _arr[21]).toString();
|
|
_output += (_arr[18] + _arr[19]).toString();
|
|
_output += (_arr[16] + _arr[17]).toString();
|
|
_output += (_arr[14] + _arr[15]).toString();
|
|
_output += (_arr[12] + _arr[13]).toString();
|
|
_output += (_arr[10] + _arr[11]).toString();
|
|
_output += (_arr[8] + _arr[9]).toString();
|
|
_output += (_arr[6] + _arr[7]).toString();
|
|
_output += (_arr[4] + _arr[5]).toString();
|
|
_output += (_arr[2] + _arr[3]).toString();
|
|
_output += (_arr[0] + _arr[1]).toString();
|
|
|
|
//Output sanity check
|
|
if(_output.length != 32)
|
|
throw new Error('Sanity check failed. Output is not a 128-bit integer');
|
|
|
|
_output = parseInt('0x'+_output); //convert the hexadecimal output string to an integer
|
|
|
|
//Conversion sanity check
|
|
if(_output === NaN)
|
|
throw new Error('Conversion from a hexadecimal string to an integer failed.');
|
|
|
|
//Lets help javascripts garbage collector a bit
|
|
_arr = undefined;
|
|
_hex = undefined;
|
|
|
|
return _output;
|
|
}
|
|
|
|
|
|
/*
|
|
Functions for reading integers from a given offset in a given array.
|
|
Supports 16, 32 and 64 bit integers. (Experimental 128-bits as well)
|
|
It also supports reading with a different Endianness.
|
|
|
|
*/
|
|
|
|
//Big Endian
|
|
export function ReadUint16(arr, off) {
|
|
|
|
if(arr.length < 2 || off > arr.length) //sanity check
|
|
throw new Error('Cannot read OOB.');
|
|
|
|
return parseInt("0x" +
|
|
arr[off].toString(16) +
|
|
arr[off + 1].toString(16)
|
|
);
|
|
}
|
|
|
|
export function ReadUint32(arr, off) {
|
|
|
|
if(arr.length < 4 || off > arr.length) //sanity check
|
|
throw new Error('Cannot read OOB.');
|
|
|
|
return parseInt("0x" +
|
|
arr[off].toString(16) +
|
|
arr[off + 1].toString(16) +
|
|
arr[off + 2].toString(16) +
|
|
arr[off + 3].toString(16)
|
|
);
|
|
}
|
|
|
|
export function ReadUint64(arr, off) {
|
|
|
|
if(arr.length < 8 || off > arr.length) //sanity check
|
|
throw new Error('Cannot read OOB.');
|
|
|
|
return parseInt("0x" +
|
|
arr[off].toString(16) +
|
|
arr[off + 1].toString(16) +
|
|
arr[off + 2].toString(16) +
|
|
arr[off + 3].toString(16) +
|
|
arr[off + 4].toString(16) +
|
|
arr[off + 5].toString(16) +
|
|
arr[off + 6].toString(16) +
|
|
arr[off + 7].toString(16)
|
|
);
|
|
}
|
|
|
|
export function ReadUint128(arr, off) {
|
|
|
|
if(arr.length < 16 || off > arr.length) //sanity check
|
|
throw new Error('Cannot read OOB.');
|
|
|
|
return parseInt("0x" +
|
|
arr[off].toString(16) +
|
|
arr[off + 1].toString(16) +
|
|
arr[off + 2].toString(16) +
|
|
arr[off + 3].toString(16) +
|
|
arr[off + 4].toString(16) +
|
|
arr[off + 5].toString(16) +
|
|
arr[off + 6].toString(16) +
|
|
arr[off + 7].toString(16) +
|
|
arr[off + 8].toString(16) +
|
|
arr[off + 9].toString(16) +
|
|
arr[off + 10].toString(16) +
|
|
arr[off + 11].toString(16) +
|
|
arr[off + 12].toString(16) +
|
|
arr[off + 13].toString(16) +
|
|
arr[off + 14].toString(16) +
|
|
arr[off + 15].toString(16)
|
|
);
|
|
}
|
|
|
|
//Little Endian
|
|
export function ReadUint16LE(arr, off) {
|
|
|
|
if(arr.length < 2 || off > arr.length) //sanity check
|
|
throw new Error('Cannot read OOB.');
|
|
|
|
return parseInt("0x" +
|
|
arr[off + 1].toString(16) +
|
|
arr[off].toString(16)
|
|
);
|
|
}
|
|
|
|
export function ReadUint32LE(arr, off) {
|
|
if(arr.length < 4 || off > arr.length) //sanity check
|
|
throw new Error('Cannot read OOB.');
|
|
|
|
return parseInt("0x" +
|
|
arr[off + 3].toString(16) +
|
|
arr[off + 2].toString(16) +
|
|
arr[off + 1].toString(16) +
|
|
arr[off].toString(16)
|
|
);
|
|
}
|
|
|
|
export function ReadUint64LE(arr, off) {
|
|
|
|
if(arr.length < 8 || off > arr.length) //sanity check
|
|
throw new Error('Cannot read OOB.');
|
|
|
|
return parseInt("0x" +
|
|
arr[off + 7].toString(16) +
|
|
arr[off + 6].toString(16) +
|
|
arr[off + 5].toString(16) +
|
|
arr[off + 4].toString(16) +
|
|
arr[off + 3].toString(16) +
|
|
arr[off + 2].toString(16) +
|
|
arr[off + 1].toString(16) +
|
|
arr[off].toString(16)
|
|
);
|
|
}
|
|
|
|
export function ReadUint128LE(arr, off) {
|
|
|
|
if(arr.length < 16 || off > arr.length) //sanity check
|
|
throw new Error('Cannot read OOB.');
|
|
|
|
return parseInt("0x" +
|
|
arr[off + 15].toString(16) +
|
|
arr[off + 14].toString(16) +
|
|
arr[off + 13].toString(16) +
|
|
arr[off + 12].toString(16) +
|
|
arr[off + 11].toString(16) +
|
|
arr[off + 10].toString(16) +
|
|
arr[off + 9].toString(16) +
|
|
arr[off + 8].toString(16) +
|
|
arr[off + 7].toString(16) +
|
|
arr[off + 6].toString(16) +
|
|
arr[off + 5].toString(16) +
|
|
arr[off + 4].toString(16) +
|
|
arr[off + 3].toString(16) +
|
|
arr[off + 2].toString(16) +
|
|
arr[off + 1].toString(16) +
|
|
arr[off].toString(16)
|
|
);
|
|
}
|
|
|
|
export function writeUint8(arr, off, val) {
|
|
if(arr.length < 2 || off > arr.length || off < 0) {
|
|
throw new Error('Cannot write OOB.');
|
|
}
|
|
|
|
|
|
if(val.length > 0xff)
|
|
throw new Error('Invalid argument. This should be a valid 8-bit integer.');
|
|
let old = arr[off];
|
|
arr[off] = val;
|
|
}
|
|
|
|
export function writeUint16(arr, off, val) {
|
|
if(arr.length < 4 || off > arr.length || off < 0) { //We should never underflow or overflow our buffer
|
|
throw new Error('Cannot write OOB.');
|
|
}
|
|
|
|
|
|
if(val.length > 0xffff) //Values that after serialization never will be a 16 bit integer should never be treated
|
|
throw new Error('Invalid argument. This should be a valid 16-bit integer.');
|
|
|
|
let old = new Array(arr[off], arr[off+1]);
|
|
|
|
if(val <= 0xff) { //Integers below 256 are always valid
|
|
arr[off] = val;
|
|
|
|
} else if(val > 0xff && val <= 0xfff) { //Integers bigger than 256 but below 4096 should be treated as two bytes instead of one and fixed with a leading zero
|
|
arr[off] = parseInt('0x'+(val.toString(16).split('')[0] + val.toString(16).split('')[1]));
|
|
arr[off+1] = parseInt('0x0'+val.toString(16).split('')[2]);
|
|
|
|
} else if(val > 0xff && val <= 0xffff) { //Integers bigger than 256 and below 65535 should be treated as two bytes and can be splitted without having to fix them with a leading zero
|
|
arr[off] = parseInt('0x'+(val.toString(16).split('')[0] + val.toString(16).split('')[1]));
|
|
arr[off+1] = parseInt('0x'+val.toString(16).split('')[2] + val.toString(16).split('')[3]);
|
|
|
|
}
|
|
|
|
}
|