oj 3.11.5 → 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 (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) {