Added methods for writing data at a specific offset to WritableCursor.

This commit is contained in:
jtuu 2019-10-11 10:39:13 +03:00
parent 6ed419cf35
commit aad45b0929
3 changed files with 195 additions and 49 deletions

View File

@ -7,95 +7,73 @@ export abstract class AbstractWritableCursor extends AbstractCursor implements W
abstract size: number;
write_u8(value: number): this {
this.ensure_size(1);
this.dv.setUint8(this._position++, value);
this.write_u8_at(this.position, value);
this._position += 1;
return this;
}
write_u16(value: number): this {
this.ensure_size(2);
this.dv.setUint16(this.position, value, this.little_endian);
this.write_u16_at(this.position, value);
this._position += 2;
return this;
}
write_u32(value: number): this {
this.ensure_size(4);
this.dv.setUint32(this.position, value, this.little_endian);
this.write_u32_at(this.position, value);
this._position += 4;
return this;
}
write_i8(value: number): this {
this.ensure_size(1);
this.dv.setInt8(this.position, value);
this.write_i8_at(this.position, value);
this._position += 1;
return this;
}
write_i16(value: number): this {
this.ensure_size(2);
this.dv.setInt16(this.position, value, this.little_endian);
this.write_i16_at(this.position, value);
this._position += 2;
return this;
}
write_i32(value: number): this {
this.ensure_size(4);
this.dv.setInt32(this.position, value, this.little_endian);
this.write_i32_at(this.position, value);
this._position += 4;
return this;
}
write_f32(value: number): this {
this.ensure_size(4);
this.dv.setFloat32(this.position, value, this.little_endian);
this.write_f32_at(this.position, value);
this._position += 4;
return this;
}
write_u8_array(array: readonly number[]): this {
this.ensure_size(array.length);
new Uint8Array(this.backing_buffer, this.offset + this.position).set(new Uint8Array(array));
this.write_u8_array_at(this.position, array);
this._position += array.length;
return this;
}
write_u16_array(array: readonly number[]): this {
this.ensure_size(2 * array.length);
const len = array.length;
for (let i = 0; i < len; i++) {
this.write_u16(array[i]);
}
this.write_u16_array_at(this.position, array);
this._position += array.length * 2;
return this;
}
write_u32_array(array: readonly number[]): this {
this.ensure_size(4 * array.length);
const len = array.length;
for (let i = 0; i < len; i++) {
this.write_u32(array[i]);
}
this.write_u32_array_at(this.position, array);
this._position += array.length * 4;
return this;
}
write_vec2_f32(value: Vec2): this {
this.ensure_size(8);
this.dv.setFloat32(this.position, value.x, this.little_endian);
this.dv.setFloat32(this.position + 4, value.y, this.little_endian);
this.write_vec2_f32_at(this.position, value);
this._position += 8;
return this;
}
write_vec3_f32(value: Vec3): this {
this.ensure_size(12);
this.dv.setFloat32(this.position, value.x, this.little_endian);
this.dv.setFloat32(this.position + 4, value.y, this.little_endian);
this.dv.setFloat32(this.position + 8, value.z, this.little_endian);
this.write_vec3_f32_at(this.position, value);
this._position += 12;
return this;
}
@ -114,45 +92,143 @@ export abstract class AbstractWritableCursor extends AbstractCursor implements W
}
write_string_ascii(str: string, byte_length: number): this {
this.ensure_size(byte_length);
this.write_string_ascii_at(this.position, str, byte_length);
this._position += byte_length;
return this;
}
write_string_utf16(str: string, byte_length: number): this {
this.write_string_utf16_at(this.position, str, byte_length);
this._position += byte_length;
return this;
}
write_u8_at(offset: number, value: number): this {
this.ensure_size(1, offset);
this.dv.setUint8(offset, value);
return this;
}
write_u16_at(offset: number, value: number): this {
this.ensure_size(2, offset);
this.dv.setUint16(offset, value, this.little_endian);
return this;
}
write_u32_at(offset: number, value: number): this {
this.ensure_size(4, offset);
this.dv.setUint32(offset, value, this.little_endian);
return this;
}
write_i8_at(offset: number, value: number): this {
this.ensure_size(1, offset);
this.dv.setInt8(offset, value);
return this;
}
write_i16_at(offset: number, value: number): this {
this.ensure_size(2, offset);
this.dv.setInt16(offset, value, this.little_endian);
return this;
}
write_i32_at(offset: number, value: number): this {
this.ensure_size(4, offset);
this.dv.setInt32(offset, value, this.little_endian);
return this;
}
write_f32_at(offset: number, value: number): this {
this.ensure_size(4, offset);
this.dv.setFloat32(offset, value, this.little_endian);
return this;
}
write_u8_array_at(offset: number, array: readonly number[]): this {
this.ensure_size(array.length, offset);
new Uint8Array(this.backing_buffer, this.offset + offset).set(new Uint8Array(array));
return this;
}
write_u16_array_at(offset: number, array: readonly number[]): this {
this.ensure_size(2 * array.length, offset);
const len = array.length;
for (let i = 0; i < len; i++) {
this.write_u16_at(offset + i * 2, array[i]);
}
return this;
}
write_u32_array_at(offset: number, array: readonly number[]): this {
this.ensure_size(4 * array.length, offset);
const len = array.length;
for (let i = 0; i < len; i++) {
this.write_u32_at(offset + i * 4, array[i]);
}
return this;
}
write_vec2_f32_at(offset: number, value: Vec2): this {
this.ensure_size(8, offset);
this.dv.setFloat32(offset, value.x, this.little_endian);
this.dv.setFloat32(offset + 4, value.y, this.little_endian);
return this;
}
write_vec3_f32_at(offset: number, value: Vec3): this {
this.ensure_size(12, offset);
this.dv.setFloat32(offset, value.x, this.little_endian);
this.dv.setFloat32(offset + 4, value.y, this.little_endian);
this.dv.setFloat32(offset + 8, value.z, this.little_endian);
return this;
}
write_string_ascii_at(offset: number, str: string, byte_length: number): this {
this.ensure_size(byte_length, offset);
const len = Math.min(byte_length, str.length);
for (let i = 0; i < len; i++) {
this.write_u8(str.codePointAt(i)!);
this.write_u8_at(offset + i, str.codePointAt(i)!);
}
const pad_len = byte_length - len;
for (let i = 0; i < pad_len; i++) {
this.write_u8(0);
this.write_u8_at(offset + len + i, 0);
}
return this;
}
write_string_utf16(str: string, byte_length: number): this {
this.ensure_size(byte_length);
write_string_utf16_at(offset: number, str: string, byte_length: number): this {
this.ensure_size(byte_length, offset);
const max_len = Math.floor(byte_length / 2);
const len = Math.min(max_len, str.length);
for (let i = 0; i < len; i++) {
this.write_u16(str.codePointAt(i)!);
this.write_u16_at(offset + i * 2, str.codePointAt(i)!);
}
const pad_len = max_len - len;
for (let i = 0; i < pad_len; i++) {
this.write_u16(0);
this.write_u16_at(offset + len * 2 + i * 2, 0);
}
return this;
}
protected ensure_size(size: number): void {
if (size > this.bytes_left) {
throw new Error(`${size} Bytes required but only ${this.bytes_left} available.`);
protected ensure_size(size: number, offset: number = this.position): void {
const left = this.size - offset;
if (size > left) {
throw new Error(`${size} Bytes required but only ${left} available.`);
}
}
}

View File

@ -63,8 +63,8 @@ export class ResizableBufferCursor extends AbstractWritableCursor implements Wri
return wrapper;
}
protected ensure_size(size: number): void {
const needed = this.position + size - this._size;
protected ensure_size(size: number, offset: number = this.position): void {
const needed = offset + size - this._size;
if (needed > 0) {
this._size += needed;

View File

@ -81,4 +81,74 @@ export interface WritableCursor extends Cursor {
* Writes characters of str without writing more than byte_length bytes. If less than byte_length bytes can be written this way, nul bytes will be inserted until byte_length bytes have been written.
*/
write_string_utf16(str: string, byte_length: number): this;
/**
* Writes an unsigned 8-bit integer at the given absolute offset. Doesn't increment position.
*/
write_u8_at(offset: number, value: number): this;
/**
* Writes an unsigned 16-bit integer at the given absolute offset. Doesn't increment position.
*/
write_u16_at(offset: number, value: number): this;
/**
* Writes an unsigned 32-bit integer at the given absolute offset. Doesn't increment position.
*/
write_u32_at(offset: number, value: number): this;
/**
* Writes a signed 8-bit integer at the given absolute offset. Doesn't increment position.
*/
write_i8_at(offset: number, value: number): this;
/**
* Writes a signed 16-bit integer at the given absolute offset. Doesn't increment position.
*/
write_i16_at(offset: number, value: number): this;
/**
* Writes a signed 32-bit integer at the given absolute offset. Doesn't increment position.
*/
write_i32_at(offset: number, value: number): this;
/**
* Writes a 32-bit floating point number at the given absolute offset. Doesn't increment position.
*/
write_f32_at(offset: number, value: number): this;
/**
* Writes an array of unsigned 8-bit integers at the given absolute offset. Doesn't increment position.
*/
write_u8_array_at(offset: number, array: number[]): this;
/**
* Writes an array of unsigned 16-bit integers at the given absolute offset. Doesn't increment position.
*/
write_u16_array_at(offset: number, array: number[]): this;
/**
* Writes an array of unsigned 32-bit integers at the given absolute offset. Doesn't increment position.
*/
write_u32_array_at(offset: number, array: number[]): this;
/**
* Writes two 32-bit floating point numbers at the given absolute offset. Doesn't increment position.
*/
write_vec2_f32_at(offset: number, value: Vec2): this;
/**
* Writes three 32-bit floating point numbers at the given absolute offset. Doesn't increment position.
*/
write_vec3_f32_at(offset: number, value: Vec3): this;
/**
* Writes byte_length characters of str at the given absolute offset. If str is shorter than byte_length, nul bytes will be inserted until byte_length bytes have been written. Doesn't increment position.
*/
write_string_ascii_at(offset: number, str: string, byte_length: number): this;
/**
* Writes characters of str without writing more than byte_length bytes. If less than byte_length bytes can be written this way, nul bytes will be inserted until byte_length bytes have been written. Doesn't increment position.
*/
write_string_utf16_at(offset: number, str: string, byte_length: number): this;
}