oj 3.11.1 → 3.11.6

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