oj 3.10.18 → 3.11.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -1
  3. data/ext/oj/buf.h +34 -38
  4. data/ext/oj/cache8.c +59 -62
  5. data/ext/oj/cache8.h +8 -7
  6. data/ext/oj/circarray.c +33 -35
  7. data/ext/oj/circarray.h +11 -9
  8. data/ext/oj/code.c +170 -174
  9. data/ext/oj/code.h +21 -20
  10. data/ext/oj/compat.c +159 -166
  11. data/ext/oj/custom.c +802 -851
  12. data/ext/oj/dump.c +766 -778
  13. data/ext/oj/dump.h +49 -51
  14. data/ext/oj/dump_compat.c +1 -0
  15. data/ext/oj/dump_leaf.c +116 -157
  16. data/ext/oj/dump_object.c +609 -628
  17. data/ext/oj/dump_strict.c +318 -327
  18. data/ext/oj/encode.h +3 -4
  19. data/ext/oj/err.c +39 -25
  20. data/ext/oj/err.h +24 -15
  21. data/ext/oj/extconf.rb +2 -1
  22. data/ext/oj/fast.c +1008 -1038
  23. data/ext/oj/hash.c +62 -66
  24. data/ext/oj/hash.h +7 -6
  25. data/ext/oj/hash_test.c +450 -443
  26. data/ext/oj/mimic_json.c +406 -407
  27. data/ext/oj/object.c +559 -528
  28. data/ext/oj/odd.c +123 -128
  29. data/ext/oj/odd.h +27 -25
  30. data/ext/oj/oj.c +1132 -918
  31. data/ext/oj/oj.h +286 -297
  32. data/ext/oj/parse.c +943 -926
  33. data/ext/oj/parse.h +70 -69
  34. data/ext/oj/rails.c +836 -839
  35. data/ext/oj/rails.h +7 -7
  36. data/ext/oj/reader.c +135 -140
  37. data/ext/oj/reader.h +66 -79
  38. data/ext/oj/resolve.c +43 -43
  39. data/ext/oj/resolve.h +3 -2
  40. data/ext/oj/rxclass.c +67 -68
  41. data/ext/oj/rxclass.h +12 -10
  42. data/ext/oj/saj.c +451 -479
  43. data/ext/oj/scp.c +93 -103
  44. data/ext/oj/sparse.c +781 -716
  45. data/ext/oj/stream_writer.c +120 -149
  46. data/ext/oj/strict.c +71 -86
  47. data/ext/oj/string_writer.c +198 -243
  48. data/ext/oj/trace.c +29 -33
  49. data/ext/oj/trace.h +14 -11
  50. data/ext/oj/util.c +103 -103
  51. data/ext/oj/util.h +3 -2
  52. data/ext/oj/val_stack.c +47 -47
  53. data/ext/oj/val_stack.h +79 -86
  54. data/ext/oj/wab.c +291 -309
  55. data/lib/oj/bag.rb +1 -0
  56. data/lib/oj/easy_hash.rb +5 -4
  57. data/lib/oj/mimic.rb +0 -12
  58. data/lib/oj/version.rb +1 -1
  59. data/pages/Modes.md +2 -1
  60. data/pages/Options.md +8 -0
  61. data/test/activerecord/result_test.rb +7 -2
  62. data/test/foo.rb +35 -32
  63. data/test/helper.rb +10 -0
  64. data/test/json_gem/json_generator_test.rb +15 -3
  65. data/test/json_gem/test_helper.rb +8 -0
  66. data/test/test_compat.rb +3 -3
  67. data/test/test_hash.rb +10 -0
  68. data/test/test_scp.rb +1 -1
  69. data/test/test_various.rb +1 -0
  70. metadata +82 -82
data/ext/oj/parse.c CHANGED
@@ -1,944 +1,961 @@
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 "parse.h"
5
+
6
+ #include <math.h>
7
+ #include <ruby/util.h>
4
8
  #include <stdio.h>
9
+ #include <stdlib.h>
5
10
  #include <string.h>
6
11
  #include <unistd.h>
7
- #include <math.h>
8
- #include <ruby/util.h>
9
12
 
10
- #include "oj.h"
11
- #include "encode.h"
12
- #include "parse.h"
13
13
  #include "buf.h"
14
- #include "val_stack.h"
14
+ #include "encode.h"
15
+ #include "oj.h"
15
16
  #include "rxclass.h"
17
+ #include "val_stack.h"
16
18
 
17
19
  // Workaround in case INFINITY is not defined in math.h or if the OS is CentOS
18
- #define OJ_INFINITY (1.0/0.0)
20
+ #define OJ_INFINITY (1.0 / 0.0)
19
21
 
20
22
  //#define EXP_MAX 1023
21
- #define EXP_MAX 100000
22
- #define DEC_MAX 15
23
+ #define EXP_MAX 100000
24
+ #define DEC_MAX 15
23
25
 
24
- static void
25
- next_non_white(ParseInfo pi) {
26
+ static void next_non_white(ParseInfo pi) {
26
27
  for (; 1; pi->cur++) {
27
- switch(*pi->cur) {
28
- case ' ':
29
- case '\t':
30
- case '\f':
31
- case '\n':
32
- case '\r':
33
- break;
34
- default:
35
- return;
36
- }
28
+ switch (*pi->cur) {
29
+ case ' ':
30
+ case '\t':
31
+ case '\f':
32
+ case '\n':
33
+ case '\r': break;
34
+ default: return;
35
+ }
37
36
  }
38
37
  }
39
38
 
40
- static void
41
- skip_comment(ParseInfo pi) {
39
+ static void skip_comment(ParseInfo pi) {
42
40
  if ('*' == *pi->cur) {
43
- pi->cur++;
44
- for (; pi->cur < pi->end; pi->cur++) {
45
- if ('*' == *pi->cur && '/' == *(pi->cur + 1)) {
46
- pi->cur += 2;
47
- return;
48
- } else if (pi->end <= pi->cur) {
49
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "comment not terminated");
50
- return;
51
- }
52
- }
41
+ pi->cur++;
42
+ for (; pi->cur < pi->end; pi->cur++) {
43
+ if ('*' == *pi->cur && '/' == *(pi->cur + 1)) {
44
+ pi->cur += 2;
45
+ return;
46
+ } else if (pi->end <= pi->cur) {
47
+ oj_set_error_at(pi,
48
+ oj_parse_error_class,
49
+ __FILE__,
50
+ __LINE__,
51
+ "comment not terminated");
52
+ return;
53
+ }
54
+ }
53
55
  } else if ('/' == *pi->cur) {
54
- for (; 1; pi->cur++) {
55
- switch (*pi->cur) {
56
- case '\n':
57
- case '\r':
58
- case '\f':
59
- case '\0':
60
- return;
61
- default:
62
- break;
63
- }
64
- }
56
+ for (; 1; pi->cur++) {
57
+ switch (*pi->cur) {
58
+ case '\n':
59
+ case '\r':
60
+ case '\f':
61
+ case '\0': return;
62
+ default: break;
63
+ }
64
+ }
65
65
  } else {
66
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid comment format");
66
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid comment format");
67
67
  }
68
68
  }
69
69
 
70
- static void
71
- add_value(ParseInfo pi, VALUE rval) {
72
- Val parent = stack_peek(&pi->stack);
70
+ static void add_value(ParseInfo pi, VALUE rval) {
71
+ Val parent = stack_peek(&pi->stack);
73
72
 
74
- if (0 == parent) { // simple add
75
- pi->add_value(pi, rval);
73
+ if (0 == parent) { // simple add
74
+ pi->add_value(pi, rval);
76
75
  } else {
77
- switch (parent->next) {
78
- case NEXT_ARRAY_NEW:
79
- case NEXT_ARRAY_ELEMENT:
80
- pi->array_append_value(pi, rval);
81
- parent->next = NEXT_ARRAY_COMMA;
82
- break;
83
- case NEXT_HASH_VALUE:
84
- pi->hash_set_value(pi, parent, rval);
85
- if (0 != parent->key && 0 < parent->klen && (parent->key < pi->json || pi->cur < parent->key)) {
86
- xfree((char*)parent->key);
87
- parent->key = 0;
88
- }
89
- parent->next = NEXT_HASH_COMMA;
90
- break;
91
- case NEXT_HASH_NEW:
92
- case NEXT_HASH_KEY:
93
- case NEXT_HASH_COMMA:
94
- case NEXT_NONE:
95
- case NEXT_ARRAY_COMMA:
96
- case NEXT_HASH_COLON:
97
- default:
98
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected %s", oj_stack_next_string(parent->next));
99
- break;
100
- }
76
+ switch (parent->next) {
77
+ case NEXT_ARRAY_NEW:
78
+ case NEXT_ARRAY_ELEMENT:
79
+ pi->array_append_value(pi, rval);
80
+ parent->next = NEXT_ARRAY_COMMA;
81
+ break;
82
+ case NEXT_HASH_VALUE:
83
+ pi->hash_set_value(pi, parent, rval);
84
+ if (0 != parent->key && 0 < parent->klen &&
85
+ (parent->key < pi->json || pi->cur < parent->key)) {
86
+ xfree((char *)parent->key);
87
+ parent->key = 0;
88
+ }
89
+ parent->next = NEXT_HASH_COMMA;
90
+ break;
91
+ case NEXT_HASH_NEW:
92
+ case NEXT_HASH_KEY:
93
+ case NEXT_HASH_COMMA:
94
+ case NEXT_NONE:
95
+ case NEXT_ARRAY_COMMA:
96
+ case NEXT_HASH_COLON:
97
+ default:
98
+ oj_set_error_at(pi,
99
+ oj_parse_error_class,
100
+ __FILE__,
101
+ __LINE__,
102
+ "expected %s",
103
+ oj_stack_next_string(parent->next));
104
+ break;
105
+ }
101
106
  }
102
107
  }
103
108
 
104
- static void
105
- read_null(ParseInfo pi) {
109
+ static void read_null(ParseInfo pi) {
106
110
  if ('u' == *pi->cur++ && 'l' == *pi->cur++ && 'l' == *pi->cur++) {
107
- add_value(pi, Qnil);
111
+ add_value(pi, Qnil);
108
112
  } else {
109
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected null");
113
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected null");
110
114
  }
111
115
  }
112
116
 
113
- static void
114
- read_true(ParseInfo pi) {
117
+ static void read_true(ParseInfo pi) {
115
118
  if ('r' == *pi->cur++ && 'u' == *pi->cur++ && 'e' == *pi->cur++) {
116
- add_value(pi, Qtrue);
119
+ add_value(pi, Qtrue);
117
120
  } else {
118
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected true");
121
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected true");
119
122
  }
120
123
  }
121
124
 
122
- static void
123
- read_false(ParseInfo pi) {
125
+ static void read_false(ParseInfo pi) {
124
126
  if ('a' == *pi->cur++ && 'l' == *pi->cur++ && 's' == *pi->cur++ && 'e' == *pi->cur++) {
125
- add_value(pi, Qfalse);
127
+ add_value(pi, Qfalse);
126
128
  } else {
127
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected false");
129
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected false");
128
130
  }
129
131
  }
130
132
 
131
- static uint32_t
132
- read_hex(ParseInfo pi, const char *h) {
133
- uint32_t b = 0;
134
- int i;
133
+ static uint32_t read_hex(ParseInfo pi, const char *h) {
134
+ uint32_t b = 0;
135
+ int i;
135
136
 
136
137
  for (i = 0; i < 4; i++, h++) {
137
- b = b << 4;
138
- if ('0' <= *h && *h <= '9') {
139
- b += *h - '0';
140
- } else if ('A' <= *h && *h <= 'F') {
141
- b += *h - 'A' + 10;
142
- } else if ('a' <= *h && *h <= 'f') {
143
- b += *h - 'a' + 10;
144
- } else {
145
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid hex character");
146
- return 0;
147
- }
138
+ b = b << 4;
139
+ if ('0' <= *h && *h <= '9') {
140
+ b += *h - '0';
141
+ } else if ('A' <= *h && *h <= 'F') {
142
+ b += *h - 'A' + 10;
143
+ } else if ('a' <= *h && *h <= 'f') {
144
+ b += *h - 'a' + 10;
145
+ } else {
146
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid hex character");
147
+ return 0;
148
+ }
148
149
  }
149
150
  return b;
150
151
  }
151
152
 
152
- static void
153
- unicode_to_chars(ParseInfo pi, Buf buf, uint32_t code) {
153
+ static void unicode_to_chars(ParseInfo pi, Buf buf, uint32_t code) {
154
154
  if (0x0000007F >= code) {
155
- buf_append(buf, (char)code);
155
+ buf_append(buf, (char)code);
156
156
  } else if (0x000007FF >= code) {
157
- buf_append(buf, 0xC0 | (code >> 6));
158
- buf_append(buf, 0x80 | (0x3F & code));
157
+ buf_append(buf, 0xC0 | (code >> 6));
158
+ buf_append(buf, 0x80 | (0x3F & code));
159
159
  } else if (0x0000FFFF >= code) {
160
- buf_append(buf, 0xE0 | (code >> 12));
161
- buf_append(buf, 0x80 | ((code >> 6) & 0x3F));
162
- buf_append(buf, 0x80 | (0x3F & code));
160
+ buf_append(buf, 0xE0 | (code >> 12));
161
+ buf_append(buf, 0x80 | ((code >> 6) & 0x3F));
162
+ buf_append(buf, 0x80 | (0x3F & code));
163
163
  } else if (0x001FFFFF >= code) {
164
- buf_append(buf, 0xF0 | (code >> 18));
165
- buf_append(buf, 0x80 | ((code >> 12) & 0x3F));
166
- buf_append(buf, 0x80 | ((code >> 6) & 0x3F));
167
- buf_append(buf, 0x80 | (0x3F & code));
164
+ buf_append(buf, 0xF0 | (code >> 18));
165
+ buf_append(buf, 0x80 | ((code >> 12) & 0x3F));
166
+ buf_append(buf, 0x80 | ((code >> 6) & 0x3F));
167
+ buf_append(buf, 0x80 | (0x3F & code));
168
168
  } else if (0x03FFFFFF >= code) {
169
- buf_append(buf, 0xF8 | (code >> 24));
170
- buf_append(buf, 0x80 | ((code >> 18) & 0x3F));
171
- buf_append(buf, 0x80 | ((code >> 12) & 0x3F));
172
- buf_append(buf, 0x80 | ((code >> 6) & 0x3F));
173
- buf_append(buf, 0x80 | (0x3F & code));
169
+ buf_append(buf, 0xF8 | (code >> 24));
170
+ buf_append(buf, 0x80 | ((code >> 18) & 0x3F));
171
+ buf_append(buf, 0x80 | ((code >> 12) & 0x3F));
172
+ buf_append(buf, 0x80 | ((code >> 6) & 0x3F));
173
+ buf_append(buf, 0x80 | (0x3F & code));
174
174
  } else if (0x7FFFFFFF >= code) {
175
- buf_append(buf, 0xFC | (code >> 30));
176
- buf_append(buf, 0x80 | ((code >> 24) & 0x3F));
177
- buf_append(buf, 0x80 | ((code >> 18) & 0x3F));
178
- buf_append(buf, 0x80 | ((code >> 12) & 0x3F));
179
- buf_append(buf, 0x80 | ((code >> 6) & 0x3F));
180
- buf_append(buf, 0x80 | (0x3F & code));
175
+ buf_append(buf, 0xFC | (code >> 30));
176
+ buf_append(buf, 0x80 | ((code >> 24) & 0x3F));
177
+ buf_append(buf, 0x80 | ((code >> 18) & 0x3F));
178
+ buf_append(buf, 0x80 | ((code >> 12) & 0x3F));
179
+ buf_append(buf, 0x80 | ((code >> 6) & 0x3F));
180
+ buf_append(buf, 0x80 | (0x3F & code));
181
181
  } else {
182
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid Unicode character");
182
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid Unicode character");
183
183
  }
184
184
  }
185
185
 
186
186
  // entered at /
187
- static void
188
- read_escaped_str(ParseInfo pi, const char *start) {
189
- struct _buf buf;
190
- const char *s;
191
- int cnt = (int)(pi->cur - start);
192
- uint32_t code;
193
- Val parent = stack_peek(&pi->stack);
187
+ static void read_escaped_str(ParseInfo pi, const char *start) {
188
+ struct _buf buf;
189
+ const char *s;
190
+ int cnt = (int)(pi->cur - start);
191
+ uint32_t code;
192
+ Val parent = stack_peek(&pi->stack);
194
193
 
195
194
  buf_init(&buf);
196
195
  if (0 < cnt) {
197
- buf_append_string(&buf, start, cnt);
196
+ buf_append_string(&buf, start, cnt);
198
197
  }
199
198
  for (s = pi->cur; '"' != *s; s++) {
200
- if (s >= pi->end) {
201
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "quoted string not terminated");
202
- buf_cleanup(&buf);
203
- return;
204
- } else if ('\\' == *s) {
205
- s++;
206
- switch (*s) {
207
- case 'n': buf_append(&buf, '\n'); break;
208
- case 'r': buf_append(&buf, '\r'); break;
209
- case 't': buf_append(&buf, '\t'); break;
210
- case 'f': buf_append(&buf, '\f'); break;
211
- case 'b': buf_append(&buf, '\b'); break;
212
- case '"': buf_append(&buf, '"'); break;
213
- case '/': buf_append(&buf, '/'); break;
214
- case '\\': buf_append(&buf, '\\'); break;
215
- case 'u':
216
- s++;
217
- if (0 == (code = read_hex(pi, s)) && err_has(&pi->err)) {
218
- buf_cleanup(&buf);
219
- return;
220
- }
221
- s += 3;
222
- if (0x0000D800 <= code && code <= 0x0000DFFF) {
223
- uint32_t c1 = (code - 0x0000D800) & 0x000003FF;
224
- uint32_t c2;
225
-
226
- s++;
227
- if ('\\' != *s || 'u' != *(s + 1)) {
228
- if (Yes == pi->options.allow_invalid) {
229
- s--;
230
- unicode_to_chars(pi, &buf, code);
231
- break;
232
- }
233
- pi->cur = s;
234
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid escaped character");
235
- buf_cleanup(&buf);
236
- return;
237
- }
238
- s += 2;
239
- if (0 == (c2 = read_hex(pi, s)) && err_has(&pi->err)) {
240
- buf_cleanup(&buf);
241
- return;
242
- }
243
- s += 3;
244
- c2 = (c2 - 0x0000DC00) & 0x000003FF;
245
- code = ((c1 << 10) | c2) + 0x00010000;
246
- }
247
- unicode_to_chars(pi, &buf, code);
248
- if (err_has(&pi->err)) {
249
- buf_cleanup(&buf);
250
- return;
251
- }
252
- break;
253
- default:
254
- // The json gem claims this is not an error despite the
255
- // ECMA-404 indicating it is not valid.
256
- if (CompatMode == pi->options.mode) {
257
- buf_append(&buf, *s);
258
- break;
259
- }
260
- pi->cur = s;
261
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid escaped character");
262
- buf_cleanup(&buf);
263
- return;
264
- }
265
- } else {
266
- buf_append(&buf, *s);
267
- }
199
+ if (s >= pi->end) {
200
+ oj_set_error_at(pi,
201
+ oj_parse_error_class,
202
+ __FILE__,
203
+ __LINE__,
204
+ "quoted string not terminated");
205
+ buf_cleanup(&buf);
206
+ return;
207
+ } else if ('\\' == *s) {
208
+ s++;
209
+ switch (*s) {
210
+ case 'n': buf_append(&buf, '\n'); break;
211
+ case 'r': buf_append(&buf, '\r'); break;
212
+ case 't': buf_append(&buf, '\t'); break;
213
+ case 'f': buf_append(&buf, '\f'); break;
214
+ case 'b': buf_append(&buf, '\b'); break;
215
+ case '"': buf_append(&buf, '"'); break;
216
+ case '/': buf_append(&buf, '/'); break;
217
+ case '\\': buf_append(&buf, '\\'); break;
218
+ case 'u':
219
+ s++;
220
+ if (0 == (code = read_hex(pi, s)) && err_has(&pi->err)) {
221
+ buf_cleanup(&buf);
222
+ return;
223
+ }
224
+ s += 3;
225
+ if (0x0000D800 <= code && code <= 0x0000DFFF) {
226
+ uint32_t c1 = (code - 0x0000D800) & 0x000003FF;
227
+ uint32_t c2;
228
+
229
+ s++;
230
+ if ('\\' != *s || 'u' != *(s + 1)) {
231
+ if (Yes == pi->options.allow_invalid) {
232
+ s--;
233
+ unicode_to_chars(pi, &buf, code);
234
+ break;
235
+ }
236
+ pi->cur = s;
237
+ oj_set_error_at(pi,
238
+ oj_parse_error_class,
239
+ __FILE__,
240
+ __LINE__,
241
+ "invalid escaped character");
242
+ buf_cleanup(&buf);
243
+ return;
244
+ }
245
+ s += 2;
246
+ if (0 == (c2 = read_hex(pi, s)) && err_has(&pi->err)) {
247
+ buf_cleanup(&buf);
248
+ return;
249
+ }
250
+ s += 3;
251
+ c2 = (c2 - 0x0000DC00) & 0x000003FF;
252
+ code = ((c1 << 10) | c2) + 0x00010000;
253
+ }
254
+ unicode_to_chars(pi, &buf, code);
255
+ if (err_has(&pi->err)) {
256
+ buf_cleanup(&buf);
257
+ return;
258
+ }
259
+ break;
260
+ default:
261
+ // The json gem claims this is not an error despite the
262
+ // ECMA-404 indicating it is not valid.
263
+ if (CompatMode == pi->options.mode) {
264
+ buf_append(&buf, *s);
265
+ break;
266
+ }
267
+ pi->cur = s;
268
+ oj_set_error_at(pi,
269
+ oj_parse_error_class,
270
+ __FILE__,
271
+ __LINE__,
272
+ "invalid escaped character");
273
+ buf_cleanup(&buf);
274
+ return;
275
+ }
276
+ } else {
277
+ buf_append(&buf, *s);
278
+ }
268
279
  }
269
280
  if (0 == parent) {
270
- pi->add_cstr(pi, buf.head, buf_len(&buf), start);
281
+ pi->add_cstr(pi, buf.head, buf_len(&buf), start);
271
282
  } else {
272
- switch (parent->next) {
273
- case NEXT_ARRAY_NEW:
274
- case NEXT_ARRAY_ELEMENT:
275
- pi->array_append_cstr(pi, buf.head, buf_len(&buf), start);
276
- parent->next = NEXT_ARRAY_COMMA;
277
- break;
278
- case NEXT_HASH_NEW:
279
- case NEXT_HASH_KEY:
280
- if (Qundef == (parent->key_val = pi->hash_key(pi, buf.head, buf_len(&buf)))) {
281
- parent->klen = buf_len(&buf);
282
- parent->key = malloc(parent->klen + 1);
283
- memcpy((char*)parent->key, buf.head, parent->klen);
284
- *(char*)(parent->key + parent->klen) = '\0';
285
- } else {
286
- parent->key = "";
287
- parent->klen = 0;
288
- }
289
- parent->k1 = *start;
290
- parent->next = NEXT_HASH_COLON;
291
- break;
292
- case NEXT_HASH_VALUE:
293
- pi->hash_set_cstr(pi, parent, buf.head, buf_len(&buf), start);
294
- if (0 != parent->key && 0 < parent->klen && (parent->key < pi->json || pi->cur < parent->key)) {
295
- xfree((char*)parent->key);
296
- parent->key = 0;
297
- }
298
- parent->next = NEXT_HASH_COMMA;
299
- break;
300
- case NEXT_HASH_COMMA:
301
- case NEXT_NONE:
302
- case NEXT_ARRAY_COMMA:
303
- case NEXT_HASH_COLON:
304
- default:
305
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected %s, not a string", oj_stack_next_string(parent->next));
306
- break;
307
- }
283
+ switch (parent->next) {
284
+ case NEXT_ARRAY_NEW:
285
+ case NEXT_ARRAY_ELEMENT:
286
+ pi->array_append_cstr(pi, buf.head, buf_len(&buf), start);
287
+ parent->next = NEXT_ARRAY_COMMA;
288
+ break;
289
+ case NEXT_HASH_NEW:
290
+ case NEXT_HASH_KEY:
291
+ if (Qundef == (parent->key_val = pi->hash_key(pi, buf.head, buf_len(&buf)))) {
292
+ parent->klen = buf_len(&buf);
293
+ parent->key = malloc(parent->klen + 1);
294
+ memcpy((char *)parent->key, buf.head, parent->klen);
295
+ *(char *)(parent->key + parent->klen) = '\0';
296
+ } else {
297
+ parent->key = "";
298
+ parent->klen = 0;
299
+ }
300
+ parent->k1 = *start;
301
+ parent->next = NEXT_HASH_COLON;
302
+ break;
303
+ case NEXT_HASH_VALUE:
304
+ pi->hash_set_cstr(pi, parent, buf.head, buf_len(&buf), start);
305
+ if (0 != parent->key && 0 < parent->klen &&
306
+ (parent->key < pi->json || pi->cur < parent->key)) {
307
+ xfree((char *)parent->key);
308
+ parent->key = 0;
309
+ }
310
+ parent->next = NEXT_HASH_COMMA;
311
+ break;
312
+ case NEXT_HASH_COMMA:
313
+ case NEXT_NONE:
314
+ case NEXT_ARRAY_COMMA:
315
+ case NEXT_HASH_COLON:
316
+ default:
317
+ oj_set_error_at(pi,
318
+ oj_parse_error_class,
319
+ __FILE__,
320
+ __LINE__,
321
+ "expected %s, not a string",
322
+ oj_stack_next_string(parent->next));
323
+ break;
324
+ }
308
325
  }
309
326
  pi->cur = s + 1;
310
327
  buf_cleanup(&buf);
311
328
  }
312
329
 
313
- static void
314
- read_str(ParseInfo pi) {
315
- const char *str = pi->cur;
316
- Val parent = stack_peek(&pi->stack);
330
+ static void read_str(ParseInfo pi) {
331
+ const char *str = pi->cur;
332
+ Val parent = stack_peek(&pi->stack);
317
333
 
318
334
  for (; '"' != *pi->cur; pi->cur++) {
319
- if (pi->end <= pi->cur) {
320
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "quoted string not terminated");
321
- return;
322
- } else if ('\0' == *pi->cur) {
323
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "NULL byte in string");
324
- return;
325
- } else if ('\\' == *pi->cur) {
326
- read_escaped_str(pi, str);
327
- return;
328
- }
335
+ if (pi->end <= pi->cur) {
336
+ oj_set_error_at(pi,
337
+ oj_parse_error_class,
338
+ __FILE__,
339
+ __LINE__,
340
+ "quoted string not terminated");
341
+ return;
342
+ } else if ('\0' == *pi->cur) {
343
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "NULL byte in string");
344
+ return;
345
+ } else if ('\\' == *pi->cur) {
346
+ read_escaped_str(pi, str);
347
+ return;
348
+ }
329
349
  }
330
- if (0 == parent) { // simple add
331
- pi->add_cstr(pi, str, pi->cur - str, str);
350
+ if (0 == parent) { // simple add
351
+ pi->add_cstr(pi, str, pi->cur - str, str);
332
352
  } else {
333
- switch (parent->next) {
334
- case NEXT_ARRAY_NEW:
335
- case NEXT_ARRAY_ELEMENT:
336
- pi->array_append_cstr(pi, str, pi->cur - str, str);
337
- parent->next = NEXT_ARRAY_COMMA;
338
- break;
339
- case NEXT_HASH_NEW:
340
- case NEXT_HASH_KEY:
341
- if (Qundef == (parent->key_val = pi->hash_key(pi, str, pi->cur - str))) {
342
- parent->key = str;
343
- parent->klen = pi->cur - str;
344
- } else {
345
- parent->key = "";
346
- parent->klen = 0;
347
- }
348
- parent->k1 = *str;
349
- parent->next = NEXT_HASH_COLON;
350
- break;
351
- case NEXT_HASH_VALUE:
352
- pi->hash_set_cstr(pi, parent, str, pi->cur - str, str);
353
- if (0 != parent->key && 0 < parent->klen && (parent->key < pi->json || pi->cur < parent->key)) {
354
- xfree((char*)parent->key);
355
- parent->key = 0;
356
- }
357
- parent->next = NEXT_HASH_COMMA;
358
- break;
359
- case NEXT_HASH_COMMA:
360
- case NEXT_NONE:
361
- case NEXT_ARRAY_COMMA:
362
- case NEXT_HASH_COLON:
363
- default:
364
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected %s, not a string", oj_stack_next_string(parent->next));
365
- break;
366
- }
353
+ switch (parent->next) {
354
+ case NEXT_ARRAY_NEW:
355
+ case NEXT_ARRAY_ELEMENT:
356
+ pi->array_append_cstr(pi, str, pi->cur - str, str);
357
+ parent->next = NEXT_ARRAY_COMMA;
358
+ break;
359
+ case NEXT_HASH_NEW:
360
+ case NEXT_HASH_KEY:
361
+ if (Qundef == (parent->key_val = pi->hash_key(pi, str, pi->cur - str))) {
362
+ parent->key = str;
363
+ parent->klen = pi->cur - str;
364
+ } else {
365
+ parent->key = "";
366
+ parent->klen = 0;
367
+ }
368
+ parent->k1 = *str;
369
+ parent->next = NEXT_HASH_COLON;
370
+ break;
371
+ case NEXT_HASH_VALUE:
372
+ pi->hash_set_cstr(pi, parent, str, pi->cur - str, str);
373
+ if (0 != parent->key && 0 < parent->klen &&
374
+ (parent->key < pi->json || pi->cur < parent->key)) {
375
+ xfree((char *)parent->key);
376
+ parent->key = 0;
377
+ }
378
+ parent->next = NEXT_HASH_COMMA;
379
+ break;
380
+ case NEXT_HASH_COMMA:
381
+ case NEXT_NONE:
382
+ case NEXT_ARRAY_COMMA:
383
+ case NEXT_HASH_COLON:
384
+ default:
385
+ oj_set_error_at(pi,
386
+ oj_parse_error_class,
387
+ __FILE__,
388
+ __LINE__,
389
+ "expected %s, not a string",
390
+ oj_stack_next_string(parent->next));
391
+ break;
392
+ }
367
393
  }
368
- pi->cur++; // move past "
394
+ pi->cur++; // move past "
369
395
  }
370
396
 
371
- static void
372
- read_num(ParseInfo pi) {
373
- struct _numInfo ni;
374
- Val parent = stack_peek(&pi->stack);
375
-
376
- ni.str = pi->cur;
377
- ni.i = 0;
378
- ni.num = 0;
379
- ni.div = 1;
380
- ni.di = 0;
381
- ni.len = 0;
382
- ni.exp = 0;
383
- ni.big = 0;
397
+ static void read_num(ParseInfo pi) {
398
+ struct _numInfo ni;
399
+ Val parent = stack_peek(&pi->stack);
400
+
401
+ ni.str = pi->cur;
402
+ ni.i = 0;
403
+ ni.num = 0;
404
+ ni.div = 1;
405
+ ni.di = 0;
406
+ ni.len = 0;
407
+ ni.exp = 0;
408
+ ni.big = 0;
384
409
  ni.infinity = 0;
385
- ni.nan = 0;
386
- ni.neg = 0;
387
- ni.has_exp = 0;
388
- ni.no_big = (FloatDec == pi->options.bigdec_load || FastDec == pi->options.bigdec_load || RubyDec == pi->options.bigdec_load);
389
- ni.bigdec_load = pi->options.bigdec_load;
410
+ ni.nan = 0;
411
+ ni.neg = 0;
412
+ ni.has_exp = 0;
413
+ if (CompatMode == pi->options.mode) {
414
+ ni.no_big = !pi->options.compat_bigdec;
415
+ ni.bigdec_load = pi->options.compat_bigdec;
416
+ } else {
417
+ ni.no_big = (FloatDec == pi->options.bigdec_load || FastDec == pi->options.bigdec_load ||
418
+ RubyDec == pi->options.bigdec_load);
419
+ ni.bigdec_load = pi->options.bigdec_load;
420
+ }
390
421
 
391
422
  if ('-' == *pi->cur) {
392
- pi->cur++;
393
- ni.neg = 1;
423
+ pi->cur++;
424
+ ni.neg = 1;
394
425
  } else if ('+' == *pi->cur) {
395
- if (StrictMode == pi->options.mode) {
396
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
397
- return;
398
- }
399
- pi->cur++;
426
+ if (StrictMode == pi->options.mode) {
427
+ oj_set_error_at(pi,
428
+ oj_parse_error_class,
429
+ __FILE__,
430
+ __LINE__,
431
+ "not a number or other value");
432
+ return;
433
+ }
434
+ pi->cur++;
400
435
  }
401
436
  if ('I' == *pi->cur) {
402
- if (No == pi->options.allow_nan || 0 != strncmp("Infinity", pi->cur, 8)) {
403
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
404
- return;
405
- }
406
- pi->cur += 8;
407
- ni.infinity = 1;
437
+ if (No == pi->options.allow_nan || 0 != strncmp("Infinity", pi->cur, 8)) {
438
+ oj_set_error_at(pi,
439
+ oj_parse_error_class,
440
+ __FILE__,
441
+ __LINE__,
442
+ "not a number or other value");
443
+ return;
444
+ }
445
+ pi->cur += 8;
446
+ ni.infinity = 1;
408
447
  } else if ('N' == *pi->cur || 'n' == *pi->cur) {
409
- if ('a' != pi->cur[1] || ('N' != pi->cur[2] && 'n' != pi->cur[2])) {
410
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
411
- return;
412
- }
413
- pi->cur += 3;
414
- ni.nan = 1;
448
+ if ('a' != pi->cur[1] || ('N' != pi->cur[2] && 'n' != pi->cur[2])) {
449
+ oj_set_error_at(pi,
450
+ oj_parse_error_class,
451
+ __FILE__,
452
+ __LINE__,
453
+ "not a number or other value");
454
+ return;
455
+ }
456
+ pi->cur += 3;
457
+ ni.nan = 1;
415
458
  } else {
416
- int dec_cnt = 0;
417
- bool zero1 = false;
418
-
419
- for (; '0' <= *pi->cur && *pi->cur <= '9'; pi->cur++) {
420
- if (0 == ni.i && '0' == *pi->cur) {
421
- zero1 = true;
422
- }
423
- if (0 < ni.i) {
424
- dec_cnt++;
425
- }
426
- if (!ni.big) {
427
- int d = (*pi->cur - '0');
428
-
429
- if (0 < d) {
430
- if (zero1 && CompatMode == pi->options.mode) {
431
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number");
432
- return;
433
- }
434
- zero1 = false;
435
- }
436
- ni.i = ni.i * 10 + d;
437
- if (INT64_MAX <= ni.i || DEC_MAX < dec_cnt) {
438
- ni.big = 1;
439
- }
440
- }
441
- }
442
- if ('.' == *pi->cur) {
443
- pi->cur++;
444
- // A trailing . is not a valid decimal but if encountered allow it
445
- // except when mimicing the JSON gem or in strict mode.
446
- if (StrictMode == pi->options.mode || CompatMode == pi->options.mode) {
447
- int pos = (int)(pi->cur - ni.str);
448
-
449
- if (1 == pos || (2 == pos && ni.neg)) {
450
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number");
451
- return;
452
- }
453
- if (*pi->cur < '0' || '9' < *pi->cur) {
454
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number");
455
- return;
456
- }
457
- }
458
- for (; '0' <= *pi->cur && *pi->cur <= '9'; pi->cur++) {
459
- int d = (*pi->cur - '0');
460
-
461
- if (0 < ni.num || 0 < ni.i) {
462
- dec_cnt++;
463
- }
464
- if (INT64_MAX <= ni.div) {
465
- if (!ni.no_big) {
466
- ni.big = true;
467
- }
468
- } else {
469
- ni.num = ni.num * 10 + d;
470
- ni.div *= 10;
471
- ni.di++;
472
- if (INT64_MAX <= ni.div || DEC_MAX < dec_cnt) {
473
- if (!ni.no_big) {
474
- ni.big = true;
475
- }
476
- }
477
- }
478
- }
479
- }
480
- if ('e' == *pi->cur || 'E' == *pi->cur) {
481
- int eneg = 0;
482
-
483
- ni.has_exp = 1;
484
- pi->cur++;
485
- if ('-' == *pi->cur) {
486
- pi->cur++;
487
- eneg = 1;
488
- } else if ('+' == *pi->cur) {
489
- pi->cur++;
490
- }
491
- for (; '0' <= *pi->cur && *pi->cur <= '9'; pi->cur++) {
492
- ni.exp = ni.exp * 10 + (*pi->cur - '0');
493
- if (EXP_MAX <= ni.exp) {
494
- ni.big = true;
495
- }
496
- }
497
- if (eneg) {
498
- ni.exp = -ni.exp;
499
- }
500
- }
501
- ni.len = pi->cur - ni.str;
459
+ int dec_cnt = 0;
460
+ bool zero1 = false;
461
+
462
+ for (; '0' <= *pi->cur && *pi->cur <= '9'; pi->cur++) {
463
+ if (0 == ni.i && '0' == *pi->cur) {
464
+ zero1 = true;
465
+ }
466
+ if (0 < ni.i) {
467
+ dec_cnt++;
468
+ }
469
+ if (!ni.big) {
470
+ int d = (*pi->cur - '0');
471
+
472
+ if (0 < d) {
473
+ if (zero1 && CompatMode == pi->options.mode) {
474
+ oj_set_error_at(pi,
475
+ oj_parse_error_class,
476
+ __FILE__,
477
+ __LINE__,
478
+ "not a number");
479
+ return;
480
+ }
481
+ zero1 = false;
482
+ }
483
+ ni.i = ni.i * 10 + d;
484
+ if (INT64_MAX <= ni.i || DEC_MAX < dec_cnt) {
485
+ ni.big = 1;
486
+ }
487
+ }
488
+ }
489
+ if ('.' == *pi->cur) {
490
+ pi->cur++;
491
+ // A trailing . is not a valid decimal but if encountered allow it
492
+ // except when mimicing the JSON gem or in strict mode.
493
+ if (StrictMode == pi->options.mode || CompatMode == pi->options.mode) {
494
+ int pos = (int)(pi->cur - ni.str);
495
+
496
+ if (1 == pos || (2 == pos && ni.neg)) {
497
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number");
498
+ return;
499
+ }
500
+ if (*pi->cur < '0' || '9' < *pi->cur) {
501
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number");
502
+ return;
503
+ }
504
+ }
505
+ for (; '0' <= *pi->cur && *pi->cur <= '9'; pi->cur++) {
506
+ int d = (*pi->cur - '0');
507
+
508
+ if (0 < ni.num || 0 < ni.i) {
509
+ dec_cnt++;
510
+ }
511
+ if (INT64_MAX <= ni.div) {
512
+ if (!ni.no_big) {
513
+ ni.big = true;
514
+ }
515
+ } else {
516
+ ni.num = ni.num * 10 + d;
517
+ ni.div *= 10;
518
+ ni.di++;
519
+ if (INT64_MAX <= ni.div || DEC_MAX < dec_cnt) {
520
+ if (!ni.no_big) {
521
+ ni.big = true;
522
+ }
523
+ }
524
+ }
525
+ }
526
+ }
527
+ if ('e' == *pi->cur || 'E' == *pi->cur) {
528
+ int eneg = 0;
529
+
530
+ ni.has_exp = 1;
531
+ pi->cur++;
532
+ if ('-' == *pi->cur) {
533
+ pi->cur++;
534
+ eneg = 1;
535
+ } else if ('+' == *pi->cur) {
536
+ pi->cur++;
537
+ }
538
+ for (; '0' <= *pi->cur && *pi->cur <= '9'; pi->cur++) {
539
+ ni.exp = ni.exp * 10 + (*pi->cur - '0');
540
+ if (EXP_MAX <= ni.exp) {
541
+ ni.big = true;
542
+ }
543
+ }
544
+ if (eneg) {
545
+ ni.exp = -ni.exp;
546
+ }
547
+ }
548
+ ni.len = pi->cur - ni.str;
502
549
  }
503
550
  // Check for special reserved values for Infinity and NaN.
504
551
  if (ni.big) {
505
- if (0 == strcasecmp(INF_VAL, ni.str)) {
506
- ni.infinity = 1;
507
- } else if (0 == strcasecmp(NINF_VAL, ni.str)) {
508
- ni.infinity = 1;
509
- ni.neg = 1;
510
- } else if (0 == strcasecmp(NAN_VAL, ni.str)) {
511
- ni.nan = 1;
512
- }
552
+ if (0 == strcasecmp(INF_VAL, ni.str)) {
553
+ ni.infinity = 1;
554
+ } else if (0 == strcasecmp(NINF_VAL, ni.str)) {
555
+ ni.infinity = 1;
556
+ ni.neg = 1;
557
+ } else if (0 == strcasecmp(NAN_VAL, ni.str)) {
558
+ ni.nan = 1;
559
+ }
513
560
  }
514
- if (BigDec == pi->options.bigdec_load) {
515
- ni.big = 1;
561
+ if (CompatMode == pi->options.mode) {
562
+ if (pi->options.compat_bigdec) {
563
+ ni.big = 1;
564
+ }
565
+ } else if (BigDec == pi->options.bigdec_load) {
566
+ ni.big = 1;
516
567
  }
517
568
  if (0 == parent) {
518
- pi->add_num(pi, &ni);
569
+ pi->add_num(pi, &ni);
519
570
  } else {
520
- switch (parent->next) {
521
- case NEXT_ARRAY_NEW:
522
- case NEXT_ARRAY_ELEMENT:
523
- pi->array_append_num(pi, &ni);
524
- parent->next = NEXT_ARRAY_COMMA;
525
- break;
526
- case NEXT_HASH_VALUE:
527
- pi->hash_set_num(pi, parent, &ni);
528
- if (0 != parent->key && 0 < parent->klen && (parent->key < pi->json || pi->cur < parent->key)) {
529
- xfree((char*)parent->key);
530
- parent->key = 0;
531
- }
532
- parent->next = NEXT_HASH_COMMA;
533
- break;
534
- default:
535
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected %s", oj_stack_next_string(parent->next));
536
- break;
537
- }
571
+ switch (parent->next) {
572
+ case NEXT_ARRAY_NEW:
573
+ case NEXT_ARRAY_ELEMENT:
574
+ pi->array_append_num(pi, &ni);
575
+ parent->next = NEXT_ARRAY_COMMA;
576
+ break;
577
+ case NEXT_HASH_VALUE:
578
+ pi->hash_set_num(pi, parent, &ni);
579
+ if (0 != parent->key && 0 < parent->klen &&
580
+ (parent->key < pi->json || pi->cur < parent->key)) {
581
+ xfree((char *)parent->key);
582
+ parent->key = 0;
583
+ }
584
+ parent->next = NEXT_HASH_COMMA;
585
+ break;
586
+ default:
587
+ oj_set_error_at(pi,
588
+ oj_parse_error_class,
589
+ __FILE__,
590
+ __LINE__,
591
+ "expected %s",
592
+ oj_stack_next_string(parent->next));
593
+ break;
594
+ }
538
595
  }
539
596
  }
540
597
 
541
- static void
542
- array_start(ParseInfo pi) {
543
- volatile VALUE v = pi->start_array(pi);
598
+ static void array_start(ParseInfo pi) {
599
+ volatile VALUE v = pi->start_array(pi);
544
600
 
545
601
  stack_push(&pi->stack, v, NEXT_ARRAY_NEW);
546
602
  }
547
603
 
548
- static void
549
- array_end(ParseInfo pi) {
550
- Val array = stack_pop(&pi->stack);
604
+ static void array_end(ParseInfo pi) {
605
+ Val array = stack_pop(&pi->stack);
551
606
 
552
607
  if (0 == array) {
553
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected array close");
608
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected array close");
554
609
  } else if (NEXT_ARRAY_COMMA != array->next && NEXT_ARRAY_NEW != array->next) {
555
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected %s, not an array close", oj_stack_next_string(array->next));
610
+ oj_set_error_at(pi,
611
+ oj_parse_error_class,
612
+ __FILE__,
613
+ __LINE__,
614
+ "expected %s, not an array close",
615
+ oj_stack_next_string(array->next));
556
616
  } else {
557
- pi->end_array(pi);
558
- add_value(pi, array->val);
617
+ pi->end_array(pi);
618
+ add_value(pi, array->val);
559
619
  }
560
620
  }
561
621
 
562
- static void
563
- hash_start(ParseInfo pi) {
564
- volatile VALUE v = pi->start_hash(pi);
622
+ static void hash_start(ParseInfo pi) {
623
+ volatile VALUE v = pi->start_hash(pi);
565
624
 
566
625
  stack_push(&pi->stack, v, NEXT_HASH_NEW);
567
626
  }
568
627
 
569
- static void
570
- hash_end(ParseInfo pi) {
571
- volatile Val hash = stack_peek(&pi->stack);
628
+ static void hash_end(ParseInfo pi) {
629
+ volatile Val hash = stack_peek(&pi->stack);
572
630
 
573
631
  // leave hash on stack until just before
574
632
  if (0 == hash) {
575
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected hash close");
633
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected hash close");
576
634
  } else if (NEXT_HASH_COMMA != hash->next && NEXT_HASH_NEW != hash->next) {
577
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected %s, not a hash close", oj_stack_next_string(hash->next));
635
+ oj_set_error_at(pi,
636
+ oj_parse_error_class,
637
+ __FILE__,
638
+ __LINE__,
639
+ "expected %s, not a hash close",
640
+ oj_stack_next_string(hash->next));
578
641
  } else {
579
- pi->end_hash(pi);
580
- stack_pop(&pi->stack);
581
- add_value(pi, hash->val);
642
+ pi->end_hash(pi);
643
+ stack_pop(&pi->stack);
644
+ add_value(pi, hash->val);
582
645
  }
583
646
  }
584
647
 
585
- static void
586
- comma(ParseInfo pi) {
587
- Val parent = stack_peek(&pi->stack);
648
+ static void comma(ParseInfo pi) {
649
+ Val parent = stack_peek(&pi->stack);
588
650
 
589
651
  if (0 == parent) {
590
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected comma");
652
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected comma");
591
653
  } else if (NEXT_ARRAY_COMMA == parent->next) {
592
- parent->next = NEXT_ARRAY_ELEMENT;
654
+ parent->next = NEXT_ARRAY_ELEMENT;
593
655
  } else if (NEXT_HASH_COMMA == parent->next) {
594
- parent->next = NEXT_HASH_KEY;
656
+ parent->next = NEXT_HASH_KEY;
595
657
  } else {
596
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected comma");
658
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected comma");
597
659
  }
598
660
  }
599
661
 
600
- static void
601
- colon(ParseInfo pi) {
602
- Val parent = stack_peek(&pi->stack);
662
+ static void colon(ParseInfo pi) {
663
+ Val parent = stack_peek(&pi->stack);
603
664
 
604
665
  if (0 != parent && NEXT_HASH_COLON == parent->next) {
605
- parent->next = NEXT_HASH_VALUE;
666
+ parent->next = NEXT_HASH_VALUE;
606
667
  } else {
607
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected colon");
668
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected colon");
608
669
  }
609
670
  }
610
671
 
611
- void
612
- oj_parse2(ParseInfo pi) {
613
- int first = 1;
614
- long start = 0;
672
+ void oj_parse2(ParseInfo pi) {
673
+ int first = 1;
674
+ long start = 0;
615
675
 
616
676
  pi->cur = pi->json;
617
677
  err_init(&pi->err);
618
678
  while (1) {
619
- if (0 < pi->max_depth && pi->max_depth <= pi->stack.tail - pi->stack.head - 1) {
620
- VALUE err_clas = oj_get_json_err_class("NestingError");
621
-
622
- oj_set_error_at(pi, err_clas, __FILE__, __LINE__, "Too deeply nested.");
623
- pi->err_class = err_clas;
624
- return;
625
- }
626
- next_non_white(pi);
627
- if (!first && '\0' != *pi->cur) {
628
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected characters after the JSON document");
629
- }
630
-
631
- // If no tokens are consumed (i.e. empty string), throw a parse error
632
- // this is the behavior of JSON.parse in both Ruby and JS.
633
- if (No == pi->options.empty_string && 1 == first && '\0' == *pi->cur) {
634
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected character");
635
- }
636
-
637
- switch (*pi->cur++) {
638
- case '{':
639
- hash_start(pi);
640
- break;
641
- case '}':
642
- hash_end(pi);
643
- break;
644
- case ':':
645
- colon(pi);
646
- break;
647
- case '[':
648
- array_start(pi);
649
- break;
650
- case ']':
651
- array_end(pi);
652
- break;
653
- case ',':
654
- comma(pi);
655
- break;
656
- case '"':
657
- read_str(pi);
658
- break;
659
- //case '+':
660
- case '+':
661
- if (CompatMode == pi->options.mode) {
662
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected character");
663
- return;
664
- }
665
- pi->cur--;
666
- read_num(pi);
667
- break;
668
- case '-':
669
- case '0':
670
- case '1':
671
- case '2':
672
- case '3':
673
- case '4':
674
- case '5':
675
- case '6':
676
- case '7':
677
- case '8':
678
- case '9':
679
- pi->cur--;
680
- read_num(pi);
681
- break;
682
- case 'I':
683
- case 'N':
684
- if (Yes == pi->options.allow_nan) {
685
- pi->cur--;
686
- read_num(pi);
687
- } else {
688
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected character");
689
- }
690
- break;
691
- case 't':
692
- read_true(pi);
693
- break;
694
- case 'f':
695
- read_false(pi);
696
- break;
697
- case 'n':
698
- if ('u' == *pi->cur) {
699
- read_null(pi);
700
- } else {
701
- pi->cur--;
702
- read_num(pi);
703
- }
704
- break;
705
- case '/':
706
- skip_comment(pi);
707
- if (first) {
708
- continue;
709
- }
710
- break;
711
- case '\0':
712
- pi->cur--;
713
- return;
714
- default:
715
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected character");
716
- return;
717
- }
718
- if (err_has(&pi->err)) {
719
- return;
720
- }
721
- if (stack_empty(&pi->stack)) {
722
- if (Qundef != pi->proc) {
723
- VALUE args[3];
724
- long len = (pi->cur - pi->json) - start;
725
-
726
- *args = stack_head_val(&pi->stack);
727
- args[1] = LONG2NUM(start);
728
- args[2] = LONG2NUM(len);
729
-
730
- if (Qnil == pi->proc) {
731
- rb_yield_values2(3, args);
732
- } else {
733
- rb_proc_call_with_block(pi->proc, 3, args, Qnil);
734
- }
735
- } else if (!pi->has_callbacks) {
736
- first = 0;
737
- }
738
- start = pi->cur - pi->json;
739
- }
679
+ if (0 < pi->max_depth && pi->max_depth <= pi->stack.tail - pi->stack.head - 1) {
680
+ VALUE err_clas = oj_get_json_err_class("NestingError");
681
+
682
+ oj_set_error_at(pi, err_clas, __FILE__, __LINE__, "Too deeply nested.");
683
+ pi->err_class = err_clas;
684
+ return;
685
+ }
686
+ next_non_white(pi);
687
+ if (!first && '\0' != *pi->cur) {
688
+ oj_set_error_at(pi,
689
+ oj_parse_error_class,
690
+ __FILE__,
691
+ __LINE__,
692
+ "unexpected characters after the JSON document");
693
+ }
694
+
695
+ // If no tokens are consumed (i.e. empty string), throw a parse error
696
+ // this is the behavior of JSON.parse in both Ruby and JS.
697
+ if (No == pi->options.empty_string && 1 == first && '\0' == *pi->cur) {
698
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected character");
699
+ }
700
+
701
+ switch (*pi->cur++) {
702
+ case '{': hash_start(pi); break;
703
+ case '}': hash_end(pi); break;
704
+ case ':': colon(pi); break;
705
+ case '[': array_start(pi); break;
706
+ case ']': array_end(pi); break;
707
+ case ',': comma(pi); break;
708
+ case '"':
709
+ read_str(pi);
710
+ break;
711
+ // case '+':
712
+ case '+':
713
+ if (CompatMode == pi->options.mode) {
714
+ oj_set_error_at(pi,
715
+ oj_parse_error_class,
716
+ __FILE__,
717
+ __LINE__,
718
+ "unexpected character");
719
+ return;
720
+ }
721
+ pi->cur--;
722
+ read_num(pi);
723
+ break;
724
+ case '-':
725
+ case '0':
726
+ case '1':
727
+ case '2':
728
+ case '3':
729
+ case '4':
730
+ case '5':
731
+ case '6':
732
+ case '7':
733
+ case '8':
734
+ case '9':
735
+ pi->cur--;
736
+ read_num(pi);
737
+ break;
738
+ case 'I':
739
+ case 'N':
740
+ if (Yes == pi->options.allow_nan) {
741
+ pi->cur--;
742
+ read_num(pi);
743
+ } else {
744
+ oj_set_error_at(pi,
745
+ oj_parse_error_class,
746
+ __FILE__,
747
+ __LINE__,
748
+ "unexpected character");
749
+ }
750
+ break;
751
+ case 't': read_true(pi); break;
752
+ case 'f': read_false(pi); break;
753
+ case 'n':
754
+ if ('u' == *pi->cur) {
755
+ read_null(pi);
756
+ } else {
757
+ pi->cur--;
758
+ read_num(pi);
759
+ }
760
+ break;
761
+ case '/':
762
+ skip_comment(pi);
763
+ if (first) {
764
+ continue;
765
+ }
766
+ break;
767
+ case '\0': pi->cur--; return;
768
+ default:
769
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected character");
770
+ return;
771
+ }
772
+ if (err_has(&pi->err)) {
773
+ return;
774
+ }
775
+ if (stack_empty(&pi->stack)) {
776
+ if (Qundef != pi->proc) {
777
+ VALUE args[3];
778
+ long len = (pi->cur - pi->json) - start;
779
+
780
+ *args = stack_head_val(&pi->stack);
781
+ args[1] = LONG2NUM(start);
782
+ args[2] = LONG2NUM(len);
783
+
784
+ if (Qnil == pi->proc) {
785
+ rb_yield_values2(3, args);
786
+ } else {
787
+ rb_proc_call_with_block(pi->proc, 3, args, Qnil);
788
+ }
789
+ } else if (!pi->has_callbacks) {
790
+ first = 0;
791
+ }
792
+ start = pi->cur - pi->json;
793
+ }
740
794
  }
741
795
  }
742
796
 
743
- static VALUE
744
- rescue_big_decimal(VALUE str, VALUE ignore) {
797
+ static VALUE rescue_big_decimal(VALUE str, VALUE ignore) {
745
798
  rb_raise(oj_parse_error_class, "Invalid value for BigDecimal()");
746
799
  return Qnil;
747
800
  }
748
801
 
749
- static VALUE
750
- parse_big_decimal(VALUE str) {
802
+ static VALUE parse_big_decimal(VALUE str) {
751
803
  return rb_funcall(rb_cObject, oj_bigdecimal_id, 1, str);
752
804
  }
753
805
 
754
- static long double exp_plus[] = {
755
- 1.0,
756
- 1.0e1,
757
- 1.0e2,
758
- 1.0e3,
759
- 1.0e4,
760
- 1.0e5,
761
- 1.0e6,
762
- 1.0e7,
763
- 1.0e8,
764
- 1.0e9,
765
- 1.0e10,
766
- 1.0e11,
767
- 1.0e12,
768
- 1.0e13,
769
- 1.0e14,
770
- 1.0e15,
771
- 1.0e16,
772
- 1.0e17,
773
- 1.0e18,
774
- 1.0e19,
775
- 1.0e20,
776
- 1.0e21,
777
- 1.0e22,
778
- 1.0e23,
779
- 1.0e24,
780
- 1.0e25,
781
- 1.0e26,
782
- 1.0e27,
783
- 1.0e28,
784
- 1.0e29,
785
- 1.0e30,
786
- 1.0e31,
787
- 1.0e32,
788
- 1.0e33,
789
- 1.0e34,
790
- 1.0e35,
791
- 1.0e36,
792
- 1.0e37,
793
- 1.0e38,
794
- 1.0e39,
795
- 1.0e40,
796
- 1.0e41,
797
- 1.0e42,
798
- 1.0e43,
799
- 1.0e44,
800
- 1.0e45,
801
- 1.0e46,
802
- 1.0e47,
803
- 1.0e48,
804
- 1.0e49,
806
+ static long double exp_plus[] = {
807
+ 1.0, 1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5, 1.0e6, 1.0e7, 1.0e8, 1.0e9,
808
+ 1.0e10, 1.0e11, 1.0e12, 1.0e13, 1.0e14, 1.0e15, 1.0e16, 1.0e17, 1.0e18, 1.0e19,
809
+ 1.0e20, 1.0e21, 1.0e22, 1.0e23, 1.0e24, 1.0e25, 1.0e26, 1.0e27, 1.0e28, 1.0e29,
810
+ 1.0e30, 1.0e31, 1.0e32, 1.0e33, 1.0e34, 1.0e35, 1.0e36, 1.0e37, 1.0e38, 1.0e39,
811
+ 1.0e40, 1.0e41, 1.0e42, 1.0e43, 1.0e44, 1.0e45, 1.0e46, 1.0e47, 1.0e48, 1.0e49,
805
812
  };
806
813
 
807
814
  VALUE
808
815
  oj_num_as_value(NumInfo ni) {
809
- volatile VALUE rnum = Qnil;
816
+ volatile VALUE rnum = Qnil;
810
817
 
811
818
  if (ni->infinity) {
812
- if (ni->neg) {
813
- rnum = rb_float_new(-OJ_INFINITY);
814
- } else {
815
- rnum = rb_float_new(OJ_INFINITY);
816
- }
819
+ if (ni->neg) {
820
+ rnum = rb_float_new(-OJ_INFINITY);
821
+ } else {
822
+ rnum = rb_float_new(OJ_INFINITY);
823
+ }
817
824
  } else if (ni->nan) {
818
- rnum = rb_float_new(0.0/0.0);
819
- } else if (1 == ni->div && 0 == ni->exp && !ni->has_exp) { // fixnum
820
- if (ni->big) {
821
- if (256 > ni->len) {
822
- char buf[256];
823
-
824
- memcpy(buf, ni->str, ni->len);
825
- buf[ni->len] = '\0';
826
- rnum = rb_cstr_to_inum(buf, 10, 0);
827
- } else {
828
- char *buf = ALLOC_N(char, ni->len + 1);
829
-
830
- memcpy(buf, ni->str, ni->len);
831
- buf[ni->len] = '\0';
832
- rnum = rb_cstr_to_inum(buf, 10, 0);
833
- xfree(buf);
834
- }
835
- } else {
836
- if (ni->neg) {
837
- rnum = rb_ll2inum(-ni->i);
838
- } else {
839
- rnum = rb_ll2inum(ni->i);
840
- }
841
- }
842
- } else { // decimal
843
- if (ni->big) {
844
- volatile VALUE bd = rb_str_new(ni->str, ni->len);
845
-
846
- rnum = rb_rescue2(parse_big_decimal, bd, rescue_big_decimal, bd, rb_eException, 0);
847
- if (ni->no_big) {
848
- rnum = rb_funcall(rnum, rb_intern("to_f"), 0);
849
- }
850
- } else if (FastDec == ni->bigdec_load) {
851
- long double ld = (long double)ni->i * (long double)ni->div + (long double)ni->num;
852
- int x = (int)((int64_t)ni->exp - ni->di);
853
-
854
- if (0 < x) {
855
- if (x < (int)(sizeof(exp_plus) / sizeof(*exp_plus))) {
856
- ld *= exp_plus[x];
857
- } else {
858
- ld *= powl(10.0, x);
859
- }
860
- } else if (x < 0) {
861
- if (-x < (int)(sizeof(exp_plus) / sizeof(*exp_plus))) {
862
- ld /= exp_plus[-x];
863
- } else {
864
- ld /= powl(10.0, -x);
865
- }
866
- }
867
- if (ni->neg) {
868
- ld = -ld;
869
- }
870
- rnum = rb_float_new((double)ld);
871
- } else if (RubyDec == ni->bigdec_load) {
872
- volatile VALUE sv = rb_str_new(ni->str, ni->len);
873
-
874
- rnum = rb_funcall(sv, rb_intern("to_f"), 0);
875
- } else {
876
- char *end;
877
- double d = strtod(ni->str, &end);
878
-
879
- if ((long)ni->len != (long)(end - ni->str)) {
880
- rb_raise(oj_parse_error_class, "Invalid float");
881
- }
882
- rnum = rb_float_new(d);
883
- }
825
+ rnum = rb_float_new(0.0 / 0.0);
826
+ } else if (1 == ni->div && 0 == ni->exp && !ni->has_exp) { // fixnum
827
+ if (ni->big) {
828
+ if (256 > ni->len) {
829
+ char buf[256];
830
+
831
+ memcpy(buf, ni->str, ni->len);
832
+ buf[ni->len] = '\0';
833
+ rnum = rb_cstr_to_inum(buf, 10, 0);
834
+ } else {
835
+ char *buf = ALLOC_N(char, ni->len + 1);
836
+
837
+ memcpy(buf, ni->str, ni->len);
838
+ buf[ni->len] = '\0';
839
+ rnum = rb_cstr_to_inum(buf, 10, 0);
840
+ xfree(buf);
841
+ }
842
+ } else {
843
+ if (ni->neg) {
844
+ rnum = rb_ll2inum(-ni->i);
845
+ } else {
846
+ rnum = rb_ll2inum(ni->i);
847
+ }
848
+ }
849
+ } else { // decimal
850
+ if (ni->big) {
851
+ volatile VALUE bd = rb_str_new(ni->str, ni->len);
852
+
853
+ rnum = rb_rescue2(parse_big_decimal, bd, rescue_big_decimal, bd, rb_eException, 0);
854
+ if (ni->no_big) {
855
+ rnum = rb_funcall(rnum, rb_intern("to_f"), 0);
856
+ }
857
+ } else if (FastDec == ni->bigdec_load) {
858
+ long double ld = (long double)ni->i * (long double)ni->div + (long double)ni->num;
859
+ int x = (int)((int64_t)ni->exp - ni->di);
860
+
861
+ if (0 < x) {
862
+ if (x < (int)(sizeof(exp_plus) / sizeof(*exp_plus))) {
863
+ ld *= exp_plus[x];
864
+ } else {
865
+ ld *= powl(10.0, x);
866
+ }
867
+ } else if (x < 0) {
868
+ if (-x < (int)(sizeof(exp_plus) / sizeof(*exp_plus))) {
869
+ ld /= exp_plus[-x];
870
+ } else {
871
+ ld /= powl(10.0, -x);
872
+ }
873
+ }
874
+ if (ni->neg) {
875
+ ld = -ld;
876
+ }
877
+ rnum = rb_float_new((double)ld);
878
+ } else if (RubyDec == ni->bigdec_load) {
879
+ volatile VALUE sv = rb_str_new(ni->str, ni->len);
880
+
881
+ rnum = rb_funcall(sv, rb_intern("to_f"), 0);
882
+ } else {
883
+ char * end;
884
+ double d = strtod(ni->str, &end);
885
+
886
+ if ((long)ni->len != (long)(end - ni->str)) {
887
+ rb_raise(oj_parse_error_class, "Invalid float");
888
+ }
889
+ rnum = rb_float_new(d);
890
+ }
884
891
  }
885
892
  return rnum;
886
893
  }
887
894
 
888
- void
889
- oj_set_error_at(ParseInfo pi, VALUE err_clas, const char* file, int line, const char *format, ...) {
890
- va_list ap;
891
- char msg[256];
892
- char *p = msg;
893
- char *end = p + sizeof(msg) - 2;
894
- char *start;
895
- Val vp;
895
+ void oj_set_error_at(ParseInfo pi,
896
+ VALUE err_clas,
897
+ const char *file,
898
+ int line,
899
+ const char *format,
900
+ ...) {
901
+ va_list ap;
902
+ char msg[256];
903
+ char * p = msg;
904
+ char * end = p + sizeof(msg) - 2;
905
+ char * start;
906
+ Val vp;
896
907
 
897
908
  va_start(ap, format);
898
909
  p += vsnprintf(msg, sizeof(msg) - 1, format, ap);
899
910
  va_end(ap);
900
911
  pi->err.clas = err_clas;
901
912
  if (p + 3 < end) {
902
- *p++ = ' ';
903
- *p++ = '(';
904
- *p++ = 'a';
905
- *p++ = 'f';
906
- *p++ = 't';
907
- *p++ = 'e';
908
- *p++ = 'r';
909
- *p++ = ' ';
910
- start = p;
911
- for (vp = pi->stack.head; vp < pi->stack.tail; vp++) {
912
- if (end <= p + 1 + vp->klen) {
913
- break;
914
- }
915
- if (NULL != vp->key) {
916
- if (start < p) {
917
- *p++ = '.';
918
- }
919
- memcpy(p, vp->key, vp->klen);
920
- p += vp->klen;
921
- } else {
922
- if (RUBY_T_ARRAY == rb_type(vp->val)) {
923
- if (end <= p + 12) {
924
- break;
925
- }
926
- p += snprintf(p, end - p, "[%ld]", RARRAY_LEN(vp->val));
927
- }
928
- }
929
- }
930
- *p++ = ')';
913
+ *p++ = ' ';
914
+ *p++ = '(';
915
+ *p++ = 'a';
916
+ *p++ = 'f';
917
+ *p++ = 't';
918
+ *p++ = 'e';
919
+ *p++ = 'r';
920
+ *p++ = ' ';
921
+ start = p;
922
+ for (vp = pi->stack.head; vp < pi->stack.tail; vp++) {
923
+ if (end <= p + 1 + vp->klen) {
924
+ break;
925
+ }
926
+ if (NULL != vp->key) {
927
+ if (start < p) {
928
+ *p++ = '.';
929
+ }
930
+ memcpy(p, vp->key, vp->klen);
931
+ p += vp->klen;
932
+ } else {
933
+ if (RUBY_T_ARRAY == rb_type(vp->val)) {
934
+ if (end <= p + 12) {
935
+ break;
936
+ }
937
+ p += snprintf(p, end - p, "[%ld]", RARRAY_LEN(vp->val));
938
+ }
939
+ }
940
+ }
941
+ *p++ = ')';
931
942
  }
932
943
  *p = '\0';
933
944
  if (0 == pi->json) {
934
- oj_err_set(&pi->err, err_clas, "%s at line %d, column %d [%s:%d]", msg, pi->rd.line, pi->rd.col, file, line);
945
+ oj_err_set(&pi->err,
946
+ err_clas,
947
+ "%s at line %d, column %d [%s:%d]",
948
+ msg,
949
+ pi->rd.line,
950
+ pi->rd.col,
951
+ file,
952
+ line);
935
953
  } else {
936
- _oj_err_set_with_location(&pi->err, err_clas, msg, pi->json, pi->cur - 1, file, line);
954
+ _oj_err_set_with_location(&pi->err, err_clas, msg, pi->json, pi->cur - 1, file, line);
937
955
  }
938
956
  }
939
957
 
940
- static VALUE
941
- protect_parse(VALUE pip) {
958
+ static VALUE protect_parse(VALUE pip) {
942
959
  oj_parse2((ParseInfo)pip);
943
960
 
944
961
  return Qnil;
@@ -946,102 +963,102 @@ protect_parse(VALUE pip) {
946
963
 
947
964
  extern int oj_utf8_index;
948
965
 
949
- static void
950
- oj_pi_set_input_str(ParseInfo pi, volatile VALUE *inputp) {
951
- rb_encoding *enc = rb_to_encoding(rb_obj_encoding(*inputp));
966
+ static void oj_pi_set_input_str(ParseInfo pi, volatile VALUE *inputp) {
967
+ rb_encoding *enc = rb_to_encoding(rb_obj_encoding(*inputp));
952
968
 
953
969
  if (rb_utf8_encoding() != enc) {
954
- *inputp = rb_str_conv_enc(*inputp, enc, rb_utf8_encoding());
970
+ *inputp = rb_str_conv_enc(*inputp, enc, rb_utf8_encoding());
955
971
  }
956
- pi->json = rb_string_value_ptr((VALUE*)inputp);
957
- pi->end = pi->json + RSTRING_LEN(*inputp);
972
+ pi->json = rb_string_value_ptr((VALUE *)inputp);
973
+ pi->end = pi->json + RSTRING_LEN(*inputp);
958
974
  }
959
975
 
960
976
  VALUE
961
977
  oj_pi_parse(int argc, VALUE *argv, ParseInfo pi, char *json, size_t len, int yieldOk) {
962
- char *buf = 0;
963
- volatile VALUE input;
964
- volatile VALUE wrapped_stack;
965
- volatile VALUE result = Qnil;
966
- int line = 0;
967
- int free_json = 0;
978
+ char * buf = 0;
979
+ volatile VALUE input;
980
+ volatile VALUE wrapped_stack;
981
+ volatile VALUE result = Qnil;
982
+ int line = 0;
983
+ int free_json = 0;
968
984
 
969
985
  if (argc < 1) {
970
- rb_raise(rb_eArgError, "Wrong number of arguments to parse.");
986
+ rb_raise(rb_eArgError, "Wrong number of arguments to parse.");
971
987
  }
972
988
  input = argv[0];
973
989
  if (2 <= argc) {
974
- if (T_HASH == rb_type(argv[1])) {
975
- oj_parse_options(argv[1], &pi->options);
976
- } else if (3 <= argc && T_HASH == rb_type(argv[2])) {
977
- oj_parse_options(argv[2], &pi->options);
978
- }
990
+ if (T_HASH == rb_type(argv[1])) {
991
+ oj_parse_options(argv[1], &pi->options);
992
+ } else if (3 <= argc && T_HASH == rb_type(argv[2])) {
993
+ oj_parse_options(argv[2], &pi->options);
994
+ }
979
995
  }
980
996
  if (yieldOk && rb_block_given_p()) {
981
- pi->proc = Qnil;
997
+ pi->proc = Qnil;
982
998
  } else {
983
- pi->proc = Qundef;
999
+ pi->proc = Qundef;
984
1000
  }
985
1001
  if (0 != json) {
986
- pi->json = json;
987
- pi->end = json + len;
988
- free_json = 1;
1002
+ pi->json = json;
1003
+ pi->end = json + len;
1004
+ free_json = 1;
989
1005
  } else if (T_STRING == rb_type(input)) {
990
- if (CompatMode == pi->options.mode) {
991
- if (No == pi->options.nilnil && 0 == RSTRING_LEN(input)) {
992
- rb_raise(oj_json_parser_error_class, "An empty string is not a valid JSON string.");
993
- }
994
- }
995
- oj_pi_set_input_str(pi, &input);
1006
+ if (CompatMode == pi->options.mode) {
1007
+ if (No == pi->options.nilnil && 0 == RSTRING_LEN(input)) {
1008
+ rb_raise(oj_json_parser_error_class, "An empty string is not a valid JSON string.");
1009
+ }
1010
+ }
1011
+ oj_pi_set_input_str(pi, &input);
996
1012
  } else if (Qnil == input) {
997
- if (Yes == pi->options.nilnil) {
998
- return Qnil;
999
- } else {
1000
- rb_raise(rb_eTypeError, "Nil is not a valid JSON source.");
1001
- }
1013
+ if (Yes == pi->options.nilnil) {
1014
+ return Qnil;
1015
+ } else {
1016
+ rb_raise(rb_eTypeError, "Nil is not a valid JSON source.");
1017
+ }
1002
1018
  } else {
1003
- VALUE clas = rb_obj_class(input);
1004
- volatile VALUE s;
1019
+ VALUE clas = rb_obj_class(input);
1020
+ volatile VALUE s;
1005
1021
 
1006
- if (oj_stringio_class == clas) {
1007
- s = rb_funcall2(input, oj_string_id, 0, 0);
1008
- oj_pi_set_input_str(pi, &s);
1022
+ if (oj_stringio_class == clas) {
1023
+ s = rb_funcall2(input, oj_string_id, 0, 0);
1024
+ oj_pi_set_input_str(pi, &s);
1009
1025
  #if !IS_WINDOWS
1010
- } else if (rb_cFile == clas && 0 == FIX2INT(rb_funcall(input, oj_pos_id, 0))) {
1011
- int fd = FIX2INT(rb_funcall(input, oj_fileno_id, 0));
1012
- ssize_t cnt;
1013
- size_t len = lseek(fd, 0, SEEK_END);
1014
-
1015
- lseek(fd, 0, SEEK_SET);
1016
- buf = ALLOC_N(char, len + 1);
1017
- pi->json = buf;
1018
- pi->end = buf + len;
1019
- if (0 >= (cnt = read(fd, (char*)pi->json, len)) || cnt != (ssize_t)len) {
1020
- if (0 != buf) {
1021
- xfree(buf);
1022
- }
1023
- rb_raise(rb_eIOError, "failed to read from IO Object.");
1024
- }
1025
- ((char*)pi->json)[len] = '\0';
1026
- /* skip UTF-8 BOM if present */
1027
- if (0xEF == (uint8_t)*pi->json && 0xBB == (uint8_t)pi->json[1] && 0xBF == (uint8_t)pi->json[2]) {
1028
- pi->cur += 3;
1029
- }
1026
+ } else if (rb_cFile == clas && 0 == FIX2INT(rb_funcall(input, oj_pos_id, 0))) {
1027
+ int fd = FIX2INT(rb_funcall(input, oj_fileno_id, 0));
1028
+ ssize_t cnt;
1029
+ size_t len = lseek(fd, 0, SEEK_END);
1030
+
1031
+ lseek(fd, 0, SEEK_SET);
1032
+ buf = ALLOC_N(char, len + 1);
1033
+ pi->json = buf;
1034
+ pi->end = buf + len;
1035
+ if (0 >= (cnt = read(fd, (char *)pi->json, len)) || cnt != (ssize_t)len) {
1036
+ if (0 != buf) {
1037
+ xfree(buf);
1038
+ }
1039
+ rb_raise(rb_eIOError, "failed to read from IO Object.");
1040
+ }
1041
+ ((char *)pi->json)[len] = '\0';
1042
+ /* skip UTF-8 BOM if present */
1043
+ if (0xEF == (uint8_t)*pi->json && 0xBB == (uint8_t)pi->json[1] &&
1044
+ 0xBF == (uint8_t)pi->json[2]) {
1045
+ pi->cur += 3;
1046
+ }
1030
1047
  #endif
1031
- } else if (rb_respond_to(input, oj_read_id)) {
1032
- // use stream parser instead
1033
- return oj_pi_sparse(argc, argv, pi, 0);
1034
- } else {
1035
- rb_raise(rb_eArgError, "parse() expected a String or IO Object.");
1036
- }
1048
+ } else if (rb_respond_to(input, oj_read_id)) {
1049
+ // use stream parser instead
1050
+ return oj_pi_sparse(argc, argv, pi, 0);
1051
+ } else {
1052
+ rb_raise(rb_eArgError, "parse() expected a String or IO Object.");
1053
+ }
1037
1054
  }
1038
1055
  if (Yes == pi->options.circular) {
1039
- pi->circ_array = oj_circ_array_new();
1056
+ pi->circ_array = oj_circ_array_new();
1040
1057
  } else {
1041
- pi->circ_array = 0;
1058
+ pi->circ_array = 0;
1042
1059
  }
1043
1060
  if (No == pi->options.allow_gc) {
1044
- rb_gc_disable();
1061
+ rb_gc_disable();
1045
1062
  }
1046
1063
  // GC can run at any time. When it runs any Object created by C will be
1047
1064
  // freed. We protect against this by wrapping the value stack in a ruby
@@ -1050,116 +1067,116 @@ oj_pi_parse(int argc, VALUE *argv, ParseInfo pi, char *json, size_t len, int yie
1050
1067
  wrapped_stack = oj_stack_init(&pi->stack);
1051
1068
  rb_protect(protect_parse, (VALUE)pi, &line);
1052
1069
  if (Qundef == pi->stack.head->val && !empty_ok(&pi->options)) {
1053
- if (No == pi->options.nilnil || (CompatMode == pi->options.mode && 0 < pi->cur - pi->json)) {
1054
- oj_set_error_at(pi, oj_json_parser_error_class, __FILE__, __LINE__, "Empty input");
1055
- }
1070
+ if (No == pi->options.nilnil ||
1071
+ (CompatMode == pi->options.mode && 0 < pi->cur - pi->json)) {
1072
+ oj_set_error_at(pi, oj_json_parser_error_class, __FILE__, __LINE__, "Empty input");
1073
+ }
1056
1074
  }
1057
- result = stack_head_val(&pi->stack);
1075
+ result = stack_head_val(&pi->stack);
1058
1076
  DATA_PTR(wrapped_stack) = 0;
1059
1077
  if (No == pi->options.allow_gc) {
1060
- rb_gc_enable();
1078
+ rb_gc_enable();
1061
1079
  }
1062
1080
  if (!err_has(&pi->err)) {
1063
- // If the stack is not empty then the JSON terminated early.
1064
- Val v;
1065
- VALUE err_class = oj_parse_error_class;
1066
-
1067
- if (0 != line) {
1068
- VALUE ec = rb_obj_class(rb_errinfo());
1069
-
1070
- if (rb_eArgError != ec && 0 != ec) {
1071
- err_class = ec;
1072
- }
1073
- if (rb_eIOError != ec) {
1074
- goto CLEANUP;
1075
- }
1076
- }
1077
- if (NULL != (v = stack_peek(&pi->stack))) {
1078
- switch (v->next) {
1079
- case NEXT_ARRAY_NEW:
1080
- case NEXT_ARRAY_ELEMENT:
1081
- case NEXT_ARRAY_COMMA:
1082
- oj_set_error_at(pi, err_class, __FILE__, __LINE__, "Array not terminated");
1083
- break;
1084
- case NEXT_HASH_NEW:
1085
- case NEXT_HASH_KEY:
1086
- case NEXT_HASH_COLON:
1087
- case NEXT_HASH_VALUE:
1088
- case NEXT_HASH_COMMA:
1089
- oj_set_error_at(pi, err_class, __FILE__, __LINE__, "Hash/Object not terminated");
1090
- break;
1091
- default:
1092
- oj_set_error_at(pi, err_class, __FILE__, __LINE__, "not terminated");
1093
- }
1094
- }
1081
+ // If the stack is not empty then the JSON terminated early.
1082
+ Val v;
1083
+ VALUE err_class = oj_parse_error_class;
1084
+
1085
+ if (0 != line) {
1086
+ VALUE ec = rb_obj_class(rb_errinfo());
1087
+
1088
+ if (rb_eArgError != ec && 0 != ec) {
1089
+ err_class = ec;
1090
+ }
1091
+ if (rb_eIOError != ec) {
1092
+ goto CLEANUP;
1093
+ }
1094
+ }
1095
+ if (NULL != (v = stack_peek(&pi->stack))) {
1096
+ switch (v->next) {
1097
+ case NEXT_ARRAY_NEW:
1098
+ case NEXT_ARRAY_ELEMENT:
1099
+ case NEXT_ARRAY_COMMA:
1100
+ oj_set_error_at(pi, err_class, __FILE__, __LINE__, "Array not terminated");
1101
+ break;
1102
+ case NEXT_HASH_NEW:
1103
+ case NEXT_HASH_KEY:
1104
+ case NEXT_HASH_COLON:
1105
+ case NEXT_HASH_VALUE:
1106
+ case NEXT_HASH_COMMA:
1107
+ oj_set_error_at(pi, err_class, __FILE__, __LINE__, "Hash/Object not terminated");
1108
+ break;
1109
+ default: oj_set_error_at(pi, err_class, __FILE__, __LINE__, "not terminated");
1110
+ }
1111
+ }
1095
1112
  }
1096
1113
  CLEANUP:
1097
1114
  // proceed with cleanup
1098
1115
  if (0 != pi->circ_array) {
1099
- oj_circ_array_free(pi->circ_array);
1116
+ oj_circ_array_free(pi->circ_array);
1100
1117
  }
1101
1118
  if (0 != buf) {
1102
- xfree(buf);
1119
+ xfree(buf);
1103
1120
  } else if (free_json) {
1104
- xfree(json);
1121
+ xfree(json);
1105
1122
  }
1106
1123
  stack_cleanup(&pi->stack);
1107
1124
  if (pi->str_rx.head != oj_default_options.str_rx.head) {
1108
- oj_rxclass_cleanup(&pi->str_rx);
1125
+ oj_rxclass_cleanup(&pi->str_rx);
1109
1126
  }
1110
1127
  if (err_has(&pi->err)) {
1111
- rb_set_errinfo(Qnil);
1112
- if (Qnil != pi->err_class) {
1113
- pi->err.clas = pi->err_class;
1114
- }
1115
- if (CompatMode == pi->options.mode && Yes != pi->options.safe) {
1116
- // The json gem requires the error message be UTF-8 encoded. In
1117
- // additional the complete JSON source must be returned. There
1118
- // does not seem to be a size limit.
1119
- VALUE msg = oj_encode(rb_str_new2(pi->err.msg));
1120
- VALUE args[1];
1121
-
1122
- if (NULL != pi->json) {
1123
- msg = rb_str_append(msg, oj_encode(rb_str_new2(" in '")));
1124
- msg = rb_str_append(msg, oj_encode(rb_str_new2(pi->json)));
1125
- }
1126
- args[0] = msg;
1127
- if (pi->err.clas == oj_parse_error_class) {
1128
- // The error was an Oj::ParseError so change to a JSON::ParserError.
1129
- pi->err.clas = oj_json_parser_error_class;
1130
- }
1131
- rb_exc_raise(rb_class_new_instance(1, args, pi->err.clas));
1132
- } else {
1133
- oj_err_raise(&pi->err);
1134
- }
1128
+ rb_set_errinfo(Qnil);
1129
+ if (Qnil != pi->err_class) {
1130
+ pi->err.clas = pi->err_class;
1131
+ }
1132
+ if (CompatMode == pi->options.mode && Yes != pi->options.safe) {
1133
+ // The json gem requires the error message be UTF-8 encoded. In
1134
+ // additional the complete JSON source must be returned. There
1135
+ // does not seem to be a size limit.
1136
+ VALUE msg = oj_encode(rb_str_new2(pi->err.msg));
1137
+ VALUE args[1];
1138
+
1139
+ if (NULL != pi->json) {
1140
+ msg = rb_str_append(msg, oj_encode(rb_str_new2(" in '")));
1141
+ msg = rb_str_append(msg, oj_encode(rb_str_new2(pi->json)));
1142
+ }
1143
+ args[0] = msg;
1144
+ if (pi->err.clas == oj_parse_error_class) {
1145
+ // The error was an Oj::ParseError so change to a JSON::ParserError.
1146
+ pi->err.clas = oj_json_parser_error_class;
1147
+ }
1148
+ rb_exc_raise(rb_class_new_instance(1, args, pi->err.clas));
1149
+ } else {
1150
+ oj_err_raise(&pi->err);
1151
+ }
1135
1152
  } else if (0 != line) {
1136
- rb_jump_tag(line);
1153
+ rb_jump_tag(line);
1137
1154
  }
1138
1155
  if (pi->options.quirks_mode == No) {
1139
- switch (rb_type(result)) {
1140
- case T_NIL:
1141
- case T_TRUE:
1142
- case T_FALSE:
1143
- case T_FIXNUM:
1144
- case T_FLOAT:
1145
- case T_CLASS:
1146
- case T_STRING:
1147
- case T_SYMBOL: {
1148
- struct _err err;
1149
-
1150
- if (Qnil == pi->err_class) {
1151
- err.clas = oj_parse_error_class;
1152
- } else {
1153
- err.clas = pi->err_class;
1154
- }
1155
- snprintf(err.msg, sizeof(err.msg), "unexpected non-document value");
1156
- oj_err_raise(&err);
1157
- break;
1158
- }
1159
- default:
1160
- // okay
1161
- break;
1162
- }
1156
+ switch (rb_type(result)) {
1157
+ case T_NIL:
1158
+ case T_TRUE:
1159
+ case T_FALSE:
1160
+ case T_FIXNUM:
1161
+ case T_FLOAT:
1162
+ case T_CLASS:
1163
+ case T_STRING:
1164
+ case T_SYMBOL: {
1165
+ struct _err err;
1166
+
1167
+ if (Qnil == pi->err_class) {
1168
+ err.clas = oj_parse_error_class;
1169
+ } else {
1170
+ err.clas = pi->err_class;
1171
+ }
1172
+ snprintf(err.msg, sizeof(err.msg), "unexpected non-document value");
1173
+ oj_err_raise(&err);
1174
+ break;
1175
+ }
1176
+ default:
1177
+ // okay
1178
+ break;
1179
+ }
1163
1180
  }
1164
1181
  return result;
1165
1182
  }