From a4a11af1a85e985128d4eef964f3b5a5644ab940 Mon Sep 17 00:00:00 2001 From: Vladimir Grichina Date: Sun, 6 Jan 2019 02:59:36 -0800 Subject: [PATCH] Support white-space between tokens --- assembly/decoder.ts | 38 ++++++++++++++++++++++--------- tests/assembly/decoder.spec.as.ts | 19 ++++++++++++---- 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/assembly/decoder.ts b/assembly/decoder.ts index c5ee461..ddf86eb 100644 --- a/assembly/decoder.ts +++ b/assembly/decoder.ts @@ -49,7 +49,7 @@ export class ThrowingJSONHandler extends JSONHandler { } setBoolean(name: string, value: bool): void { - assert(false, 'Unexpected boolean field ' + name + ' : ' + (value ? 'true' : 'false')); + assert(false, 'Unexpected bool field ' + name + ' : ' + (value ? 'true' : 'false')); } setNull(name: string): void { @@ -97,6 +97,7 @@ export class JSONDecoder { this.lastKey = null assert(this.parseValue(), "Cannot parse JSON"); + // TODO: Error if input left } private peekChar(): i32 { @@ -108,22 +109,25 @@ export class JSONDecoder { return this.buffer[this.readIndex++]; } - private parseValue(): boolean { - return this.parseObject() + private parseValue(): bool { + this.skipWhitespace(); + let result = this.parseObject() || this.parseArray() || this.parseString() || this.parseBoolean() || this.parseNumber() || this.parseNull() - // TODO: Error if input left + this.skipWhitespace(); + return result; } - private parseObject(): boolean { + private parseObject(): bool { if (this.peekChar() != "{".charCodeAt(0)) { return false; } this.handler.pushObject(this.lastKey); this.readChar(); + this.skipWhitespace(); let firstItem = true; while (this.peekChar() != "}".charCodeAt(0)) { @@ -141,16 +145,18 @@ export class JSONDecoder { } private parseKey(): void { + this.skipWhitespace(); this.lastKey = this.readString(); + this.skipWhitespace(); assert(this.readChar() == ":".charCodeAt(0), "Expected ':'"); } - private parseArray(): boolean { + private parseArray(): bool { // TODO return false; } - private parseString(): boolean { + private parseString(): bool { if (this.peekChar() != '"'.charCodeAt(0)) { return false; } @@ -158,7 +164,7 @@ export class JSONDecoder { return true; } - private readString(): String { + private readString(): string { assert(this.readChar() == '"'.charCodeAt(0), "Expected double-quoted string"); let savedIndex = this.readIndex; for (;;) { @@ -183,7 +189,7 @@ export class JSONDecoder { return ""; } - private parseNumber(): boolean { + private parseNumber(): bool { // TODO: Parse floats let number: i32 = 0; let sign: i32 = 1; @@ -205,7 +211,7 @@ export class JSONDecoder { return false; } - private parseBoolean(): boolean { + private parseBoolean(): bool { if (this.peekChar() == FALSE_STR.charCodeAt(0)) { this.readAndAssert(FALSE_STR); this.handler.setBoolean(this.lastKey, false); @@ -220,7 +226,7 @@ export class JSONDecoder { return false; } - private parseNull(): boolean { + private parseNull(): bool { if (this.peekChar() == NULL_STR.charCodeAt(0)) { this.readAndAssert(NULL_STR); this.handler.setNull(this.lastKey); @@ -234,4 +240,14 @@ export class JSONDecoder { assert(str.charCodeAt(i) == this.readChar(), "Expected '" + str + "'"); } } + + private skipWhitespace(): void { + while (this.isWhitespace(this.peekChar())) { + this.readChar(); + } + } + + private isWhitespace(charCode: i32): bool { + return charCode == 0x9 || charCode == 0xa || charCode == 0xd || charCode == 0x20; + } } diff --git a/tests/assembly/decoder.spec.as.ts b/tests/assembly/decoder.spec.as.ts index 49445e3..1e785b4 100644 --- a/tests/assembly/decoder.spec.as.ts +++ b/tests/assembly/decoder.spec.as.ts @@ -108,6 +108,10 @@ export class StringConversionTests { return this.roundripTest("{}"); } + static shouldHandleEmptyObjectWithWhitespace(): bool { + return this.roundripTest("{ }", "{}"); + } + static shouldHandleInt32(): bool { return this.roundripTest('{"int":4660}'); } @@ -140,8 +144,15 @@ export class StringConversionTests { return this.roundripTest('{"str":"foo","obj":{"a":1,"b":-123456}}'); } - private static roundripTest(jsonString: string): bool { - logStr("----------------- " + jsonString); + static shouldHandleWhitespace(): bool { + return this.roundripTest( + ' { "str":"foo","obj": {"a":1, "b" :\n -123456} } ', + '{"str":"foo","obj":{"a":1,"b":-123456}}'); + } + + private static roundripTest(jsonString: string, expectedString: string = null): bool { + expectedString = expectedString || jsonString; + logStr("----------------- " + jsonString ); let buffer: Uint8Array = new Uint8Array(jsonString.lengthUTF8); let utf8ptr = jsonString.toUTF8(); // TODO: std should expose memcpy? @@ -149,8 +160,8 @@ export class StringConversionTests { buffer[i] = load(utf8ptr + i); } this.createDecoder().deserialize(buffer); - assert(this.handler.result == jsonString, - "Expected:\n" + jsonString + "\n" + "Actual:\n" + this.handler.result); + assert(this.handler.result == expectedString, + "Expected:\n" + expectedString + "\n" + "Actual:\n" + this.handler.result); return true; } }