/
JONReader.java
153 lines (112 loc) · 3.25 KB
/
JONReader.java
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
package jon.io;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.util.Stack;
import jon.exceptions.JONReadException;
import jon.model.JONEntity;
import jon.model.JONValue;
import static jon.JONSymbols.*;
public class JONReader extends InputStreamReader {
protected final Stack<JONEntity> entityStack = new Stack<>();
protected final Stack<String> nameStack = new Stack<>();
protected final Stack<String> typeStack = new Stack<>();
protected boolean ignoring = false;
public JONReader(InputStream in, Charset cs) {
super(in, cs);
}
public JONReader(InputStream in, CharsetDecoder dec) {
super(in, dec);
}
public JONReader(InputStream in, String charsetName) throws UnsupportedEncodingException {
super(in, charsetName);
}
public JONReader(InputStream in) {
super(in);
}
public JONEntity readEntity() throws IOException {
int last = -1;
JONEntity entity = null;
StringBuilder buffer = new StringBuilder(1024);
do {
last = read();
// fuck whitespace
if(Character.isWhitespace(last)) continue;
char lastChar = (char) last;
if(lastChar == COMMENT) {
ignoring = !ignoring;
continue;
}
if(ignoring) continue;
switch(lastChar) {
case ENTITY_START:
entityStack.push(new JONEntity(buffer.toString()));
clear(buffer);
break;
case ENTITY_END:
JONEntity lastEntity = entityStack.pop();
if(entityStack.empty()) {
entity = lastEntity;
break;
}
entityStack.peek().addChild(lastEntity);
break;
case VALUE_TAGGER:
nameStack.push(buffer.toString());
clear(buffer);
break;
case VALUE_START:
typeStack.push(buffer.toString());
clear(buffer);
break;
case VALUE_END:
entityStack.peek().addChild(new JONValue(nameStack.pop(), typeStack.pop(), buffer.toString()));
clear(buffer);
break;
default:
buffer.append(lastChar);
//System.out.println("buffer: " + buffer);
break;
}
} while(last != -1);
if(entity == null) throw new JONReadException("No entity found!");
return entity;
}
public JONValue readValue() throws IOException {
int last = -1;
StringBuilder buffer = new StringBuilder(64);
String name = null;
String type = null;
do {
last = read();
char lastChar = (char) last;
switch(lastChar) {
case VALUE_TAGGER:
name = buffer.toString();
clear(buffer);
break;
case VALUE_START:
type = buffer.toString();
clear(buffer);
break;
case VALUE_END:
if(name == null) throw new JONReadException("Name was null!");
if(type == null) throw new JONReadException("Type was null");
if(name.isEmpty()) throw new JONReadException("Name was empty!");
if(type.isEmpty()) throw new JONReadException("Type was empty!");
return new JONValue(name, type, buffer.toString());
default:
buffer.append(lastChar);
break;
}
} while(last != -1);
return null;
}
// if anyone knows a better way to reuse a StringBuilder, tell me
private static void clear(StringBuilder buffer) {
buffer.setLength(0);
}
}