oj 3.10.6 → 3.12.0

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