oj 3.14.2 → 3.15.0

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 (150) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -1
  3. data/README.md +0 -1
  4. data/ext/oj/buf.h +2 -2
  5. data/ext/oj/cache.c +16 -16
  6. data/ext/oj/cache8.c +7 -7
  7. data/ext/oj/circarray.c +2 -1
  8. data/ext/oj/circarray.h +2 -2
  9. data/ext/oj/code.c +2 -2
  10. data/ext/oj/code.h +2 -2
  11. data/ext/oj/compat.c +6 -14
  12. data/ext/oj/custom.c +6 -16
  13. data/ext/oj/debug.c +3 -9
  14. data/ext/oj/dump.c +43 -18
  15. data/ext/oj/dump_compat.c +551 -576
  16. data/ext/oj/dump_leaf.c +3 -5
  17. data/ext/oj/dump_object.c +35 -36
  18. data/ext/oj/dump_strict.c +2 -4
  19. data/ext/oj/encoder.c +1 -1
  20. data/ext/oj/err.c +2 -13
  21. data/ext/oj/err.h +9 -12
  22. data/ext/oj/extconf.rb +1 -1
  23. data/ext/oj/fast.c +24 -38
  24. data/ext/oj/intern.c +38 -42
  25. data/ext/oj/intern.h +3 -7
  26. data/ext/oj/mem.c +211 -217
  27. data/ext/oj/mem.h +10 -10
  28. data/ext/oj/mimic_json.c +39 -24
  29. data/ext/oj/object.c +12 -26
  30. data/ext/oj/odd.c +2 -1
  31. data/ext/oj/odd.h +4 -4
  32. data/ext/oj/oj.c +80 -81
  33. data/ext/oj/oj.h +56 -54
  34. data/ext/oj/parse.c +55 -118
  35. data/ext/oj/parse.h +5 -10
  36. data/ext/oj/parser.c +7 -8
  37. data/ext/oj/parser.h +7 -8
  38. data/ext/oj/rails.c +28 -59
  39. data/ext/oj/reader.c +5 -9
  40. data/ext/oj/reader.h +1 -1
  41. data/ext/oj/resolve.c +3 -4
  42. data/ext/oj/rxclass.c +1 -1
  43. data/ext/oj/rxclass.h +1 -1
  44. data/ext/oj/saj.c +4 -4
  45. data/ext/oj/saj2.c +32 -49
  46. data/ext/oj/saj2.h +1 -1
  47. data/ext/oj/scp.c +3 -14
  48. data/ext/oj/sparse.c +18 -67
  49. data/ext/oj/stream_writer.c +5 -18
  50. data/ext/oj/strict.c +16 -40
  51. data/ext/oj/string_writer.c +6 -14
  52. data/ext/oj/trace.h +27 -16
  53. data/ext/oj/usual.c +62 -61
  54. data/ext/oj/usual.h +6 -6
  55. data/ext/oj/util.h +1 -1
  56. data/ext/oj/val_stack.h +4 -4
  57. data/ext/oj/wab.c +16 -36
  58. data/lib/oj/active_support_helper.rb +0 -1
  59. data/lib/oj/bag.rb +7 -1
  60. data/lib/oj/easy_hash.rb +4 -5
  61. data/lib/oj/error.rb +0 -1
  62. data/lib/oj/json.rb +4 -2
  63. data/lib/oj/mimic.rb +4 -2
  64. data/lib/oj/state.rb +8 -5
  65. data/lib/oj/version.rb +1 -2
  66. data/lib/oj.rb +2 -0
  67. data/pages/Options.md +4 -0
  68. data/test/_test_active.rb +8 -9
  69. data/test/_test_active_mimic.rb +7 -8
  70. data/test/_test_mimic_rails.rb +17 -20
  71. data/test/activerecord/result_test.rb +5 -6
  72. data/test/files.rb +15 -15
  73. data/test/foo.rb +9 -52
  74. data/test/helper.rb +5 -8
  75. data/test/isolated/shared.rb +3 -2
  76. data/test/json_gem/json_addition_test.rb +2 -2
  77. data/test/json_gem/json_common_interface_test.rb +4 -4
  78. data/test/json_gem/json_encoding_test.rb +0 -0
  79. data/test/json_gem/json_ext_parser_test.rb +1 -0
  80. data/test/json_gem/json_fixtures_test.rb +3 -2
  81. data/test/json_gem/json_generator_test.rb +43 -32
  82. data/test/json_gem/json_generic_object_test.rb +11 -11
  83. data/test/json_gem/json_parser_test.rb +46 -46
  84. data/test/json_gem/json_string_matching_test.rb +9 -9
  85. data/test/mem.rb +13 -12
  86. data/test/perf.rb +21 -26
  87. data/test/perf_compat.rb +31 -33
  88. data/test/perf_dump.rb +25 -25
  89. data/test/perf_fast.rb +80 -82
  90. data/test/perf_file.rb +27 -29
  91. data/test/perf_object.rb +65 -69
  92. data/test/perf_once.rb +12 -11
  93. data/test/perf_parser.rb +41 -48
  94. data/test/perf_saj.rb +46 -54
  95. data/test/perf_scp.rb +57 -69
  96. data/test/perf_simple.rb +41 -39
  97. data/test/perf_strict.rb +68 -70
  98. data/test/perf_wab.rb +67 -69
  99. data/test/prec.rb +3 -3
  100. data/test/sample/change.rb +0 -1
  101. data/test/sample/dir.rb +0 -1
  102. data/test/sample/doc.rb +0 -1
  103. data/test/sample/file.rb +0 -1
  104. data/test/sample/group.rb +0 -1
  105. data/test/sample/hasprops.rb +0 -1
  106. data/test/sample/layer.rb +0 -1
  107. data/test/sample/rect.rb +0 -1
  108. data/test/sample/shape.rb +0 -1
  109. data/test/sample/text.rb +0 -1
  110. data/test/sample.rb +16 -16
  111. data/test/sample_json.rb +8 -8
  112. data/test/test_compat.rb +52 -52
  113. data/test/test_custom.rb +61 -51
  114. data/test/test_debian.rb +7 -10
  115. data/test/test_fast.rb +86 -90
  116. data/test/test_file.rb +24 -29
  117. data/test/test_gc.rb +5 -5
  118. data/test/test_generate.rb +5 -5
  119. data/test/test_hash.rb +4 -4
  120. data/test/test_integer_range.rb +9 -9
  121. data/test/test_null.rb +20 -20
  122. data/test/test_object.rb +78 -87
  123. data/test/test_parser.rb +4 -4
  124. data/test/test_parser_debug.rb +4 -4
  125. data/test/test_parser_saj.rb +27 -25
  126. data/test/test_parser_usual.rb +6 -6
  127. data/test/test_rails.rb +2 -2
  128. data/test/test_saj.rb +10 -8
  129. data/test/test_scp.rb +35 -35
  130. data/test/test_strict.rb +28 -32
  131. data/test/test_various.rb +140 -97
  132. data/test/test_wab.rb +46 -44
  133. data/test/test_writer.rb +47 -47
  134. data/test/tests.rb +7 -7
  135. data/test/tests_mimic.rb +6 -6
  136. data/test/tests_mimic_addition.rb +6 -6
  137. metadata +18 -30
  138. data/test/activesupport4/decoding_test.rb +0 -108
  139. data/test/activesupport4/encoding_test.rb +0 -531
  140. data/test/activesupport4/test_helper.rb +0 -41
  141. data/test/activesupport5/abstract_unit.rb +0 -45
  142. data/test/activesupport5/decoding_test.rb +0 -133
  143. data/test/activesupport5/encoding_test.rb +0 -500
  144. data/test/activesupport5/encoding_test_cases.rb +0 -98
  145. data/test/activesupport5/test_helper.rb +0 -72
  146. data/test/activesupport5/time_zone_test_helpers.rb +0 -39
  147. data/test/bar.rb +0 -11
  148. data/test/baz.rb +0 -16
  149. data/test/bug.rb +0 -16
  150. data/test/zoo.rb +0 -13
data/ext/oj/mimic_json.c CHANGED
@@ -1,9 +1,9 @@
1
1
  // Copyright (c) 2012, 2017 Peter Ohler. All rights reserved.
2
2
  // Licensed under the MIT License. See LICENSE file in the project root for license details.
3
3
 
4
- #include "mem.h"
5
4
  #include "dump.h"
6
5
  #include "encode.h"
6
+ #include "mem.h"
7
7
  #include "oj.h"
8
8
  #include "parse.h"
9
9
 
@@ -349,12 +349,11 @@ static VALUE mimic_load(int argc, VALUE *argv, VALUE self) {
349
349
  static VALUE mimic_dump_load(int argc, VALUE *argv, VALUE self) {
350
350
  if (1 > argc) {
351
351
  rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)");
352
- } else if (T_STRING == rb_type(*argv)) {
352
+ }
353
+ if (T_STRING == rb_type(*argv)) {
353
354
  return mimic_load(argc, argv, self);
354
- } else {
355
- return mimic_dump(argc, argv, self);
356
355
  }
357
- return Qnil;
356
+ return mimic_dump(argc, argv, self);
358
357
  }
359
358
 
360
359
  static VALUE mimic_generate_core(int argc, VALUE *argv, Options copts) {
@@ -368,8 +367,8 @@ static VALUE mimic_generate_core(int argc, VALUE *argv, Options copts) {
368
367
 
369
368
  oj_out_init(&out);
370
369
 
371
- out.omit_nil = copts->dump_opts.omit_nil;
372
- out.caller = CALLER_GENERATE;
370
+ out.omit_nil = copts->dump_opts.omit_nil;
371
+ out.caller = CALLER_GENERATE;
373
372
  // For obj.to_json or generate nan is not allowed but if called from dump
374
373
  // it is.
375
374
  copts->dump_opts.nan_dump = RaiseNan;
@@ -389,10 +388,8 @@ static VALUE mimic_generate_core(int argc, VALUE *argv, Options copts) {
389
388
  VALUE active_hack[1];
390
389
 
391
390
  if (Qundef == state_class) {
392
- rb_warn(
393
- "Oj::Rails.mimic_JSON was called implicitly. "
394
- "Call it explicitly beforehand if you want to remove this warning."
395
- );
391
+ rb_warn("Oj::Rails.mimic_JSON was called implicitly. "
392
+ "Call it explicitly beforehand if you want to remove this warning.");
396
393
  oj_define_mimic_json(0, NULL, Qnil);
397
394
  }
398
395
  active_hack[0] = rb_funcall(state_class, oj_new_id, 0);
@@ -467,7 +464,7 @@ oj_mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
467
464
  }
468
465
  if (1 == argc || Qnil == argv[1]) {
469
466
  h = rb_hash_new();
470
- } else {
467
+ } else {
471
468
  h = argv[1];
472
469
  }
473
470
  if (!oj_hash_has_key(h, oj_indent_sym)) {
@@ -486,10 +483,8 @@ oj_mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
486
483
  rb_hash_aset(h, oj_array_nl_sym, rb_str_new2("\n"));
487
484
  }
488
485
  if (Qundef == state_class) {
489
- rb_warn(
490
- "Oj::Rails.mimic_JSON was called implicitly. "
491
- "Call it explicitly beforehand if you want to remove this warning."
492
- );
486
+ rb_warn("Oj::Rails.mimic_JSON was called implicitly. "
487
+ "Call it explicitly beforehand if you want to remove this warning.");
493
488
  oj_define_mimic_json(0, NULL, Qnil);
494
489
  }
495
490
  rargs[1] = rb_funcall(state_class, oj_new_id, 1, h);
@@ -658,11 +653,9 @@ static VALUE mimic_recurse_proc(VALUE self, VALUE obj) {
658
653
  *
659
654
  * - *id* [_nil_|String] new create_id
660
655
  *
661
- * Returns [_String_] the id.
656
+ * Returns [_nil_|_String_] the id.
662
657
  */
663
658
  static VALUE mimic_set_create_id(VALUE self, VALUE id) {
664
- Check_Type(id, T_STRING);
665
-
666
659
  if (NULL != oj_default_options.create_id) {
667
660
  if (oj_json_class != oj_default_options.create_id) {
668
661
  OJ_R_FREE((char *)oj_default_options.create_id);
@@ -671,10 +664,11 @@ static VALUE mimic_set_create_id(VALUE self, VALUE id) {
671
664
  oj_default_options.create_id_len = 0;
672
665
  }
673
666
  if (Qnil != id) {
674
- size_t len = RSTRING_LEN(id) + 1;
667
+ const char *ptr = StringValueCStr(id);
668
+ size_t len = RSTRING_LEN(id) + 1;
675
669
 
676
670
  oj_default_options.create_id = OJ_R_ALLOC_N(char, len);
677
- strcpy((char *)oj_default_options.create_id, StringValuePtr(id));
671
+ strcpy((char *)oj_default_options.create_id, ptr);
678
672
  oj_default_options.create_id_len = len - 1;
679
673
  }
680
674
  return id;
@@ -744,6 +738,7 @@ static struct _options mimic_object_to_json_options = {0, // indent
744
738
  0, // array_size
745
739
  RaiseNan, // nan_dump
746
740
  false, // omit_nil
741
+ false, // omit_null_byte
747
742
  100, // max_depth
748
743
  },
749
744
  {
@@ -763,9 +758,9 @@ static VALUE mimic_object_to_json(int argc, VALUE *argv, VALUE self) {
763
758
 
764
759
  oj_out_init(&out);
765
760
 
766
- out.omit_nil = copts.dump_opts.omit_nil;
767
- copts.mode = CompatMode;
768
- copts.to_json = No;
761
+ out.omit_nil = copts.dump_opts.omit_nil;
762
+ copts.mode = CompatMode;
763
+ copts.to_json = No;
769
764
  if (1 <= argc && Qnil != argv[0]) {
770
765
  oj_parse_mimic_dump_options(argv[0], &copts);
771
766
  }
@@ -797,28 +792,48 @@ void oj_mimic_json_methods(VALUE json) {
797
792
  VALUE json_error;
798
793
  VALUE generator;
799
794
  VALUE ext;
795
+ VALUE verbose;
796
+
797
+ // rb_undef_method doesn't work for modules or maybe sometimes
798
+ // doesn't. Anyway setting verbose should hide the warning.
799
+ verbose = rb_gv_get("$VERBOSE");
800
+ rb_gv_set("$VERBOSE", Qfalse);
800
801
 
802
+ rb_undef_method(json, "create_id=");
801
803
  rb_define_module_function(json, "create_id=", mimic_set_create_id, 1);
804
+ rb_undef_method(json, "create_id");
802
805
  rb_define_module_function(json, "create_id", mimic_create_id, 0);
803
806
 
807
+ rb_undef_method(json, "dump");
804
808
  rb_define_module_function(json, "dump", mimic_dump, -1);
809
+ rb_undef_method(json, "load");
805
810
  rb_define_module_function(json, "load", mimic_load, -1);
806
811
  rb_define_module_function(json, "restore", mimic_load, -1);
812
+ rb_undef_method(json, "recurse_proc");
807
813
  rb_define_module_function(json, "recurse_proc", mimic_recurse_proc, 1);
814
+ rb_undef_method(json, "[]");
808
815
  rb_define_module_function(json, "[]", mimic_dump_load, -1);
809
816
 
817
+ rb_undef_method(json, "generate");
810
818
  rb_define_module_function(json, "generate", oj_mimic_generate, -1);
819
+ rb_undef_method(json, "fast_generate");
811
820
  rb_define_module_function(json, "fast_generate", oj_mimic_generate, -1);
821
+ rb_undef_method(json, "pretty_generate");
812
822
  rb_define_module_function(json, "pretty_generate", oj_mimic_pretty_generate, -1);
813
823
  // For older versions of JSON, the deprecated unparse methods.
824
+ rb_undef_method(json, "unparse");
814
825
  rb_define_module_function(json, "unparse", oj_mimic_generate, -1);
815
826
  rb_define_module_function(json, "fast_unparse", oj_mimic_generate, -1);
816
827
  rb_define_module_function(json, "pretty_unparse", oj_mimic_pretty_generate, -1);
817
828
 
829
+ rb_undef_method(json, "parse");
818
830
  rb_define_module_function(json, "parse", oj_mimic_parse, -1);
831
+ rb_undef_method(json, "parse!");
819
832
  rb_define_module_function(json, "parse!", mimic_parse_bang, -1);
820
833
 
834
+ rb_undef_method(json, "state");
821
835
  rb_define_module_function(json, "state", mimic_state, 0);
836
+ rb_gv_set("$VERBOSE", verbose);
822
837
 
823
838
  if (rb_const_defined_at(json, rb_intern("JSONError"))) {
824
839
  json_error = rb_const_get(json, rb_intern("JSONError"));
data/ext/oj/object.c CHANGED
@@ -270,8 +270,8 @@ static int hat_num(ParseInfo pi, Val parent, Val kval, NumInfo ni) {
270
270
  parent->val = rb_funcall2(parent->val, oj_utc_id, 0, 0);
271
271
  } else if (ni->has_exp) {
272
272
  struct timespec ts;
273
- ts.tv_sec = ni->i;
274
- ts.tv_nsec = nsec;
273
+ ts.tv_sec = ni->i;
274
+ ts.tv_nsec = nsec;
275
275
  parent->val = rb_time_timespec_new(&ts, (int)ni->exp);
276
276
  } else {
277
277
  parent->val = rb_time_nano_new(ni->i, (long)nsec);
@@ -325,14 +325,14 @@ static int hat_value(ParseInfo pi, Val parent, const char *key, size_t klen, vol
325
325
  sc = oj_name2struct(pi, *RARRAY_CONST_PTR(value), rb_eArgError);
326
326
  }
327
327
  if (sc == rb_cRange) {
328
- parent->val = rb_class_new_instance(len - 1, RARRAY_CONST_PTR(value) + 1, rb_cRange);
328
+ parent->val = rb_class_new_instance(len - 1, RARRAY_CONST_PTR(value) + 1, rb_cRange);
329
329
  } else {
330
330
  // Create a properly initialized struct instance without calling the initialize method.
331
331
  parent->val = rb_obj_alloc(sc);
332
332
  // If the JSON array has more entries than the struct class allows, we record an error.
333
333
  #ifdef RSTRUCT_LEN
334
334
  #if RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
335
- slen = (int)NUM2LONG(RSTRUCT_LEN(parent->val));
335
+ slen = (int)NUM2LONG(RSTRUCT_LEN(parent->val));
336
336
  #else // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
337
337
  slen = (int)RSTRUCT_LEN(parent->val);
338
338
  #endif // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
@@ -446,9 +446,7 @@ WHICH_TYPE:
446
446
  rb_class2name(rb_obj_class(parent->val)));
447
447
  return;
448
448
  }
449
- if (RB_UNLIKELY(Yes == pi->options.trace)) {
450
- oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rval);
451
- }
449
+ TRACE_PARSE_CALL(pi->options.trace, "set_string", pi, rval);
452
450
  }
453
451
 
454
452
  static void hash_set_num(ParseInfo pi, Val kval, NumInfo ni) {
@@ -517,9 +515,7 @@ WHICH_TYPE:
517
515
  rb_class2name(rb_obj_class(parent->val)));
518
516
  return;
519
517
  }
520
- if (RB_UNLIKELY(Yes == pi->options.trace)) {
521
- oj_trace_parse_call("add_number", pi, __FILE__, __LINE__, rval);
522
- }
518
+ TRACE_PARSE_CALL(pi->options.trace, "add_number", pi, rval);
523
519
  }
524
520
 
525
521
  static void hash_set_value(ParseInfo pi, Val kval, VALUE value) {
@@ -545,7 +541,7 @@ WHICH_TYPE:
545
541
  }
546
542
  } else {
547
543
  if (3 <= klen && '^' == *key && '#' == key[1] && T_ARRAY == rb_type(value)) {
548
- long len = RARRAY_LEN(value);
544
+ long len = RARRAY_LEN(value);
549
545
  volatile const VALUE *a = RARRAY_CONST_PTR(value);
550
546
 
551
547
  if (2 != len) {
@@ -603,9 +599,7 @@ WHICH_TYPE:
603
599
  rb_class2name(rb_obj_class(parent->val)));
604
600
  return;
605
601
  }
606
- if (RB_UNLIKELY(Yes == pi->options.trace)) {
607
- oj_trace_parse_call("add_value", pi, __FILE__, __LINE__, value);
608
- }
602
+ TRACE_PARSE_CALL(pi->options.trace, "add_value", pi, value);
609
603
  }
610
604
 
611
605
  static VALUE start_hash(ParseInfo pi) {
@@ -651,32 +645,24 @@ static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const c
651
645
  }
652
646
  rval = str_to_value(pi, str, len, orig);
653
647
  rb_ary_push(stack_peek(&pi->stack)->val, rval);
654
- if (RB_UNLIKELY(Yes == pi->options.trace)) {
655
- oj_trace_parse_call("append_string", pi, __FILE__, __LINE__, rval);
656
- }
648
+ TRACE_PARSE_CALL(pi->options.trace, "append_string", pi, rval);
657
649
  }
658
650
 
659
651
  static void array_append_num(ParseInfo pi, NumInfo ni) {
660
652
  volatile VALUE rval = oj_num_as_value(ni);
661
653
 
662
654
  rb_ary_push(stack_peek(&pi->stack)->val, rval);
663
- if (RB_UNLIKELY(Yes == pi->options.trace)) {
664
- oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, rval);
665
- }
655
+ TRACE_PARSE_CALL(pi->options.trace, "append_number", pi, rval);
666
656
  }
667
657
 
668
658
  static void add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
669
659
  pi->stack.head->val = str_to_value(pi, str, len, orig);
670
- if (RB_UNLIKELY(Yes == pi->options.trace)) {
671
- oj_trace_parse_call("add_string", pi, __FILE__, __LINE__, pi->stack.head->val);
672
- }
660
+ TRACE_PARSE_CALL(pi->options.trace, "add_string", pi, pi->stack.head->val);
673
661
  }
674
662
 
675
663
  static void add_num(ParseInfo pi, NumInfo ni) {
676
664
  pi->stack.head->val = oj_num_as_value(ni);
677
- if (RB_UNLIKELY(Yes == pi->options.trace)) {
678
- oj_trace_parse_call("add_num", pi, __FILE__, __LINE__, pi->stack.head->val);
679
- }
665
+ TRACE_PARSE_CALL(pi->options.trace, "add_num", pi, pi->stack.head->val);
680
666
  }
681
667
 
682
668
  void oj_set_object_callbacks(ParseInfo pi) {
data/ext/oj/odd.c CHANGED
@@ -1,11 +1,12 @@
1
1
  // Copyright (c) 2011 Peter Ohler. All rights reserved.
2
2
  // Licensed under the MIT License. See LICENSE file in the project root for license details.
3
3
 
4
- #include "mem.h"
5
4
  #include "odd.h"
6
5
 
7
6
  #include <string.h>
8
7
 
8
+ #include "mem.h"
9
+
9
10
  static Odd odds = NULL;
10
11
  static ID sec_id;
11
12
  static ID sec_fraction_id;
data/ext/oj/odd.h CHANGED
@@ -14,7 +14,7 @@ typedef VALUE (*AttrGetFunc)(VALUE obj);
14
14
 
15
15
  typedef struct _odd {
16
16
  struct _odd *next;
17
- const char * classname;
17
+ const char *classname;
18
18
  size_t clen;
19
19
  VALUE clas; // Ruby class or module
20
20
  VALUE create_obj;
@@ -22,15 +22,15 @@ typedef struct _odd {
22
22
  int attr_cnt;
23
23
  bool is_module;
24
24
  bool raw;
25
- const char * attr_names[MAX_ODD_ARGS]; // NULL terminated attr names
25
+ const char *attr_names[MAX_ODD_ARGS]; // NULL terminated attr names
26
26
  ID attrs[MAX_ODD_ARGS]; // 0 terminated attr IDs
27
27
  AttrGetFunc attrFuncs[MAX_ODD_ARGS];
28
- } * Odd;
28
+ } *Odd;
29
29
 
30
30
  typedef struct _oddArgs {
31
31
  Odd odd;
32
32
  VALUE args[MAX_ODD_ARGS];
33
- } * OddArgs;
33
+ } *OddArgs;
34
34
 
35
35
  extern void oj_odd_init(void);
36
36
  extern Odd oj_get_odd(VALUE clas);
data/ext/oj/oj.c CHANGED
@@ -11,10 +11,10 @@
11
11
  #include <sys/types.h>
12
12
  #include <unistd.h>
13
13
 
14
- #include "mem.h"
15
14
  #include "dump.h"
16
15
  #include "encode.h"
17
16
  #include "intern.h"
17
+ #include "mem.h"
18
18
  #include "odd.h"
19
19
  #include "parse.h"
20
20
  #include "rails.h"
@@ -22,7 +22,7 @@
22
22
  typedef struct _yesNoOpt {
23
23
  VALUE sym;
24
24
  char *attr;
25
- } * YesNoOpt;
25
+ } *YesNoOpt;
26
26
 
27
27
  void Init_oj();
28
28
 
@@ -135,6 +135,7 @@ static VALUE newline_sym;
135
135
  static VALUE nilnil_sym;
136
136
  static VALUE null_sym;
137
137
  static VALUE object_sym;
138
+ static VALUE omit_null_byte_sym;
138
139
  static VALUE omit_nil_sym;
139
140
  static VALUE rails_sym;
140
141
  static VALUE raise_sym;
@@ -156,8 +157,8 @@ static VALUE word_sym;
156
157
  static VALUE xmlschema_sym;
157
158
  static VALUE xss_safe_sym;
158
159
 
159
- rb_encoding *oj_utf8_encoding = 0;
160
- int oj_utf8_encoding_index = 0;
160
+ rb_encoding *oj_utf8_encoding = 0;
161
+ int oj_utf8_encoding_index = 0;
161
162
 
162
163
  #ifdef HAVE_PTHREAD_MUTEX_INIT
163
164
  pthread_mutex_t oj_cache_mutex;
@@ -222,6 +223,7 @@ struct _options oj_default_options = {
222
223
  0, // array_size
223
224
  AutoNan, // nan_dump
224
225
  false, // omit_nil
226
+ false, // omit_null_byte
225
227
  MAX_DEPTH, // max_depth
226
228
  },
227
229
  {
@@ -291,6 +293,7 @@ struct _options oj_default_options = {
291
293
  *used
292
294
  * - *:array_class* [_Class_|_nil_] Class to use instead of Array on load
293
295
  * - *:omit_nil* [_true_|_false_] if true Hash and Object attributes with nil values are omitted
296
+ * - *:omit_null_byte* [_true_|_false_] if true null bytes in strings will be omitted when dumping
294
297
  * - *:ignore* [_nil_|_Array_] either nil or an Array of classes to ignore when dumping
295
298
  * - *:ignore_under* [_Boolean_] if true then attributes that start with _ are ignored when dumping in
296
299
  *object or custom mode.
@@ -384,6 +387,7 @@ static VALUE get_def_opts(VALUE self) {
384
387
  opts,
385
388
  cache_keys_sym,
386
389
  (Yes == oj_default_options.cache_keys) ? Qtrue : ((No == oj_default_options.cache_keys) ? Qfalse : Qnil));
390
+
387
391
  switch (oj_default_options.mode) {
388
392
  case StrictMode: rb_hash_aset(opts, mode_sym, strict_sym); break;
389
393
  case CompatMode: rb_hash_aset(opts, mode_sym, compat_sym); break;
@@ -459,13 +463,14 @@ static VALUE get_def_opts(VALUE self) {
459
463
  default: rb_hash_aset(opts, nan_sym, auto_sym); break;
460
464
  }
461
465
  rb_hash_aset(opts, omit_nil_sym, oj_default_options.dump_opts.omit_nil ? Qtrue : Qfalse);
466
+ rb_hash_aset(opts, omit_null_byte_sym, oj_default_options.dump_opts.omit_null_byte ? Qtrue : Qfalse);
462
467
  rb_hash_aset(opts, oj_hash_class_sym, oj_default_options.hash_class);
463
468
  rb_hash_aset(opts, oj_array_class_sym, oj_default_options.array_class);
464
469
 
465
470
  if (NULL == oj_default_options.ignore) {
466
471
  rb_hash_aset(opts, ignore_sym, Qnil);
467
472
  } else {
468
- VALUE * vp;
473
+ VALUE *vp;
469
474
  volatile VALUE a = rb_ary_new();
470
475
 
471
476
  for (vp = oj_default_options.ignore; Qnil != *vp; vp++) {
@@ -640,15 +645,9 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
640
645
  } else if (float_prec_sym == k) {
641
646
  int n;
642
647
 
643
- #ifdef RUBY_INTEGER_UNIFICATION
644
648
  if (rb_cInteger != rb_obj_class(v)) {
645
649
  rb_raise(rb_eArgError, ":float_precision must be a Integer.");
646
650
  }
647
- #else
648
- if (T_FIXNUM != rb_type(v)) {
649
- rb_raise(rb_eArgError, ":float_precision must be a Fixnum.");
650
- }
651
- #endif
652
651
  n = FIX2INT(v);
653
652
  if (0 >= n) {
654
653
  *copts->float_fmt = '\0';
@@ -663,15 +662,9 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
663
662
  } else if (cache_str_sym == k || cache_string_sym == k) {
664
663
  int n;
665
664
 
666
- #ifdef RUBY_INTEGER_UNIFICATION
667
665
  if (rb_cInteger != rb_obj_class(v)) {
668
666
  rb_raise(rb_eArgError, ":cache_str must be a Integer.");
669
667
  }
670
- #else
671
- if (T_FIXNUM != rb_type(v)) {
672
- rb_raise(rb_eArgError, ":cache_str must be a Fixnum.");
673
- }
674
- #endif
675
668
  n = FIX2INT(v);
676
669
  if (0 >= n) {
677
670
  copts->cache_str = 0;
@@ -684,15 +677,9 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
684
677
  } else if (sec_prec_sym == k) {
685
678
  int n;
686
679
 
687
- #ifdef RUBY_INTEGER_UNIFICATION
688
680
  if (rb_cInteger != rb_obj_class(v)) {
689
681
  rb_raise(rb_eArgError, ":second_precision must be a Integer.");
690
682
  }
691
- #else
692
- if (T_FIXNUM != rb_type(v)) {
693
- rb_raise(rb_eArgError, ":second_precision must be a Fixnum.");
694
- }
695
- #endif
696
683
  n = NUM2INT(v);
697
684
  if (0 > n) {
698
685
  n = 0;
@@ -883,6 +870,17 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
883
870
  } else {
884
871
  rb_raise(rb_eArgError, ":omit_nil must be true or false.");
885
872
  }
873
+ } else if (omit_null_byte_sym == k) {
874
+ if (Qnil == v) {
875
+ return ST_CONTINUE;
876
+ }
877
+ if (Qtrue == v) {
878
+ copts->dump_opts.omit_null_byte = true;
879
+ } else if (Qfalse == v) {
880
+ copts->dump_opts.omit_null_byte = false;
881
+ } else {
882
+ rb_raise(rb_eArgError, ":omit_null_byte must be true or false.");
883
+ }
886
884
  } else if (oj_ascii_only_sym == k) {
887
885
  // This is here only for backwards compatibility with the original Oj.
888
886
  if (Qtrue == v) {
@@ -950,7 +948,7 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
950
948
  if (Qnil == v) {
951
949
  return ST_CONTINUE;
952
950
  }
953
- copts->sym_key = (Qtrue == v) ? Yes : No;
951
+ copts->sym_key = (Qtrue == v) ? Yes : No;
954
952
  }
955
953
  return ST_CONTINUE;
956
954
  }
@@ -1115,7 +1113,7 @@ static VALUE load(int argc, VALUE *argv, VALUE self) {
1115
1113
  * Returns [_Object_|_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_]
1116
1114
  */
1117
1115
  static VALUE load_file(int argc, VALUE *argv, VALUE self) {
1118
- char * path;
1116
+ char *path;
1119
1117
  int fd;
1120
1118
  Mode mode = oj_default_options.mode;
1121
1119
  struct _parseInfo pi;
@@ -1123,7 +1121,7 @@ static VALUE load_file(int argc, VALUE *argv, VALUE self) {
1123
1121
  if (1 > argc) {
1124
1122
  rb_raise(rb_eArgError, "Wrong number of arguments to load().");
1125
1123
  }
1126
- Check_Type(*argv, T_STRING);
1124
+ path = StringValuePtr(*argv);
1127
1125
  parse_info_init(&pi);
1128
1126
  pi.options = oj_default_options;
1129
1127
  pi.handler = Qnil;
@@ -1154,16 +1152,15 @@ static VALUE load_file(int argc, VALUE *argv, VALUE self) {
1154
1152
  }
1155
1153
  }
1156
1154
  }
1157
- path = StringValuePtr(*argv);
1158
1155
  #ifdef _WIN32
1159
1156
  {
1160
1157
  WCHAR *wide_path;
1161
1158
  wide_path = rb_w32_mbstr_to_wstr(CP_UTF8, path, -1, NULL);
1162
- fd = rb_w32_wopen(wide_path, O_RDONLY);
1159
+ fd = rb_w32_wopen(wide_path, O_RDONLY);
1163
1160
  OJ_FREE(wide_path);
1164
1161
  }
1165
1162
  #else
1166
- fd = open(path, O_RDONLY);
1163
+ fd = open(path, O_RDONLY);
1167
1164
  #endif
1168
1165
  if (0 == fd) {
1169
1166
  rb_raise(rb_eIOError, "%s", strerror(errno));
@@ -1238,10 +1235,10 @@ static VALUE safe_load(VALUE self, VALUE doc) {
1238
1235
  */
1239
1236
 
1240
1237
  struct dump_arg {
1241
- struct _out * out;
1238
+ struct _out *out;
1242
1239
  struct _options *copts;
1243
1240
  int argc;
1244
- VALUE * argv;
1241
+ VALUE *argv;
1245
1242
  };
1246
1243
 
1247
1244
  static VALUE dump_body(VALUE a) {
@@ -1297,8 +1294,9 @@ static VALUE dump(int argc, VALUE *argv, VALUE self) {
1297
1294
 
1298
1295
  oj_out_init(arg.out);
1299
1296
 
1300
- arg.out->omit_nil = copts.dump_opts.omit_nil;
1301
- arg.out->caller = CALLER_DUMP;
1297
+ arg.out->omit_nil = copts.dump_opts.omit_nil;
1298
+ arg.out->omit_null_byte = copts.dump_opts.omit_null_byte;
1299
+ arg.out->caller = CALLER_DUMP;
1302
1300
 
1303
1301
  return rb_ensure(dump_body, (VALUE)&arg, dump_ensure, (VALUE)&arg);
1304
1302
  }
@@ -1345,7 +1343,8 @@ static VALUE to_json(int argc, VALUE *argv, VALUE self) {
1345
1343
 
1346
1344
  oj_out_init(&out);
1347
1345
 
1348
- out.omit_nil = copts.dump_opts.omit_nil;
1346
+ out.omit_nil = copts.dump_opts.omit_nil;
1347
+ out.omit_null_byte = copts.dump_opts.omit_null_byte;
1349
1348
  // For obj.to_json or generate nan is not allowed but if called from dump
1350
1349
  // it is.
1351
1350
  oj_dump_obj_to_json_using_params(*argv, &copts, &out, argc - 1, argv + 1);
@@ -1377,7 +1376,6 @@ static VALUE to_file(int argc, VALUE *argv, VALUE self) {
1377
1376
  if (3 == argc) {
1378
1377
  oj_parse_options(argv[2], &copts);
1379
1378
  }
1380
- Check_Type(*argv, T_STRING);
1381
1379
  oj_write_obj_to_file(argv[1], StringValuePtr(*argv), &copts);
1382
1380
 
1383
1381
  return Qnil;
@@ -1719,8 +1717,7 @@ static VALUE protect_require(VALUE x) {
1719
1717
 
1720
1718
  extern void print_all_odds(const char *label);
1721
1719
 
1722
- static VALUE
1723
- debug_odd(VALUE self, VALUE label) {
1720
+ static VALUE debug_odd(VALUE self, VALUE label) {
1724
1721
  print_all_odds(RSTRING_PTR(label));
1725
1722
  return Qnil;
1726
1723
  }
@@ -1780,7 +1777,7 @@ void Init_oj(void) {
1780
1777
  rb_protect(protect_require, Qnil, &err);
1781
1778
  rb_require("stringio");
1782
1779
  oj_utf8_encoding_index = rb_enc_find_index("UTF-8");
1783
- oj_utf8_encoding = rb_enc_from_index(oj_utf8_encoding_index);
1780
+ oj_utf8_encoding = rb_enc_from_index(oj_utf8_encoding_index);
1784
1781
 
1785
1782
  // rb_define_module_function(Oj, "hash_test", hash_test, 0);
1786
1783
  rb_define_module_function(Oj, "debug_odd", debug_odd, 1);
@@ -1819,49 +1816,49 @@ void Init_oj(void) {
1819
1816
 
1820
1817
  rb_define_module_function(Oj, "mem_report", mem_report, 0);
1821
1818
 
1822
- oj_add_value_id = rb_intern("add_value");
1823
- oj_array_append_id = rb_intern("array_append");
1824
- oj_array_end_id = rb_intern("array_end");
1825
- oj_array_start_id = rb_intern("array_start");
1826
- oj_as_json_id = rb_intern("as_json");
1827
- oj_at_id = rb_intern("at");
1828
- oj_begin_id = rb_intern("begin");
1829
- oj_bigdecimal_id = rb_intern("BigDecimal");
1830
- oj_end_id = rb_intern("end");
1831
- oj_error_id = rb_intern("error");
1832
- oj_exclude_end_id = rb_intern("exclude_end?");
1833
- oj_file_id = rb_intern("file?");
1834
- oj_fileno_id = rb_intern("fileno");
1835
- oj_ftype_id = rb_intern("ftype");
1836
- oj_hash_end_id = rb_intern("hash_end");
1837
- oj_hash_key_id = rb_intern("hash_key");
1838
- oj_hash_set_id = rb_intern("hash_set");
1839
- oj_hash_start_id = rb_intern("hash_start");
1840
- oj_iconv_id = rb_intern("iconv");
1841
- oj_json_create_id = rb_intern("json_create");
1842
- oj_length_id = rb_intern("length");
1843
- oj_new_id = rb_intern("new");
1844
- oj_parse_id = rb_intern("parse");
1845
- oj_pos_id = rb_intern("pos");
1846
- oj_raw_json_id = rb_intern("raw_json");
1847
- oj_read_id = rb_intern("read");
1848
- oj_readpartial_id = rb_intern("readpartial");
1849
- oj_replace_id = rb_intern("replace");
1850
- oj_stat_id = rb_intern("stat");
1851
- oj_string_id = rb_intern("string");
1852
- oj_to_h_id = rb_intern("to_h");
1853
- oj_to_hash_id = rb_intern("to_hash");
1854
- oj_to_json_id = rb_intern("to_json");
1855
- oj_to_s_id = rb_intern("to_s");
1856
- oj_to_sym_id = rb_intern("to_sym");
1857
- oj_to_time_id = rb_intern("to_time");
1858
- oj_tv_nsec_id = rb_intern("tv_nsec");
1859
- oj_tv_sec_id = rb_intern("tv_sec");
1860
- oj_tv_usec_id = rb_intern("tv_usec");
1861
- oj_utc_id = rb_intern("utc");
1862
- oj_utc_offset_id = rb_intern("utc_offset");
1863
- oj_utcq_id = rb_intern("utc?");
1864
- oj_write_id = rb_intern("write");
1819
+ oj_add_value_id = rb_intern("add_value");
1820
+ oj_array_append_id = rb_intern("array_append");
1821
+ oj_array_end_id = rb_intern("array_end");
1822
+ oj_array_start_id = rb_intern("array_start");
1823
+ oj_as_json_id = rb_intern("as_json");
1824
+ oj_at_id = rb_intern("at");
1825
+ oj_begin_id = rb_intern("begin");
1826
+ oj_bigdecimal_id = rb_intern("BigDecimal");
1827
+ oj_end_id = rb_intern("end");
1828
+ oj_error_id = rb_intern("error");
1829
+ oj_exclude_end_id = rb_intern("exclude_end?");
1830
+ oj_file_id = rb_intern("file?");
1831
+ oj_fileno_id = rb_intern("fileno");
1832
+ oj_ftype_id = rb_intern("ftype");
1833
+ oj_hash_end_id = rb_intern("hash_end");
1834
+ oj_hash_key_id = rb_intern("hash_key");
1835
+ oj_hash_set_id = rb_intern("hash_set");
1836
+ oj_hash_start_id = rb_intern("hash_start");
1837
+ oj_iconv_id = rb_intern("iconv");
1838
+ oj_json_create_id = rb_intern("json_create");
1839
+ oj_length_id = rb_intern("length");
1840
+ oj_new_id = rb_intern("new");
1841
+ oj_parse_id = rb_intern("parse");
1842
+ oj_pos_id = rb_intern("pos");
1843
+ oj_raw_json_id = rb_intern("raw_json");
1844
+ oj_read_id = rb_intern("read");
1845
+ oj_readpartial_id = rb_intern("readpartial");
1846
+ oj_replace_id = rb_intern("replace");
1847
+ oj_stat_id = rb_intern("stat");
1848
+ oj_string_id = rb_intern("string");
1849
+ oj_to_h_id = rb_intern("to_h");
1850
+ oj_to_hash_id = rb_intern("to_hash");
1851
+ oj_to_json_id = rb_intern("to_json");
1852
+ oj_to_s_id = rb_intern("to_s");
1853
+ oj_to_sym_id = rb_intern("to_sym");
1854
+ oj_to_time_id = rb_intern("to_time");
1855
+ oj_tv_nsec_id = rb_intern("tv_nsec");
1856
+ oj_tv_sec_id = rb_intern("tv_sec");
1857
+ oj_tv_usec_id = rb_intern("tv_usec");
1858
+ oj_utc_id = rb_intern("utc");
1859
+ oj_utc_offset_id = rb_intern("utc_offset");
1860
+ oj_utcq_id = rb_intern("utc?");
1861
+ oj_write_id = rb_intern("write");
1865
1862
 
1866
1863
  rb_require("oj/bag");
1867
1864
  rb_require("oj/error");
@@ -1988,6 +1985,8 @@ void Init_oj(void) {
1988
1985
  rb_gc_register_address(&oj_quirks_mode_sym);
1989
1986
  oj_safe_sym = ID2SYM(rb_intern("safe"));
1990
1987
  rb_gc_register_address(&oj_safe_sym);
1988
+ omit_null_byte_sym = ID2SYM(rb_intern("omit_null_byte"));
1989
+ rb_gc_register_address(&omit_null_byte_sym);
1991
1990
  oj_space_before_sym = ID2SYM(rb_intern("space_before"));
1992
1991
  rb_gc_register_address(&oj_space_before_sym);
1993
1992
  oj_space_sym = ID2SYM(rb_intern("space"));