oj 3.9.1 → 3.16.11

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