cos/memory.js

364 lines
8.8 KiB
JavaScript

class ProcessableData {
constructor(data, from = 0, to){
if(data){
this.data = data;
this.init(from, to);
}
}
/** @type {Uint8Array} */
data = null;
/** @type {DataView} */
dt = null;
/** @type {number} */
cursor = 0;
/**
* @param {number} from
* @param {number} to
*/
init(from, to){
if(this.data == null)
{
this.data = new Uint8Array(1024 * 1024);
}
this.dt = new DataView(this.data.buffer, from, to);
}
/** @param {number} value */
writeUInt8(value){
this.dt.setUint8(this.cursor,value);
this.cursor += 1;
}
/** @param {number} value */
writeUInt16(value){
this.dt.setUint16(this.cursor,value);
this.cursor += 2;
}
/** @param {number} value */
writeUInt32(value){
this.dt.setUint32(this.cursor,value);
this.cursor += 4;
}
/** @param {number} value */
writeInt8(value){
this.dt.setInt8(this.cursor,value);
this.cursor += 1;
}
/** @param {number} value */
writeInt16(value){
this.dt.setInt16(this.cursor,value);
this.cursor += 2;
}
/** @param {number} value */
writeInt32(value){
this.dt.setInt32(this.cursor,value);
this.cursor += 4;
}
/** @param {number} value */
writeFloat32(value){
this.dt.setFloat32(this.cursor,value);
this.cursor += 4;
}
/** @param {number} value */
writeFloat64(value){
this.dt.setFloat64(this.cursor,value);
this.cursor += 8;
}
/** @returns {number} */
readUInt8(){
let value = this.dt.getUint8(this.cursor);
this.cursor += 1;
return value;
}
/** @returns {number} */
readUInt16(){
let value = this.dt.getUint16(this.cursor);
this.cursor += 2;
return value;
}
/** @returns {number} */
readUInt32(){
let value = this.dt.getUint32(this.cursor);
this.cursor += 4;
return value;
}
/** @returns {number} */
readInt8(){
let value = this.dt.getInt8(this.cursor);
this.cursor += 1;
return value;
}
/** @returns {number} */
readInt16(){
let value = this.dt.getInt16(this.cursor);
this.cursor += 2;
return value;
}
/** @returns {number} */
readInt32(){
let value = this.dt.getInt32(this.cursor);
this.cursor += 4;
return value;
}
/** @returns {number} */
readFloat32(){
let value = this.dt.getFloat32(this.cursor);
this.cursor += 4;
return value;
}
/** @returns {number} */
readFloat64(){
let value = this.dt.getFloat64(this.cursor);
this.cursor += 8;
return value;
}
getAllData(){
return this.dt.buffer.slice(0, this.cursor);
}
}
class ConstructedData extends ProcessableData {
/** @param {string} value */
writeString(value){
let encodedText = new TextEncoder().encode(value);
for (const byte of encodedText)
{
this.writeUInt8(byte);
}
}
/**
* @param {number} value
* @returns {string}
*/
readString(size){
let minibuffer = this.data.buffer.slice(this.cursor, this.cursor + size);
return new TextDecoder().decode(minibuffer);
}
/**
* @param {boolean|0|1} flag1
* @param {boolean|0|1} flag2
* @param {boolean|0|1} flag3
* @param {boolean|0|1} flag4
* @param {boolean|0|1} flag5
* @param {boolean|0|1} flag6
* @param {boolean|0|1} flag7
* @param {boolean|0|1} flag8
*/
writeFlags(flag1, flag2, flag3, flag4, flag5, flag6, flag7, flag8){
let value = (
(flag1 << 1) |
(flag2 << 2) |
(flag3 << 3) |
(flag4 << 4) |
(flag5 << 5) |
(flag6 << 6) |
(flag7 << 7) |
(flag8 << 8)
);
this.writeUInt8(value);
}
/** @returns {number[]} */
readFlags(){
let value = this.readUInt8();
let result = (
(value >> 0 & 0x1),
(value >> 1 & 0x1),
(value >> 2 & 0x1),
(value >> 3 & 0x1),
(value >> 4 & 0x1),
(value >> 5 & 0x1),
(value >> 6 & 0x1),
(value >> 7 & 0x1)
);
return result;
}
/**
* @param {number} r
* @param {number} g
* @param {number} b
*/
writeRGB(r,g,b){
this.writeUInt8(r);
this.writeUInt8(g);
this.writeUInt8(b);
}
/** @returns {{r:number,g:number,b:number}} */
readRGB(){
return {
r: this.readUInt8(),
g: this.readUInt8(),
b: this.readUInt8()
}
}
/**
* @param {number} r
* @param {number} g
* @param {number} b
*/
writeRGBA(r,g,b,a){
this.writeUInt8(r);
this.writeUInt8(g);
this.writeUInt8(b);
this.writeUInt8(a);
}
/** @returns {{r:number,g:number,b:number,a:number}} */
readRGBA(){
return {
r: this.readUInt8(),
g: this.readUInt8(),
b: this.readUInt8(),
a: this.readUInt8()
}
}
/** @param {number} size */
writeVarNumber(size){
let iszero = false;
let isInt = Number.isInteger(size);
let is1Byte = false;
let is2Byte = false;
let is4Byte = false;
let is8Byte = false;
let issigned = false;
issigned = size < 0;
if(isInt){
if(size === 0)
{
iszero = true;
}else if(size >= 0 && size <= 255)
{
is1Byte = true;
}else if(size >= -127 && size <= 127)
{
is1Byte = true;
}else if(size >= -32768 && size <= 32767)
{
is2Byte = true;
}else if(size >= -2147483648 && size <= 2147483647)
{
is4Byte = true;
}
}else {
if(size >= -3.4028235e38 && size <= 3.4028235e38)
{
is4Byte = true;
}else {
is8Byte = true;
}
};
this.writeFlags(
iszero,
isInt,
is1Byte,
is2Byte,
is4Byte,
is8Byte,
issigned,
255
);
if(isInt == false)
{
if(is4Byte)
{
this.writeFloat32(size);
}
if(is8Byte)
{
this.writeFloat64(size);
}
}else{
if(is1Byte)
{
if(issigned)
{
this.writeInt16(size);
}else{
this.writeUInt8(size);
}
}
if(is2Byte)
{
if(issigned)
{
this.writeInt32(size);
}else{
this.writeUInt16(size);
}
}
if(is4Byte)
{
if(issigned)
{
this.writeInt32(size);
}else{
this.writeUInt32(size);
}
}
}
}
/** @returns {number} */
readVarNumber(){
let [
iszero,
isInt,
is1Byte,
is2Byte,
is4Byte,
is8Byte,
issigned
] = this.readFlags();
if(iszero)
{
return 0;
}
if(!isInt)
{
if(is4Byte)
{
return this.readFloat32(); // 32-bit float
}else if(is8Byte)
{
return this.readFloat64(); // 64-bit float
}
}else {
if(is1Byte)
{
if(issigned)
{
return this.readInt8();
}else
{
return this.readUInt8();
}
}else if(is2Byte)
{
if(issigned)
{
return this.readInt16();
}else {
return this.readUInt16();
}
}else if(is4Byte)
{
if(issigned)
{
return this.readInt32();
}else {
return this.readUInt32();
}
}
}
}
/** @param {Date|string} dateorString */
writeDate(dateorString){
let date = new Date(dateorString);
this.writeUInt32(+date);
}
/** @returns {Date} */
readDate(){
return new Date(this.readUInt32());
}
};