oj 3.11.5 → 3.16.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (168) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1421 -0
  3. data/README.md +19 -5
  4. data/RELEASE_NOTES.md +61 -0
  5. data/ext/oj/buf.h +20 -6
  6. data/ext/oj/cache.c +329 -0
  7. data/ext/oj/cache.h +22 -0
  8. data/ext/oj/cache8.c +10 -9
  9. data/ext/oj/circarray.c +8 -6
  10. data/ext/oj/circarray.h +2 -2
  11. data/ext/oj/code.c +19 -33
  12. data/ext/oj/code.h +2 -2
  13. data/ext/oj/compat.c +27 -77
  14. data/ext/oj/custom.c +86 -179
  15. data/ext/oj/debug.c +126 -0
  16. data/ext/oj/dump.c +256 -249
  17. data/ext/oj/dump.h +26 -12
  18. data/ext/oj/dump_compat.c +565 -642
  19. data/ext/oj/dump_leaf.c +17 -63
  20. data/ext/oj/dump_object.c +65 -187
  21. data/ext/oj/dump_strict.c +27 -51
  22. data/ext/oj/encoder.c +43 -0
  23. data/ext/oj/err.c +2 -13
  24. data/ext/oj/err.h +24 -8
  25. data/ext/oj/extconf.rb +21 -6
  26. data/ext/oj/fast.c +149 -149
  27. data/ext/oj/intern.c +313 -0
  28. data/ext/oj/intern.h +22 -0
  29. data/ext/oj/mem.c +318 -0
  30. data/ext/oj/mem.h +53 -0
  31. data/ext/oj/mimic_json.c +121 -106
  32. data/ext/oj/object.c +85 -162
  33. data/ext/oj/odd.c +89 -67
  34. data/ext/oj/odd.h +15 -15
  35. data/ext/oj/oj.c +542 -411
  36. data/ext/oj/oj.h +99 -73
  37. data/ext/oj/parse.c +175 -187
  38. data/ext/oj/parse.h +26 -24
  39. data/ext/oj/parser.c +1600 -0
  40. data/ext/oj/parser.h +101 -0
  41. data/ext/oj/rails.c +112 -159
  42. data/ext/oj/rails.h +1 -1
  43. data/ext/oj/reader.c +11 -14
  44. data/ext/oj/reader.h +4 -2
  45. data/ext/oj/resolve.c +5 -24
  46. data/ext/oj/rxclass.c +7 -6
  47. data/ext/oj/rxclass.h +1 -1
  48. data/ext/oj/saj.c +22 -33
  49. data/ext/oj/saj2.c +584 -0
  50. data/ext/oj/saj2.h +23 -0
  51. data/ext/oj/scp.c +5 -28
  52. data/ext/oj/sparse.c +28 -72
  53. data/ext/oj/stream_writer.c +50 -40
  54. data/ext/oj/strict.c +56 -61
  55. data/ext/oj/string_writer.c +72 -39
  56. data/ext/oj/trace.h +31 -4
  57. data/ext/oj/usual.c +1218 -0
  58. data/ext/oj/usual.h +69 -0
  59. data/ext/oj/util.h +1 -1
  60. data/ext/oj/val_stack.c +14 -3
  61. data/ext/oj/val_stack.h +8 -7
  62. data/ext/oj/validate.c +46 -0
  63. data/ext/oj/wab.c +63 -88
  64. data/lib/oj/active_support_helper.rb +1 -3
  65. data/lib/oj/bag.rb +7 -1
  66. data/lib/oj/easy_hash.rb +4 -5
  67. data/lib/oj/error.rb +1 -2
  68. data/lib/oj/json.rb +162 -150
  69. data/lib/oj/mimic.rb +9 -7
  70. data/lib/oj/saj.rb +20 -6
  71. data/lib/oj/schandler.rb +5 -4
  72. data/lib/oj/state.rb +12 -8
  73. data/lib/oj/version.rb +1 -2
  74. data/lib/oj.rb +2 -0
  75. data/pages/Compatibility.md +1 -1
  76. data/pages/InstallOptions.md +20 -0
  77. data/pages/JsonGem.md +15 -0
  78. data/pages/Modes.md +8 -3
  79. data/pages/Options.md +43 -5
  80. data/pages/Parser.md +309 -0
  81. data/pages/Rails.md +14 -2
  82. data/test/_test_active.rb +8 -9
  83. data/test/_test_active_mimic.rb +7 -8
  84. data/test/_test_mimic_rails.rb +17 -20
  85. data/test/activerecord/result_test.rb +5 -6
  86. data/test/activesupport6/encoding_test.rb +63 -28
  87. data/test/{activesupport5 → activesupport7}/abstract_unit.rb +16 -12
  88. data/test/{activesupport5 → activesupport7}/decoding_test.rb +2 -10
  89. data/test/{activesupport5 → activesupport7}/encoding_test.rb +86 -50
  90. data/test/{activesupport5 → activesupport7}/encoding_test_cases.rb +6 -0
  91. data/test/{activesupport5 → activesupport7}/time_zone_test_helpers.rb +8 -0
  92. data/test/files.rb +15 -15
  93. data/test/foo.rb +16 -45
  94. data/test/helper.rb +11 -8
  95. data/test/isolated/shared.rb +3 -2
  96. data/test/json_gem/json_addition_test.rb +2 -2
  97. data/test/json_gem/json_common_interface_test.rb +8 -6
  98. data/test/json_gem/json_encoding_test.rb +0 -0
  99. data/test/json_gem/json_ext_parser_test.rb +1 -0
  100. data/test/json_gem/json_fixtures_test.rb +3 -2
  101. data/test/json_gem/json_generator_test.rb +56 -38
  102. data/test/json_gem/json_generic_object_test.rb +11 -11
  103. data/test/json_gem/json_parser_test.rb +54 -47
  104. data/test/json_gem/json_string_matching_test.rb +9 -9
  105. data/test/json_gem/test_helper.rb +7 -3
  106. data/test/mem.rb +34 -0
  107. data/test/perf.rb +22 -27
  108. data/test/perf_compat.rb +31 -33
  109. data/test/perf_dump.rb +50 -0
  110. data/test/perf_fast.rb +80 -82
  111. data/test/perf_file.rb +27 -29
  112. data/test/perf_object.rb +65 -69
  113. data/test/perf_once.rb +59 -0
  114. data/test/perf_parser.rb +183 -0
  115. data/test/perf_saj.rb +46 -54
  116. data/test/perf_scp.rb +58 -69
  117. data/test/perf_simple.rb +41 -39
  118. data/test/perf_strict.rb +74 -82
  119. data/test/perf_wab.rb +67 -69
  120. data/test/prec.rb +5 -5
  121. data/test/sample/change.rb +0 -1
  122. data/test/sample/dir.rb +0 -1
  123. data/test/sample/doc.rb +0 -1
  124. data/test/sample/file.rb +0 -1
  125. data/test/sample/group.rb +0 -1
  126. data/test/sample/hasprops.rb +0 -1
  127. data/test/sample/layer.rb +0 -1
  128. data/test/sample/rect.rb +0 -1
  129. data/test/sample/shape.rb +0 -1
  130. data/test/sample/text.rb +0 -1
  131. data/test/sample.rb +16 -16
  132. data/test/sample_json.rb +8 -8
  133. data/test/test_compat.rb +95 -43
  134. data/test/test_custom.rb +73 -51
  135. data/test/test_debian.rb +7 -10
  136. data/test/test_fast.rb +135 -79
  137. data/test/test_file.rb +41 -30
  138. data/test/test_gc.rb +16 -5
  139. data/test/test_generate.rb +5 -5
  140. data/test/test_hash.rb +5 -5
  141. data/test/test_integer_range.rb +9 -9
  142. data/test/test_null.rb +20 -20
  143. data/test/test_object.rb +99 -96
  144. data/test/test_parser.rb +11 -0
  145. data/test/test_parser_debug.rb +27 -0
  146. data/test/test_parser_saj.rb +337 -0
  147. data/test/test_parser_usual.rb +251 -0
  148. data/test/test_rails.rb +2 -2
  149. data/test/test_saj.rb +10 -8
  150. data/test/test_scp.rb +37 -39
  151. data/test/test_strict.rb +40 -32
  152. data/test/test_various.rb +165 -84
  153. data/test/test_wab.rb +48 -44
  154. data/test/test_writer.rb +47 -47
  155. data/test/tests.rb +13 -5
  156. data/test/tests_mimic.rb +12 -3
  157. data/test/tests_mimic_addition.rb +12 -3
  158. metadata +74 -128
  159. data/ext/oj/hash.c +0 -131
  160. data/ext/oj/hash.h +0 -19
  161. data/ext/oj/hash_test.c +0 -491
  162. data/test/activesupport4/decoding_test.rb +0 -108
  163. data/test/activesupport4/encoding_test.rb +0 -531
  164. data/test/activesupport4/test_helper.rb +0 -41
  165. data/test/activesupport5/test_helper.rb +0 -72
  166. data/test/bar.rb +0 -35
  167. data/test/baz.rb +0 -16
  168. data/test/zoo.rb +0 -13
data/ext/oj/object.c CHANGED
@@ -7,7 +7,7 @@
7
7
 
8
8
  #include "encode.h"
9
9
  #include "err.h"
10
- #include "hash.h"
10
+ #include "intern.h"
11
11
  #include "odd.h"
12
12
  #include "oj.h"
13
13
  #include "parse.h"
@@ -32,16 +32,17 @@ static VALUE calc_hash_key(ParseInfo pi, Val kval, char k1) {
32
32
  volatile VALUE rkey;
33
33
 
34
34
  if (':' == k1) {
35
- rkey = rb_str_new(kval->key + 1, kval->klen - 1);
36
- rkey = oj_encode(rkey);
37
- rkey = rb_funcall(rkey, oj_to_sym_id, 0);
38
- } else {
39
- rkey = rb_str_new(kval->key, kval->klen);
40
- rkey = oj_encode(rkey);
41
- if (Yes == pi->options.sym_key) {
42
- rkey = rb_str_intern(rkey);
43
- }
35
+ return ID2SYM(rb_intern3(kval->key + 1, kval->klen - 1, oj_utf8_encoding));
36
+ }
37
+ if (Yes == pi->options.sym_key) {
38
+ return ID2SYM(rb_intern3(kval->key, kval->klen, oj_utf8_encoding));
44
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
45
46
  return rkey;
46
47
  }
47
48
 
@@ -49,9 +50,7 @@ static VALUE str_to_value(ParseInfo pi, const char *str, size_t len, const char
49
50
  volatile VALUE rstr = Qnil;
50
51
 
51
52
  if (':' == *orig && 0 < len) {
52
- rstr = rb_str_new(str + 1, len - 1);
53
- rstr = oj_encode(rstr);
54
- rstr = rb_funcall(rstr, oj_to_sym_id, 0);
53
+ rstr = ID2SYM(rb_intern3(str + 1, len - 1, oj_utf8_encoding));
55
54
  } else if (pi->circ_array && 3 <= len && '^' == *orig && 'r' == orig[1]) {
56
55
  long i = read_long(str + 2, len - 2);
57
56
 
@@ -61,17 +60,11 @@ static VALUE str_to_value(ParseInfo pi, const char *str, size_t len, const char
61
60
  }
62
61
  rstr = oj_circ_array_get(pi->circ_array, i);
63
62
  } else {
64
- rstr = rb_str_new(str, len);
65
- rstr = oj_encode(rstr);
63
+ rstr = rb_utf8_str_new(str, len);
66
64
  }
67
65
  return rstr;
68
66
  }
69
67
 
70
- #if (RUBY_VERSION_MAJOR == 1 && RUBY_VERSION_MINOR == 8)
71
- static VALUE oj_parse_xml_time(const char *str, int len) {
72
- return rb_funcall(rb_cTime, oj_parse_id, 1, rb_str_new(str, len));
73
- }
74
- #else
75
68
  // The much faster approach (4x faster)
76
69
  static int parse_num(const char *str, const char *end, int cnt) {
77
70
  int n = 0;
@@ -90,8 +83,9 @@ static int parse_num(const char *str, const char *end, int cnt) {
90
83
 
91
84
  VALUE
92
85
  oj_parse_xml_time(const char *str, int len) {
93
- VALUE args[8];
94
- const char *end = str + len;
86
+ VALUE args[7];
87
+ const char *end = str + len;
88
+ const char *orig = str;
95
89
  int n;
96
90
 
97
91
  // year
@@ -151,7 +145,9 @@ oj_parse_xml_time(const char *str, int len) {
151
145
  char c = *str++;
152
146
 
153
147
  if ('.' == c) {
154
- long long nsec = 0;
148
+ unsigned long long num = 0;
149
+ unsigned long long den = 1;
150
+ const unsigned long long last_den_limit = ULLONG_MAX / 10;
155
151
 
156
152
  for (; str < end; str++) {
157
153
  c = *str;
@@ -159,9 +155,14 @@ oj_parse_xml_time(const char *str, int len) {
159
155
  str++;
160
156
  break;
161
157
  }
162
- nsec = nsec * 10 + (c - '0');
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;
163
164
  }
164
- args[5] = rb_float_new((double)n + ((double)nsec + 0.5) / 1000000000.0);
165
+ args[5] = rb_funcall(INT2NUM(n), oj_plus_id, 1, rb_rational_new(ULL2NUM(num), ULL2NUM(den)));
165
166
  } else {
166
167
  args[5] = rb_ll2inum(n);
167
168
  }
@@ -203,7 +204,6 @@ oj_parse_xml_time(const char *str, int len) {
203
204
  }
204
205
  return rb_funcall2(rb_cTime, oj_new_id, 7, args);
205
206
  }
206
- #endif
207
207
 
208
208
  static int hat_cstr(ParseInfo pi, Val parent, Val kval, const char *str, size_t len) {
209
209
  const char *key = kval->key;
@@ -228,16 +228,10 @@ static int hat_cstr(ParseInfo pi, Val parent, Val kval, const char *str, size_t
228
228
  }
229
229
  parent->val = odd->clas;
230
230
  parent->odd_args = oj_odd_alloc_args(odd);
231
- } break;
232
- case 'm':
233
- parent->val = rb_str_new(str + 1, len - 1);
234
- parent->val = oj_encode(parent->val);
235
- parent->val = rb_funcall(parent->val, oj_to_sym_id, 0);
236
- break;
237
- case 's':
238
- parent->val = rb_str_new(str, len);
239
- parent->val = oj_encode(parent->val);
240
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;
241
235
  case 'c': // class
242
236
  {
243
237
  VALUE clas = oj_name2class(pi, str, len, Yes == pi->options.auto_define, rb_eArgError);
@@ -247,7 +241,8 @@ static int hat_cstr(ParseInfo pi, Val parent, Val kval, const char *str, size_t
247
241
  } else {
248
242
  parent->val = clas;
249
243
  }
250
- } break;
244
+ break;
245
+ }
251
246
  case 't': // time
252
247
  parent->val = oj_parse_xml_time(str, (int)len);
253
248
  break;
@@ -277,32 +272,22 @@ static int hat_num(ParseInfo pi, Val parent, Val kval, NumInfo ni) {
277
272
  }
278
273
  if (86400 == ni->exp) { // UTC time
279
274
  parent->val = rb_time_nano_new(ni->i, (long)nsec);
280
- // Since the ruby C routines alway create local time, the
275
+ // Since the ruby C routines always create local time, the
281
276
  // offset and then a conversion to UTC keeps makes the time
282
277
  // match the expected value.
283
278
  parent->val = rb_funcall2(parent->val, oj_utc_id, 0, 0);
284
279
  } else if (ni->has_exp) {
285
- int64_t t = (int64_t)(ni->i + ni->exp);
286
- struct _timeInfo ti;
287
- VALUE args[8];
288
-
289
- sec_as_time(t, &ti);
290
- args[0] = LONG2NUM((long)(ti.year));
291
- args[1] = LONG2NUM(ti.mon);
292
- args[2] = LONG2NUM(ti.day);
293
- args[3] = LONG2NUM(ti.hour);
294
- args[4] = LONG2NUM(ti.min);
295
- args[5] = rb_float_new((double)ti.sec + ((double)nsec + 0.5) / 1000000000.0);
296
- args[6] = LONG2NUM(ni->exp);
297
- parent->val = rb_funcall2(rb_cTime, oj_new_id, 7, args);
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);
298
284
  } else {
299
285
  parent->val = rb_time_nano_new(ni->i, (long)nsec);
300
286
  }
301
287
  }
302
288
  break;
303
- case 'i': // circular index
304
- if (!ni->infinity && !ni->neg && 1 == ni->div && 0 == ni->exp &&
305
- 0 != pi->circ_array) { // fixnum
289
+ case 'i': // circular index
290
+ if (!ni->infinity && !ni->neg && 1 == ni->div && 0 == ni->exp && 0 != pi->circ_array) { // fixnum
306
291
  if (Qnil == parent->val) {
307
292
  parent->val = rb_hash_new();
308
293
  }
@@ -331,7 +316,7 @@ static int hat_value(ParseInfo pi, Val parent, const char *key, size_t klen, vol
331
316
  oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "Invalid struct data");
332
317
  return 1;
333
318
  }
334
- e1 = *RARRAY_PTR(value);
319
+ e1 = *RARRAY_CONST_PTR(value);
335
320
  // check for anonymous Struct
336
321
  if (T_ARRAY == rb_type(e1)) {
337
322
  VALUE args[1024];
@@ -339,46 +324,50 @@ static int hat_value(ParseInfo pi, Val parent, const char *key, size_t klen, vol
339
324
  int i, cnt = (int)RARRAY_LEN(e1);
340
325
 
341
326
  for (i = 0; i < cnt; i++) {
342
- rstr = rb_ary_entry(e1, i);
327
+ rstr = RARRAY_AREF(e1, i);
343
328
  args[i] = rb_funcall(rstr, oj_to_sym_id, 0);
344
329
  }
345
330
  sc = rb_funcall2(rb_cStruct, oj_new_id, cnt, args);
346
331
  } else {
347
332
  // If struct is not defined then we let this fail and raise an exception.
348
- sc = oj_name2struct(pi, *RARRAY_PTR(value), rb_eArgError);
333
+ sc = oj_name2struct(pi, *RARRAY_CONST_PTR(value), rb_eArgError);
349
334
  }
350
- // Create a properly initialized struct instance without calling the initialize method.
351
- parent->val = rb_obj_alloc(sc);
352
- // If the JSON array has more entries than the struct class allows, we record an error.
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.
353
341
  #ifdef RSTRUCT_LEN
354
342
  #if RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
355
- slen = (int)NUM2LONG(RSTRUCT_LEN(parent->val));
343
+ slen = (int)NUM2LONG(RSTRUCT_LEN(parent->val));
356
344
  #else // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
357
- slen = (int)RSTRUCT_LEN(parent->val);
345
+ slen = (int)RSTRUCT_LEN(parent->val);
358
346
  #endif // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
359
347
  #else
360
- slen = FIX2INT(rb_funcall2(parent->val, oj_length_id, 0, 0));
348
+ slen = FIX2INT(rb_funcall2(parent->val, oj_length_id, 0, 0));
361
349
  #endif
362
- // MRI >= 1.9
363
- if (len - 1 > slen) {
364
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "Invalid struct data");
365
- } else {
366
- 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;
367
355
 
368
- for (i = 0; i < len - 1; i++) {
369
- rb_struct_aset(parent->val, INT2FIX(i), RARRAY_PTR(value)[i + 1]);
356
+ for (i = 0; i < len - 1; i++) {
357
+ rb_struct_aset(parent->val, INT2FIX(i), RARRAY_CONST_PTR(value)[i + 1]);
358
+ }
370
359
  }
371
360
  }
372
361
  return 1;
373
362
  } else if (3 <= klen && '#' == key[1]) {
374
- volatile VALUE *a;
363
+ volatile const VALUE *a;
375
364
 
376
365
  if (2 != len) {
377
366
  oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid hash pair");
378
367
  return 1;
379
368
  }
380
369
  parent->val = rb_hash_new();
381
- a = RARRAY_PTR(value);
370
+ a = RARRAY_CONST_PTR(value);
382
371
  rb_hash_aset(parent->val, *a, a[1]);
383
372
 
384
373
  return 1;
@@ -388,55 +377,17 @@ static int hat_value(ParseInfo pi, Val parent, const char *key, size_t klen, vol
388
377
  }
389
378
 
390
379
  void oj_set_obj_ivar(Val parent, Val kval, VALUE value) {
391
- const char *key = kval->key;
392
- int klen = kval->klen;
393
- ID var_id;
394
- ID * slot;
395
-
396
- #ifdef HAVE_PTHREAD_MUTEX_INIT
397
- pthread_mutex_lock(&oj_cache_mutex);
398
- #else
399
- rb_mutex_lock(oj_cache_mutex);
400
- #endif
401
- if (0 == (var_id = oj_attr_hash_get(key, klen, &slot))) {
402
- char attr[256];
403
-
404
- if ((int)sizeof(attr) <= klen + 2) {
405
- char *buf = ALLOC_N(char, klen + 2);
406
-
407
- if ('~' == *key) {
408
- strncpy(buf, key + 1, klen - 1);
409
- buf[klen - 1] = '\0';
410
- } else {
411
- *buf = '@';
412
- strncpy(buf + 1, key, klen);
413
- buf[klen + 1] = '\0';
414
- }
415
- var_id = rb_intern(buf);
416
- xfree(buf);
417
- } else {
418
- if ('~' == *key) {
419
- strncpy(attr, key + 1, klen - 1);
420
- attr[klen - 1] = '\0';
421
- } else {
422
- *attr = '@';
423
- strncpy(attr + 1, key, klen);
424
- attr[klen + 1] = '\0';
425
- }
426
- var_id = rb_intern(attr);
427
- }
428
- *slot = var_id;
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);
429
386
  }
430
- #ifdef HAVE_PTHREAD_MUTEX_INIT
431
- pthread_mutex_unlock(&oj_cache_mutex);
432
- #else
433
- rb_mutex_unlock(oj_cache_mutex);
434
- #endif
435
- rb_ivar_set(parent->val, var_id, value);
436
387
  }
437
388
 
438
389
  static void hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, const char *orig) {
439
- const char * key = kval->key;
390
+ const char *key = kval->key;
440
391
  int klen = kval->klen;
441
392
  Val parent = stack_peek(&pi->stack);
442
393
  volatile VALUE rval = Qnil;
@@ -451,9 +402,7 @@ WHICH_TYPE:
451
402
  }
452
403
  break;
453
404
  case T_HASH:
454
- rb_hash_aset(parent->val,
455
- calc_hash_key(pi, kval, parent->k1),
456
- str_to_value(pi, str, len, orig));
405
+ rb_hash_aset(parent->val, calc_hash_key(pi, kval, parent->k1), str_to_value(pi, str, len, orig));
457
406
  break;
458
407
  case T_STRING:
459
408
  rval = str_to_value(pi, str, len, orig);
@@ -505,13 +454,11 @@ WHICH_TYPE:
505
454
  rb_class2name(rb_obj_class(parent->val)));
506
455
  return;
507
456
  }
508
- if (Yes == pi->options.trace) {
509
- oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rval);
510
- }
457
+ TRACE_PARSE_CALL(pi->options.trace, "set_string", pi, rval);
511
458
  }
512
459
 
513
460
  static void hash_set_num(ParseInfo pi, Val kval, NumInfo ni) {
514
- const char * key = kval->key;
461
+ const char *key = kval->key;
515
462
  int klen = kval->klen;
516
463
  Val parent = stack_peek(&pi->stack);
517
464
  volatile VALUE rval = Qnil;
@@ -530,8 +477,8 @@ WHICH_TYPE:
530
477
  rb_hash_aset(parent->val, calc_hash_key(pi, kval, parent->k1), rval);
531
478
  break;
532
479
  case T_OBJECT:
533
- if (2 == klen && '^' == *key && 'i' == key[1] && !ni->infinity && !ni->neg &&
534
- 1 == ni->div && 0 == ni->exp && 0 != pi->circ_array) { // fixnum
480
+ if (2 == klen && '^' == *key && 'i' == key[1] && !ni->infinity && !ni->neg && 1 == ni->div && 0 == ni->exp &&
481
+ 0 != pi->circ_array) { // fixnum
535
482
  oj_circ_array_set(pi->circ_array, parent->val, ni->i);
536
483
  } else {
537
484
  rval = oj_num_as_value(ni);
@@ -576,9 +523,7 @@ WHICH_TYPE:
576
523
  rb_class2name(rb_obj_class(parent->val)));
577
524
  return;
578
525
  }
579
- if (Yes == pi->options.trace) {
580
- oj_trace_parse_call("add_number", pi, __FILE__, __LINE__, rval);
581
- }
526
+ TRACE_PARSE_CALL(pi->options.trace, "add_number", pi, rval);
582
527
  }
583
528
 
584
529
  static void hash_set_value(ParseInfo pi, Val kval, VALUE value) {
@@ -604,15 +549,11 @@ WHICH_TYPE:
604
549
  }
605
550
  } else {
606
551
  if (3 <= klen && '^' == *key && '#' == key[1] && T_ARRAY == rb_type(value)) {
607
- long len = RARRAY_LEN(value);
608
- volatile VALUE *a = RARRAY_PTR(value);
552
+ long len = RARRAY_LEN(value);
553
+ volatile const VALUE *a = RARRAY_CONST_PTR(value);
609
554
 
610
555
  if (2 != len) {
611
- oj_set_error_at(pi,
612
- oj_parse_error_class,
613
- __FILE__,
614
- __LINE__,
615
- "invalid hash pair");
556
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid hash pair");
616
557
  return;
617
558
  }
618
559
  rb_hash_aset(parent->val, *a, a[1]);
@@ -666,15 +607,11 @@ WHICH_TYPE:
666
607
  rb_class2name(rb_obj_class(parent->val)));
667
608
  return;
668
609
  }
669
- if (Yes == pi->options.trace) {
670
- oj_trace_parse_call("add_value", pi, __FILE__, __LINE__, value);
671
- }
610
+ TRACE_PARSE_CALL(pi->options.trace, "add_value", pi, value);
672
611
  }
673
612
 
674
613
  static VALUE start_hash(ParseInfo pi) {
675
- if (Yes == pi->options.trace) {
676
- oj_trace_parse_in("start_hash", pi, __FILE__, __LINE__);
677
- }
614
+ TRACE_PARSE_IN(pi->options.trace, "start_hash", pi);
678
615
  return Qnil;
679
616
  }
680
617
 
@@ -686,24 +623,18 @@ static void end_hash(ParseInfo pi) {
686
623
  } else if (NULL != parent->odd_args) {
687
624
  OddArgs oa = parent->odd_args;
688
625
 
689
- parent->val = rb_funcall2(oa->odd->create_obj,
690
- oa->odd->create_op,
691
- oa->odd->attr_cnt,
692
- oa->args);
626
+ parent->val = rb_funcall2(oa->odd->create_obj, oa->odd->create_op, oa->odd->attr_cnt, oa->args);
693
627
  oj_odd_free(oa);
694
628
  parent->odd_args = NULL;
695
629
  }
696
- if (Yes == pi->options.trace) {
697
- oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
698
- }
630
+ TRACE_PARSE_HASH_END(pi->options.trace, pi);
699
631
  }
700
632
 
701
633
  static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
702
634
  volatile VALUE rval = Qnil;
703
635
 
704
636
  // orig lets us know whether the string was ^r1 or \u005er1
705
- if (3 <= len && 0 != pi->circ_array && '^' == orig[0] &&
706
- 0 == rb_array_len(stack_peek(&pi->stack)->val)) {
637
+ if (3 <= len && 0 != pi->circ_array && '^' == orig[0] && 0 == rb_array_len(stack_peek(&pi->stack)->val)) {
707
638
  if ('i' == str[1]) {
708
639
  long i = read_long(str + 2, len - 2);
709
640
 
@@ -722,32 +653,24 @@ static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const c
722
653
  }
723
654
  rval = str_to_value(pi, str, len, orig);
724
655
  rb_ary_push(stack_peek(&pi->stack)->val, rval);
725
- if (Yes == pi->options.trace) {
726
- oj_trace_parse_call("append_string", pi, __FILE__, __LINE__, rval);
727
- }
656
+ TRACE_PARSE_CALL(pi->options.trace, "append_string", pi, rval);
728
657
  }
729
658
 
730
659
  static void array_append_num(ParseInfo pi, NumInfo ni) {
731
660
  volatile VALUE rval = oj_num_as_value(ni);
732
661
 
733
662
  rb_ary_push(stack_peek(&pi->stack)->val, rval);
734
- if (Yes == pi->options.trace) {
735
- oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, rval);
736
- }
663
+ TRACE_PARSE_CALL(pi->options.trace, "append_number", pi, rval);
737
664
  }
738
665
 
739
666
  static void add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
740
667
  pi->stack.head->val = str_to_value(pi, str, len, orig);
741
- if (Yes == pi->options.trace) {
742
- oj_trace_parse_call("add_string", pi, __FILE__, __LINE__, pi->stack.head->val);
743
- }
668
+ TRACE_PARSE_CALL(pi->options.trace, "add_string", pi, pi->stack.head->val);
744
669
  }
745
670
 
746
671
  static void add_num(ParseInfo pi, NumInfo ni) {
747
672
  pi->stack.head->val = oj_num_as_value(ni);
748
- if (Yes == pi->options.trace) {
749
- oj_trace_parse_call("add_num", pi, __FILE__, __LINE__, pi->stack.head->val);
750
- }
673
+ TRACE_PARSE_CALL(pi->options.trace, "add_num", pi, pi->stack.head->val);
751
674
  }
752
675
 
753
676
  void oj_set_object_callbacks(ParseInfo pi) {