speed up json core module

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

View File

@@ -954,9 +954,11 @@ proc newIndent(curr, indent: int, ml: bool): int =
proc nl(s: var string, ml: bool) =
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.
result = newStringOfCap(s.len + s.len shr 3)
## Appends to ``result``.
const
HexChars = "0123456789ABCDEF"
result.add("\"")
for x in runes(s):
var r = int(x)
@@ -967,10 +969,19 @@ proc escapeJson*(s: string): string =
of '\\': result.add("\\\\")
else: result.add(c)
else:
result.add("\\u")
result.add(toHex(r, 4))
# toHex inlined for more speed (saves stupid string allocations):
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("\"")
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,
lstArr = false, currIndent = 0) =
case node.kind
@@ -988,7 +999,7 @@ proc toPretty(result: var string, node: JsonNode, indent = 2, ml = true,
inc i
# Need to indent more than {
result.indent(newIndent(currIndent, indent, ml))
result.add(escapeJson(key))
escapeJson(key, result)
result.add(": ")
toPretty(result, val, indent, ml, false,
newIndent(currIndent, indent, ml))
@@ -999,16 +1010,19 @@ proc toPretty(result: var string, node: JsonNode, indent = 2, ml = true,
result.add("{}")
of JString:
if lstArr: result.indent(currIndent)
result.add(escapeJson(node.str))
escapeJson(node.str, result)
of JInt:
if lstArr: result.indent(currIndent)
result.add($node.num)
when defined(js): result.add($node.num)
else: result.add(node.num)
of JFloat:
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:
if lstArr: result.indent(currIndent)
result.add($node.bval)
result.add(if node.bval: "true" else: "false")
of JArray:
if lstArr: result.indent(currIndent)
if len(node.elems) != 0:
@@ -1057,12 +1071,12 @@ proc toUgly*(result: var string, node: JsonNode) =
for key, value in pairs(node.fields):
if comma: result.add ","
else: comma = true
result.add key.escapeJson()
key.escapeJson(result)
result.add ":"
result.toUgly value
result.add "}"
of JString:
result.add node.str.escapeJson()
node.str.escapeJson(result)
of JInt:
result.add($node.num)
of JFloat:
@@ -1394,4 +1408,6 @@ when isMainModule:
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 escapeJson("\10FoobarÄ") == "\"\\u000AFoobar\\u00C4\""
echo("Tests succeeded!")