diff --git a/lib/classes/LLLindenText.spec.ts b/lib/classes/LLLindenText.spec.ts new file mode 100644 index 0000000..a29f181 --- /dev/null +++ b/lib/classes/LLLindenText.spec.ts @@ -0,0 +1,13 @@ +import { LLLindenText } from './LLLindenText'; +import * as assert from 'assert'; + +describe('LLLindenText', () => +{ + it('can successfully parse a notecard asset', () => + { + const buf = Buffer.from('TGluZGVuIHRleHQgdmVyc2lvbiAyCnsKTExFbWJlZGRlZEl0ZW1zIHZlcnNpb24gMQp7CmNvdW50IDAKfQpUZXh0IGxlbmd0aCA5NDAKCgogICAgSGV5LCB0aGFua3MgZm9yIHlvdXIgcHVyY2hhc2Ugb2YgdGhlIENhc3BlclZlbmQgQ29tcGxldGUgRmF0IFBhY2suCiAgICAKICAgIEVhY2ggY29tcG9uZW50IGluIHRoaXMgZmF0IHBhY2sgaXMgYSBzZXBhcmF0ZSBwcm9kdWN0IHdpdGggaXRzIG93biBpbnN0cnVjdGlvbnMuCiAgICAKICAgIElmIHlvdSdyZSBuZXcgdG8gQ2FzcGVyVmVuZCwgdGhlIGZpcnN0IHN0ZXAgaXMgdG8gc2V0IHVwIHRoZSAiUHJlbWl1bSBWZW5kb3JzIiAtIHRoaXMgaXMgCiAgICB5b3VyIG1haW4gc3lzdGVtIHRoYXQgZXZlcnl0aGluZyBlbHNlIHBsdWdzIGluIHRvLiAKICAgIAogICAgQ2FzcGVyVmVuZCAyIGhhcyBhIGNvbXBsZXRlIG9ubGluZSBtYW51YWwgYXZhaWxhYmxlIGhlcmU6CiAgICAKICAgIGh0dHBzOi8vd2lraS5jYXNwZXJkbnMuY29tL2luZGV4LnBocD90aXRsZT1DYXNwZXJWZW5kXzIKICAgIAogICAgT3VyIG1hbnVhbCBpcyBjb25zdGFudGx5IGJlaW5nIHVwZGF0ZWQgd2l0aCBtb3JlIGhlbHAsIGd1aWRlcyBhbmQgaW5mb3JtYXRpb24uIAogICAgCiAgICBEb24ndCBmb3JnZXQsIGlmIHlvdSBnZXQgc3R1Y2sgLSB3ZSd2ZSBnb3QgYSB1c2VyIHN1cHBvcnQgZ3JvdXAgZnVsbCBvZiB2ZXJ5IGhlbHBmdWwgCiAgICBhbmQgYXdlc29tZSBwZW9wbGUuIFlvdSB3ZXJlIHNlbnQgYW4gaW52aXRlIHRvIHRoZSBncm91cCB3aGVuIHlvdSBwdXJjaGFzZWQsCiAgICBob3dldmVyIGlmIHlvdSBtaXNzZWQgdGhpcywgcGxlYXNlIElNIENhc3BlciBXYXJkZW4gZm9yIGFuIGludml0ZS4KICAgIAogICAgWW91IGNhbiBhbHNvIElNIG1lIGRpcmVjdGx5IGZvciBoZWxwIChDYXNwZXIgV2FyZGVuKS4gSWYgSSdtIG5vdCBvbmxpbmUsCiAgICB5b3Ugd2lsbCByZWNlaXZlIGEgbGluayB3aGljaCBhbGxvd3MgeW91IHRvIHN1Ym1pdCBhIHN1cHBvcnQgdGlja2V0Ln0KAA==', 'base64'); + const text = new LLLindenText(buf); + const expected = Buffer.from('CgogICAgSGV5LCB0aGFua3MgZm9yIHlvdXIgcHVyY2hhc2Ugb2YgdGhlIENhc3BlclZlbmQgQ29tcGxldGUgRmF0IFBhY2suCiAgICAKICAgIEVhY2ggY29tcG9uZW50IGluIHRoaXMgZmF0IHBhY2sgaXMgYSBzZXBhcmF0ZSBwcm9kdWN0IHdpdGggaXRzIG93biBpbnN0cnVjdGlvbnMuCiAgICAKICAgIElmIHlvdSdyZSBuZXcgdG8gQ2FzcGVyVmVuZCwgdGhlIGZpcnN0IHN0ZXAgaXMgdG8gc2V0IHVwIHRoZSAiUHJlbWl1bSBWZW5kb3JzIiAtIHRoaXMgaXMgCiAgICB5b3VyIG1haW4gc3lzdGVtIHRoYXQgZXZlcnl0aGluZyBlbHNlIHBsdWdzIGluIHRvLiAKICAgIAogICAgQ2FzcGVyVmVuZCAyIGhhcyBhIGNvbXBsZXRlIG9ubGluZSBtYW51YWwgYXZhaWxhYmxlIGhlcmU6CiAgICAKICAgIGh0dHBzOi8vd2lraS5jYXNwZXJkbnMuY29tL2luZGV4LnBocD90aXRsZT1DYXNwZXJWZW5kXzIKICAgIAogICAgT3VyIG1hbnVhbCBpcyBjb25zdGFudGx5IGJlaW5nIHVwZGF0ZWQgd2l0aCBtb3JlIGhlbHAsIGd1aWRlcyBhbmQgaW5mb3JtYXRpb24uIAogICAgCiAgICBEb24ndCBmb3JnZXQsIGlmIHlvdSBnZXQgc3R1Y2sgLSB3ZSd2ZSBnb3QgYSB1c2VyIHN1cHBvcnQgZ3JvdXAgZnVsbCBvZiB2ZXJ5IGhlbHBmdWwgCiAgICBhbmQgYXdlc29tZSBwZW9wbGUuIFlvdSB3ZXJlIHNlbnQgYW4gaW52aXRlIHRvIHRoZSBncm91cCB3aGVuIHlvdSBwdXJjaGFzZWQsCiAgICBob3dldmVyIGlmIHlvdSBtaXNzZWQgdGhpcywgcGxlYXNlIElNIENhc3BlciBXYXJkZW4gZm9yIGFuIGludml0ZS4KICAgIAogICAgWW91IGNhbiBhbHNvIElNIG1lIGRpcmVjdGx5IGZvciBoZWxwIChDYXNwZXIgV2FyZGVuKS4gSWYgSSdtIG5vdCBvbmxpbmUsCiAgICB5b3Ugd2lsbCByZWNlaXZlIGEgbGluayB3aGljaCBhbGxvd3MgeW91IHRvIHN1Ym1pdCBhIHN1cHBvcnQgdGlja2V0Lg==', 'base64'); + assert.equal(text.body, expected.toString('ascii')); + }); +}); diff --git a/lib/classes/LLLindenText.ts b/lib/classes/LLLindenText.ts index a21ddec..c0ad72f 100644 --- a/lib/classes/LLLindenText.ts +++ b/lib/classes/LLLindenText.ts @@ -12,6 +12,8 @@ export class LLLindenText lineNum: 0 }; + private pos = 0; + body = ''; embeddedItems: { [key: number]: InventoryItem } = {}; @@ -20,7 +22,8 @@ export class LLLindenText if (data !== undefined) { const initial = data.toString('ascii'); - this.lineObj.lines = initial.replace(/\r\n/g, '\n').split('\n'); + this.lineObj.lines = initial.split('\n'); + this.pos = 0; let line = this.getLine(); if (!line.startsWith('Linden text version')) @@ -52,31 +55,12 @@ export class LLLindenText { throw new Error('Error parsing Linden Text file: ' + line); } - let textLength = parseInt(this.getLastToken(line), 10); - do - { - line = this.getLine(); - textLength -= Buffer.byteLength(line); - if (textLength < 0) - { - const extraChars = 0 - textLength; - const rest = line.substr(line.length - extraChars); - line = line.substr(0, line.length - extraChars); - this.lineObj.lines.splice(this.lineObj.lineNum, 0, rest); - textLength = 0; - this.body += line; - } - else - { - this.body += line; - if (textLength > 0) - { - this.body += '\n'; - textLength--; - } - } - } - while (textLength > 0); + const textLength = parseInt(this.getLastToken(line), 10); + this.body = data.slice(this.pos, this.pos + textLength).toString(); + const remainingBuffer = data.slice(this.pos + textLength).toString('ascii'); + this.lineObj.lines = remainingBuffer.split('\n'); + this.lineObj.lineNum = 0; + line = this.getLine(); if (line !== '}') { @@ -173,7 +157,9 @@ export class LLLindenText private getLine(): string { - return this.lineObj.lines[this.lineObj.lineNum++].trim().replace(/[\t ]+/g, ' '); + const line = this.lineObj.lines[this.lineObj.lineNum++]; + this.pos += Buffer.byteLength(line) + 1; + return line.replace(/\r/, '').trim().replace(/[\t ]+/g, ' '); } } diff --git a/package.json b/package.json index 6e99b72..781a89d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@caspertech/node-metaverse", - "version": "0.6.19", + "version": "0.6.21", "description": "A node.js interface for Second Life.", "main": "dist/lib/index.js", "types": "dist/lib/index.d.ts",