oj 3.10.18 → 3.11.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) 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 +406 -407
  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 +1132 -918
  31. data/ext/oj/oj.h +286 -297
  32. data/ext/oj/parse.c +943 -926
  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 +781 -716
  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/pages/Modes.md +2 -1
  60. data/pages/Options.md +8 -0
  61. data/test/activerecord/result_test.rb +7 -2
  62. data/test/foo.rb +35 -32
  63. data/test/helper.rb +10 -0
  64. data/test/json_gem/json_generator_test.rb +15 -3
  65. data/test/json_gem/test_helper.rb +8 -0
  66. data/test/test_compat.rb +3 -3
  67. data/test/test_hash.rb +10 -0
  68. data/test/test_scp.rb +1 -1
  69. data/test/test_various.rb +1 -0
  70. metadata +82 -82
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,789 +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;
403
- ni.no_big = (FloatDec == pi->options.bigdec_load || FastDec == pi->options.bigdec_load || RubyDec == pi->options.bigdec_load);
404
- ni.bigdec_load = pi->options.bigdec_load;
425
+ ni.nan = 0;
426
+ ni.neg = 0;
427
+ ni.has_exp = 0;
428
+ if (CompatMode == pi->options.mode) {
429
+ ni.no_big = !pi->options.compat_bigdec;
430
+ ni.bigdec_load = pi->options.compat_bigdec;
431
+ } else {
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;
435
+ }
405
436
 
406
437
  c = reader_get(&pi->rd);
407
438
  if ('-' == c) {
408
- c = reader_get(&pi->rd);
409
- ni.neg = 1;
439
+ c = reader_get(&pi->rd);
440
+ ni.neg = 1;
410
441
  } else if ('+' == c) {
411
- c = reader_get(&pi->rd);
442
+ c = reader_get(&pi->rd);
412
443
  }
413
444
  if ('I' == c) {
414
- if (No == pi->options.allow_nan) {
415
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
416
- return;
417
- } else if (0 != reader_expect(&pi->rd, "nfinity")) {
418
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
419
- return;
420
- }
421
- 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;
422
461
  } else {
423
- int dec_cnt = 0;
424
- bool zero1 = false;
425
-
426
- for (; '0' <= c && c <= '9'; c = reader_get(&pi->rd)) {
427
- if (0 == ni.i && '0' == c) {
428
- zero1 = true;
429
- }
430
- if (0 < ni.i) {
431
- dec_cnt++;
432
- }
433
- if (ni.big) {
434
- ni.big++;
435
- } else {
436
- int d = (c - '0');
437
-
438
- if (0 < d) {
439
- if (zero1 && CompatMode == pi->options.mode) {
440
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number");
441
- return;
442
- }
443
- zero1 = false;
444
- }
445
- ni.i = ni.i * 10 + d;
446
- if (INT64_MAX <= ni.i || DEC_MAX < dec_cnt) {
447
- ni.big = 1;
448
- }
449
- }
450
- }
451
- if ('.' == c) {
452
- c = reader_get(&pi->rd);
453
- // A trailing . is not a valid decimal but if encountered allow it
454
- // except when mimicing the JSON gem.
455
- if (CompatMode == pi->options.mode) {
456
- if (c < '0' || '9' < c) {
457
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number");
458
- }
459
- }
460
- for (; '0' <= c && c <= '9'; c = reader_get(&pi->rd)) {
461
- int d = (c - '0');
462
-
463
- if (0 < ni.num || 0 < ni.i) {
464
- dec_cnt++;
465
- }
466
- if (INT64_MAX <= ni.div) {
467
- if (!ni.no_big) {
468
- ni.big = true;
469
- }
470
- } else {
471
- ni.num = ni.num * 10 + d;
472
- ni.div *= 10;
473
- ni.di++;
474
- if (INT64_MAX <= ni.div || DEC_MAX < dec_cnt) {
475
- if (!ni.no_big) {
476
- ni.big = true;
477
- }
478
- }
479
- }
480
- }
481
- }
482
- if ('e' == c || 'E' == c) {
483
- int eneg = 0;
484
-
485
- ni.has_exp = 1;
486
- c = reader_get(&pi->rd);
487
- if ('-' == c) {
488
- c = reader_get(&pi->rd);
489
- eneg = 1;
490
- } else if ('+' == c) {
491
- c = reader_get(&pi->rd);
492
- }
493
- for (; '0' <= c && c <= '9'; c = reader_get(&pi->rd)) {
494
- ni.exp = ni.exp * 10 + (c - '0');
495
- if (EXP_MAX <= ni.exp) {
496
- ni.big = 1;
497
- }
498
- }
499
- if (eneg) {
500
- ni.exp = -ni.exp;
501
- }
502
- }
503
- ni.len = pi->rd.tail - pi->rd.str;
504
- if (0 != c) {
505
- reader_backup(&pi->rd);
506
- }
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
+ }
507
550
  }
508
551
  ni.str = pi->rd.str;
509
552
  ni.len = pi->rd.tail - pi->rd.str;
510
553
  // Check for special reserved values for Infinity and NaN.
511
554
  if (ni.big) {
512
- if (0 == strcasecmp(INF_VAL, ni.str)) {
513
- ni.infinity = 1;
514
- } else if (0 == strcasecmp(NINF_VAL, ni.str)) {
515
- ni.infinity = 1;
516
- ni.neg = 1;
517
- } else if (0 == strcasecmp(NAN_VAL, ni.str)) {
518
- ni.nan = 1;
519
- }
520
- }
521
- if (BigDec == pi->options.bigdec_load) {
522
- ni.big = 1;
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
+ }
563
+ }
564
+ if (CompatMode == pi->options.mode) {
565
+ if (pi->options.compat_bigdec) {
566
+ ni.big = 1;
567
+ }
568
+ } else if (BigDec == pi->options.bigdec_load) {
569
+ ni.big = 1;
523
570
  }
524
571
  add_num_value(pi, &ni);
525
572
  reader_release(&pi->rd);
526
573
  }
527
574
 
528
- static void
529
- read_nan(ParseInfo pi) {
530
- struct _numInfo ni;
531
- char c;
532
-
533
- ni.str = pi->rd.str;
534
- ni.i = 0;
535
- ni.num = 0;
536
- ni.div = 1;
537
- ni.di = 0;
538
- ni.len = 0;
539
- ni.exp = 0;
540
- 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;
541
587
  ni.infinity = 0;
542
- ni.nan = 1;
543
- ni.neg = 0;
544
- ni.no_big = (FloatDec == pi->options.bigdec_load || FastDec == pi->options.bigdec_load || RubyDec == pi->options.bigdec_load);
545
- ni.bigdec_load = pi->options.bigdec_load;
588
+ ni.nan = 1;
589
+ ni.neg = 0;
590
+ if (CompatMode == pi->options.mode) {
591
+ ni.no_big = !pi->options.compat_bigdec;
592
+ ni.bigdec_load = pi->options.compat_bigdec;
593
+ } else {
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;
597
+ }
546
598
 
547
- if ('a' != reader_get(&pi->rd) ||
548
- ('N' != (c = reader_get(&pi->rd)) && 'n' != c)) {
549
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
550
- 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;
551
602
  }
552
- if (BigDec == pi->options.bigdec_load) {
553
- ni.big = 1;
603
+ if (CompatMode == pi->options.mode) {
604
+ if (pi->options.compat_bigdec) {
605
+ ni.big = 1;
606
+ }
607
+ } else if (BigDec == pi->options.bigdec_load) {
608
+ ni.big = 1;
554
609
  }
555
610
  add_num_value(pi, &ni);
556
611
  }
557
612
 
558
- static void
559
- array_start(ParseInfo pi) {
560
- VALUE v = pi->start_array(pi);
613
+ static void array_start(ParseInfo pi) {
614
+ VALUE v = pi->start_array(pi);
561
615
 
562
616
  stack_push(&pi->stack, v, NEXT_ARRAY_NEW);
563
617
  }
564
618
 
565
- static void
566
- array_end(ParseInfo pi) {
567
- Val array = stack_pop(&pi->stack);
619
+ static void array_end(ParseInfo pi) {
620
+ Val array = stack_pop(&pi->stack);
568
621
 
569
622
  if (0 == array) {
570
- 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");
571
624
  } else if (NEXT_ARRAY_COMMA != array->next && NEXT_ARRAY_NEW != array->next) {
572
- 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));
573
631
  } else {
574
- pi->end_array(pi);
575
- add_value(pi, array->val);
632
+ pi->end_array(pi);
633
+ add_value(pi, array->val);
576
634
  }
577
635
  }
578
636
 
579
- static void
580
- hash_start(ParseInfo pi) {
581
- volatile VALUE v = pi->start_hash(pi);
637
+ static void hash_start(ParseInfo pi) {
638
+ volatile VALUE v = pi->start_hash(pi);
582
639
 
583
640
  stack_push(&pi->stack, v, NEXT_HASH_NEW);
584
641
  }
585
642
 
586
- static void
587
- hash_end(ParseInfo pi) {
588
- volatile Val hash = stack_peek(&pi->stack);
643
+ static void hash_end(ParseInfo pi) {
644
+ volatile Val hash = stack_peek(&pi->stack);
589
645
 
590
646
  // leave hash on stack until just before
591
647
  if (0 == hash) {
592
- 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");
593
649
  } else if (NEXT_HASH_COMMA != hash->next && NEXT_HASH_NEW != hash->next) {
594
- 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));
595
656
  } else {
596
- pi->end_hash(pi);
597
- stack_pop(&pi->stack);
598
- add_value(pi, hash->val);
657
+ pi->end_hash(pi);
658
+ stack_pop(&pi->stack);
659
+ add_value(pi, hash->val);
599
660
  }
600
661
  }
601
662
 
602
- static void
603
- comma(ParseInfo pi) {
604
- Val parent = stack_peek(&pi->stack);
663
+ static void comma(ParseInfo pi) {
664
+ Val parent = stack_peek(&pi->stack);
605
665
 
606
666
  if (0 == parent) {
607
- 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");
608
668
  } else if (NEXT_ARRAY_COMMA == parent->next) {
609
- parent->next = NEXT_ARRAY_ELEMENT;
669
+ parent->next = NEXT_ARRAY_ELEMENT;
610
670
  } else if (NEXT_HASH_COMMA == parent->next) {
611
- parent->next = NEXT_HASH_KEY;
671
+ parent->next = NEXT_HASH_KEY;
612
672
  } else {
613
- 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");
614
674
  }
615
675
  }
616
676
 
617
- static void
618
- colon(ParseInfo pi) {
619
- Val parent = stack_peek(&pi->stack);
677
+ static void colon(ParseInfo pi) {
678
+ Val parent = stack_peek(&pi->stack);
620
679
 
621
680
  if (0 != parent && NEXT_HASH_COLON == parent->next) {
622
- parent->next = NEXT_HASH_VALUE;
681
+ parent->next = NEXT_HASH_VALUE;
623
682
  } else {
624
- 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");
625
684
  }
626
685
  }
627
686
 
628
- void
629
- oj_sparse2(ParseInfo pi) {
630
- int first = 1;
631
- char c;
632
- long start = 0;
687
+ void oj_sparse2(ParseInfo pi) {
688
+ int first = 1;
689
+ char c;
690
+ long start = 0;
633
691
 
634
692
  err_init(&pi->err);
635
693
  while (1) {
636
- if (0 < pi->max_depth && pi->max_depth <= pi->stack.tail - pi->stack.head - 1) {
637
- VALUE err_clas = oj_get_json_err_class("NestingError");
638
-
639
- oj_set_error_at(pi, err_clas, __FILE__, __LINE__, "Too deeply nested.");
640
- pi->err_class = err_clas;
641
- return;
642
- }
643
- c = reader_next_non_white(&pi->rd);
644
- if (!first && '\0' != c) {
645
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected characters after the JSON document");
646
- }
647
- switch (c) {
648
- case '{':
649
- hash_start(pi);
650
- break;
651
- case '}':
652
- hash_end(pi);
653
- break;
654
- case ':':
655
- colon(pi);
656
- break;
657
- case '[':
658
- array_start(pi);
659
- break;
660
- case ']':
661
- array_end(pi);
662
- break;
663
- case ',':
664
- comma(pi);
665
- break;
666
- case '"':
667
- read_str(pi);
668
- break;
669
- case '+':
670
- if (CompatMode == pi->options.mode) {
671
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected character");
672
- return;
673
- }
674
- pi->cur--;
675
- read_num(pi);
676
- break;
677
- case '-':
678
- case '0':
679
- case '1':
680
- case '2':
681
- case '3':
682
- case '4':
683
- case '5':
684
- case '6':
685
- case '7':
686
- case '8':
687
- case '9':
688
- reader_backup(&pi->rd);
689
- read_num(pi);
690
- break;
691
- case 'I':
692
- if (Yes == pi->options.allow_nan) {
693
- reader_backup(&pi->rd);
694
- read_num(pi);
695
- } else {
696
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected character");
697
- return;
698
- }
699
- break;
700
- case 'N':
701
- if (Yes == pi->options.allow_nan) {
702
- read_nan(pi);
703
- } else {
704
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected character");
705
- return;
706
- }
707
- break;
708
- case 't':
709
- read_true(pi);
710
- break;
711
- case 'f':
712
- read_false(pi);
713
- break;
714
- case 'n':
715
- c = reader_get(&pi->rd);
716
- if ('u' == c) {
717
- if (0 == reader_expect(&pi->rd, "ll")) {
718
- add_value(pi, Qnil);
719
- } else {
720
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected null");
721
- return;
722
- }
723
- } else if ('a' == c) {
724
- struct _numInfo ni;
725
-
726
- c = reader_get(&pi->rd);
727
- if ('N' != c && 'n' != c) {
728
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected NaN");
729
- return;
730
- }
731
- ni.str = pi->rd.str;
732
- ni.i = 0;
733
- ni.num = 0;
734
- ni.div = 1;
735
- ni.di = 0;
736
- ni.len = 0;
737
- ni.exp = 0;
738
- ni.big = 0;
739
- ni.infinity = 0;
740
- ni.nan = 1;
741
- ni.neg = 0;
742
- ni.no_big = (FloatDec == pi->options.bigdec_load || RubyDec == pi->options.bigdec_load || FastDec == pi->options.bigdec_load);
743
- ni.bigdec_load = pi->options.bigdec_load;
744
- add_num_value(pi, &ni);
745
- } else {
746
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid token");
747
- return;
748
- }
749
- break;
750
- case '/':
751
- skip_comment(pi);
752
- break;
753
- case '\0':
754
- return;
755
- default:
756
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected character '%c' [0x%02x]", c, c);
757
- return;
758
- }
759
- if (err_has(&pi->err)) {
760
- return;
761
- }
762
- if (stack_empty(&pi->stack)) {
763
- if (Qundef != pi->proc) {
764
- VALUE args[3];
765
- long len = pi->rd.pos - start;
766
-
767
- *args = stack_head_val(&pi->stack);
768
- args[1] = LONG2NUM(start);
769
- args[2] = LONG2NUM(len);
770
-
771
- if (Qnil == pi->proc) {
772
- rb_yield_values2(3, args);
773
- } else {
774
- rb_proc_call_with_block(pi->proc, 3, args, Qnil);
775
- }
776
- } else if (!pi->has_callbacks) {
777
- first = 0;
778
- }
779
- start = pi->rd.pos;
780
- // TBD break if option set to allow that
781
- }
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
+ }
782
848
  }
783
849
  }
784
850
 
785
- static VALUE
786
- protect_parse(VALUE pip) {
851
+ static VALUE protect_parse(VALUE pip) {
787
852
  oj_sparse2((ParseInfo)pip);
788
853
 
789
854
  return Qnil;
@@ -791,46 +856,47 @@ protect_parse(VALUE pip) {
791
856
 
792
857
  VALUE
793
858
  oj_pi_sparse(int argc, VALUE *argv, ParseInfo pi, int fd) {
794
- volatile VALUE input;
795
- volatile VALUE wrapped_stack;
796
- VALUE result = Qnil;
797
- int line = 0;
859
+ volatile VALUE input;
860
+ volatile VALUE wrapped_stack;
861
+ VALUE result = Qnil;
862
+ int line = 0;
798
863
 
799
864
  if (argc < 1) {
800
- rb_raise(rb_eArgError, "Wrong number of arguments to parse.");
865
+ rb_raise(rb_eArgError, "Wrong number of arguments to parse.");
801
866
  }
802
867
  input = argv[0];
803
868
  if (2 <= argc) {
804
- if (T_HASH == rb_type(argv[1])) {
805
- oj_parse_options(argv[1], &pi->options);
806
- } else if (3 <= argc && T_HASH == rb_type(argv[2])) {
807
- oj_parse_options(argv[2], &pi->options);
808
- }
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
+ }
809
874
  }
810
875
  if (Qnil == input) {
811
- if (Yes == pi->options.nilnil) {
812
- return Qnil;
813
- } else {
814
- rb_raise(rb_eTypeError, "Nil is not a valid JSON source.");
815
- }
816
- } else if (CompatMode == pi->options.mode && T_STRING == rb_type(input) && No == pi->options.nilnil && 0 == RSTRING_LEN(input)) {
817
- 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.");
818
884
  }
819
885
  if (rb_block_given_p()) {
820
- pi->proc = Qnil;
886
+ pi->proc = Qnil;
821
887
  } else {
822
- pi->proc = Qundef;
888
+ pi->proc = Qundef;
823
889
  }
824
890
  oj_reader_init(&pi->rd, input, fd, CompatMode == pi->options.mode);
825
- pi->json = 0; // indicates reader is in use
891
+ pi->json = 0; // indicates reader is in use
826
892
 
827
893
  if (Yes == pi->options.circular) {
828
- pi->circ_array = oj_circ_array_new();
894
+ pi->circ_array = oj_circ_array_new();
829
895
  } else {
830
- pi->circ_array = 0;
896
+ pi->circ_array = 0;
831
897
  }
832
898
  if (No == pi->options.allow_gc) {
833
- rb_gc_disable();
899
+ rb_gc_disable();
834
900
  }
835
901
  // GC can run at any time. When it runs any Object created by C will be
836
902
  // freed. We protect against this by wrapping the value stack in a ruby
@@ -839,81 +905,80 @@ oj_pi_sparse(int argc, VALUE *argv, ParseInfo pi, int fd) {
839
905
  wrapped_stack = oj_stack_init(&pi->stack);
840
906
  rb_protect(protect_parse, (VALUE)pi, &line);
841
907
  if (Qundef == pi->stack.head->val && !empty_ok(&pi->options)) {
842
- 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");
843
909
  }
844
- result = stack_head_val(&pi->stack);
910
+ result = stack_head_val(&pi->stack);
845
911
  DATA_PTR(wrapped_stack) = 0;
846
912
  if (No == pi->options.allow_gc) {
847
- rb_gc_enable();
913
+ rb_gc_enable();
848
914
  }
849
915
  if (!err_has(&pi->err)) {
850
- // If the stack is not empty then the JSON terminated early.
851
- Val v;
852
- VALUE err_class = oj_parse_error_class;
853
-
854
- if (0 != line) {
855
- VALUE ec = rb_obj_class(rb_errinfo());
856
-
857
- if (rb_eIOError != ec) {
858
- goto CLEANUP;
859
- }
860
- // Sometimes the class of the error is 0 which seems broken.
861
- if (rb_eArgError != ec && 0 != ec) {
862
- err_class = ec;
863
- }
864
- }
865
- if (0 != (v = stack_peek(&pi->stack))) {
866
- switch (v->next) {
867
- case NEXT_ARRAY_NEW:
868
- case NEXT_ARRAY_ELEMENT:
869
- case NEXT_ARRAY_COMMA:
870
- oj_set_error_at(pi, err_class, __FILE__, __LINE__, "Array not terminated");
871
- break;
872
- case NEXT_HASH_NEW:
873
- case NEXT_HASH_KEY:
874
- case NEXT_HASH_COLON:
875
- case NEXT_HASH_VALUE:
876
- case NEXT_HASH_COMMA:
877
- oj_set_error_at(pi, err_class, __FILE__, __LINE__, "Hash/Object not terminated");
878
- break;
879
- default:
880
- oj_set_error_at(pi, err_class, __FILE__, __LINE__, "not terminated");
881
- }
882
- }
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
+ }
883
948
  }
884
949
  CLEANUP:
885
950
  // proceed with cleanup
886
951
  if (0 != pi->circ_array) {
887
- oj_circ_array_free(pi->circ_array);
952
+ oj_circ_array_free(pi->circ_array);
888
953
  }
889
954
  stack_cleanup(&pi->stack);
890
955
  if (0 != fd) {
891
- close(fd);
956
+ close(fd);
892
957
  }
893
958
  if (err_has(&pi->err)) {
894
- rb_set_errinfo(Qnil);
895
- if (Qnil != pi->err_class && 0 != pi->err_class) {
896
- pi->err.clas = pi->err_class;
897
- }
898
- if (CompatMode == pi->options.mode && Yes != pi->options.safe) {
899
- // The json gem requires the error message be UTF-8 encoded. In
900
- // additional the complete JSON source should be returned but that
901
- // is not possible without stored all the bytes read and reading
902
- // the remaining bytes on the stream. Both seem like a very bad
903
- // idea.
904
- VALUE args[] = { oj_encode(rb_str_new2(pi->err.msg)) };
905
-
906
- if (pi->err.clas == oj_parse_error_class) {
907
- // The error was an Oj::ParseError so change to a JSON::ParserError.
908
- pi->err.clas = oj_json_parser_error_class;
909
- }
910
- rb_exc_raise(rb_class_new_instance(1, args, pi->err.clas));
911
- } else {
912
- oj_err_raise(&pi->err);
913
- }
914
- 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);
915
980
  } else if (0 != line) {
916
- rb_jump_tag(line);
981
+ rb_jump_tag(line);
917
982
  }
918
983
  return result;
919
984
  }