oj 3.11.0 → 3.11.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -1
  3. data/ext/oj/buf.h +34 -38
  4. data/ext/oj/cache8.c +59 -62
  5. data/ext/oj/cache8.h +8 -7
  6. data/ext/oj/circarray.c +33 -35
  7. data/ext/oj/circarray.h +11 -9
  8. data/ext/oj/code.c +170 -174
  9. data/ext/oj/code.h +21 -20
  10. data/ext/oj/compat.c +159 -166
  11. data/ext/oj/custom.c +802 -851
  12. data/ext/oj/dump.c +766 -778
  13. data/ext/oj/dump.h +49 -51
  14. data/ext/oj/dump_compat.c +1 -0
  15. data/ext/oj/dump_leaf.c +116 -157
  16. data/ext/oj/dump_object.c +609 -628
  17. data/ext/oj/dump_strict.c +318 -327
  18. data/ext/oj/encode.h +3 -4
  19. data/ext/oj/err.c +39 -25
  20. data/ext/oj/err.h +24 -15
  21. data/ext/oj/extconf.rb +2 -1
  22. data/ext/oj/fast.c +1008 -1038
  23. data/ext/oj/hash.c +62 -66
  24. data/ext/oj/hash.h +7 -6
  25. data/ext/oj/hash_test.c +450 -443
  26. data/ext/oj/mimic_json.c +413 -402
  27. data/ext/oj/object.c +559 -528
  28. data/ext/oj/odd.c +123 -128
  29. data/ext/oj/odd.h +27 -25
  30. data/ext/oj/oj.c +1131 -924
  31. data/ext/oj/oj.h +286 -298
  32. data/ext/oj/parse.c +938 -930
  33. data/ext/oj/parse.h +70 -69
  34. data/ext/oj/rails.c +836 -839
  35. data/ext/oj/rails.h +7 -7
  36. data/ext/oj/reader.c +135 -140
  37. data/ext/oj/reader.h +66 -79
  38. data/ext/oj/resolve.c +43 -43
  39. data/ext/oj/resolve.h +3 -2
  40. data/ext/oj/rxclass.c +67 -68
  41. data/ext/oj/rxclass.h +12 -10
  42. data/ext/oj/saj.c +451 -479
  43. data/ext/oj/scp.c +93 -103
  44. data/ext/oj/sparse.c +770 -730
  45. data/ext/oj/stream_writer.c +120 -149
  46. data/ext/oj/strict.c +71 -86
  47. data/ext/oj/string_writer.c +198 -243
  48. data/ext/oj/trace.c +29 -33
  49. data/ext/oj/trace.h +14 -11
  50. data/ext/oj/util.c +103 -103
  51. data/ext/oj/util.h +3 -2
  52. data/ext/oj/val_stack.c +47 -47
  53. data/ext/oj/val_stack.h +79 -86
  54. data/ext/oj/wab.c +291 -309
  55. data/lib/oj/bag.rb +1 -0
  56. data/lib/oj/easy_hash.rb +5 -4
  57. data/lib/oj/mimic.rb +0 -12
  58. data/lib/oj/version.rb +1 -1
  59. data/test/activerecord/result_test.rb +7 -2
  60. data/test/foo.rb +35 -32
  61. data/test/helper.rb +10 -0
  62. data/test/json_gem/json_generator_test.rb +15 -3
  63. data/test/json_gem/test_helper.rb +8 -0
  64. data/test/test_compat.rb +2 -2
  65. data/test/test_generate.rb +21 -0
  66. data/test/test_hash.rb +10 -0
  67. data/test/test_scp.rb +1 -1
  68. metadata +4 -2
data/ext/oj/scp.c CHANGED
@@ -1,39 +1,34 @@
1
1
  // Copyright (c) 2012 Peter Ohler. All rights reserved.
2
+ // Licensed under the MIT License. See LICENSE file in the project root for license details.
2
3
 
3
- #include <stdlib.h>
4
+ #include <math.h>
4
5
  #include <stdio.h>
6
+ #include <stdlib.h>
5
7
  #include <string.h>
6
- #include <math.h>
7
8
  #include <sys/types.h>
8
9
  #include <unistd.h>
9
10
 
11
+ #include "encode.h"
10
12
  #include "oj.h"
11
13
  #include "parse.h"
12
- #include "encode.h"
13
14
 
14
- static VALUE
15
- noop_start(ParseInfo pi) {
15
+ static VALUE noop_start(ParseInfo pi) {
16
16
  return Qnil;
17
17
  }
18
18
 
19
- static void
20
- noop_end(ParseInfo pi) {
19
+ static void noop_end(ParseInfo pi) {
21
20
  }
22
21
 
23
- static void
24
- noop_add_value(ParseInfo pi, VALUE val) {
22
+ static void noop_add_value(ParseInfo pi, VALUE val) {
25
23
  }
26
24
 
27
- static void
28
- noop_add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
25
+ static void noop_add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
29
26
  }
30
27
 
31
- static void
32
- noop_add_num(ParseInfo pi, NumInfo ni) {
28
+ static void noop_add_num(ParseInfo pi, NumInfo ni) {
33
29
  }
34
30
 
35
- static VALUE
36
- noop_hash_key(ParseInfo pi, const char *key, size_t klen) {
31
+ static VALUE noop_hash_key(ParseInfo pi, const char *key, size_t klen) {
37
32
  return Qundef;
38
33
  }
39
34
 
@@ -41,181 +36,176 @@ static void
41
36
  noop_hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, const char *orig) {
42
37
  }
43
38
 
44
- static void
45
- noop_hash_set_num(ParseInfo pi, Val kval, NumInfo ni) {
39
+ static void noop_hash_set_num(ParseInfo pi, Val kval, NumInfo ni) {
46
40
  }
47
41
 
48
- static void
49
- noop_hash_set_value(ParseInfo pi, Val kval, VALUE value) {
42
+ static void noop_hash_set_value(ParseInfo pi, Val kval, VALUE value) {
50
43
  }
51
44
 
52
- static void
53
- noop_array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
45
+ static void noop_array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
54
46
  }
55
47
 
56
- static void
57
- noop_array_append_num(ParseInfo pi, NumInfo ni) {
48
+ static void noop_array_append_num(ParseInfo pi, NumInfo ni) {
58
49
  }
59
50
 
60
- static void
61
- noop_array_append_value(ParseInfo pi, VALUE value) {
51
+ static void noop_array_append_value(ParseInfo pi, VALUE value) {
62
52
  }
63
53
 
64
- static void
65
- add_value(ParseInfo pi, VALUE val) {
54
+ static void add_value(ParseInfo pi, VALUE val) {
66
55
  rb_funcall(pi->handler, oj_add_value_id, 1, val);
67
56
  }
68
57
 
69
- static void
70
- add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
71
- volatile VALUE rstr = rb_str_new(str, len);
58
+ static void add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
59
+ volatile VALUE rstr = rb_str_new(str, len);
72
60
 
73
61
  rstr = oj_encode(rstr);
74
62
  rb_funcall(pi->handler, oj_add_value_id, 1, rstr);
75
63
  }
76
64
 
77
- static void
78
- add_num(ParseInfo pi, NumInfo ni) {
65
+ static void add_num(ParseInfo pi, NumInfo ni) {
79
66
  rb_funcall(pi->handler, oj_add_value_id, 1, oj_num_as_value(ni));
80
67
  }
81
68
 
82
- static VALUE
83
- start_hash(ParseInfo pi) {
69
+ static VALUE start_hash(ParseInfo pi) {
84
70
  return rb_funcall(pi->handler, oj_hash_start_id, 0);
85
71
  }
86
72
 
87
- static void
88
- end_hash(ParseInfo pi) {
73
+ static void end_hash(ParseInfo pi) {
89
74
  rb_funcall(pi->handler, oj_hash_end_id, 0);
90
75
  }
91
76
 
92
- static VALUE
93
- start_array(ParseInfo pi) {
77
+ static VALUE start_array(ParseInfo pi) {
94
78
  return rb_funcall(pi->handler, oj_array_start_id, 0);
95
79
  }
96
80
 
97
- static void
98
- end_array(ParseInfo pi) {
81
+ static void end_array(ParseInfo pi) {
99
82
  rb_funcall(pi->handler, oj_array_end_id, 0);
100
83
  }
101
84
 
102
- static VALUE
103
- calc_hash_key(ParseInfo pi, Val kval) {
104
- volatile VALUE rkey = kval->key_val;
85
+ static VALUE calc_hash_key(ParseInfo pi, Val kval) {
86
+ volatile VALUE rkey = kval->key_val;
105
87
 
106
88
  if (Qundef == rkey) {
107
- rkey = rb_str_new(kval->key, kval->klen);
108
- rkey = oj_encode(rkey);
109
- if (Yes == pi->options.sym_key) {
110
- rkey = rb_str_intern(rkey);
111
- }
89
+ rkey = rb_str_new(kval->key, kval->klen);
90
+ rkey = oj_encode(rkey);
91
+ if (Yes == pi->options.sym_key) {
92
+ rkey = rb_str_intern(rkey);
93
+ }
112
94
  }
113
95
  return rkey;
114
96
  }
115
97
 
116
- static VALUE
117
- hash_key(ParseInfo pi, const char *key, size_t klen) {
98
+ static VALUE hash_key(ParseInfo pi, const char *key, size_t klen) {
118
99
  return rb_funcall(pi->handler, oj_hash_key_id, 1, rb_str_new(key, klen));
119
100
  }
120
101
 
121
- static void
122
- hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, const char *orig) {
123
- volatile VALUE rstr = rb_str_new(str, len);
102
+ static void hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, const char *orig) {
103
+ volatile VALUE rstr = rb_str_new(str, len);
124
104
 
125
105
  rstr = oj_encode(rstr);
126
- rb_funcall(pi->handler, oj_hash_set_id, 3, stack_peek(&pi->stack)->val, calc_hash_key(pi, kval), rstr);
106
+ rb_funcall(pi->handler,
107
+ oj_hash_set_id,
108
+ 3,
109
+ stack_peek(&pi->stack)->val,
110
+ calc_hash_key(pi, kval),
111
+ rstr);
127
112
  }
128
113
 
129
- static void
130
- hash_set_num(ParseInfo pi, Val kval, NumInfo ni) {
131
- rb_funcall(pi->handler, oj_hash_set_id, 3, stack_peek(&pi->stack)->val, calc_hash_key(pi, kval), oj_num_as_value(ni));
114
+ static void hash_set_num(ParseInfo pi, Val kval, NumInfo ni) {
115
+ rb_funcall(pi->handler,
116
+ oj_hash_set_id,
117
+ 3,
118
+ stack_peek(&pi->stack)->val,
119
+ calc_hash_key(pi, kval),
120
+ oj_num_as_value(ni));
132
121
  }
133
122
 
134
- static void
135
- hash_set_value(ParseInfo pi, Val kval, VALUE value) {
136
- rb_funcall(pi->handler, oj_hash_set_id, 3, stack_peek(&pi->stack)->val, calc_hash_key(pi, kval), value);
123
+ static void hash_set_value(ParseInfo pi, Val kval, VALUE value) {
124
+ rb_funcall(pi->handler,
125
+ oj_hash_set_id,
126
+ 3,
127
+ stack_peek(&pi->stack)->val,
128
+ calc_hash_key(pi, kval),
129
+ value);
137
130
  }
138
131
 
139
- static void
140
- array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
141
- volatile VALUE rstr = rb_str_new(str, len);
132
+ static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
133
+ volatile VALUE rstr = rb_str_new(str, len);
142
134
 
143
135
  rstr = oj_encode(rstr);
144
136
  rb_funcall(pi->handler, oj_array_append_id, 2, stack_peek(&pi->stack)->val, rstr);
145
137
  }
146
138
 
147
- static void
148
- array_append_num(ParseInfo pi, NumInfo ni) {
139
+ static void array_append_num(ParseInfo pi, NumInfo ni) {
149
140
  rb_funcall(pi->handler, oj_array_append_id, 2, stack_peek(&pi->stack)->val, oj_num_as_value(ni));
150
141
  }
151
142
 
152
- static void
153
- array_append_value(ParseInfo pi, VALUE value) {
143
+ static void array_append_value(ParseInfo pi, VALUE value) {
154
144
  rb_funcall(pi->handler, oj_array_append_id, 2, stack_peek(&pi->stack)->val, value);
155
145
  }
156
146
 
157
147
  VALUE
158
148
  oj_sc_parse(int argc, VALUE *argv, VALUE self) {
159
- struct _parseInfo pi;
160
- VALUE input = argv[1];
149
+ struct _parseInfo pi;
150
+ VALUE input = argv[1];
161
151
 
162
152
  parse_info_init(&pi);
163
153
  pi.err_class = Qnil;
164
154
  pi.max_depth = 0;
165
- pi.options = oj_default_options;
155
+ pi.options = oj_default_options;
166
156
  if (3 == argc) {
167
- oj_parse_options(argv[2], &pi.options);
157
+ oj_parse_options(argv[2], &pi.options);
168
158
  }
169
159
  if (rb_block_given_p()) {
170
- pi.proc = Qnil;
160
+ pi.proc = Qnil;
171
161
  } else {
172
- pi.proc = Qundef;
162
+ pi.proc = Qundef;
173
163
  }
174
164
  pi.handler = *argv;
175
165
 
176
- pi.start_hash = rb_respond_to(pi.handler, oj_hash_start_id) ? start_hash : noop_start;
177
- pi.end_hash = rb_respond_to(pi.handler, oj_hash_end_id) ? end_hash : noop_end;
178
- pi.hash_key = rb_respond_to(pi.handler, oj_hash_key_id) ? hash_key : noop_hash_key;
166
+ pi.start_hash = rb_respond_to(pi.handler, oj_hash_start_id) ? start_hash : noop_start;
167
+ pi.end_hash = rb_respond_to(pi.handler, oj_hash_end_id) ? end_hash : noop_end;
168
+ pi.hash_key = rb_respond_to(pi.handler, oj_hash_key_id) ? hash_key : noop_hash_key;
179
169
  pi.start_array = rb_respond_to(pi.handler, oj_array_start_id) ? start_array : noop_start;
180
- pi.end_array = rb_respond_to(pi.handler, oj_array_end_id) ? end_array : noop_end;
170
+ pi.end_array = rb_respond_to(pi.handler, oj_array_end_id) ? end_array : noop_end;
181
171
  if (rb_respond_to(pi.handler, oj_hash_set_id)) {
182
- pi.hash_set_value = hash_set_value;
183
- pi.hash_set_cstr = hash_set_cstr;
184
- pi.hash_set_num = hash_set_num;
185
- pi.expect_value = 1;
172
+ pi.hash_set_value = hash_set_value;
173
+ pi.hash_set_cstr = hash_set_cstr;
174
+ pi.hash_set_num = hash_set_num;
175
+ pi.expect_value = 1;
186
176
  } else {
187
- pi.hash_set_value = noop_hash_set_value;
188
- pi.hash_set_cstr = noop_hash_set_cstr;
189
- pi.hash_set_num = noop_hash_set_num;
190
- pi.expect_value = 0;
177
+ pi.hash_set_value = noop_hash_set_value;
178
+ pi.hash_set_cstr = noop_hash_set_cstr;
179
+ pi.hash_set_num = noop_hash_set_num;
180
+ pi.expect_value = 0;
191
181
  }
192
182
  if (rb_respond_to(pi.handler, oj_array_append_id)) {
193
- pi.array_append_value = array_append_value;
194
- pi.array_append_cstr = array_append_cstr;
195
- pi.array_append_num = array_append_num;
196
- pi.expect_value = 1;
183
+ pi.array_append_value = array_append_value;
184
+ pi.array_append_cstr = array_append_cstr;
185
+ pi.array_append_num = array_append_num;
186
+ pi.expect_value = 1;
197
187
  } else {
198
- pi.array_append_value = noop_array_append_value;
199
- pi.array_append_cstr = noop_array_append_cstr;
200
- pi.array_append_num = noop_array_append_num;
201
- pi.expect_value = 0;
188
+ pi.array_append_value = noop_array_append_value;
189
+ pi.array_append_cstr = noop_array_append_cstr;
190
+ pi.array_append_num = noop_array_append_num;
191
+ pi.expect_value = 0;
202
192
  }
203
193
  if (rb_respond_to(pi.handler, oj_add_value_id)) {
204
- pi.add_cstr = add_cstr;
205
- pi.add_num = add_num;
206
- pi.add_value = add_value;
207
- pi.expect_value = 1;
194
+ pi.add_cstr = add_cstr;
195
+ pi.add_num = add_num;
196
+ pi.add_value = add_value;
197
+ pi.expect_value = 1;
208
198
  } else {
209
- pi.add_cstr = noop_add_cstr;
210
- pi.add_num = noop_add_num;
211
- pi.add_value = noop_add_value;
212
- pi.expect_value = 0;
199
+ pi.add_cstr = noop_add_cstr;
200
+ pi.add_num = noop_add_num;
201
+ pi.add_value = noop_add_value;
202
+ pi.expect_value = 0;
213
203
  }
214
204
  pi.has_callbacks = true;
215
205
 
216
206
  if (T_STRING == rb_type(input)) {
217
- return oj_pi_parse(argc - 1, argv + 1, &pi, 0, 0, 1);
207
+ return oj_pi_parse(argc - 1, argv + 1, &pi, 0, 0, 1);
218
208
  } else {
219
- return oj_pi_sparse(argc - 1, argv + 1, &pi, 0);
209
+ return oj_pi_sparse(argc - 1, argv + 1, &pi, 0);
220
210
  }
221
211
  }
data/ext/oj/sparse.c CHANGED
@@ -1,814 +1,854 @@
1
1
  // Copyright (c) 2013 Peter Ohler. All rights reserved.
2
+ // Licensed under the MIT License. See LICENSE file in the project root for license details.
2
3
 
3
- #include <stdlib.h>
4
+ #include <math.h>
4
5
  #include <stdio.h>
6
+ #include <stdlib.h>
5
7
  #include <string.h>
6
8
  #include <unistd.h>
7
- #include <math.h>
8
9
 
9
- #include "oj.h"
10
+ #include "buf.h"
10
11
  #include "encode.h"
12
+ #include "hash.h" // for oj_strndup()
13
+ #include "oj.h"
11
14
  #include "parse.h"
12
- #include "buf.h"
13
- #include "hash.h" // for oj_strndup()
14
15
  #include "val_stack.h"
15
16
 
16
17
  // Workaround in case INFINITY is not defined in math.h or if the OS is CentOS
17
- #define OJ_INFINITY (1.0/0.0)
18
+ #define OJ_INFINITY (1.0 / 0.0)
18
19
 
19
20
  #ifdef RUBINIUS_RUBY
20
- #define NUM_MAX 0x07FFFFFF
21
+ #define NUM_MAX 0x07FFFFFF
21
22
  #else
22
- #define NUM_MAX (FIXNUM_MAX >> 8)
23
+ #define NUM_MAX (FIXNUM_MAX >> 8)
23
24
  #endif
24
- #define EXP_MAX 100000
25
- #define DEC_MAX 15
25
+ #define EXP_MAX 100000
26
+ #define DEC_MAX 15
26
27
 
27
- static void
28
- skip_comment(ParseInfo pi) {
29
- char c = reader_get(&pi->rd);
28
+ static void skip_comment(ParseInfo pi) {
29
+ char c = reader_get(&pi->rd);
30
30
 
31
31
  if ('*' == c) {
32
- while ('\0' != (c = reader_get(&pi->rd))) {
33
- if ('*' == c) {
34
- c = reader_get(&pi->rd);
35
- if ('/' == c) {
36
- return;
37
- }
38
- }
39
- }
32
+ while ('\0' != (c = reader_get(&pi->rd))) {
33
+ if ('*' == c) {
34
+ c = reader_get(&pi->rd);
35
+ if ('/' == c) {
36
+ return;
37
+ }
38
+ }
39
+ }
40
40
  } else if ('/' == c) {
41
- while ('\0' != (c = reader_get(&pi->rd))) {
42
- switch (c) {
43
- case '\n':
44
- case '\r':
45
- case '\f':
46
- case '\0':
47
- return;
48
- default:
49
- break;
50
- }
51
- }
41
+ while ('\0' != (c = reader_get(&pi->rd))) {
42
+ switch (c) {
43
+ case '\n':
44
+ case '\r':
45
+ case '\f':
46
+ case '\0': return;
47
+ default: break;
48
+ }
49
+ }
52
50
  } else {
53
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid comment format");
51
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid comment format");
54
52
  }
55
53
  if ('\0' == c) {
56
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "comment not terminated");
57
- return;
54
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "comment not terminated");
55
+ return;
58
56
  }
59
57
  }
60
58
 
61
- static void
62
- add_value(ParseInfo pi, VALUE rval) {
63
- Val parent = stack_peek(&pi->stack);
59
+ static void add_value(ParseInfo pi, VALUE rval) {
60
+ Val parent = stack_peek(&pi->stack);
64
61
 
65
- if (0 == parent) { // simple add
66
- pi->add_value(pi, rval);
62
+ if (0 == parent) { // simple add
63
+ pi->add_value(pi, rval);
67
64
  } else {
68
- switch (parent->next) {
69
- case NEXT_ARRAY_NEW:
70
- case NEXT_ARRAY_ELEMENT:
71
- pi->array_append_value(pi, rval);
72
- parent->next = NEXT_ARRAY_COMMA;
73
- break;
74
- case NEXT_HASH_VALUE:
75
- pi->hash_set_value(pi, parent, rval);
76
- if (parent->kalloc) {
77
- xfree((char*)parent->key);
78
- }
79
- parent->key = 0;
80
- parent->kalloc = 0;
81
- parent->next = NEXT_HASH_COMMA;
82
- break;
83
- case NEXT_HASH_NEW:
84
- case NEXT_HASH_KEY:
85
- case NEXT_HASH_COMMA:
86
- case NEXT_NONE:
87
- case NEXT_ARRAY_COMMA:
88
- case NEXT_HASH_COLON:
89
- default:
90
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected %s", oj_stack_next_string(parent->next));
91
- break;
92
- }
65
+ switch (parent->next) {
66
+ case NEXT_ARRAY_NEW:
67
+ case NEXT_ARRAY_ELEMENT:
68
+ pi->array_append_value(pi, rval);
69
+ parent->next = NEXT_ARRAY_COMMA;
70
+ break;
71
+ case NEXT_HASH_VALUE:
72
+ pi->hash_set_value(pi, parent, rval);
73
+ if (parent->kalloc) {
74
+ xfree((char *)parent->key);
75
+ }
76
+ parent->key = 0;
77
+ parent->kalloc = 0;
78
+ parent->next = NEXT_HASH_COMMA;
79
+ break;
80
+ case NEXT_HASH_NEW:
81
+ case NEXT_HASH_KEY:
82
+ case NEXT_HASH_COMMA:
83
+ case NEXT_NONE:
84
+ case NEXT_ARRAY_COMMA:
85
+ case NEXT_HASH_COLON:
86
+ default:
87
+ oj_set_error_at(pi,
88
+ oj_parse_error_class,
89
+ __FILE__,
90
+ __LINE__,
91
+ "expected %s",
92
+ oj_stack_next_string(parent->next));
93
+ break;
94
+ }
93
95
  }
94
96
  }
95
97
 
96
- static void
97
- add_num_value(ParseInfo pi, NumInfo ni) {
98
- Val parent = stack_peek(&pi->stack);
98
+ static void add_num_value(ParseInfo pi, NumInfo ni) {
99
+ Val parent = stack_peek(&pi->stack);
99
100
 
100
101
  if (0 == parent) {
101
- pi->add_num(pi, ni);
102
+ pi->add_num(pi, ni);
102
103
  } else {
103
- switch (parent->next) {
104
- case NEXT_ARRAY_NEW:
105
- case NEXT_ARRAY_ELEMENT:
106
- pi->array_append_num(pi, ni);
107
- parent->next = NEXT_ARRAY_COMMA;
108
- break;
109
- case NEXT_HASH_VALUE:
110
- pi->hash_set_num(pi, parent, ni);
111
- if (parent->kalloc) {
112
- xfree((char*)parent->key);
113
- }
114
- parent->key = 0;
115
- parent->kalloc = 0;
116
- parent->next = NEXT_HASH_COMMA;
117
- break;
118
- default:
119
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected %s", oj_stack_next_string(parent->next));
120
- break;
121
- }
104
+ switch (parent->next) {
105
+ case NEXT_ARRAY_NEW:
106
+ case NEXT_ARRAY_ELEMENT:
107
+ pi->array_append_num(pi, ni);
108
+ parent->next = NEXT_ARRAY_COMMA;
109
+ break;
110
+ case NEXT_HASH_VALUE:
111
+ pi->hash_set_num(pi, parent, ni);
112
+ if (parent->kalloc) {
113
+ xfree((char *)parent->key);
114
+ }
115
+ parent->key = 0;
116
+ parent->kalloc = 0;
117
+ parent->next = NEXT_HASH_COMMA;
118
+ break;
119
+ default:
120
+ oj_set_error_at(pi,
121
+ oj_parse_error_class,
122
+ __FILE__,
123
+ __LINE__,
124
+ "expected %s",
125
+ oj_stack_next_string(parent->next));
126
+ break;
127
+ }
122
128
  }
123
129
  }
124
130
 
125
- static void
126
- read_true(ParseInfo pi) {
131
+ static void read_true(ParseInfo pi) {
127
132
  if (0 == reader_expect(&pi->rd, "rue")) {
128
- add_value(pi, Qtrue);
133
+ add_value(pi, Qtrue);
129
134
  } else {
130
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected true");
135
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected true");
131
136
  }
132
137
  }
133
138
 
134
- static void
135
- read_false(ParseInfo pi) {
139
+ static void read_false(ParseInfo pi) {
136
140
  if (0 == reader_expect(&pi->rd, "alse")) {
137
- add_value(pi, Qfalse);
141
+ add_value(pi, Qfalse);
138
142
  } else {
139
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected false");
143
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected false");
140
144
  }
141
145
  }
142
146
 
143
- static uint32_t
144
- read_hex(ParseInfo pi) {
145
- uint32_t b = 0;
146
- int i;
147
- char c;
147
+ static uint32_t read_hex(ParseInfo pi) {
148
+ uint32_t b = 0;
149
+ int i;
150
+ char c;
148
151
 
149
152
  for (i = 0; i < 4; i++) {
150
- c = reader_get(&pi->rd);
151
- b = b << 4;
152
- if ('0' <= c && c <= '9') {
153
- b += c - '0';
154
- } else if ('A' <= c && c <= 'F') {
155
- b += c - 'A' + 10;
156
- } else if ('a' <= c && c <= 'f') {
157
- b += c - 'a' + 10;
158
- } else {
159
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid hex character");
160
- return 0;
161
- }
153
+ c = reader_get(&pi->rd);
154
+ b = b << 4;
155
+ if ('0' <= c && c <= '9') {
156
+ b += c - '0';
157
+ } else if ('A' <= c && c <= 'F') {
158
+ b += c - 'A' + 10;
159
+ } else if ('a' <= c && c <= 'f') {
160
+ b += c - 'a' + 10;
161
+ } else {
162
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid hex character");
163
+ return 0;
164
+ }
162
165
  }
163
166
  return b;
164
167
  }
165
168
 
166
- static void
167
- unicode_to_chars(ParseInfo pi, Buf buf, uint32_t code) {
169
+ static void unicode_to_chars(ParseInfo pi, Buf buf, uint32_t code) {
168
170
  if (0x0000007F >= code) {
169
- buf_append(buf, (char)code);
171
+ buf_append(buf, (char)code);
170
172
  } else if (0x000007FF >= code) {
171
- buf_append(buf, 0xC0 | (code >> 6));
172
- buf_append(buf, 0x80 | (0x3F & code));
173
+ buf_append(buf, 0xC0 | (code >> 6));
174
+ buf_append(buf, 0x80 | (0x3F & code));
173
175
  } else if (0x0000FFFF >= code) {
174
- buf_append(buf, 0xE0 | (code >> 12));
175
- buf_append(buf, 0x80 | ((code >> 6) & 0x3F));
176
- buf_append(buf, 0x80 | (0x3F & code));
176
+ buf_append(buf, 0xE0 | (code >> 12));
177
+ buf_append(buf, 0x80 | ((code >> 6) & 0x3F));
178
+ buf_append(buf, 0x80 | (0x3F & code));
177
179
  } else if (0x001FFFFF >= code) {
178
- buf_append(buf, 0xF0 | (code >> 18));
179
- buf_append(buf, 0x80 | ((code >> 12) & 0x3F));
180
- buf_append(buf, 0x80 | ((code >> 6) & 0x3F));
181
- buf_append(buf, 0x80 | (0x3F & code));
180
+ buf_append(buf, 0xF0 | (code >> 18));
181
+ buf_append(buf, 0x80 | ((code >> 12) & 0x3F));
182
+ buf_append(buf, 0x80 | ((code >> 6) & 0x3F));
183
+ buf_append(buf, 0x80 | (0x3F & code));
182
184
  } else if (0x03FFFFFF >= code) {
183
- buf_append(buf, 0xF8 | (code >> 24));
184
- buf_append(buf, 0x80 | ((code >> 18) & 0x3F));
185
- buf_append(buf, 0x80 | ((code >> 12) & 0x3F));
186
- buf_append(buf, 0x80 | ((code >> 6) & 0x3F));
187
- buf_append(buf, 0x80 | (0x3F & code));
185
+ buf_append(buf, 0xF8 | (code >> 24));
186
+ buf_append(buf, 0x80 | ((code >> 18) & 0x3F));
187
+ buf_append(buf, 0x80 | ((code >> 12) & 0x3F));
188
+ buf_append(buf, 0x80 | ((code >> 6) & 0x3F));
189
+ buf_append(buf, 0x80 | (0x3F & code));
188
190
  } else if (0x7FFFFFFF >= code) {
189
- buf_append(buf, 0xFC | (code >> 30));
190
- buf_append(buf, 0x80 | ((code >> 24) & 0x3F));
191
- buf_append(buf, 0x80 | ((code >> 18) & 0x3F));
192
- buf_append(buf, 0x80 | ((code >> 12) & 0x3F));
193
- buf_append(buf, 0x80 | ((code >> 6) & 0x3F));
194
- buf_append(buf, 0x80 | (0x3F & code));
191
+ buf_append(buf, 0xFC | (code >> 30));
192
+ buf_append(buf, 0x80 | ((code >> 24) & 0x3F));
193
+ buf_append(buf, 0x80 | ((code >> 18) & 0x3F));
194
+ buf_append(buf, 0x80 | ((code >> 12) & 0x3F));
195
+ buf_append(buf, 0x80 | ((code >> 6) & 0x3F));
196
+ buf_append(buf, 0x80 | (0x3F & code));
195
197
  } else {
196
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid Unicode character");
198
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid Unicode character");
197
199
  }
198
200
  }
199
201
 
200
202
  // entered at backslash
201
- static void
202
- read_escaped_str(ParseInfo pi) {
203
- struct _buf buf;
204
- char c;
205
- uint32_t code;
206
- Val parent = stack_peek(&pi->stack);
203
+ static void read_escaped_str(ParseInfo pi) {
204
+ struct _buf buf;
205
+ char c;
206
+ uint32_t code;
207
+ Val parent = stack_peek(&pi->stack);
207
208
 
208
209
  buf_init(&buf);
209
210
  if (pi->rd.str < pi->rd.tail) {
210
- buf_append_string(&buf, pi->rd.str, pi->rd.tail - pi->rd.str);
211
+ buf_append_string(&buf, pi->rd.str, pi->rd.tail - pi->rd.str);
211
212
  }
212
213
  while ('\"' != (c = reader_get(&pi->rd))) {
213
- if ('\0' == c) {
214
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "quoted string not terminated");
215
- buf_cleanup(&buf);
216
- return;
217
- } else if ('\\' == c) {
218
- c = reader_get(&pi->rd);
219
- switch (c) {
220
- case 'n': buf_append(&buf, '\n'); break;
221
- case 'r': buf_append(&buf, '\r'); break;
222
- case 't': buf_append(&buf, '\t'); break;
223
- case 'f': buf_append(&buf, '\f'); break;
224
- case 'b': buf_append(&buf, '\b'); break;
225
- case '"': buf_append(&buf, '"'); break;
226
- case '/': buf_append(&buf, '/'); break;
227
- case '\\': buf_append(&buf, '\\'); break;
228
- case 'u':
229
- if (0 == (code = read_hex(pi)) && err_has(&pi->err)) {
230
- buf_cleanup(&buf);
231
- return;
232
- }
233
- if (0x0000D800 <= code && code <= 0x0000DFFF) {
234
- uint32_t c1 = (code - 0x0000D800) & 0x000003FF;
235
- uint32_t c2;
236
- char ch2;
237
-
238
- c = reader_get(&pi->rd);
239
- ch2 = reader_get(&pi->rd);
240
- if ('\\' != c || 'u' != ch2) {
241
- if (Yes == pi->options.allow_invalid) {
242
- unicode_to_chars(pi, &buf, code);
243
- reader_backup(&pi->rd);
244
- reader_backup(&pi->rd);
245
- break;
246
- }
247
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid escaped character");
248
- buf_cleanup(&buf);
249
- return;
250
- }
251
- if (0 == (c2 = read_hex(pi)) && err_has(&pi->err)) {
252
- buf_cleanup(&buf);
253
- return;
254
- }
255
- c2 = (c2 - 0x0000DC00) & 0x000003FF;
256
- code = ((c1 << 10) | c2) + 0x00010000;
257
- }
258
- unicode_to_chars(pi, &buf, code);
259
- if (err_has(&pi->err)) {
260
- buf_cleanup(&buf);
261
- return;
262
- }
263
- break;
264
- default:
265
- // The json gem claims this is not an error despite the
266
- // ECMA-404 indicating it is not valid.
267
- if (CompatMode == pi->options.mode) {
268
- buf_append(&buf, c);
269
- break;
270
- }
271
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid escaped character");
272
- buf_cleanup(&buf);
273
- return;
274
- }
275
- } else {
276
- buf_append(&buf, c);
277
- }
214
+ if ('\0' == c) {
215
+ oj_set_error_at(pi,
216
+ oj_parse_error_class,
217
+ __FILE__,
218
+ __LINE__,
219
+ "quoted string not terminated");
220
+ buf_cleanup(&buf);
221
+ return;
222
+ } else if ('\\' == c) {
223
+ c = reader_get(&pi->rd);
224
+ switch (c) {
225
+ case 'n': buf_append(&buf, '\n'); break;
226
+ case 'r': buf_append(&buf, '\r'); break;
227
+ case 't': buf_append(&buf, '\t'); break;
228
+ case 'f': buf_append(&buf, '\f'); break;
229
+ case 'b': buf_append(&buf, '\b'); break;
230
+ case '"': buf_append(&buf, '"'); break;
231
+ case '/': buf_append(&buf, '/'); break;
232
+ case '\\': buf_append(&buf, '\\'); break;
233
+ case 'u':
234
+ if (0 == (code = read_hex(pi)) && err_has(&pi->err)) {
235
+ buf_cleanup(&buf);
236
+ return;
237
+ }
238
+ if (0x0000D800 <= code && code <= 0x0000DFFF) {
239
+ uint32_t c1 = (code - 0x0000D800) & 0x000003FF;
240
+ uint32_t c2;
241
+ char ch2;
242
+
243
+ c = reader_get(&pi->rd);
244
+ ch2 = reader_get(&pi->rd);
245
+ if ('\\' != c || 'u' != ch2) {
246
+ if (Yes == pi->options.allow_invalid) {
247
+ unicode_to_chars(pi, &buf, code);
248
+ reader_backup(&pi->rd);
249
+ reader_backup(&pi->rd);
250
+ break;
251
+ }
252
+ oj_set_error_at(pi,
253
+ oj_parse_error_class,
254
+ __FILE__,
255
+ __LINE__,
256
+ "invalid escaped character");
257
+ buf_cleanup(&buf);
258
+ return;
259
+ }
260
+ if (0 == (c2 = read_hex(pi)) && err_has(&pi->err)) {
261
+ buf_cleanup(&buf);
262
+ return;
263
+ }
264
+ c2 = (c2 - 0x0000DC00) & 0x000003FF;
265
+ code = ((c1 << 10) | c2) + 0x00010000;
266
+ }
267
+ unicode_to_chars(pi, &buf, code);
268
+ if (err_has(&pi->err)) {
269
+ buf_cleanup(&buf);
270
+ return;
271
+ }
272
+ break;
273
+ default:
274
+ // The json gem claims this is not an error despite the
275
+ // ECMA-404 indicating it is not valid.
276
+ if (CompatMode == pi->options.mode) {
277
+ buf_append(&buf, c);
278
+ break;
279
+ }
280
+ oj_set_error_at(pi,
281
+ oj_parse_error_class,
282
+ __FILE__,
283
+ __LINE__,
284
+ "invalid escaped character");
285
+ buf_cleanup(&buf);
286
+ return;
287
+ }
288
+ } else {
289
+ buf_append(&buf, c);
290
+ }
278
291
  }
279
292
  if (0 == parent) {
280
- pi->add_cstr(pi, buf.head, buf_len(&buf), pi->rd.str);
293
+ pi->add_cstr(pi, buf.head, buf_len(&buf), pi->rd.str);
281
294
  } else {
282
- switch (parent->next) {
283
- case NEXT_ARRAY_NEW:
284
- case NEXT_ARRAY_ELEMENT:
285
- pi->array_append_cstr(pi, buf.head, buf_len(&buf), pi->rd.str);
286
- parent->next = NEXT_ARRAY_COMMA;
287
- break;
288
- case NEXT_HASH_NEW:
289
- case NEXT_HASH_KEY:
290
- if (Qundef == (parent->key_val = pi->hash_key(pi, buf.head, buf_len(&buf)))) {
291
- parent->klen = buf_len(&buf);
292
- parent->key = malloc(parent->klen + 1);
293
- memcpy((char*)parent->key, buf.head, parent->klen);
294
- *(char*)(parent->key + parent->klen) = '\0';
295
- } else {
296
- parent->key = "";
297
- parent->klen = 0;
298
- }
299
- parent->k1 = *pi->rd.str;
300
- parent->next = NEXT_HASH_COLON;
301
- break;
302
- case NEXT_HASH_VALUE:
303
- pi->hash_set_cstr(pi, parent, buf.head, buf_len(&buf), pi->rd.str);
304
- if (parent->kalloc) {
305
- xfree((char*)parent->key);
306
- }
307
- parent->key = 0;
308
- parent->kalloc = 0;
309
- parent->next = NEXT_HASH_COMMA;
310
- break;
311
- case NEXT_HASH_COMMA:
312
- case NEXT_NONE:
313
- case NEXT_ARRAY_COMMA:
314
- case NEXT_HASH_COLON:
315
- default:
316
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected %s, not a string", oj_stack_next_string(parent->next));
317
- break;
318
- }
295
+ switch (parent->next) {
296
+ case NEXT_ARRAY_NEW:
297
+ case NEXT_ARRAY_ELEMENT:
298
+ pi->array_append_cstr(pi, buf.head, buf_len(&buf), pi->rd.str);
299
+ parent->next = NEXT_ARRAY_COMMA;
300
+ break;
301
+ case NEXT_HASH_NEW:
302
+ case NEXT_HASH_KEY:
303
+ if (Qundef == (parent->key_val = pi->hash_key(pi, buf.head, buf_len(&buf)))) {
304
+ parent->klen = buf_len(&buf);
305
+ parent->key = malloc(parent->klen + 1);
306
+ memcpy((char *)parent->key, buf.head, parent->klen);
307
+ *(char *)(parent->key + parent->klen) = '\0';
308
+ } else {
309
+ parent->key = "";
310
+ parent->klen = 0;
311
+ }
312
+ parent->k1 = *pi->rd.str;
313
+ parent->next = NEXT_HASH_COLON;
314
+ break;
315
+ case NEXT_HASH_VALUE:
316
+ pi->hash_set_cstr(pi, parent, buf.head, buf_len(&buf), pi->rd.str);
317
+ if (parent->kalloc) {
318
+ xfree((char *)parent->key);
319
+ }
320
+ parent->key = 0;
321
+ parent->kalloc = 0;
322
+ parent->next = NEXT_HASH_COMMA;
323
+ break;
324
+ case NEXT_HASH_COMMA:
325
+ case NEXT_NONE:
326
+ case NEXT_ARRAY_COMMA:
327
+ case NEXT_HASH_COLON:
328
+ default:
329
+ oj_set_error_at(pi,
330
+ oj_parse_error_class,
331
+ __FILE__,
332
+ __LINE__,
333
+ "expected %s, not a string",
334
+ oj_stack_next_string(parent->next));
335
+ break;
336
+ }
319
337
  }
320
338
  buf_cleanup(&buf);
321
339
  }
322
340
 
323
- static void
324
- read_str(ParseInfo pi) {
325
- Val parent = stack_peek(&pi->stack);
326
- char c;
341
+ static void read_str(ParseInfo pi) {
342
+ Val parent = stack_peek(&pi->stack);
343
+ char c;
327
344
 
328
345
  reader_protect(&pi->rd);
329
346
  while ('\"' != (c = reader_get(&pi->rd))) {
330
- if ('\0' == c) {
331
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "quoted string not terminated");
332
- return;
333
- } else if ('\\' == c) {
334
- reader_backup(&pi->rd);
335
- read_escaped_str(pi);
336
- reader_release(&pi->rd);
337
- return;
338
- }
339
- }
340
- if (0 == parent) { // simple add
341
- pi->add_cstr(pi, pi->rd.str, pi->rd.tail - pi->rd.str - 1, pi->rd.str);
347
+ if ('\0' == c) {
348
+ oj_set_error_at(pi,
349
+ oj_parse_error_class,
350
+ __FILE__,
351
+ __LINE__,
352
+ "quoted string not terminated");
353
+ return;
354
+ } else if ('\\' == c) {
355
+ reader_backup(&pi->rd);
356
+ read_escaped_str(pi);
357
+ reader_release(&pi->rd);
358
+ return;
359
+ }
360
+ }
361
+ if (0 == parent) { // simple add
362
+ pi->add_cstr(pi, pi->rd.str, pi->rd.tail - pi->rd.str - 1, pi->rd.str);
342
363
  } else {
343
- switch (parent->next) {
344
- case NEXT_ARRAY_NEW:
345
- case NEXT_ARRAY_ELEMENT:
346
- pi->array_append_cstr(pi, pi->rd.str, pi->rd.tail - pi->rd.str - 1, pi->rd.str);
347
- parent->next = NEXT_ARRAY_COMMA;
348
- break;
349
- case NEXT_HASH_NEW:
350
- case NEXT_HASH_KEY:
351
- parent->klen = pi->rd.tail - pi->rd.str - 1;
352
- if (sizeof(parent->karray) <= parent->klen) {
353
- parent->key = oj_strndup(pi->rd.str, parent->klen);
354
- parent->kalloc = 1;
355
- } else {
356
- memcpy(parent->karray, pi->rd.str, parent->klen);
357
- parent->karray[parent->klen] = '\0';
358
- parent->key = parent->karray;
359
- parent->kalloc = 0;
360
- }
361
- parent->key_val = pi->hash_key(pi, parent->key, parent->klen);
362
- parent->k1 = *pi->rd.str;
363
- parent->next = NEXT_HASH_COLON;
364
- break;
365
- case NEXT_HASH_VALUE:
366
- pi->hash_set_cstr(pi, parent, pi->rd.str, pi->rd.tail - pi->rd.str - 1, pi->rd.str);
367
- if (parent->kalloc) {
368
- xfree((char*)parent->key);
369
- }
370
- parent->key = 0;
371
- parent->kalloc = 0;
372
- parent->next = NEXT_HASH_COMMA;
373
- break;
374
- case NEXT_HASH_COMMA:
375
- case NEXT_NONE:
376
- case NEXT_ARRAY_COMMA:
377
- case NEXT_HASH_COLON:
378
- default:
379
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected %s, not a string", oj_stack_next_string(parent->next));
380
- break;
381
- }
364
+ switch (parent->next) {
365
+ case NEXT_ARRAY_NEW:
366
+ case NEXT_ARRAY_ELEMENT:
367
+ pi->array_append_cstr(pi, pi->rd.str, pi->rd.tail - pi->rd.str - 1, pi->rd.str);
368
+ parent->next = NEXT_ARRAY_COMMA;
369
+ break;
370
+ case NEXT_HASH_NEW:
371
+ case NEXT_HASH_KEY:
372
+ parent->klen = pi->rd.tail - pi->rd.str - 1;
373
+ if (sizeof(parent->karray) <= parent->klen) {
374
+ parent->key = oj_strndup(pi->rd.str, parent->klen);
375
+ parent->kalloc = 1;
376
+ } else {
377
+ memcpy(parent->karray, pi->rd.str, parent->klen);
378
+ parent->karray[parent->klen] = '\0';
379
+ parent->key = parent->karray;
380
+ parent->kalloc = 0;
381
+ }
382
+ parent->key_val = pi->hash_key(pi, parent->key, parent->klen);
383
+ parent->k1 = *pi->rd.str;
384
+ parent->next = NEXT_HASH_COLON;
385
+ break;
386
+ case NEXT_HASH_VALUE:
387
+ pi->hash_set_cstr(pi, parent, pi->rd.str, pi->rd.tail - pi->rd.str - 1, pi->rd.str);
388
+ if (parent->kalloc) {
389
+ xfree((char *)parent->key);
390
+ }
391
+ parent->key = 0;
392
+ parent->kalloc = 0;
393
+ parent->next = NEXT_HASH_COMMA;
394
+ break;
395
+ case NEXT_HASH_COMMA:
396
+ case NEXT_NONE:
397
+ case NEXT_ARRAY_COMMA:
398
+ case NEXT_HASH_COLON:
399
+ default:
400
+ oj_set_error_at(pi,
401
+ oj_parse_error_class,
402
+ __FILE__,
403
+ __LINE__,
404
+ "expected %s, not a string",
405
+ oj_stack_next_string(parent->next));
406
+ break;
407
+ }
382
408
  }
383
409
  reader_release(&pi->rd);
384
410
  }
385
411
 
386
- static void
387
- read_num(ParseInfo pi) {
388
- struct _numInfo ni;
389
- char c;
412
+ static void read_num(ParseInfo pi) {
413
+ struct _numInfo ni;
414
+ char c;
390
415
 
391
416
  reader_protect(&pi->rd);
392
- ni.i = 0;
393
- ni.num = 0;
394
- ni.div = 1;
395
- ni.di = 0;
396
- ni.len = 0;
397
- ni.exp = 0;
398
- ni.big = 0;
417
+ ni.i = 0;
418
+ ni.num = 0;
419
+ ni.div = 1;
420
+ ni.di = 0;
421
+ ni.len = 0;
422
+ ni.exp = 0;
423
+ ni.big = 0;
399
424
  ni.infinity = 0;
400
- ni.nan = 0;
401
- ni.neg = 0;
402
- ni.has_exp = 0;
425
+ ni.nan = 0;
426
+ ni.neg = 0;
427
+ ni.has_exp = 0;
403
428
  if (CompatMode == pi->options.mode) {
404
- ni.no_big = !pi->options.compat_bigdec;
405
- ni.bigdec_load = pi->options.compat_bigdec;
429
+ ni.no_big = !pi->options.compat_bigdec;
430
+ ni.bigdec_load = pi->options.compat_bigdec;
406
431
  } else {
407
- ni.no_big = (FloatDec == pi->options.bigdec_load || FastDec == pi->options.bigdec_load || RubyDec == pi->options.bigdec_load);
408
- ni.bigdec_load = pi->options.bigdec_load;
432
+ ni.no_big = (FloatDec == pi->options.bigdec_load || FastDec == pi->options.bigdec_load ||
433
+ RubyDec == pi->options.bigdec_load);
434
+ ni.bigdec_load = pi->options.bigdec_load;
409
435
  }
410
436
 
411
437
  c = reader_get(&pi->rd);
412
438
  if ('-' == c) {
413
- c = reader_get(&pi->rd);
414
- ni.neg = 1;
439
+ c = reader_get(&pi->rd);
440
+ ni.neg = 1;
415
441
  } else if ('+' == c) {
416
- c = reader_get(&pi->rd);
442
+ c = reader_get(&pi->rd);
417
443
  }
418
444
  if ('I' == c) {
419
- if (No == pi->options.allow_nan) {
420
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
421
- return;
422
- } else if (0 != reader_expect(&pi->rd, "nfinity")) {
423
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
424
- return;
425
- }
426
- ni.infinity = 1;
445
+ if (No == pi->options.allow_nan) {
446
+ oj_set_error_at(pi,
447
+ oj_parse_error_class,
448
+ __FILE__,
449
+ __LINE__,
450
+ "not a number or other value");
451
+ return;
452
+ } else if (0 != reader_expect(&pi->rd, "nfinity")) {
453
+ oj_set_error_at(pi,
454
+ oj_parse_error_class,
455
+ __FILE__,
456
+ __LINE__,
457
+ "not a number or other value");
458
+ return;
459
+ }
460
+ ni.infinity = 1;
427
461
  } else {
428
- int dec_cnt = 0;
429
- bool zero1 = false;
430
-
431
- for (; '0' <= c && c <= '9'; c = reader_get(&pi->rd)) {
432
- if (0 == ni.i && '0' == c) {
433
- zero1 = true;
434
- }
435
- if (0 < ni.i) {
436
- dec_cnt++;
437
- }
438
- if (ni.big) {
439
- ni.big++;
440
- } else {
441
- int d = (c - '0');
442
-
443
- if (0 < d) {
444
- if (zero1 && CompatMode == pi->options.mode) {
445
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number");
446
- return;
447
- }
448
- zero1 = false;
449
- }
450
- ni.i = ni.i * 10 + d;
451
- if (INT64_MAX <= ni.i || DEC_MAX < dec_cnt) {
452
- ni.big = 1;
453
- }
454
- }
455
- }
456
- if ('.' == c) {
457
- c = reader_get(&pi->rd);
458
- // A trailing . is not a valid decimal but if encountered allow it
459
- // except when mimicing the JSON gem.
460
- if (CompatMode == pi->options.mode) {
461
- if (c < '0' || '9' < c) {
462
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number");
463
- }
464
- }
465
- for (; '0' <= c && c <= '9'; c = reader_get(&pi->rd)) {
466
- int d = (c - '0');
467
-
468
- if (0 < ni.num || 0 < ni.i) {
469
- dec_cnt++;
470
- }
471
- if (INT64_MAX <= ni.div) {
472
- if (!ni.no_big) {
473
- ni.big = true;
474
- }
475
- } else {
476
- ni.num = ni.num * 10 + d;
477
- ni.div *= 10;
478
- ni.di++;
479
- if (INT64_MAX <= ni.div || DEC_MAX < dec_cnt) {
480
- if (!ni.no_big) {
481
- ni.big = true;
482
- }
483
- }
484
- }
485
- }
486
- }
487
- if ('e' == c || 'E' == c) {
488
- int eneg = 0;
489
-
490
- ni.has_exp = 1;
491
- c = reader_get(&pi->rd);
492
- if ('-' == c) {
493
- c = reader_get(&pi->rd);
494
- eneg = 1;
495
- } else if ('+' == c) {
496
- c = reader_get(&pi->rd);
497
- }
498
- for (; '0' <= c && c <= '9'; c = reader_get(&pi->rd)) {
499
- ni.exp = ni.exp * 10 + (c - '0');
500
- if (EXP_MAX <= ni.exp) {
501
- ni.big = 1;
502
- }
503
- }
504
- if (eneg) {
505
- ni.exp = -ni.exp;
506
- }
507
- }
508
- ni.len = pi->rd.tail - pi->rd.str;
509
- if (0 != c) {
510
- reader_backup(&pi->rd);
511
- }
462
+ int dec_cnt = 0;
463
+ bool zero1 = false;
464
+
465
+ for (; '0' <= c && c <= '9'; c = reader_get(&pi->rd)) {
466
+ if (0 == ni.i && '0' == c) {
467
+ zero1 = true;
468
+ }
469
+ if (0 < ni.i) {
470
+ dec_cnt++;
471
+ }
472
+ if (ni.big) {
473
+ ni.big++;
474
+ } else {
475
+ int d = (c - '0');
476
+
477
+ if (0 < d) {
478
+ if (zero1 && CompatMode == pi->options.mode) {
479
+ oj_set_error_at(pi,
480
+ oj_parse_error_class,
481
+ __FILE__,
482
+ __LINE__,
483
+ "not a number");
484
+ return;
485
+ }
486
+ zero1 = false;
487
+ }
488
+ ni.i = ni.i * 10 + d;
489
+ if (INT64_MAX <= ni.i || DEC_MAX < dec_cnt) {
490
+ ni.big = 1;
491
+ }
492
+ }
493
+ }
494
+ if ('.' == c) {
495
+ c = reader_get(&pi->rd);
496
+ // A trailing . is not a valid decimal but if encountered allow it
497
+ // except when mimicing the JSON gem.
498
+ if (CompatMode == pi->options.mode) {
499
+ if (c < '0' || '9' < c) {
500
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number");
501
+ }
502
+ }
503
+ for (; '0' <= c && c <= '9'; c = reader_get(&pi->rd)) {
504
+ int d = (c - '0');
505
+
506
+ if (0 < ni.num || 0 < ni.i) {
507
+ dec_cnt++;
508
+ }
509
+ if (INT64_MAX <= ni.div) {
510
+ if (!ni.no_big) {
511
+ ni.big = true;
512
+ }
513
+ } else {
514
+ ni.num = ni.num * 10 + d;
515
+ ni.div *= 10;
516
+ ni.di++;
517
+ if (INT64_MAX <= ni.div || DEC_MAX < dec_cnt) {
518
+ if (!ni.no_big) {
519
+ ni.big = true;
520
+ }
521
+ }
522
+ }
523
+ }
524
+ }
525
+ if ('e' == c || 'E' == c) {
526
+ int eneg = 0;
527
+
528
+ ni.has_exp = 1;
529
+ c = reader_get(&pi->rd);
530
+ if ('-' == c) {
531
+ c = reader_get(&pi->rd);
532
+ eneg = 1;
533
+ } else if ('+' == c) {
534
+ c = reader_get(&pi->rd);
535
+ }
536
+ for (; '0' <= c && c <= '9'; c = reader_get(&pi->rd)) {
537
+ ni.exp = ni.exp * 10 + (c - '0');
538
+ if (EXP_MAX <= ni.exp) {
539
+ ni.big = 1;
540
+ }
541
+ }
542
+ if (eneg) {
543
+ ni.exp = -ni.exp;
544
+ }
545
+ }
546
+ ni.len = pi->rd.tail - pi->rd.str;
547
+ if (0 != c) {
548
+ reader_backup(&pi->rd);
549
+ }
512
550
  }
513
551
  ni.str = pi->rd.str;
514
552
  ni.len = pi->rd.tail - pi->rd.str;
515
553
  // Check for special reserved values for Infinity and NaN.
516
554
  if (ni.big) {
517
- if (0 == strcasecmp(INF_VAL, ni.str)) {
518
- ni.infinity = 1;
519
- } else if (0 == strcasecmp(NINF_VAL, ni.str)) {
520
- ni.infinity = 1;
521
- ni.neg = 1;
522
- } else if (0 == strcasecmp(NAN_VAL, ni.str)) {
523
- ni.nan = 1;
524
- }
555
+ if (0 == strcasecmp(INF_VAL, ni.str)) {
556
+ ni.infinity = 1;
557
+ } else if (0 == strcasecmp(NINF_VAL, ni.str)) {
558
+ ni.infinity = 1;
559
+ ni.neg = 1;
560
+ } else if (0 == strcasecmp(NAN_VAL, ni.str)) {
561
+ ni.nan = 1;
562
+ }
525
563
  }
526
564
  if (CompatMode == pi->options.mode) {
527
- if (pi->options.compat_bigdec) {
528
- ni.big = 1;
529
- }
565
+ if (pi->options.compat_bigdec) {
566
+ ni.big = 1;
567
+ }
530
568
  } else if (BigDec == pi->options.bigdec_load) {
531
- ni.big = 1;
569
+ ni.big = 1;
532
570
  }
533
571
  add_num_value(pi, &ni);
534
572
  reader_release(&pi->rd);
535
573
  }
536
574
 
537
- static void
538
- read_nan(ParseInfo pi) {
539
- struct _numInfo ni;
540
- char c;
541
-
542
- ni.str = pi->rd.str;
543
- ni.i = 0;
544
- ni.num = 0;
545
- ni.div = 1;
546
- ni.di = 0;
547
- ni.len = 0;
548
- ni.exp = 0;
549
- ni.big = 0;
575
+ static void read_nan(ParseInfo pi) {
576
+ struct _numInfo ni;
577
+ char c;
578
+
579
+ ni.str = pi->rd.str;
580
+ ni.i = 0;
581
+ ni.num = 0;
582
+ ni.div = 1;
583
+ ni.di = 0;
584
+ ni.len = 0;
585
+ ni.exp = 0;
586
+ ni.big = 0;
550
587
  ni.infinity = 0;
551
- ni.nan = 1;
552
- ni.neg = 0;
588
+ ni.nan = 1;
589
+ ni.neg = 0;
553
590
  if (CompatMode == pi->options.mode) {
554
- ni.no_big = !pi->options.compat_bigdec;
555
- ni.bigdec_load = pi->options.compat_bigdec;
591
+ ni.no_big = !pi->options.compat_bigdec;
592
+ ni.bigdec_load = pi->options.compat_bigdec;
556
593
  } else {
557
- ni.no_big = (FloatDec == pi->options.bigdec_load || FastDec == pi->options.bigdec_load || RubyDec == pi->options.bigdec_load);
558
- ni.bigdec_load = pi->options.bigdec_load;
594
+ ni.no_big = (FloatDec == pi->options.bigdec_load || FastDec == pi->options.bigdec_load ||
595
+ RubyDec == pi->options.bigdec_load);
596
+ ni.bigdec_load = pi->options.bigdec_load;
559
597
  }
560
598
 
561
- if ('a' != reader_get(&pi->rd) ||
562
- ('N' != (c = reader_get(&pi->rd)) && 'n' != c)) {
563
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
564
- return;
599
+ if ('a' != reader_get(&pi->rd) || ('N' != (c = reader_get(&pi->rd)) && 'n' != c)) {
600
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
601
+ return;
565
602
  }
566
603
  if (CompatMode == pi->options.mode) {
567
- if (pi->options.compat_bigdec) {
568
- ni.big = 1;
569
- }
604
+ if (pi->options.compat_bigdec) {
605
+ ni.big = 1;
606
+ }
570
607
  } else if (BigDec == pi->options.bigdec_load) {
571
- ni.big = 1;
608
+ ni.big = 1;
572
609
  }
573
610
  add_num_value(pi, &ni);
574
611
  }
575
612
 
576
- static void
577
- array_start(ParseInfo pi) {
578
- VALUE v = pi->start_array(pi);
613
+ static void array_start(ParseInfo pi) {
614
+ VALUE v = pi->start_array(pi);
579
615
 
580
616
  stack_push(&pi->stack, v, NEXT_ARRAY_NEW);
581
617
  }
582
618
 
583
- static void
584
- array_end(ParseInfo pi) {
585
- Val array = stack_pop(&pi->stack);
619
+ static void array_end(ParseInfo pi) {
620
+ Val array = stack_pop(&pi->stack);
586
621
 
587
622
  if (0 == array) {
588
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected array close");
623
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected array close");
589
624
  } else if (NEXT_ARRAY_COMMA != array->next && NEXT_ARRAY_NEW != array->next) {
590
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected %s, not an array close", oj_stack_next_string(array->next));
625
+ oj_set_error_at(pi,
626
+ oj_parse_error_class,
627
+ __FILE__,
628
+ __LINE__,
629
+ "expected %s, not an array close",
630
+ oj_stack_next_string(array->next));
591
631
  } else {
592
- pi->end_array(pi);
593
- add_value(pi, array->val);
632
+ pi->end_array(pi);
633
+ add_value(pi, array->val);
594
634
  }
595
635
  }
596
636
 
597
- static void
598
- hash_start(ParseInfo pi) {
599
- volatile VALUE v = pi->start_hash(pi);
637
+ static void hash_start(ParseInfo pi) {
638
+ volatile VALUE v = pi->start_hash(pi);
600
639
 
601
640
  stack_push(&pi->stack, v, NEXT_HASH_NEW);
602
641
  }
603
642
 
604
- static void
605
- hash_end(ParseInfo pi) {
606
- volatile Val hash = stack_peek(&pi->stack);
643
+ static void hash_end(ParseInfo pi) {
644
+ volatile Val hash = stack_peek(&pi->stack);
607
645
 
608
646
  // leave hash on stack until just before
609
647
  if (0 == hash) {
610
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected hash close");
648
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected hash close");
611
649
  } else if (NEXT_HASH_COMMA != hash->next && NEXT_HASH_NEW != hash->next) {
612
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected %s, not a hash close", oj_stack_next_string(hash->next));
650
+ oj_set_error_at(pi,
651
+ oj_parse_error_class,
652
+ __FILE__,
653
+ __LINE__,
654
+ "expected %s, not a hash close",
655
+ oj_stack_next_string(hash->next));
613
656
  } else {
614
- pi->end_hash(pi);
615
- stack_pop(&pi->stack);
616
- add_value(pi, hash->val);
657
+ pi->end_hash(pi);
658
+ stack_pop(&pi->stack);
659
+ add_value(pi, hash->val);
617
660
  }
618
661
  }
619
662
 
620
- static void
621
- comma(ParseInfo pi) {
622
- Val parent = stack_peek(&pi->stack);
663
+ static void comma(ParseInfo pi) {
664
+ Val parent = stack_peek(&pi->stack);
623
665
 
624
666
  if (0 == parent) {
625
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected comma");
667
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected comma");
626
668
  } else if (NEXT_ARRAY_COMMA == parent->next) {
627
- parent->next = NEXT_ARRAY_ELEMENT;
669
+ parent->next = NEXT_ARRAY_ELEMENT;
628
670
  } else if (NEXT_HASH_COMMA == parent->next) {
629
- parent->next = NEXT_HASH_KEY;
671
+ parent->next = NEXT_HASH_KEY;
630
672
  } else {
631
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected comma");
673
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected comma");
632
674
  }
633
675
  }
634
676
 
635
- static void
636
- colon(ParseInfo pi) {
637
- Val parent = stack_peek(&pi->stack);
677
+ static void colon(ParseInfo pi) {
678
+ Val parent = stack_peek(&pi->stack);
638
679
 
639
680
  if (0 != parent && NEXT_HASH_COLON == parent->next) {
640
- parent->next = NEXT_HASH_VALUE;
681
+ parent->next = NEXT_HASH_VALUE;
641
682
  } else {
642
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected colon");
683
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected colon");
643
684
  }
644
685
  }
645
686
 
646
- void
647
- oj_sparse2(ParseInfo pi) {
648
- int first = 1;
649
- char c;
650
- long start = 0;
687
+ void oj_sparse2(ParseInfo pi) {
688
+ int first = 1;
689
+ char c;
690
+ long start = 0;
651
691
 
652
692
  err_init(&pi->err);
653
693
  while (1) {
654
- if (0 < pi->max_depth && pi->max_depth <= pi->stack.tail - pi->stack.head - 1) {
655
- VALUE err_clas = oj_get_json_err_class("NestingError");
656
-
657
- oj_set_error_at(pi, err_clas, __FILE__, __LINE__, "Too deeply nested.");
658
- pi->err_class = err_clas;
659
- return;
660
- }
661
- c = reader_next_non_white(&pi->rd);
662
- if (!first && '\0' != c) {
663
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected characters after the JSON document");
664
- }
665
- switch (c) {
666
- case '{':
667
- hash_start(pi);
668
- break;
669
- case '}':
670
- hash_end(pi);
671
- break;
672
- case ':':
673
- colon(pi);
674
- break;
675
- case '[':
676
- array_start(pi);
677
- break;
678
- case ']':
679
- array_end(pi);
680
- break;
681
- case ',':
682
- comma(pi);
683
- break;
684
- case '"':
685
- read_str(pi);
686
- break;
687
- case '+':
688
- if (CompatMode == pi->options.mode) {
689
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected character");
690
- return;
691
- }
692
- pi->cur--;
693
- read_num(pi);
694
- break;
695
- case '-':
696
- case '0':
697
- case '1':
698
- case '2':
699
- case '3':
700
- case '4':
701
- case '5':
702
- case '6':
703
- case '7':
704
- case '8':
705
- case '9':
706
- reader_backup(&pi->rd);
707
- read_num(pi);
708
- break;
709
- case 'I':
710
- if (Yes == pi->options.allow_nan) {
711
- reader_backup(&pi->rd);
712
- read_num(pi);
713
- } else {
714
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected character");
715
- return;
716
- }
717
- break;
718
- case 'N':
719
- if (Yes == pi->options.allow_nan) {
720
- read_nan(pi);
721
- } else {
722
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected character");
723
- return;
724
- }
725
- break;
726
- case 't':
727
- read_true(pi);
728
- break;
729
- case 'f':
730
- read_false(pi);
731
- break;
732
- case 'n':
733
- c = reader_get(&pi->rd);
734
- if ('u' == c) {
735
- if (0 == reader_expect(&pi->rd, "ll")) {
736
- add_value(pi, Qnil);
737
- } else {
738
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected null");
739
- return;
740
- }
741
- } else if ('a' == c) {
742
- struct _numInfo ni;
743
-
744
- c = reader_get(&pi->rd);
745
- if ('N' != c && 'n' != c) {
746
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected NaN");
747
- return;
748
- }
749
- ni.str = pi->rd.str;
750
- ni.i = 0;
751
- ni.num = 0;
752
- ni.div = 1;
753
- ni.di = 0;
754
- ni.len = 0;
755
- ni.exp = 0;
756
- ni.big = 0;
757
- ni.infinity = 0;
758
- ni.nan = 1;
759
- ni.neg = 0;
760
- if (CompatMode == pi->options.mode) {
761
- ni.no_big = !pi->options.compat_bigdec;
762
- ni.bigdec_load = pi->options.compat_bigdec;
763
- } else {
764
- ni.no_big = (FloatDec == pi->options.bigdec_load ||
765
- FastDec == pi->options.bigdec_load ||
766
- RubyDec == pi->options.bigdec_load);
767
- ni.bigdec_load = pi->options.bigdec_load;
768
- }
769
- add_num_value(pi, &ni);
770
- } else {
771
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid token");
772
- return;
773
- }
774
- break;
775
- case '/':
776
- skip_comment(pi);
777
- break;
778
- case '\0':
779
- return;
780
- default:
781
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected character '%c' [0x%02x]", c, c);
782
- return;
783
- }
784
- if (err_has(&pi->err)) {
785
- return;
786
- }
787
- if (stack_empty(&pi->stack)) {
788
- if (Qundef != pi->proc) {
789
- VALUE args[3];
790
- long len = pi->rd.pos - start;
791
-
792
- *args = stack_head_val(&pi->stack);
793
- args[1] = LONG2NUM(start);
794
- args[2] = LONG2NUM(len);
795
-
796
- if (Qnil == pi->proc) {
797
- rb_yield_values2(3, args);
798
- } else {
799
- rb_proc_call_with_block(pi->proc, 3, args, Qnil);
800
- }
801
- } else if (!pi->has_callbacks) {
802
- first = 0;
803
- }
804
- start = pi->rd.pos;
805
- // TBD break if option set to allow that
806
- }
694
+ if (0 < pi->max_depth && pi->max_depth <= pi->stack.tail - pi->stack.head - 1) {
695
+ VALUE err_clas = oj_get_json_err_class("NestingError");
696
+
697
+ oj_set_error_at(pi, err_clas, __FILE__, __LINE__, "Too deeply nested.");
698
+ pi->err_class = err_clas;
699
+ return;
700
+ }
701
+ c = reader_next_non_white(&pi->rd);
702
+ if (!first && '\0' != c) {
703
+ oj_set_error_at(pi,
704
+ oj_parse_error_class,
705
+ __FILE__,
706
+ __LINE__,
707
+ "unexpected characters after the JSON document");
708
+ }
709
+ switch (c) {
710
+ case '{': hash_start(pi); break;
711
+ case '}': hash_end(pi); break;
712
+ case ':': colon(pi); break;
713
+ case '[': array_start(pi); break;
714
+ case ']': array_end(pi); break;
715
+ case ',': comma(pi); break;
716
+ case '"': read_str(pi); break;
717
+ case '+':
718
+ if (CompatMode == pi->options.mode) {
719
+ oj_set_error_at(pi,
720
+ oj_parse_error_class,
721
+ __FILE__,
722
+ __LINE__,
723
+ "unexpected character");
724
+ return;
725
+ }
726
+ pi->cur--;
727
+ read_num(pi);
728
+ break;
729
+ case '-':
730
+ case '0':
731
+ case '1':
732
+ case '2':
733
+ case '3':
734
+ case '4':
735
+ case '5':
736
+ case '6':
737
+ case '7':
738
+ case '8':
739
+ case '9':
740
+ reader_backup(&pi->rd);
741
+ read_num(pi);
742
+ break;
743
+ case 'I':
744
+ if (Yes == pi->options.allow_nan) {
745
+ reader_backup(&pi->rd);
746
+ read_num(pi);
747
+ } else {
748
+ oj_set_error_at(pi,
749
+ oj_parse_error_class,
750
+ __FILE__,
751
+ __LINE__,
752
+ "unexpected character");
753
+ return;
754
+ }
755
+ break;
756
+ case 'N':
757
+ if (Yes == pi->options.allow_nan) {
758
+ read_nan(pi);
759
+ } else {
760
+ oj_set_error_at(pi,
761
+ oj_parse_error_class,
762
+ __FILE__,
763
+ __LINE__,
764
+ "unexpected character");
765
+ return;
766
+ }
767
+ break;
768
+ case 't': read_true(pi); break;
769
+ case 'f': read_false(pi); break;
770
+ case 'n':
771
+ c = reader_get(&pi->rd);
772
+ if ('u' == c) {
773
+ if (0 == reader_expect(&pi->rd, "ll")) {
774
+ add_value(pi, Qnil);
775
+ } else {
776
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected null");
777
+ return;
778
+ }
779
+ } else if ('a' == c) {
780
+ struct _numInfo ni;
781
+
782
+ c = reader_get(&pi->rd);
783
+ if ('N' != c && 'n' != c) {
784
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected NaN");
785
+ return;
786
+ }
787
+ ni.str = pi->rd.str;
788
+ ni.i = 0;
789
+ ni.num = 0;
790
+ ni.div = 1;
791
+ ni.di = 0;
792
+ ni.len = 0;
793
+ ni.exp = 0;
794
+ ni.big = 0;
795
+ ni.infinity = 0;
796
+ ni.nan = 1;
797
+ ni.neg = 0;
798
+ if (CompatMode == pi->options.mode) {
799
+ ni.no_big = !pi->options.compat_bigdec;
800
+ ni.bigdec_load = pi->options.compat_bigdec;
801
+ } else {
802
+ ni.no_big = (FloatDec == pi->options.bigdec_load ||
803
+ FastDec == pi->options.bigdec_load ||
804
+ RubyDec == pi->options.bigdec_load);
805
+ ni.bigdec_load = pi->options.bigdec_load;
806
+ }
807
+ add_num_value(pi, &ni);
808
+ } else {
809
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid token");
810
+ return;
811
+ }
812
+ break;
813
+ case '/': skip_comment(pi); break;
814
+ case '\0': return;
815
+ default:
816
+ oj_set_error_at(pi,
817
+ oj_parse_error_class,
818
+ __FILE__,
819
+ __LINE__,
820
+ "unexpected character '%c' [0x%02x]",
821
+ c,
822
+ c);
823
+ return;
824
+ }
825
+ if (err_has(&pi->err)) {
826
+ return;
827
+ }
828
+ if (stack_empty(&pi->stack)) {
829
+ if (Qundef != pi->proc) {
830
+ VALUE args[3];
831
+ long len = pi->rd.pos - start;
832
+
833
+ *args = stack_head_val(&pi->stack);
834
+ args[1] = LONG2NUM(start);
835
+ args[2] = LONG2NUM(len);
836
+
837
+ if (Qnil == pi->proc) {
838
+ rb_yield_values2(3, args);
839
+ } else {
840
+ rb_proc_call_with_block(pi->proc, 3, args, Qnil);
841
+ }
842
+ } else if (!pi->has_callbacks) {
843
+ first = 0;
844
+ }
845
+ start = pi->rd.pos;
846
+ // TBD break if option set to allow that
847
+ }
807
848
  }
808
849
  }
809
850
 
810
- static VALUE
811
- protect_parse(VALUE pip) {
851
+ static VALUE protect_parse(VALUE pip) {
812
852
  oj_sparse2((ParseInfo)pip);
813
853
 
814
854
  return Qnil;
@@ -816,46 +856,47 @@ protect_parse(VALUE pip) {
816
856
 
817
857
  VALUE
818
858
  oj_pi_sparse(int argc, VALUE *argv, ParseInfo pi, int fd) {
819
- volatile VALUE input;
820
- volatile VALUE wrapped_stack;
821
- VALUE result = Qnil;
822
- int line = 0;
859
+ volatile VALUE input;
860
+ volatile VALUE wrapped_stack;
861
+ VALUE result = Qnil;
862
+ int line = 0;
823
863
 
824
864
  if (argc < 1) {
825
- rb_raise(rb_eArgError, "Wrong number of arguments to parse.");
865
+ rb_raise(rb_eArgError, "Wrong number of arguments to parse.");
826
866
  }
827
867
  input = argv[0];
828
868
  if (2 <= argc) {
829
- if (T_HASH == rb_type(argv[1])) {
830
- oj_parse_options(argv[1], &pi->options);
831
- } else if (3 <= argc && T_HASH == rb_type(argv[2])) {
832
- oj_parse_options(argv[2], &pi->options);
833
- }
869
+ if (T_HASH == rb_type(argv[1])) {
870
+ oj_parse_options(argv[1], &pi->options);
871
+ } else if (3 <= argc && T_HASH == rb_type(argv[2])) {
872
+ oj_parse_options(argv[2], &pi->options);
873
+ }
834
874
  }
835
875
  if (Qnil == input) {
836
- if (Yes == pi->options.nilnil) {
837
- return Qnil;
838
- } else {
839
- rb_raise(rb_eTypeError, "Nil is not a valid JSON source.");
840
- }
841
- } else if (CompatMode == pi->options.mode && T_STRING == rb_type(input) && No == pi->options.nilnil && 0 == RSTRING_LEN(input)) {
842
- rb_raise(oj_json_parser_error_class, "An empty string is not a valid JSON string.");
876
+ if (Yes == pi->options.nilnil) {
877
+ return Qnil;
878
+ } else {
879
+ rb_raise(rb_eTypeError, "Nil is not a valid JSON source.");
880
+ }
881
+ } else if (CompatMode == pi->options.mode && T_STRING == rb_type(input) &&
882
+ No == pi->options.nilnil && 0 == RSTRING_LEN(input)) {
883
+ rb_raise(oj_json_parser_error_class, "An empty string is not a valid JSON string.");
843
884
  }
844
885
  if (rb_block_given_p()) {
845
- pi->proc = Qnil;
886
+ pi->proc = Qnil;
846
887
  } else {
847
- pi->proc = Qundef;
888
+ pi->proc = Qundef;
848
889
  }
849
890
  oj_reader_init(&pi->rd, input, fd, CompatMode == pi->options.mode);
850
- pi->json = 0; // indicates reader is in use
891
+ pi->json = 0; // indicates reader is in use
851
892
 
852
893
  if (Yes == pi->options.circular) {
853
- pi->circ_array = oj_circ_array_new();
894
+ pi->circ_array = oj_circ_array_new();
854
895
  } else {
855
- pi->circ_array = 0;
896
+ pi->circ_array = 0;
856
897
  }
857
898
  if (No == pi->options.allow_gc) {
858
- rb_gc_disable();
899
+ rb_gc_disable();
859
900
  }
860
901
  // GC can run at any time. When it runs any Object created by C will be
861
902
  // freed. We protect against this by wrapping the value stack in a ruby
@@ -864,81 +905,80 @@ oj_pi_sparse(int argc, VALUE *argv, ParseInfo pi, int fd) {
864
905
  wrapped_stack = oj_stack_init(&pi->stack);
865
906
  rb_protect(protect_parse, (VALUE)pi, &line);
866
907
  if (Qundef == pi->stack.head->val && !empty_ok(&pi->options)) {
867
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "Empty input");
908
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "Empty input");
868
909
  }
869
- result = stack_head_val(&pi->stack);
910
+ result = stack_head_val(&pi->stack);
870
911
  DATA_PTR(wrapped_stack) = 0;
871
912
  if (No == pi->options.allow_gc) {
872
- rb_gc_enable();
913
+ rb_gc_enable();
873
914
  }
874
915
  if (!err_has(&pi->err)) {
875
- // If the stack is not empty then the JSON terminated early.
876
- Val v;
877
- VALUE err_class = oj_parse_error_class;
878
-
879
- if (0 != line) {
880
- VALUE ec = rb_obj_class(rb_errinfo());
881
-
882
- if (rb_eIOError != ec) {
883
- goto CLEANUP;
884
- }
885
- // Sometimes the class of the error is 0 which seems broken.
886
- if (rb_eArgError != ec && 0 != ec) {
887
- err_class = ec;
888
- }
889
- }
890
- if (0 != (v = stack_peek(&pi->stack))) {
891
- switch (v->next) {
892
- case NEXT_ARRAY_NEW:
893
- case NEXT_ARRAY_ELEMENT:
894
- case NEXT_ARRAY_COMMA:
895
- oj_set_error_at(pi, err_class, __FILE__, __LINE__, "Array not terminated");
896
- break;
897
- case NEXT_HASH_NEW:
898
- case NEXT_HASH_KEY:
899
- case NEXT_HASH_COLON:
900
- case NEXT_HASH_VALUE:
901
- case NEXT_HASH_COMMA:
902
- oj_set_error_at(pi, err_class, __FILE__, __LINE__, "Hash/Object not terminated");
903
- break;
904
- default:
905
- oj_set_error_at(pi, err_class, __FILE__, __LINE__, "not terminated");
906
- }
907
- }
916
+ // If the stack is not empty then the JSON terminated early.
917
+ Val v;
918
+ VALUE err_class = oj_parse_error_class;
919
+
920
+ if (0 != line) {
921
+ VALUE ec = rb_obj_class(rb_errinfo());
922
+
923
+ if (rb_eIOError != ec) {
924
+ goto CLEANUP;
925
+ }
926
+ // Sometimes the class of the error is 0 which seems broken.
927
+ if (rb_eArgError != ec && 0 != ec) {
928
+ err_class = ec;
929
+ }
930
+ }
931
+ if (0 != (v = stack_peek(&pi->stack))) {
932
+ switch (v->next) {
933
+ case NEXT_ARRAY_NEW:
934
+ case NEXT_ARRAY_ELEMENT:
935
+ case NEXT_ARRAY_COMMA:
936
+ oj_set_error_at(pi, err_class, __FILE__, __LINE__, "Array not terminated");
937
+ break;
938
+ case NEXT_HASH_NEW:
939
+ case NEXT_HASH_KEY:
940
+ case NEXT_HASH_COLON:
941
+ case NEXT_HASH_VALUE:
942
+ case NEXT_HASH_COMMA:
943
+ oj_set_error_at(pi, err_class, __FILE__, __LINE__, "Hash/Object not terminated");
944
+ break;
945
+ default: oj_set_error_at(pi, err_class, __FILE__, __LINE__, "not terminated");
946
+ }
947
+ }
908
948
  }
909
949
  CLEANUP:
910
950
  // proceed with cleanup
911
951
  if (0 != pi->circ_array) {
912
- oj_circ_array_free(pi->circ_array);
952
+ oj_circ_array_free(pi->circ_array);
913
953
  }
914
954
  stack_cleanup(&pi->stack);
915
955
  if (0 != fd) {
916
- close(fd);
956
+ close(fd);
917
957
  }
918
958
  if (err_has(&pi->err)) {
919
- rb_set_errinfo(Qnil);
920
- if (Qnil != pi->err_class && 0 != pi->err_class) {
921
- pi->err.clas = pi->err_class;
922
- }
923
- if (CompatMode == pi->options.mode && Yes != pi->options.safe) {
924
- // The json gem requires the error message be UTF-8 encoded. In
925
- // additional the complete JSON source should be returned but that
926
- // is not possible without stored all the bytes read and reading
927
- // the remaining bytes on the stream. Both seem like a very bad
928
- // idea.
929
- VALUE args[] = { oj_encode(rb_str_new2(pi->err.msg)) };
930
-
931
- if (pi->err.clas == oj_parse_error_class) {
932
- // The error was an Oj::ParseError so change to a JSON::ParserError.
933
- pi->err.clas = oj_json_parser_error_class;
934
- }
935
- rb_exc_raise(rb_class_new_instance(1, args, pi->err.clas));
936
- } else {
937
- oj_err_raise(&pi->err);
938
- }
939
- oj_err_raise(&pi->err);
959
+ rb_set_errinfo(Qnil);
960
+ if (Qnil != pi->err_class && 0 != pi->err_class) {
961
+ pi->err.clas = pi->err_class;
962
+ }
963
+ if (CompatMode == pi->options.mode && Yes != pi->options.safe) {
964
+ // The json gem requires the error message be UTF-8 encoded. In
965
+ // additional the complete JSON source should be returned but that
966
+ // is not possible without stored all the bytes read and reading
967
+ // the remaining bytes on the stream. Both seem like a very bad
968
+ // idea.
969
+ VALUE args[] = {oj_encode(rb_str_new2(pi->err.msg))};
970
+
971
+ if (pi->err.clas == oj_parse_error_class) {
972
+ // The error was an Oj::ParseError so change to a JSON::ParserError.
973
+ pi->err.clas = oj_json_parser_error_class;
974
+ }
975
+ rb_exc_raise(rb_class_new_instance(1, args, pi->err.clas));
976
+ } else {
977
+ oj_err_raise(&pi->err);
978
+ }
979
+ oj_err_raise(&pi->err);
940
980
  } else if (0 != line) {
941
- rb_jump_tag(line);
981
+ rb_jump_tag(line);
942
982
  }
943
983
  return result;
944
984
  }