-
Notifications
You must be signed in to change notification settings - Fork 1
/
json_hand.jl
182 lines (172 loc) · 5.4 KB
/
json_hand.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
#JSON Parser
#Adapted from http://www.mathworks.com/matlabcentral/fileexchange/23393
#Original BSD Licence, (c) 2011, François Glineur
function parse_json(strng::String)
pos = 1
len = length(strng)
# String delimiters and escape characters are identified beforehand to improve speed
# esc = regexp(str, "[\"\\\\]"); index_esc = 1; len_esc = length(esc); #TODO Enable for speed
function parse_object()
parse_char('{')
object = Dict{String, Any}()
if next_char() != '}'
while true
str = parse_string()
if isempty(str)
error("Name of value at position $pos cannot be empty")
end
parse_char(':')
val = parse_value()
object[str] = val
if next_char() == '}'
break
end
parse_char(',')
end
end
parse_char('}')
return object
end
function parse_array()
parse_char('[')
object = Set()
if next_char != ']'
while true
val = parse_value()
add!(object, val)
if next_char() == ']'
break
end
parse_char(',')
end
end
parse_char(']')
return object
end
function parse_char(c::Char)
skip_whitespace()
if pos > len || strng[pos] != c
error("Expected $c at position $pos")
else
pos = pos + 1
skip_whitespace()
end
end
function next_char()
skip_whitespace()
if pos > len
c = '\0'
else
c = strng[pos]
end
end
function skip_whitespace()
while pos <= len && isspace(strng[pos])
pos = pos + 1
end
end
function parse_string()
if strng[pos] != '"'
error("String starting with quotation expected at position $pos")
else
pos = pos + 1
end
str = ""
while pos <= len
# while index_esc <= len_esc && esc(index_esc) < pos
# index_esc = index_esc + 1
# end
# if index_esc > len_esc
# str = string(str, strng[pos:end])
# pos = len + 1
# break
# else
# str = string(str, strng[pos:esc(index_esc)-1])
# pos = esc(index_esc)
# end
nc = strng[pos]
if nc == '"'
pos = pos + 1
return string(str)
elseif nc == '\\'
if pos+1 > len
error_pos("End of file reached right after escape character")
end
pos = pos + 1
anc = strng[pos]
if anc == '"' || anc == '\\' || anc == '/'
str = string(str, strng[pos])
pos = pos + 1
elseif anc == 'b' || anc == 'f'|| anc == 'n' || anc == 'r' || anc == 't'
str = string(str, '\\', string[pos])
pos = pos + 1
elseif anc == 'u'
if pos+4 > len
error_pos("End of file reached in escaped unicode character")
end
str = string(str, strng[pos-1:pos+4])
pos = pos + 5
end
else # should never happen
str = string(str,strng[pos])
pos = pos + 1
end
end
error("End of file while expecting end of string")
end
function parse_number()
num_regex = r"^[\w]?[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?[\w]?"
m = match(num_regex, strng[pos:min(len,pos+20)])
if m === nothing
error("Error reading number at position $pos")
end
delta = m.offset + length(m.match)
pos = pos + delta -1
return float(m.match)
end
function parse_value()
nc = strng[pos]
if nc == '"'
val = parse_string()
return val
elseif nc == '['
val = parse_array()
return val
elseif nc == '{'
val = parse_object()
return val
elseif nc == '-' || nc == '0' || nc == '1' || nc == '2' || nc == '3' || nc == '4' || nc == '5' || nc == '6' || nc == '7' || nc == '8' || nc == '9'
val = parse_number()
return val
elseif nc == 't'
if pos+3 <= len && strng[pos:pos+3] == "true"
val = true
pos = pos + 4
return val
end
elseif nc == 'f'
if pos+4 <= len && strng[pos:pos+4] == "false"
val = false
pos = pos + 5
return val
end
elseif nc == 'n'
if pos+3 <= len && strng[pos:pos+3] == "null"
val = []
pos = pos + 4
return val
end
end
error("Value expected at position $pos")
end
if pos <= len
nc = next_char()
if nc == '{'
return parse_object()
elseif nc == '['
return parse_array()
else
error("Outer level structure must be an object or an array")
end
end
end