speed up json core module

This commit is contained in:
Andreas Rumpf 2016-11-21 13:54:16 +01:00
commit 18690d4a61

View file

@ -954,9 +954,11 @@ proc newIndent(curr, indent: int, ml: bool): int =
proc nl(s: var string, ml: bool) = proc nl(s: var string, ml: bool) =
if ml: s.add("\n") if ml: s.add("\n")
proc escapeJson*(s: string): string = proc escapeJson*(s: string; result: var string) =
## Converts a string `s` to its JSON representation. ## Converts a string `s` to its JSON representation.
result = newStringOfCap(s.len + s.len shr 3) ## Appends to ``result``.
const
HexChars = "0123456789ABCDEF"
result.add("\"") result.add("\"")
for x in runes(s): for x in runes(s):
var r = int(x) var r = int(x)
@ -967,10 +969,19 @@ proc escapeJson*(s: string): string =
of '\\': result.add("\\\\") of '\\': result.add("\\\\")
else: result.add(c) else: result.add(c)
else: else:
result.add("\\u") # toHex inlined for more speed (saves stupid string allocations):
result.add(toHex(r, 4)) result.add("\\u0000")
let start = result.len - 4
for j in countdown(3, 0):
result[j+start] = HexChars[r and 0xF]
r = r shr 4
result.add("\"") result.add("\"")
proc escapeJson*(s: string): string =
## Converts a string `s` to its JSON representation.
result = newStringOfCap(s.len + s.len shr 3)
escapeJson(s, result)
proc toPretty(result: var string, node: JsonNode, indent = 2, ml = true, proc toPretty(result: var string, node: JsonNode, indent = 2, ml = true,
lstArr = false, currIndent = 0) = lstArr = false, currIndent = 0) =
case node.kind case node.kind
@ -988,7 +999,7 @@ proc toPretty(result: var string, node: JsonNode, indent = 2, ml = true,
inc i inc i
# Need to indent more than { # Need to indent more than {
result.indent(newIndent(currIndent, indent, ml)) result.indent(newIndent(currIndent, indent, ml))
result.add(escapeJson(key)) escapeJson(key, result)
result.add(": ") result.add(": ")
toPretty(result, val, indent, ml, false, toPretty(result, val, indent, ml, false,
newIndent(currIndent, indent, ml)) newIndent(currIndent, indent, ml))
@ -999,16 +1010,19 @@ proc toPretty(result: var string, node: JsonNode, indent = 2, ml = true,
result.add("{}") result.add("{}")
of JString: of JString:
if lstArr: result.indent(currIndent) if lstArr: result.indent(currIndent)
result.add(escapeJson(node.str)) escapeJson(node.str, result)
of JInt: of JInt:
if lstArr: result.indent(currIndent) if lstArr: result.indent(currIndent)
result.add($node.num) when defined(js): result.add($node.num)
else: result.add(node.num)
of JFloat: of JFloat:
if lstArr: result.indent(currIndent) if lstArr: result.indent(currIndent)
result.add($node.fnum) # Fixme: implement new system.add ops for the JS target
when defined(js): result.add($node.fnum)
else: result.add(node.fnum)
of JBool: of JBool:
if lstArr: result.indent(currIndent) if lstArr: result.indent(currIndent)
result.add($node.bval) result.add(if node.bval: "true" else: "false")
of JArray: of JArray:
if lstArr: result.indent(currIndent) if lstArr: result.indent(currIndent)
if len(node.elems) != 0: if len(node.elems) != 0:
@ -1057,12 +1071,12 @@ proc toUgly*(result: var string, node: JsonNode) =
for key, value in pairs(node.fields): for key, value in pairs(node.fields):
if comma: result.add "," if comma: result.add ","
else: comma = true else: comma = true
result.add key.escapeJson() key.escapeJson(result)
result.add ":" result.add ":"
result.toUgly value result.toUgly value
result.add "}" result.add "}"
of JString: of JString:
result.add node.str.escapeJson() node.str.escapeJson(result)
of JInt: of JInt:
result.add($node.num) result.add($node.num)
of JFloat: of JFloat:
@ -1394,4 +1408,6 @@ when isMainModule:
var parsed2 = parseFile("tests/testdata/jsontest2.json") var parsed2 = parseFile("tests/testdata/jsontest2.json")
doAssert(parsed2{"repository", "description"}.str=="IRC Library for Haskell", "Couldn't fetch via multiply nested key using {}") doAssert(parsed2{"repository", "description"}.str=="IRC Library for Haskell", "Couldn't fetch via multiply nested key using {}")
doAssert escapeJson("\10FoobarÄ") == "\"\\u000AFoobar\\u00C4\""
echo("Tests succeeded!") echo("Tests succeeded!")