From 25adda6f3feb2ea614e1d000b600c8c89bee15f9 Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Tue, 21 Jul 2020 21:59:16 +0300 Subject: [PATCH] Alternative implementation that doesn't require rewind points --- json_serialization/lexer.nim | 51 ++++++++++++++++++++---------- json_serialization/reader.nim | 59 ++++++++++++++++++++++++++--------- tests/test_serialization.nim | 4 +-- 3 files changed, 81 insertions(+), 33 deletions(-) diff --git a/json_serialization/lexer.nim b/json_serialization/lexer.nim index 09af92d..50d4a5e 100644 --- a/json_serialization/lexer.nim +++ b/json_serialization/lexer.nim @@ -1,5 +1,5 @@ import - unicode, + unicode, json, faststreams/inputs, types @@ -61,22 +61,39 @@ const 1e20, 1e21, 1e22] # TODO: this table should be much larger # The largest JSON number value is 1E308 -proc renderTok*(s: JsonLexer): string = - case s.tok - of tkError, tkEof: "" - of tkString: "" - of tkInt: "" - of tkNegativeInt: "" - of tkFloat: "" - of tkTrue: "true" - of tkFalse: "false" - of tkNull: "null" - of tkCurlyLe: "{" - of tkCurlyRi: "}" - of tkBracketLe: "[" - of tkBracketRi: "]" - of tkColon: ":" - of tkComma: "," +proc renderTok*(lexer: JsonLexer, output: var string) = + case lexer.tok + of tkError, tkEof: + discard + of tkString: + output.add '"' + lexer.strVal.escapeJsonUnquoted output + output.add '"' + of tkInt: + output.add $lexer.absIntVal + of tkNegativeInt: + output.add '-' + output.add $lexer.absIntVal + of tkFloat: + output.add $lexer.floatVal + of tkTrue: + output.add "true" + of tkFalse: + output.add "false" + of tkNull: + output.add "null" + of tkCurlyLe: + output.add '{' + of tkCurlyRi: + output.add '}' + of tkBracketLe: + output.add '[' + of tkBracketRi: + output.add ']' + of tkColon: + output.add ':' + of tkComma: + output.add ',' template peek(s: InputStream): char = char inputs.peek(s) diff --git a/json_serialization/reader.nim b/json_serialization/reader.nim index 87adbda..920c376 100644 --- a/json_serialization/reader.nim +++ b/json_serialization/reader.nim @@ -177,17 +177,48 @@ proc skipSingleJsValue(r: var JsonReader) = of tkString, tkInt, tkNegativeInt, tkFloat, tkTrue, tkFalse, tkNull: r.lexer.next() -proc captureSingleJsValue(r: var JsonReader, value: var string) = - value = $r.lexer.tok - let pos = r.lexer.stream.createRewindPoint() - echo "skipiing ", pos - r.skipSingleJsValue() - let finalPos = r.lexer.stream.pos - echo "done ", finalPos - echo "Rewiding ", finalPos - pos - r.lexer.stream.rewindTo pos - value.setLen(finalPos - pos) - doAssert r.lexer.stream.readInto(value) +proc captureSingleJsValue(r: var JsonReader, output: var string) = + r.lexer.renderTok output + case r.lexer.tok + of tkCurlyLe: + r.lexer.next() + if r.lexer.tok != tkCurlyRi: + while true: + r.lexer.renderTok output + r.skipToken tkString + r.lexer.renderTok output + r.skipToken tkColon + r.captureSingleJsValue(output) + r.lexer.renderTok output + if r.lexer.tok == tkCurlyRi: + break + else: + r.skipToken tkComma + else: + output.add '}' + # Skip over the last tkCurlyRi + r.lexer.next() + + of tkBracketLe: + r.lexer.next() + if r.lexer.tok != tkBracketRi: + while true: + r.captureSingleJsValue(output) + r.lexer.renderTok output + if r.lexer.tok == tkBracketRi: + break + else: + r.skipToken tkComma + else: + output.add ']' + # Skip over the last tkBracketRi + r.lexer.next() + + of tkColon, tkComma, tkEof, tkError, tkBracketRi, tkCurlyRi: + r.raiseUnexpectedToken etValue + + of tkString, tkInt, tkNegativeInt, tkFloat, tkTrue, tkFalse, tkNull: + r.lexer.next() proc allocPtr[T](p: var ptr T) = p = create(T) @@ -251,14 +282,14 @@ proc readValue*[T](r: var JsonReader, value: var T) r.requireToken tkString value = r.lexer.strVal r.lexer.next() - + elif value is seq[char]: r.requireToken tkString value.setLen(r.lexer.strVal.len) for i in 0..")