From 2456eae91a25c2c67fd067b3c638495752a3db9f Mon Sep 17 00:00:00 2001 From: C-3PO Date: Sun, 24 Jun 2018 02:06:49 +0200 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=20Allow=2016-bit=20and=2032-bit=20rea?= =?UTF-8?q?ds=20in=20ByteReader?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ssn/extractFile.ts | 6 +++--- src/ssn/extractFileByteReader.ts | 19 +++++++++++++++---- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/ssn/extractFile.ts b/src/ssn/extractFile.ts index ec7f7e4..67bd037 100644 --- a/src/ssn/extractFile.ts +++ b/src/ssn/extractFile.ts @@ -11,14 +11,14 @@ export default async function extractFile(file: ISsnFileEntry, dvArray: DataView const byteReader = new ByteReader(dvArray, file.diskNumberStart, file.offset); //Local file header signature must be 0x04034B50 - if (byteReader.readByte() !== 0x50 || byteReader.readByte() !== 0x4B || byteReader.readByte() !== 0x03 || byteReader.readByte() !== 0x04) { + if (byteReader.readUint32() !== 0x04034B50) { throw new Error('Local file header had wrong magic'); } //All fields in the local file header are copies of the central file header, so we can skip them. //FIXME: Maybe we should actually read these fields to verify that they are identical? byteReader.seek(22); - const localFilenameSize = byteReader.readByte() + (byteReader.readByte() << 8); - const localExtraSize = byteReader.readByte() + (byteReader.readByte() << 8); + const localFilenameSize = byteReader.readUint16(); + const localExtraSize = byteReader.readUint16(); byteReader.seek(localFilenameSize + localExtraSize); //Extract actual file contents diff --git a/src/ssn/extractFileByteReader.ts b/src/ssn/extractFileByteReader.ts index a653970..06413ba 100644 --- a/src/ssn/extractFileByteReader.ts +++ b/src/ssn/extractFileByteReader.ts @@ -7,7 +7,8 @@ export default class ByteReader { this.dvIndex = startDvIndex; this.pos = offset; } - public readByte() { + /** Reads one byte and returns it. */ + public readUint8() { const curByte = this.dvArray[this.dvIndex].getUint8(this.pos); this.pos += 1; if (this.pos >= this.dvArray[this.dvIndex].byteLength) { @@ -17,18 +18,28 @@ export default class ByteReader { } return curByte; } - public seek(num: number) { - this.pos += num; + /** Reads two bytes as an unsigned 16-bit integer and returns it. */ + public readUint16() { + return this.readUint8() | (this.readUint8() << 8); + } + /** Reads four bytes as an unsigned 32-bit integer and returns it. */ + public readUint32() { + return (this.readUint8() | (this.readUint8() << 8) | (this.readUint8() << 16) | (this.readUint8() << 24)) >>> 0; + } + /** Seeks the given number of bytes forward, without reading the bytes. */ + public seek(numBytes: number) { + this.pos += numBytes; if (this.pos >= this.dvArray[this.dvIndex].byteLength) { this.pos -= this.dvArray[this.dvIndex].byteLength; this.dvIndex += 1; if (this.dvIndex >= this.dvArray.length) { throw new Error('Tried to read beyond DataView boundary in extractFile'); } } } + /** Reads the given amount of bytes, and returns it as a DataView. */ public extractDv(length: number) { const dv = new DataView(new ArrayBuffer(length)); for (let i = 0; i < length; i += 1) { - dv.setUint8(i, this.readByte()); //TODO: refactor this so it is more optimized + dv.setUint8(i, this.readUint8()); //TODO: refactor this so it is more optimized } return dv; }