oj 3.13.7 → 3.13.23

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 (83) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +75 -0
  3. data/README.md +11 -0
  4. data/ext/oj/buf.h +4 -0
  5. data/ext/oj/circarray.c +1 -1
  6. data/ext/oj/code.c +15 -22
  7. data/ext/oj/compat.c +10 -10
  8. data/ext/oj/custom.c +66 -112
  9. data/ext/oj/dump.c +147 -184
  10. data/ext/oj/dump.h +25 -8
  11. data/ext/oj/dump_compat.c +47 -89
  12. data/ext/oj/dump_leaf.c +14 -58
  13. data/ext/oj/dump_object.c +72 -188
  14. data/ext/oj/dump_strict.c +19 -31
  15. data/ext/oj/encoder.c +43 -0
  16. data/ext/oj/extconf.rb +5 -4
  17. data/ext/oj/fast.c +36 -24
  18. data/ext/oj/intern.c +22 -12
  19. data/ext/oj/intern.h +1 -1
  20. data/ext/oj/mimic_json.c +74 -73
  21. data/ext/oj/object.c +54 -72
  22. data/ext/oj/odd.c +83 -63
  23. data/ext/oj/odd.h +13 -13
  24. data/ext/oj/oj.c +166 -175
  25. data/ext/oj/oj.h +25 -3
  26. data/ext/oj/parse.c +123 -79
  27. data/ext/oj/parse.h +2 -0
  28. data/ext/oj/parser.c +77 -21
  29. data/ext/oj/parser.h +12 -0
  30. data/ext/oj/rails.c +46 -70
  31. data/ext/oj/rails.h +1 -1
  32. data/ext/oj/reader.c +2 -0
  33. data/ext/oj/saj.c +11 -23
  34. data/ext/oj/saj2.c +333 -85
  35. data/ext/oj/saj2.h +23 -0
  36. data/ext/oj/sparse.c +4 -0
  37. data/ext/oj/stream_writer.c +3 -1
  38. data/ext/oj/strict.c +13 -13
  39. data/ext/oj/string_writer.c +12 -5
  40. data/ext/oj/usual.c +86 -131
  41. data/ext/oj/usual.h +68 -0
  42. data/ext/oj/val_stack.c +1 -1
  43. data/ext/oj/validate.c +21 -26
  44. data/ext/oj/wab.c +22 -27
  45. data/lib/oj/saj.rb +20 -6
  46. data/lib/oj/state.rb +1 -1
  47. data/lib/oj/version.rb +1 -1
  48. data/pages/Compatibility.md +1 -1
  49. data/pages/JsonGem.md +15 -0
  50. data/pages/Modes.md +6 -3
  51. data/pages/Options.md +6 -0
  52. data/pages/Rails.md +12 -0
  53. data/test/activesupport7/abstract_unit.rb +49 -0
  54. data/test/activesupport7/decoding_test.rb +125 -0
  55. data/test/activesupport7/encoding_test.rb +486 -0
  56. data/test/activesupport7/encoding_test_cases.rb +104 -0
  57. data/test/activesupport7/time_zone_test_helpers.rb +47 -0
  58. data/test/bar.rb +3 -8
  59. data/test/bug.rb +16 -0
  60. data/test/foo.rb +71 -7
  61. data/test/helper.rb +8 -2
  62. data/test/json_gem/json_generator_test.rb +5 -4
  63. data/test/json_gem/json_parser_test.rb +8 -1
  64. data/test/json_gem/test_helper.rb +7 -3
  65. data/test/perf_dump.rb +50 -0
  66. data/test/test_compat.rb +25 -0
  67. data/test/test_custom.rb +13 -2
  68. data/test/test_fast.rb +37 -7
  69. data/test/test_file.rb +23 -7
  70. data/test/test_gc.rb +11 -0
  71. data/test/test_object.rb +8 -10
  72. data/test/test_parser.rb +3 -19
  73. data/test/test_parser_debug.rb +27 -0
  74. data/test/test_parser_saj.rb +92 -2
  75. data/test/test_saj.rb +1 -1
  76. data/test/test_scp.rb +2 -4
  77. data/test/test_strict.rb +2 -0
  78. data/test/test_various.rb +32 -2
  79. data/test/test_wab.rb +2 -0
  80. data/test/tests.rb +9 -1
  81. data/test/tests_mimic.rb +9 -0
  82. data/test/tests_mimic_addition.rb +9 -0
  83. metadata +15 -115
data/ext/oj/oj.c CHANGED
@@ -32,6 +32,7 @@ ID oj_array_append_id;
32
32
  ID oj_array_end_id;
33
33
  ID oj_array_start_id;
34
34
  ID oj_as_json_id;
35
+ ID oj_at_id;
35
36
  ID oj_begin_id;
36
37
  ID oj_bigdecimal_id;
37
38
  ID oj_end_id;
@@ -45,7 +46,6 @@ ID oj_hash_key_id;
45
46
  ID oj_hash_set_id;
46
47
  ID oj_hash_start_id;
47
48
  ID oj_iconv_id;
48
- ID oj_instance_variables_id;
49
49
  ID oj_json_create_id;
50
50
  ID oj_length_id;
51
51
  ID oj_new_id;
@@ -90,10 +90,13 @@ VALUE oj_array_class_sym;
90
90
  VALUE oj_create_additions_sym;
91
91
  VALUE oj_decimal_class_sym;
92
92
  VALUE oj_hash_class_sym;
93
+ VALUE oj_in_sym;
93
94
  VALUE oj_indent_sym;
95
+ VALUE oj_nanosecond_sym;
94
96
  VALUE oj_object_class_sym;
95
97
  VALUE oj_quirks_mode_sym;
96
98
  VALUE oj_safe_sym;
99
+ VALUE oj_symbolize_names_sym;
97
100
  VALUE oj_trace_sym;
98
101
 
99
102
  static VALUE allow_blank_sym;
@@ -136,6 +139,7 @@ static VALUE rails_sym;
136
139
  static VALUE raise_sym;
137
140
  static VALUE ruby_sym;
138
141
  static VALUE sec_prec_sym;
142
+ static VALUE slash_sym;
139
143
  static VALUE strict_sym;
140
144
  static VALUE symbol_keys_sym;
141
145
  static VALUE time_format_sym;
@@ -152,6 +156,7 @@ static VALUE xmlschema_sym;
152
156
  static VALUE xss_safe_sym;
153
157
 
154
158
  rb_encoding *oj_utf8_encoding = 0;
159
+ int oj_utf8_encoding_index = 0;
155
160
 
156
161
  #ifdef HAVE_PTHREAD_MUTEX_INIT
157
162
  pthread_mutex_t oj_cache_mutex;
@@ -238,7 +243,7 @@ struct _options oj_default_options = {
238
243
  *references
239
244
  * - *:auto_define* [_Boolean_|_nil_] automatically define classes if they do not exist
240
245
  * - *:symbol_keys* [_Boolean_|_nil_] use symbols instead of strings for hash keys
241
- * - *:escape_mode* [_:newline_|_:json_|_:xss_safe_|_:ascii_|_unicode_xss_|_nil_] determines the
246
+ * - *:escape_mode* [_:newline_|_:json_|_:slash_|_:xss_safe_|_:ascii_|_:unicode_xss_|_nil_] determines the
242
247
  *characters to escape
243
248
  * - *:class_cache* [_Boolean_|_nil_] cache classes for faster parsing (if dynamically modifying
244
249
  *classes or reloading classes then don't use this)
@@ -246,7 +251,7 @@ struct _options oj_default_options = {
246
251
  *to use for JSON
247
252
  * - *:time_format* [_:unix_|_:unix_zone_|_:xmlschema_|_:ruby_] time format when dumping
248
253
  * - *:bigdecimal_as_decimal* [_Boolean_|_nil_] dump BigDecimal as a decimal number or as a String
249
- * - *:bigdecimal_load* [_:bigdecimal_|_:float_|_:auto_|_:fast_] load decimals as BigDecimal instead
254
+ * - *:bigdecimal_load* [_:bigdecimal_|_:float_|_:auto_|_:fast_|_:ruby_] load decimals as BigDecimal instead
250
255
  *of as a Float. :auto pick the most precise for the number of digits. :float should be the same as
251
256
  *ruby. :fast may require rounding but is must faster.
252
257
  * - *:compat_bigdecimal* [_true_|_false_] load decimals as BigDecimal instead of as a Float when in
@@ -308,106 +313,76 @@ static VALUE get_def_opts(VALUE self) {
308
313
  rb_hash_aset(opts, sec_prec_sym, INT2FIX(oj_default_options.sec_prec));
309
314
  rb_hash_aset(opts,
310
315
  circular_sym,
311
- (Yes == oj_default_options.circular)
312
- ? Qtrue
313
- : ((No == oj_default_options.circular) ? Qfalse : Qnil));
314
- rb_hash_aset(opts,
315
- class_cache_sym,
316
- (Yes == oj_default_options.class_cache)
317
- ? Qtrue
318
- : ((No == oj_default_options.class_cache) ? Qfalse : Qnil));
319
- rb_hash_aset(opts,
320
- auto_define_sym,
321
- (Yes == oj_default_options.auto_define)
322
- ? Qtrue
323
- : ((No == oj_default_options.auto_define) ? Qfalse : Qnil));
316
+ (Yes == oj_default_options.circular) ? Qtrue : ((No == oj_default_options.circular) ? Qfalse : Qnil));
317
+ rb_hash_aset(
318
+ opts,
319
+ class_cache_sym,
320
+ (Yes == oj_default_options.class_cache) ? Qtrue : ((No == oj_default_options.class_cache) ? Qfalse : Qnil));
321
+ rb_hash_aset(
322
+ opts,
323
+ auto_define_sym,
324
+ (Yes == oj_default_options.auto_define) ? Qtrue : ((No == oj_default_options.auto_define) ? Qfalse : Qnil));
324
325
  rb_hash_aset(opts,
325
326
  symbol_keys_sym,
326
- (Yes == oj_default_options.sym_key)
327
- ? Qtrue
328
- : ((No == oj_default_options.sym_key) ? Qfalse : Qnil));
329
- rb_hash_aset(opts,
330
- bigdecimal_as_decimal_sym,
331
- (Yes == oj_default_options.bigdec_as_num)
332
- ? Qtrue
333
- : ((No == oj_default_options.bigdec_as_num) ? Qfalse : Qnil));
334
- rb_hash_aset(opts,
335
- oj_create_additions_sym,
336
- (Yes == oj_default_options.create_ok)
337
- ? Qtrue
338
- : ((No == oj_default_options.create_ok) ? Qfalse : Qnil));
327
+ (Yes == oj_default_options.sym_key) ? Qtrue : ((No == oj_default_options.sym_key) ? Qfalse : Qnil));
328
+ rb_hash_aset(
329
+ opts,
330
+ bigdecimal_as_decimal_sym,
331
+ (Yes == oj_default_options.bigdec_as_num) ? Qtrue : ((No == oj_default_options.bigdec_as_num) ? Qfalse : Qnil));
332
+ rb_hash_aset(
333
+ opts,
334
+ oj_create_additions_sym,
335
+ (Yes == oj_default_options.create_ok) ? Qtrue : ((No == oj_default_options.create_ok) ? Qfalse : Qnil));
339
336
  rb_hash_aset(opts,
340
337
  use_to_json_sym,
341
- (Yes == oj_default_options.to_json)
342
- ? Qtrue
343
- : ((No == oj_default_options.to_json) ? Qfalse : Qnil));
338
+ (Yes == oj_default_options.to_json) ? Qtrue : ((No == oj_default_options.to_json) ? Qfalse : Qnil));
344
339
  rb_hash_aset(opts,
345
340
  use_to_hash_sym,
346
- (Yes == oj_default_options.to_hash)
347
- ? Qtrue
348
- : ((No == oj_default_options.to_hash) ? Qfalse : Qnil));
341
+ (Yes == oj_default_options.to_hash) ? Qtrue : ((No == oj_default_options.to_hash) ? Qfalse : Qnil));
349
342
  rb_hash_aset(opts,
350
343
  use_as_json_sym,
351
- (Yes == oj_default_options.as_json)
352
- ? Qtrue
353
- : ((No == oj_default_options.as_json) ? Qfalse : Qnil));
344
+ (Yes == oj_default_options.as_json) ? Qtrue : ((No == oj_default_options.as_json) ? Qfalse : Qnil));
354
345
  rb_hash_aset(opts,
355
346
  use_raw_json_sym,
356
- (Yes == oj_default_options.raw_json)
357
- ? Qtrue
358
- : ((No == oj_default_options.raw_json) ? Qfalse : Qnil));
347
+ (Yes == oj_default_options.raw_json) ? Qtrue : ((No == oj_default_options.raw_json) ? Qfalse : Qnil));
359
348
  rb_hash_aset(opts,
360
349
  nilnil_sym,
361
- (Yes == oj_default_options.nilnil)
362
- ? Qtrue
363
- : ((No == oj_default_options.nilnil) ? Qfalse : Qnil));
364
- rb_hash_aset(opts,
365
- empty_string_sym,
366
- (Yes == oj_default_options.empty_string)
367
- ? Qtrue
368
- : ((No == oj_default_options.empty_string) ? Qfalse : Qnil));
350
+ (Yes == oj_default_options.nilnil) ? Qtrue : ((No == oj_default_options.nilnil) ? Qfalse : Qnil));
351
+ rb_hash_aset(
352
+ opts,
353
+ empty_string_sym,
354
+ (Yes == oj_default_options.empty_string) ? Qtrue : ((No == oj_default_options.empty_string) ? Qfalse : Qnil));
369
355
  rb_hash_aset(opts,
370
356
  allow_gc_sym,
371
- (Yes == oj_default_options.allow_gc)
372
- ? Qtrue
373
- : ((No == oj_default_options.allow_gc) ? Qfalse : Qnil));
374
- rb_hash_aset(opts,
375
- oj_quirks_mode_sym,
376
- (Yes == oj_default_options.quirks_mode)
377
- ? Qtrue
378
- : ((No == oj_default_options.quirks_mode) ? Qfalse : Qnil));
379
- rb_hash_aset(opts,
380
- allow_invalid_unicode_sym,
381
- (Yes == oj_default_options.allow_invalid)
382
- ? Qtrue
383
- : ((No == oj_default_options.allow_invalid) ? Qfalse : Qnil));
384
- rb_hash_aset(opts,
385
- oj_allow_nan_sym,
386
- (Yes == oj_default_options.allow_nan)
387
- ? Qtrue
388
- : ((No == oj_default_options.allow_nan) ? Qfalse : Qnil));
357
+ (Yes == oj_default_options.allow_gc) ? Qtrue : ((No == oj_default_options.allow_gc) ? Qfalse : Qnil));
358
+ rb_hash_aset(
359
+ opts,
360
+ oj_quirks_mode_sym,
361
+ (Yes == oj_default_options.quirks_mode) ? Qtrue : ((No == oj_default_options.quirks_mode) ? Qfalse : Qnil));
362
+ rb_hash_aset(
363
+ opts,
364
+ allow_invalid_unicode_sym,
365
+ (Yes == oj_default_options.allow_invalid) ? Qtrue : ((No == oj_default_options.allow_invalid) ? Qfalse : Qnil));
366
+ rb_hash_aset(
367
+ opts,
368
+ oj_allow_nan_sym,
369
+ (Yes == oj_default_options.allow_nan) ? Qtrue : ((No == oj_default_options.allow_nan) ? Qfalse : Qnil));
389
370
  rb_hash_aset(opts,
390
371
  oj_trace_sym,
391
- (Yes == oj_default_options.trace)
392
- ? Qtrue
393
- : ((No == oj_default_options.trace) ? Qfalse : Qnil));
372
+ (Yes == oj_default_options.trace) ? Qtrue : ((No == oj_default_options.trace) ? Qfalse : Qnil));
394
373
  rb_hash_aset(opts,
395
374
  oj_safe_sym,
396
- (Yes == oj_default_options.safe)
397
- ? Qtrue
398
- : ((No == oj_default_options.safe) ? Qfalse : Qnil));
375
+ (Yes == oj_default_options.safe) ? Qtrue : ((No == oj_default_options.safe) ? Qfalse : Qnil));
399
376
  rb_hash_aset(opts, float_prec_sym, INT2FIX(oj_default_options.float_prec));
400
377
  rb_hash_aset(opts, cache_str_sym, INT2FIX(oj_default_options.cache_str));
401
- rb_hash_aset(opts,
402
- ignore_under_sym,
403
- (Yes == oj_default_options.ignore_under)
404
- ? Qtrue
405
- : ((No == oj_default_options.ignore_under) ? Qfalse : Qnil));
406
- rb_hash_aset(opts,
407
- cache_keys_sym,
408
- (Yes == oj_default_options.cache_keys)
409
- ? Qtrue
410
- : ((No == oj_default_options.cache_keys) ? Qfalse : Qnil));
378
+ rb_hash_aset(
379
+ opts,
380
+ ignore_under_sym,
381
+ (Yes == oj_default_options.ignore_under) ? Qtrue : ((No == oj_default_options.ignore_under) ? Qfalse : Qnil));
382
+ rb_hash_aset(
383
+ opts,
384
+ cache_keys_sym,
385
+ (Yes == oj_default_options.cache_keys) ? Qtrue : ((No == oj_default_options.cache_keys) ? Qfalse : Qnil));
411
386
  switch (oj_default_options.mode) {
412
387
  case StrictMode: rb_hash_aset(opts, mode_sym, strict_sym); break;
413
388
  case CompatMode: rb_hash_aset(opts, mode_sym, compat_sym); break;
@@ -433,6 +408,7 @@ static VALUE get_def_opts(VALUE self) {
433
408
  switch (oj_default_options.escape_mode) {
434
409
  case NLEsc: rb_hash_aset(opts, escape_mode_sym, newline_sym); break;
435
410
  case JSONEsc: rb_hash_aset(opts, escape_mode_sym, json_sym); break;
411
+ case SlashEsc: rb_hash_aset(opts, escape_mode_sym, slash_sym); break;
436
412
  case XSSEsc: rb_hash_aset(opts, escape_mode_sym, xss_safe_sym); break;
437
413
  case ASCIIEsc: rb_hash_aset(opts, escape_mode_sym, ascii_sym); break;
438
414
  case JXEsc: rb_hash_aset(opts, escape_mode_sym, unicode_xss_sym); break;
@@ -453,30 +429,25 @@ static VALUE get_def_opts(VALUE self) {
453
429
  default: rb_hash_aset(opts, bigdecimal_load_sym, auto_sym); break;
454
430
  }
455
431
  rb_hash_aset(opts, compat_bigdecimal_sym, oj_default_options.compat_bigdec ? Qtrue : Qfalse);
432
+ rb_hash_aset(opts,
433
+ create_id_sym,
434
+ (NULL == oj_default_options.create_id) ? Qnil : rb_str_new2(oj_default_options.create_id));
456
435
  rb_hash_aset(
457
436
  opts,
458
- create_id_sym,
459
- (NULL == oj_default_options.create_id) ? Qnil : rb_str_new2(oj_default_options.create_id));
460
- rb_hash_aset(opts,
461
- oj_space_sym,
462
- (0 == oj_default_options.dump_opts.after_size)
463
- ? Qnil
464
- : rb_str_new2(oj_default_options.dump_opts.after_sep));
465
- rb_hash_aset(opts,
466
- oj_space_before_sym,
467
- (0 == oj_default_options.dump_opts.before_size)
468
- ? Qnil
469
- : rb_str_new2(oj_default_options.dump_opts.before_sep));
470
- rb_hash_aset(opts,
471
- oj_object_nl_sym,
472
- (0 == oj_default_options.dump_opts.hash_size)
473
- ? Qnil
474
- : rb_str_new2(oj_default_options.dump_opts.hash_nl));
475
- rb_hash_aset(opts,
476
- oj_array_nl_sym,
477
- (0 == oj_default_options.dump_opts.array_size)
478
- ? Qnil
479
- : rb_str_new2(oj_default_options.dump_opts.array_nl));
437
+ oj_space_sym,
438
+ (0 == oj_default_options.dump_opts.after_size) ? Qnil : rb_str_new2(oj_default_options.dump_opts.after_sep));
439
+ rb_hash_aset(
440
+ opts,
441
+ oj_space_before_sym,
442
+ (0 == oj_default_options.dump_opts.before_size) ? Qnil : rb_str_new2(oj_default_options.dump_opts.before_sep));
443
+ rb_hash_aset(
444
+ opts,
445
+ oj_object_nl_sym,
446
+ (0 == oj_default_options.dump_opts.hash_size) ? Qnil : rb_str_new2(oj_default_options.dump_opts.hash_nl));
447
+ rb_hash_aset(
448
+ opts,
449
+ oj_array_nl_sym,
450
+ (0 == oj_default_options.dump_opts.array_size) ? Qnil : rb_str_new2(oj_default_options.dump_opts.array_nl));
480
451
 
481
452
  switch (oj_default_options.dump_opts.nan_dump) {
482
453
  case NullNan: rb_hash_aset(opts, nan_sym, null_sym); break;
@@ -584,16 +555,14 @@ static VALUE set_def_opts(VALUE self, VALUE opts) {
584
555
  return Qnil;
585
556
  }
586
557
 
587
- bool oj_hash_has_key(VALUE hash, VALUE key)
588
- {
558
+ bool oj_hash_has_key(VALUE hash, VALUE key) {
589
559
  if (Qundef == rb_hash_lookup2(hash, key, Qundef)) {
590
560
  return false;
591
561
  }
592
562
  return true;
593
563
  }
594
564
 
595
- bool set_yesno_options(VALUE key, VALUE value, Options copts)
596
- {
565
+ bool set_yesno_options(VALUE key, VALUE value, Options copts) {
597
566
  struct _yesNoOpt ynos[] = {{circular_sym, &copts->circular},
598
567
  {auto_define_sym, &copts->auto_define},
599
568
  {symbol_keys_sym, &copts->sym_key},
@@ -616,29 +585,26 @@ bool set_yesno_options(VALUE key, VALUE value, Options copts)
616
585
  {oj_create_additions_sym, &copts->create_ok},
617
586
  {cache_keys_sym, &copts->cache_keys},
618
587
  {Qnil, 0}};
619
- YesNoOpt o;
620
-
621
- for (o = ynos; 0 != o->attr; o++) {
622
- if (key == o->sym) {
623
- if (Qnil == value) {
624
- *o->attr = NotSet;
625
- } else if (Qtrue == value) {
626
- *o->attr = Yes;
627
- } else if (Qfalse == value) {
628
- *o->attr = No;
629
- } else {
630
- rb_raise(rb_eArgError,
631
- "%s must be true, false, or nil.",
632
- rb_id2name(key));
633
- }
634
- return true;
635
- }
636
- }
588
+ YesNoOpt o;
589
+
590
+ for (o = ynos; 0 != o->attr; o++) {
591
+ if (key == o->sym) {
592
+ if (Qnil == value) {
593
+ *o->attr = NotSet;
594
+ } else if (Qtrue == value) {
595
+ *o->attr = Yes;
596
+ } else if (Qfalse == value) {
597
+ *o->attr = No;
598
+ } else {
599
+ rb_raise(rb_eArgError, "%s must be true, false, or nil.", rb_id2name(key));
600
+ }
601
+ return true;
602
+ }
603
+ }
637
604
  return false;
638
605
  }
639
606
 
640
- static int parse_options_cb(VALUE k, VALUE v, VALUE opts)
641
- {
607
+ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
642
608
  Options copts = (Options)opts;
643
609
  size_t len;
644
610
 
@@ -753,8 +719,7 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts)
753
719
  } else if (rails_sym == v) {
754
720
  copts->mode = RailsMode;
755
721
  } else {
756
- rb_raise(rb_eArgError,
757
- ":mode must be :object, :strict, :compat, :null, :custom, :rails, or :wab.");
722
+ rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, :null, :custom, :rails, or :wab.");
758
723
  }
759
724
  } else if (time_format_sym == k) {
760
725
  if (unix_sym == v) {
@@ -773,6 +738,8 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts)
773
738
  copts->escape_mode = NLEsc;
774
739
  } else if (json_sym == v) {
775
740
  copts->escape_mode = JSONEsc;
741
+ } else if (slash_sym == v) {
742
+ copts->escape_mode = SlashEsc;
776
743
  } else if (xss_safe_sym == v) {
777
744
  copts->escape_mode = XSSEsc;
778
745
  } else if (ascii_sym == v) {
@@ -780,8 +747,7 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts)
780
747
  } else if (unicode_xss_sym == v) {
781
748
  copts->escape_mode = JXEsc;
782
749
  } else {
783
- rb_raise(rb_eArgError,
784
- ":encoding must be :newline, :json, :xss_safe, :unicode_xss, or :ascii.");
750
+ rb_raise(rb_eArgError, ":encoding must be :newline, :json, :xss_safe, :unicode_xss, or :ascii.");
785
751
  }
786
752
  } else if (bigdecimal_load_sym == k) {
787
753
  if (Qnil == v) {
@@ -892,7 +858,6 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts)
892
858
  if (Qnil == v) {
893
859
  return ST_CONTINUE;
894
860
  }
895
-
896
861
  if (null_sym == v) {
897
862
  copts->dump_opts.nan_dump = NullNan;
898
863
  } else if (huge_sym == v) {
@@ -910,7 +875,6 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts)
910
875
  if (Qnil == v) {
911
876
  return ST_CONTINUE;
912
877
  }
913
-
914
878
  if (Qtrue == v) {
915
879
  copts->dump_opts.omit_nil = true;
916
880
  } else if (Qfalse == v) {
@@ -918,7 +882,7 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts)
918
882
  } else {
919
883
  rb_raise(rb_eArgError, ":omit_nil must be true or false.");
920
884
  }
921
- } else if(oj_ascii_only_sym == k) {
885
+ } else if (oj_ascii_only_sym == k) {
922
886
  // This is here only for backwards compatibility with the original Oj.
923
887
  if (Qtrue == v) {
924
888
  copts->escape_mode = ASCIIEsc;
@@ -959,7 +923,7 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts)
959
923
 
960
924
  copts->ignore = ALLOC_N(VALUE, cnt + 1);
961
925
  for (i = 0; i < cnt; i++) {
962
- copts->ignore[i] = rb_ary_entry(v, i);
926
+ copts->ignore[i] = RARRAY_AREF(v, i);
963
927
  }
964
928
  copts->ignore[i] = Qnil;
965
929
  }
@@ -968,8 +932,7 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts)
968
932
  if (Qnil == v) {
969
933
  return ST_CONTINUE;
970
934
  }
971
-
972
- if (TYPE(v) == T_STRUCT && rb_obj_class(v) == rb_cRange) {
935
+ if (rb_obj_class(v) == rb_cRange) {
973
936
  VALUE min = rb_funcall(v, oj_begin_id, 0);
974
937
  VALUE max = rb_funcall(v, oj_end_id, 0);
975
938
 
@@ -982,8 +945,12 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts)
982
945
  } else if (Qfalse != v) {
983
946
  rb_raise(rb_eArgError, ":integer_range must be a range of Fixnum.");
984
947
  }
948
+ } else if (symbol_keys_sym == k || oj_symbolize_names_sym == k) {
949
+ if (Qnil == v) {
950
+ return ST_CONTINUE;
951
+ }
952
+ copts->sym_key = (Qtrue == v) ? Yes : No;
985
953
  }
986
-
987
954
  return ST_CONTINUE;
988
955
  }
989
956
 
@@ -1014,9 +981,7 @@ static int match_string_cb(VALUE key, VALUE value, VALUE rx) {
1014
981
  rb_raise(rb_eArgError, "%s", rc->err);
1015
982
  }
1016
983
  break;
1017
- default:
1018
- rb_raise(rb_eArgError, "for :match_string, keys must either a String or RegExp.");
1019
- break;
984
+ default: rb_raise(rb_eArgError, "for :match_string, keys must either a String or RegExp."); break;
1020
985
  }
1021
986
  return ST_CONTINUE;
1022
987
  }
@@ -1184,14 +1149,22 @@ static VALUE load_file(int argc, VALUE *argv, VALUE self) {
1184
1149
  } else if (wab_sym == v) {
1185
1150
  mode = WabMode;
1186
1151
  } else {
1187
- rb_raise(
1188
- rb_eArgError,
1189
- ":mode must be :object, :strict, :compat, :null, :custom, :rails, or :wab.");
1152
+ rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, :null, :custom, :rails, or :wab.");
1190
1153
  }
1191
1154
  }
1192
1155
  }
1193
1156
  path = StringValuePtr(*argv);
1194
- if (0 == (fd = open(path, O_RDONLY))) {
1157
+ #ifdef _WIN32
1158
+ {
1159
+ WCHAR *wide_path;
1160
+ wide_path = rb_w32_mbstr_to_wstr(CP_UTF8, path, -1, NULL);
1161
+ fd = rb_w32_wopen(wide_path, O_RDONLY);
1162
+ free(wide_path);
1163
+ }
1164
+ #else
1165
+ fd = open(path, O_RDONLY);
1166
+ #endif
1167
+ if (0 == fd) {
1195
1168
  rb_raise(rb_eIOError, "%s", strerror(errno));
1196
1169
  }
1197
1170
  switch (mode) {
@@ -1264,16 +1237,15 @@ static VALUE safe_load(VALUE self, VALUE doc) {
1264
1237
  */
1265
1238
 
1266
1239
  struct dump_arg {
1267
- struct _out *out;
1240
+ struct _out * out;
1268
1241
  struct _options *copts;
1269
- int argc;
1270
- VALUE *argv;
1242
+ int argc;
1243
+ VALUE * argv;
1271
1244
  };
1272
1245
 
1273
- static VALUE dump_body(VALUE a)
1274
- {
1246
+ static VALUE dump_body(VALUE a) {
1275
1247
  volatile struct dump_arg *arg = (void *)a;
1276
- VALUE rstr;
1248
+ VALUE rstr;
1277
1249
 
1278
1250
  oj_dump_obj_to_json_using_params(*arg->argv, arg->copts, arg->out, arg->argc - 1, arg->argv + 1);
1279
1251
  if (0 == arg->out->buf) {
@@ -1285,13 +1257,11 @@ static VALUE dump_body(VALUE a)
1285
1257
  return rstr;
1286
1258
  }
1287
1259
 
1288
- static VALUE dump_ensure(VALUE a)
1289
- {
1260
+ static VALUE dump_ensure(VALUE a) {
1290
1261
  volatile struct dump_arg *arg = (void *)a;
1291
1262
 
1292
- if (arg->out->allocated) {
1293
- xfree(arg->out->buf);
1294
- }
1263
+ oj_out_free(arg->out);
1264
+
1295
1265
  return Qnil;
1296
1266
  }
1297
1267
 
@@ -1303,7 +1273,6 @@ static VALUE dump_ensure(VALUE a)
1303
1273
  * - *options* [_Hash_] same as default_options
1304
1274
  */
1305
1275
  static VALUE dump(int argc, VALUE *argv, VALUE self) {
1306
- char buf[4096];
1307
1276
  struct dump_arg arg;
1308
1277
  struct _out out;
1309
1278
  struct _options copts = oj_default_options;
@@ -1320,14 +1289,13 @@ static VALUE dump(int argc, VALUE *argv, VALUE self) {
1320
1289
  if (CompatMode == copts.mode && copts.escape_mode != ASCIIEsc) {
1321
1290
  copts.escape_mode = JSONEsc;
1322
1291
  }
1323
- arg.out = &out;
1292
+ arg.out = &out;
1324
1293
  arg.copts = &copts;
1325
- arg.argc = argc;
1326
- arg.argv = argv;
1294
+ arg.argc = argc;
1295
+ arg.argv = argv;
1296
+
1297
+ oj_out_init(arg.out);
1327
1298
 
1328
- arg.out->buf = buf;
1329
- arg.out->end = buf + sizeof(buf) - 10;
1330
- arg.out->allocated = false;
1331
1299
  arg.out->omit_nil = copts.dump_opts.omit_nil;
1332
1300
  arg.out->caller = CALLER_DUMP;
1333
1301
 
@@ -1359,7 +1327,6 @@ static VALUE dump(int argc, VALUE *argv, VALUE self) {
1359
1327
  * Returns [_String_] the encoded JSON.
1360
1328
  */
1361
1329
  static VALUE to_json(int argc, VALUE *argv, VALUE self) {
1362
- char buf[4096];
1363
1330
  struct _out out;
1364
1331
  struct _options copts = oj_default_options;
1365
1332
  VALUE rstr;
@@ -1374,9 +1341,9 @@ static VALUE to_json(int argc, VALUE *argv, VALUE self) {
1374
1341
  }
1375
1342
  copts.mode = CompatMode;
1376
1343
  copts.to_json = Yes;
1377
- out.buf = buf;
1378
- out.end = buf + sizeof(buf) - 10;
1379
- out.allocated = false;
1344
+
1345
+ oj_out_init(&out);
1346
+
1380
1347
  out.omit_nil = copts.dump_opts.omit_nil;
1381
1348
  // For obj.to_json or generate nan is not allowed but if called from dump
1382
1349
  // it is.
@@ -1387,9 +1354,9 @@ static VALUE to_json(int argc, VALUE *argv, VALUE self) {
1387
1354
  }
1388
1355
  rstr = rb_str_new2(out.buf);
1389
1356
  rstr = oj_encode(rstr);
1390
- if (out.allocated) {
1391
- xfree(out.buf);
1392
- }
1357
+
1358
+ oj_out_free(&out);
1359
+
1393
1360
  return rstr;
1394
1361
  }
1395
1362
 
@@ -1749,6 +1716,15 @@ static VALUE protect_require(VALUE x) {
1749
1716
  return Qnil;
1750
1717
  }
1751
1718
 
1719
+ extern void print_all_odds(const char *label);
1720
+
1721
+ static VALUE
1722
+ debug_odd(VALUE self, VALUE label) {
1723
+ print_all_odds(RSTRING_PTR(label));
1724
+ return Qnil;
1725
+ }
1726
+
1727
+
1752
1728
  /* Document-module: Oj
1753
1729
  *
1754
1730
  * Optimized JSON (Oj), as the name implies was written to provide speed
@@ -1777,15 +1753,19 @@ static VALUE protect_require(VALUE x) {
1777
1753
  *
1778
1754
  * - *:wab* specifically for WAB data exchange.
1779
1755
  */
1780
- void Init_oj() {
1756
+ void Init_oj(void) {
1781
1757
  int err = 0;
1782
1758
 
1783
1759
  #if HAVE_RB_EXT_RACTOR_SAFE
1784
1760
  rb_ext_ractor_safe(true);
1785
1761
  #endif
1786
1762
  Oj = rb_define_module("Oj");
1763
+ rb_gc_register_address(&Oj);
1787
1764
 
1788
1765
  oj_cstack_class = rb_define_class_under(Oj, "CStack", rb_cObject);
1766
+ rb_gc_register_address(&oj_cstack_class);
1767
+
1768
+ rb_undef_alloc_func(oj_cstack_class);
1789
1769
 
1790
1770
  oj_string_writer_init();
1791
1771
  oj_stream_writer_init();
@@ -1794,9 +1774,11 @@ void Init_oj() {
1794
1774
  // On Rubinius the require fails but can be done from a ruby file.
1795
1775
  rb_protect(protect_require, Qnil, &err);
1796
1776
  rb_require("stringio");
1797
- oj_utf8_encoding = rb_enc_find("UTF-8");
1777
+ oj_utf8_encoding_index = rb_enc_find_index("UTF-8");
1778
+ oj_utf8_encoding = rb_enc_from_index(oj_utf8_encoding_index);
1798
1779
 
1799
1780
  // rb_define_module_function(Oj, "hash_test", hash_test, 0);
1781
+ rb_define_module_function(Oj, "debug_odd", debug_odd, 1);
1800
1782
 
1801
1783
  rb_define_module_function(Oj, "default_options", get_def_opts, 0);
1802
1784
  rb_define_module_function(Oj, "default_options=", set_def_opts, 1);
@@ -1835,6 +1817,7 @@ void Init_oj() {
1835
1817
  oj_array_end_id = rb_intern("array_end");
1836
1818
  oj_array_start_id = rb_intern("array_start");
1837
1819
  oj_as_json_id = rb_intern("as_json");
1820
+ oj_at_id = rb_intern("at");
1838
1821
  oj_begin_id = rb_intern("begin");
1839
1822
  oj_bigdecimal_id = rb_intern("BigDecimal");
1840
1823
  oj_end_id = rb_intern("end");
@@ -1848,7 +1831,6 @@ void Init_oj() {
1848
1831
  oj_hash_set_id = rb_intern("hash_set");
1849
1832
  oj_hash_start_id = rb_intern("hash_start");
1850
1833
  oj_iconv_id = rb_intern("iconv");
1851
- oj_instance_variables_id = rb_intern("instance_variables");
1852
1834
  oj_json_create_id = rb_intern("json_create");
1853
1835
  oj_length_id = rb_intern("length");
1854
1836
  oj_new_id = rb_intern("new");
@@ -1983,10 +1965,14 @@ void Init_oj() {
1983
1965
  rb_gc_register_address(&oj_decimal_class_sym);
1984
1966
  oj_hash_class_sym = ID2SYM(rb_intern("hash_class"));
1985
1967
  rb_gc_register_address(&oj_hash_class_sym);
1968
+ oj_in_sym = ID2SYM(rb_intern("in"));
1969
+ rb_gc_register_address(&oj_in_sym);
1986
1970
  oj_indent_sym = ID2SYM(rb_intern("indent"));
1987
1971
  rb_gc_register_address(&oj_indent_sym);
1988
1972
  oj_max_nesting_sym = ID2SYM(rb_intern("max_nesting"));
1989
1973
  rb_gc_register_address(&oj_max_nesting_sym);
1974
+ oj_nanosecond_sym = ID2SYM(rb_intern("nanosecond"));
1975
+ rb_gc_register_address(&oj_nanosecond_sym);
1990
1976
  oj_object_class_sym = ID2SYM(rb_intern("object_class"));
1991
1977
  rb_gc_register_address(&oj_object_class_sym);
1992
1978
  oj_object_nl_sym = ID2SYM(rb_intern("object_nl"));
@@ -2011,10 +1997,14 @@ void Init_oj() {
2011
1997
  rb_gc_register_address(&ruby_sym);
2012
1998
  sec_prec_sym = ID2SYM(rb_intern("second_precision"));
2013
1999
  rb_gc_register_address(&sec_prec_sym);
2000
+ slash_sym = ID2SYM(rb_intern("slash"));
2001
+ rb_gc_register_address(&slash_sym);
2014
2002
  strict_sym = ID2SYM(rb_intern("strict"));
2015
2003
  rb_gc_register_address(&strict_sym);
2016
2004
  symbol_keys_sym = ID2SYM(rb_intern("symbol_keys"));
2017
2005
  rb_gc_register_address(&symbol_keys_sym);
2006
+ oj_symbolize_names_sym = ID2SYM(rb_intern("symbolize_names"));
2007
+ rb_gc_register_address(&oj_symbolize_names_sym);
2018
2008
  time_format_sym = ID2SYM(rb_intern("time_format"));
2019
2009
  rb_gc_register_address(&time_format_sym);
2020
2010
  unicode_xss_sym = ID2SYM(rb_intern("unicode_xss"));
@@ -2061,4 +2051,5 @@ void Init_oj() {
2061
2051
  oj_init_doc();
2062
2052
 
2063
2053
  oj_parser_init();
2054
+ oj_scanner_init();
2064
2055
  }