oj 3.10.6 → 3.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +6 -1
  3. data/ext/oj/buf.h +36 -68
  4. data/ext/oj/cache8.c +59 -62
  5. data/ext/oj/cache8.h +9 -36
  6. data/ext/oj/circarray.c +36 -42
  7. data/ext/oj/circarray.h +12 -13
  8. data/ext/oj/code.c +172 -179
  9. data/ext/oj/code.h +22 -24
  10. data/ext/oj/compat.c +168 -181
  11. data/ext/oj/custom.c +800 -864
  12. data/ext/oj/dump.c +774 -776
  13. data/ext/oj/dump.h +50 -55
  14. data/ext/oj/dump_compat.c +2 -4
  15. data/ext/oj/dump_leaf.c +118 -162
  16. data/ext/oj/dump_object.c +610 -632
  17. data/ext/oj/dump_strict.c +319 -331
  18. data/ext/oj/encode.h +4 -33
  19. data/ext/oj/err.c +40 -29
  20. data/ext/oj/err.h +25 -44
  21. data/ext/oj/extconf.rb +2 -1
  22. data/ext/oj/fast.c +1054 -1081
  23. data/ext/oj/hash.c +78 -95
  24. data/ext/oj/hash.h +10 -35
  25. data/ext/oj/hash_test.c +451 -472
  26. data/ext/oj/mimic_json.c +415 -402
  27. data/ext/oj/object.c +588 -532
  28. data/ext/oj/odd.c +124 -132
  29. data/ext/oj/odd.h +28 -29
  30. data/ext/oj/oj.c +1178 -905
  31. data/ext/oj/oj.h +289 -298
  32. data/ext/oj/parse.c +946 -870
  33. data/ext/oj/parse.h +81 -79
  34. data/ext/oj/rails.c +837 -842
  35. data/ext/oj/rails.h +8 -11
  36. data/ext/oj/reader.c +139 -147
  37. data/ext/oj/reader.h +68 -84
  38. data/ext/oj/resolve.c +44 -47
  39. data/ext/oj/resolve.h +4 -6
  40. data/ext/oj/rxclass.c +69 -73
  41. data/ext/oj/rxclass.h +13 -14
  42. data/ext/oj/saj.c +453 -484
  43. data/ext/oj/scp.c +88 -113
  44. data/ext/oj/sparse.c +783 -714
  45. data/ext/oj/stream_writer.c +123 -157
  46. data/ext/oj/strict.c +133 -106
  47. data/ext/oj/string_writer.c +199 -247
  48. data/ext/oj/trace.c +34 -41
  49. data/ext/oj/trace.h +15 -15
  50. data/ext/oj/util.c +104 -104
  51. data/ext/oj/util.h +4 -3
  52. data/ext/oj/val_stack.c +48 -76
  53. data/ext/oj/val_stack.h +80 -115
  54. data/ext/oj/wab.c +317 -328
  55. data/lib/oj.rb +0 -8
  56. data/lib/oj/bag.rb +1 -0
  57. data/lib/oj/easy_hash.rb +5 -4
  58. data/lib/oj/mimic.rb +45 -13
  59. data/lib/oj/version.rb +1 -1
  60. data/pages/Modes.md +1 -0
  61. data/pages/Options.md +23 -11
  62. data/test/activerecord/result_test.rb +7 -2
  63. data/test/foo.rb +8 -40
  64. data/test/helper.rb +10 -0
  65. data/test/json_gem/json_common_interface_test.rb +8 -3
  66. data/test/json_gem/json_generator_test.rb +15 -3
  67. data/test/json_gem/test_helper.rb +8 -0
  68. data/test/perf.rb +1 -1
  69. data/test/perf_scp.rb +11 -10
  70. data/test/perf_strict.rb +17 -23
  71. data/test/prec.rb +23 -0
  72. data/test/sample_json.rb +1 -1
  73. data/test/test_compat.rb +16 -3
  74. data/test/test_custom.rb +11 -0
  75. data/test/test_fast.rb +32 -2
  76. data/test/test_generate.rb +21 -0
  77. data/test/test_hash.rb +10 -0
  78. data/test/test_rails.rb +9 -0
  79. data/test/test_scp.rb +1 -1
  80. data/test/test_various.rb +4 -2
  81. metadata +89 -85
data/ext/oj/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
  }