Files
PSFree/module/rw.mjs
T
Kameleon 1220a577a2 Update to psfree-1.5rc1
900 Port in process: DO NOT USE IT.
2025-05-10 09:34:58 -06:00

141 lines
4.0 KiB
JavaScript

/* Copyright (C) 2023-2025 anonymous
This file is part of PSFree.
PSFree is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
PSFree is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
import { Int, lohi_from_one } from './int64.mjs';
// DataView's accessors are constant time and are faster when doing multi-byte
// accesses but the single-byte accessors are slightly slower compared to just
// indexing the Uint8Array
//
// to get the best of both worlds, BufferView uses a DataView for multi-byte
// accesses and a Uint8Array for single-byte
//
// instances of BufferView will their have m_mode set to WastefulTypedArray
// since we use the .buffer getter to create a DataView
export class BufferView extends Uint8Array {
constructor(...args) {
super(...args);
this._dview = new DataView(this.buffer, this.byteOffset);
}
read16(offset) {
return this._dview.getUint16(offset, true);
}
read32(offset) {
return this._dview.getUint32(offset, true);
}
read64(offset) {
return new Int(
this._dview.getUint32(offset, true),
this._dview.getUint32(offset + 4, true),
);
}
write16(offset, value) {
this._dview.setUint16(offset, value, true);
}
write32(offset, value) {
this._dview.setUint32(offset, value, true);
}
write64(offset, value) {
const values = lohi_from_one(value);
this._dview.setUint32(offset, values[0], true);
this._dview.setUint32(offset + 4, values[1], true);
}
}
// WARNING: These functions are now deprecated. use BufferView instead.
// view.buffer is the underlying ArrayBuffer of a TypedArray, but since we will
// be corrupting the m_vector of our target views later, the ArrayBuffer's
// buffer will not correspond to our fake m_vector anyway.
//
// can't use:
//
// function read32(u8_view, offset) {
// let res = new Uint32Array(u8_view.buffer, offset, 1);
// return res[0];
// }
//
// to implement read32, we need to index the view instead:
//
// function read32(u8_view, offset) {
// let res = 0;
// for (let i = 0; i < 4; i++) {
// res += u8_view[offset + i] << i*8;
// }
// // << returns a signed integer, >>> converts it to unsigned
// return res >>> 0;
// }
// for reads less than 8 bytes
function read(u8_view, offset, size) {
let res = 0;
for (let i = 0; i < size; i++) {
res += u8_view[offset + i] << i*8;
}
// << returns a signed integer, >>> converts it to unsigned
return res >>> 0;
}
export function read16(u8_view, offset) {
return read(u8_view, offset, 2);
}
export function read32(u8_view, offset) {
return read(u8_view, offset, 4);
}
export function read64(u8_view, offset) {
return new Int(read32(u8_view, offset), read32(u8_view, offset + 4));
}
// for writes less than 8 bytes
function write(u8_view, offset, value, size) {
for (let i = 0; i < size; i++) {
u8_view[offset + i] = (value >>> i*8) & 0xff;
}
}
export function write16(u8_view, offset, value) {
write(u8_view, offset, value, 2);
}
export function write32(u8_view, offset, value) {
write(u8_view, offset, value, 4);
}
export function write64(u8_view, offset, value) {
if (!(value instanceof Int)) {
throw TypeError('write64 value must be an Int');
}
let low = value.lo;
let high = value.hi;
for (let i = 0; i < 4; i++) {
u8_view[offset + i] = (low >>> i*8) & 0xff;
}
for (let i = 0; i < 4; i++) {
u8_view[offset + 4 + i] = (high >>> i*8) & 0xff;
}
}