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/dump_compat.c CHANGED
@@ -1,4 +1,5 @@
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
4
  #include "code.h"
4
5
  #include "dump.h"
@@ -6,242 +7,219 @@
6
7
  #include "trace.h"
7
8
 
8
9
  // Workaround in case INFINITY is not defined in math.h or if the OS is CentOS
9
- #define OJ_INFINITY (1.0/0.0)
10
+ #define OJ_INFINITY (1.0 / 0.0)
10
11
 
11
- bool oj_use_hash_alt = false;
12
- bool oj_use_array_alt = false;
12
+ bool oj_use_hash_alt = false;
13
+ bool oj_use_array_alt = false;
13
14
 
14
- static bool use_struct_alt = false;
15
- static bool use_exception_alt = false;
16
- static bool use_bignum_alt = false;
15
+ static bool use_struct_alt = false;
16
+ static bool use_exception_alt = false;
17
+ static bool use_bignum_alt = false;
17
18
 
18
- static void
19
- raise_json_err(const char *msg, const char *err_classname) {
19
+ static void raise_json_err(const char *msg, const char *err_classname) {
20
20
  rb_raise(oj_get_json_err_class(err_classname), "%s", msg);
21
21
  }
22
22
 
23
- static void
24
- dump_obj_classname(const char *classname, int depth, Out out) {
25
- int d2 = depth + 1;
26
- size_t len = strlen(classname);
27
- size_t sep_len = out->opts->dump_opts.before_size + out->opts->dump_opts.after_size + 2;
28
- size_t size = d2 * out->indent + 10 + len + out->opts->create_id_len + sep_len;
23
+ static void dump_obj_classname(const char *classname, int depth, Out out) {
24
+ int d2 = depth + 1;
25
+ size_t len = strlen(classname);
26
+ size_t sep_len = out->opts->dump_opts.before_size + out->opts->dump_opts.after_size + 2;
27
+ size_t size = d2 * out->indent + 10 + len + out->opts->create_id_len + sep_len;
29
28
 
30
29
  assure_size(out, size);
31
30
  *out->cur++ = '{';
32
31
  fill_indent(out, d2);
33
32
  *out->cur++ = '"';
34
- memcpy(out->cur, out->opts->create_id, out->opts->create_id_len);
35
- out->cur += out->opts->create_id_len;
33
+ APPEND_CHARS(out->cur, out->opts->create_id, out->opts->create_id_len);
36
34
  *out->cur++ = '"';
37
35
  if (0 < out->opts->dump_opts.before_size) {
38
- strcpy(out->cur, out->opts->dump_opts.before_sep);
39
- out->cur += out->opts->dump_opts.before_size;
36
+ APPEND_CHARS(out->cur, out->opts->dump_opts.before_sep, out->opts->dump_opts.before_size);
40
37
  }
41
38
  *out->cur++ = ':';
42
39
  if (0 < out->opts->dump_opts.after_size) {
43
- strcpy(out->cur, out->opts->dump_opts.after_sep);
44
- out->cur += out->opts->dump_opts.after_size;
40
+ APPEND_CHARS(out->cur, out->opts->dump_opts.after_sep, out->opts->dump_opts.after_size);
45
41
  }
46
42
  *out->cur++ = '"';
47
- memcpy(out->cur, classname, len);
48
- out->cur += len;
43
+ APPEND_CHARS(out->cur, classname, len);
49
44
  *out->cur++ = '"';
50
45
  }
51
46
 
52
- static void
53
- dump_values_array(VALUE *values, int depth, Out out) {
54
- size_t size;
55
- int d2 = depth + 1;
47
+ static void dump_values_array(VALUE *values, int depth, Out out) {
48
+ size_t size;
49
+ int d2 = depth + 1;
56
50
 
57
51
  assure_size(out, d2 * out->indent + 3);
58
52
  *out->cur++ = '[';
59
53
  if (Qundef == *values) {
60
- *out->cur++ = ']';
54
+ *out->cur++ = ']';
61
55
  } else {
62
- if (out->opts->dump_opts.use) {
63
- size = d2 * out->opts->dump_opts.indent_size + out->opts->dump_opts.array_size + 2;
64
- size += out->opts->dump_opts.array_size;
65
- size += out->opts->dump_opts.indent_size;
66
- } else {
67
- size = d2 * out->indent + 3;
68
- }
69
- for (; Qundef != *values; values++) {
70
- assure_size(out, size);
71
- if (out->opts->dump_opts.use) {
72
- if (0 < out->opts->dump_opts.array_size) {
73
- strcpy(out->cur, out->opts->dump_opts.array_nl);
74
- out->cur += out->opts->dump_opts.array_size;
75
- }
76
- if (0 < out->opts->dump_opts.indent_size) {
77
- int i;
78
-
79
- for (i = d2; 0 < i; i--) {
80
- strcpy(out->cur, out->opts->dump_opts.indent_str);
81
- out->cur += out->opts->dump_opts.indent_size;
82
- }
83
- }
84
- } else {
85
- fill_indent(out, d2);
86
- }
87
- oj_dump_compat_val(*values, d2, out, true);
88
- if (Qundef != *(values + 1)) {
89
- *out->cur++ = ',';
90
- }
91
- }
92
- assure_size(out, size);
93
- if (out->opts->dump_opts.use) {
94
- if (0 < out->opts->dump_opts.array_size) {
95
- strcpy(out->cur, out->opts->dump_opts.array_nl);
96
- out->cur += out->opts->dump_opts.array_size;
97
- }
98
- if (0 < out->opts->dump_opts.indent_size) {
99
- int i;
100
-
101
- for (i = depth; 0 < i; i--) {
102
- strcpy(out->cur, out->opts->dump_opts.indent_str);
103
- out->cur += out->opts->dump_opts.indent_size;
104
- }
105
- }
106
- } else {
107
- fill_indent(out, depth);
108
- }
109
- *out->cur++ = ']';
56
+ if (out->opts->dump_opts.use) {
57
+ size = d2 * out->opts->dump_opts.indent_size + out->opts->dump_opts.array_size + 2;
58
+ size += out->opts->dump_opts.array_size;
59
+ size += out->opts->dump_opts.indent_size;
60
+ } else {
61
+ size = d2 * out->indent + 3;
62
+ }
63
+ for (; Qundef != *values; values++) {
64
+ assure_size(out, size);
65
+ if (out->opts->dump_opts.use) {
66
+ if (0 < out->opts->dump_opts.array_size) {
67
+ APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
68
+ }
69
+ if (0 < out->opts->dump_opts.indent_size) {
70
+ int i;
71
+
72
+ for (i = d2; 0 < i; i--) {
73
+ APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
74
+ }
75
+ }
76
+ } else {
77
+ fill_indent(out, d2);
78
+ }
79
+ oj_dump_compat_val(*values, d2, out, true);
80
+ if (Qundef != *(values + 1)) {
81
+ *out->cur++ = ',';
82
+ }
83
+ }
84
+ assure_size(out, size);
85
+ if (out->opts->dump_opts.use) {
86
+ if (0 < out->opts->dump_opts.array_size) {
87
+ APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
88
+ }
89
+ if (0 < out->opts->dump_opts.indent_size) {
90
+ int i;
91
+
92
+ for (i = depth; 0 < i; i--) {
93
+ APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
94
+ }
95
+ }
96
+ } else {
97
+ fill_indent(out, depth);
98
+ }
99
+ *out->cur++ = ']';
110
100
  }
111
101
  }
112
102
 
113
- static void
114
- dump_to_json(VALUE obj, Out out) {
115
- volatile VALUE rs;
116
- const char *s;
117
- int len;
103
+ static void dump_to_json(VALUE obj, Out out) {
104
+ volatile VALUE rs;
105
+ const char *s;
106
+ int len;
118
107
 
119
- if (Yes == out->opts->trace) {
120
- oj_trace("to_json", obj, __FILE__, __LINE__, 0, TraceRubyIn);
121
- }
108
+ TRACE(out->opts->trace, "to_json", obj, 0, TraceRubyIn);
122
109
  if (0 == rb_obj_method_arity(obj, oj_to_json_id)) {
123
- rs = rb_funcall(obj, oj_to_json_id, 0);
110
+ rs = rb_funcall(obj, oj_to_json_id, 0);
124
111
  } else {
125
- rs = rb_funcall2(obj, oj_to_json_id, out->argc, out->argv);
126
- }
127
- if (Yes == out->opts->trace) {
128
- oj_trace("to_json", obj, __FILE__, __LINE__, 0, TraceRubyOut);
112
+ rs = rb_funcall2(obj, oj_to_json_id, out->argc, out->argv);
129
113
  }
114
+ TRACE(out->opts->trace, "to_json", obj, 0, TraceRubyOut);
130
115
 
131
- s = rb_string_value_ptr((VALUE*)&rs);
116
+ StringValue(rs);
117
+ s = RSTRING_PTR(rs);
132
118
  len = (int)RSTRING_LEN(rs);
133
119
 
134
120
  assure_size(out, len + 1);
135
- memcpy(out->cur, s, len);
136
- out->cur += len;
121
+ APPEND_CHARS(out->cur, s, len);
137
122
  *out->cur = '\0';
138
123
  }
139
124
 
140
- static void
141
- dump_array(VALUE a, int depth, Out out, bool as_ok) {
142
- size_t size;
143
- int i, cnt;
144
- int d2 = depth + 1;
145
- long id = oj_check_circular(a, out);
125
+ static void dump_array(VALUE a, int depth, Out out, bool as_ok) {
126
+ size_t size;
127
+ int i, cnt;
128
+ int d2 = depth + 1;
129
+ long id = oj_check_circular(a, out);
146
130
 
147
131
  if (0 > id) {
148
- raise_json_err("Too deeply nested", "NestingError");
149
- return;
132
+ raise_json_err("Too deeply nested", "NestingError");
133
+ return;
150
134
  }
151
- if (as_ok && !oj_use_hash_alt && rb_obj_class(a) != rb_cArray && rb_respond_to(a, oj_to_json_id)) {
152
- dump_to_json(a, out);
153
- return;
135
+ if (as_ok && !oj_use_array_alt && rb_obj_class(a) != rb_cArray && rb_respond_to(a, oj_to_json_id)) {
136
+ dump_to_json(a, out);
137
+ return;
154
138
  }
155
- cnt = (int)RARRAY_LEN(a);
139
+ cnt = (int)RARRAY_LEN(a);
156
140
  *out->cur++ = '[';
157
141
  assure_size(out, 2);
158
142
  if (0 == cnt) {
159
- *out->cur++ = ']';
143
+ *out->cur++ = ']';
160
144
  } else {
161
- if (out->opts->dump_opts.use) {
162
- size = d2 * out->opts->dump_opts.indent_size + out->opts->dump_opts.array_size + 1;
163
- } else {
164
- size = d2 * out->indent + 2;
165
- }
166
- cnt--;
167
- for (i = 0; i <= cnt; i++) {
168
- assure_size(out, size);
169
- if (out->opts->dump_opts.use) {
170
- if (0 < out->opts->dump_opts.array_size) {
171
- strcpy(out->cur, out->opts->dump_opts.array_nl);
172
- out->cur += out->opts->dump_opts.array_size;
173
- }
174
- if (0 < out->opts->dump_opts.indent_size) {
175
- int i;
176
- for (i = d2; 0 < i; i--) {
177
- strcpy(out->cur, out->opts->dump_opts.indent_str);
178
- out->cur += out->opts->dump_opts.indent_size;
179
- }
180
- }
181
- } else {
182
- fill_indent(out, d2);
183
- }
184
- oj_dump_compat_val(rb_ary_entry(a, i), d2, out, true);
185
- if (i < cnt) {
186
- *out->cur++ = ',';
187
- }
188
- }
189
- if (out->opts->dump_opts.use) {
190
- size = out->opts->dump_opts.array_size + out->opts->dump_opts.indent_size * depth + 1;
191
- assure_size(out, size);
192
- if (0 < out->opts->dump_opts.array_size) {
193
- strcpy(out->cur, out->opts->dump_opts.array_nl);
194
- out->cur += out->opts->dump_opts.array_size;
195
- }
196
- if (0 < out->opts->dump_opts.indent_size) {
197
- int i;
198
-
199
- for (i = depth; 0 < i; i--) {
200
- strcpy(out->cur, out->opts->dump_opts.indent_str);
201
- out->cur += out->opts->dump_opts.indent_size;
202
- }
203
- }
204
- } else {
205
- size = depth * out->indent + 1;
206
- assure_size(out, size);
207
- fill_indent(out, depth);
208
- }
209
- *out->cur++ = ']';
145
+ if (out->opts->dump_opts.use) {
146
+ size = d2 * out->opts->dump_opts.indent_size + out->opts->dump_opts.array_size + 1;
147
+ } else {
148
+ size = d2 * out->indent + 2;
149
+ }
150
+ assure_size(out, size * cnt);
151
+ cnt--;
152
+ for (i = 0; i <= cnt; i++) {
153
+ if (out->opts->dump_opts.use) {
154
+ if (0 < out->opts->dump_opts.array_size) {
155
+ APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
156
+ }
157
+ if (0 < out->opts->dump_opts.indent_size) {
158
+ int i;
159
+ for (i = d2; 0 < i; i--) {
160
+ APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
161
+ }
162
+ }
163
+ } else {
164
+ fill_indent(out, d2);
165
+ }
166
+ oj_dump_compat_val(RARRAY_AREF(a, i), d2, out, true);
167
+ if (i < cnt) {
168
+ *out->cur++ = ',';
169
+ }
170
+ }
171
+ if (out->opts->dump_opts.use) {
172
+ size = out->opts->dump_opts.array_size + out->opts->dump_opts.indent_size * depth + 1;
173
+ assure_size(out, size);
174
+ if (0 < out->opts->dump_opts.array_size) {
175
+ APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
176
+ }
177
+ if (0 < out->opts->dump_opts.indent_size) {
178
+ int i;
179
+
180
+ for (i = depth; 0 < i; i--) {
181
+ APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
182
+ }
183
+ }
184
+ } else {
185
+ size = depth * out->indent + 1;
186
+ assure_size(out, size);
187
+ fill_indent(out, depth);
188
+ }
189
+ *out->cur++ = ']';
210
190
  }
211
191
  *out->cur = '\0';
212
192
  }
213
193
 
214
- static ID _dump_id = 0;
194
+ static ID _dump_id = 0;
215
195
 
216
- static void
217
- bigdecimal_alt(VALUE obj, int depth, Out out) {
218
- struct _attr attrs[] = {
219
- { "b", 1, Qnil },
220
- { NULL, 0, Qnil },
196
+ static void bigdecimal_alt(VALUE obj, int depth, Out out) {
197
+ struct _attr attrs[] = {
198
+ {"b", 1, Qnil},
199
+ {NULL, 0, Qnil},
221
200
  };
222
201
 
223
202
  if (0 == _dump_id) {
224
- _dump_id = rb_intern("_dump");
203
+ _dump_id = rb_intern("_dump");
225
204
  }
226
205
  attrs[0].value = rb_funcall(obj, _dump_id, 0);
227
206
 
228
207
  oj_code_attrs(obj, attrs, depth, out, true);
229
208
  }
230
209
 
231
- static ID real_id = 0;
232
- static ID imag_id = 0;
210
+ static ID real_id = 0;
211
+ static ID imag_id = 0;
233
212
 
234
- static void
235
- complex_alt(VALUE obj, int depth, Out out) {
236
- struct _attr attrs[] = {
237
- { "r", 1, Qnil },
238
- { "i", 1, Qnil },
239
- { NULL, 0, Qnil },
213
+ static void complex_alt(VALUE obj, int depth, Out out) {
214
+ struct _attr attrs[] = {
215
+ {"r", 1, Qnil},
216
+ {"i", 1, Qnil},
217
+ {NULL, 0, Qnil},
240
218
  };
241
219
 
242
220
  if (0 == real_id) {
243
- real_id = rb_intern("real");
244
- imag_id = rb_intern("imag");
221
+ real_id = rb_intern("real");
222
+ imag_id = rb_intern("imag");
245
223
  }
246
224
  attrs[0].value = rb_funcall(obj, real_id, 0);
247
225
  attrs[1].value = rb_funcall(obj, imag_id, 0);
@@ -249,25 +227,24 @@ complex_alt(VALUE obj, int depth, Out out) {
249
227
  oj_code_attrs(obj, attrs, depth, out, true);
250
228
  }
251
229
 
252
- static ID year_id = 0;
253
- static ID month_id = 0;
254
- static ID day_id = 0;
255
- static ID start_id = 0;
256
-
257
- static void
258
- date_alt(VALUE obj, int depth, Out out) {
259
- struct _attr attrs[] = {
260
- { "y", 1, Qnil },
261
- { "m", 1, Qnil },
262
- { "d", 1, Qnil },
263
- { "sg", 2, Qnil },
264
- { NULL, 0, Qnil },
230
+ static ID year_id = 0;
231
+ static ID month_id = 0;
232
+ static ID day_id = 0;
233
+ static ID start_id = 0;
234
+
235
+ static void date_alt(VALUE obj, int depth, Out out) {
236
+ struct _attr attrs[] = {
237
+ {"y", 1, Qnil},
238
+ {"m", 1, Qnil},
239
+ {"d", 1, Qnil},
240
+ {"sg", 2, Qnil},
241
+ {NULL, 0, Qnil},
265
242
  };
266
243
  if (0 == year_id) {
267
- year_id = rb_intern("year");
268
- month_id = rb_intern("month");
269
- day_id = rb_intern("day");
270
- start_id = rb_intern("start");
244
+ year_id = rb_intern("year");
245
+ month_id = rb_intern("month");
246
+ day_id = rb_intern("day");
247
+ start_id = rb_intern("start");
271
248
  }
272
249
  attrs[0].value = rb_funcall(obj, year_id, 0);
273
250
  attrs[1].value = rb_funcall(obj, month_id, 0);
@@ -277,33 +254,32 @@ date_alt(VALUE obj, int depth, Out out) {
277
254
  oj_code_attrs(obj, attrs, depth, out, true);
278
255
  }
279
256
 
280
- static ID hour_id = 0;
281
- static ID min_id = 0;
282
- static ID sec_id = 0;
283
- static ID offset_id = 0;
284
-
285
- static void
286
- datetime_alt(VALUE obj, int depth, Out out) {
287
- struct _attr attrs[] = {
288
- { "y", 1, Qnil },
289
- { "m", 1, Qnil },
290
- { "d", 1, Qnil },
291
- { "H", 1, Qnil },
292
- { "M", 1, Qnil },
293
- { "S", 1, Qnil },
294
- { "of", 2, Qnil },
295
- { "sg", 2, Qnil },
296
- { NULL, 0, Qnil },
257
+ static ID hour_id = 0;
258
+ static ID min_id = 0;
259
+ static ID sec_id = 0;
260
+ static ID offset_id = 0;
261
+
262
+ static void datetime_alt(VALUE obj, int depth, Out out) {
263
+ struct _attr attrs[] = {
264
+ {"y", 1, Qnil},
265
+ {"m", 1, Qnil},
266
+ {"d", 1, Qnil},
267
+ {"H", 1, Qnil},
268
+ {"M", 1, Qnil},
269
+ {"S", 1, Qnil},
270
+ {"of", 2, Qnil},
271
+ {"sg", 2, Qnil},
272
+ {NULL, 0, Qnil},
297
273
  };
298
274
  if (0 == hour_id) {
299
- year_id = rb_intern("year");
300
- month_id = rb_intern("month");
301
- day_id = rb_intern("day");
302
- hour_id = rb_intern("hour");
303
- min_id = rb_intern("min");
304
- sec_id = rb_intern("sec");
305
- offset_id = rb_intern("offset");
306
- start_id = rb_intern("start");
275
+ year_id = rb_intern("year");
276
+ month_id = rb_intern("month");
277
+ day_id = rb_intern("day");
278
+ hour_id = rb_intern("hour");
279
+ min_id = rb_intern("min");
280
+ sec_id = rb_intern("sec");
281
+ offset_id = rb_intern("offset");
282
+ start_id = rb_intern("start");
307
283
  }
308
284
  attrs[0].value = rb_funcall(obj, year_id, 0);
309
285
  attrs[1].value = rb_funcall(obj, month_id, 0);
@@ -311,103 +287,88 @@ datetime_alt(VALUE obj, int depth, Out out) {
311
287
  attrs[3].value = rb_funcall(obj, hour_id, 0);
312
288
  attrs[4].value = rb_funcall(obj, min_id, 0);
313
289
  attrs[5].value = rb_funcall(obj, sec_id, 0);
314
- attrs[6].value = rb_funcall(rb_funcall(obj, offset_id, 0), oj_to_s_id, 0);
290
+ attrs[6].value = oj_safe_string_convert(rb_funcall(obj, offset_id, 0));
315
291
  attrs[7].value = rb_funcall(obj, start_id, 0);
316
292
 
317
293
  oj_code_attrs(obj, attrs, depth, out, true);
318
294
  }
319
295
 
320
- static ID message_id = 0;
321
- static ID backtrace_id = 0;
296
+ static ID message_id = 0;
297
+ static ID backtrace_id = 0;
322
298
 
323
- static void
324
- exception_alt(VALUE obj, int depth, Out out) {
325
- int d3 = depth + 2;
326
- size_t size = d3 * out->indent + 2;
327
- size_t sep_len = out->opts->dump_opts.before_size + out->opts->dump_opts.after_size + 2;
299
+ static void exception_alt(VALUE obj, int depth, Out out) {
300
+ int d3 = depth + 2;
301
+ size_t size = d3 * out->indent + 2;
302
+ size_t sep_len = out->opts->dump_opts.before_size + out->opts->dump_opts.after_size + 2;
328
303
 
329
304
  if (0 == message_id) {
330
- message_id = rb_intern("message");
331
- backtrace_id = rb_intern("backtrace");
305
+ message_id = rb_intern("message");
306
+ backtrace_id = rb_intern("backtrace");
332
307
  }
333
308
  dump_obj_classname(rb_class2name(rb_obj_class(obj)), depth, out);
334
309
 
335
310
  assure_size(out, size + sep_len + 6);
336
311
  *out->cur++ = ',';
337
312
  fill_indent(out, d3);
338
- *out->cur++ = '"';
339
- *out->cur++ = 'm';
340
- *out->cur++ = '"';
313
+ APPEND_CHARS(out->cur, "\"m\"", 3);
341
314
  if (0 < out->opts->dump_opts.before_size) {
342
- strcpy(out->cur, out->opts->dump_opts.before_sep);
343
- out->cur += out->opts->dump_opts.before_size;
315
+ APPEND_CHARS(out->cur, out->opts->dump_opts.before_sep, out->opts->dump_opts.before_size);
344
316
  }
345
317
  *out->cur++ = ':';
346
318
  if (0 < out->opts->dump_opts.after_size) {
347
- strcpy(out->cur, out->opts->dump_opts.after_sep);
348
- out->cur += out->opts->dump_opts.after_size;
319
+ APPEND_CHARS(out->cur, out->opts->dump_opts.after_sep, out->opts->dump_opts.after_size);
349
320
  }
350
321
  oj_dump_str(rb_funcall(obj, message_id, 0), 0, out, false);
351
322
  assure_size(out, size + sep_len + 6);
352
323
  *out->cur++ = ',';
353
324
  fill_indent(out, d3);
354
- *out->cur++ = '"';
355
- *out->cur++ = 'b';
356
- *out->cur++ = '"';
325
+ APPEND_CHARS(out->cur, "\"b\"", 3);
357
326
  if (0 < out->opts->dump_opts.before_size) {
358
- strcpy(out->cur, out->opts->dump_opts.before_sep);
359
- out->cur += out->opts->dump_opts.before_size;
327
+ APPEND_CHARS(out->cur, out->opts->dump_opts.before_sep, out->opts->dump_opts.before_size);
360
328
  }
361
329
  *out->cur++ = ':';
362
330
  if (0 < out->opts->dump_opts.after_size) {
363
- strcpy(out->cur, out->opts->dump_opts.after_sep);
364
- out->cur += out->opts->dump_opts.after_size;
331
+ APPEND_CHARS(out->cur, out->opts->dump_opts.after_sep, out->opts->dump_opts.after_size);
365
332
  }
366
333
  dump_array(rb_funcall(obj, backtrace_id, 0), depth, out, false);
367
334
  fill_indent(out, depth);
368
335
  *out->cur++ = '}';
369
- *out->cur = '\0';
336
+ *out->cur = '\0';
370
337
  }
371
338
 
372
- static ID table_id = 0;
339
+ static ID table_id = 0;
373
340
 
374
- static void
375
- openstruct_alt(VALUE obj, int depth, Out out) {
376
- struct _attr attrs[] = {
377
- { "t", 1, Qnil },
378
- { NULL, 0, Qnil },
341
+ static void openstruct_alt(VALUE obj, int depth, Out out) {
342
+ struct _attr attrs[] = {
343
+ {"t", 1, Qnil},
344
+ {NULL, 0, Qnil},
379
345
  };
380
346
  if (0 == table_id) {
381
- table_id = rb_intern("table");
347
+ table_id = rb_intern("table");
382
348
  }
383
349
  attrs[0].value = rb_funcall(obj, table_id, 0);
384
350
 
385
351
  oj_code_attrs(obj, attrs, depth, out, true);
386
352
  }
387
353
 
388
- static void
389
- range_alt(VALUE obj, int depth, Out out) {
390
- int d3 = depth + 2;
391
- size_t size = d3 * out->indent + 2;
392
- size_t sep_len = out->opts->dump_opts.before_size + out->opts->dump_opts.after_size + 2;
393
- VALUE args[] = { Qundef, Qundef, Qundef, Qundef };
354
+ static void range_alt(VALUE obj, int depth, Out out) {
355
+ int d3 = depth + 2;
356
+ size_t size = d3 * out->indent + 2;
357
+ size_t sep_len = out->opts->dump_opts.before_size + out->opts->dump_opts.after_size + 2;
358
+ VALUE args[] = {Qundef, Qundef, Qundef, Qundef};
394
359
 
395
360
  dump_obj_classname(rb_class2name(rb_obj_class(obj)), depth, out);
396
361
 
397
362
  assure_size(out, size + sep_len + 6);
398
363
  *out->cur++ = ',';
399
364
  fill_indent(out, d3);
400
- *out->cur++ = '"';
401
- *out->cur++ = 'a';
402
- *out->cur++ = '"';
365
+ APPEND_CHARS(out->cur, "\"a\"", 3);
403
366
  if (0 < out->opts->dump_opts.before_size) {
404
- strcpy(out->cur, out->opts->dump_opts.before_sep);
405
- out->cur += out->opts->dump_opts.before_size;
367
+ APPEND_CHARS(out->cur, out->opts->dump_opts.before_sep, out->opts->dump_opts.before_size);
406
368
  }
407
369
  *out->cur++ = ':';
408
370
  if (0 < out->opts->dump_opts.after_size) {
409
- strcpy(out->cur, out->opts->dump_opts.after_sep);
410
- out->cur += out->opts->dump_opts.after_size;
371
+ APPEND_CHARS(out->cur, out->opts->dump_opts.after_sep, out->opts->dump_opts.after_size);
411
372
  }
412
373
  args[0] = rb_funcall(obj, oj_begin_id, 0);
413
374
  args[1] = rb_funcall(obj, oj_end_id, 0);
@@ -415,22 +376,21 @@ range_alt(VALUE obj, int depth, Out out) {
415
376
  dump_values_array(args, depth, out);
416
377
  fill_indent(out, depth);
417
378
  *out->cur++ = '}';
418
- *out->cur = '\0';
379
+ *out->cur = '\0';
419
380
  }
420
381
 
421
- static ID numerator_id = 0;
422
- static ID denominator_id = 0;
382
+ static ID numerator_id = 0;
383
+ static ID denominator_id = 0;
423
384
 
424
- static void
425
- rational_alt(VALUE obj, int depth, Out out) {
426
- struct _attr attrs[] = {
427
- { "n", 1, Qnil },
428
- { "d", 1, Qnil },
429
- { NULL, 0, Qnil },
385
+ static void rational_alt(VALUE obj, int depth, Out out) {
386
+ struct _attr attrs[] = {
387
+ {"n", 1, Qnil},
388
+ {"d", 1, Qnil},
389
+ {NULL, 0, Qnil},
430
390
  };
431
391
  if (0 == numerator_id) {
432
- numerator_id = rb_intern("numerator");
433
- denominator_id = rb_intern("denominator");
392
+ numerator_id = rb_intern("numerator");
393
+ denominator_id = rb_intern("denominator");
434
394
  }
435
395
  attrs[0].value = rb_funcall(obj, numerator_id, 0);
436
396
  attrs[1].value = rb_funcall(obj, denominator_id, 0);
@@ -438,19 +398,18 @@ rational_alt(VALUE obj, int depth, Out out) {
438
398
  oj_code_attrs(obj, attrs, depth, out, true);
439
399
  }
440
400
 
441
- static ID options_id = 0;
442
- static ID source_id = 0;
401
+ static ID options_id = 0;
402
+ static ID source_id = 0;
443
403
 
444
- static void
445
- regexp_alt(VALUE obj, int depth, Out out) {
446
- struct _attr attrs[] = {
447
- { "o", 1, Qnil },
448
- { "s", 1, Qnil },
449
- { NULL, 0, Qnil },
404
+ static void regexp_alt(VALUE obj, int depth, Out out) {
405
+ struct _attr attrs[] = {
406
+ {"o", 1, Qnil},
407
+ {"s", 1, Qnil},
408
+ {NULL, 0, Qnil},
450
409
  };
451
410
  if (0 == options_id) {
452
- options_id = rb_intern("options");
453
- source_id = rb_intern("source");
411
+ options_id = rb_intern("options");
412
+ source_id = rb_intern("source");
454
413
  }
455
414
  attrs[0].value = rb_funcall(obj, options_id, 0);
456
415
  attrs[1].value = rb_funcall(obj, source_id, 0);
@@ -458,30 +417,24 @@ regexp_alt(VALUE obj, int depth, Out out) {
458
417
  oj_code_attrs(obj, attrs, depth, out, true);
459
418
  }
460
419
 
461
- static void
462
- time_alt(VALUE obj, int depth, Out out) {
463
- struct _attr attrs[] = {
464
- { "s", 1, Qundef, 0, Qundef },
465
- { "n", 1, Qundef, 0, Qundef },
466
- { NULL, 0, Qnil },
420
+ static void time_alt(VALUE obj, int depth, Out out) {
421
+ struct _attr attrs[] = {
422
+ {"s", 1, Qundef, 0, Qundef},
423
+ {"n", 1, Qundef, 0, Qundef},
424
+ {NULL, 0, Qnil},
467
425
  };
468
- time_t sec;
469
- long long nsec;
426
+ time_t sec;
427
+ long long nsec;
470
428
 
471
- #ifdef HAVE_RB_TIME_TIMESPEC
472
429
  if (16 <= sizeof(struct timespec)) {
473
- struct timespec ts = rb_time_timespec(obj);
430
+ struct timespec ts = rb_time_timespec(obj);
474
431
 
475
- sec = (long long)ts.tv_sec;
476
- nsec = ts.tv_nsec;
432
+ sec = (long long)ts.tv_sec;
433
+ nsec = ts.tv_nsec;
477
434
  } else {
478
- sec = rb_num2ll(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
479
- nsec = rb_num2ll(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
435
+ sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
436
+ nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
480
437
  }
481
- #else
482
- sec = rb_num2ll(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
483
- nsec = rb_num2ll(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
484
- #endif
485
438
 
486
439
  attrs[0].num = sec;
487
440
  attrs[1].num = nsec;
@@ -489,68 +442,68 @@ time_alt(VALUE obj, int depth, Out out) {
489
442
  oj_code_attrs(obj, attrs, depth, out, true);
490
443
  }
491
444
 
492
- struct _code oj_compat_codes[] = {
493
- { "BigDecimal", Qnil, bigdecimal_alt, NULL, false },
494
- { "Complex", Qnil, complex_alt, NULL, false },
495
- { "Date", Qnil, date_alt, false },
496
- { "DateTime", Qnil, datetime_alt, NULL, false },
497
- { "OpenStruct", Qnil, openstruct_alt, NULL, false },
498
- { "Range", Qnil, range_alt, NULL, false },
499
- { "Rational", Qnil, rational_alt, NULL, false },
500
- { "Regexp", Qnil, regexp_alt, NULL, false },
501
- { "Time", Qnil, time_alt, NULL, false },
445
+ struct _code oj_compat_codes[] = {
446
+ {"BigDecimal", Qnil, bigdecimal_alt, NULL, false},
447
+ {"Complex", Qnil, complex_alt, NULL, false},
448
+ {"Date", Qnil, date_alt, false},
449
+ {"DateTime", Qnil, datetime_alt, NULL, false},
450
+ {"OpenStruct", Qnil, openstruct_alt, NULL, false},
451
+ {"Range", Qnil, range_alt, NULL, false},
452
+ {"Rational", Qnil, rational_alt, NULL, false},
453
+ {"Regexp", Qnil, regexp_alt, NULL, false},
454
+ {"Time", Qnil, time_alt, NULL, false},
502
455
  // TBD the rest of the library classes
503
- { NULL, Qundef, NULL, NULL, false },
456
+ {NULL, Qundef, NULL, NULL, false},
504
457
  };
505
458
 
506
459
  VALUE
507
460
  oj_add_to_json(int argc, VALUE *argv, VALUE self) {
508
- Code a;
461
+ Code a;
509
462
 
510
463
  if (0 == argc) {
511
- for (a = oj_compat_codes; NULL != a->name; a++) {
512
- if (Qnil == a->clas || Qundef == a->clas) {
513
- a->clas = rb_const_get_at(rb_cObject, rb_intern(a->name));
514
- }
515
- a->active = true;
516
- }
517
- use_struct_alt = true;
518
- use_exception_alt = true;
519
- use_bignum_alt = true;
520
- oj_use_hash_alt = true;
521
- oj_use_array_alt = true;
464
+ for (a = oj_compat_codes; NULL != a->name; a++) {
465
+ if (Qnil == a->clas || Qundef == a->clas) {
466
+ a->clas = rb_const_get_at(rb_cObject, rb_intern(a->name));
467
+ }
468
+ a->active = true;
469
+ }
470
+ use_struct_alt = true;
471
+ use_exception_alt = true;
472
+ use_bignum_alt = true;
473
+ oj_use_hash_alt = true;
474
+ oj_use_array_alt = true;
522
475
  } else {
523
- for (; 0 < argc; argc--, argv++) {
524
- if (rb_cStruct == *argv) {
525
- use_struct_alt = true;
526
- continue;
527
- }
528
- if (rb_eException == *argv) {
529
- use_exception_alt = true;
530
- continue;
531
- }
532
- if (rb_cInteger == *argv) {
533
- use_bignum_alt = true;
534
- continue;
535
- }
536
- if (rb_cHash == *argv) {
537
- oj_use_hash_alt = true;
538
- continue;
539
- }
540
- if (rb_cArray == *argv) {
541
- oj_use_array_alt = true;
542
- continue;
543
- }
544
- for (a = oj_compat_codes; NULL != a->name; a++) {
545
- if (Qnil == a->clas || Qundef == a->clas) {
546
- a->clas = rb_const_get_at(rb_cObject, rb_intern(a->name));
547
- }
548
- if (*argv == a->clas) {
549
- a->active = true;
550
- break;
551
- }
552
- }
553
- }
476
+ for (; 0 < argc; argc--, argv++) {
477
+ if (rb_cStruct == *argv) {
478
+ use_struct_alt = true;
479
+ continue;
480
+ }
481
+ if (rb_eException == *argv) {
482
+ use_exception_alt = true;
483
+ continue;
484
+ }
485
+ if (rb_cInteger == *argv) {
486
+ use_bignum_alt = true;
487
+ continue;
488
+ }
489
+ if (rb_cHash == *argv) {
490
+ oj_use_hash_alt = true;
491
+ continue;
492
+ }
493
+ if (rb_cArray == *argv) {
494
+ oj_use_array_alt = true;
495
+ continue;
496
+ }
497
+ for (a = oj_compat_codes; NULL != a->name; a++) {
498
+ if (Qnil == a->clas || Qundef == a->clas) {
499
+ a->clas = rb_const_get_at(rb_cObject, rb_intern(a->name));
500
+ }
501
+ if (*argv == a->clas) {
502
+ a->active = true;
503
+ break;
504
+ }
505
+ }
506
+ }
554
507
  }
555
508
  return Qnil;
556
509
  }
@@ -558,36 +511,36 @@ oj_add_to_json(int argc, VALUE *argv, VALUE self) {
558
511
  VALUE
559
512
  oj_remove_to_json(int argc, VALUE *argv, VALUE self) {
560
513
  if (0 == argc) {
561
- oj_code_set_active(oj_compat_codes, Qnil, false);
562
- use_struct_alt = false;
563
- use_exception_alt = false;
564
- use_bignum_alt = false;
565
- oj_use_hash_alt = false;
566
- oj_use_array_alt = false;
514
+ oj_code_set_active(oj_compat_codes, Qnil, false);
515
+ use_struct_alt = false;
516
+ use_exception_alt = false;
517
+ use_bignum_alt = false;
518
+ oj_use_hash_alt = false;
519
+ oj_use_array_alt = false;
567
520
  } else {
568
- for (; 0 < argc; argc--, argv++) {
569
- if (rb_cStruct == *argv) {
570
- use_struct_alt = false;
571
- continue;
572
- }
573
- if (rb_eException == *argv) {
574
- use_exception_alt = false;
575
- continue;
576
- }
577
- if (rb_cInteger == *argv) {
578
- use_bignum_alt = false;
579
- continue;
580
- }
581
- if (rb_cHash == *argv) {
582
- oj_use_hash_alt = false;
583
- continue;
584
- }
585
- if (rb_cArray == *argv) {
586
- oj_use_array_alt = false;
587
- continue;
588
- }
589
- oj_code_set_active(oj_compat_codes, *argv, false);
590
- }
521
+ for (; 0 < argc; argc--, argv++) {
522
+ if (rb_cStruct == *argv) {
523
+ use_struct_alt = false;
524
+ continue;
525
+ }
526
+ if (rb_eException == *argv) {
527
+ use_exception_alt = false;
528
+ continue;
529
+ }
530
+ if (rb_cInteger == *argv) {
531
+ use_bignum_alt = false;
532
+ continue;
533
+ }
534
+ if (rb_cHash == *argv) {
535
+ oj_use_hash_alt = false;
536
+ continue;
537
+ }
538
+ if (rb_cArray == *argv) {
539
+ oj_use_array_alt = false;
540
+ continue;
541
+ }
542
+ oj_code_set_active(oj_compat_codes, *argv, false);
543
+ }
591
544
  }
592
545
  return Qnil;
593
546
  }
@@ -595,378 +548,349 @@ oj_remove_to_json(int argc, VALUE *argv, VALUE self) {
595
548
  // The JSON gem is inconsistent with handling of infinity. Using
596
549
  // JSON.dump(0.1/0) returns the string Infinity but (0.1/0).to_json raise and
597
550
  // exception. Worse, for BigDecimals a quoted "Infinity" is returned.
598
- static void
599
- dump_float(VALUE obj, int depth, Out out, bool as_ok) {
600
- char buf[64];
601
- char *b;
602
- double d = rb_num2dbl(obj);
603
- int cnt = 0;
551
+ static void dump_float(VALUE obj, int depth, Out out, bool as_ok) {
552
+ char buf[64];
553
+ char *b;
554
+ double d = rb_num2dbl(obj);
555
+ int cnt = 0;
604
556
 
605
557
  if (0.0 == d) {
606
- b = buf;
607
- *b++ = '0';
608
- *b++ = '.';
609
- *b++ = '0';
610
- *b++ = '\0';
611
- cnt = 3;
558
+ b = buf;
559
+ *b++ = '0';
560
+ *b++ = '.';
561
+ *b++ = '0';
562
+ *b++ = '\0';
563
+ cnt = 3;
612
564
  } else if (OJ_INFINITY == d) {
613
- if (WordNan == out->opts->dump_opts.nan_dump) {
614
- strcpy(buf, "Infinity");
615
- } else {
616
- raise_json_err("Infinity not allowed in JSON.", "GeneratorError");
617
- }
565
+ if (WordNan == out->opts->dump_opts.nan_dump) {
566
+ strcpy(buf, "Infinity");
567
+ cnt = 8;
568
+ } else {
569
+ raise_json_err("Infinity not allowed in JSON.", "GeneratorError");
570
+ }
618
571
  } else if (-OJ_INFINITY == d) {
619
- if (WordNan == out->opts->dump_opts.nan_dump) {
620
- strcpy(buf, "-Infinity");
621
- } else {
622
- raise_json_err("-Infinity not allowed in JSON.", "GeneratorError");
623
- }
572
+ if (WordNan == out->opts->dump_opts.nan_dump) {
573
+ strcpy(buf, "-Infinity");
574
+ cnt = 9;
575
+ } else {
576
+ raise_json_err("-Infinity not allowed in JSON.", "GeneratorError");
577
+ }
624
578
  } else if (isnan(d)) {
625
- if (WordNan == out->opts->dump_opts.nan_dump) {
626
- strcpy(buf, "NaN");
627
- } else {
628
- raise_json_err("NaN not allowed in JSON.", "GeneratorError");
629
- }
579
+ if (WordNan == out->opts->dump_opts.nan_dump) {
580
+ strcpy(buf, "NaN");
581
+ cnt = 3;
582
+ } else {
583
+ raise_json_err("NaN not allowed in JSON.", "GeneratorError");
584
+ }
630
585
  } else if (d == (double)(long long int)d) {
631
- cnt = snprintf(buf, sizeof(buf), "%.1f", d);
586
+ cnt = snprintf(buf, sizeof(buf), "%.1f", d);
632
587
  } else if (oj_rails_float_opt) {
633
- cnt = oj_dump_float_printf(buf, sizeof(buf), obj, d, "%0.16g");
588
+ cnt = oj_dump_float_printf(buf, sizeof(buf), obj, d, "%0.16g");
634
589
  } else {
635
- volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
590
+ volatile VALUE rstr = oj_safe_string_convert(obj);
636
591
 
637
- strcpy(buf, rb_string_value_ptr((VALUE*)&rstr));
638
- cnt = (int)RSTRING_LEN(rstr);
592
+ strcpy(buf, RSTRING_PTR(rstr));
593
+ cnt = (int)RSTRING_LEN(rstr);
639
594
  }
640
595
  assure_size(out, cnt);
641
- for (b = buf; '\0' != *b; b++) {
642
- *out->cur++ = *b;
643
- }
596
+ APPEND_CHARS(out->cur, buf, cnt);
644
597
  *out->cur = '\0';
645
598
  }
646
599
 
647
- static int
648
- hash_cb(VALUE key, VALUE value, VALUE ov) {
649
- Out out = (Out)ov;
650
- int depth = out->depth;
600
+ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
601
+ Out out = (Out)ov;
602
+ int depth = out->depth;
651
603
 
652
604
  if (out->omit_nil && Qnil == value) {
653
- return ST_CONTINUE;
605
+ return ST_CONTINUE;
654
606
  }
655
607
  if (!out->opts->dump_opts.use) {
656
- assure_size(out, depth * out->indent + 1);
657
- fill_indent(out, depth);
608
+ assure_size(out, depth * out->indent + 1);
609
+ fill_indent(out, depth);
658
610
  } else {
659
- assure_size(out, depth * out->opts->dump_opts.indent_size + out->opts->dump_opts.hash_size + 1);
660
- if (0 < out->opts->dump_opts.hash_size) {
661
- strcpy(out->cur, out->opts->dump_opts.hash_nl);
662
- out->cur += out->opts->dump_opts.hash_size;
663
- }
664
- if (0 < out->opts->dump_opts.indent_size) {
665
- int i;
666
- for (i = depth; 0 < i; i--) {
667
- strcpy(out->cur, out->opts->dump_opts.indent_str);
668
- out->cur += out->opts->dump_opts.indent_size;
669
- }
670
- }
611
+ assure_size(out, depth * out->opts->dump_opts.indent_size + out->opts->dump_opts.hash_size + 1);
612
+ if (0 < out->opts->dump_opts.hash_size) {
613
+ APPEND_CHARS(out->cur, out->opts->dump_opts.hash_nl, out->opts->dump_opts.hash_size);
614
+ }
615
+ if (0 < out->opts->dump_opts.indent_size) {
616
+ int i;
617
+ for (i = depth; 0 < i; i--) {
618
+ APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
619
+ }
620
+ }
671
621
  }
672
622
  switch (rb_type(key)) {
673
- case T_STRING:
674
- oj_dump_str(key, 0, out, false);
675
- break;
676
- case T_SYMBOL:
677
- oj_dump_sym(key, 0, out, false);
678
- break;
623
+ case T_STRING: oj_dump_str(key, 0, out, false); break;
624
+ case T_SYMBOL: oj_dump_sym(key, 0, out, false); break;
679
625
  default:
680
- /*rb_raise(rb_eTypeError, "In :compat mode all Hash keys must be Strings or Symbols, not %s.\n", rb_class2name(rb_obj_class(key)));*/
681
- oj_dump_str(rb_funcall(key, oj_to_s_id, 0), 0, out, false);
682
- break;
626
+ /*rb_raise(rb_eTypeError, "In :compat mode all Hash keys must be Strings or Symbols, not %s.\n",
627
+ * rb_class2name(rb_obj_class(key)));*/
628
+ oj_dump_str(oj_safe_string_convert(key), 0, out, false);
629
+ break;
683
630
  }
684
631
  if (!out->opts->dump_opts.use) {
685
- *out->cur++ = ':';
632
+ *out->cur++ = ':';
686
633
  } else {
687
- assure_size(out, out->opts->dump_opts.before_size + out->opts->dump_opts.after_size + 2);
688
- if (0 < out->opts->dump_opts.before_size) {
689
- strcpy(out->cur, out->opts->dump_opts.before_sep);
690
- out->cur += out->opts->dump_opts.before_size;
691
- }
692
- *out->cur++ = ':';
693
- if (0 < out->opts->dump_opts.after_size) {
694
- strcpy(out->cur, out->opts->dump_opts.after_sep);
695
- out->cur += out->opts->dump_opts.after_size;
696
- }
634
+ assure_size(out, out->opts->dump_opts.before_size + out->opts->dump_opts.after_size + 2);
635
+ if (0 < out->opts->dump_opts.before_size) {
636
+ APPEND_CHARS(out->cur, out->opts->dump_opts.before_sep, out->opts->dump_opts.before_size);
637
+ }
638
+ *out->cur++ = ':';
639
+ if (0 < out->opts->dump_opts.after_size) {
640
+ APPEND_CHARS(out->cur, out->opts->dump_opts.after_sep, out->opts->dump_opts.after_size);
641
+ }
697
642
  }
698
643
  oj_dump_compat_val(value, depth, out, true);
699
- out->depth = depth;
644
+ out->depth = depth;
700
645
  *out->cur++ = ',';
701
646
 
702
647
  return ST_CONTINUE;
703
648
  }
704
649
 
705
- static void
706
- dump_hash(VALUE obj, int depth, Out out, bool as_ok) {
707
- int cnt;
708
- long id = oj_check_circular(obj, out);
650
+ static void dump_hash(VALUE obj, int depth, Out out, bool as_ok) {
651
+ int cnt;
652
+ long id = oj_check_circular(obj, out);
709
653
 
710
654
  if (0 > id) {
711
- raise_json_err("Too deeply nested", "NestingError");
712
- return;
655
+ raise_json_err("Too deeply nested", "NestingError");
656
+ return;
713
657
  }
714
658
  if (as_ok && !oj_use_hash_alt && rb_obj_class(obj) != rb_cHash && rb_respond_to(obj, oj_to_json_id)) {
715
- dump_to_json(obj, out);
716
- return;
659
+ dump_to_json(obj, out);
660
+ return;
717
661
  }
718
662
  cnt = (int)RHASH_SIZE(obj);
719
663
  assure_size(out, 2);
720
664
  if (0 == cnt) {
721
- *out->cur++ = '{';
722
- *out->cur++ = '}';
665
+ APPEND_CHARS(out->cur, "{}", 2);
723
666
  } else {
724
- *out->cur++ = '{';
725
- out->depth = depth + 1;
726
- rb_hash_foreach(obj, hash_cb, (VALUE)out);
727
- if (',' == *(out->cur - 1)) {
728
- out->cur--; // backup to overwrite last comma
729
- }
730
- if (!out->opts->dump_opts.use) {
731
- assure_size(out, depth * out->indent + 2);
732
- fill_indent(out, depth);
733
- } else {
734
- assure_size(out, depth * out->opts->dump_opts.indent_size + out->opts->dump_opts.hash_size + 1);
735
- if (0 < out->opts->dump_opts.hash_size) {
736
- strcpy(out->cur, out->opts->dump_opts.hash_nl);
737
- out->cur += out->opts->dump_opts.hash_size;
738
- }
739
- if (0 < out->opts->dump_opts.indent_size) {
740
- int i;
741
-
742
- for (i = depth; 0 < i; i--) {
743
- strcpy(out->cur, out->opts->dump_opts.indent_str);
744
- out->cur += out->opts->dump_opts.indent_size;
745
- }
746
- }
747
- }
748
- *out->cur++ = '}';
667
+ *out->cur++ = '{';
668
+ out->depth = depth + 1;
669
+ rb_hash_foreach(obj, hash_cb, (VALUE)out);
670
+ if (',' == *(out->cur - 1)) {
671
+ out->cur--; // backup to overwrite last comma
672
+ }
673
+ if (!out->opts->dump_opts.use) {
674
+ assure_size(out, depth * out->indent + 2);
675
+ fill_indent(out, depth);
676
+ } else {
677
+ assure_size(out, depth * out->opts->dump_opts.indent_size + out->opts->dump_opts.hash_size + 1);
678
+ if (0 < out->opts->dump_opts.hash_size) {
679
+ APPEND_CHARS(out->cur, out->opts->dump_opts.hash_nl, out->opts->dump_opts.hash_size);
680
+ }
681
+ if (0 < out->opts->dump_opts.indent_size) {
682
+ int i;
683
+
684
+ for (i = depth; 0 < i; i--) {
685
+ APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
686
+ }
687
+ }
688
+ }
689
+ *out->cur++ = '}';
749
690
  }
750
691
  *out->cur = '\0';
751
692
  }
752
693
 
753
694
  // In compat mode only the first call check for to_json. After that to_s is
754
695
  // called.
755
- static void
756
- dump_obj(VALUE obj, int depth, Out out, bool as_ok) {
696
+ static void dump_obj(VALUE obj, int depth, Out out, bool as_ok) {
757
697
  if (oj_code_dump(oj_compat_codes, obj, depth, out)) {
758
- return;
698
+ return;
759
699
  }
760
700
  if (use_exception_alt && rb_obj_is_kind_of(obj, rb_eException)) {
761
- exception_alt(obj, depth, out);
762
- return;
701
+ exception_alt(obj, depth, out);
702
+ return;
763
703
  }
764
704
  if (Yes == out->opts->raw_json && rb_respond_to(obj, oj_raw_json_id)) {
765
- oj_dump_raw_json(obj, depth, out);
766
- return;
705
+ oj_dump_raw_json(obj, depth, out);
706
+ return;
767
707
  }
768
708
  if (as_ok && rb_respond_to(obj, oj_to_json_id)) {
769
- dump_to_json(obj, out);
770
- return;
709
+ dump_to_json(obj, out);
710
+ return;
771
711
  }
772
712
  // Nothing else matched so encode as a JSON object with Ruby obj members
773
713
  // as JSON object members.
774
714
  oj_dump_obj_to_s(obj, out);
775
715
  }
776
716
 
777
- static void
778
- dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
779
- VALUE clas = rb_obj_class(obj);
717
+ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
718
+ VALUE clas = rb_obj_class(obj);
780
719
 
781
720
  if (oj_code_dump(oj_compat_codes, obj, depth, out)) {
782
- return;
721
+ return;
783
722
  }
784
723
  if (rb_cRange == clas) {
785
- *out->cur++ = '"';
786
- oj_dump_compat_val(rb_funcall(obj, oj_begin_id, 0), 0, out, false);
787
- assure_size(out, 3);
788
- *out->cur++ = '.';
789
- *out->cur++ = '.';
790
- if (Qtrue == rb_funcall(obj, oj_exclude_end_id, 0)) {
791
- *out->cur++ = '.';
792
- }
793
- oj_dump_compat_val(rb_funcall(obj, oj_end_id, 0), 0, out, false);
794
- *out->cur++ = '"';
795
-
796
- return;
724
+ *out->cur++ = '"';
725
+ oj_dump_compat_val(rb_funcall(obj, oj_begin_id, 0), 0, out, false);
726
+ assure_size(out, 3);
727
+ APPEND_CHARS(out->cur, "..", 2);
728
+ if (Qtrue == rb_funcall(obj, oj_exclude_end_id, 0)) {
729
+ *out->cur++ = '.';
730
+ }
731
+ oj_dump_compat_val(rb_funcall(obj, oj_end_id, 0), 0, out, false);
732
+ *out->cur++ = '"';
733
+
734
+ return;
797
735
  }
798
736
  if (as_ok && rb_respond_to(obj, oj_to_json_id)) {
799
- dump_to_json(obj, out);
737
+ dump_to_json(obj, out);
800
738
 
801
- return;
739
+ return;
802
740
  }
803
741
  if (use_struct_alt) {
804
- int d3 = depth + 2;
805
- size_t size = d3 * out->indent + 2;
806
- size_t sep_len = out->opts->dump_opts.before_size + out->opts->dump_opts.after_size + 2;
807
- const char *classname = rb_class2name(rb_obj_class(obj));
808
- VALUE args[100];
809
- int cnt;
810
- int i;
811
-
812
- if (NULL == classname || '#' == *classname) {
813
- raise_json_err("Only named structs are supported.", "JSONError");
814
- }
742
+ int d3 = depth + 2;
743
+ size_t size = d3 * out->indent + 2;
744
+ size_t sep_len = out->opts->dump_opts.before_size + out->opts->dump_opts.after_size + 2;
745
+ const char *classname = rb_class2name(rb_obj_class(obj));
746
+ VALUE args[100];
747
+ int cnt;
748
+ int i;
749
+
750
+ if (NULL == classname || '#' == *classname) {
751
+ raise_json_err("Only named structs are supported.", "JSONError");
752
+ }
815
753
  #ifdef RSTRUCT_LEN
816
754
  #if RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
817
- cnt = (int)NUM2LONG(RSTRUCT_LEN(obj));
818
- #else // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
819
- cnt = (int)RSTRUCT_LEN(obj);
820
- #endif // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
755
+ cnt = (int)NUM2LONG(RSTRUCT_LEN(obj));
756
+ #else // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
757
+ cnt = (int)RSTRUCT_LEN(obj);
758
+ #endif // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
821
759
  #else
822
- // This is a bit risky as a struct in C ruby is not the same as a Struct
823
- // class in interpreted Ruby so length() may not be defined.
824
- cnt = FIX2INT(rb_funcall2(obj, oj_length_id, 0, 0));
760
+ // This is a bit risky as a struct in C ruby is not the same as a Struct
761
+ // class in interpreted Ruby so length() may not be defined.
762
+ cnt = FIX2INT(rb_funcall2(obj, oj_length_id, 0, 0));
825
763
  #endif
826
- if (sizeof(args) / sizeof(*args) <= (size_t)cnt) {
827
- // TBD allocate and try again
828
- cnt = 99;
829
- }
830
- dump_obj_classname(rb_class2name(rb_obj_class(obj)), depth, out);
831
-
832
- assure_size(out, size + sep_len + 6);
833
- *out->cur++ = ',';
834
- fill_indent(out, d3);
835
- *out->cur++ = '"';
836
- *out->cur++ = 'v';
837
- *out->cur++ = '"';
838
- if (0 < out->opts->dump_opts.before_size) {
839
- strcpy(out->cur, out->opts->dump_opts.before_sep);
840
- out->cur += out->opts->dump_opts.before_size;
841
- }
842
- *out->cur++ = ':';
843
- if (0 < out->opts->dump_opts.after_size) {
844
- strcpy(out->cur, out->opts->dump_opts.after_sep);
845
- out->cur += out->opts->dump_opts.after_size;
846
- }
847
- for (i = 0; i < cnt; i++) {
764
+ if (sizeof(args) / sizeof(*args) <= (size_t)cnt) {
765
+ // TBD allocate and try again
766
+ cnt = 99;
767
+ }
768
+ dump_obj_classname(rb_class2name(rb_obj_class(obj)), depth, out);
769
+
770
+ assure_size(out, size + sep_len + 6);
771
+ *out->cur++ = ',';
772
+ fill_indent(out, d3);
773
+ APPEND_CHARS(out->cur, "\"v\"", 3);
774
+ if (0 < out->opts->dump_opts.before_size) {
775
+ APPEND_CHARS(out->cur, out->opts->dump_opts.before_sep, out->opts->dump_opts.before_size);
776
+ }
777
+ *out->cur++ = ':';
778
+ if (0 < out->opts->dump_opts.after_size) {
779
+ APPEND_CHARS(out->cur, out->opts->dump_opts.after_sep, out->opts->dump_opts.after_size);
780
+ }
781
+ for (i = 0; i < cnt; i++) {
848
782
  #ifdef RSTRUCT_LEN
849
- args[i] = RSTRUCT_GET(obj, i);
783
+ args[i] = RSTRUCT_GET(obj, i);
850
784
  #else
851
- args[i] = rb_struct_aref(obj, INT2FIX(i));
785
+ args[i] = rb_struct_aref(obj, INT2FIX(i));
852
786
  #endif
853
- }
854
- args[cnt] = Qundef;
855
- dump_values_array(args, depth, out);
856
- fill_indent(out, depth);
857
- *out->cur++ = '}';
858
- *out->cur = '\0';
787
+ }
788
+ args[cnt] = Qundef;
789
+ dump_values_array(args, depth, out);
790
+ fill_indent(out, depth);
791
+ *out->cur++ = '}';
792
+ *out->cur = '\0';
859
793
  } else {
860
- oj_dump_obj_to_s(obj, out);
794
+ oj_dump_obj_to_s(obj, out);
861
795
  }
862
796
  }
863
797
 
864
- static void
865
- dump_bignum(VALUE obj, int depth, Out out, bool as_ok) {
798
+ static void dump_bignum(VALUE obj, int depth, Out out, bool as_ok) {
866
799
  // The json gem uses to_s explicitly. to_s can be overridden while
867
800
  // rb_big2str can not so unless overridden by using add_to_json(Integer)
868
801
  // this must use to_s to pass the json gem unit tests.
869
- volatile VALUE rs;
870
- int cnt;
871
- bool dump_as_string = false;
802
+ volatile VALUE rs;
803
+ int cnt;
804
+ bool dump_as_string = false;
872
805
 
873
806
  if (use_bignum_alt) {
874
- rs = rb_big2str(obj, 10);
807
+ rs = rb_big2str(obj, 10);
875
808
  } else {
876
- rs = rb_funcall(obj, oj_to_s_id, 0);
809
+ rs = oj_safe_string_convert(obj);
877
810
  }
878
811
  rb_check_type(rs, T_STRING);
879
812
  cnt = (int)RSTRING_LEN(rs);
880
813
 
881
814
  if (out->opts->int_range_min != 0 || out->opts->int_range_max != 0) {
882
- dump_as_string = true; // Bignum cannot be inside of Fixnum range
883
- assure_size(out, cnt + 2);
884
- *out->cur++ = '"';
815
+ dump_as_string = true; // Bignum cannot be inside of Fixnum range
816
+ assure_size(out, cnt + 2);
817
+ *out->cur++ = '"';
885
818
  } else {
886
- assure_size(out, cnt);
819
+ assure_size(out, cnt);
887
820
  }
888
- memcpy(out->cur, rb_string_value_ptr((VALUE*)&rs), cnt);
889
- out->cur += cnt;
821
+ APPEND_CHARS(out->cur, RSTRING_PTR(rs), cnt);
890
822
  if (dump_as_string) {
891
- *out->cur++ = '"';
823
+ *out->cur++ = '"';
892
824
  }
893
825
  *out->cur = '\0';
894
826
  }
895
827
 
896
- static DumpFunc compat_funcs[] = {
897
- NULL, // RUBY_T_NONE = 0x00,
898
- dump_obj, // RUBY_T_OBJECT = 0x01,
899
- oj_dump_class, // RUBY_T_CLASS = 0x02,
900
- oj_dump_class, // RUBY_T_MODULE = 0x03,
901
- dump_float, // RUBY_T_FLOAT = 0x04,
902
- oj_dump_str, // RUBY_T_STRING = 0x05,
903
- dump_obj, // RUBY_T_REGEXP = 0x06,
904
- dump_array, // RUBY_T_ARRAY = 0x07,
905
- dump_hash, // RUBY_T_HASH = 0x08,
906
- dump_struct, // RUBY_T_STRUCT = 0x09,
907
- dump_bignum, // RUBY_T_BIGNUM = 0x0a,
908
- NULL, // RUBY_T_FILE = 0x0b,
909
- dump_obj, // RUBY_T_DATA = 0x0c,
910
- NULL, // RUBY_T_MATCH = 0x0d,
911
- dump_obj, // RUBY_T_COMPLEX = 0x0e,
912
- dump_obj, // RUBY_T_RATIONAL = 0x0f,
913
- NULL, // 0x10
914
- oj_dump_nil, // RUBY_T_NIL = 0x11,
915
- oj_dump_true, // RUBY_T_TRUE = 0x12,
916
- oj_dump_false, // RUBY_T_FALSE = 0x13,
917
- oj_dump_sym, // RUBY_T_SYMBOL = 0x14,
918
- oj_dump_fixnum, // RUBY_T_FIXNUM = 0x15,
828
+ static DumpFunc compat_funcs[] = {
829
+ NULL, // RUBY_T_NONE = 0x00,
830
+ dump_obj, // RUBY_T_OBJECT = 0x01,
831
+ oj_dump_class, // RUBY_T_CLASS = 0x02,
832
+ oj_dump_class, // RUBY_T_MODULE = 0x03,
833
+ dump_float, // RUBY_T_FLOAT = 0x04,
834
+ oj_dump_str, // RUBY_T_STRING = 0x05,
835
+ dump_obj, // RUBY_T_REGEXP = 0x06,
836
+ dump_array, // RUBY_T_ARRAY = 0x07,
837
+ dump_hash, // RUBY_T_HASH = 0x08,
838
+ dump_struct, // RUBY_T_STRUCT = 0x09,
839
+ dump_bignum, // RUBY_T_BIGNUM = 0x0a,
840
+ NULL, // RUBY_T_FILE = 0x0b,
841
+ dump_obj, // RUBY_T_DATA = 0x0c,
842
+ NULL, // RUBY_T_MATCH = 0x0d,
843
+ dump_obj, // RUBY_T_COMPLEX = 0x0e,
844
+ dump_obj, // RUBY_T_RATIONAL = 0x0f,
845
+ NULL, // 0x10
846
+ oj_dump_nil, // RUBY_T_NIL = 0x11,
847
+ oj_dump_true, // RUBY_T_TRUE = 0x12,
848
+ oj_dump_false, // RUBY_T_FALSE = 0x13,
849
+ oj_dump_sym, // RUBY_T_SYMBOL = 0x14,
850
+ oj_dump_fixnum, // RUBY_T_FIXNUM = 0x15,
919
851
  };
920
852
 
921
- static void
922
- set_state_depth(VALUE state, int depth) {
923
- VALUE json_module = rb_const_get_at(rb_cObject, rb_intern("JSON"));
924
- VALUE ext = rb_const_get(json_module, rb_intern("Ext"));
925
- VALUE generator = rb_const_get(ext, rb_intern("Generator"));
926
- VALUE state_class = rb_const_get(generator, rb_intern("State"));
853
+ static void set_state_depth(VALUE state, int depth) {
854
+ if (0 == rb_const_defined(rb_cObject, rb_intern("JSON"))) {
855
+ rb_require("oj/json");
856
+ }
857
+ {
858
+ VALUE json_module = rb_const_get_at(rb_cObject, rb_intern("JSON"));
859
+ VALUE ext = rb_const_get(json_module, rb_intern("Ext"));
860
+ VALUE generator = rb_const_get(ext, rb_intern("Generator"));
861
+ VALUE state_class = rb_const_get(generator, rb_intern("State"));
927
862
 
928
- if (state_class == rb_obj_class(state)) {
929
- rb_funcall(state, rb_intern("depth="), 1, INT2NUM(depth));
863
+ if (state_class == rb_obj_class(state)) {
864
+ rb_funcall(state, rb_intern("depth="), 1, INT2NUM(depth));
865
+ }
930
866
  }
931
867
  }
932
868
 
933
- void
934
- oj_dump_compat_val(VALUE obj, int depth, Out out, bool as_ok) {
935
- int type = rb_type(obj);
869
+ void oj_dump_compat_val(VALUE obj, int depth, Out out, bool as_ok) {
870
+ int type = rb_type(obj);
936
871
 
937
- if (Yes == out->opts->trace) {
938
- oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceIn);
939
- }
872
+ TRACE(out->opts->trace, "dump", obj, depth, TraceIn);
873
+ // The max_nesting logic is that an empty Array or Hash is assumed to have
874
+ // content so the max_nesting should fail but a non-collection value is
875
+ // okay. That means a check for a collectable value is needed before
876
+ // raising.
940
877
  if (out->opts->dump_opts.max_depth <= depth) {
941
- // When JSON.dump is called then an ArgumentError is expected and the
942
- // limit is the depth inclusive. If JSON.generate is called then a
943
- // NestingError is expected and the limit is inclusive. Worse than
944
- // that there are unit tests for both.
945
- if (CALLER_DUMP == out->caller) {
946
- if (0 < out->argc) {
947
- set_state_depth(*out->argv, depth);
948
- }
949
- rb_raise(rb_eArgError, "Too deeply nested.");
950
- } else if (out->opts->dump_opts.max_depth < depth) {
951
- if (0 < out->argc) {
952
- set_state_depth(*out->argv, depth - 1);
953
- }
954
- raise_json_err("Too deeply nested", "NestingError");
955
- }
878
+ if (RUBY_T_ARRAY == type || RUBY_T_HASH == type) {
879
+ if (0 < out->argc) {
880
+ set_state_depth(*out->argv, depth);
881
+ }
882
+ raise_json_err("Too deeply nested", "NestingError");
883
+ }
956
884
  }
957
885
  if (0 < type && type <= RUBY_T_FIXNUM) {
958
- DumpFunc f = compat_funcs[type];
886
+ DumpFunc f = compat_funcs[type];
959
887
 
960
- if (NULL != f) {
961
- f(obj, depth, out, as_ok);
962
- if (Yes == out->opts->trace) {
963
- oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceOut);
964
- }
965
- return;
966
- }
888
+ if (NULL != f) {
889
+ f(obj, depth, out, as_ok);
890
+ TRACE(out->opts->trace, "dump", obj, depth, TraceOut);
891
+ return;
892
+ }
967
893
  }
968
894
  oj_dump_nil(Qnil, depth, out, false);
969
- if (Yes == out->opts->trace) {
970
- oj_trace("dump", Qnil, __FILE__, __LINE__, depth, TraceOut);
971
- }
895
+ TRACE(out->opts->trace, "dump", Qnil, depth, TraceOut);
972
896
  }