-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsjson.py
156 lines (130 loc) · 4.1 KB
/
sjson.py
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
class SJCallback:
def start(self):
pass
def end(self):
pass
def start_object(self):
pass
def end_object(self):
pass
def start_list(self):
pass
def end_list(self):
pass
def obj_key(self, s: str) -> bool:
return False
def obj_value_string(self, v: str):
pass
def obj_value_bool(self, b: bool):
pass
def obj_value_number(self, n : number):
pass
def obj_value_null(self):
pass
def loads(stream: Stream , cb: SJCallback):
c = stream.read(1)
if len(c) > 0:
cb.start()
side = False # False=left, True=right
while True:
if len(c) == 0:
break
if c == '"': # Begin of a string
s = ""
while True:
# TODO: \" is not managed
c = stream.read(1)
if c == '"':
break
elif len(c) == 0:
# TODO: error
pass
else:
s = s + c
if side == False:
skip = cb.obj_key(s)
if skip:
q = 0
g = 0
while True:
c = stream.read(1)
if c == '[':
q += 1
elif c == ']':
q -= 1
elif c == '{':
g += 1
elif c == '}' and g != 0:
g -= 1
elif c == '}' and g == 0:
break
elif c == ',' and g == 0 and q == 0:
break
elif len(c) == 0:
# TODO: error in parsing
break
else:
cb.obj_value_string(s)
if c.isdigit() or c == "-": # Parsing number
if c == "-":
d = 0
sign = -1
else:
d = int(c)
sign = 1
div = 0
while True:
# TODO: \" is not managed
c = stream.read(1)
if c == '.':
if div != 0:
# TODO: exception double point
pass
div = 1
elif not c.isdigit():
break
elif len(c) == 0:
# TODO: error
pass
else:
div *= 10
d = d*10 + int(c)
div = 1 if div == 0 else div
cb.obj_value_number(sign * d / div)
# Not an elif because c could be changed
if c == "{": # Begin of dictionaries
cb.start_object()
side = False
elif c == "}": # End of dictionaries
cb.end_object()
elif c == "[": # Begin of list
cb.start_list()
elif c == "]": # End of list
cb.end_list()
elif c == ":": # Separator of dictionaries
side = True
elif c == ",":
side = False
elif c == 't': # Start of True
c = stream.read(3)
if c == 'rue':
cb.obj_value_bool(True)
else:
# TODO: error in parsing
pass
elif c == 'f': # Start of False
c = stream.read(4)
if c == 'alse':
cb.obj_value_bool(False)
else:
# TODO: error in parsing
pass
elif c == 'n': # Start of null
c = stream.read(3)
if c == 'ull':
cb.obj_value_null()
else:
# TODO: error in parsing
pass
c = stream.read(1)
cb.end()