corrade-vassal – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 1 #region Header
2 /*
3 * JsonReader.cs
4 * Stream-like access to JSON text.
5 *
6 * The authors disclaim copyright to this source code. For more details, see
7 * the COPYING file included with this distribution.
8 */
9 #endregion
10  
11  
12 using System;
13 using System.Collections.Generic;
14 using System.IO;
15 using System.Text;
16  
17  
18 namespace LitJson
19 {
20 public enum JsonToken
21 {
22 None,
23  
24 ObjectStart,
25 PropertyName,
26 ObjectEnd,
27  
28 ArrayStart,
29 ArrayEnd,
30  
31 Int,
32 Long,
33 Double,
34  
35 String,
36  
37 Boolean,
38 Null
39 }
40  
41  
42 public class JsonReader
43 {
44 #region Fields
45 private static IDictionary<int, IDictionary<int, int[]>> parse_table;
46  
47 private Stack<int> automaton_stack;
48 private int current_input;
49 private int current_symbol;
50 private bool end_of_json;
51 private bool end_of_input;
52 private Lexer lexer;
53 private bool parser_in_string;
54 private bool parser_return;
55 private bool read_started;
56 private TextReader reader;
57 private bool reader_is_owned;
58 private object token_value;
59 private JsonToken token;
60 #endregion
61  
62  
63 #region Public Properties
64 public bool AllowComments {
65 get { return lexer.AllowComments; }
66 set { lexer.AllowComments = value; }
67 }
68  
69 public bool AllowSingleQuotedStrings {
70 get { return lexer.AllowSingleQuotedStrings; }
71 set { lexer.AllowSingleQuotedStrings = value; }
72 }
73  
74 public bool EndOfInput {
75 get { return end_of_input; }
76 }
77  
78 public bool EndOfJson {
79 get { return end_of_json; }
80 }
81  
82 public JsonToken Token {
83 get { return token; }
84 }
85  
86 public object Value {
87 get { return token_value; }
88 }
89 #endregion
90  
91  
92 #region Constructors
93 static JsonReader ()
94 {
95 PopulateParseTable ();
96 }
97  
98 public JsonReader (string json_text) :
99 this (new StringReader (json_text), true)
100 {
101 }
102  
103 public JsonReader (TextReader reader) :
104 this (reader, false)
105 {
106 }
107  
108 private JsonReader (TextReader reader, bool owned)
109 {
110 if (reader == null)
111 throw new ArgumentNullException ("reader");
112  
113 parser_in_string = false;
114 parser_return = false;
115  
116 read_started = false;
117 automaton_stack = new Stack<int> ();
118 automaton_stack.Push ((int) ParserToken.End);
119 automaton_stack.Push ((int) ParserToken.Text);
120  
121 lexer = new Lexer (reader);
122  
123 end_of_input = false;
124 end_of_json = false;
125  
126 this.reader = reader;
127 reader_is_owned = owned;
128 }
129 #endregion
130  
131  
132 #region Static Methods
133 private static void PopulateParseTable ()
134 {
135 parse_table = new Dictionary<int, IDictionary<int, int[]>> ();
136  
137 TableAddRow (ParserToken.Array);
138 TableAddCol (ParserToken.Array, '[',
139 '[',
140 (int) ParserToken.ArrayPrime);
141  
142 TableAddRow (ParserToken.ArrayPrime);
143 TableAddCol (ParserToken.ArrayPrime, '"',
144 (int) ParserToken.Value,
145  
146 (int) ParserToken.ValueRest,
147 ']');
148 TableAddCol (ParserToken.ArrayPrime, '[',
149 (int) ParserToken.Value,
150 (int) ParserToken.ValueRest,
151 ']');
152 TableAddCol (ParserToken.ArrayPrime, ']',
153 ']');
154 TableAddCol (ParserToken.ArrayPrime, '{',
155 (int) ParserToken.Value,
156 (int) ParserToken.ValueRest,
157 ']');
158 TableAddCol (ParserToken.ArrayPrime, (int) ParserToken.Number,
159 (int) ParserToken.Value,
160 (int) ParserToken.ValueRest,
161 ']');
162 TableAddCol (ParserToken.ArrayPrime, (int) ParserToken.True,
163 (int) ParserToken.Value,
164 (int) ParserToken.ValueRest,
165 ']');
166 TableAddCol (ParserToken.ArrayPrime, (int) ParserToken.False,
167 (int) ParserToken.Value,
168 (int) ParserToken.ValueRest,
169 ']');
170 TableAddCol (ParserToken.ArrayPrime, (int) ParserToken.Null,
171 (int) ParserToken.Value,
172 (int) ParserToken.ValueRest,
173 ']');
174  
175 TableAddRow (ParserToken.Object);
176 TableAddCol (ParserToken.Object, '{',
177 '{',
178 (int) ParserToken.ObjectPrime);
179  
180 TableAddRow (ParserToken.ObjectPrime);
181 TableAddCol (ParserToken.ObjectPrime, '"',
182 (int) ParserToken.Pair,
183 (int) ParserToken.PairRest,
184 '}');
185 TableAddCol (ParserToken.ObjectPrime, '}',
186 '}');
187  
188 TableAddRow (ParserToken.Pair);
189 TableAddCol (ParserToken.Pair, '"',
190 (int) ParserToken.String,
191 ':',
192 (int) ParserToken.Value);
193  
194 TableAddRow (ParserToken.PairRest);
195 TableAddCol (ParserToken.PairRest, ',',
196 ',',
197 (int) ParserToken.Pair,
198 (int) ParserToken.PairRest);
199 TableAddCol (ParserToken.PairRest, '}',
200 (int) ParserToken.Epsilon);
201  
202 TableAddRow (ParserToken.String);
203 TableAddCol (ParserToken.String, '"',
204 '"',
205 (int) ParserToken.CharSeq,
206 '"');
207  
208 TableAddRow (ParserToken.Text);
209 TableAddCol (ParserToken.Text, '[',
210 (int) ParserToken.Array);
211 TableAddCol (ParserToken.Text, '{',
212 (int) ParserToken.Object);
213  
214 TableAddRow (ParserToken.Value);
215 TableAddCol (ParserToken.Value, '"',
216 (int) ParserToken.String);
217 TableAddCol (ParserToken.Value, '[',
218 (int) ParserToken.Array);
219 TableAddCol (ParserToken.Value, '{',
220 (int) ParserToken.Object);
221 TableAddCol (ParserToken.Value, (int) ParserToken.Number,
222 (int) ParserToken.Number);
223 TableAddCol (ParserToken.Value, (int) ParserToken.True,
224 (int) ParserToken.True);
225 TableAddCol (ParserToken.Value, (int) ParserToken.False,
226 (int) ParserToken.False);
227 TableAddCol (ParserToken.Value, (int) ParserToken.Null,
228 (int) ParserToken.Null);
229  
230 TableAddRow (ParserToken.ValueRest);
231 TableAddCol (ParserToken.ValueRest, ',',
232 ',',
233 (int) ParserToken.Value,
234 (int) ParserToken.ValueRest);
235 TableAddCol (ParserToken.ValueRest, ']',
236 (int) ParserToken.Epsilon);
237 }
238  
239 private static void TableAddCol (ParserToken row, int col,
240 params int[] symbols)
241 {
242 parse_table[(int) row].Add (col, symbols);
243 }
244  
245 private static void TableAddRow (ParserToken rule)
246 {
247 parse_table.Add ((int) rule, new Dictionary<int, int[]> ());
248 }
249 #endregion
250  
251  
252 #region Private Methods
253 private void ProcessNumber (string number)
254 {
255 if (number.IndexOf ('.') != -1 ||
256 number.IndexOf ('e') != -1 ||
257 number.IndexOf ('E') != -1) {
258  
259 double n_double;
260 if (Double.TryParse (number, out n_double)) {
261 token = JsonToken.Double;
262 token_value = n_double;
263  
264 return;
265 }
266 }
267  
268 int n_int32;
269 if (Int32.TryParse (number, out n_int32)) {
270 token = JsonToken.Int;
271 token_value = n_int32;
272  
273 return;
274 }
275  
276 long n_int64;
277 if (Int64.TryParse (number, out n_int64)) {
278 token = JsonToken.Long;
279 token_value = n_int64;
280  
281 return;
282 }
283  
284 // Shouldn't happen, but just in case, return something
285 token = JsonToken.Int;
286 token_value = 0;
287 }
288  
289 private void ProcessSymbol ()
290 {
291 if (current_symbol == '[') {
292 token = JsonToken.ArrayStart;
293 parser_return = true;
294  
295 } else if (current_symbol == ']') {
296 token = JsonToken.ArrayEnd;
297 parser_return = true;
298  
299 } else if (current_symbol == '{') {
300 token = JsonToken.ObjectStart;
301 parser_return = true;
302  
303 } else if (current_symbol == '}') {
304 token = JsonToken.ObjectEnd;
305 parser_return = true;
306  
307 } else if (current_symbol == '"') {
308 if (parser_in_string) {
309 parser_in_string = false;
310  
311 parser_return = true;
312  
313 } else {
314 if (token == JsonToken.None)
315 token = JsonToken.String;
316  
317 parser_in_string = true;
318 }
319  
320 } else if (current_symbol == (int) ParserToken.CharSeq) {
321 token_value = lexer.StringValue;
322  
323 } else if (current_symbol == (int) ParserToken.False) {
324 token = JsonToken.Boolean;
325 token_value = false;
326 parser_return = true;
327  
328 } else if (current_symbol == (int) ParserToken.Null) {
329 token = JsonToken.Null;
330 parser_return = true;
331  
332 } else if (current_symbol == (int) ParserToken.Number) {
333 ProcessNumber (lexer.StringValue);
334  
335 parser_return = true;
336  
337 } else if (current_symbol == (int) ParserToken.Pair) {
338 token = JsonToken.PropertyName;
339  
340 } else if (current_symbol == (int) ParserToken.True) {
341 token = JsonToken.Boolean;
342 token_value = true;
343 parser_return = true;
344  
345 }
346 }
347  
348 private bool ReadToken ()
349 {
350 if (end_of_input)
351 return false;
352  
353 lexer.NextToken ();
354  
355 if (lexer.EndOfInput) {
356 Close ();
357  
358 return false;
359 }
360  
361 current_input = lexer.Token;
362  
363 return true;
364 }
365 #endregion
366  
367  
368 public void Close ()
369 {
370 if (end_of_input)
371 return;
372  
373 end_of_input = true;
374 end_of_json = true;
375  
376 if (reader_is_owned)
377 reader.Close ();
378  
379 reader = null;
380 }
381  
382 public bool Read ()
383 {
384 if (end_of_input)
385 return false;
386  
387 if (end_of_json) {
388 end_of_json = false;
389 automaton_stack.Clear ();
390 automaton_stack.Push ((int) ParserToken.End);
391 automaton_stack.Push ((int) ParserToken.Text);
392 }
393  
394 parser_in_string = false;
395 parser_return = false;
396  
397 token = JsonToken.None;
398 token_value = null;
399  
400 if (! read_started) {
401 read_started = true;
402  
403 if (! ReadToken ())
404 return false;
405 }
406  
407  
408 int[] entry_symbols;
409  
410 while (true) {
411 if (parser_return) {
412 if (automaton_stack.Peek () == (int) ParserToken.End)
413 end_of_json = true;
414  
415 return true;
416 }
417  
418 current_symbol = automaton_stack.Pop ();
419  
420 ProcessSymbol ();
421  
422 if (current_symbol == current_input) {
423 if (! ReadToken ()) {
424 if (automaton_stack.Peek () != (int) ParserToken.End)
425 throw new JsonException (
426 "Input doesn't evaluate to proper JSON text");
427  
428 if (parser_return)
429 return true;
430  
431 return false;
432 }
433  
434 continue;
435 }
436  
437 try {
438  
439 entry_symbols =
440 parse_table[current_symbol][current_input];
441  
442 } catch (KeyNotFoundException e) {
443 throw new JsonException ((ParserToken) current_input, e);
444 }
445  
446 if (entry_symbols[0] == (int) ParserToken.Epsilon)
447 continue;
448  
449 for (int i = entry_symbols.Length - 1; i >= 0; i--)
450 automaton_stack.Push (entry_symbols[i]);
451 }
452 }
453  
454 }
455 }