oj 3.10.6 → 3.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +6 -1
  3. data/ext/oj/buf.h +36 -68
  4. data/ext/oj/cache8.c +59 -62
  5. data/ext/oj/cache8.h +9 -36
  6. data/ext/oj/circarray.c +36 -42
  7. data/ext/oj/circarray.h +12 -13
  8. data/ext/oj/code.c +172 -179
  9. data/ext/oj/code.h +22 -24
  10. data/ext/oj/compat.c +176 -181
  11. data/ext/oj/custom.c +800 -864
  12. data/ext/oj/dump.c +774 -776
  13. data/ext/oj/dump.h +50 -55
  14. data/ext/oj/dump_compat.c +2 -4
  15. data/ext/oj/dump_leaf.c +118 -162
  16. data/ext/oj/dump_object.c +610 -632
  17. data/ext/oj/dump_strict.c +319 -331
  18. data/ext/oj/encode.h +4 -33
  19. data/ext/oj/err.c +40 -29
  20. data/ext/oj/err.h +25 -44
  21. data/ext/oj/extconf.rb +2 -1
  22. data/ext/oj/fast.c +1054 -1081
  23. data/ext/oj/hash.c +102 -97
  24. data/ext/oj/hash.h +10 -35
  25. data/ext/oj/hash_test.c +451 -472
  26. data/ext/oj/mimic_json.c +415 -402
  27. data/ext/oj/object.c +588 -532
  28. data/ext/oj/odd.c +124 -132
  29. data/ext/oj/odd.h +28 -29
  30. data/ext/oj/oj.c +1186 -906
  31. data/ext/oj/oj.h +289 -298
  32. data/ext/oj/parse.c +946 -870
  33. data/ext/oj/parse.h +81 -79
  34. data/ext/oj/rails.c +837 -842
  35. data/ext/oj/rails.h +8 -11
  36. data/ext/oj/reader.c +139 -147
  37. data/ext/oj/reader.h +68 -84
  38. data/ext/oj/resolve.c +44 -47
  39. data/ext/oj/resolve.h +4 -6
  40. data/ext/oj/rxclass.c +69 -73
  41. data/ext/oj/rxclass.h +13 -14
  42. data/ext/oj/saj.c +453 -484
  43. data/ext/oj/scp.c +88 -113
  44. data/ext/oj/sparse.c +783 -714
  45. data/ext/oj/stream_writer.c +123 -157
  46. data/ext/oj/strict.c +133 -106
  47. data/ext/oj/string_writer.c +199 -247
  48. data/ext/oj/trace.c +34 -41
  49. data/ext/oj/trace.h +15 -15
  50. data/ext/oj/util.c +104 -104
  51. data/ext/oj/util.h +4 -3
  52. data/ext/oj/val_stack.c +48 -76
  53. data/ext/oj/val_stack.h +80 -115
  54. data/ext/oj/wab.c +321 -325
  55. data/lib/oj.rb +0 -8
  56. data/lib/oj/bag.rb +1 -0
  57. data/lib/oj/easy_hash.rb +5 -4
  58. data/lib/oj/mimic.rb +47 -13
  59. data/lib/oj/version.rb +1 -1
  60. data/pages/Modes.md +1 -0
  61. data/pages/Options.md +23 -11
  62. data/test/activerecord/result_test.rb +7 -2
  63. data/test/foo.rb +8 -40
  64. data/test/helper.rb +10 -0
  65. data/test/json_gem/json_common_interface_test.rb +8 -3
  66. data/test/json_gem/json_generator_test.rb +15 -3
  67. data/test/json_gem/test_helper.rb +8 -0
  68. data/test/perf.rb +1 -1
  69. data/test/perf_scp.rb +11 -10
  70. data/test/perf_strict.rb +17 -23
  71. data/test/prec.rb +23 -0
  72. data/test/sample_json.rb +1 -1
  73. data/test/test_compat.rb +16 -3
  74. data/test/test_custom.rb +11 -0
  75. data/test/test_fast.rb +32 -2
  76. data/test/test_generate.rb +21 -0
  77. data/test/test_hash.rb +10 -0
  78. data/test/test_rails.rb +9 -0
  79. data/test/test_scp.rb +1 -1
  80. data/test/test_various.rb +4 -2
  81. metadata +89 -85
data/ext/oj/object.c CHANGED
@@ -1,414 +1,425 @@
1
- /* object.c
2
- * Copyright (c) 2012, Peter Ohler
3
- * All rights reserved.
4
- */
1
+ // Copyright (c) 2012 Peter Ohler. All rights reserved.
2
+ // Licensed under the MIT License. See LICENSE file in the project root for license details.
5
3
 
6
4
  #include <stdint.h>
7
5
  #include <stdio.h>
8
6
  #include <time.h>
9
7
 
10
- #include "oj.h"
8
+ #include "encode.h"
11
9
  #include "err.h"
12
- #include "parse.h"
13
- #include "resolve.h"
14
10
  #include "hash.h"
15
11
  #include "odd.h"
16
- #include "encode.h"
12
+ #include "oj.h"
13
+ #include "parse.h"
14
+ #include "resolve.h"
17
15
  #include "trace.h"
18
16
  #include "util.h"
19
17
 
20
- inline static long
21
- read_long(const char *str, size_t len) {
22
- long n = 0;
18
+ inline static long read_long(const char *str, size_t len) {
19
+ long n = 0;
23
20
 
24
21
  for (; 0 < len; str++, len--) {
25
- if ('0' <= *str && *str <= '9') {
26
- n = n * 10 + (*str - '0');
27
- } else {
28
- return -1;
29
- }
22
+ if ('0' <= *str && *str <= '9') {
23
+ n = n * 10 + (*str - '0');
24
+ } else {
25
+ return -1;
26
+ }
30
27
  }
31
28
  return n;
32
29
  }
33
30
 
34
- static VALUE
35
- calc_hash_key(ParseInfo pi, Val kval, char k1) {
36
- volatile VALUE rkey;
31
+ static VALUE calc_hash_key(ParseInfo pi, Val kval, char k1) {
32
+ volatile VALUE rkey;
33
+ #if 0
34
+ VALUE *slot;
37
35
 
38
36
  if (':' == k1) {
39
- rkey = rb_str_new(kval->key + 1, kval->klen - 1);
40
- rkey = oj_encode(rkey);
41
- rkey = rb_funcall(rkey, oj_to_sym_id, 0);
37
+ if (Qnil == (rkey = oj_sym_hash_get(kval->key + 1, kval->klen - 1, &slot))) {
38
+ rkey = rb_str_new(kval->key + 1, kval->klen - 1);
39
+ rkey = oj_encode(rkey);
40
+ rkey = rb_str_intern(rkey);
41
+ *slot = rkey;
42
+ rb_gc_register_address(slot);
43
+ }
44
+ } else if (Yes == pi->options.sym_key) {
45
+ if (Qnil == (rkey = oj_sym_hash_get(kval->key, kval->klen, &slot))) {
46
+ rkey = rb_str_new(kval->key, kval->klen);
47
+ rkey = oj_encode(rkey);
48
+ rkey = rb_str_intern(rkey);
49
+ *slot = rkey;
50
+ rb_gc_register_address(slot);
51
+ }
52
+ } else {
53
+ if (Qnil == (rkey = oj_str_hash_get(kval->key, kval->klen, &slot))) {
54
+ rkey = rb_str_new(kval->key, kval->klen);
55
+ rkey = oj_encode(rkey);
56
+ *slot = rkey;
57
+ rb_gc_register_address(slot);
58
+ }
59
+ }
60
+ #else
61
+ if (':' == k1) {
62
+ rkey = rb_str_new(kval->key + 1, kval->klen - 1);
63
+ rkey = oj_encode(rkey);
64
+ rkey = rb_str_intern(rkey);
42
65
  } else {
43
- rkey = rb_str_new(kval->key, kval->klen);
44
- rkey = oj_encode(rkey);
45
- if (Yes == pi->options.sym_key) {
46
- rkey = rb_str_intern(rkey);
47
- }
66
+ rkey = rb_str_new(kval->key, kval->klen);
67
+ rkey = oj_encode(rkey);
68
+ if (Yes == pi->options.sym_key) {
69
+ rkey = rb_str_intern(rkey);
70
+ }
48
71
  }
72
+ #endif
49
73
  return rkey;
50
74
  }
51
75
 
52
- static VALUE
53
- str_to_value(ParseInfo pi, const char *str, size_t len, const char *orig) {
54
- volatile VALUE rstr = Qnil;
76
+ static VALUE str_to_value(ParseInfo pi, const char *str, size_t len, const char *orig) {
77
+ volatile VALUE rstr = Qnil;
55
78
 
56
79
  if (':' == *orig && 0 < len) {
57
- rstr = rb_str_new(str + 1, len - 1);
58
- rstr = oj_encode(rstr);
59
- rstr = rb_funcall(rstr, oj_to_sym_id, 0);
80
+ rstr = rb_str_new(str + 1, len - 1);
81
+ rstr = oj_encode(rstr);
82
+ rstr = rb_funcall(rstr, oj_to_sym_id, 0);
60
83
  } else if (pi->circ_array && 3 <= len && '^' == *orig && 'r' == orig[1]) {
61
- long i = read_long(str + 2, len - 2);
84
+ long i = read_long(str + 2, len - 2);
62
85
 
63
- if (0 > i) {
64
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a valid ID number");
65
- return Qnil;
66
- }
67
- rstr = oj_circ_array_get(pi->circ_array, i);
86
+ if (0 > i) {
87
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a valid ID number");
88
+ return Qnil;
89
+ }
90
+ rstr = oj_circ_array_get(pi->circ_array, i);
68
91
  } else {
69
- rstr = rb_str_new(str, len);
70
- rstr = oj_encode(rstr);
92
+ rstr = rb_str_new(str, len);
93
+ rstr = oj_encode(rstr);
71
94
  }
72
95
  return rstr;
73
96
  }
74
97
 
75
98
  #if (RUBY_VERSION_MAJOR == 1 && RUBY_VERSION_MINOR == 8)
76
- static VALUE
77
- oj_parse_xml_time(const char *str, int len) {
99
+ static VALUE oj_parse_xml_time(const char *str, int len) {
78
100
  return rb_funcall(rb_cTime, oj_parse_id, 1, rb_str_new(str, len));
79
101
  }
80
102
  #else
81
103
  // The much faster approach (4x faster)
82
- static int
83
- parse_num(const char *str, const char *end, int cnt) {
84
- int n = 0;
85
- char c;
86
- int i;
104
+ static int parse_num(const char *str, const char *end, int cnt) {
105
+ int n = 0;
106
+ char c;
107
+ int i;
87
108
 
88
109
  for (i = cnt; 0 < i; i--, str++) {
89
- c = *str;
90
- if (end <= str || c < '0' || '9' < c) {
91
- return -1;
92
- }
93
- n = n * 10 + (c - '0');
110
+ c = *str;
111
+ if (end <= str || c < '0' || '9' < c) {
112
+ return -1;
113
+ }
114
+ n = n * 10 + (c - '0');
94
115
  }
95
116
  return n;
96
117
  }
97
118
 
98
119
  VALUE
99
120
  oj_parse_xml_time(const char *str, int len) {
100
- VALUE args[8];
101
- const char *end = str + len;
102
- int n;
121
+ VALUE args[8];
122
+ const char *end = str + len;
123
+ int n;
103
124
 
104
125
  // year
105
126
  if (0 > (n = parse_num(str, end, 4))) {
106
- return Qnil;
127
+ return Qnil;
107
128
  }
108
129
  str += 4;
109
130
  args[0] = LONG2NUM(n);
110
131
  if ('-' != *str++) {
111
- return Qnil;
132
+ return Qnil;
112
133
  }
113
134
  // month
114
135
  if (0 > (n = parse_num(str, end, 2))) {
115
- return Qnil;
136
+ return Qnil;
116
137
  }
117
138
  str += 2;
118
139
  args[1] = LONG2NUM(n);
119
140
  if ('-' != *str++) {
120
- return Qnil;
141
+ return Qnil;
121
142
  }
122
143
  // day
123
144
  if (0 > (n = parse_num(str, end, 2))) {
124
- return Qnil;
145
+ return Qnil;
125
146
  }
126
147
  str += 2;
127
148
  args[2] = LONG2NUM(n);
128
149
  if ('T' != *str++) {
129
- return Qnil;
150
+ return Qnil;
130
151
  }
131
152
  // hour
132
153
  if (0 > (n = parse_num(str, end, 2))) {
133
- return Qnil;
154
+ return Qnil;
134
155
  }
135
156
  str += 2;
136
157
  args[3] = LONG2NUM(n);
137
158
  if (':' != *str++) {
138
- return Qnil;
159
+ return Qnil;
139
160
  }
140
161
  // minute
141
162
  if (0 > (n = parse_num(str, end, 2))) {
142
- return Qnil;
163
+ return Qnil;
143
164
  }
144
165
  str += 2;
145
166
  args[4] = LONG2NUM(n);
146
167
  if (':' != *str++) {
147
- return Qnil;
168
+ return Qnil;
148
169
  }
149
170
  // second
150
171
  if (0 > (n = parse_num(str, end, 2))) {
151
- return Qnil;
172
+ return Qnil;
152
173
  }
153
174
  str += 2;
154
175
  if (str == end) {
155
- args[5] = LONG2NUM(n);
156
- args[6] = LONG2NUM(0);
176
+ args[5] = LONG2NUM(n);
177
+ args[6] = LONG2NUM(0);
157
178
  } else {
158
- char c = *str++;
159
-
160
- if ('.' == c) {
161
- long long nsec = 0;
162
-
163
- for (; str < end; str++) {
164
- c = *str;
165
- if (c < '0' || '9' < c) {
166
- str++;
167
- break;
168
- }
169
- nsec = nsec * 10 + (c - '0');
170
- }
171
- args[5] = rb_float_new((double)n + ((double)nsec + 0.5) / 1000000000.0);
172
- } else {
173
- args[5] = rb_ll2inum(n);
174
- }
175
- if (end < str) {
176
- args[6] = LONG2NUM(0);
177
- } else {
178
- if ('Z' == c) {
179
- return rb_funcall2(rb_cTime, oj_utc_id, 6, args);
180
- } else if ('+' == c) {
181
- int hr = parse_num(str, end, 2);
182
- int min;
183
-
184
- str += 2;
185
- if (0 > hr || ':' != *str++) {
186
- return Qnil;
187
- }
188
- min = parse_num(str, end, 2);
189
- if (0 > min) {
190
- return Qnil;
191
- }
192
- args[6] = LONG2NUM(hr * 3600 + min * 60);
193
- } else if ('-' == c) {
194
- int hr = parse_num(str, end, 2);
195
- int min;
196
-
197
- str += 2;
198
- if (0 > hr || ':' != *str++) {
199
- return Qnil;
200
- }
201
- min = parse_num(str, end, 2);
202
- if (0 > min) {
203
- return Qnil;
204
- }
205
- args[6] = LONG2NUM(-(hr * 3600 + min * 60));
206
- } else {
207
- args[6] = LONG2NUM(0);
208
- }
209
- }
179
+ char c = *str++;
180
+
181
+ if ('.' == c) {
182
+ long long nsec = 0;
183
+
184
+ for (; str < end; str++) {
185
+ c = *str;
186
+ if (c < '0' || '9' < c) {
187
+ str++;
188
+ break;
189
+ }
190
+ nsec = nsec * 10 + (c - '0');
191
+ }
192
+ args[5] = rb_float_new((double)n + ((double)nsec + 0.5) / 1000000000.0);
193
+ } else {
194
+ args[5] = rb_ll2inum(n);
195
+ }
196
+ if (end < str) {
197
+ args[6] = LONG2NUM(0);
198
+ } else {
199
+ if ('Z' == c) {
200
+ return rb_funcall2(rb_cTime, oj_utc_id, 6, args);
201
+ } else if ('+' == c) {
202
+ int hr = parse_num(str, end, 2);
203
+ int min;
204
+
205
+ str += 2;
206
+ if (0 > hr || ':' != *str++) {
207
+ return Qnil;
208
+ }
209
+ min = parse_num(str, end, 2);
210
+ if (0 > min) {
211
+ return Qnil;
212
+ }
213
+ args[6] = LONG2NUM(hr * 3600 + min * 60);
214
+ } else if ('-' == c) {
215
+ int hr = parse_num(str, end, 2);
216
+ int min;
217
+
218
+ str += 2;
219
+ if (0 > hr || ':' != *str++) {
220
+ return Qnil;
221
+ }
222
+ min = parse_num(str, end, 2);
223
+ if (0 > min) {
224
+ return Qnil;
225
+ }
226
+ args[6] = LONG2NUM(-(hr * 3600 + min * 60));
227
+ } else {
228
+ args[6] = LONG2NUM(0);
229
+ }
230
+ }
210
231
  }
211
232
  return rb_funcall2(rb_cTime, oj_new_id, 7, args);
212
233
  }
213
234
  #endif
214
235
 
215
- static int
216
- hat_cstr(ParseInfo pi, Val parent, Val kval, const char *str, size_t len) {
217
- const char *key = kval->key;
218
- int klen = kval->klen;
236
+ static int hat_cstr(ParseInfo pi, Val parent, Val kval, const char *str, size_t len) {
237
+ const char *key = kval->key;
238
+ int klen = kval->klen;
219
239
 
220
240
  if (2 == klen) {
221
- switch (key[1]) {
222
- case 'o': // object
223
- { // name2class sets an error if the class is not found or created
224
- VALUE clas = oj_name2class(pi, str, len, Yes == pi->options.auto_define, rb_eArgError);
225
-
226
- if (Qundef != clas) {
227
- parent->val = rb_obj_alloc(clas);
228
- }
229
- }
230
- break;
231
- case 'O': // odd object
232
- {
233
- Odd odd = oj_get_oddc(str, len);
234
-
235
- if (0 == odd) {
236
- return 0;
237
- }
238
- parent->val = odd->clas;
239
- parent->odd_args = oj_odd_alloc_args(odd);
240
- }
241
- break;
242
- case 'm':
243
- parent->val = rb_str_new(str + 1, len - 1);
244
- parent->val = oj_encode(parent->val);
245
- parent->val = rb_funcall(parent->val, oj_to_sym_id, 0);
246
- break;
247
- case 's':
248
- parent->val = rb_str_new(str, len);
249
- parent->val = oj_encode(parent->val);
250
- break;
251
- case 'c': // class
252
- {
253
- VALUE clas = oj_name2class(pi, str, len, Yes == pi->options.auto_define, rb_eArgError);
254
-
255
- if (Qundef == clas) {
256
- return 0;
257
- } else {
258
- parent->val = clas;
259
- }
260
- }
261
- break;
262
- case 't': // time
263
- parent->val = oj_parse_xml_time(str, (int)len);
264
- break;
265
- default:
266
- return 0;
267
- break;
268
- }
269
- return 1; // handled
241
+ switch (key[1]) {
242
+ case 'o': // object
243
+ { // name2class sets an error if the class is not found or created
244
+ VALUE clas = oj_name2class(pi, str, len, Yes == pi->options.auto_define, rb_eArgError);
245
+
246
+ if (Qundef != clas) {
247
+ parent->val = rb_obj_alloc(clas);
248
+ }
249
+ } break;
250
+ case 'O': // odd object
251
+ {
252
+ Odd odd = oj_get_oddc(str, len);
253
+
254
+ if (0 == odd) {
255
+ return 0;
256
+ }
257
+ parent->val = odd->clas;
258
+ parent->odd_args = oj_odd_alloc_args(odd);
259
+ } break;
260
+ case 'm':
261
+ parent->val = rb_str_new(str + 1, len - 1);
262
+ parent->val = oj_encode(parent->val);
263
+ parent->val = rb_funcall(parent->val, oj_to_sym_id, 0);
264
+ break;
265
+ case 's':
266
+ parent->val = rb_str_new(str, len);
267
+ parent->val = oj_encode(parent->val);
268
+ break;
269
+ case 'c': // class
270
+ {
271
+ VALUE clas = oj_name2class(pi, str, len, Yes == pi->options.auto_define, rb_eArgError);
272
+
273
+ if (Qundef == clas) {
274
+ return 0;
275
+ } else {
276
+ parent->val = clas;
277
+ }
278
+ } break;
279
+ case 't': // time
280
+ parent->val = oj_parse_xml_time(str, (int)len);
281
+ break;
282
+ default: return 0; break;
283
+ }
284
+ return 1; // handled
270
285
  }
271
286
  return 0;
272
287
  }
273
288
 
274
- static int
275
- hat_num(ParseInfo pi, Val parent, Val kval, NumInfo ni) {
289
+ static int hat_num(ParseInfo pi, Val parent, Val kval, NumInfo ni) {
276
290
  if (2 == kval->klen) {
277
- switch (kval->key[1]) {
278
- case 't': // time as a float
279
- if (0 == ni->div || 9 < ni->di) {
280
- rb_raise(rb_eArgError, "Invalid time decimal representation.");
281
- //parent->val = rb_time_nano_new(0, 0);
282
- } else {
283
- int64_t nsec = ni->num * 1000000000LL / ni->div;
284
-
285
- if (ni->neg) {
286
- ni->i = -ni->i;
287
- if (0 < nsec) {
288
- ni->i--;
289
- nsec = 1000000000LL - nsec;
290
- }
291
- }
292
- if (86400 == ni->exp) { // UTC time
293
- parent->val = rb_time_nano_new(ni->i, (long)nsec);
294
- // Since the ruby C routines alway create local time, the
295
- // offset and then a conversion to UTC keeps makes the time
296
- // match the expected value.
297
- parent->val = rb_funcall2(parent->val, oj_utc_id, 0, 0);
298
- } else if (ni->hasExp) {
299
- int64_t t = (int64_t)(ni->i + ni->exp);
300
- struct _timeInfo ti;
301
- VALUE args[8];
302
-
303
- sec_as_time(t, &ti);
304
- args[0] = LONG2NUM((long)(ti.year));
305
- args[1] = LONG2NUM(ti.mon);
306
- args[2] = LONG2NUM(ti.day);
307
- args[3] = LONG2NUM(ti.hour);
308
- args[4] = LONG2NUM(ti.min);
309
- args[5] = rb_float_new((double)ti.sec + ((double)nsec + 0.5) / 1000000000.0);
310
- args[6] = LONG2NUM(ni->exp);
311
- parent->val = rb_funcall2(rb_cTime, oj_new_id, 7, args);
312
- } else {
313
- parent->val = rb_time_nano_new(ni->i, (long)nsec);
314
- }
315
- }
316
- break;
317
- case 'i': // circular index
318
- if (!ni->infinity && !ni->neg && 1 == ni->div && 0 == ni->exp && 0 != pi->circ_array) { // fixnum
319
- if (Qnil == parent->val) {
320
- parent->val = rb_hash_new();
321
- }
322
- oj_circ_array_set(pi->circ_array, parent->val, ni->i);
323
- } else {
324
- return 0;
325
- }
326
- break;
327
- default:
328
- return 0;
329
- break;
330
- }
331
- return 1; // handled
291
+ switch (kval->key[1]) {
292
+ case 't': // time as a float
293
+ if (0 == ni->div || 9 < ni->di) {
294
+ rb_raise(rb_eArgError, "Invalid time decimal representation.");
295
+ // parent->val = rb_time_nano_new(0, 0);
296
+ } else {
297
+ int64_t nsec = ni->num * 1000000000LL / ni->div;
298
+
299
+ if (ni->neg) {
300
+ ni->i = -ni->i;
301
+ if (0 < nsec) {
302
+ ni->i--;
303
+ nsec = 1000000000LL - nsec;
304
+ }
305
+ }
306
+ if (86400 == ni->exp) { // UTC time
307
+ parent->val = rb_time_nano_new(ni->i, (long)nsec);
308
+ // Since the ruby C routines alway create local time, the
309
+ // offset and then a conversion to UTC keeps makes the time
310
+ // match the expected value.
311
+ parent->val = rb_funcall2(parent->val, oj_utc_id, 0, 0);
312
+ } else if (ni->has_exp) {
313
+ int64_t t = (int64_t)(ni->i + ni->exp);
314
+ struct _timeInfo ti;
315
+ VALUE args[8];
316
+
317
+ sec_as_time(t, &ti);
318
+ args[0] = LONG2NUM((long)(ti.year));
319
+ args[1] = LONG2NUM(ti.mon);
320
+ args[2] = LONG2NUM(ti.day);
321
+ args[3] = LONG2NUM(ti.hour);
322
+ args[4] = LONG2NUM(ti.min);
323
+ args[5] = rb_float_new((double)ti.sec + ((double)nsec + 0.5) / 1000000000.0);
324
+ args[6] = LONG2NUM(ni->exp);
325
+ parent->val = rb_funcall2(rb_cTime, oj_new_id, 7, args);
326
+ } else {
327
+ parent->val = rb_time_nano_new(ni->i, (long)nsec);
328
+ }
329
+ }
330
+ break;
331
+ case 'i': // circular index
332
+ if (!ni->infinity && !ni->neg && 1 == ni->div && 0 == ni->exp &&
333
+ 0 != pi->circ_array) { // fixnum
334
+ if (Qnil == parent->val) {
335
+ parent->val = rb_hash_new();
336
+ }
337
+ oj_circ_array_set(pi->circ_array, parent->val, ni->i);
338
+ } else {
339
+ return 0;
340
+ }
341
+ break;
342
+ default: return 0; break;
343
+ }
344
+ return 1; // handled
332
345
  }
333
346
  return 0;
334
347
  }
335
348
 
336
- static int
337
- hat_value(ParseInfo pi, Val parent, const char *key, size_t klen, volatile VALUE value) {
349
+ static int hat_value(ParseInfo pi, Val parent, const char *key, size_t klen, volatile VALUE value) {
338
350
  if (T_ARRAY == rb_type(value)) {
339
- int len = (int)RARRAY_LEN(value);
340
-
341
- if (2 == klen && 'u' == key[1]) {
342
- volatile VALUE sc;
343
- volatile VALUE e1;
344
- int slen;
345
-
346
- if (0 == len) {
347
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "Invalid struct data");
348
- return 1;
349
- }
350
- e1 = *RARRAY_PTR(value);
351
- // check for anonymous Struct
352
- if (T_ARRAY == rb_type(e1)) {
353
- VALUE args[1024];
354
- volatile VALUE rstr;
355
- int i, cnt = (int)RARRAY_LEN(e1);
356
-
357
- for (i = 0; i < cnt; i++) {
358
- rstr = rb_ary_entry(e1, i);
359
- args[i] = rb_funcall(rstr, oj_to_sym_id, 0);
360
- }
361
- sc = rb_funcall2(rb_cStruct, oj_new_id, cnt, args);
362
- } else {
363
- // If struct is not defined then we let this fail and raise an exception.
364
- sc = oj_name2struct(pi, *RARRAY_PTR(value), rb_eArgError);
365
- }
351
+ int len = (int)RARRAY_LEN(value);
352
+
353
+ if (2 == klen && 'u' == key[1]) {
354
+ volatile VALUE sc;
355
+ volatile VALUE e1;
356
+ int slen;
357
+
358
+ if (0 == len) {
359
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "Invalid struct data");
360
+ return 1;
361
+ }
362
+ e1 = *RARRAY_PTR(value);
363
+ // check for anonymous Struct
364
+ if (T_ARRAY == rb_type(e1)) {
365
+ VALUE args[1024];
366
+ volatile VALUE rstr;
367
+ int i, cnt = (int)RARRAY_LEN(e1);
368
+
369
+ for (i = 0; i < cnt; i++) {
370
+ rstr = rb_ary_entry(e1, i);
371
+ args[i] = rb_funcall(rstr, oj_to_sym_id, 0);
372
+ }
373
+ sc = rb_funcall2(rb_cStruct, oj_new_id, cnt, args);
374
+ } else {
375
+ // If struct is not defined then we let this fail and raise an exception.
376
+ sc = oj_name2struct(pi, *RARRAY_PTR(value), rb_eArgError);
377
+ }
366
378
  // Create a properly initialized struct instance without calling the initialize method.
367
379
  parent->val = rb_obj_alloc(sc);
368
380
  // If the JSON array has more entries than the struct class allows, we record an error.
369
381
  #ifdef RSTRUCT_LEN
370
382
  #if RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
371
- slen = (int)NUM2LONG(RSTRUCT_LEN(parent->val));
372
- #else // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
373
- slen = (int)RSTRUCT_LEN(parent->val);
374
- #endif // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
383
+ slen = (int)NUM2LONG(RSTRUCT_LEN(parent->val));
384
+ #else // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
385
+ slen = (int)RSTRUCT_LEN(parent->val);
386
+ #endif // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
375
387
  #else
376
- slen = FIX2INT(rb_funcall2(parent->val, oj_length_id, 0, 0));
388
+ slen = FIX2INT(rb_funcall2(parent->val, oj_length_id, 0, 0));
377
389
  #endif
378
390
  // MRI >= 1.9
379
391
  if (len - 1 > slen) {
380
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "Invalid struct data");
392
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "Invalid struct data");
381
393
  } else {
382
- int i;
394
+ int i;
383
395
 
384
- for (i = 0; i < len - 1; i++) {
385
- rb_struct_aset(parent->val, INT2FIX(i), RARRAY_PTR(value)[i + 1]);
386
- }
396
+ for (i = 0; i < len - 1; i++) {
397
+ rb_struct_aset(parent->val, INT2FIX(i), RARRAY_PTR(value)[i + 1]);
398
+ }
387
399
  }
388
- return 1;
389
- } else if (3 <= klen && '#' == key[1]) {
390
- volatile VALUE *a;
400
+ return 1;
401
+ } else if (3 <= klen && '#' == key[1]) {
402
+ volatile VALUE *a;
391
403
 
392
- if (2 != len) {
393
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid hash pair");
394
- return 1;
395
- }
396
- parent->val = rb_hash_new();
397
- a = RARRAY_PTR(value);
398
- rb_hash_aset(parent->val, *a, a[1]);
404
+ if (2 != len) {
405
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid hash pair");
406
+ return 1;
407
+ }
408
+ parent->val = rb_hash_new();
409
+ a = RARRAY_PTR(value);
410
+ rb_hash_aset(parent->val, *a, a[1]);
399
411
 
400
- return 1;
401
- }
412
+ return 1;
413
+ }
402
414
  }
403
415
  return 0;
404
416
  }
405
417
 
406
- void
407
- oj_set_obj_ivar(Val parent, Val kval, VALUE value) {
408
- const char *key = kval->key;
409
- int klen = kval->klen;
410
- ID var_id;
411
- ID *slot;
418
+ void oj_set_obj_ivar(Val parent, Val kval, VALUE value) {
419
+ const char *key = kval->key;
420
+ int klen = kval->klen;
421
+ ID var_id;
422
+ ID * slot;
412
423
 
413
424
  #ifdef HAVE_PTHREAD_MUTEX_INIT
414
425
  pthread_mutex_lock(&oj_cache_mutex);
@@ -416,33 +427,33 @@ oj_set_obj_ivar(Val parent, Val kval, VALUE value) {
416
427
  rb_mutex_lock(oj_cache_mutex);
417
428
  #endif
418
429
  if (0 == (var_id = oj_attr_hash_get(key, klen, &slot))) {
419
- char attr[256];
420
-
421
- if ((int)sizeof(attr) <= klen + 2) {
422
- char *buf = ALLOC_N(char, klen + 2);
423
-
424
- if ('~' == *key) {
425
- strncpy(buf, key + 1, klen - 1);
426
- buf[klen - 1] = '\0';
427
- } else {
428
- *buf = '@';
429
- strncpy(buf + 1, key, klen);
430
- buf[klen + 1] = '\0';
431
- }
432
- var_id = rb_intern(buf);
433
- xfree(buf);
434
- } else {
435
- if ('~' == *key) {
436
- strncpy(attr, key + 1, klen - 1);
437
- attr[klen - 1] = '\0';
438
- } else {
439
- *attr = '@';
440
- strncpy(attr + 1, key, klen);
441
- attr[klen + 1] = '\0';
442
- }
443
- var_id = rb_intern(attr);
444
- }
445
- *slot = var_id;
430
+ char attr[256];
431
+
432
+ if ((int)sizeof(attr) <= klen + 2) {
433
+ char *buf = ALLOC_N(char, klen + 2);
434
+
435
+ if ('~' == *key) {
436
+ strncpy(buf, key + 1, klen - 1);
437
+ buf[klen - 1] = '\0';
438
+ } else {
439
+ *buf = '@';
440
+ strncpy(buf + 1, key, klen);
441
+ buf[klen + 1] = '\0';
442
+ }
443
+ var_id = rb_intern(buf);
444
+ xfree(buf);
445
+ } else {
446
+ if ('~' == *key) {
447
+ strncpy(attr, key + 1, klen - 1);
448
+ attr[klen - 1] = '\0';
449
+ } else {
450
+ *attr = '@';
451
+ strncpy(attr + 1, key, klen);
452
+ attr[klen + 1] = '\0';
453
+ }
454
+ var_id = rb_intern(attr);
455
+ }
456
+ *slot = var_id;
446
457
  }
447
458
  #ifdef HAVE_PTHREAD_MUTEX_INIT
448
459
  pthread_mutex_unlock(&oj_cache_mutex);
@@ -452,324 +463,369 @@ oj_set_obj_ivar(Val parent, Val kval, VALUE value) {
452
463
  rb_ivar_set(parent->val, var_id, value);
453
464
  }
454
465
 
455
- static void
456
- hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, const char *orig) {
457
- const char *key = kval->key;
458
- int klen = kval->klen;
459
- Val parent = stack_peek(&pi->stack);
460
- volatile VALUE rval = Qnil;
466
+ static void hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, const char *orig) {
467
+ const char * key = kval->key;
468
+ int klen = kval->klen;
469
+ Val parent = stack_peek(&pi->stack);
470
+ volatile VALUE rval = Qnil;
461
471
 
462
- WHICH_TYPE:
472
+ WHICH_TYPE:
463
473
  switch (rb_type(parent->val)) {
464
474
  case T_NIL:
465
- parent->odd_args = NULL; // make sure it is NULL in case not odd
466
- if ('^' != *key || !hat_cstr(pi, parent, kval, str, len)) {
467
- parent->val = rb_hash_new();
468
- goto WHICH_TYPE;
469
- }
470
- break;
475
+ parent->odd_args = NULL; // make sure it is NULL in case not odd
476
+ if ('^' != *key || !hat_cstr(pi, parent, kval, str, len)) {
477
+ parent->val = rb_hash_new();
478
+ goto WHICH_TYPE;
479
+ }
480
+ break;
471
481
  case T_HASH:
472
- rb_hash_aset(parent->val, calc_hash_key(pi, kval, parent->k1), str_to_value(pi, str, len, orig));
473
- break;
482
+ rb_hash_aset(parent->val,
483
+ calc_hash_key(pi, kval, parent->k1),
484
+ str_to_value(pi, str, len, orig));
485
+ break;
474
486
  case T_STRING:
475
- rval = str_to_value(pi, str, len, orig);
476
- if (4 == klen && 's' == *key && 'e' == key[1] && 'l' == key[2] && 'f' == key[3]) {
477
- rb_funcall(parent->val, oj_replace_id, 1, rval);
478
- } else {
479
- oj_set_obj_ivar(parent, kval, rval);
480
- }
481
- break;
487
+ rval = str_to_value(pi, str, len, orig);
488
+ if (4 == klen && 's' == *key && 'e' == key[1] && 'l' == key[2] && 'f' == key[3]) {
489
+ rb_funcall(parent->val, oj_replace_id, 1, rval);
490
+ } else {
491
+ oj_set_obj_ivar(parent, kval, rval);
492
+ }
493
+ break;
482
494
  case T_OBJECT:
483
- rval = str_to_value(pi, str, len, orig);
484
- oj_set_obj_ivar(parent, kval, rval);
485
- break;
495
+ rval = str_to_value(pi, str, len, orig);
496
+ oj_set_obj_ivar(parent, kval, rval);
497
+ break;
486
498
  case T_CLASS:
487
- if (NULL == parent->odd_args) {
488
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "%s is not an odd class", rb_class2name(rb_obj_class(parent->val)));
489
- return;
490
- } else {
491
- rval = str_to_value(pi, str, len, orig);
492
- if (0 != oj_odd_set_arg(parent->odd_args, kval->key, kval->klen, rval)) {
493
- char buf[256];
494
-
495
- if ((int)sizeof(buf) - 1 <= klen) {
496
- klen = sizeof(buf) - 2;
497
- }
498
- memcpy(buf, key, klen);
499
- buf[klen] = '\0';
500
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "%s is not an attribute of %s", buf, rb_class2name(rb_obj_class(parent->val)));
501
- }
502
- }
503
- break;
499
+ if (NULL == parent->odd_args) {
500
+ oj_set_error_at(pi,
501
+ oj_parse_error_class,
502
+ __FILE__,
503
+ __LINE__,
504
+ "%s is not an odd class",
505
+ rb_class2name(rb_obj_class(parent->val)));
506
+ return;
507
+ } else {
508
+ rval = str_to_value(pi, str, len, orig);
509
+ if (0 != oj_odd_set_arg(parent->odd_args, kval->key, kval->klen, rval)) {
510
+ char buf[256];
511
+
512
+ if ((int)sizeof(buf) - 1 <= klen) {
513
+ klen = sizeof(buf) - 2;
514
+ }
515
+ memcpy(buf, key, klen);
516
+ buf[klen] = '\0';
517
+ oj_set_error_at(pi,
518
+ oj_parse_error_class,
519
+ __FILE__,
520
+ __LINE__,
521
+ "%s is not an attribute of %s",
522
+ buf,
523
+ rb_class2name(rb_obj_class(parent->val)));
524
+ }
525
+ }
526
+ break;
504
527
  default:
505
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "can not add attributes to a %s", rb_class2name(rb_obj_class(parent->val)));
506
- return;
528
+ oj_set_error_at(pi,
529
+ oj_parse_error_class,
530
+ __FILE__,
531
+ __LINE__,
532
+ "can not add attributes to a %s",
533
+ rb_class2name(rb_obj_class(parent->val)));
534
+ return;
507
535
  }
508
536
  if (Yes == pi->options.trace) {
509
- oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rval);
537
+ oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rval);
510
538
  }
511
539
  }
512
540
 
513
- static void
514
- hash_set_num(ParseInfo pi, Val kval, NumInfo ni) {
515
- const char *key = kval->key;
516
- int klen = kval->klen;
517
- Val parent = stack_peek(&pi->stack);
518
- volatile VALUE rval = Qnil;
541
+ static void hash_set_num(ParseInfo pi, Val kval, NumInfo ni) {
542
+ const char * key = kval->key;
543
+ int klen = kval->klen;
544
+ Val parent = stack_peek(&pi->stack);
545
+ volatile VALUE rval = Qnil;
519
546
 
520
- WHICH_TYPE:
547
+ WHICH_TYPE:
521
548
  switch (rb_type(parent->val)) {
522
549
  case T_NIL:
523
- parent->odd_args = NULL; // make sure it is NULL in case not odd
524
- if ('^' != *key || !hat_num(pi, parent, kval, ni)) {
525
- parent->val = rb_hash_new();
526
- goto WHICH_TYPE;
527
- }
528
- break;
550
+ parent->odd_args = NULL; // make sure it is NULL in case not odd
551
+ if ('^' != *key || !hat_num(pi, parent, kval, ni)) {
552
+ parent->val = rb_hash_new();
553
+ goto WHICH_TYPE;
554
+ }
555
+ break;
529
556
  case T_HASH:
530
- rval = oj_num_as_value(ni);
531
- rb_hash_aset(parent->val, calc_hash_key(pi, kval, parent->k1), rval);
532
- break;
557
+ rval = oj_num_as_value(ni);
558
+ rb_hash_aset(parent->val, calc_hash_key(pi, kval, parent->k1), rval);
559
+ break;
533
560
  case T_OBJECT:
534
- if (2 == klen && '^' == *key && 'i' == key[1] &&
535
- !ni->infinity && !ni->neg && 1 == ni->div && 0 == ni->exp && 0 != pi->circ_array) { // fixnum
536
- oj_circ_array_set(pi->circ_array, parent->val, ni->i);
537
- } else {
538
- rval = oj_num_as_value(ni);
539
- oj_set_obj_ivar(parent, kval, rval);
540
- }
541
- break;
561
+ if (2 == klen && '^' == *key && 'i' == key[1] && !ni->infinity && !ni->neg &&
562
+ 1 == ni->div && 0 == ni->exp && 0 != pi->circ_array) { // fixnum
563
+ oj_circ_array_set(pi->circ_array, parent->val, ni->i);
564
+ } else {
565
+ rval = oj_num_as_value(ni);
566
+ oj_set_obj_ivar(parent, kval, rval);
567
+ }
568
+ break;
542
569
  case T_CLASS:
543
- if (NULL == parent->odd_args) {
544
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "%s is not an odd class", rb_class2name(rb_obj_class(parent->val)));
545
- return;
546
- } else {
547
- rval = oj_num_as_value(ni);
548
- if (0 != oj_odd_set_arg(parent->odd_args, key, klen, rval)) {
549
- char buf[256];
550
-
551
- if ((int)sizeof(buf) - 1 <= klen) {
552
- klen = sizeof(buf) - 2;
553
- }
554
- memcpy(buf, key, klen);
555
- buf[klen] = '\0';
556
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "%s is not an attribute of %s", buf, rb_class2name(rb_obj_class(parent->val)));
557
- }
558
- }
559
- break;
570
+ if (NULL == parent->odd_args) {
571
+ oj_set_error_at(pi,
572
+ oj_parse_error_class,
573
+ __FILE__,
574
+ __LINE__,
575
+ "%s is not an odd class",
576
+ rb_class2name(rb_obj_class(parent->val)));
577
+ return;
578
+ } else {
579
+ rval = oj_num_as_value(ni);
580
+ if (0 != oj_odd_set_arg(parent->odd_args, key, klen, rval)) {
581
+ char buf[256];
582
+
583
+ if ((int)sizeof(buf) - 1 <= klen) {
584
+ klen = sizeof(buf) - 2;
585
+ }
586
+ memcpy(buf, key, klen);
587
+ buf[klen] = '\0';
588
+ oj_set_error_at(pi,
589
+ oj_parse_error_class,
590
+ __FILE__,
591
+ __LINE__,
592
+ "%s is not an attribute of %s",
593
+ buf,
594
+ rb_class2name(rb_obj_class(parent->val)));
595
+ }
596
+ }
597
+ break;
560
598
  default:
561
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "can not add attributes to a %s", rb_class2name(rb_obj_class(parent->val)));
562
- return;
599
+ oj_set_error_at(pi,
600
+ oj_parse_error_class,
601
+ __FILE__,
602
+ __LINE__,
603
+ "can not add attributes to a %s",
604
+ rb_class2name(rb_obj_class(parent->val)));
605
+ return;
563
606
  }
564
607
  if (Yes == pi->options.trace) {
565
- oj_trace_parse_call("add_number", pi, __FILE__, __LINE__, rval);
608
+ oj_trace_parse_call("add_number", pi, __FILE__, __LINE__, rval);
566
609
  }
567
610
  }
568
611
 
569
- static void
570
- hash_set_value(ParseInfo pi, Val kval, VALUE value) {
571
- const char *key = kval->key;
572
- int klen = kval->klen;
573
- Val parent = stack_peek(&pi->stack);
612
+ static void hash_set_value(ParseInfo pi, Val kval, VALUE value) {
613
+ const char *key = kval->key;
614
+ int klen = kval->klen;
615
+ Val parent = stack_peek(&pi->stack);
574
616
 
575
- WHICH_TYPE:
617
+ WHICH_TYPE:
576
618
  switch (rb_type(parent->val)) {
577
619
  case T_NIL:
578
- parent->odd_args = NULL; // make sure it is NULL in case not odd
579
- if ('^' != *key || !hat_value(pi, parent, key, klen, value)) {
580
- parent->val = rb_hash_new();
581
- goto WHICH_TYPE;
582
- }
583
- break;
620
+ parent->odd_args = NULL; // make sure it is NULL in case not odd
621
+ if ('^' != *key || !hat_value(pi, parent, key, klen, value)) {
622
+ parent->val = rb_hash_new();
623
+ goto WHICH_TYPE;
624
+ }
625
+ break;
584
626
  case T_HASH:
585
- if (rb_cHash != rb_obj_class(parent->val)) {
586
- if (4 == klen && 's' == *key && 'e' == key[1] && 'l' == key[2] && 'f' == key[3]) {
587
- rb_funcall(parent->val, oj_replace_id, 1, value);
588
- } else {
589
- oj_set_obj_ivar(parent, kval, value);
590
- }
591
- } else {
592
- if (3 <= klen && '^' == *key && '#' == key[1] && T_ARRAY == rb_type(value)) {
593
- long len = RARRAY_LEN(value);
594
- volatile VALUE *a = RARRAY_PTR(value);
595
-
596
- if (2 != len) {
597
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid hash pair");
598
- return;
599
- }
600
- rb_hash_aset(parent->val, *a, a[1]);
601
- } else {
602
- rb_hash_aset(parent->val, calc_hash_key(pi, kval, parent->k1), value);
603
- }
604
- }
605
- break;
627
+ if (rb_cHash != rb_obj_class(parent->val)) {
628
+ if (4 == klen && 's' == *key && 'e' == key[1] && 'l' == key[2] && 'f' == key[3]) {
629
+ rb_funcall(parent->val, oj_replace_id, 1, value);
630
+ } else {
631
+ oj_set_obj_ivar(parent, kval, value);
632
+ }
633
+ } else {
634
+ if (3 <= klen && '^' == *key && '#' == key[1] && T_ARRAY == rb_type(value)) {
635
+ long len = RARRAY_LEN(value);
636
+ volatile VALUE *a = RARRAY_PTR(value);
637
+
638
+ if (2 != len) {
639
+ oj_set_error_at(pi,
640
+ oj_parse_error_class,
641
+ __FILE__,
642
+ __LINE__,
643
+ "invalid hash pair");
644
+ return;
645
+ }
646
+ rb_hash_aset(parent->val, *a, a[1]);
647
+ } else {
648
+ rb_hash_aset(parent->val, calc_hash_key(pi, kval, parent->k1), value);
649
+ }
650
+ }
651
+ break;
606
652
  case T_ARRAY:
607
- if (4 == klen && 's' == *key && 'e' == key[1] && 'l' == key[2] && 'f' == key[3]) {
608
- rb_funcall(parent->val, oj_replace_id, 1, value);
609
- } else {
610
- oj_set_obj_ivar(parent, kval, value);
611
- }
612
- break;
613
- case T_STRING: // for subclassed strings
614
- case T_OBJECT:
615
- oj_set_obj_ivar(parent, kval, value);
616
- break;
653
+ if (4 == klen && 's' == *key && 'e' == key[1] && 'l' == key[2] && 'f' == key[3]) {
654
+ rb_funcall(parent->val, oj_replace_id, 1, value);
655
+ } else {
656
+ oj_set_obj_ivar(parent, kval, value);
657
+ }
658
+ break;
659
+ case T_STRING: // for subclassed strings
660
+ case T_OBJECT: oj_set_obj_ivar(parent, kval, value); break;
617
661
  case T_MODULE:
618
662
  case T_CLASS:
619
- if (NULL == parent->odd_args) {
620
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "%s is not an odd class", rb_class2name(rb_obj_class(parent->val)));
621
- return;
622
- } else if (0 != oj_odd_set_arg(parent->odd_args, key, klen, value)) {
623
- char buf[256];
624
-
625
- if ((int)sizeof(buf) - 1 <= klen) {
626
- klen = sizeof(buf) - 2;
627
- }
628
- memcpy(buf, key, klen);
629
- buf[klen] = '\0';
630
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "%s is not an attribute of %s", buf, rb_class2name(rb_obj_class(parent->val)));
631
- }
632
- break;
663
+ if (NULL == parent->odd_args) {
664
+ oj_set_error_at(pi,
665
+ oj_parse_error_class,
666
+ __FILE__,
667
+ __LINE__,
668
+ "%s is not an odd class",
669
+ rb_class2name(rb_obj_class(parent->val)));
670
+ return;
671
+ } else if (0 != oj_odd_set_arg(parent->odd_args, key, klen, value)) {
672
+ char buf[256];
673
+
674
+ if ((int)sizeof(buf) - 1 <= klen) {
675
+ klen = sizeof(buf) - 2;
676
+ }
677
+ memcpy(buf, key, klen);
678
+ buf[klen] = '\0';
679
+ oj_set_error_at(pi,
680
+ oj_parse_error_class,
681
+ __FILE__,
682
+ __LINE__,
683
+ "%s is not an attribute of %s",
684
+ buf,
685
+ rb_class2name(rb_obj_class(parent->val)));
686
+ }
687
+ break;
633
688
  default:
634
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "can not add attributes to a %s", rb_class2name(rb_obj_class(parent->val)));
635
- return;
689
+ oj_set_error_at(pi,
690
+ oj_parse_error_class,
691
+ __FILE__,
692
+ __LINE__,
693
+ "can not add attributes to a %s",
694
+ rb_class2name(rb_obj_class(parent->val)));
695
+ return;
636
696
  }
637
697
  if (Yes == pi->options.trace) {
638
- oj_trace_parse_call("add_value", pi, __FILE__, __LINE__, value);
698
+ oj_trace_parse_call("add_value", pi, __FILE__, __LINE__, value);
639
699
  }
640
700
  }
641
701
 
642
- static VALUE
643
- start_hash(ParseInfo pi) {
702
+ static VALUE start_hash(ParseInfo pi) {
644
703
  if (Yes == pi->options.trace) {
645
- oj_trace_parse_in("start_hash", pi, __FILE__, __LINE__);
704
+ oj_trace_parse_in("start_hash", pi, __FILE__, __LINE__);
646
705
  }
647
706
  return Qnil;
648
707
  }
649
708
 
650
- static void
651
- end_hash(ParseInfo pi) {
652
- Val parent = stack_peek(&pi->stack);
709
+ static void end_hash(ParseInfo pi) {
710
+ Val parent = stack_peek(&pi->stack);
653
711
 
654
712
  if (Qnil == parent->val) {
655
- parent->val = rb_hash_new();
713
+ parent->val = rb_hash_new();
656
714
  } else if (NULL != parent->odd_args) {
657
- OddArgs oa = parent->odd_args;
715
+ OddArgs oa = parent->odd_args;
658
716
 
659
- parent->val = rb_funcall2(oa->odd->create_obj, oa->odd->create_op, oa->odd->attr_cnt, oa->args);
660
- oj_odd_free(oa);
661
- parent->odd_args = NULL;
717
+ parent->val = rb_funcall2(oa->odd->create_obj,
718
+ oa->odd->create_op,
719
+ oa->odd->attr_cnt,
720
+ oa->args);
721
+ oj_odd_free(oa);
722
+ parent->odd_args = NULL;
662
723
  }
663
724
  if (Yes == pi->options.trace) {
664
- oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
725
+ oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
665
726
  }
666
727
  }
667
728
 
668
- static void
669
- array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
670
- volatile VALUE rval = Qnil;
729
+ static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
730
+ volatile VALUE rval = Qnil;
671
731
 
672
732
  // orig lets us know whether the string was ^r1 or \u005er1
673
- if (3 <= len && 0 != pi->circ_array && '^' == orig[0] && 0 == rb_array_len(stack_peek(&pi->stack)->val)) {
674
- if ('i' == str[1]) {
675
- long i = read_long(str + 2, len - 2);
676
-
677
- if (0 < i) {
678
- oj_circ_array_set(pi->circ_array, stack_peek(&pi->stack)->val, i);
679
- return;
680
- }
681
- } else if ('r' == str[1]) {
682
- long i = read_long(str + 2, len - 2);
683
-
684
- if (0 < i) {
685
- rb_ary_push(stack_peek(&pi->stack)->val, oj_circ_array_get(pi->circ_array, i));
686
- return;
687
- }
733
+ if (3 <= len && 0 != pi->circ_array && '^' == orig[0] &&
734
+ 0 == rb_array_len(stack_peek(&pi->stack)->val)) {
735
+ if ('i' == str[1]) {
736
+ long i = read_long(str + 2, len - 2);
737
+
738
+ if (0 < i) {
739
+ oj_circ_array_set(pi->circ_array, stack_peek(&pi->stack)->val, i);
740
+ return;
741
+ }
742
+ } else if ('r' == str[1]) {
743
+ long i = read_long(str + 2, len - 2);
688
744
 
689
- }
745
+ if (0 < i) {
746
+ rb_ary_push(stack_peek(&pi->stack)->val, oj_circ_array_get(pi->circ_array, i));
747
+ return;
748
+ }
749
+ }
690
750
  }
691
751
  rval = str_to_value(pi, str, len, orig);
692
752
  rb_ary_push(stack_peek(&pi->stack)->val, rval);
693
753
  if (Yes == pi->options.trace) {
694
- oj_trace_parse_call("append_string", pi, __FILE__, __LINE__, rval);
754
+ oj_trace_parse_call("append_string", pi, __FILE__, __LINE__, rval);
695
755
  }
696
756
  }
697
757
 
698
- static void
699
- array_append_num(ParseInfo pi, NumInfo ni) {
700
- volatile VALUE rval = oj_num_as_value(ni);
758
+ static void array_append_num(ParseInfo pi, NumInfo ni) {
759
+ volatile VALUE rval = oj_num_as_value(ni);
701
760
 
702
761
  rb_ary_push(stack_peek(&pi->stack)->val, rval);
703
762
  if (Yes == pi->options.trace) {
704
- oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, rval);
763
+ oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, rval);
705
764
  }
706
765
  }
707
766
 
708
- static void
709
- add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
767
+ static void add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
710
768
  pi->stack.head->val = str_to_value(pi, str, len, orig);
711
769
  if (Yes == pi->options.trace) {
712
- oj_trace_parse_call("add_string", pi, __FILE__, __LINE__, pi->stack.head->val);
770
+ oj_trace_parse_call("add_string", pi, __FILE__, __LINE__, pi->stack.head->val);
713
771
  }
714
772
  }
715
773
 
716
- static void
717
- add_num(ParseInfo pi, NumInfo ni) {
774
+ static void add_num(ParseInfo pi, NumInfo ni) {
718
775
  pi->stack.head->val = oj_num_as_value(ni);
719
776
  if (Yes == pi->options.trace) {
720
- oj_trace_parse_call("add_num", pi, __FILE__, __LINE__, pi->stack.head->val);
777
+ oj_trace_parse_call("add_num", pi, __FILE__, __LINE__, pi->stack.head->val);
721
778
  }
722
779
  }
723
780
 
724
- void
725
- oj_set_object_callbacks(ParseInfo pi) {
781
+ void oj_set_object_callbacks(ParseInfo pi) {
726
782
  oj_set_strict_callbacks(pi);
727
- pi->end_hash = end_hash;
728
- pi->start_hash = start_hash;
729
- pi->hash_set_cstr = hash_set_cstr;
730
- pi->hash_set_num = hash_set_num;
731
- pi->hash_set_value = hash_set_value;
732
- pi->add_cstr = add_cstr;
733
- pi->add_num = add_num;
783
+ pi->end_hash = end_hash;
784
+ pi->start_hash = start_hash;
785
+ pi->hash_set_cstr = hash_set_cstr;
786
+ pi->hash_set_num = hash_set_num;
787
+ pi->hash_set_value = hash_set_value;
788
+ pi->add_cstr = add_cstr;
789
+ pi->add_num = add_num;
734
790
  pi->array_append_cstr = array_append_cstr;
735
- pi->array_append_num = array_append_num;
791
+ pi->array_append_num = array_append_num;
736
792
  }
737
793
 
738
794
  VALUE
739
795
  oj_object_parse(int argc, VALUE *argv, VALUE self) {
740
- struct _parseInfo pi;
796
+ struct _parseInfo pi;
741
797
 
742
798
  parse_info_init(&pi);
743
- pi.options = oj_default_options;
744
- pi.handler = Qnil;
799
+ pi.options = oj_default_options;
800
+ pi.handler = Qnil;
745
801
  pi.err_class = Qnil;
746
802
  oj_set_object_callbacks(&pi);
747
803
 
748
804
  if (T_STRING == rb_type(*argv)) {
749
- return oj_pi_parse(argc, argv, &pi, 0, 0, 1);
805
+ return oj_pi_parse(argc, argv, &pi, 0, 0, 1);
750
806
  } else {
751
- return oj_pi_sparse(argc, argv, &pi, 0);
807
+ return oj_pi_sparse(argc, argv, &pi, 0);
752
808
  }
753
809
  }
754
810
 
755
811
  VALUE
756
812
  oj_object_parse_cstr(int argc, VALUE *argv, char *json, size_t len) {
757
- struct _parseInfo pi;
813
+ struct _parseInfo pi;
758
814
 
759
815
  parse_info_init(&pi);
760
- pi.options = oj_default_options;
761
- pi.handler = Qnil;
816
+ pi.options = oj_default_options;
817
+ pi.handler = Qnil;
762
818
  pi.err_class = Qnil;
763
819
  oj_set_strict_callbacks(&pi);
764
- pi.end_hash = end_hash;
765
- pi.start_hash = start_hash;
766
- pi.hash_set_cstr = hash_set_cstr;
767
- pi.hash_set_num = hash_set_num;
768
- pi.hash_set_value = hash_set_value;
769
- pi.add_cstr = add_cstr;
770
- pi.add_num = add_num;
820
+ pi.end_hash = end_hash;
821
+ pi.start_hash = start_hash;
822
+ pi.hash_set_cstr = hash_set_cstr;
823
+ pi.hash_set_num = hash_set_num;
824
+ pi.hash_set_value = hash_set_value;
825
+ pi.add_cstr = add_cstr;
826
+ pi.add_num = add_num;
771
827
  pi.array_append_cstr = array_append_cstr;
772
- pi.array_append_num = array_append_num;
828
+ pi.array_append_num = array_append_num;
773
829
 
774
830
  return oj_pi_parse(argc, argv, &pi, json, len, 1);
775
831
  }