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