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_object.c CHANGED
@@ -1,841 +1,700 @@
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 "dump.h"
5
+ #include "mem.h"
4
6
  #include "odd.h"
5
7
  #include "trace.h"
6
8
 
7
- static const char hex_chars[17] = "0123456789abcdef";
9
+ static const char hex_chars[17] = "0123456789abcdef";
8
10
 
9
- static void dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out);
11
+ static void dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out);
10
12
 
11
- static void
12
- dump_time(VALUE obj, Out out) {
13
+ static void dump_time(VALUE obj, Out out) {
13
14
  switch (out->opts->time_format) {
14
15
  case RubyTime:
15
- case XmlTime: oj_dump_xml_time(obj, out); break;
16
- case UnixZTime: oj_dump_time(obj, out, 1); break;
16
+ case XmlTime: oj_dump_xml_time(obj, out); break;
17
+ case UnixZTime: oj_dump_time(obj, out, 1); break;
17
18
  case UnixTime:
18
- default: oj_dump_time(obj, out, 0); break;
19
+ default: oj_dump_time(obj, out, 0); break;
19
20
  }
20
21
  }
21
22
 
22
- static void
23
- dump_data(VALUE obj, int depth, Out out, bool as_ok) {
24
- VALUE clas = rb_obj_class(obj);
23
+ static void dump_data(VALUE obj, int depth, Out out, bool as_ok) {
24
+ VALUE clas = rb_obj_class(obj);
25
25
 
26
26
  if (rb_cTime == clas) {
27
- assure_size(out, 6);
28
- *out->cur++ = '{';
29
- *out->cur++ = '"';
30
- *out->cur++ = '^';
31
- *out->cur++ = 't';
32
- *out->cur++ = '"';
33
- *out->cur++ = ':';
34
- dump_time(obj, out);
35
- *out->cur++ = '}';
36
- *out->cur = '\0';
27
+ assure_size(out, 6);
28
+ APPEND_CHARS(out->cur, "{\"^t\":", 6);
29
+ dump_time(obj, out);
30
+ *out->cur++ = '}';
31
+ *out->cur = '\0';
37
32
  } else {
38
- if (oj_bigdecimal_class == clas) {
39
- volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
40
- const char *str = rb_string_value_ptr((VALUE*)&rstr);
41
- int len = (int)RSTRING_LEN(rstr);
42
-
43
- if (No != out->opts->bigdec_as_num) {
44
- oj_dump_raw(str, len, out);
45
- } else if (0 == strcasecmp("Infinity", str)) {
46
- str = oj_nan_str(obj, out->opts->dump_opts.nan_dump, out->opts->mode, true, &len);
47
- oj_dump_raw(str, len, out);
48
- } else if (0 == strcasecmp("-Infinity", str)) {
49
- str = oj_nan_str(obj, out->opts->dump_opts.nan_dump, out->opts->mode, false, &len);
50
- oj_dump_raw(str, len, out);
51
- } else {
52
- oj_dump_cstr(str, len, 0, 0, out);
53
- }
54
- } else {
55
- long id = oj_check_circular(obj, out);
56
-
57
- if (0 <= id) {
58
- dump_obj_attrs(obj, clas, id, depth, out);
59
- }
60
- }
33
+ if (oj_bigdecimal_class == clas) {
34
+ volatile VALUE rstr = oj_safe_string_convert(obj);
35
+ const char *str = RSTRING_PTR(rstr);
36
+ int len = (int)RSTRING_LEN(rstr);
37
+
38
+ if (No != out->opts->bigdec_as_num) {
39
+ oj_dump_raw(str, len, out);
40
+ } else if (0 == strcasecmp("Infinity", str)) {
41
+ str = oj_nan_str(obj, out->opts->dump_opts.nan_dump, out->opts->mode, true, &len);
42
+ oj_dump_raw(str, len, out);
43
+ } else if (0 == strcasecmp("-Infinity", str)) {
44
+ str = oj_nan_str(obj, out->opts->dump_opts.nan_dump, out->opts->mode, false, &len);
45
+ oj_dump_raw(str, len, out);
46
+ } else {
47
+ oj_dump_cstr(str, len, 0, 0, out);
48
+ }
49
+ } else {
50
+ long id = oj_check_circular(obj, out);
51
+
52
+ if (0 <= id) {
53
+ dump_obj_attrs(obj, clas, id, depth, out);
54
+ }
55
+ }
61
56
  }
62
57
  }
63
58
 
64
- static void
65
- dump_obj(VALUE obj, int depth, Out out, bool as_ok) {
66
- VALUE clas = rb_obj_class(obj);
59
+ static void dump_obj(VALUE obj, int depth, Out out, bool as_ok) {
60
+ VALUE clas = rb_obj_class(obj);
67
61
 
68
62
  if (oj_bigdecimal_class == clas) {
69
- volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
70
- const char *str = rb_string_value_ptr((VALUE*)&rstr);
71
- int len = (int)RSTRING_LEN(rstr);
72
-
73
- if (0 == strcasecmp("Infinity", str)) {
74
- str = oj_nan_str(obj, out->opts->dump_opts.nan_dump, out->opts->mode, true, &len);
75
- oj_dump_raw(str, len, out);
76
- } else if (0 == strcasecmp("-Infinity", str)) {
77
- str = oj_nan_str(obj, out->opts->dump_opts.nan_dump, out->opts->mode, false, &len);
78
- oj_dump_raw(str, len, out);
79
- } else {
80
- oj_dump_raw(str, len, out);
81
- }
63
+ volatile VALUE rstr = oj_safe_string_convert(obj);
64
+ const char *str = RSTRING_PTR(rstr);
65
+ int len = (int)RSTRING_LEN(rstr);
66
+
67
+ if (0 == strcasecmp("Infinity", str)) {
68
+ str = oj_nan_str(obj, out->opts->dump_opts.nan_dump, out->opts->mode, true, &len);
69
+ oj_dump_raw(str, len, out);
70
+ } else if (0 == strcasecmp("-Infinity", str)) {
71
+ str = oj_nan_str(obj, out->opts->dump_opts.nan_dump, out->opts->mode, false, &len);
72
+ oj_dump_raw(str, len, out);
73
+ } else {
74
+ oj_dump_raw(str, len, out);
75
+ }
82
76
  } else {
83
- long id = oj_check_circular(obj, out);
77
+ long id = oj_check_circular(obj, out);
84
78
 
85
- if (0 <= id) {
86
- dump_obj_attrs(obj, clas, id, depth, out);
87
- }
79
+ if (0 <= id) {
80
+ dump_obj_attrs(obj, clas, id, depth, out);
81
+ }
88
82
  }
89
83
  }
90
84
 
91
- static void
92
- dump_class(VALUE obj, int depth, Out out, bool as_ok) {
93
- const char *s = rb_class2name(obj);
94
- size_t len = strlen(s);
85
+ static void dump_class(VALUE obj, int depth, Out out, bool as_ok) {
86
+ const char *s = rb_class2name(obj);
87
+ size_t len = strlen(s);
95
88
 
96
89
  assure_size(out, 6);
97
- *out->cur++ = '{';
98
- *out->cur++ = '"';
99
- *out->cur++ = '^';
100
- *out->cur++ = 'c';
101
- *out->cur++ = '"';
102
- *out->cur++ = ':';
90
+ APPEND_CHARS(out->cur, "{\"^c\":", 6);
103
91
  oj_dump_cstr(s, len, 0, 0, out);
104
92
  *out->cur++ = '}';
105
- *out->cur = '\0';
93
+ *out->cur = '\0';
106
94
  }
107
95
 
108
- static void
109
- dump_array_class(VALUE a, VALUE clas, int depth, Out out) {
110
- size_t size;
111
- int i, cnt;
112
- int d2 = depth + 1;
113
- long id = oj_check_circular(a, out);
96
+ static void dump_array_class(VALUE a, VALUE clas, int depth, Out out) {
97
+ size_t size;
98
+ int i, cnt;
99
+ int d2 = depth + 1;
100
+ long id = oj_check_circular(a, out);
114
101
 
115
102
  if (id < 0) {
116
- return;
103
+ return;
117
104
  }
118
105
  if (Qundef != clas && rb_cArray != clas && ObjectMode == out->opts->mode) {
119
- dump_obj_attrs(a, clas, 0, depth, out);
120
- return;
106
+ dump_obj_attrs(a, clas, 0, depth, out);
107
+ return;
121
108
  }
122
- cnt = (int)RARRAY_LEN(a);
109
+ cnt = (int)RARRAY_LEN(a);
123
110
  *out->cur++ = '[';
124
111
  if (0 < id) {
125
- assure_size(out, d2 * out->indent + 16);
126
- fill_indent(out, d2);
127
- *out->cur++ = '"';
128
- *out->cur++ = '^';
129
- *out->cur++ = 'i';
130
- dump_ulong(id, out);
131
- *out->cur++ = '"';
112
+ assure_size(out, d2 * out->indent + 16);
113
+ fill_indent(out, d2);
114
+ APPEND_CHARS(out->cur, "\"^i", 3);
115
+ dump_ulong(id, out);
116
+ *out->cur++ = '"';
132
117
  }
133
118
  size = 2;
134
119
  assure_size(out, 2);
135
120
  if (0 == cnt) {
136
- *out->cur++ = ']';
121
+ *out->cur++ = ']';
137
122
  } else {
138
- if (0 < id) {
139
- *out->cur++ = ',';
140
- }
141
- if (out->opts->dump_opts.use) {
142
- size = d2 * out->opts->dump_opts.indent_size + out->opts->dump_opts.array_size + 1;
143
- } else {
144
- size = d2 * out->indent + 2;
145
- }
146
- cnt--;
147
- for (i = 0; i <= cnt; i++) {
148
- assure_size(out, size);
149
- if (out->opts->dump_opts.use) {
150
- if (0 < out->opts->dump_opts.array_size) {
151
- strcpy(out->cur, out->opts->dump_opts.array_nl);
152
- out->cur += out->opts->dump_opts.array_size;
153
- }
154
- if (0 < out->opts->dump_opts.indent_size) {
155
- int i;
156
- for (i = d2; 0 < i; i--) {
157
- strcpy(out->cur, out->opts->dump_opts.indent_str);
158
- out->cur += out->opts->dump_opts.indent_size;
159
- }
160
- }
161
- } else {
162
- fill_indent(out, d2);
163
- }
164
- oj_dump_obj_val(rb_ary_entry(a, i), d2, out);
165
- if (i < cnt) {
166
- *out->cur++ = ',';
167
- }
168
- }
169
- size = depth * out->indent + 1;
170
- assure_size(out, size);
171
- if (out->opts->dump_opts.use) {
172
- //printf("*** d2: %u indent: %u '%s'\n", d2, out->opts->dump_opts->indent_size, out->opts->dump_opts->indent);
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
-
180
- for (i = depth; 0 < i; i--) {
181
- strcpy(out->cur, out->opts->dump_opts.indent_str);
182
- out->cur += out->opts->dump_opts.indent_size;
183
- }
184
- }
185
- } else {
186
- fill_indent(out, depth);
187
- }
188
- *out->cur++ = ']';
123
+ if (0 < id) {
124
+ *out->cur++ = ',';
125
+ }
126
+ if (out->opts->dump_opts.use) {
127
+ size = d2 * out->opts->dump_opts.indent_size + out->opts->dump_opts.array_size + 1;
128
+ } else {
129
+ size = d2 * out->indent + 2;
130
+ }
131
+ assure_size(out, size * cnt);
132
+ cnt--;
133
+ for (i = 0; i <= cnt; i++) {
134
+ if (out->opts->dump_opts.use) {
135
+ if (0 < out->opts->dump_opts.array_size) {
136
+ APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
137
+ }
138
+ if (0 < out->opts->dump_opts.indent_size) {
139
+ int i;
140
+ for (i = d2; 0 < i; i--) {
141
+ APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
142
+ }
143
+ }
144
+ } else {
145
+ fill_indent(out, d2);
146
+ }
147
+ oj_dump_obj_val(RARRAY_AREF(a, i), d2, out);
148
+ if (i < cnt) {
149
+ *out->cur++ = ',';
150
+ }
151
+ }
152
+ size = depth * out->indent + 1;
153
+ assure_size(out, size);
154
+ if (out->opts->dump_opts.use) {
155
+ // printf("*** d2: %u indent: %u '%s'\n", d2, out->opts->dump_opts->indent_size,
156
+ // out->opts->dump_opts->indent);
157
+ if (0 < out->opts->dump_opts.array_size) {
158
+ APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
159
+ }
160
+ if (0 < out->opts->dump_opts.indent_size) {
161
+ int i;
162
+
163
+ for (i = depth; 0 < i; i--) {
164
+ APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
165
+ }
166
+ }
167
+ } else {
168
+ fill_indent(out, depth);
169
+ }
170
+ *out->cur++ = ']';
189
171
  }
190
172
  *out->cur = '\0';
191
173
  }
192
174
 
193
- static void
194
- dump_array(VALUE obj, int depth, Out out, bool as_ok) {
175
+ static void dump_array(VALUE obj, int depth, Out out, bool as_ok) {
195
176
  dump_array_class(obj, rb_obj_class(obj), depth, out);
196
177
  }
197
178
 
198
- static void
199
- dump_str_class(VALUE obj, VALUE clas, int depth, Out out) {
179
+ static void dump_str_class(VALUE obj, VALUE clas, int depth, Out out) {
200
180
  if (Qundef != clas && rb_cString != clas) {
201
- dump_obj_attrs(obj, clas, 0, depth, out);
181
+ dump_obj_attrs(obj, clas, 0, depth, out);
202
182
  } else {
203
- const char *s = rb_string_value_ptr((VALUE*)&obj);
204
- size_t len = (int)RSTRING_LEN(obj);
205
- char s1 = s[1];
183
+ const char *s = RSTRING_PTR(obj);
184
+ size_t len = (int)RSTRING_LEN(obj);
185
+ char s1 = s[1];
206
186
 
207
- oj_dump_cstr(s, len, 0, (':' == *s || ('^' == *s && ('r' == s1 || 'i' == s1))), out);
187
+ oj_dump_cstr(s, len, 0, (':' == *s || ('^' == *s && ('r' == s1 || 'i' == s1))), out);
208
188
  }
209
189
  }
210
190
 
211
- static void
212
- dump_str(VALUE obj, int depth, Out out, bool as_ok) {
191
+ static void dump_str(VALUE obj, int depth, Out out, bool as_ok) {
213
192
  dump_str_class(obj, rb_obj_class(obj), depth, out);
214
193
  }
215
194
 
216
- static void
217
- dump_sym(VALUE obj, int depth, Out out, bool as_ok) {
218
- volatile VALUE s = rb_sym_to_s(obj);
195
+ static void dump_sym(VALUE obj, int depth, Out out, bool as_ok) {
196
+ volatile VALUE s = rb_sym2str(obj);
219
197
 
220
- oj_dump_cstr(rb_string_value_ptr((VALUE*)&s), (int)RSTRING_LEN(s), 1, 0, out);
198
+ oj_dump_cstr(RSTRING_PTR(s), (int)RSTRING_LEN(s), 1, 0, out);
221
199
  }
222
200
 
223
- static int
224
- hash_cb(VALUE key, VALUE value, VALUE ov) {
225
- Out out = (Out)ov;
226
- int depth = out->depth;
227
- long size = depth * out->indent + 1;
201
+ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
202
+ Out out = (Out)ov;
203
+ int depth = out->depth;
204
+ long size = depth * out->indent + 1;
228
205
 
229
- if (oj_dump_ignore(out->opts, value)) {
230
- return ST_CONTINUE;
206
+ if (dump_ignore(out->opts, value)) {
207
+ return ST_CONTINUE;
231
208
  }
232
209
  if (out->omit_nil && Qnil == value) {
233
- return ST_CONTINUE;
210
+ return ST_CONTINUE;
234
211
  }
235
212
  assure_size(out, size);
236
213
  fill_indent(out, depth);
237
- if (rb_type(key) == T_STRING) {
238
- dump_str_class(key, Qundef, depth, out);
239
- *out->cur++ = ':';
240
- oj_dump_obj_val(value, depth, out);
241
- } else if (rb_type(key) == T_SYMBOL) {
242
- dump_sym(key, 0, out, false);
243
- *out->cur++ = ':';
244
- oj_dump_obj_val(value, depth, out);
245
- } else {
246
- int d2 = depth + 1;
247
- long s2 = size + out->indent + 1;
248
- int i;
249
- int started = 0;
250
- uint8_t b;
251
-
252
- assure_size(out, s2 + 15);
253
- *out->cur++ = '"';
254
- *out->cur++ = '^';
255
- *out->cur++ = '#';
256
- out->hash_cnt++;
257
- for (i = 28; 0 <= i; i -= 4) {
258
- b = (uint8_t)((out->hash_cnt >> i) & 0x0000000F);
259
- if ('\0' != b) {
260
- started = 1;
261
- }
262
- if (started) {
263
- *out->cur++ = hex_chars[b];
264
- }
265
- }
266
- *out->cur++ = '"';
267
- *out->cur++ = ':';
268
- *out->cur++ = '[';
269
- fill_indent(out, d2);
270
- oj_dump_obj_val(key, d2, out);
271
- assure_size(out, s2);
272
- *out->cur++ = ',';
273
- fill_indent(out, d2);
274
- oj_dump_obj_val(value, d2, out);
275
- assure_size(out, size);
276
- fill_indent(out, depth);
277
- *out->cur++ = ']';
278
- }
279
- out->depth = depth;
214
+ switch (rb_type(key)) {
215
+ case T_STRING:
216
+ dump_str_class(key, Qundef, depth, out);
217
+ *out->cur++ = ':';
218
+ oj_dump_obj_val(value, depth, out);
219
+ break;
220
+
221
+ case T_SYMBOL:
222
+ dump_sym(key, 0, out, false);
223
+ *out->cur++ = ':';
224
+ oj_dump_obj_val(value, depth, out);
225
+ break;
226
+
227
+ default: {
228
+ int d2 = depth + 1;
229
+ long s2 = size + out->indent + 1;
230
+ int i;
231
+ int started = 0;
232
+ uint8_t b;
233
+
234
+ assure_size(out, s2 + 15);
235
+ APPEND_CHARS(out->cur, "\"^#", 3);
236
+ out->hash_cnt++;
237
+ for (i = 28; 0 <= i; i -= 4) {
238
+ b = (uint8_t)((out->hash_cnt >> i) & 0x0000000F);
239
+ if ('\0' != b) {
240
+ started = 1;
241
+ }
242
+ if (started) {
243
+ *out->cur++ = hex_chars[b];
244
+ }
245
+ }
246
+ APPEND_CHARS(out->cur, "\":[", 3);
247
+ fill_indent(out, d2);
248
+ oj_dump_obj_val(key, d2, out);
249
+ assure_size(out, s2);
250
+ *out->cur++ = ',';
251
+ fill_indent(out, d2);
252
+ oj_dump_obj_val(value, d2, out);
253
+ assure_size(out, size);
254
+ fill_indent(out, depth);
255
+ *out->cur++ = ']';
256
+ }
257
+ }
258
+ out->depth = depth;
280
259
  *out->cur++ = ',';
281
260
 
282
261
  return ST_CONTINUE;
283
262
  }
284
263
 
285
- static void
286
- dump_hash_class(VALUE obj, VALUE clas, int depth, Out out) {
287
- int cnt;
288
- size_t size;
264
+ static void dump_hash_class(VALUE obj, VALUE clas, int depth, Out out) {
265
+ int cnt;
266
+ size_t size;
289
267
 
290
268
  if (Qundef != clas && rb_cHash != clas) {
291
- dump_obj_attrs(obj, clas, 0, depth, out);
292
- return;
269
+ dump_obj_attrs(obj, clas, 0, depth, out);
270
+ return;
293
271
  }
294
- cnt = (int)RHASH_SIZE(obj);
272
+ cnt = (int)RHASH_SIZE(obj);
295
273
  size = depth * out->indent + 2;
296
274
  assure_size(out, 2);
297
275
  if (0 == cnt) {
298
- *out->cur++ = '{';
299
- *out->cur++ = '}';
276
+ APPEND_CHARS(out->cur, "{}", 2);
300
277
  } else {
301
- long id = oj_check_circular(obj, out);
302
-
303
- if (0 > id) {
304
- return;
305
- }
306
- *out->cur++ = '{';
307
- if (0 < id) {
308
- assure_size(out, size + 16);
309
- fill_indent(out, depth + 1);
310
- *out->cur++ = '"';
311
- *out->cur++ = '^';
312
- *out->cur++ = 'i';
313
- *out->cur++ = '"';
314
- *out->cur++ = ':';
315
- dump_ulong(id, out);
316
- *out->cur++ = ',';
317
- }
318
- out->depth = depth + 1;
319
- rb_hash_foreach(obj, hash_cb, (VALUE)out);
320
- if (',' == *(out->cur - 1)) {
321
- out->cur--; // backup to overwrite last comma
322
- }
323
- if (!out->opts->dump_opts.use) {
324
- assure_size(out, size);
325
- fill_indent(out, depth);
326
- } else {
327
- size = depth * out->opts->dump_opts.indent_size + out->opts->dump_opts.hash_size + 1;
328
- assure_size(out, size);
329
- if (0 < out->opts->dump_opts.hash_size) {
330
- strcpy(out->cur, out->opts->dump_opts.hash_nl);
331
- out->cur += out->opts->dump_opts.hash_size;
332
- }
333
- if (0 < out->opts->dump_opts.indent_size) {
334
- int i;
335
-
336
- for (i = depth; 0 < i; i--) {
337
- strcpy(out->cur, out->opts->dump_opts.indent_str);
338
- out->cur += out->opts->dump_opts.indent_size;
339
- }
340
- }
341
- }
342
- *out->cur++ = '}';
278
+ long id = oj_check_circular(obj, out);
279
+
280
+ if (0 > id) {
281
+ return;
282
+ }
283
+ *out->cur++ = '{';
284
+ if (0 < id) {
285
+ assure_size(out, size + 16);
286
+ fill_indent(out, depth + 1);
287
+ APPEND_CHARS(out->cur, "\"^i\":", 5);
288
+ dump_ulong(id, out);
289
+ *out->cur++ = ',';
290
+ }
291
+ out->depth = depth + 1;
292
+ rb_hash_foreach(obj, hash_cb, (VALUE)out);
293
+ if (',' == *(out->cur - 1)) {
294
+ out->cur--; // backup to overwrite last comma
295
+ }
296
+ if (!out->opts->dump_opts.use) {
297
+ assure_size(out, size);
298
+ fill_indent(out, depth);
299
+ } else {
300
+ size = depth * out->opts->dump_opts.indent_size + out->opts->dump_opts.hash_size + 1;
301
+ assure_size(out, size);
302
+ if (0 < out->opts->dump_opts.hash_size) {
303
+ APPEND_CHARS(out->cur, out->opts->dump_opts.hash_nl, out->opts->dump_opts.hash_size);
304
+ }
305
+ if (0 < out->opts->dump_opts.indent_size) {
306
+ int i;
307
+
308
+ for (i = depth; 0 < i; i--) {
309
+ APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
310
+ }
311
+ }
312
+ }
313
+ *out->cur++ = '}';
343
314
  }
344
315
  *out->cur = '\0';
345
316
  }
346
317
 
347
- #ifdef HAVE_RB_IVAR_FOREACH
348
- static int
349
- dump_attr_cb(ID key, VALUE value, VALUE ov) {
350
- Out out = (Out)ov;
351
- int depth = out->depth;
352
- size_t size = depth * out->indent + 1;
353
- const char *attr = rb_id2name(key);
318
+ static int dump_attr_cb(ID key, VALUE value, VALUE ov) {
319
+ Out out = (Out)ov;
320
+ int depth = out->depth;
321
+ size_t size = depth * out->indent + 1;
322
+ const char *attr = rb_id2name(key);
354
323
 
355
- if (oj_dump_ignore(out->opts, value)) {
356
- return ST_CONTINUE;
324
+ if (dump_ignore(out->opts, value)) {
325
+ return ST_CONTINUE;
357
326
  }
358
327
  if (out->omit_nil && Qnil == value) {
359
- return ST_CONTINUE;
328
+ return ST_CONTINUE;
360
329
  }
361
330
  // Some exceptions such as NoMethodError have an invisible attribute where
362
331
  // the key name is NULL. Not an empty string but NULL.
363
332
  if (NULL == attr) {
364
- attr = "";
333
+ attr = "";
365
334
  } else if (Yes == out->opts->ignore_under && '@' == *attr && '_' == attr[1]) {
366
- return ST_CONTINUE;
335
+ return ST_CONTINUE;
367
336
  }
368
337
  if (0 == strcmp("bt", attr) || 0 == strcmp("mesg", attr)) {
369
- return ST_CONTINUE;
338
+ return ST_CONTINUE;
370
339
  }
371
340
  assure_size(out, size);
372
341
  fill_indent(out, depth);
373
342
  if ('@' == *attr) {
374
- attr++;
375
- oj_dump_cstr(attr, strlen(attr), 0, 0, out);
343
+ attr++;
344
+ oj_dump_cstr(attr, strlen(attr), 0, 0, out);
376
345
  } else {
377
- char buf[32];
346
+ char buf[32];
378
347
 
379
- *buf = '~';
380
- strncpy(buf + 1, attr, sizeof(buf) - 2);
381
- buf[sizeof(buf) - 1] = '\0';
382
- oj_dump_cstr(buf, strlen(buf), 0, 0, out);
348
+ *buf = '~';
349
+ strncpy(buf + 1, attr, sizeof(buf) - 2);
350
+ buf[sizeof(buf) - 1] = '\0';
351
+ oj_dump_cstr(buf, strlen(buf), 0, 0, out);
383
352
  }
384
353
  *out->cur++ = ':';
385
354
  oj_dump_obj_val(value, depth, out);
386
- out->depth = depth;
355
+ out->depth = depth;
387
356
  *out->cur++ = ',';
388
357
 
389
358
  return ST_CONTINUE;
390
359
  }
391
- #endif
392
360
 
393
- static void
394
- dump_hash(VALUE obj, int depth, Out out, bool as_ok) {
361
+ static void dump_hash(VALUE obj, int depth, Out out, bool as_ok) {
395
362
  dump_hash_class(obj, rb_obj_class(obj), depth, out);
396
363
  }
397
364
 
398
- static void
399
- dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
400
- ID *idp;
401
- AttrGetFunc *fp;
402
- volatile VALUE v;
403
- const char *name;
404
- size_t size;
405
- int d2 = depth + 1;
365
+ static void dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
366
+ ID *idp;
367
+ AttrGetFunc *fp;
368
+ volatile VALUE v;
369
+ const char *name;
370
+ size_t size;
371
+ int d2 = depth + 1;
406
372
 
407
373
  assure_size(out, 2);
408
374
  *out->cur++ = '{';
409
375
  if (Qundef != clas) {
410
- const char *class_name = rb_class2name(clas);
411
- int clen = (int)strlen(class_name);
412
-
413
- size = d2 * out->indent + clen + 10;
414
- assure_size(out, size);
415
- fill_indent(out, d2);
416
- *out->cur++ = '"';
417
- *out->cur++ = '^';
418
- *out->cur++ = 'O';
419
- *out->cur++ = '"';
420
- *out->cur++ = ':';
421
- oj_dump_cstr(class_name, clen, 0, 0, out);
422
- *out->cur++ = ',';
376
+ const char *class_name = rb_class2name(clas);
377
+ int clen = (int)strlen(class_name);
378
+
379
+ size = d2 * out->indent + clen + 10;
380
+ assure_size(out, size);
381
+ fill_indent(out, d2);
382
+ APPEND_CHARS(out->cur, "\"^O\":", 5);
383
+ oj_dump_cstr(class_name, clen, 0, 0, out);
384
+ *out->cur++ = ',';
423
385
  }
424
386
  if (odd->raw) {
425
- v = rb_funcall(obj, *odd->attrs, 0);
426
- if (Qundef == v || T_STRING != rb_type(v)) {
427
- rb_raise(rb_eEncodingError, "Invalid type for raw JSON.");
428
- } else {
429
- const char *s = rb_string_value_ptr((VALUE*)&v);
430
- int len = (int)RSTRING_LEN(v);
431
- const char *name = rb_id2name(*odd->attrs);
432
- size_t nlen = strlen(name);
433
-
434
- size = len + d2 * out->indent + nlen + 10;
435
- assure_size(out, size);
436
- fill_indent(out, d2);
437
- *out->cur++ = '"';
438
- memcpy(out->cur, name, nlen);
439
- out->cur += nlen;
440
- *out->cur++ = '"';
441
- *out->cur++ = ':';
442
- memcpy(out->cur, s, len);
443
- out->cur += len;
444
- *out->cur = '\0';
445
- }
387
+ v = rb_funcall(obj, *odd->attrs, 0);
388
+ if (Qundef == v || T_STRING != rb_type(v)) {
389
+ rb_raise(rb_eEncodingError, "Invalid type for raw JSON.");
390
+ } else {
391
+ const char *s = RSTRING_PTR(v);
392
+ int len = (int)RSTRING_LEN(v);
393
+ const char *name = rb_id2name(*odd->attrs);
394
+ size_t nlen = strlen(name);
395
+
396
+ size = len + d2 * out->indent + nlen + 10;
397
+ assure_size(out, size);
398
+ fill_indent(out, d2);
399
+ *out->cur++ = '"';
400
+ APPEND_CHARS(out->cur, name, nlen);
401
+ APPEND_CHARS(out->cur, "\":", 2);
402
+ APPEND_CHARS(out->cur, s, len);
403
+ *out->cur = '\0';
404
+ }
446
405
  } else {
447
- size = d2 * out->indent + 1;
448
- for (idp = odd->attrs, fp = odd->attrFuncs; 0 != *idp; idp++, fp++) {
449
- size_t nlen;
450
-
451
- assure_size(out, size);
452
- name = rb_id2name(*idp);
453
- nlen = strlen(name);
454
- if (0 != *fp) {
455
- v = (*fp)(obj);
456
- } else if (0 == strchr(name, '.')) {
457
- v = rb_funcall(obj, *idp, 0);
458
- } else {
459
- char nbuf[256];
460
- char *n2 = nbuf;
461
- char *n;
462
- char *end;
463
- ID i;
464
-
465
- if (sizeof(nbuf) <= nlen) {
466
- if (NULL == (n2 = strdup(name))) {
467
- rb_raise(rb_eNoMemError, "for attribute name.");
468
- }
469
- } else {
470
- strcpy(n2, name);
471
- }
472
- n = n2;
473
- v = obj;
474
- while (0 != (end = strchr(n, '.'))) {
475
- *end = '\0';
476
- i = rb_intern(n);
477
- v = rb_funcall(v, i, 0);
478
- n = end + 1;
479
- }
480
- i = rb_intern(n);
481
- v = rb_funcall(v, i, 0);
482
- if (nbuf != n2) {
483
- free(n2);
484
- }
485
- }
486
- fill_indent(out, d2);
487
- oj_dump_cstr(name, nlen, 0, 0, out);
488
- *out->cur++ = ':';
489
- oj_dump_obj_val(v, d2, out);
490
- assure_size(out, 2);
491
- *out->cur++ = ',';
492
- }
493
- out->cur--;
406
+ size = d2 * out->indent + 1;
407
+ for (idp = odd->attrs, fp = odd->attrFuncs; 0 != *idp; idp++, fp++) {
408
+ size_t nlen;
409
+
410
+ assure_size(out, size);
411
+ name = rb_id2name(*idp);
412
+ nlen = strlen(name);
413
+ if (NULL != *fp) {
414
+ v = (*fp)(obj);
415
+ } else if (0 == strchr(name, '.')) {
416
+ v = rb_funcall(obj, *idp, 0);
417
+ } else {
418
+ char nbuf[256];
419
+ char *n2 = nbuf;
420
+ char *n;
421
+ char *end;
422
+ ID i;
423
+
424
+ if (sizeof(nbuf) <= nlen) {
425
+ if (NULL == (n2 = OJ_STRDUP(name))) {
426
+ rb_raise(rb_eNoMemError, "for attribute name.");
427
+ }
428
+ } else {
429
+ strcpy(n2, name);
430
+ }
431
+ n = n2;
432
+ v = obj;
433
+ while (0 != (end = strchr(n, '.'))) {
434
+ *end = '\0';
435
+ i = rb_intern(n);
436
+ v = rb_funcall(v, i, 0);
437
+ n = end + 1;
438
+ }
439
+ i = rb_intern(n);
440
+ v = rb_funcall(v, i, 0);
441
+ if (nbuf != n2) {
442
+ OJ_FREE(n2);
443
+ }
444
+ }
445
+ fill_indent(out, d2);
446
+ oj_dump_cstr(name, nlen, 0, 0, out);
447
+ *out->cur++ = ':';
448
+ oj_dump_obj_val(v, d2, out);
449
+ assure_size(out, 2);
450
+ *out->cur++ = ',';
451
+ }
452
+ out->cur--;
494
453
  }
495
454
  *out->cur++ = '}';
496
- *out->cur = '\0';
455
+ *out->cur = '\0';
497
456
  }
498
457
 
499
- static void
500
- dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out) {
501
- size_t size = 0;
502
- int d2 = depth + 1;
503
- int type = rb_type(obj);
504
- Odd odd;
458
+ static void dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out) {
459
+ size_t size = 0;
460
+ int d2 = depth + 1;
461
+ int type = rb_type(obj);
462
+ Odd odd;
505
463
 
506
464
  if (0 != (odd = oj_get_odd(clas))) {
507
- dump_odd(obj, odd, clas, depth + 1, out);
508
- return;
465
+ dump_odd(obj, odd, clas, depth + 1, out);
466
+ return;
509
467
  }
510
468
  assure_size(out, 2);
511
469
  *out->cur++ = '{';
512
470
  if (Qundef != clas) {
513
- const char *class_name = rb_class2name(clas);
514
- int clen = (int)strlen(class_name);
515
-
516
- assure_size(out, d2 * out->indent + clen + 10);
517
- fill_indent(out, d2);
518
- *out->cur++ = '"';
519
- *out->cur++ = '^';
520
- *out->cur++ = 'o';
521
- *out->cur++ = '"';
522
- *out->cur++ = ':';
523
- oj_dump_cstr(class_name, clen, 0, 0, out);
471
+ const char *class_name = rb_class2name(clas);
472
+ int clen = (int)strlen(class_name);
473
+
474
+ assure_size(out, d2 * out->indent + clen + 10);
475
+ fill_indent(out, d2);
476
+ APPEND_CHARS(out->cur, "\"^o\":", 5);
477
+ oj_dump_cstr(class_name, clen, 0, 0, out);
524
478
  }
525
479
  if (0 < id) {
526
- assure_size(out, d2 * out->indent + 16);
527
- *out->cur++ = ',';
528
- fill_indent(out, d2);
529
- *out->cur++ = '"';
530
- *out->cur++ = '^';
531
- *out->cur++ = 'i';
532
- *out->cur++ = '"';
533
- *out->cur++ = ':';
534
- dump_ulong(id, out);
480
+ assure_size(out, d2 * out->indent + 16);
481
+ *out->cur++ = ',';
482
+ fill_indent(out, d2);
483
+ APPEND_CHARS(out->cur, "\"^i\":", 5);
484
+ dump_ulong(id, out);
535
485
  }
536
486
  switch (type) {
537
487
  case T_STRING:
538
- assure_size(out, d2 * out->indent + 14);
539
- *out->cur++ = ',';
540
- fill_indent(out, d2);
541
- *out->cur++ = '"';
542
- *out->cur++ = 's';
543
- *out->cur++ = 'e';
544
- *out->cur++ = 'l';
545
- *out->cur++ = 'f';
546
- *out->cur++ = '"';
547
- *out->cur++ = ':';
548
- oj_dump_cstr(rb_string_value_ptr((VALUE*)&obj), (int)RSTRING_LEN(obj), 0, 0, out);
549
- break;
488
+ assure_size(out, d2 * out->indent + 14);
489
+ *out->cur++ = ',';
490
+ fill_indent(out, d2);
491
+ APPEND_CHARS(out->cur, "\"self\":", 7);
492
+ oj_dump_cstr(RSTRING_PTR(obj), (int)RSTRING_LEN(obj), 0, 0, out);
493
+ break;
550
494
  case T_ARRAY:
551
- assure_size(out, d2 * out->indent + 14);
552
- *out->cur++ = ',';
553
- fill_indent(out, d2);
554
- *out->cur++ = '"';
555
- *out->cur++ = 's';
556
- *out->cur++ = 'e';
557
- *out->cur++ = 'l';
558
- *out->cur++ = 'f';
559
- *out->cur++ = '"';
560
- *out->cur++ = ':';
561
- dump_array_class(obj, Qundef, depth + 1, out);
562
- break;
495
+ assure_size(out, d2 * out->indent + 14);
496
+ *out->cur++ = ',';
497
+ fill_indent(out, d2);
498
+ APPEND_CHARS(out->cur, "\"self\":", 7);
499
+ dump_array_class(obj, Qundef, depth + 1, out);
500
+ break;
563
501
  case T_HASH:
564
- assure_size(out, d2 * out->indent + 14);
565
- *out->cur++ = ',';
566
- fill_indent(out, d2);
567
- *out->cur++ = '"';
568
- *out->cur++ = 's';
569
- *out->cur++ = 'e';
570
- *out->cur++ = 'l';
571
- *out->cur++ = 'f';
572
- *out->cur++ = '"';
573
- *out->cur++ = ':';
574
- dump_hash_class(obj, Qundef, depth + 1, out);
575
- break;
576
- default:
577
- break;
502
+ assure_size(out, d2 * out->indent + 14);
503
+ *out->cur++ = ',';
504
+ fill_indent(out, d2);
505
+ APPEND_CHARS(out->cur, "\"self\":", 7);
506
+ dump_hash_class(obj, Qundef, depth + 1, out);
507
+ break;
508
+ default: break;
578
509
  }
579
510
  {
580
- int cnt;
581
- #ifdef HAVE_RB_IVAR_COUNT
582
- cnt = (int)rb_ivar_count(obj);
583
- #else
584
- volatile VALUE vars = rb_funcall2(obj, oj_instance_variables_id, 0, 0);
585
- VALUE *np = RARRAY_PTR(vars);
586
- ID vid;
587
- const char *attr;
588
- int i;
589
- int first = 1;
590
-
591
- cnt = (int)RARRAY_LEN(vars);
592
- #endif
593
- if (Qundef != clas && 0 < cnt) {
594
- *out->cur++ = ',';
595
- }
596
- if (0 == cnt && Qundef == clas) {
597
- // Might be something special like an Enumerable.
598
- if (Qtrue == rb_obj_is_kind_of(obj, oj_enumerable_class)) {
599
- out->cur--;
600
- oj_dump_obj_val(rb_funcall(obj, rb_intern("entries"), 0), depth, out);
601
- return;
602
- }
603
- }
604
- out->depth = depth + 1;
605
- #ifdef HAVE_RB_IVAR_FOREACH
606
- rb_ivar_foreach(obj, dump_attr_cb, (VALUE)out);
607
- if (',' == *(out->cur - 1)) {
608
- out->cur--; // backup to overwrite last comma
609
- }
610
- #else
611
- size = d2 * out->indent + 1;
612
- for (i = cnt; 0 < i; i--, np++) {
613
- VALUE value;
614
-
615
- vid = rb_to_id(*np);
616
- attr = rb_id2name(vid);
617
- if (Yes == out->opts->ignore_under && '@' == *attr && '_' == attr[1]) {
618
- continue;
619
- }
620
- value = rb_ivar_get(obj, vid);
621
-
622
- if (oj_dump_ignore(out->opts, value)) {
623
- continue;
624
- }
625
- if (out->omit_nil && Qnil == value) {
626
- continue;
627
- }
628
- if (first) {
629
- first = 0;
630
- } else {
631
- *out->cur++ = ',';
632
- }
633
- assure_size(out, size);
634
- fill_indent(out, d2);
635
- if ('@' == *attr) {
636
- attr++;
637
- oj_dump_cstr(attr, strlen(attr), 0, 0, out);
638
- } else {
639
- char buf[32];
640
-
641
- *buf = '~';
642
- strncpy(buf + 1, attr, sizeof(buf) - 2);
643
- buf[sizeof(buf) - 1] = '\0';
644
- oj_dump_cstr(buf, strlen(attr) + 1, 0, 0, out);
645
- }
646
- *out->cur++ = ':';
647
- oj_dump_obj_val(value, d2, out);
648
- assure_size(out, 2);
649
- }
650
- #endif
651
- if (rb_obj_is_kind_of(obj, rb_eException)) {
652
- volatile VALUE rv;
653
-
654
- if (',' != *(out->cur - 1)) {
655
- *out->cur++ = ',';
656
- }
657
- // message
658
- assure_size(out, size);
659
- fill_indent(out, d2);
660
- oj_dump_cstr("~mesg", 5, 0, 0, out);
661
- *out->cur++ = ':';
662
- rv = rb_funcall2(obj, rb_intern("message"), 0, 0);
663
- oj_dump_obj_val(rv, d2, out);
664
- assure_size(out, 2);
665
- *out->cur++ = ',';
666
- // backtrace
667
- assure_size(out, size);
668
- fill_indent(out, d2);
669
- oj_dump_cstr("~bt", 3, 0, 0, out);
670
- *out->cur++ = ':';
671
- rv = rb_funcall2(obj, rb_intern("backtrace"), 0, 0);
672
- oj_dump_obj_val(rv, d2, out);
673
- assure_size(out, 2);
674
- }
675
- out->depth = depth;
511
+ int cnt = (int)rb_ivar_count(obj);
512
+
513
+ if (Qundef != clas && 0 < cnt) {
514
+ *out->cur++ = ',';
515
+ }
516
+ if (0 == cnt && Qundef == clas) {
517
+ // Might be something special like an Enumerable.
518
+ if (Qtrue == rb_obj_is_kind_of(obj, oj_enumerable_class)) {
519
+ out->cur--;
520
+ oj_dump_obj_val(rb_funcall(obj, rb_intern("entries"), 0), depth, out);
521
+ return;
522
+ }
523
+ }
524
+ out->depth = depth + 1;
525
+ rb_ivar_foreach(obj, dump_attr_cb, (VALUE)out);
526
+ if (',' == *(out->cur - 1)) {
527
+ out->cur--; // backup to overwrite last comma
528
+ }
529
+ if (rb_obj_is_kind_of(obj, rb_eException)) {
530
+ volatile VALUE rv;
531
+
532
+ if (',' != *(out->cur - 1)) {
533
+ *out->cur++ = ',';
534
+ }
535
+ // message
536
+ assure_size(out, size);
537
+ fill_indent(out, d2);
538
+ oj_dump_cstr("~mesg", 5, 0, 0, out);
539
+ *out->cur++ = ':';
540
+ rv = rb_funcall2(obj, rb_intern("message"), 0, 0);
541
+ oj_dump_obj_val(rv, d2, out);
542
+ assure_size(out, 2);
543
+ *out->cur++ = ',';
544
+ // backtrace
545
+ assure_size(out, size);
546
+ fill_indent(out, d2);
547
+ oj_dump_cstr("~bt", 3, 0, 0, out);
548
+ *out->cur++ = ':';
549
+ rv = rb_funcall2(obj, rb_intern("backtrace"), 0, 0);
550
+ oj_dump_obj_val(rv, d2, out);
551
+ assure_size(out, 2);
552
+ }
553
+ out->depth = depth;
676
554
  }
677
555
  fill_indent(out, depth);
678
556
  *out->cur++ = '}';
679
- *out->cur = '\0';
557
+ *out->cur = '\0';
680
558
  }
681
559
 
682
- static void
683
- dump_regexp(VALUE obj, int depth, Out out, bool as_ok) {
560
+ static void dump_regexp(VALUE obj, int depth, Out out, bool as_ok) {
684
561
  dump_obj_attrs(obj, rb_obj_class(obj), 0, depth, out);
685
562
  }
686
563
 
687
- static void
688
- dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
689
- VALUE clas = rb_obj_class(obj);
690
- const char *class_name = rb_class2name(clas);
691
- int i;
692
- int d2 = depth + 1;
693
- int d3 = d2 + 1;
694
- size_t len = strlen(class_name);
695
- size_t size = d2 * out->indent + d3 * out->indent + 10 + len;
564
+ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
565
+ VALUE clas = rb_obj_class(obj);
566
+ const char *class_name = rb_class2name(clas);
567
+ int i;
568
+ int d2 = depth + 1;
569
+ int d3 = d2 + 1;
570
+ size_t len = strlen(class_name);
571
+ size_t size = d2 * out->indent + d3 * out->indent + 10 + len;
696
572
 
697
573
  assure_size(out, size);
698
574
  *out->cur++ = '{';
699
575
  fill_indent(out, d2);
700
- *out->cur++ = '"';
701
- *out->cur++ = '^';
702
- *out->cur++ = 'u';
703
- *out->cur++ = '"';
704
- *out->cur++ = ':';
705
- *out->cur++ = '[';
576
+ APPEND_CHARS(out->cur, "\"^u\":[", 6);
706
577
  if ('#' == *class_name) {
707
- VALUE ma = rb_struct_s_members(clas);
708
- const char *name;
709
- int cnt = (int)RARRAY_LEN(ma);
710
-
711
- *out->cur++ = '[';
712
- for (i = 0; i < cnt; i++) {
713
- volatile VALUE s = rb_sym_to_s(rb_ary_entry(ma, i));
714
-
715
- name = rb_string_value_ptr((VALUE*)&s);
716
- len = (int)RSTRING_LEN(s);
717
- size = len + 3;
718
- assure_size(out, size);
719
- if (0 < i) {
720
- *out->cur++ = ',';
721
- }
722
- *out->cur++ = '"';
723
- memcpy(out->cur, name, len);
724
- out->cur += len;
725
- *out->cur++ = '"';
726
- }
727
- *out->cur++ = ']';
578
+ VALUE ma = rb_struct_s_members(clas);
579
+ const char *name;
580
+ int cnt = (int)RARRAY_LEN(ma);
581
+
582
+ *out->cur++ = '[';
583
+ for (i = 0; i < cnt; i++) {
584
+ volatile VALUE s = rb_sym2str(RARRAY_AREF(ma, i));
585
+
586
+ name = RSTRING_PTR(s);
587
+ len = (int)RSTRING_LEN(s);
588
+ size = len + 3;
589
+ assure_size(out, size);
590
+ if (0 < i) {
591
+ *out->cur++ = ',';
592
+ }
593
+ *out->cur++ = '"';
594
+ APPEND_CHARS(out->cur, name, len);
595
+ *out->cur++ = '"';
596
+ }
597
+ *out->cur++ = ']';
728
598
  } else {
729
- fill_indent(out, d3);
730
- *out->cur++ = '"';
731
- memcpy(out->cur, class_name, len);
732
- out->cur += len;
733
- *out->cur++ = '"';
599
+ fill_indent(out, d3);
600
+ *out->cur++ = '"';
601
+ APPEND_CHARS(out->cur, class_name, len);
602
+ *out->cur++ = '"';
734
603
  }
735
604
  *out->cur++ = ',';
736
- size = d3 * out->indent + 2;
605
+ size = d3 * out->indent + 2;
737
606
  #ifdef RSTRUCT_LEN
738
607
  {
739
- VALUE v;
740
- int cnt;
608
+ VALUE v;
609
+ int cnt;
741
610
  #if RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
742
- cnt = (int)NUM2LONG(RSTRUCT_LEN(obj));
743
- #else // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
744
- cnt = (int)RSTRUCT_LEN(obj);
745
- #endif // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
746
-
747
- for (i = 0; i < cnt; i++) {
748
- v = RSTRUCT_GET(obj, i);
749
- if (oj_dump_ignore(out->opts, v)) {
750
- v = Qnil;
751
- }
752
- assure_size(out, size);
753
- fill_indent(out, d3);
754
- oj_dump_obj_val(v, d3, out);
755
- *out->cur++ = ',';
756
- }
611
+ cnt = (int)NUM2LONG(RSTRUCT_LEN(obj));
612
+ #else // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
613
+ cnt = (int)RSTRUCT_LEN(obj);
614
+ #endif // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
615
+
616
+ for (i = 0; i < cnt; i++) {
617
+ v = RSTRUCT_GET(obj, i);
618
+ if (dump_ignore(out->opts, v)) {
619
+ v = Qnil;
620
+ }
621
+ assure_size(out, size);
622
+ fill_indent(out, d3);
623
+ oj_dump_obj_val(v, d3, out);
624
+ *out->cur++ = ',';
625
+ }
757
626
  }
758
627
  #else
759
628
  {
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
- int slen = FIX2INT(rb_funcall2(obj, oj_length_id, 0, 0));
763
-
764
- for (i = 0; i < slen; i++) {
765
- assure_size(out, size);
766
- fill_indent(out, d3);
767
- if (oj_dump_ignore(out->opts, v)) {
768
- v = Qnil;
769
- }
770
- oj_dump_obj_val(rb_struct_aref(obj, INT2FIX(i)), d3, out, 0, 0, true);
771
- *out->cur++ = ',';
772
- }
629
+ // This is a bit risky as a struct in C ruby is not the same as a Struct
630
+ // class in interpreted Ruby so length() may not be defined.
631
+ int slen = FIX2INT(rb_funcall2(obj, oj_length_id, 0, 0));
632
+
633
+ for (i = 0; i < slen; i++) {
634
+ assure_size(out, size);
635
+ fill_indent(out, d3);
636
+ if (dump_ignore(out->opts, v)) {
637
+ v = Qnil;
638
+ }
639
+ oj_dump_obj_val(rb_struct_aref(obj, INT2FIX(i)), d3, out, 0, 0, true);
640
+ *out->cur++ = ',';
641
+ }
773
642
  }
774
643
  #endif
775
644
  out->cur--;
776
- *out->cur++ = ']';
777
- *out->cur++ = '}';
645
+ APPEND_CHARS(out->cur, "]}", 2);
778
646
  *out->cur = '\0';
779
647
  }
780
648
 
781
- static void
782
- dump_complex(VALUE obj, int depth, Out out, bool as_ok) {
649
+ static void dump_complex(VALUE obj, int depth, Out out, bool as_ok) {
783
650
  dump_obj_attrs(obj, rb_obj_class(obj), 0, depth, out);
784
651
  }
785
652
 
786
- static void
787
- dump_rational(VALUE obj, int depth, Out out, bool as_ok) {
653
+ static void dump_rational(VALUE obj, int depth, Out out, bool as_ok) {
788
654
  dump_obj_attrs(obj, rb_obj_class(obj), 0, depth, out);
789
655
  }
790
656
 
791
- static DumpFunc obj_funcs[] = {
792
- NULL, // RUBY_T_NONE = 0x00,
793
- dump_obj, // RUBY_T_OBJECT = 0x01,
794
- dump_class, // RUBY_T_CLASS = 0x02,
795
- dump_class, // RUBY_T_MODULE = 0x03,
796
- oj_dump_float, // RUBY_T_FLOAT = 0x04,
797
- dump_str, // RUBY_T_STRING = 0x05,
798
- dump_regexp, // RUBY_T_REGEXP = 0x06,
799
- dump_array, // RUBY_T_ARRAY = 0x07,
800
- dump_hash, // RUBY_T_HASH = 0x08,
801
- dump_struct, // RUBY_T_STRUCT = 0x09,
802
- oj_dump_bignum, // RUBY_T_BIGNUM = 0x0a,
803
- NULL, // RUBY_T_FILE = 0x0b,
804
- dump_data, // RUBY_T_DATA = 0x0c,
805
- NULL, // RUBY_T_MATCH = 0x0d,
806
- dump_complex, // RUBY_T_COMPLEX = 0x0e,
807
- dump_rational, // RUBY_T_RATIONAL = 0x0f,
808
- NULL, // 0x10
809
- oj_dump_nil, // RUBY_T_NIL = 0x11,
810
- oj_dump_true, // RUBY_T_TRUE = 0x12,
811
- oj_dump_false, // RUBY_T_FALSE = 0x13,
812
- dump_sym, // RUBY_T_SYMBOL = 0x14,
813
- oj_dump_fixnum, // RUBY_T_FIXNUM = 0x15,
657
+ static DumpFunc obj_funcs[] = {
658
+ NULL, // RUBY_T_NONE = 0x00,
659
+ dump_obj, // RUBY_T_OBJECT = 0x01,
660
+ dump_class, // RUBY_T_CLASS = 0x02,
661
+ dump_class, // RUBY_T_MODULE = 0x03,
662
+ oj_dump_float, // RUBY_T_FLOAT = 0x04,
663
+ dump_str, // RUBY_T_STRING = 0x05,
664
+ dump_regexp, // RUBY_T_REGEXP = 0x06,
665
+ dump_array, // RUBY_T_ARRAY = 0x07,
666
+ dump_hash, // RUBY_T_HASH = 0x08,
667
+ dump_struct, // RUBY_T_STRUCT = 0x09,
668
+ oj_dump_bignum, // RUBY_T_BIGNUM = 0x0a,
669
+ NULL, // RUBY_T_FILE = 0x0b,
670
+ dump_data, // RUBY_T_DATA = 0x0c,
671
+ NULL, // RUBY_T_MATCH = 0x0d,
672
+ dump_complex, // RUBY_T_COMPLEX = 0x0e,
673
+ dump_rational, // RUBY_T_RATIONAL = 0x0f,
674
+ NULL, // 0x10
675
+ oj_dump_nil, // RUBY_T_NIL = 0x11,
676
+ oj_dump_true, // RUBY_T_TRUE = 0x12,
677
+ oj_dump_false, // RUBY_T_FALSE = 0x13,
678
+ dump_sym, // RUBY_T_SYMBOL = 0x14,
679
+ oj_dump_fixnum, // RUBY_T_FIXNUM = 0x15,
814
680
  };
815
681
 
816
- void
817
- oj_dump_obj_val(VALUE obj, int depth, Out out) {
818
- int type = rb_type(obj);
682
+ void oj_dump_obj_val(VALUE obj, int depth, Out out) {
683
+ int type = rb_type(obj);
819
684
 
820
- if (Yes == out->opts->trace) {
821
- oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceIn);
822
- }
685
+ TRACE(out->opts->trace, "dump", obj, depth, TraceIn);
823
686
  if (MAX_DEPTH < depth) {
824
- rb_raise(rb_eNoMemError, "Too deeply nested.\n");
687
+ rb_raise(rb_eNoMemError, "Too deeply nested.\n");
825
688
  }
826
689
  if (0 < type && type <= RUBY_T_FIXNUM) {
827
- DumpFunc f = obj_funcs[type];
828
-
829
- if (NULL != f) {
830
- f(obj, depth, out, false);
831
- if (Yes == out->opts->trace) {
832
- oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceOut);
833
- }
834
- return;
835
- }
690
+ DumpFunc f = obj_funcs[type];
691
+
692
+ if (NULL != f) {
693
+ f(obj, depth, out, false);
694
+ TRACE(out->opts->trace, "dump", obj, depth, TraceOut);
695
+ return;
696
+ }
836
697
  }
837
698
  oj_dump_nil(Qnil, depth, out, false);
838
- if (Yes == out->opts->trace) {
839
- oj_trace("dump", Qnil, __FILE__, __LINE__, depth, TraceOut);
840
- }
699
+ TRACE(out->opts->trace, "dump", Qnil, depth, TraceOut);
841
700
  }