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
|
package json_array
import (
"main/walk"
"encoding/json"
"errors"
"bufio"
)
type state int
const (
stateStart state = iota
stateValueStart
stateEnd
stateDead
)
func atomiseValue(value interface{}) []walk.Atom {
switch v := value.(type) {
case nil:
return []walk.Atom{walk.NewAtomNull()}
case bool:
return []walk.Atom{walk.NewAtomBool(v)}
case float64:
return []walk.Atom{walk.NewAtomNumber(v)}
case string:
atoms := []walk.Atom{walk.NewAtomStringTerminal()}
for _, r := range v {
atoms = append(atoms, walk.NewAtomStringRune(r))
}
atoms = append(atoms, walk.NewAtomStringTerminal())
return atoms
case []interface{}:
atoms := []walk.Atom{walk.NewAtomTerminal(walk.ArrayBegin)}
for _, element := range v {
atoms = append(atoms, atomiseValue(element)...)
}
atoms = append(atoms, walk.NewAtomTerminal(walk.ArrayEnd))
return atoms
case map[string]interface{}:
atoms := []walk.Atom{walk.NewAtomTerminal(walk.MapBegin)}
for key, element := range v {
atoms = append(atoms, atomiseValue(key)...)
atoms = append(atoms, atomiseValue(element)...)
}
atoms = append(atoms, walk.NewAtomTerminal(walk.MapEnd))
return atoms
default:
panic("Invalid JSON value type")
}
}
func NewJSONArrayReader(reader *bufio.Reader) *JSONArrayReader {
return &JSONArrayReader {
decoder: json.NewDecoder(reader),
state: stateStart,
index: 0,
}
}
type JSONArrayReader struct {
decoder *json.Decoder
state state
index int
}
func (in *JSONArrayReader) Read() (walk.WalkItem, error) {
restart:
switch in.state {
case stateStart:
arrayStart, err := in.decoder.Token()
if err != nil {
panic("Error reading start of JSON array")
}
delim, isDelim := arrayStart.(json.Delim)
if !isDelim || delim != '[' {
panic("JSON input is not an array!")
}
in.state = stateValueStart
goto restart
case stateValueStart:
if !in.decoder.More() {
in.state = stateEnd
goto restart
}
var m interface{}
err := in.decoder.Decode(&m)
if err != nil {
panic("Error decoding array value")
}
in.index += 1
return walk.WalkItem {
Path: []walk.Atom{walk.NewAtomNumber(float64(in.index - 1))},
Value: atomiseValue(m),
}, nil
case stateEnd:
arrayEnd, err := in.decoder.Token()
if err != nil {
panic("Error reading end of JSON array")
}
delim, isDelim := arrayEnd.(json.Delim)
if !isDelim || delim != ']' {
panic("JSON array wasn't ended")
}
in.state = stateDead
return walk.WalkItem{}, errors.New("eof")
case stateDead:
return walk.WalkItem{}, errors.New("eof")
default:
panic("Unreachable!!!")
}
}
func (in *JSONArrayReader) AssertDone() {
if in.state != stateDead || in.decoder.More() {
panic("More JSON after array value")
}
}
|