oj 3.11.0 → 3.16.5

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