oj 3.11.0 → 3.16.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1421 -0
  3. data/README.md +20 -5
  4. data/RELEASE_NOTES.md +61 -0
  5. data/ext/oj/buf.h +48 -38
  6. data/ext/oj/cache.c +329 -0
  7. data/ext/oj/cache.h +22 -0
  8. data/ext/oj/cache8.c +60 -62
  9. data/ext/oj/cache8.h +8 -7
  10. data/ext/oj/circarray.c +35 -35
  11. data/ext/oj/circarray.h +11 -9
  12. data/ext/oj/code.c +156 -174
  13. data/ext/oj/code.h +19 -18
  14. data/ext/oj/compat.c +140 -197
  15. data/ext/oj/custom.c +737 -879
  16. data/ext/oj/debug.c +126 -0
  17. data/ext/oj/dump.c +830 -835
  18. data/ext/oj/dump.h +65 -53
  19. data/ext/oj/dump_compat.c +566 -642
  20. data/ext/oj/dump_leaf.c +95 -182
  21. data/ext/oj/dump_object.c +518 -659
  22. data/ext/oj/dump_strict.c +301 -334
  23. data/ext/oj/encode.h +3 -4
  24. data/ext/oj/encoder.c +43 -0
  25. data/ext/oj/err.c +27 -24
  26. data/ext/oj/err.h +38 -13
  27. data/ext/oj/extconf.rb +23 -7
  28. data/ext/oj/fast.c +1043 -1073
  29. data/ext/oj/intern.c +313 -0
  30. data/ext/oj/intern.h +22 -0
  31. data/ext/oj/mem.c +318 -0
  32. data/ext/oj/mem.h +53 -0
  33. data/ext/oj/mimic_json.c +449 -423
  34. data/ext/oj/object.c +530 -576
  35. data/ext/oj/odd.c +155 -138
  36. data/ext/oj/odd.h +24 -22
  37. data/ext/oj/oj.c +1331 -993
  38. data/ext/oj/oj.h +306 -292
  39. data/ext/oj/parse.c +934 -938
  40. data/ext/oj/parse.h +73 -70
  41. data/ext/oj/parser.c +1600 -0
  42. data/ext/oj/parser.h +101 -0
  43. data/ext/oj/rails.c +795 -845
  44. data/ext/oj/rails.h +7 -7
  45. data/ext/oj/reader.c +132 -140
  46. data/ext/oj/reader.h +67 -78
  47. data/ext/oj/resolve.c +40 -59
  48. data/ext/oj/resolve.h +3 -2
  49. data/ext/oj/rxclass.c +67 -67
  50. data/ext/oj/rxclass.h +11 -9
  51. data/ext/oj/saj.c +441 -480
  52. data/ext/oj/saj2.c +584 -0
  53. data/ext/oj/saj2.h +23 -0
  54. data/ext/oj/scp.c +78 -111
  55. data/ext/oj/sparse.c +726 -730
  56. data/ext/oj/stream_writer.c +146 -165
  57. data/ext/oj/strict.c +103 -123
  58. data/ext/oj/string_writer.c +241 -253
  59. data/ext/oj/trace.c +29 -33
  60. data/ext/oj/trace.h +41 -11
  61. data/ext/oj/usual.c +1218 -0
  62. data/ext/oj/usual.h +69 -0
  63. data/ext/oj/util.c +103 -103
  64. data/ext/oj/util.h +3 -2
  65. data/ext/oj/val_stack.c +60 -49
  66. data/ext/oj/val_stack.h +79 -85
  67. data/ext/oj/validate.c +46 -0
  68. data/ext/oj/wab.c +307 -350
  69. data/lib/oj/active_support_helper.rb +1 -3
  70. data/lib/oj/bag.rb +8 -1
  71. data/lib/oj/easy_hash.rb +9 -9
  72. data/lib/oj/error.rb +1 -2
  73. data/lib/oj/json.rb +162 -150
  74. data/lib/oj/mimic.rb +9 -19
  75. data/lib/oj/saj.rb +20 -6
  76. data/lib/oj/schandler.rb +5 -4
  77. data/lib/oj/state.rb +12 -8
  78. data/lib/oj/version.rb +1 -2
  79. data/lib/oj.rb +2 -0
  80. data/pages/Compatibility.md +1 -1
  81. data/pages/InstallOptions.md +20 -0
  82. data/pages/JsonGem.md +15 -0
  83. data/pages/Modes.md +8 -3
  84. data/pages/Options.md +43 -5
  85. data/pages/Parser.md +309 -0
  86. data/pages/Rails.md +14 -2
  87. data/test/_test_active.rb +8 -9
  88. data/test/_test_active_mimic.rb +7 -8
  89. data/test/_test_mimic_rails.rb +17 -20
  90. data/test/activerecord/result_test.rb +12 -8
  91. data/test/activesupport6/encoding_test.rb +63 -28
  92. data/test/{activesupport5 → activesupport7}/abstract_unit.rb +16 -12
  93. data/test/{activesupport5 → activesupport7}/decoding_test.rb +2 -10
  94. data/test/{activesupport5 → activesupport7}/encoding_test.rb +86 -50
  95. data/test/{activesupport5 → activesupport7}/encoding_test_cases.rb +6 -0
  96. data/test/{activesupport5 → activesupport7}/time_zone_test_helpers.rb +8 -0
  97. data/test/files.rb +15 -15
  98. data/test/foo.rb +17 -43
  99. data/test/helper.rb +16 -3
  100. data/test/isolated/shared.rb +3 -2
  101. data/test/json_gem/json_addition_test.rb +2 -2
  102. data/test/json_gem/json_common_interface_test.rb +8 -6
  103. data/test/json_gem/json_encoding_test.rb +0 -0
  104. data/test/json_gem/json_ext_parser_test.rb +1 -0
  105. data/test/json_gem/json_fixtures_test.rb +3 -2
  106. data/test/json_gem/json_generator_test.rb +71 -41
  107. data/test/json_gem/json_generic_object_test.rb +11 -11
  108. data/test/json_gem/json_parser_test.rb +54 -47
  109. data/test/json_gem/json_string_matching_test.rb +9 -9
  110. data/test/json_gem/test_helper.rb +12 -0
  111. data/test/mem.rb +34 -0
  112. data/test/perf.rb +22 -27
  113. data/test/perf_compat.rb +31 -33
  114. data/test/perf_dump.rb +50 -0
  115. data/test/perf_fast.rb +80 -82
  116. data/test/perf_file.rb +27 -29
  117. data/test/perf_object.rb +65 -69
  118. data/test/perf_once.rb +59 -0
  119. data/test/perf_parser.rb +183 -0
  120. data/test/perf_saj.rb +46 -54
  121. data/test/perf_scp.rb +58 -69
  122. data/test/perf_simple.rb +41 -39
  123. data/test/perf_strict.rb +74 -82
  124. data/test/perf_wab.rb +67 -69
  125. data/test/prec.rb +5 -5
  126. data/test/sample/change.rb +0 -1
  127. data/test/sample/dir.rb +0 -1
  128. data/test/sample/doc.rb +0 -1
  129. data/test/sample/file.rb +0 -1
  130. data/test/sample/group.rb +0 -1
  131. data/test/sample/hasprops.rb +0 -1
  132. data/test/sample/layer.rb +0 -1
  133. data/test/sample/rect.rb +0 -1
  134. data/test/sample/shape.rb +0 -1
  135. data/test/sample/text.rb +0 -1
  136. data/test/sample.rb +16 -16
  137. data/test/sample_json.rb +8 -8
  138. data/test/test_compat.rb +97 -45
  139. data/test/test_custom.rb +73 -51
  140. data/test/test_debian.rb +7 -10
  141. data/test/test_fast.rb +135 -79
  142. data/test/test_file.rb +41 -30
  143. data/test/test_gc.rb +16 -5
  144. data/test/test_generate.rb +21 -0
  145. data/test/test_hash.rb +15 -5
  146. data/test/test_integer_range.rb +9 -9
  147. data/test/test_null.rb +20 -20
  148. data/test/test_object.rb +99 -96
  149. data/test/test_parser.rb +11 -0
  150. data/test/test_parser_debug.rb +27 -0
  151. data/test/test_parser_saj.rb +337 -0
  152. data/test/test_parser_usual.rb +251 -0
  153. data/test/test_rails.rb +2 -2
  154. data/test/test_saj.rb +10 -8
  155. data/test/test_scp.rb +38 -40
  156. data/test/test_strict.rb +40 -32
  157. data/test/test_various.rb +165 -84
  158. data/test/test_wab.rb +48 -44
  159. data/test/test_writer.rb +47 -47
  160. data/test/tests.rb +13 -5
  161. data/test/tests_mimic.rb +12 -3
  162. data/test/tests_mimic_addition.rb +12 -3
  163. metadata +75 -127
  164. data/ext/oj/hash.c +0 -135
  165. data/ext/oj/hash.h +0 -18
  166. data/ext/oj/hash_test.c +0 -484
  167. data/test/activesupport4/decoding_test.rb +0 -108
  168. data/test/activesupport4/encoding_test.rb +0 -531
  169. data/test/activesupport4/test_helper.rb +0 -41
  170. data/test/activesupport5/test_helper.rb +0 -72
  171. data/test/bar.rb +0 -35
  172. data/test/baz.rb +0 -16
  173. data/test/zoo.rb +0 -13
data/ext/oj/mimic_json.c CHANGED
@@ -1,24 +1,24 @@
1
1
  // Copyright (c) 2012, 2017 Peter Ohler. All rights reserved.
2
+ // Licensed under the MIT License. See LICENSE file in the project root for license details.
2
3
 
3
- #include "oj.h"
4
- #include "encode.h"
5
4
  #include "dump.h"
5
+ #include "encode.h"
6
+ #include "mem.h"
7
+ #include "oj.h"
6
8
  #include "parse.h"
7
9
 
8
- static VALUE symbolize_names_sym = Qundef;
9
-
10
- extern const char oj_json_class[];
10
+ extern const char oj_json_class[];
11
11
 
12
- VALUE oj_array_nl_sym;
13
- VALUE oj_ascii_only_sym;
14
- VALUE oj_json_generator_error_class;
15
- VALUE oj_json_parser_error_class;
16
- VALUE oj_max_nesting_sym;
17
- VALUE oj_object_nl_sym;
18
- VALUE oj_space_before_sym;
19
- VALUE oj_space_sym;
12
+ VALUE oj_array_nl_sym;
13
+ VALUE oj_ascii_only_sym;
14
+ VALUE oj_json_generator_error_class;
15
+ VALUE oj_json_parser_error_class;
16
+ VALUE oj_max_nesting_sym;
17
+ VALUE oj_object_nl_sym;
18
+ VALUE oj_space_before_sym;
19
+ VALUE oj_space_sym;
20
20
 
21
- static VALUE state_class;
21
+ static VALUE state_class = Qundef;
22
22
 
23
23
  // mimic JSON documentation
24
24
 
@@ -53,14 +53,14 @@ static VALUE state_class;
53
53
 
54
54
  VALUE
55
55
  oj_get_json_err_class(const char *err_classname) {
56
- volatile VALUE json_module;
57
- volatile VALUE clas;
58
- volatile VALUE json_error_class;
56
+ volatile VALUE json_module;
57
+ volatile VALUE clas;
58
+ volatile VALUE json_error_class;
59
59
 
60
60
  if (rb_const_defined_at(rb_cObject, rb_intern("JSON"))) {
61
- json_module = rb_const_get_at(rb_cObject, rb_intern("JSON"));
61
+ json_module = rb_const_get_at(rb_cObject, rb_intern("JSON"));
62
62
  } else {
63
- json_module = rb_define_module("JSON");
63
+ json_module = rb_define_module("JSON");
64
64
  }
65
65
  if (rb_const_defined_at(json_module, rb_intern("JSONError"))) {
66
66
  json_error_class = rb_const_get(json_module, rb_intern("JSONError"));
@@ -68,113 +68,121 @@ oj_get_json_err_class(const char *err_classname) {
68
68
  json_error_class = rb_define_class_under(json_module, "JSONError", rb_eStandardError);
69
69
  }
70
70
  if (0 == strcmp(err_classname, "JSONError")) {
71
- clas = json_error_class;
71
+ clas = json_error_class;
72
72
  } else {
73
- if (rb_const_defined_at(json_module, rb_intern(err_classname))) {
74
- clas = rb_const_get(json_module, rb_intern(err_classname));
75
- } else {
76
- clas = rb_define_class_under(json_module, err_classname, json_error_class);
77
- }
73
+ if (rb_const_defined_at(json_module, rb_intern(err_classname))) {
74
+ clas = rb_const_get(json_module, rb_intern(err_classname));
75
+ } else {
76
+ clas = rb_define_class_under(json_module, err_classname, json_error_class);
77
+ }
78
78
  }
79
79
  return clas;
80
80
  }
81
81
 
82
- void
83
- oj_parse_mimic_dump_options(VALUE ropts, Options copts) {
84
- VALUE v;
85
- size_t len;
82
+ void oj_parse_mimic_dump_options(VALUE ropts, Options copts) {
83
+ VALUE v;
84
+ size_t len;
86
85
 
87
86
  if (T_HASH != rb_type(ropts)) {
88
- if (rb_respond_to(ropts, oj_to_hash_id)) {
89
- ropts = rb_funcall(ropts, oj_to_hash_id, 0);
90
- } else if (rb_respond_to(ropts, oj_to_h_id)) {
91
- ropts = rb_funcall(ropts, oj_to_h_id, 0);
92
- } else if (Qnil == ropts) {
93
- return;
94
- } else {
95
- rb_raise(rb_eArgError, "options must be a hash.");
96
- }
87
+ if (rb_respond_to(ropts, oj_to_hash_id)) {
88
+ ropts = rb_funcall(ropts, oj_to_hash_id, 0);
89
+ } else if (rb_respond_to(ropts, oj_to_h_id)) {
90
+ ropts = rb_funcall(ropts, oj_to_h_id, 0);
91
+ } else if (Qnil == ropts) {
92
+ return;
93
+ } else {
94
+ rb_raise(rb_eArgError, "options must be a hash.");
95
+ }
97
96
  }
98
97
  v = rb_hash_lookup(ropts, oj_max_nesting_sym);
99
98
  if (Qtrue == v) {
100
- copts->dump_opts.max_depth = 100;
99
+ copts->dump_opts.max_depth = 100;
101
100
  } else if (Qfalse == v || Qnil == v) {
102
- copts->dump_opts.max_depth = MAX_DEPTH;
101
+ copts->dump_opts.max_depth = MAX_DEPTH;
103
102
  } else if (T_FIXNUM == rb_type(v)) {
104
- copts->dump_opts.max_depth = NUM2INT(v);
105
- if (0 >= copts->dump_opts.max_depth) {
106
- copts->dump_opts.max_depth = MAX_DEPTH;
107
- }
103
+ copts->dump_opts.max_depth = NUM2INT(v);
104
+ if (0 >= copts->dump_opts.max_depth) {
105
+ copts->dump_opts.max_depth = MAX_DEPTH;
106
+ }
108
107
  }
109
108
  if (Qnil != (v = rb_hash_lookup(ropts, oj_allow_nan_sym))) {
110
- if (Qtrue == v) {
111
- copts->dump_opts.nan_dump = WordNan;
112
- } else {
113
- copts->dump_opts.nan_dump = RaiseNan;
114
- }
109
+ if (Qtrue == v) {
110
+ copts->dump_opts.nan_dump = WordNan;
111
+ } else {
112
+ copts->dump_opts.nan_dump = RaiseNan;
113
+ }
115
114
  }
116
115
  if (Qnil != (v = rb_hash_lookup(ropts, oj_indent_sym))) {
117
- rb_check_type(v, T_STRING);
118
- if (sizeof(copts->dump_opts.indent_str) <= (len = RSTRING_LEN(v))) {
119
- rb_raise(rb_eArgError, "indent string is limited to %lu characters.", (unsigned long)sizeof(copts->dump_opts.indent_str));
120
- }
121
- strcpy(copts->dump_opts.indent_str, StringValuePtr(v));
122
- copts->dump_opts.indent_size = (uint8_t)len;
123
- copts->dump_opts.use = true;
116
+ rb_check_type(v, T_STRING);
117
+ if (sizeof(copts->dump_opts.indent_str) <= (len = RSTRING_LEN(v))) {
118
+ rb_raise(rb_eArgError,
119
+ "indent string is limited to %lu characters.",
120
+ (unsigned long)sizeof(copts->dump_opts.indent_str));
121
+ }
122
+ strcpy(copts->dump_opts.indent_str, StringValuePtr(v));
123
+ copts->dump_opts.indent_size = (uint8_t)len;
124
+ copts->dump_opts.use = true;
124
125
  }
125
126
  if (Qnil != (v = rb_hash_lookup(ropts, oj_space_sym))) {
126
- rb_check_type(v, T_STRING);
127
- if (sizeof(copts->dump_opts.after_sep) <= (len = RSTRING_LEN(v))) {
128
- rb_raise(rb_eArgError, "space string is limited to %lu characters.", (unsigned long)sizeof(copts->dump_opts.after_sep));
129
- }
130
- strcpy(copts->dump_opts.after_sep, StringValuePtr(v));
131
- copts->dump_opts.after_size = (uint8_t)len;
132
- copts->dump_opts.use = true;
127
+ rb_check_type(v, T_STRING);
128
+ if (sizeof(copts->dump_opts.after_sep) <= (len = RSTRING_LEN(v))) {
129
+ rb_raise(rb_eArgError,
130
+ "space string is limited to %lu characters.",
131
+ (unsigned long)sizeof(copts->dump_opts.after_sep));
132
+ }
133
+ strcpy(copts->dump_opts.after_sep, StringValuePtr(v));
134
+ copts->dump_opts.after_size = (uint8_t)len;
135
+ copts->dump_opts.use = true;
133
136
  }
134
137
  if (Qnil != (v = rb_hash_lookup(ropts, oj_space_before_sym))) {
135
- rb_check_type(v, T_STRING);
136
- if (sizeof(copts->dump_opts.before_sep) <= (len = RSTRING_LEN(v))) {
137
- rb_raise(rb_eArgError, "space_before string is limited to %lu characters.", (unsigned long)sizeof(copts->dump_opts.before_sep));
138
- }
139
- strcpy(copts->dump_opts.before_sep, StringValuePtr(v));
140
- copts->dump_opts.before_size = (uint8_t)len;
141
- copts->dump_opts.use = true;
138
+ rb_check_type(v, T_STRING);
139
+ if (sizeof(copts->dump_opts.before_sep) <= (len = RSTRING_LEN(v))) {
140
+ rb_raise(rb_eArgError,
141
+ "space_before string is limited to %lu characters.",
142
+ (unsigned long)sizeof(copts->dump_opts.before_sep));
143
+ }
144
+ strcpy(copts->dump_opts.before_sep, StringValuePtr(v));
145
+ copts->dump_opts.before_size = (uint8_t)len;
146
+ copts->dump_opts.use = true;
142
147
  }
143
148
  if (Qnil != (v = rb_hash_lookup(ropts, oj_object_nl_sym))) {
144
- rb_check_type(v, T_STRING);
145
- if (sizeof(copts->dump_opts.hash_nl) <= (len = RSTRING_LEN(v))) {
146
- rb_raise(rb_eArgError, "object_nl string is limited to %lu characters.", (unsigned long)sizeof(copts->dump_opts.hash_nl));
147
- }
148
- strcpy(copts->dump_opts.hash_nl, StringValuePtr(v));
149
- copts->dump_opts.hash_size = (uint8_t)len;
150
- copts->dump_opts.use = true;
149
+ rb_check_type(v, T_STRING);
150
+ if (sizeof(copts->dump_opts.hash_nl) <= (len = RSTRING_LEN(v))) {
151
+ rb_raise(rb_eArgError,
152
+ "object_nl string is limited to %lu characters.",
153
+ (unsigned long)sizeof(copts->dump_opts.hash_nl));
154
+ }
155
+ strcpy(copts->dump_opts.hash_nl, StringValuePtr(v));
156
+ copts->dump_opts.hash_size = (uint8_t)len;
157
+ copts->dump_opts.use = true;
151
158
  }
152
159
  if (Qnil != (v = rb_hash_lookup(ropts, oj_array_nl_sym))) {
153
- rb_check_type(v, T_STRING);
154
- if (sizeof(copts->dump_opts.array_nl) <= (len = RSTRING_LEN(v))) {
155
- rb_raise(rb_eArgError, "array_nl string is limited to %lu characters.", (unsigned long)sizeof(copts->dump_opts.array_nl));
156
- }
157
- strcpy(copts->dump_opts.array_nl, StringValuePtr(v));
158
- copts->dump_opts.array_size = (uint8_t)len;
159
- copts->dump_opts.use = true;
160
+ rb_check_type(v, T_STRING);
161
+ if (sizeof(copts->dump_opts.array_nl) <= (len = RSTRING_LEN(v))) {
162
+ rb_raise(rb_eArgError,
163
+ "array_nl string is limited to %lu characters.",
164
+ (unsigned long)sizeof(copts->dump_opts.array_nl));
165
+ }
166
+ strcpy(copts->dump_opts.array_nl, StringValuePtr(v));
167
+ copts->dump_opts.array_size = (uint8_t)len;
168
+ copts->dump_opts.use = true;
160
169
  }
161
170
  if (Qnil != (v = rb_hash_lookup(ropts, oj_quirks_mode_sym))) {
162
- copts->quirks_mode = (Qtrue == v) ? Yes : No;
171
+ copts->quirks_mode = (Qtrue == v) ? Yes : No;
163
172
  }
164
173
  if (Qnil != (v = rb_hash_lookup(ropts, oj_ascii_only_sym))) {
165
- // generate seems to assume anything except nil and false are true.
166
- if (Qfalse == v) {
167
- copts->escape_mode = JXEsc;
168
- } else {
169
- copts->escape_mode = ASCIIEsc;
170
- }
174
+ // generate seems to assume anything except nil and false are true.
175
+ if (Qfalse == v) {
176
+ copts->escape_mode = JXEsc;
177
+ } else {
178
+ copts->escape_mode = ASCIIEsc;
179
+ }
171
180
  }
172
181
  }
173
182
 
174
- static int
175
- mimic_limit_arg(VALUE a) {
183
+ static int mimic_limit_arg(VALUE a) {
176
184
  if (Qnil == a || T_FIXNUM != rb_type(a)) {
177
- return -1;
185
+ return -1;
178
186
  }
179
187
  return NUM2INT(a);
180
188
  }
@@ -190,44 +198,41 @@ mimic_limit_arg(VALUE a) {
190
198
  *
191
199
  * Returns [_String_] a JSON string.
192
200
  */
193
- static VALUE
194
- mimic_dump(int argc, VALUE *argv, VALUE self) {
195
- char buf[4096];
196
- struct _out out;
197
- struct _options copts = oj_default_options;
198
- VALUE rstr;
199
- VALUE active_hack[1];
201
+ static VALUE mimic_dump(int argc, VALUE *argv, VALUE self) {
202
+ struct _out out;
203
+ struct _options copts = oj_default_options;
204
+ VALUE rstr;
205
+ VALUE active_hack[1];
200
206
 
201
207
  copts.str_rx.head = NULL;
202
208
  copts.str_rx.tail = NULL;
203
- out.buf = buf;
204
- out.end = buf + sizeof(buf) - 10;
205
- out.allocated = false;
206
- out.caller = CALLER_DUMP;
209
+
210
+ oj_out_init(&out);
211
+
207
212
  copts.escape_mode = JXEsc;
208
- copts.mode = CompatMode;
213
+ copts.mode = CompatMode;
209
214
 
210
215
  /* seems like this is not correct
211
216
  if (No == copts.nilnil && Qnil == *argv) {
212
- rb_raise(rb_eTypeError, "nil not allowed.");
217
+ rb_raise(rb_eTypeError, "nil not allowed.");
213
218
  }
214
219
  */
215
- copts.dump_opts.max_depth = MAX_DEPTH; // when using dump there is no limit
216
- out.omit_nil = copts.dump_opts.omit_nil;
220
+ copts.dump_opts.max_depth = MAX_DEPTH; // when using dump there is no limit
221
+ out.omit_nil = copts.dump_opts.omit_nil;
217
222
 
218
223
  if (2 <= argc) {
219
- int limit;
220
-
221
- // The json gem take a more liberal approach to optional
222
- // arguments. Expected are (obj, anIO=nil, limit=nil) yet the io
223
- // argument can be left off completely and the 2nd argument is then
224
- // the limit.
225
- if (0 <= (limit = mimic_limit_arg(argv[1]))) {
226
- copts.dump_opts.max_depth = limit;
227
- }
228
- if (3 <= argc && 0 <= (limit = mimic_limit_arg(argv[2]))) {
229
- copts.dump_opts.max_depth = limit;
230
- }
224
+ int limit;
225
+
226
+ // The json gem take a more liberal approach to optional
227
+ // arguments. Expected are (obj, anIO=nil, limit=nil) yet the io
228
+ // argument can be left off completely and the 2nd argument is then
229
+ // the limit.
230
+ if (0 <= (limit = mimic_limit_arg(argv[1]))) {
231
+ copts.dump_opts.max_depth = limit;
232
+ }
233
+ if (3 <= argc && 0 <= (limit = mimic_limit_arg(argv[2]))) {
234
+ copts.dump_opts.max_depth = limit;
235
+ }
231
236
  }
232
237
  // ActiveSupport in active_support/core_ext/object/json.rb check the
233
238
  // optional argument type to to_json and it the argument is a
@@ -239,53 +244,48 @@ mimic_dump(int argc, VALUE *argv, VALUE self) {
239
244
  oj_dump_obj_to_json_using_params(*argv, &copts, &out, 1, active_hack);
240
245
 
241
246
  if (0 == out.buf) {
242
- rb_raise(rb_eNoMemError, "Not enough memory.");
247
+ rb_raise(rb_eNoMemError, "Not enough memory.");
243
248
  }
244
249
  rstr = rb_str_new2(out.buf);
245
250
  rstr = oj_encode(rstr);
246
251
  if (2 <= argc && Qnil != argv[1] && rb_respond_to(argv[1], oj_write_id)) {
247
- VALUE io = argv[1];
248
- VALUE args[1];
252
+ VALUE io = argv[1];
253
+ VALUE args[1];
249
254
 
250
- *args = rstr;
251
- rb_funcall2(io, oj_write_id, 1, args);
252
- rstr = io;
253
- }
254
- if (out.allocated) {
255
- xfree(out.buf);
255
+ *args = rstr;
256
+ rb_funcall2(io, oj_write_id, 1, args);
257
+ rstr = io;
256
258
  }
259
+
260
+ oj_out_free(&out);
261
+
257
262
  return rstr;
258
263
  }
259
264
 
260
265
  // This is the signature for the hash_foreach callback also.
261
- static int
262
- mimic_walk(VALUE key, VALUE obj, VALUE proc) {
266
+ static int mimic_walk(VALUE key, VALUE obj, VALUE proc) {
263
267
  switch (rb_type(obj)) {
264
- case T_HASH:
265
- rb_hash_foreach(obj, mimic_walk, proc);
266
- break;
267
- case T_ARRAY:
268
- {
269
- size_t cnt = RARRAY_LEN(obj);
270
- size_t i;
271
-
272
- for (i = 0; i < cnt; i++) {
273
- mimic_walk(Qnil, rb_ary_entry(obj, i), proc);
274
- }
275
- break;
276
- }
277
- default:
278
- break;
268
+ case T_HASH: rb_hash_foreach(obj, mimic_walk, proc); break;
269
+ case T_ARRAY: {
270
+ size_t cnt = RARRAY_LEN(obj);
271
+ size_t i;
272
+
273
+ for (i = 0; i < cnt; i++) {
274
+ mimic_walk(Qnil, RARRAY_AREF(obj, i), proc);
275
+ }
276
+ break;
277
+ }
278
+ default: break;
279
279
  }
280
280
  if (Qnil == proc) {
281
- if (rb_block_given_p()) {
282
- rb_yield(obj);
283
- }
281
+ if (rb_block_given_p()) {
282
+ rb_yield(obj);
283
+ }
284
284
  } else {
285
- VALUE args[1];
285
+ VALUE args[1];
286
286
 
287
- *args = obj;
288
- rb_proc_call_with_block(proc, 1, args, Qnil);
287
+ *args = obj;
288
+ rb_proc_call_with_block(proc, 1, args, Qnil);
289
289
  }
290
290
  return ST_CONTINUE;
291
291
  }
@@ -315,20 +315,19 @@ mimic_walk(VALUE key, VALUE obj, VALUE proc) {
315
315
  *
316
316
  * Returns [_Object_] the decode Object.
317
317
  */
318
- static VALUE
319
- mimic_load(int argc, VALUE *argv, VALUE self) {
320
- VALUE obj;
321
- VALUE p = Qnil;
318
+ static VALUE mimic_load(int argc, VALUE *argv, VALUE self) {
319
+ VALUE obj;
320
+ VALUE p = Qnil;
322
321
 
323
322
  obj = oj_compat_load(argc, argv, self);
324
323
  if (2 <= argc) {
325
- if (rb_cProc == rb_obj_class(argv[1])) {
326
- p = argv[1];
327
- } else if (3 <= argc) {
328
- if (rb_cProc == rb_obj_class(argv[2])) {
329
- p = argv[2];
330
- }
331
- }
324
+ if (rb_cProc == rb_obj_class(argv[1])) {
325
+ p = argv[1];
326
+ } else if (3 <= argc) {
327
+ if (rb_cProc == rb_obj_class(argv[2])) {
328
+ p = argv[2];
329
+ }
330
+ }
332
331
  }
333
332
  mimic_walk(Qnil, obj, p);
334
333
 
@@ -346,54 +345,62 @@ mimic_load(int argc, VALUE *argv, VALUE self) {
346
345
  *
347
346
  * Returns [_Object_]
348
347
  */
349
- static VALUE
350
- mimic_dump_load(int argc, VALUE *argv, VALUE self) {
348
+ static VALUE mimic_dump_load(int argc, VALUE *argv, VALUE self) {
351
349
  if (1 > argc) {
352
- rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)");
353
- } else if (T_STRING == rb_type(*argv)) {
354
- return mimic_load(argc, argv, self);
355
- } else {
356
- return mimic_dump(argc, argv, self);
350
+ rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)");
357
351
  }
358
- return Qnil;
352
+ if (T_STRING == rb_type(*argv)) {
353
+ return mimic_load(argc, argv, self);
354
+ }
355
+ return mimic_dump(argc, argv, self);
359
356
  }
360
357
 
361
- static VALUE
362
- mimic_generate_core(int argc, VALUE *argv, Options copts) {
363
- char buf[4096];
364
- struct _out out;
365
- VALUE rstr;
358
+ static VALUE mimic_generate_core(int argc, VALUE *argv, Options copts) {
359
+ struct _out out;
360
+ VALUE rstr;
361
+
362
+ if (0 == argc) {
363
+ rb_raise(rb_eArgError, "wrong number of arguments (0))");
364
+ }
365
+ memset(out.stack_buffer, 0, sizeof(out.stack_buffer));
366
366
 
367
- memset(buf, 0, sizeof(buf));
367
+ oj_out_init(&out);
368
368
 
369
- out.buf = buf;
370
- out.end = buf + sizeof(buf) - 10;
371
- out.allocated = false;
372
369
  out.omit_nil = copts->dump_opts.omit_nil;
373
- out.caller = CALLER_GENERATE;
374
370
  // For obj.to_json or generate nan is not allowed but if called from dump
375
371
  // it is.
376
372
  copts->dump_opts.nan_dump = RaiseNan;
377
- copts->mode = CompatMode;
378
- copts->to_json = Yes;
373
+ copts->mode = CompatMode;
374
+ copts->to_json = Yes;
379
375
  if (2 == argc && Qnil != argv[1]) {
380
- oj_parse_mimic_dump_options(argv[1], copts);
376
+ oj_parse_mimic_dump_options(argv[1], copts);
381
377
  }
382
378
  /* seems like this is not correct
383
379
  if (No == copts->nilnil && Qnil == *argv) {
384
- rb_raise(rb_eTypeError, "nil not allowed.");
380
+ rb_raise(rb_eTypeError, "nil not allowed.");
385
381
  }
386
382
  */
387
- oj_dump_obj_to_json_using_params(*argv, copts, &out, argc - 1, argv + 1);
383
+ if (1 < argc) {
384
+ oj_dump_obj_to_json_using_params(*argv, copts, &out, argc - 1, argv + 1);
385
+ } else {
386
+ VALUE active_hack[1];
388
387
 
388
+ if (Qundef == state_class) {
389
+ rb_warn("Oj::Rails.mimic_JSON was called implicitly. "
390
+ "Call it explicitly beforehand if you want to remove this warning.");
391
+ oj_define_mimic_json(0, NULL, Qnil);
392
+ }
393
+ active_hack[0] = rb_funcall(state_class, oj_new_id, 0);
394
+ oj_dump_obj_to_json_using_params(*argv, copts, &out, 1, active_hack);
395
+ }
389
396
  if (0 == out.buf) {
390
- rb_raise(rb_eNoMemError, "Not enough memory.");
397
+ rb_raise(rb_eNoMemError, "Not enough memory.");
391
398
  }
392
399
  rstr = rb_str_new2(out.buf);
393
400
  rstr = oj_encode(rstr);
394
- if (out.allocated) {
395
- xfree(out.buf);
396
- }
401
+
402
+ oj_out_free(&out);
403
+
397
404
  return rstr;
398
405
  }
399
406
 
@@ -417,13 +424,14 @@ mimic_generate_core(int argc, VALUE *argv, Options copts) {
417
424
  * - *:space_before* [_String_] String placed before a : delimiter
418
425
  * - *:object_nl* [_String_] String placed after a JSON object
419
426
  * - *:array_nl* [_String_] String placed after a JSON array
420
- * - *:ascii_only* [_Boolean_] if not nil or false then use only ascii characters in the output. Note JSON.generate does support this even if it is not documented.
427
+ * - *:ascii_only* [_Boolean_] if not nil or false then use only ascii characters in the output.
428
+ * Note JSON.generate does support this even if it is not documented.
421
429
  *
422
430
  * Returns [_String_] generated JSON.
423
431
  */
424
432
  VALUE
425
433
  oj_mimic_generate(int argc, VALUE *argv, VALUE self) {
426
- struct _options copts = oj_default_options;
434
+ struct _options copts = oj_default_options;
427
435
 
428
436
  copts.str_rx.head = NULL;
429
437
  copts.str_rx.tail = NULL;
@@ -441,33 +449,41 @@ oj_mimic_generate(int argc, VALUE *argv, VALUE self) {
441
449
  */
442
450
  VALUE
443
451
  oj_mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
444
- struct _options copts = oj_default_options;
445
- VALUE rargs[2];
446
- volatile VALUE h;
452
+ struct _options copts = oj_default_options;
453
+ VALUE rargs[2];
454
+ volatile VALUE h;
447
455
 
448
456
  // Some (all?) json gem to_json methods need a State instance and not just
449
457
  // a Hash. I haven't dug deep enough to find out why but using a State
450
458
  // instance and not a Hash gives the desired behavior.
451
459
  *rargs = *argv;
452
- if (1 == argc) {
453
- h = rb_hash_new();
460
+ if (0 == argc) {
461
+ rb_raise(rb_eArgError, "wrong number of arguments (0))");
462
+ }
463
+ if (1 == argc || Qnil == argv[1]) {
464
+ h = rb_hash_new();
454
465
  } else {
455
- h = argv[1];
466
+ h = argv[1];
467
+ }
468
+ if (!oj_hash_has_key(h, oj_indent_sym)) {
469
+ rb_hash_aset(h, oj_indent_sym, rb_str_new2(" "));
456
470
  }
457
- if (Qfalse == rb_funcall(h, oj_has_key_id, 1, oj_indent_sym)) {
458
- rb_hash_aset(h, oj_indent_sym, rb_str_new2(" "));
471
+ if (!oj_hash_has_key(h, oj_space_before_sym)) {
472
+ rb_hash_aset(h, oj_space_before_sym, rb_str_new2(""));
459
473
  }
460
- if (Qfalse == rb_funcall(h, oj_has_key_id, 1, oj_space_before_sym)) {
461
- rb_hash_aset(h, oj_space_before_sym, rb_str_new2(""));
474
+ if (!oj_hash_has_key(h, oj_space_sym)) {
475
+ rb_hash_aset(h, oj_space_sym, rb_str_new2(" "));
462
476
  }
463
- if (Qfalse == rb_funcall(h, oj_has_key_id, 1, oj_space_sym)) {
464
- rb_hash_aset(h, oj_space_sym, rb_str_new2(" "));
477
+ if (!oj_hash_has_key(h, oj_object_nl_sym)) {
478
+ rb_hash_aset(h, oj_object_nl_sym, rb_str_new2("\n"));
465
479
  }
466
- if (Qfalse == rb_funcall(h, oj_has_key_id, 1, oj_object_nl_sym)) {
467
- rb_hash_aset(h, oj_object_nl_sym, rb_str_new2("\n"));
480
+ if (!oj_hash_has_key(h, oj_array_nl_sym)) {
481
+ rb_hash_aset(h, oj_array_nl_sym, rb_str_new2("\n"));
468
482
  }
469
- if (Qfalse == rb_funcall(h, oj_has_key_id, 1, oj_array_nl_sym)) {
470
- rb_hash_aset(h, oj_array_nl_sym, rb_str_new2("\n"));
483
+ if (Qundef == state_class) {
484
+ rb_warn("Oj::Rails.mimic_JSON was called implicitly. "
485
+ "Call it explicitly beforehand if you want to remove this warning.");
486
+ oj_define_mimic_json(0, NULL, Qnil);
471
487
  }
472
488
  rargs[1] = rb_funcall(state_class, oj_new_id, 1, h);
473
489
 
@@ -483,104 +499,99 @@ oj_mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
483
499
  copts.dump_opts.hash_size = (uint8_t)strlen(copts.dump_opts.hash_nl);
484
500
  strcpy(copts.dump_opts.array_nl, "\n");
485
501
  copts.dump_opts.array_size = (uint8_t)strlen(copts.dump_opts.array_nl);
486
- copts.dump_opts.use = true;
502
+ copts.dump_opts.use = true;
487
503
 
488
504
  return mimic_generate_core(2, rargs, &copts);
489
505
  }
490
506
 
491
- static VALUE
492
- mimic_parse_core(int argc, VALUE *argv, VALUE self, bool bang) {
493
- struct _parseInfo pi;
494
- VALUE ropts;
495
- VALUE args[1];
507
+ static int parse_options_cb(VALUE k, VALUE v, VALUE info) {
508
+ struct _parseInfo *pi = (struct _parseInfo *)info;
509
+
510
+ if (oj_symbolize_names_sym == k) {
511
+ pi->options.sym_key = (Qtrue == v) ? Yes : No;
512
+ } else if (oj_quirks_mode_sym == k) {
513
+ pi->options.quirks_mode = (Qtrue == v) ? Yes : No;
514
+ } else if (oj_create_additions_sym == k) {
515
+ pi->options.create_ok = (Qtrue == v) ? Yes : No;
516
+ } else if (oj_allow_nan_sym == k) {
517
+ pi->options.allow_nan = (Qtrue == v) ? Yes : No;
518
+ } else if (oj_hash_class_sym == k) {
519
+ if (Qnil == v) {
520
+ pi->options.hash_class = Qnil;
521
+ } else {
522
+ rb_check_type(v, T_CLASS);
523
+ pi->options.hash_class = v;
524
+ }
525
+ } else if (oj_object_class_sym == k) {
526
+ if (Qnil == v) {
527
+ pi->options.hash_class = Qnil;
528
+ } else {
529
+ rb_check_type(v, T_CLASS);
530
+ pi->options.hash_class = v;
531
+ }
532
+ } else if (oj_array_class_sym == k) {
533
+ if (Qnil == v) {
534
+ pi->options.array_class = Qnil;
535
+ } else {
536
+ rb_check_type(v, T_CLASS);
537
+ pi->options.array_class = v;
538
+ }
539
+ } else if (oj_decimal_class_sym == k) {
540
+ pi->options.compat_bigdec = (oj_bigdecimal_class == v);
541
+ }
542
+ return ST_CONTINUE;
543
+ }
544
+
545
+ static VALUE mimic_parse_core(int argc, VALUE *argv, VALUE self, bool bang) {
546
+ struct _parseInfo pi;
547
+ VALUE ropts;
548
+ VALUE args[1];
496
549
 
497
550
  rb_scan_args(argc, argv, "11", NULL, &ropts);
498
551
  parse_info_init(&pi);
499
552
  oj_set_compat_callbacks(&pi);
500
553
 
501
554
  pi.err_class = oj_json_parser_error_class;
502
- //pi.err_class = Qnil;
503
-
504
- pi.options = oj_default_options;
505
- pi.options.auto_define = No;
506
- pi.options.quirks_mode = Yes;
507
- pi.options.allow_invalid = No;
508
- pi.options.empty_string = No;
509
- pi.options.create_ok = No;
510
- pi.options.allow_nan = (bang ? Yes : No);
511
- pi.options.nilnil = No;
512
- pi.options.bigdec_load = RubyDec;
513
- pi.options.mode = CompatMode;
514
- pi.max_depth = 100;
555
+ // pi.err_class = Qnil;
556
+
557
+ pi.options = oj_default_options;
558
+ pi.options.auto_define = No;
559
+ pi.options.quirks_mode = Yes;
560
+ pi.options.allow_invalid = Yes;
561
+ pi.options.empty_string = No;
562
+ pi.options.create_ok = No;
563
+ pi.options.allow_nan = (bang ? Yes : No);
564
+ pi.options.nilnil = No;
565
+ pi.options.bigdec_load = RubyDec;
566
+ pi.options.mode = CompatMode;
567
+ pi.max_depth = 100;
515
568
 
516
569
  if (Qnil != ropts) {
517
- VALUE v;
518
-
519
- if (T_HASH != rb_type(ropts)) {
520
- rb_raise(rb_eArgError, "options must be a hash.");
521
- }
522
- if (Qundef == symbolize_names_sym) {
523
- symbolize_names_sym = ID2SYM(rb_intern("symbolize_names")); rb_gc_register_address(&symbolize_names_sym);
524
- }
525
- if (Qnil != (v = rb_hash_lookup(ropts, symbolize_names_sym))) {
526
- pi.options.sym_key = (Qtrue == v) ? Yes : No;
527
- }
528
- if (Qnil != (v = rb_hash_lookup(ropts, oj_quirks_mode_sym))) {
529
- pi.options.quirks_mode = (Qtrue == v) ? Yes : No;
530
- }
531
- if (Qnil != (v = rb_hash_lookup(ropts, oj_create_additions_sym))) {
532
- pi.options.create_ok = (Qtrue == v) ? Yes : No;
533
- }
534
- if (Qnil != (v = rb_hash_lookup(ropts, oj_allow_nan_sym))) {
535
- pi.options.allow_nan = (Qtrue == v) ? Yes : No;
536
- }
537
-
538
- if (Qtrue == rb_funcall(ropts, oj_has_key_id, 1, oj_hash_class_sym)) {
539
- if (Qnil == (v = rb_hash_lookup(ropts, oj_hash_class_sym))) {
540
- pi.options.hash_class = Qnil;
541
- } else {
542
- rb_check_type(v, T_CLASS);
543
- pi.options.hash_class = v;
544
- }
545
- }
546
- if (Qtrue == rb_funcall(ropts, oj_has_key_id, 1, oj_object_class_sym)) {
547
- if (Qnil == (v = rb_hash_lookup(ropts, oj_object_class_sym))) {
548
- pi.options.hash_class = Qnil;
549
- } else {
550
- rb_check_type(v, T_CLASS);
551
- pi.options.hash_class = v;
552
- }
553
- }
554
- if (Qtrue == rb_funcall(ropts, oj_has_key_id, 1, oj_array_class_sym)) {
555
- if (Qnil == (v = rb_hash_lookup(ropts, oj_array_class_sym))) {
556
- pi.options.array_class = Qnil;
557
- } else {
558
- rb_check_type(v, T_CLASS);
559
- pi.options.array_class = v;
560
- }
561
- }
562
- if (Qtrue == rb_funcall(ropts, oj_has_key_id, 1, oj_decimal_class_sym)) {
563
- pi.options.compat_bigdec = (oj_bigdecimal_class == rb_hash_lookup(ropts, oj_decimal_class_sym));
564
- }
565
- v = rb_hash_lookup(ropts, oj_max_nesting_sym);
566
- if (Qtrue == v) {
567
- pi.max_depth = 100;
568
- } else if (Qfalse == v || Qnil == v) {
569
- pi.max_depth = 0;
570
- } else if (T_FIXNUM == rb_type(v)) {
571
- pi.max_depth = NUM2INT(v);
572
- }
573
- oj_parse_opt_match_string(&pi.options.str_rx, ropts);
574
- if (Yes == pi.options.create_ok && Yes == pi.options.sym_key) {
575
- rb_raise(rb_eArgError, ":symbolize_names and :create_additions can not both be true.");
576
- }
570
+ VALUE v;
571
+
572
+ if (T_HASH != rb_type(ropts)) {
573
+ rb_raise(rb_eArgError, "options must be a hash.");
574
+ }
575
+ rb_hash_foreach(ropts, parse_options_cb, (VALUE)&pi);
576
+ v = rb_hash_lookup(ropts, oj_max_nesting_sym);
577
+ if (Qtrue == v) {
578
+ pi.max_depth = 100;
579
+ } else if (Qfalse == v || Qnil == v) {
580
+ pi.max_depth = 0;
581
+ } else if (T_FIXNUM == rb_type(v)) {
582
+ pi.max_depth = NUM2INT(v);
583
+ }
584
+ oj_parse_opt_match_string(&pi.options.str_rx, ropts);
585
+ if (Yes == pi.options.create_ok && Yes == pi.options.sym_key) {
586
+ rb_raise(rb_eArgError, ":symbolize_names and :create_additions can not both be true.");
587
+ }
577
588
  }
578
589
  *args = *argv;
579
590
 
580
591
  if (T_STRING == rb_type(*args)) {
581
- return oj_pi_parse(1, args, &pi, 0, 0, false);
592
+ return oj_pi_parse(1, args, &pi, 0, 0, false);
582
593
  } else {
583
- return oj_pi_sparse(1, args, &pi, 0);
594
+ return oj_pi_sparse(1, args, &pi, 0);
584
595
  }
585
596
  }
586
597
 
@@ -593,8 +604,10 @@ mimic_parse_core(int argc, VALUE *argv, VALUE self, bool bang) {
593
604
  *
594
605
  * - *source* [_String_|IO] source to parse
595
606
  * - *opts* [_Hash_] options
596
- * - *:symbolize* [Boolean] _names flag indicating JSON object keys should be Symbols instead of Strings
597
- * - *:create_additions* [Boolean] flag indicating a key matching +create_id+ in a JSON object should trigger the creation of Ruby Object
607
+ * - *:symbolize* [Boolean] _names flag indicating JSON object keys should be Symbols instead of
608
+ * Strings
609
+ * - *:create_additions* [Boolean] flag indicating a key matching +create_id+ in a JSON object
610
+ * should trigger the creation of Ruby Object
598
611
  *
599
612
  * Returns [Object]
600
613
  * @see create_id=
@@ -610,8 +623,7 @@ oj_mimic_parse(int argc, VALUE *argv, VALUE self) {
610
623
  * Same as parse().
611
624
  * @see parse
612
625
  */
613
- static VALUE
614
- mimic_parse_bang(int argc, VALUE *argv, VALUE self) {
626
+ static VALUE mimic_parse_bang(int argc, VALUE *argv, VALUE self) {
615
627
  return mimic_parse_core(argc, argv, self, true);
616
628
  }
617
629
 
@@ -623,8 +635,7 @@ mimic_parse_bang(int argc, VALUE *argv, VALUE self) {
623
635
  * - *obj* [_Hash_|Array] object to walk
624
636
  * - *proc* [_Proc_] to yield to on each element
625
637
  */
626
- static VALUE
627
- mimic_recurse_proc(VALUE self, VALUE obj) {
638
+ static VALUE mimic_recurse_proc(VALUE self, VALUE obj) {
628
639
  rb_need_block();
629
640
  mimic_walk(Qnil, obj, Qnil);
630
641
 
@@ -639,25 +650,23 @@ mimic_recurse_proc(VALUE self, VALUE obj) {
639
650
  *
640
651
  * - *id* [_nil_|String] new create_id
641
652
  *
642
- * Returns [_String_] the id.
653
+ * Returns [_nil_|_String_] the id.
643
654
  */
644
- static VALUE
645
- mimic_set_create_id(VALUE self, VALUE id) {
646
- Check_Type(id, T_STRING);
647
-
655
+ static VALUE mimic_set_create_id(VALUE self, VALUE id) {
648
656
  if (NULL != oj_default_options.create_id) {
649
- if (oj_json_class != oj_default_options.create_id) {
650
- xfree((char*)oj_default_options.create_id);
651
- }
652
- oj_default_options.create_id = NULL;
653
- oj_default_options.create_id_len = 0;
657
+ if (oj_json_class != oj_default_options.create_id) {
658
+ OJ_R_FREE((char *)oj_default_options.create_id);
659
+ }
660
+ oj_default_options.create_id = NULL;
661
+ oj_default_options.create_id_len = 0;
654
662
  }
655
663
  if (Qnil != id) {
656
- size_t len = RSTRING_LEN(id) + 1;
664
+ const char *ptr = StringValueCStr(id);
665
+ size_t len = RSTRING_LEN(id) + 1;
657
666
 
658
- oj_default_options.create_id = ALLOC_N(char, len);
659
- strcpy((char*)oj_default_options.create_id, StringValuePtr(id));
660
- oj_default_options.create_id_len = len - 1;
667
+ oj_default_options.create_id = OJ_R_ALLOC_N(char, len);
668
+ strcpy((char *)oj_default_options.create_id, ptr);
669
+ oj_default_options.create_id_len = len - 1;
661
670
  }
662
671
  return id;
663
672
  }
@@ -667,103 +676,103 @@ mimic_set_create_id(VALUE self, VALUE id) {
667
676
  *
668
677
  * Returns [_String_] the create_id.
669
678
  */
670
- static VALUE
671
- mimic_create_id(VALUE self) {
679
+ static VALUE mimic_create_id(VALUE self) {
672
680
  if (NULL != oj_default_options.create_id) {
673
- return oj_encode(rb_str_new_cstr(oj_default_options.create_id));
681
+ return rb_utf8_str_new(oj_default_options.create_id, oj_default_options.create_id_len);
674
682
  }
675
683
  return rb_str_new_cstr(oj_json_class);
676
684
  }
677
685
 
678
- static struct _options mimic_object_to_json_options = {
679
- 0, // indent
680
- No, // circular
681
- No, // auto_define
682
- No, // sym_key
683
- JXEsc, // escape_mode
684
- CompatMode, // mode
685
- No, // class_cache
686
- RubyTime, // time_format
687
- No, // bigdec_as_num
688
- RubyDec, // bigdec_load
689
- false, // compat_bigdec
690
- No, // to_hash
691
- No, // to_json
692
- No, // as_json
693
- No, // raw_json
694
- No, // nilnil
695
- No, // empty_string
696
- Yes, // allow_gc
697
- Yes, // quirks_mode
698
- No, // allow_invalid
699
- No, // create_ok
700
- No, // allow_nan
701
- No, // trace
702
- No, // safe
703
- false, // sec_prec_set
704
- No, // ignore_under
705
- 0, // int_range_min
706
- 0, // int_range_max
707
- oj_json_class,// create_id
708
- 10, // create_id_len
709
- 3, // sec_prec
710
- 0, // float_prec
711
- "%0.16g", // float_fmt
712
- Qnil, // hash_class
713
- Qnil, // array_class
714
- { // dump_opts
715
- false, //use
716
- "", // indent
717
- "", // before_sep
718
- "", // after_sep
719
- "", // hash_nl
720
- "", // array_nl
721
- 0, // indent_size
722
- 0, // before_size
723
- 0, // after_size
724
- 0, // hash_size
725
- 0, // array_size
726
- RaiseNan,// nan_dump
727
- false, // omit_nil
728
- 100, // max_depth
729
- },
730
- { // str_rx
731
- NULL, // head
732
- NULL, // tail
733
- { '\0' }, // err
734
- }
735
- };
736
-
737
- static VALUE
738
- mimic_object_to_json(int argc, VALUE *argv, VALUE self) {
739
- char buf[4096];
740
- struct _out out;
741
- VALUE rstr;
742
- struct _options copts = oj_default_options;
686
+ static struct _options mimic_object_to_json_options = {0, // indent
687
+ No, // circular
688
+ No, // auto_define
689
+ No, // sym_key
690
+ JXEsc, // escape_mode
691
+ CompatMode, // mode
692
+ No, // class_cache
693
+ RubyTime, // time_format
694
+ No, // bigdec_as_num
695
+ RubyDec, // bigdec_load
696
+ false, // compat_bigdec
697
+ No, // to_hash
698
+ No, // to_json
699
+ No, // as_json
700
+ No, // raw_json
701
+ No, // nilnil
702
+ No, // empty_string
703
+ Yes, // allow_gc
704
+ Yes, // quirks_mode
705
+ Yes, // allow_invalid
706
+ No, // create_ok
707
+ No, // allow_nan
708
+ No, // trace
709
+ No, // safe
710
+ false, // sec_prec_set
711
+ No, // ignore_under
712
+ Yes, // cache_keys
713
+ 0, // cache_str
714
+ 0, // int_range_min
715
+ 0, // int_range_max
716
+ oj_json_class, // create_id
717
+ 10, // create_id_len
718
+ 3, // sec_prec
719
+ 0, // float_prec
720
+ "%0.16g", // float_fmt
721
+ Qnil, // hash_class
722
+ Qnil, // array_class
723
+ {
724
+ // dump_opts
725
+ false, // use
726
+ "", // indent
727
+ "", // before_sep
728
+ "", // after_sep
729
+ "", // hash_nl
730
+ "", // array_nl
731
+ 0, // indent_size
732
+ 0, // before_size
733
+ 0, // after_size
734
+ 0, // hash_size
735
+ 0, // array_size
736
+ RaiseNan, // nan_dump
737
+ false, // omit_nil
738
+ false, // omit_null_byte
739
+ 100, // max_depth
740
+ },
741
+ {
742
+ // str_rx
743
+ NULL, // head
744
+ NULL, // tail
745
+ {'\0'}, // err
746
+ }};
747
+
748
+ static VALUE mimic_object_to_json(int argc, VALUE *argv, VALUE self) {
749
+ struct _out out;
750
+ VALUE rstr;
751
+ struct _options copts = oj_default_options;
743
752
 
744
753
  copts.str_rx.head = NULL;
745
754
  copts.str_rx.tail = NULL;
746
- out.buf = buf;
747
- out.end = buf + sizeof(buf) - 10;
748
- out.allocated = false;
749
- out.omit_nil = copts.dump_opts.omit_nil;
750
- copts.mode = CompatMode;
755
+
756
+ oj_out_init(&out);
757
+
758
+ out.omit_nil = copts.dump_opts.omit_nil;
759
+ copts.mode = CompatMode;
751
760
  copts.to_json = No;
752
761
  if (1 <= argc && Qnil != argv[0]) {
753
- oj_parse_mimic_dump_options(argv[0], &copts);
762
+ oj_parse_mimic_dump_options(argv[0], &copts);
754
763
  }
755
764
  // To be strict the mimic_object_to_json_options should be used but people
756
765
  // seem to prefer the option of changing that.
757
- //oj_dump_obj_to_json(self, &mimic_object_to_json_options, &out);
766
+ // oj_dump_obj_to_json(self, &mimic_object_to_json_options, &out);
758
767
  oj_dump_obj_to_json_using_params(self, &copts, &out, argc, argv);
759
- if (0 == out.buf) {
760
- rb_raise(rb_eNoMemError, "Not enough memory.");
768
+ if (NULL == out.buf) {
769
+ rb_raise(rb_eNoMemError, "Not enough memory.");
761
770
  }
762
771
  rstr = rb_str_new2(out.buf);
763
772
  rstr = oj_encode(rstr);
764
- if (out.allocated) {
765
- xfree(out.buf);
766
- }
773
+
774
+ oj_out_free(&out);
775
+
767
776
  return rstr;
768
777
  }
769
778
 
@@ -772,38 +781,56 @@ mimic_object_to_json(int argc, VALUE *argv, VALUE self) {
772
781
  *
773
782
  * Returns [_JSON::State_] the JSON::State class.
774
783
  */
775
- static VALUE
776
- mimic_state(VALUE self) {
784
+ static VALUE mimic_state(VALUE self) {
777
785
  return state_class;
778
786
  }
779
787
 
780
- void
781
- oj_mimic_json_methods(VALUE json) {
782
- VALUE json_error;
783
- VALUE generator;
784
- VALUE ext;
788
+ void oj_mimic_json_methods(VALUE json) {
789
+ VALUE json_error;
790
+ VALUE generator;
791
+ VALUE ext;
792
+ VALUE verbose;
793
+
794
+ // rb_undef_method doesn't work for modules or maybe sometimes
795
+ // doesn't. Anyway setting verbose should hide the warning.
796
+ verbose = rb_gv_get("$VERBOSE");
797
+ rb_gv_set("$VERBOSE", Qfalse);
785
798
 
799
+ rb_undef_method(json, "create_id=");
786
800
  rb_define_module_function(json, "create_id=", mimic_set_create_id, 1);
801
+ rb_undef_method(json, "create_id");
787
802
  rb_define_module_function(json, "create_id", mimic_create_id, 0);
788
803
 
804
+ rb_undef_method(json, "dump");
789
805
  rb_define_module_function(json, "dump", mimic_dump, -1);
806
+ rb_undef_method(json, "load");
790
807
  rb_define_module_function(json, "load", mimic_load, -1);
791
808
  rb_define_module_function(json, "restore", mimic_load, -1);
809
+ rb_undef_method(json, "recurse_proc");
792
810
  rb_define_module_function(json, "recurse_proc", mimic_recurse_proc, 1);
811
+ rb_undef_method(json, "[]");
793
812
  rb_define_module_function(json, "[]", mimic_dump_load, -1);
794
813
 
814
+ rb_undef_method(json, "generate");
795
815
  rb_define_module_function(json, "generate", oj_mimic_generate, -1);
816
+ rb_undef_method(json, "fast_generate");
796
817
  rb_define_module_function(json, "fast_generate", oj_mimic_generate, -1);
818
+ rb_undef_method(json, "pretty_generate");
797
819
  rb_define_module_function(json, "pretty_generate", oj_mimic_pretty_generate, -1);
798
820
  // For older versions of JSON, the deprecated unparse methods.
821
+ rb_undef_method(json, "unparse");
799
822
  rb_define_module_function(json, "unparse", oj_mimic_generate, -1);
800
823
  rb_define_module_function(json, "fast_unparse", oj_mimic_generate, -1);
801
824
  rb_define_module_function(json, "pretty_unparse", oj_mimic_pretty_generate, -1);
802
825
 
826
+ rb_undef_method(json, "parse");
803
827
  rb_define_module_function(json, "parse", oj_mimic_parse, -1);
828
+ rb_undef_method(json, "parse!");
804
829
  rb_define_module_function(json, "parse!", mimic_parse_bang, -1);
805
830
 
831
+ rb_undef_method(json, "state");
806
832
  rb_define_module_function(json, "state", mimic_state, 0);
833
+ rb_gv_set("$VERBOSE", verbose);
807
834
 
808
835
  if (rb_const_defined_at(json, rb_intern("JSONError"))) {
809
836
  json_error = rb_const_get(json, rb_intern("JSONError"));
@@ -813,36 +840,35 @@ oj_mimic_json_methods(VALUE json) {
813
840
  if (rb_const_defined_at(json, rb_intern("ParserError"))) {
814
841
  oj_json_parser_error_class = rb_const_get(json, rb_intern("ParserError"));
815
842
  } else {
816
- oj_json_parser_error_class = rb_define_class_under(json, "ParserError", json_error);
843
+ oj_json_parser_error_class = rb_define_class_under(json, "ParserError", json_error);
817
844
  }
818
845
  if (rb_const_defined_at(json, rb_intern("GeneratorError"))) {
819
846
  oj_json_generator_error_class = rb_const_get(json, rb_intern("GeneratorError"));
820
847
  } else {
821
- oj_json_generator_error_class = rb_define_class_under(json, "GeneratorError", json_error);
848
+ oj_json_generator_error_class = rb_define_class_under(json, "GeneratorError", json_error);
822
849
  }
823
850
  if (rb_const_defined_at(json, rb_intern("NestingError"))) {
824
851
  rb_const_get(json, rb_intern("NestingError"));
825
852
  } else {
826
- rb_define_class_under(json, "NestingError", json_error);
853
+ rb_define_class_under(json, "NestingError", json_error);
827
854
  }
828
855
 
829
856
  if (rb_const_defined_at(json, rb_intern("Ext"))) {
830
- ext = rb_const_get_at(json, rb_intern("Ext"));
831
- } else {
832
- ext = rb_define_module_under(json, "Ext");
857
+ ext = rb_const_get_at(json, rb_intern("Ext"));
858
+ } else {
859
+ ext = rb_define_module_under(json, "Ext");
833
860
  }
834
861
  if (rb_const_defined_at(ext, rb_intern("Generator"))) {
835
- generator = rb_const_get_at(ext, rb_intern("Generator"));
836
- } else {
837
- generator = rb_define_module_under(ext, "Generator");
862
+ generator = rb_const_get_at(ext, rb_intern("Generator"));
863
+ } else {
864
+ generator = rb_define_module_under(ext, "Generator");
838
865
  }
839
866
  if (!rb_const_defined_at(generator, rb_intern("State"))) {
840
- rb_require("oj/state");
867
+ rb_require("oj/state");
841
868
  }
842
869
  // Pull in the JSON::State mimic file.
843
870
  state_class = rb_const_get_at(generator, rb_intern("State"));
844
-
845
- symbolize_names_sym = ID2SYM(rb_intern("symbolize_names")); rb_gc_register_address(&symbolize_names_sym);
871
+ rb_gc_register_mark_object(state_class);
846
872
  }
847
873
 
848
874
  /* Document-module: JSON
@@ -851,31 +877,31 @@ oj_mimic_json_methods(VALUE json) {
851
877
  */
852
878
  VALUE
853
879
  oj_define_mimic_json(int argc, VALUE *argv, VALUE self) {
854
- VALUE dummy;
855
- VALUE verbose;
856
- VALUE json;
880
+ VALUE dummy;
881
+ VALUE verbose;
882
+ VALUE json;
857
883
 
858
884
  // Either set the paths to indicate JSON has been loaded or replaces the
859
885
  // methods if it has been loaded.
860
886
  if (rb_const_defined_at(rb_cObject, rb_intern("JSON"))) {
861
- json = rb_const_get_at(rb_cObject, rb_intern("JSON"));
887
+ json = rb_const_get_at(rb_cObject, rb_intern("JSON"));
862
888
  } else {
863
- json = rb_define_module("JSON");
889
+ json = rb_define_module("JSON");
864
890
  }
865
891
  verbose = rb_gv_get("$VERBOSE");
866
892
  rb_gv_set("$VERBOSE", Qfalse);
867
893
  rb_define_module_function(rb_cObject, "JSON", mimic_dump_load, -1);
868
894
  dummy = rb_gv_get("$LOADED_FEATURES");
869
895
  if (rb_type(dummy) == T_ARRAY) {
870
- rb_ary_push(dummy, rb_str_new2("json"));
871
- if (0 < argc) {
872
- VALUE mimic_args[1];
896
+ rb_ary_push(dummy, rb_str_new2("json"));
897
+ if (0 < argc) {
898
+ VALUE mimic_args[1];
873
899
 
874
- *mimic_args = *argv;
875
- rb_funcall2(Oj, rb_intern("mimic_loaded"), 1, mimic_args);
876
- } else {
877
- rb_funcall2(Oj, rb_intern("mimic_loaded"), 0, 0);
878
- }
900
+ *mimic_args = *argv;
901
+ rb_funcall2(Oj, rb_intern("mimic_loaded"), 1, mimic_args);
902
+ } else {
903
+ rb_funcall2(Oj, rb_intern("mimic_loaded"), 0, 0);
904
+ }
879
905
  }
880
906
  oj_mimic_json_methods(json);
881
907
 
@@ -883,7 +909,7 @@ oj_define_mimic_json(int argc, VALUE *argv, VALUE self) {
883
909
 
884
910
  rb_gv_set("$VERBOSE", verbose);
885
911
 
886
- oj_default_options = mimic_object_to_json_options;
912
+ oj_default_options = mimic_object_to_json_options;
887
913
  oj_default_options.to_json = Yes;
888
914
 
889
915
  return json;