Skip to content

Commit 667ad63

Browse files
committed
improve quality of perf_parse_json implementation
Allocating strings with json character-by-character with ""+c+c+… is bad style, and this was not handling \u correctly either. We could make strcat a separate micro-benchmark, but it is not a particularly interesting test case currently.
1 parent c5b94b3 commit 667ad63

File tree

1 file changed

+38
-21
lines changed

1 file changed

+38
-21
lines changed

src/problem/JSONParse.jl

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -75,36 +75,53 @@ function perf_parse_json(strng::AbstractString)
7575
if strng[pos] != '"'
7676
error("AbstractString starting with quotation expected at position $pos")
7777
else
78-
pos = pos + 1
78+
pos += 1
7979
end
80-
str = ""
80+
str = IOBuffer()
8181
while pos <= len
8282
nc = strng[pos]
8383
if nc == '"'
84+
pos += 1
85+
return String(take!(str))
86+
elseif nc == '\\'
8487
pos = pos + 1
85-
return string(str)
86-
elseif nc == '\\'
87-
if pos+1 > len
88-
error_pos("End of file reached right after escape character")
89-
end
90-
pos = pos + 1
88+
pos > len && break # goto error handling
9189
anc = strng[pos]
92-
if anc == '"' || anc == '\\' || anc == '/'
93-
str = string(str, strng[pos])
94-
pos = pos + 1
95-
elseif anc == 'b' || anc == 'f'|| anc == 'n' || anc == 'r' || anc == 't'
96-
str = string(str, '\\', string[pos])
97-
pos = pos + 1
90+
if anc == '"'
91+
write(str, "\"")
92+
pos += 1
93+
elseif anc == '\\'
94+
write(str, "\\")
95+
pos += 1
96+
elseif anc == '/'
97+
write(str, "/")
98+
pos += 1
99+
elseif anc == 'b'
100+
write(str, "\b")
101+
pos += 1
102+
elseif anc == 'f'
103+
write(str, "\f")
104+
pos += 1
105+
elseif anc == 'n'
106+
write(str, "\n")
107+
pos += 1
108+
elseif anc == 'r'
109+
write(str, "\r")
110+
pos += 1
111+
elseif anc == 't'
112+
write(str, "\t")
113+
pos += 1
98114
elseif anc == 'u'
99-
if pos+4 > len
100-
error_pos("End of file reached in escaped unicode character")
101-
end
102-
str = string(str, strng[pos-1:pos+4])
115+
pos + 4 > len && break # goto error handling
116+
write(str, Char(parse(Int, strng[pos:pos+4], base=16)))
103117
pos = pos + 5
118+
else # should rarely happen
119+
write(str, anc)
120+
pos = pos + 1
104121
end
105-
else # should never happen
106-
str = string(str,strng[pos])
107-
pos = pos + 1
122+
else # common case
123+
write(str, nc)
124+
pos = nextind(strng, pos)
108125
end
109126
end
110127
error("End of file while expecting end of string")

0 commit comments

Comments
 (0)