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/rails.c CHANGED
@@ -1,157 +1,154 @@
1
1
  // Copyright (c) 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 "rails.h"
4
- #include "encode.h"
5
+
5
6
  #include "code.h"
6
7
  #include "encode.h"
8
+ #include "mem.h"
7
9
  #include "trace.h"
8
10
  #include "util.h"
9
11
 
10
- #define OJ_INFINITY (1.0/0.0)
12
+ #define OJ_INFINITY (1.0 / 0.0)
11
13
 
12
14
  // TBD keep static array of strings and functions to help with rails optimization
13
15
  typedef struct _encoder {
14
- struct _rOptTable ropts;
15
- struct _options opts;
16
- VALUE arg;
16
+ struct _rOptTable ropts;
17
+ struct _options opts;
18
+ VALUE arg;
17
19
  } *Encoder;
18
20
 
19
- bool oj_rails_hash_opt = false;
20
- bool oj_rails_array_opt = false;
21
- bool oj_rails_float_opt = false;
21
+ bool oj_rails_hash_opt = false;
22
+ bool oj_rails_array_opt = false;
23
+ bool oj_rails_float_opt = false;
22
24
 
23
- extern void oj_mimic_json_methods(VALUE json);
25
+ extern void oj_mimic_json_methods(VALUE json);
24
26
 
25
- static void dump_rails_val(VALUE obj, int depth, Out out, bool as_ok);
27
+ static void dump_rails_val(VALUE obj, int depth, Out out, bool as_ok);
26
28
 
27
- extern VALUE Oj;
29
+ extern VALUE Oj;
28
30
 
29
- static struct _rOptTable ropts = { 0, 0, NULL };
31
+ static struct _rOptTable ropts = {0, 0, NULL};
30
32
 
31
- static VALUE encoder_class = Qnil;
32
- static bool escape_html = true;
33
- static bool xml_time = true;
33
+ static VALUE encoder_class = Qnil;
34
+ static bool escape_html = true;
35
+ static bool xml_time = true;
34
36
 
35
- static ROpt create_opt(ROptTable rot, VALUE clas);
37
+ static ROpt create_opt(ROptTable rot, VALUE clas);
36
38
 
37
- ROpt
38
- oj_rails_get_opt(ROptTable rot, VALUE clas) {
39
+ ROpt oj_rails_get_opt(ROptTable rot, VALUE clas) {
39
40
  if (NULL == rot) {
40
- rot = &ropts;
41
+ rot = &ropts;
41
42
  }
42
43
  if (0 < rot->len) {
43
- int lo = 0;
44
- int hi = rot->len - 1;
45
- int mid;
46
- VALUE v;
47
-
48
- if (clas < rot->table->clas || rot->table[hi].clas < clas) {
49
- return NULL;
50
- }
51
- if (rot->table[lo].clas == clas) {
52
- return rot->table;
53
- }
54
- if (rot->table[hi].clas == clas) {
55
- return &rot->table[hi];
56
- }
57
- while (2 <= hi - lo) {
58
- mid = (hi + lo) / 2;
59
- v = rot->table[mid].clas;
60
- if (v == clas) {
61
- return &rot->table[mid];
62
- }
63
- if (v < clas) {
64
- lo = mid;
65
- } else {
66
- hi = mid;
67
- }
68
- }
44
+ int lo = 0;
45
+ int hi = rot->len - 1;
46
+ int mid;
47
+ VALUE v;
48
+
49
+ if (clas < rot->table->clas || rot->table[hi].clas < clas) {
50
+ return NULL;
51
+ }
52
+ if (rot->table[lo].clas == clas) {
53
+ return rot->table;
54
+ }
55
+ if (rot->table[hi].clas == clas) {
56
+ return &rot->table[hi];
57
+ }
58
+ while (2 <= hi - lo) {
59
+ mid = (hi + lo) / 2;
60
+ v = rot->table[mid].clas;
61
+ if (v == clas) {
62
+ return &rot->table[mid];
63
+ }
64
+ if (v < clas) {
65
+ lo = mid;
66
+ } else {
67
+ hi = mid;
68
+ }
69
+ }
69
70
  }
70
71
  return NULL;
71
72
  }
72
73
 
73
- static ROptTable
74
- copy_opts(ROptTable src, ROptTable dest) {
75
- dest->len = src->len;
74
+ static ROptTable copy_opts(ROptTable src, ROptTable dest) {
75
+ dest->len = src->len;
76
76
  dest->alen = src->alen;
77
77
  if (NULL == src->table) {
78
- dest->table = NULL;
78
+ dest->table = NULL;
79
79
  } else {
80
- dest->table = ALLOC_N(struct _rOpt, dest->alen);
81
- memcpy(dest->table, src->table, sizeof(struct _rOpt) * dest->alen);
80
+ dest->table = OJ_R_ALLOC_N(struct _rOpt, dest->alen);
81
+ memcpy(dest->table, src->table, sizeof(struct _rOpt) * dest->alen);
82
82
  }
83
83
  return NULL;
84
84
  }
85
85
 
86
- static int
87
- dump_attr_cb(ID key, VALUE value, VALUE ov) {
88
- Out out = (Out)ov;
89
- int depth = out->depth;
90
- size_t size = depth * out->indent + 1;
91
- const char *attr = rb_id2name(key);
86
+ static int dump_attr_cb(ID key, VALUE value, VALUE ov) {
87
+ Out out = (Out)ov;
88
+ int depth = out->depth;
89
+ size_t size = depth * out->indent + 1;
90
+ const char *attr = rb_id2name(key);
92
91
 
93
92
  // Some exceptions such as NoMethodError have an invisible attribute where
94
93
  // the key name is NULL. Not an empty string but NULL.
95
94
  if (NULL == attr) {
96
- attr = "";
95
+ attr = "";
97
96
  }
98
97
  if (0 == strcmp("bt", attr) || 0 == strcmp("mesg", attr)) {
99
- return ST_CONTINUE;
98
+ return ST_CONTINUE;
100
99
  }
101
100
  assure_size(out, size);
102
101
  fill_indent(out, depth);
103
102
  if ('@' == *attr) {
104
- attr++;
105
- oj_dump_cstr(attr, strlen(attr), 0, 0, out);
103
+ attr++;
104
+ oj_dump_cstr(attr, strlen(attr), 0, 0, out);
106
105
  } else {
107
- char buf[32];
106
+ char buf[32];
108
107
 
109
- *buf = '~';
110
- strncpy(buf + 1, attr, sizeof(buf) - 2);
111
- buf[sizeof(buf) - 1] = '\0';
112
- oj_dump_cstr(buf, strlen(buf), 0, 0, out);
108
+ *buf = '~';
109
+ strncpy(buf + 1, attr, sizeof(buf) - 2);
110
+ buf[sizeof(buf) - 1] = '\0';
111
+ oj_dump_cstr(buf, strlen(buf), 0, 0, out);
113
112
  }
114
113
  *out->cur++ = ':';
115
114
  dump_rails_val(value, depth, out, true);
116
- out->depth = depth;
115
+ out->depth = depth;
117
116
  *out->cur++ = ',';
118
117
 
119
118
  return ST_CONTINUE;
120
119
  }
121
120
 
122
- static void
123
- dump_obj_attrs(VALUE obj, int depth, Out out, bool as_ok) {
121
+ static void dump_obj_attrs(VALUE obj, int depth, Out out, bool as_ok) {
124
122
  assure_size(out, 2);
125
123
  *out->cur++ = '{';
126
- out->depth = depth + 1;
124
+ out->depth = depth + 1;
127
125
  rb_ivar_foreach(obj, dump_attr_cb, (VALUE)out);
128
126
  if (',' == *(out->cur - 1)) {
129
- out->cur--; // backup to overwrite last comma
127
+ out->cur--; // backup to overwrite last comma
130
128
  }
131
129
  out->depth = depth;
132
130
  fill_indent(out, depth);
133
131
  *out->cur++ = '}';
134
- *out->cur = '\0';
132
+ *out->cur = '\0';
135
133
  }
136
134
 
137
- static void
138
- dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
139
- int d3 = depth + 2;
140
- size_t size = d3 * out->indent + 2;
141
- size_t sep_len = out->opts->dump_opts.before_size + out->opts->dump_opts.after_size + 2;
142
- volatile VALUE ma;
143
- volatile VALUE v;
144
- int cnt;
145
- int i;
146
- int len;
147
- const char *name;
135
+ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
136
+ int d3 = depth + 2;
137
+ size_t size = d3 * out->indent + 2;
138
+ size_t sep_len = out->opts->dump_opts.before_size + out->opts->dump_opts.after_size + 2;
139
+ volatile VALUE ma;
140
+ volatile VALUE v;
141
+ int cnt;
142
+ int i;
143
+ int len;
144
+ const char *name;
148
145
 
149
146
  #ifdef RSTRUCT_LEN
150
147
  #if RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
151
148
  cnt = (int)NUM2LONG(RSTRUCT_LEN(obj));
152
- #else // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
149
+ #else // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
153
150
  cnt = (int)RSTRUCT_LEN(obj);
154
- #endif // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
151
+ #endif // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
155
152
  #else
156
153
  // This is a bit risky as a struct in C ruby is not the same as a Struct
157
154
  // class in interpreted Ruby so length() may not be defined.
@@ -161,91 +158,85 @@ dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
161
158
  assure_size(out, 2);
162
159
  *out->cur++ = '{';
163
160
  for (i = 0; i < cnt; i++) {
164
- volatile VALUE s = rb_sym_to_s(rb_ary_entry(ma, i));
165
-
166
- name = rb_string_value_ptr((VALUE*)&s);
167
- len = (int)RSTRING_LEN(s);
168
- assure_size(out, size + sep_len + 6);
169
- if (0 < i) {
170
- *out->cur++ = ',';
171
- }
172
- fill_indent(out, d3);
173
- *out->cur++ = '"';
174
- memcpy(out->cur, name, len);
175
- out->cur += len;
176
- *out->cur++ = '"';
177
- if (0 < out->opts->dump_opts.before_size) {
178
- strcpy(out->cur, out->opts->dump_opts.before_sep);
179
- out->cur += out->opts->dump_opts.before_size;
180
- }
181
- *out->cur++ = ':';
182
- if (0 < out->opts->dump_opts.after_size) {
183
- strcpy(out->cur, out->opts->dump_opts.after_sep);
184
- out->cur += out->opts->dump_opts.after_size;
185
- }
161
+ volatile VALUE s = rb_sym2str(RARRAY_AREF(ma, i));
162
+
163
+ name = RSTRING_PTR(s);
164
+ len = (int)RSTRING_LEN(s);
165
+ assure_size(out, size + sep_len + 6);
166
+ if (0 < i) {
167
+ *out->cur++ = ',';
168
+ }
169
+ fill_indent(out, d3);
170
+ *out->cur++ = '"';
171
+ APPEND_CHARS(out->cur, name, len);
172
+ *out->cur++ = '"';
173
+ if (0 < out->opts->dump_opts.before_size) {
174
+ APPEND_CHARS(out->cur, out->opts->dump_opts.before_sep, out->opts->dump_opts.before_size);
175
+ }
176
+ *out->cur++ = ':';
177
+ if (0 < out->opts->dump_opts.after_size) {
178
+ APPEND_CHARS(out->cur, out->opts->dump_opts.after_sep, out->opts->dump_opts.after_size);
179
+ }
186
180
  #ifdef RSTRUCT_LEN
187
- v = RSTRUCT_GET(obj, i);
181
+ v = RSTRUCT_GET(obj, i);
188
182
  #else
189
- v = rb_struct_aref(obj, INT2FIX(i));
183
+ v = rb_struct_aref(obj, INT2FIX(i));
190
184
  #endif
191
- dump_rails_val(v, d3, out, true);
185
+ dump_rails_val(v, d3, out, true);
192
186
  }
193
187
  fill_indent(out, depth);
194
188
  *out->cur++ = '}';
195
- *out->cur = '\0';
189
+ *out->cur = '\0';
196
190
  }
197
191
 
198
- static ID to_a_id = 0;
192
+ static ID to_a_id = 0;
199
193
 
200
- static void
201
- dump_enumerable(VALUE obj, int depth, Out out, bool as_ok) {
194
+ static void dump_enumerable(VALUE obj, int depth, Out out, bool as_ok) {
202
195
  if (0 == to_a_id) {
203
- to_a_id = rb_intern("to_a");
196
+ to_a_id = rb_intern("to_a");
204
197
  }
205
198
  dump_rails_val(rb_funcall(obj, to_a_id, 0), depth, out, false);
206
199
  }
207
200
 
208
- static void
209
- dump_bigdecimal(VALUE obj, int depth, Out out, bool as_ok) {
210
- volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
211
- const char *str = rb_string_value_ptr((VALUE*)&rstr);
201
+ static void dump_bigdecimal(VALUE obj, int depth, Out out, bool as_ok) {
202
+ volatile VALUE rstr = oj_safe_string_convert(obj);
203
+ const char *str = RSTRING_PTR(rstr);
212
204
 
213
205
  if ('I' == *str || 'N' == *str || ('-' == *str && 'I' == str[1])) {
214
- oj_dump_nil(Qnil, depth, out, false);
206
+ oj_dump_nil(Qnil, depth, out, false);
215
207
  } else if (out->opts->int_range_max != 0 || out->opts->int_range_min != 0) {
216
- oj_dump_cstr(str, (int)RSTRING_LEN(rstr), 0, 0, out);
208
+ oj_dump_cstr(str, (int)RSTRING_LEN(rstr), 0, 0, out);
217
209
  } else if (Yes == out->opts->bigdec_as_num) {
218
- oj_dump_raw(str, (int)RSTRING_LEN(rstr), out);
210
+ oj_dump_raw(str, (int)RSTRING_LEN(rstr), out);
219
211
  } else {
220
- oj_dump_cstr(str, (int)RSTRING_LEN(rstr), 0, 0, out);
212
+ oj_dump_cstr(str, (int)RSTRING_LEN(rstr), 0, 0, out);
221
213
  }
222
214
  }
223
215
 
224
- static void
225
- dump_sec_nano(VALUE obj, int64_t sec, long nsec, Out out) {
226
- char buf[64];
227
- struct _timeInfo ti;
228
- long one = 1000000000;
229
- long tzsecs = NUM2LONG(rb_funcall2(obj, oj_utc_offset_id, 0, 0));
230
- int tzhour, tzmin;
231
- char tzsign = '+';
232
- int len;
216
+ static void dump_sec_nano(VALUE obj, int64_t sec, long nsec, Out out) {
217
+ char buf[64];
218
+ struct _timeInfo ti;
219
+ long one = 1000000000;
220
+ long tzsecs = NUM2LONG(rb_funcall2(obj, oj_utc_offset_id, 0, 0));
221
+ int tzhour, tzmin;
222
+ char tzsign = '+';
223
+ int len;
233
224
 
234
225
  if (out->end - out->cur <= 36) {
235
- assure_size(out, 36);
226
+ assure_size(out, 36);
236
227
  }
237
228
  if (9 > out->opts->sec_prec) {
238
- int i;
239
-
240
- // Rails does not round when reducing precision but instead floors,
241
- for (i = 9 - out->opts->sec_prec; 0 < i; i--) {
242
- nsec = nsec / 10;
243
- one /= 10;
244
- }
245
- if (one <= nsec) {
246
- nsec -= one;
247
- sec++;
248
- }
229
+ int i;
230
+
231
+ // Rails does not round when reducing precision but instead floors,
232
+ for (i = 9 - out->opts->sec_prec; 0 < i; i--) {
233
+ nsec = nsec / 10;
234
+ one /= 10;
235
+ }
236
+ if (one <= nsec) {
237
+ nsec -= one;
238
+ sec++;
239
+ }
249
240
  }
250
241
  // 2012-01-05T23:58:07.123456000+09:00 or 2012/01/05 23:58:07 +0900
251
242
  sec += tzsecs;
@@ -253,509 +244,505 @@ dump_sec_nano(VALUE obj, int64_t sec, long nsec, Out out) {
253
244
  if (0 > tzsecs) {
254
245
  tzsign = '-';
255
246
  tzhour = (int)(tzsecs / -3600);
256
- tzmin = (int)(tzsecs / -60) - (tzhour * 60);
247
+ tzmin = (int)(tzsecs / -60) - (tzhour * 60);
257
248
  } else {
258
249
  tzhour = (int)(tzsecs / 3600);
259
- tzmin = (int)(tzsecs / 60) - (tzhour * 60);
250
+ tzmin = (int)(tzsecs / 60) - (tzhour * 60);
260
251
  }
261
252
  if (!xml_time) {
262
- len = sprintf(buf, "%04d/%02d/%02d %02d:%02d:%02d %c%02d%02d", ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec, tzsign, tzhour, tzmin);
253
+ len = sprintf(buf,
254
+ "%04d/%02d/%02d %02d:%02d:%02d %c%02d%02d",
255
+ ti.year,
256
+ ti.mon,
257
+ ti.day,
258
+ ti.hour,
259
+ ti.min,
260
+ ti.sec,
261
+ tzsign,
262
+ tzhour,
263
+ tzmin);
263
264
  } else if (0 == out->opts->sec_prec) {
264
- if (0 == tzsecs && rb_funcall2(obj, oj_utcq_id, 0, 0)) {
265
- len = sprintf(buf, "%04d-%02d-%02dT%02d:%02d:%02dZ", ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec);
266
- } else {
267
- len = sprintf(buf, "%04d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d", ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec, tzsign, tzhour, tzmin);
268
- }
265
+ if (0 == tzsecs && rb_funcall2(obj, oj_utcq_id, 0, 0)) {
266
+ len = sprintf(buf, "%04d-%02d-%02dT%02d:%02d:%02dZ", ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec);
267
+ } else {
268
+ len = sprintf(buf,
269
+ "%04d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d",
270
+ ti.year,
271
+ ti.mon,
272
+ ti.day,
273
+ ti.hour,
274
+ ti.min,
275
+ ti.sec,
276
+ tzsign,
277
+ tzhour,
278
+ tzmin);
279
+ }
269
280
  } else if (0 == tzsecs && rb_funcall2(obj, oj_utcq_id, 0, 0)) {
270
- char format[64] = "%04d-%02d-%02dT%02d:%02d:%02d.%09ldZ";
271
-
272
- len = 30;
273
- if (9 > out->opts->sec_prec) {
274
- format[32] = '0' + out->opts->sec_prec;
275
- len -= 9 - out->opts->sec_prec;
276
- }
277
- len = sprintf(buf, format, ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec, nsec);
281
+ char format[64] = "%04d-%02d-%02dT%02d:%02d:%02d.%09ldZ";
282
+
283
+ len = 30;
284
+ if (9 > out->opts->sec_prec) {
285
+ format[32] = '0' + out->opts->sec_prec;
286
+ len -= 9 - out->opts->sec_prec;
287
+ }
288
+ len = sprintf(buf, format, ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec, nsec);
278
289
  } else {
279
- char format[64] = "%04d-%02d-%02dT%02d:%02d:%02d.%09ld%c%02d:%02d";
290
+ char format[64] = "%04d-%02d-%02dT%02d:%02d:%02d.%09ld%c%02d:%02d";
280
291
 
281
- len = 35;
282
- if (9 > out->opts->sec_prec) {
283
- format[32] = '0' + out->opts->sec_prec;
284
- len -= 9 - out->opts->sec_prec;
285
- }
286
- len = sprintf(buf, format, ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec, nsec, tzsign, tzhour, tzmin);
292
+ len = 35;
293
+ if (9 > out->opts->sec_prec) {
294
+ format[32] = '0' + out->opts->sec_prec;
295
+ len -= 9 - out->opts->sec_prec;
296
+ }
297
+ len = sprintf(buf, format, ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec, nsec, tzsign, tzhour, tzmin);
287
298
  }
288
299
  oj_dump_cstr(buf, len, 0, 0, out);
289
300
  }
290
301
 
291
- static void
292
- dump_time(VALUE obj, int depth, Out out, bool as_ok) {
293
- long long sec;
294
- long long nsec;
302
+ static void dump_time(VALUE obj, int depth, Out out, bool as_ok) {
303
+ long long sec;
304
+ long long nsec;
295
305
 
296
- #ifdef HAVE_RB_TIME_TIMESPEC
297
306
  if (16 <= sizeof(struct timespec)) {
298
- struct timespec ts = rb_time_timespec(obj);
307
+ struct timespec ts = rb_time_timespec(obj);
299
308
 
300
- sec = (long long)ts.tv_sec;
301
- nsec = ts.tv_nsec;
309
+ sec = (long long)ts.tv_sec;
310
+ nsec = ts.tv_nsec;
302
311
  } else {
303
- sec = rb_num2ll(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
304
- nsec = rb_num2ll(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
312
+ sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
313
+ nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
305
314
  }
306
- #else
307
- sec = rb_num2ll(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
308
- nsec = rb_num2ll(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
309
- #endif
310
315
  dump_sec_nano(obj, sec, nsec, out);
311
316
  }
312
317
 
313
- static void
314
- dump_timewithzone(VALUE obj, int depth, Out out, bool as_ok) {
315
- int64_t sec = NUM2LONG(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
316
- long long nsec = 0;
318
+ static void dump_timewithzone(VALUE obj, int depth, Out out, bool as_ok) {
319
+ int64_t sec = NUM2LONG(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
320
+ long long nsec = 0;
317
321
 
318
322
  if (rb_respond_to(obj, oj_tv_nsec_id)) {
319
- nsec = rb_num2ll(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
323
+ nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
320
324
  } else if (rb_respond_to(obj, oj_tv_usec_id)) {
321
- nsec = rb_num2ll(rb_funcall2(obj, oj_tv_usec_id, 0, 0)) * 1000;
325
+ nsec = NUM2LL(rb_funcall2(obj, oj_tv_usec_id, 0, 0)) * 1000;
322
326
  }
323
327
  dump_sec_nano(obj, sec, nsec, out);
324
328
  }
325
329
 
326
- static void
327
- dump_to_s(VALUE obj, int depth, Out out, bool as_ok) {
328
- volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
330
+ static void dump_to_s(VALUE obj, int depth, Out out, bool as_ok) {
331
+ volatile VALUE rstr = oj_safe_string_convert(obj);
329
332
 
330
- oj_dump_cstr(rb_string_value_ptr((VALUE*)&rstr), (int)RSTRING_LEN(rstr), 0, 0, out);
333
+ oj_dump_cstr(RSTRING_PTR(rstr), (int)RSTRING_LEN(rstr), 0, 0, out);
331
334
  }
332
335
 
333
- static ID parameters_id = 0;
336
+ static ID parameters_id = 0;
334
337
 
335
338
  typedef struct _strLen {
336
- const char *str;
337
- int len;
339
+ const char *str;
340
+ int len;
338
341
  } *StrLen;
339
342
 
340
- static void
341
- dump_actioncontroller_parameters(VALUE obj, int depth, Out out, bool as_ok) {
343
+ static void dump_actioncontroller_parameters(VALUE obj, int depth, Out out, bool as_ok) {
342
344
  if (0 == parameters_id) {
343
- parameters_id = rb_intern("@parameters");
345
+ parameters_id = rb_intern("@parameters");
344
346
  }
345
347
  out->argc = 0;
346
348
  dump_rails_val(rb_ivar_get(obj, parameters_id), depth, out, true);
347
349
  }
348
350
 
349
- static StrLen
350
- columns_array(VALUE rcols, int *ccnt) {
351
- volatile VALUE v;
352
- StrLen cp;
353
- StrLen cols;
354
- int i;
355
- int cnt = (int)RARRAY_LEN(rcols);
351
+ static StrLen columns_array(VALUE rcols, int *ccnt) {
352
+ volatile VALUE v;
353
+ StrLen cp;
354
+ StrLen cols;
355
+ int i;
356
+ int cnt = (int)RARRAY_LEN(rcols);
356
357
 
357
358
  *ccnt = cnt;
358
- cols = ALLOC_N(struct _strLen, cnt);
359
+ cols = OJ_R_ALLOC_N(struct _strLen, cnt);
359
360
  for (i = 0, cp = cols; i < cnt; i++, cp++) {
360
- v = rb_ary_entry(rcols, i);
361
- if (T_STRING != rb_type(v)) {
362
- v = rb_funcall(v, oj_to_s_id, 0);
363
- }
364
- cp->str = StringValuePtr(v);
365
- cp->len = (int)RSTRING_LEN(v);
361
+ v = RARRAY_AREF(rcols, i);
362
+ if (T_STRING != rb_type(v)) {
363
+ v = oj_safe_string_convert(v);
364
+ }
365
+ cp->str = StringValuePtr(v);
366
+ cp->len = (int)RSTRING_LEN(v);
366
367
  }
367
368
  return cols;
368
369
  }
369
370
 
370
- static void
371
- dump_row(VALUE row, StrLen cols, int ccnt, int depth, Out out) {
372
- size_t size;
373
- int d2 = depth + 1;
374
- int i;
371
+ static void dump_row(VALUE row, StrLen cols, int ccnt, int depth, Out out) {
372
+ size_t size;
373
+ int d2 = depth + 1;
374
+ int i;
375
375
 
376
376
  assure_size(out, 2);
377
377
  *out->cur++ = '{';
378
- size = depth * out->indent + 3;
378
+ size = depth * out->indent + 3;
379
379
  for (i = 0; i < ccnt; i++, cols++) {
380
- assure_size(out, size);
381
- if (out->opts->dump_opts.use) {
382
- if (0 < out->opts->dump_opts.array_size) {
383
- strcpy(out->cur, out->opts->dump_opts.array_nl);
384
- out->cur += out->opts->dump_opts.array_size;
385
- }
386
- if (0 < out->opts->dump_opts.indent_size) {
387
- int i;
388
- for (i = d2; 0 < i; i--) {
389
- strcpy(out->cur, out->opts->dump_opts.indent_str);
390
- out->cur += out->opts->dump_opts.indent_size;
391
- }
392
- }
393
- } else {
394
- fill_indent(out, d2);
395
- }
396
- oj_dump_cstr(cols->str, cols->len, 0, 0, out);
397
- *out->cur++ = ':';
398
- dump_rails_val(rb_ary_entry(row, i), depth, out, true);
399
- if (i < ccnt - 1) {
400
- *out->cur++ = ',';
401
- }
380
+ assure_size(out, size);
381
+ if (out->opts->dump_opts.use) {
382
+ if (0 < out->opts->dump_opts.array_size) {
383
+ APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
384
+ }
385
+ if (0 < out->opts->dump_opts.indent_size) {
386
+ int i;
387
+ for (i = d2; 0 < i; i--) {
388
+ APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
389
+ }
390
+ }
391
+ } else {
392
+ fill_indent(out, d2);
393
+ }
394
+ oj_dump_cstr(cols->str, cols->len, 0, 0, out);
395
+ *out->cur++ = ':';
396
+ dump_rails_val(RARRAY_AREF(row, i), depth, out, true);
397
+ if (i < ccnt - 1) {
398
+ *out->cur++ = ',';
399
+ }
402
400
  }
403
401
  size = depth * out->indent + 1;
404
402
  assure_size(out, size);
405
403
  if (out->opts->dump_opts.use) {
406
- if (0 < out->opts->dump_opts.array_size) {
407
- strcpy(out->cur, out->opts->dump_opts.array_nl);
408
- out->cur += out->opts->dump_opts.array_size;
409
- }
410
- if (0 < out->opts->dump_opts.indent_size) {
411
- int i;
412
-
413
- for (i = depth; 0 < i; i--) {
414
- strcpy(out->cur, out->opts->dump_opts.indent_str);
415
- out->cur += out->opts->dump_opts.indent_size;
416
- }
417
- }
404
+ if (0 < out->opts->dump_opts.array_size) {
405
+ APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
406
+ }
407
+ if (0 < out->opts->dump_opts.indent_size) {
408
+ int i;
409
+
410
+ for (i = depth; 0 < i; i--) {
411
+ APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
412
+ }
413
+ }
418
414
  } else {
419
- fill_indent(out, depth);
415
+ fill_indent(out, depth);
420
416
  }
421
417
  *out->cur++ = '}';
422
418
  }
423
419
 
424
- static ID rows_id = 0;
425
- static ID columns_id = 0;
420
+ static ID rows_id = 0;
421
+ static ID columns_id = 0;
426
422
 
427
- static void
428
- dump_activerecord_result(VALUE obj, int depth, Out out, bool as_ok) {
429
- volatile VALUE rows;
430
- StrLen cols;
431
- int ccnt = 0;
432
- int i, rcnt;
433
- size_t size;
434
- int d2 = depth + 1;
423
+ static void dump_activerecord_result(VALUE obj, int depth, Out out, bool as_ok) {
424
+ volatile VALUE rows;
425
+ StrLen cols;
426
+ int ccnt = 0;
427
+ int i, rcnt;
428
+ size_t size;
429
+ int d2 = depth + 1;
435
430
 
436
431
  if (0 == rows_id) {
437
- rows_id = rb_intern("@rows");
438
- columns_id = rb_intern("@columns");
432
+ rows_id = rb_intern("@rows");
433
+ columns_id = rb_intern("@columns");
439
434
  }
440
435
  out->argc = 0;
441
- cols = columns_array(rb_ivar_get(obj, columns_id), &ccnt);
442
- rows = rb_ivar_get(obj, rows_id);
443
- rcnt = (int)RARRAY_LEN(rows);
436
+ cols = columns_array(rb_ivar_get(obj, columns_id), &ccnt);
437
+ rows = rb_ivar_get(obj, rows_id);
438
+ rcnt = (int)RARRAY_LEN(rows);
444
439
  assure_size(out, 2);
445
440
  *out->cur++ = '[';
446
441
  if (out->opts->dump_opts.use) {
447
- size = d2 * out->opts->dump_opts.indent_size + out->opts->dump_opts.array_size + 1;
442
+ size = d2 * out->opts->dump_opts.indent_size + out->opts->dump_opts.array_size + 1;
448
443
  } else {
449
- size = d2 * out->indent + 2;
444
+ size = d2 * out->indent + 2;
450
445
  }
451
446
  assure_size(out, 2);
452
447
  for (i = 0; i < rcnt; i++) {
453
- assure_size(out, size);
454
- if (out->opts->dump_opts.use) {
455
- if (0 < out->opts->dump_opts.array_size) {
456
- strcpy(out->cur, out->opts->dump_opts.array_nl);
457
- out->cur += out->opts->dump_opts.array_size;
458
- }
459
- if (0 < out->opts->dump_opts.indent_size) {
460
- int i;
461
- for (i = d2; 0 < i; i--) {
462
- strcpy(out->cur, out->opts->dump_opts.indent_str);
463
- out->cur += out->opts->dump_opts.indent_size;
464
- }
465
- }
466
- } else {
467
- fill_indent(out, d2);
468
- }
469
- dump_row(rb_ary_entry(rows, i), cols, ccnt, d2, out);
470
- if (i < rcnt - 1) {
471
- *out->cur++ = ',';
472
- }
473
- }
474
- xfree(cols);
448
+ assure_size(out, size);
449
+ if (out->opts->dump_opts.use) {
450
+ if (0 < out->opts->dump_opts.array_size) {
451
+ APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
452
+ }
453
+ if (0 < out->opts->dump_opts.indent_size) {
454
+ int i;
455
+ for (i = d2; 0 < i; i--) {
456
+ APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
457
+ }
458
+ }
459
+ } else {
460
+ fill_indent(out, d2);
461
+ }
462
+ dump_row(RARRAY_AREF(rows, i), cols, ccnt, d2, out);
463
+ if (i < rcnt - 1) {
464
+ *out->cur++ = ',';
465
+ }
466
+ }
467
+ OJ_R_FREE(cols);
475
468
  size = depth * out->indent + 1;
476
469
  assure_size(out, size);
477
470
  if (out->opts->dump_opts.use) {
478
- if (0 < out->opts->dump_opts.array_size) {
479
- strcpy(out->cur, out->opts->dump_opts.array_nl);
480
- out->cur += out->opts->dump_opts.array_size;
481
- }
482
- if (0 < out->opts->dump_opts.indent_size) {
483
- int i;
484
-
485
- for (i = depth; 0 < i; i--) {
486
- strcpy(out->cur, out->opts->dump_opts.indent_str);
487
- out->cur += out->opts->dump_opts.indent_size;
488
- }
489
- }
471
+ if (0 < out->opts->dump_opts.array_size) {
472
+ APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
473
+ }
474
+ if (0 < out->opts->dump_opts.indent_size) {
475
+ int i;
476
+
477
+ for (i = depth; 0 < i; i--) {
478
+ APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
479
+ }
480
+ }
490
481
  } else {
491
- fill_indent(out, depth);
482
+ fill_indent(out, depth);
492
483
  }
493
484
  *out->cur++ = ']';
494
485
  }
495
486
 
496
487
  typedef struct _namedFunc {
497
- const char *name;
498
- DumpFunc func;
488
+ const char *name;
489
+ DumpFunc func;
499
490
  } *NamedFunc;
500
491
 
501
- static void
502
- dump_as_string(VALUE obj, int depth, Out out, bool as_ok) {
492
+ static void dump_as_string(VALUE obj, int depth, Out out, bool as_ok) {
503
493
  if (oj_code_dump(oj_compat_codes, obj, depth, out)) {
504
- out->argc = 0;
505
- return;
494
+ out->argc = 0;
495
+ return;
506
496
  }
507
497
  oj_dump_obj_to_s(obj, out);
508
498
  }
509
499
 
510
- static void
511
- dump_as_json(VALUE obj, int depth, Out out, bool as_ok) {
512
- volatile VALUE ja;
500
+ static void dump_as_json(VALUE obj, int depth, Out out, bool as_ok) {
501
+ volatile VALUE ja;
513
502
 
514
- if (Yes == out->opts->trace) {
515
- oj_trace("as_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyIn);
516
- }
503
+ TRACE(out->opts->trace, "as_json", obj, depth + 1, TraceRubyIn);
517
504
  // Some classes elect to not take an options argument so check the arity
518
505
  // of as_json.
519
506
  if (0 == rb_obj_method_arity(obj, oj_as_json_id)) {
520
- ja = rb_funcall(obj, oj_as_json_id, 0);
507
+ ja = rb_funcall(obj, oj_as_json_id, 0);
521
508
  } else {
522
- ja = rb_funcall2(obj, oj_as_json_id, out->argc, out->argv);
523
- }
524
- if (Yes == out->opts->trace) {
525
- oj_trace("as_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyOut);
509
+ ja = rb_funcall2(obj, oj_as_json_id, out->argc, out->argv);
526
510
  }
511
+ TRACE(out->opts->trace, "as_json", obj, depth + 1, TraceRubyOut);
527
512
 
528
513
  out->argc = 0;
529
514
  if (ja == obj || !as_ok) {
530
- // Once as_json is called it should never be called again on the same
531
- // object with as_ok.
532
- dump_rails_val(ja, depth, out, false);
515
+ // Once as_json is called it should never be called again on the same
516
+ // object with as_ok.
517
+ dump_rails_val(ja, depth, out, false);
533
518
  } else {
534
- int type = rb_type(ja);
519
+ int type = rb_type(ja);
535
520
 
536
- if (T_HASH == type || T_ARRAY == type) {
537
- dump_rails_val(ja, depth, out, true);
538
- } else {
539
- dump_rails_val(ja, depth, out, true);
540
- }
521
+ if (T_HASH == type || T_ARRAY == type) {
522
+ dump_rails_val(ja, depth, out, true);
523
+ } else {
524
+ dump_rails_val(ja, depth, out, true);
525
+ }
541
526
  }
542
527
  }
543
528
 
544
- static void
545
- dump_regexp(VALUE obj, int depth, Out out, bool as_ok) {
529
+ static void dump_regexp(VALUE obj, int depth, Out out, bool as_ok) {
546
530
  if (as_ok && rb_respond_to(obj, oj_as_json_id)) {
547
- dump_as_json(obj, depth, out, false);
548
- return;
531
+ dump_as_json(obj, depth, out, false);
532
+ return;
549
533
  }
550
534
  dump_as_string(obj, depth, out, as_ok);
551
535
  }
552
536
 
553
- static struct _namedFunc dump_map[] = {
554
- { "ActionController::Parameters", dump_actioncontroller_parameters },
555
- { "ActiveRecord::Result", dump_activerecord_result },
556
- { "ActiveSupport::TimeWithZone", dump_timewithzone },
557
- { "BigDecimal", dump_bigdecimal },
558
- { "Range", dump_to_s },
559
- { "Regexp", dump_regexp },
537
+ static struct _namedFunc dump_map[] = {
538
+ {"ActionController::Parameters", dump_actioncontroller_parameters},
539
+ {"ActiveRecord::Result", dump_activerecord_result},
540
+ {"ActiveSupport::TimeWithZone", dump_timewithzone},
541
+ {"BigDecimal", dump_bigdecimal},
542
+ {"Range", dump_to_s},
543
+ {"Regexp", dump_regexp},
560
544
  //{ "Regexp", dump_to_s },
561
- { "Time", dump_time },
562
- { NULL, NULL },
545
+ {"Time", dump_time},
546
+ {NULL, NULL},
563
547
  };
564
548
 
565
- static VALUE activerecord_base = Qundef;
566
- static ID attributes_id = 0;
549
+ static VALUE activerecord_base = Qundef;
550
+ static ID attributes_id = 0;
567
551
 
568
- static void
569
- dump_activerecord(VALUE obj, int depth, Out out, bool as_ok) {
552
+ static void dump_activerecord(VALUE obj, int depth, Out out, bool as_ok) {
570
553
  if (0 == attributes_id) {
571
- attributes_id = rb_intern("@attributes");
554
+ attributes_id = rb_intern("@attributes");
572
555
  }
573
556
  out->argc = 0;
574
557
  dump_rails_val(rb_ivar_get(obj, attributes_id), depth, out, true);
575
558
  }
576
559
 
577
- static ROpt
578
- create_opt(ROptTable rot, VALUE clas) {
579
- ROpt ro;
580
- NamedFunc nf;
581
- const char *classname = rb_class2name(clas);
582
- int olen = rot->len;
560
+ static ROpt create_opt(ROptTable rot, VALUE clas) {
561
+ ROpt ro;
562
+ NamedFunc nf;
563
+ const char *classname = rb_class2name(clas);
564
+ int olen = rot->len;
583
565
 
584
566
  rot->len++;
585
567
  if (NULL == rot->table) {
586
- rot->alen = 256;
587
- rot->table = ALLOC_N(struct _rOpt, rot->alen);
588
- memset(rot->table, 0, sizeof(struct _rOpt) * rot->alen);
568
+ rot->alen = 256;
569
+ rot->table = OJ_R_ALLOC_N(struct _rOpt, rot->alen);
570
+ memset(rot->table, 0, sizeof(struct _rOpt) * rot->alen);
589
571
  } else if (rot->alen <= rot->len) {
590
- rot->alen *= 2;
591
- REALLOC_N(rot->table, struct _rOpt, rot->alen);
592
- memset(rot->table + olen, 0, sizeof(struct _rOpt) * olen);
572
+ rot->alen *= 2;
573
+ OJ_R_REALLOC_N(rot->table, struct _rOpt, rot->alen);
574
+ memset(rot->table + olen, 0, sizeof(struct _rOpt) * olen);
593
575
  }
594
576
  if (0 == olen) {
595
- ro = rot->table;
577
+ ro = rot->table;
596
578
  } else if (rot->table[olen - 1].clas < clas) {
597
- ro = &rot->table[olen];
579
+ ro = &rot->table[olen];
598
580
  } else {
599
- int i;
581
+ int i;
600
582
 
601
- for (i = 0, ro = rot->table; i < olen; i++, ro++) {
602
- if (clas < ro->clas) {
603
- memmove(ro + 1, ro, sizeof(struct _rOpt) * (olen - i));
604
- break;
605
- }
606
- }
583
+ for (i = 0, ro = rot->table; i < olen; i++, ro++) {
584
+ if (clas < ro->clas) {
585
+ memmove(ro + 1, ro, sizeof(struct _rOpt) * (olen - i));
586
+ break;
587
+ }
588
+ }
607
589
  }
608
590
  ro->clas = clas;
609
- ro->on = true;
591
+ ro->on = true;
610
592
  ro->dump = dump_obj_attrs;
611
593
  for (nf = dump_map; NULL != nf->name; nf++) {
612
- if (0 == strcmp(nf->name, classname)) {
613
- ro->dump = nf->func;
614
- break;
615
- }
594
+ if (0 == strcmp(nf->name, classname)) {
595
+ ro->dump = nf->func;
596
+ break;
597
+ }
616
598
  }
617
599
  if (ro->dump == dump_obj_attrs) {
618
- if (Qundef == activerecord_base) {
619
- // If not defined let an exception be raised.
620
- VALUE ar = rb_const_get_at(rb_cObject, rb_intern("ActiveRecord"));
621
-
622
- if (Qundef != ar) {
623
- activerecord_base = rb_const_get_at(ar, rb_intern("Base"));
624
- }
625
- }
626
- if (Qundef != activerecord_base && Qtrue == rb_class_inherited_p(clas, activerecord_base)) {
627
- ro->dump = dump_activerecord;
628
- } else if (Qtrue == rb_class_inherited_p(clas, rb_cStruct)) { // check before enumerable
629
- ro->dump = dump_struct;
630
- } else if (Qtrue == rb_class_inherited_p(clas, rb_mEnumerable)) {
631
- ro->dump = dump_enumerable;
632
- } else if (Qtrue == rb_class_inherited_p(clas, rb_eException)) {
633
- ro->dump = dump_to_s;
634
- }
600
+ if (Qundef == activerecord_base) {
601
+ // If not defined let an exception be raised.
602
+ VALUE ar = rb_const_get_at(rb_cObject, rb_intern("ActiveRecord"));
603
+
604
+ if (Qundef != ar) {
605
+ activerecord_base = rb_const_get_at(ar, rb_intern("Base"));
606
+ }
607
+ }
608
+ if (Qundef != activerecord_base && Qtrue == rb_class_inherited_p(clas, activerecord_base)) {
609
+ ro->dump = dump_activerecord;
610
+ } else if (Qtrue == rb_class_inherited_p(clas, rb_cStruct)) { // check before enumerable
611
+ ro->dump = dump_struct;
612
+ } else if (Qtrue == rb_class_inherited_p(clas, rb_mEnumerable)) {
613
+ ro->dump = dump_enumerable;
614
+ } else if (Qtrue == rb_class_inherited_p(clas, rb_eException)) {
615
+ ro->dump = dump_to_s;
616
+ }
635
617
  }
636
618
  return ro;
637
619
  }
638
620
 
639
- static void
640
- encoder_free(void *ptr) {
621
+ static void encoder_free(void *ptr) {
641
622
  if (NULL != ptr) {
642
- Encoder e = (Encoder)ptr;
623
+ Encoder e = (Encoder)ptr;
643
624
 
644
- if (NULL != e->ropts.table) {
645
- xfree(e->ropts.table);
646
- }
647
- xfree(ptr);
625
+ if (NULL != e->ropts.table) {
626
+ OJ_R_FREE(e->ropts.table);
627
+ }
628
+ OJ_R_FREE(ptr);
648
629
  }
649
630
  }
650
631
 
651
- static void
652
- encoder_mark(void *ptr) {
632
+ static void encoder_mark(void *ptr) {
653
633
  if (NULL != ptr) {
654
- Encoder e = (Encoder)ptr;
634
+ Encoder e = (Encoder)ptr;
655
635
 
656
- if (Qnil != e->arg) {
657
- rb_gc_mark(e->arg);
658
- }
636
+ if (Qnil != e->arg) {
637
+ rb_gc_mark(e->arg);
638
+ }
659
639
  }
660
640
  }
661
641
 
642
+ static const rb_data_type_t oj_encoder_type = {
643
+ "Oj/encoder",
644
+ {
645
+ encoder_mark,
646
+ encoder_free,
647
+ NULL,
648
+ },
649
+ 0,
650
+ 0,
651
+ };
652
+
662
653
  /* Document-method: new
663
654
  * call-seq: new(options=nil)
664
655
  *
665
656
  * Creates a new Encoder.
666
657
  * - *options* [_Hash_] formatting options
667
658
  */
668
- static VALUE
669
- encoder_new(int argc, VALUE *argv, VALUE self) {
670
- Encoder e = ALLOC(struct _encoder);
659
+ static VALUE encoder_new(int argc, VALUE *argv, VALUE self) {
660
+ Encoder e = OJ_R_ALLOC(struct _encoder);
671
661
 
672
662
  e->opts = oj_default_options;
673
- e->arg = Qnil;
663
+ e->arg = Qnil;
674
664
  copy_opts(&ropts, &e->ropts);
675
665
 
676
666
  if (1 <= argc && Qnil != *argv) {
677
- oj_parse_options(*argv, &e->opts);
678
- e->arg = *argv;
667
+ oj_parse_options(*argv, &e->opts);
668
+ e->arg = *argv;
679
669
  }
680
- return Data_Wrap_Struct(encoder_class, encoder_mark, encoder_free, e);
670
+ return TypedData_Wrap_Struct(encoder_class, &oj_encoder_type, e);
681
671
  }
682
672
 
683
- static VALUE
684
- resolve_classpath(const char *name) {
685
- char class_name[1024];
686
- VALUE clas;
687
- char *end = class_name + sizeof(class_name) - 1;
688
- char *s;
689
- const char *n = name;
690
- ID cid;
673
+ static VALUE resolve_classpath(const char *name) {
674
+ char class_name[1024];
675
+ VALUE clas;
676
+ char *end = class_name + sizeof(class_name) - 1;
677
+ char *s;
678
+ const char *n = name;
679
+ ID cid;
691
680
 
692
681
  clas = rb_cObject;
693
682
  for (s = class_name; '\0' != *n; n++) {
694
- if (':' == *n) {
695
- *s = '\0';
696
- n++;
697
- if (':' != *n) {
698
- return Qnil;
699
- }
700
- cid = rb_intern(class_name);
701
- if (!rb_const_defined_at(clas, cid)) {
702
- return Qnil;
703
- }
704
- clas = rb_const_get_at(clas, cid);
705
- s = class_name;
706
- } else if (end <= s) {
707
- return Qnil;
708
- } else {
709
- *s++ = *n;
710
- }
711
- }
712
- *s = '\0';
683
+ if (':' == *n) {
684
+ *s = '\0';
685
+ n++;
686
+ if (':' != *n) {
687
+ return Qnil;
688
+ }
689
+ cid = rb_intern(class_name);
690
+ if (!rb_const_defined_at(clas, cid)) {
691
+ return Qnil;
692
+ }
693
+ clas = rb_const_get_at(clas, cid);
694
+ s = class_name;
695
+ } else if (end <= s) {
696
+ return Qnil;
697
+ } else {
698
+ *s++ = *n;
699
+ }
700
+ }
701
+ *s = '\0';
713
702
  cid = rb_intern(class_name);
714
703
  if (!rb_const_defined_at(clas, cid)) {
715
- return Qnil;
704
+ return Qnil;
716
705
  }
717
706
  clas = rb_const_get_at(clas, cid);
718
707
 
719
708
  return clas;
720
709
  }
721
710
 
722
- static void
723
- optimize(int argc, VALUE *argv, ROptTable rot, bool on) {
724
- ROpt ro;
711
+ static void optimize(int argc, VALUE *argv, ROptTable rot, bool on) {
712
+ ROpt ro;
725
713
 
726
714
  if (0 == argc) {
727
- int i;
728
- NamedFunc nf;
729
- VALUE clas;
730
-
731
- oj_rails_hash_opt = on;
732
- oj_rails_array_opt = on;
733
- oj_rails_float_opt = on;
734
-
735
- for (nf = dump_map; NULL != nf->name; nf++) {
736
- if (Qnil != (clas = resolve_classpath(nf->name))) {
737
- if (NULL == oj_rails_get_opt(rot, clas)) {
738
- create_opt(rot, clas);
739
- }
740
- }
741
- }
742
- for (i = 0; i < rot->len; i++) {
743
- rot->table[i].on = on;
744
- }
715
+ int i;
716
+ NamedFunc nf;
717
+ VALUE clas;
718
+
719
+ oj_rails_hash_opt = on;
720
+ oj_rails_array_opt = on;
721
+ oj_rails_float_opt = on;
722
+
723
+ for (nf = dump_map; NULL != nf->name; nf++) {
724
+ if (Qnil != (clas = resolve_classpath(nf->name))) {
725
+ if (NULL == oj_rails_get_opt(rot, clas)) {
726
+ create_opt(rot, clas);
727
+ }
728
+ }
729
+ }
730
+ for (i = 0; i < rot->len; i++) {
731
+ rot->table[i].on = on;
732
+ }
745
733
  }
746
734
  for (; 0 < argc; argc--, argv++) {
747
- if (rb_cHash == *argv) {
748
- oj_rails_hash_opt = on;
749
- } else if (rb_cArray == *argv) {
750
- oj_rails_array_opt = on;
751
- } else if (rb_cFloat == *argv) {
752
- oj_rails_float_opt = on;
753
- } else if (oj_string_writer_class == *argv) {
754
- string_writer_optimized = on;
755
- } else if (NULL != (ro = oj_rails_get_opt(rot, *argv)) ||
756
- NULL != (ro = create_opt(rot, *argv))) {
757
- ro->on = on;
758
- }
735
+ if (rb_cHash == *argv) {
736
+ oj_rails_hash_opt = on;
737
+ } else if (rb_cArray == *argv) {
738
+ oj_rails_array_opt = on;
739
+ } else if (rb_cFloat == *argv) {
740
+ oj_rails_float_opt = on;
741
+ } else if (oj_string_writer_class == *argv) {
742
+ string_writer_optimized = on;
743
+ } else if (NULL != (ro = oj_rails_get_opt(rot, *argv)) || NULL != (ro = create_opt(rot, *argv))) {
744
+ ro->on = on;
745
+ }
759
746
  }
760
747
  }
761
748
 
@@ -771,9 +758,9 @@ optimize(int argc, VALUE *argv, ROptTable rot, bool on) {
771
758
  *
772
759
  * - *classes* [_Class_] a list of classes to optimize
773
760
  */
774
- static VALUE
775
- encoder_optimize(int argc, VALUE *argv, VALUE self) {
776
- Encoder e = (Encoder)DATA_PTR(self);
761
+ static VALUE encoder_optimize(int argc, VALUE *argv, VALUE self) {
762
+ Encoder e;
763
+ TypedData_Get_Struct(self, struct _encoder, &oj_encoder_type, e);
777
764
 
778
765
  optimize(argc, argv, &e->ropts, true);
779
766
 
@@ -792,8 +779,7 @@ encoder_optimize(int argc, VALUE *argv, VALUE self) {
792
779
  *
793
780
  * - *classes* [_Class_] a list of classes to optimize
794
781
  */
795
- static VALUE
796
- rails_optimize(int argc, VALUE *argv, VALUE self) {
782
+ static VALUE rails_optimize(int argc, VALUE *argv, VALUE self) {
797
783
  optimize(argc, argv, &ropts, true);
798
784
  string_writer_optimized = true;
799
785
 
@@ -808,15 +794,16 @@ rails_optimize(int argc, VALUE *argv, VALUE self) {
808
794
  */
809
795
  VALUE
810
796
  rails_mimic_json(VALUE self) {
811
- VALUE json;
797
+ VALUE json;
812
798
 
813
799
  if (rb_const_defined_at(rb_cObject, rb_intern("JSON"))) {
814
- json = rb_const_get_at(rb_cObject, rb_intern("JSON"));
800
+ json = rb_const_get_at(rb_cObject, rb_intern("JSON"));
815
801
  } else {
816
- json = rb_define_module("JSON");
802
+ json = rb_define_module("JSON");
817
803
  }
818
804
  oj_mimic_json_methods(json);
819
- //oj_default_options.mode = RailsMode;
805
+ // Setting the default mode breaks the prmoise in the docs not to.
806
+ // oj_default_options.mode = RailsMode;
820
807
 
821
808
  return Qnil;
822
809
  }
@@ -828,9 +815,9 @@ rails_mimic_json(VALUE self) {
828
815
  *
829
816
  * - *classes* [_Class_] a list of classes to deoptimize
830
817
  */
831
- static VALUE
832
- encoder_deoptimize(int argc, VALUE *argv, VALUE self) {
833
- Encoder e = (Encoder)DATA_PTR(self);
818
+ static VALUE encoder_deoptimize(int argc, VALUE *argv, VALUE self) {
819
+ Encoder e;
820
+ TypedData_Get_Struct(self, struct _encoder, &oj_encoder_type, e);
834
821
 
835
822
  optimize(argc, argv, &e->ropts, false);
836
823
 
@@ -844,8 +831,7 @@ encoder_deoptimize(int argc, VALUE *argv, VALUE self) {
844
831
  *
845
832
  * - *classes* [_Class_] a list of classes to deoptimize
846
833
  */
847
- static VALUE
848
- rails_deoptimize(int argc, VALUE *argv, VALUE self) {
834
+ static VALUE rails_deoptimize(int argc, VALUE *argv, VALUE self) {
849
835
  optimize(argc, argv, &ropts, false);
850
836
  string_writer_optimized = false;
851
837
 
@@ -859,13 +845,15 @@ rails_deoptimize(int argc, VALUE *argv, VALUE self) {
859
845
  *
860
846
  * @return true if the class is being optimized for rails and false otherwise
861
847
  */
862
- static VALUE
863
- encoder_optimized(VALUE self, VALUE clas) {
864
- Encoder e = (Encoder)DATA_PTR(self);
865
- ROpt ro = oj_rails_get_opt(&e->ropts, clas);
848
+ static VALUE encoder_optimized(VALUE self, VALUE clas) {
849
+ Encoder e;
850
+ ROpt ro;
851
+
852
+ TypedData_Get_Struct(self, struct _encoder, &oj_encoder_type, e);
853
+ ro = oj_rails_get_opt(&e->ropts, clas);
866
854
 
867
855
  if (NULL == ro) {
868
- return Qfalse;
856
+ return Qfalse;
869
857
  }
870
858
  return (ro->on) ? Qtrue : Qfalse;
871
859
  }
@@ -875,95 +863,87 @@ encoder_optimized(VALUE self, VALUE clas) {
875
863
  *
876
864
  * Returns true if the specified Class is being optimized.
877
865
  */
878
- static VALUE
879
- rails_optimized(VALUE self, VALUE clas) {
880
- ROpt ro = oj_rails_get_opt(&ropts, clas);
866
+ static VALUE rails_optimized(VALUE self, VALUE clas) {
867
+ ROpt ro = oj_rails_get_opt(&ropts, clas);
881
868
 
882
869
  if (NULL == ro) {
883
- return Qfalse;
870
+ return Qfalse;
884
871
  }
885
872
  return (ro->on) ? Qtrue : Qfalse;
886
873
  }
887
874
 
888
875
  typedef struct _oo {
889
- Out out;
890
- VALUE obj;
876
+ Out out;
877
+ VALUE obj;
891
878
  } *OO;
892
879
 
893
- static VALUE
894
- protect_dump(VALUE ov) {
895
- OO oo = (OO)ov;
880
+ static VALUE protect_dump(VALUE ov) {
881
+ OO oo = (OO)ov;
896
882
 
897
883
  dump_rails_val(oo->obj, 0, oo->out, true);
898
884
 
899
885
  return Qnil;
900
886
  }
901
887
 
902
- static VALUE
903
- encode(VALUE obj, ROptTable ropts, Options opts, int argc, VALUE *argv) {
904
- char buf[4096];
905
- struct _out out;
906
- struct _options copts = *opts;
907
- volatile VALUE rstr = Qnil;
908
- struct _oo oo;
909
- int line = 0;
910
-
911
- oo.out = &out;
912
- oo.obj = obj;
888
+ static VALUE encode(VALUE obj, ROptTable ropts, Options opts, int argc, VALUE *argv) {
889
+ struct _out out;
890
+ struct _options copts = *opts;
891
+ volatile VALUE rstr = Qnil;
892
+ struct _oo oo;
893
+ int line = 0;
894
+
895
+ oo.out = &out;
896
+ oo.obj = obj;
913
897
  copts.str_rx.head = NULL;
914
898
  copts.str_rx.tail = NULL;
915
- copts.mode = RailsMode;
899
+ copts.mode = RailsMode;
916
900
  if (escape_html) {
917
- copts.escape_mode = RailsXEsc;
901
+ copts.escape_mode = RailsXEsc;
918
902
  } else {
919
- copts.escape_mode = RailsEsc;
903
+ copts.escape_mode = RailsEsc;
920
904
  }
921
- out.buf = buf;
922
- out.end = buf + sizeof(buf) - 10;
923
- out.allocated = false;
905
+
906
+ oj_out_init(&out);
907
+
924
908
  out.omit_nil = copts.dump_opts.omit_nil;
925
- out.caller = 0;
926
- out.cur = out.buf;
909
+ out.cur = out.buf;
927
910
  out.circ_cnt = 0;
928
- out.opts = &copts;
911
+ out.opts = &copts;
929
912
  out.hash_cnt = 0;
930
- out.indent = copts.indent;
931
- out.argc = argc;
932
- out.argv = argv;
933
- out.ropts = ropts;
913
+ out.indent = copts.indent;
914
+ out.argc = argc;
915
+ out.argv = argv;
916
+ out.ropts = ropts;
934
917
  if (Yes == copts.circular) {
935
- oj_cache8_new(&out.circ_cache);
918
+ oj_cache8_new(&out.circ_cache);
936
919
  }
937
- //dump_rails_val(*argv, 0, &out, true);
920
+ // dump_rails_val(*argv, 0, &out, true);
938
921
  rb_protect(protect_dump, (VALUE)&oo, &line);
939
922
 
940
923
  if (0 == line) {
941
- if (0 < out.indent) {
942
- switch (*(out.cur - 1)) {
943
- case ']':
944
- case '}':
945
- assure_size(&out, 2);
946
- *out.cur++ = '\n';
947
- default:
948
- break;
949
- }
950
- }
951
- *out.cur = '\0';
952
-
953
- if (0 == out.buf) {
954
- rb_raise(rb_eNoMemError, "Not enough memory.");
955
- }
956
- rstr = rb_str_new2(out.buf);
957
- rstr = oj_encode(rstr);
924
+ if (0 < out.indent) {
925
+ switch (*(out.cur - 1)) {
926
+ case ']':
927
+ case '}': assure_size(&out, 2); *out.cur++ = '\n';
928
+ default: break;
929
+ }
930
+ }
931
+ *out.cur = '\0';
932
+
933
+ if (0 == out.buf) {
934
+ rb_raise(rb_eNoMemError, "Not enough memory.");
935
+ }
936
+ rstr = rb_str_new2(out.buf);
937
+ rstr = oj_encode(rstr);
958
938
  }
959
939
  if (Yes == copts.circular) {
960
- oj_cache8_delete(out.circ_cache);
961
- }
962
- if (out.allocated) {
963
- xfree(out.buf);
940
+ oj_cache8_delete(out.circ_cache);
964
941
  }
942
+
943
+ oj_out_free(&out);
944
+
965
945
  if (0 != line) {
966
- rb_jump_tag(line);
946
+ rb_jump_tag(line);
967
947
  }
968
948
  return rstr;
969
949
  }
@@ -975,14 +955,14 @@ encode(VALUE obj, ROptTable ropts, Options opts, int argc, VALUE *argv) {
975
955
  *
976
956
  * Returns encoded object as a JSON string.
977
957
  */
978
- static VALUE
979
- encoder_encode(VALUE self, VALUE obj) {
980
- Encoder e = (Encoder)DATA_PTR(self);
958
+ static VALUE encoder_encode(VALUE self, VALUE obj) {
959
+ Encoder e;
960
+ TypedData_Get_Struct(self, struct _encoder, &oj_encoder_type, e);
981
961
 
982
962
  if (Qnil != e->arg) {
983
- VALUE argv[1] = { e->arg };
963
+ VALUE argv[1] = {e->arg};
984
964
 
985
- return encode(obj, &e->ropts, &e->opts, 1, argv);
965
+ return encode(obj, &e->ropts, &e->opts, 1, argv);
986
966
  }
987
967
  return encode(obj, &e->ropts, &e->opts, 0, NULL);
988
968
  }
@@ -997,26 +977,24 @@ encoder_encode(VALUE self, VALUE obj) {
997
977
  *
998
978
  * Returns [_String_]
999
979
  */
1000
- static VALUE
1001
- rails_encode(int argc, VALUE *argv, VALUE self) {
980
+ static VALUE rails_encode(int argc, VALUE *argv, VALUE self) {
1002
981
  if (1 > argc) {
1003
- rb_raise(rb_eArgError, "wrong number of arguments (0 for 1).");
982
+ rb_raise(rb_eArgError, "wrong number of arguments (0 for 1).");
1004
983
  }
1005
984
  if (1 == argc) {
1006
- return encode(*argv, NULL, &oj_default_options, 0, NULL);
985
+ return encode(*argv, NULL, &oj_default_options, 0, NULL);
1007
986
  } else {
1008
- return encode(*argv, NULL, &oj_default_options, argc - 1, argv + 1);
987
+ return encode(*argv, NULL, &oj_default_options, argc - 1, argv + 1);
1009
988
  }
1010
989
  }
1011
990
 
1012
- static VALUE
1013
- rails_use_standard_json_time_format(VALUE self, VALUE state) {
991
+ static VALUE rails_use_standard_json_time_format(VALUE self, VALUE state) {
1014
992
  if (Qtrue == state || Qfalse == state) {
1015
- // no change needed
993
+ // no change needed
1016
994
  } else if (Qnil == state) {
1017
- state = Qfalse;
995
+ state = Qfalse;
1018
996
  } else {
1019
- state = Qtrue;
997
+ state = Qtrue;
1020
998
  }
1021
999
  rb_iv_set(self, "@use_standard_json_time_format", state);
1022
1000
  xml_time = Qtrue == state;
@@ -1024,28 +1002,24 @@ rails_use_standard_json_time_format(VALUE self, VALUE state) {
1024
1002
  return state;
1025
1003
  }
1026
1004
 
1027
- static VALUE
1028
- rails_use_standard_json_time_format_get(VALUE self) {
1005
+ static VALUE rails_use_standard_json_time_format_get(VALUE self) {
1029
1006
  return xml_time ? Qtrue : Qfalse;
1030
1007
  }
1031
1008
 
1032
- static VALUE
1033
- rails_escape_html_entities_in_json(VALUE self, VALUE state) {
1009
+ static VALUE rails_escape_html_entities_in_json(VALUE self, VALUE state) {
1034
1010
  rb_iv_set(self, "@escape_html_entities_in_json", state);
1035
1011
  escape_html = Qtrue == state;
1036
1012
 
1037
1013
  return state;
1038
1014
  }
1039
1015
 
1040
- static VALUE
1041
- rails_escape_html_entities_in_json_get(VALUE self) {
1016
+ static VALUE rails_escape_html_entities_in_json_get(VALUE self) {
1042
1017
  return escape_html ? Qtrue : Qfalse;
1043
1018
  }
1044
1019
 
1045
- static VALUE
1046
- rails_time_precision(VALUE self, VALUE prec) {
1020
+ static VALUE rails_time_precision(VALUE self, VALUE prec) {
1047
1021
  rb_iv_set(self, "@time_precision", prec);
1048
- oj_default_options.sec_prec = NUM2INT(prec);
1022
+ oj_default_options.sec_prec = NUM2INT(prec);
1049
1023
  oj_default_options.sec_prec_set = true;
1050
1024
 
1051
1025
  return prec;
@@ -1058,27 +1032,26 @@ rails_time_precision(VALUE self, VALUE prec) {
1058
1032
  * formatting globals used by ActiveSupport to allow the use of those globals
1059
1033
  * in the Oj::Rails optimizations.
1060
1034
  */
1061
- static VALUE
1062
- rails_set_encoder(VALUE self) {
1063
- VALUE active;
1064
- VALUE json;
1065
- VALUE encoding;
1066
- VALUE pv;
1067
- VALUE verbose;
1068
- VALUE enc = resolve_classpath("ActiveSupport::JSON::Encoding");
1035
+ static VALUE rails_set_encoder(VALUE self) {
1036
+ VALUE active;
1037
+ VALUE json;
1038
+ VALUE encoding;
1039
+ VALUE pv;
1040
+ VALUE verbose;
1041
+ VALUE enc = resolve_classpath("ActiveSupport::JSON::Encoding");
1069
1042
 
1070
1043
  if (Qnil != enc) {
1071
- escape_html = Qtrue == rb_iv_get(self, "@escape_html_entities_in_json");
1072
- xml_time = Qtrue == rb_iv_get(enc, "@use_standard_json_time_format");
1044
+ escape_html = Qtrue == rb_iv_get(self, "@escape_html_entities_in_json");
1045
+ xml_time = Qtrue == rb_iv_get(enc, "@use_standard_json_time_format");
1073
1046
  }
1074
1047
  if (rb_const_defined_at(rb_cObject, rb_intern("ActiveSupport"))) {
1075
- active = rb_const_get_at(rb_cObject, rb_intern("ActiveSupport"));
1048
+ active = rb_const_get_at(rb_cObject, rb_intern("ActiveSupport"));
1076
1049
  } else {
1077
- rb_raise(rb_eStandardError, "ActiveSupport not loaded.");
1050
+ rb_raise(rb_eStandardError, "ActiveSupport not loaded.");
1078
1051
  }
1079
1052
  rb_funcall(active, rb_intern("json_encoder="), 1, encoder_class);
1080
1053
 
1081
- json = rb_const_get_at(active, rb_intern("JSON"));
1054
+ json = rb_const_get_at(active, rb_intern("JSON"));
1082
1055
  encoding = rb_const_get_at(json, rb_intern("Encoding"));
1083
1056
 
1084
1057
  // rb_undef_method doesn't work for modules or maybe sometimes
@@ -1090,15 +1063,15 @@ rails_set_encoder(VALUE self) {
1090
1063
  rb_undef_method(encoding, "use_standard_json_time_format");
1091
1064
  rb_define_module_function(encoding, "use_standard_json_time_format", rails_use_standard_json_time_format_get, 0);
1092
1065
 
1093
- pv = rb_iv_get(encoding, "@escape_html_entities_in_json");
1066
+ pv = rb_iv_get(encoding, "@escape_html_entities_in_json");
1094
1067
  escape_html = Qtrue == pv;
1095
1068
  rb_undef_method(encoding, "escape_html_entities_in_json=");
1096
1069
  rb_define_module_function(encoding, "escape_html_entities_in_json=", rails_escape_html_entities_in_json, 1);
1097
1070
  rb_undef_method(encoding, "escape_html_entities_in_json");
1098
1071
  rb_define_module_function(encoding, "escape_html_entities_in_json", rails_escape_html_entities_in_json_get, 0);
1099
1072
 
1100
- pv = rb_iv_get(encoding, "@time_precision");
1101
- oj_default_options.sec_prec = NUM2INT(pv);
1073
+ pv = rb_iv_get(encoding, "@time_precision");
1074
+ oj_default_options.sec_prec = NUM2INT(pv);
1102
1075
  oj_default_options.sec_prec_set = true;
1103
1076
  rb_undef_method(encoding, "time_precision=");
1104
1077
  rb_define_module_function(encoding, "time_precision=", rails_time_precision, 1);
@@ -1113,16 +1086,15 @@ rails_set_encoder(VALUE self) {
1113
1086
  * Sets the JSON.parse function to be the Oj::parse function which is json gem
1114
1087
  * compatible.
1115
1088
  */
1116
- static VALUE
1117
- rails_set_decoder(VALUE self) {
1118
- VALUE json;
1119
- VALUE json_error;
1120
- VALUE verbose;
1089
+ static VALUE rails_set_decoder(VALUE self) {
1090
+ VALUE json;
1091
+ VALUE json_error;
1092
+ VALUE verbose;
1121
1093
 
1122
1094
  if (rb_const_defined_at(rb_cObject, rb_intern("JSON"))) {
1123
- json = rb_const_get_at(rb_cObject, rb_intern("JSON"));
1095
+ json = rb_const_get_at(rb_cObject, rb_intern("JSON"));
1124
1096
  } else {
1125
- json = rb_define_module("JSON");
1097
+ json = rb_define_module("JSON");
1126
1098
  }
1127
1099
  if (rb_const_defined_at(json, rb_intern("JSONError"))) {
1128
1100
  json_error = rb_const_get(json, rb_intern("JSONError"));
@@ -1132,7 +1104,7 @@ rails_set_decoder(VALUE self) {
1132
1104
  if (rb_const_defined_at(json, rb_intern("ParserError"))) {
1133
1105
  oj_json_parser_error_class = rb_const_get(json, rb_intern("ParserError"));
1134
1106
  } else {
1135
- oj_json_parser_error_class = rb_define_class_under(json, "ParserError", json_error);
1107
+ oj_json_parser_error_class = rb_define_class_under(json, "ParserError", json_error);
1136
1108
  }
1137
1109
  // rb_undef_method doesn't work for modules or maybe sometimes
1138
1110
  // doesn't. Anyway setting verbose should hide the warning.
@@ -1168,13 +1140,15 @@ oj_optimize_rails(VALUE self) {
1168
1140
  *
1169
1141
  * The Oj ActiveSupport compliant encoder.
1170
1142
  */
1171
- void
1172
- oj_mimic_rails_init() {
1173
- VALUE rails = rb_define_module_under(Oj, "Rails");
1143
+ void oj_mimic_rails_init(void) {
1144
+ VALUE rails = rb_define_module_under(Oj, "Rails");
1174
1145
 
1175
1146
  rb_define_module_function(rails, "encode", rails_encode, -1);
1176
1147
 
1177
1148
  encoder_class = rb_define_class_under(rails, "Encoder", rb_cObject);
1149
+ rb_gc_register_address(&encoder_class);
1150
+ rb_undef_alloc_func(encoder_class);
1151
+
1178
1152
  rb_define_module_function(encoder_class, "new", encoder_new, -1);
1179
1153
  rb_define_module_function(rails, "optimize", rails_optimize, -1);
1180
1154
  rb_define_module_function(rails, "deoptimize", rails_deoptimize, -1);
@@ -1190,336 +1164,312 @@ oj_mimic_rails_init() {
1190
1164
  rb_define_method(encoder_class, "optimized?", encoder_optimized, 1);
1191
1165
  }
1192
1166
 
1193
- static void
1194
- dump_to_hash(VALUE obj, int depth, Out out) {
1167
+ static void dump_to_hash(VALUE obj, int depth, Out out) {
1195
1168
  dump_rails_val(rb_funcall(obj, oj_to_hash_id, 0), depth, out, true);
1196
1169
  }
1197
1170
 
1198
- static void
1199
- dump_float(VALUE obj, int depth, Out out, bool as_ok) {
1200
- char buf[64];
1201
- char *b;
1202
- double d = rb_num2dbl(obj);
1203
- int cnt = 0;
1171
+ static void dump_float(VALUE obj, int depth, Out out, bool as_ok) {
1172
+ char buf[64];
1173
+ char *b;
1174
+ double d = rb_num2dbl(obj);
1175
+ int cnt = 0;
1204
1176
 
1205
1177
  if (0.0 == d) {
1206
- b = buf;
1207
- *b++ = '0';
1208
- *b++ = '.';
1209
- *b++ = '0';
1210
- *b++ = '\0';
1211
- cnt = 3;
1178
+ b = buf;
1179
+ *b++ = '0';
1180
+ *b++ = '.';
1181
+ *b++ = '0';
1182
+ *b++ = '\0';
1183
+ cnt = 3;
1212
1184
  } else {
1213
- if (isnan(d) || OJ_INFINITY == d || -OJ_INFINITY == d) {
1214
- strcpy(buf, "null");
1215
- cnt = 4;
1216
- } else if (d == (double)(long long int)d) {
1217
- cnt = snprintf(buf, sizeof(buf), "%.1f", d);
1218
- } else if (oj_rails_float_opt) {
1219
- cnt = oj_dump_float_printf(buf, sizeof(buf), obj, d, "%0.16g");
1220
- } else {
1221
- volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
1222
-
1223
- strcpy(buf, rb_string_value_ptr((VALUE*)&rstr));
1224
- cnt = (int)RSTRING_LEN(rstr);
1225
- }
1185
+ if (isnan(d) || OJ_INFINITY == d || -OJ_INFINITY == d) {
1186
+ strcpy(buf, "null");
1187
+ cnt = 4;
1188
+ } else if (d == (double)(long long int)d) {
1189
+ cnt = snprintf(buf, sizeof(buf), "%.1f", d);
1190
+ } else if (oj_rails_float_opt) {
1191
+ cnt = oj_dump_float_printf(buf, sizeof(buf), obj, d, "%0.16g");
1192
+ } else {
1193
+ volatile VALUE rstr = oj_safe_string_convert(obj);
1194
+
1195
+ strcpy(buf, RSTRING_PTR(rstr));
1196
+ cnt = (int)RSTRING_LEN(rstr);
1197
+ }
1226
1198
  }
1227
1199
  assure_size(out, cnt);
1228
1200
  for (b = buf; '\0' != *b; b++) {
1229
- *out->cur++ = *b;
1201
+ *out->cur++ = *b;
1230
1202
  }
1231
1203
  *out->cur = '\0';
1232
1204
  }
1233
1205
 
1234
- static void
1235
- dump_array(VALUE a, int depth, Out out, bool as_ok) {
1236
- size_t size;
1237
- int i, cnt;
1238
- int d2 = depth + 1;
1206
+ static void dump_array(VALUE a, int depth, Out out, bool as_ok) {
1207
+ size_t size;
1208
+ int i, cnt;
1209
+ int d2 = depth + 1;
1239
1210
 
1240
1211
  if (Yes == out->opts->circular) {
1241
- if (0 > oj_check_circular(a, out)) {
1242
- oj_dump_nil(Qnil, 0, out, false);
1243
- return;
1244
- }
1212
+ if (0 > oj_check_circular(a, out)) {
1213
+ oj_dump_nil(Qnil, 0, out, false);
1214
+ return;
1215
+ }
1245
1216
  }
1246
- //if (!oj_rails_array_opt && as_ok && 0 < out->argc && rb_respond_to(a, oj_as_json_id)) {
1217
+ // if (!oj_rails_array_opt && as_ok && 0 < out->argc && rb_respond_to(a, oj_as_json_id)) {
1247
1218
  if (as_ok && 0 < out->argc && rb_respond_to(a, oj_as_json_id)) {
1248
- dump_as_json(a, depth, out, false);
1249
- return;
1219
+ dump_as_json(a, depth, out, false);
1220
+ return;
1250
1221
  }
1251
- cnt = (int)RARRAY_LEN(a);
1222
+ cnt = (int)RARRAY_LEN(a);
1252
1223
  *out->cur++ = '[';
1253
- size = 2;
1224
+ size = 2;
1254
1225
  assure_size(out, size);
1255
1226
  if (0 == cnt) {
1256
- *out->cur++ = ']';
1227
+ *out->cur++ = ']';
1257
1228
  } else {
1258
- if (out->opts->dump_opts.use) {
1259
- size = d2 * out->opts->dump_opts.indent_size + out->opts->dump_opts.array_size + 1;
1260
- } else {
1261
- size = d2 * out->indent + 2;
1262
- }
1263
- cnt--;
1264
- for (i = 0; i <= cnt; i++) {
1265
- assure_size(out, size);
1266
- if (out->opts->dump_opts.use) {
1267
- if (0 < out->opts->dump_opts.array_size) {
1268
- strcpy(out->cur, out->opts->dump_opts.array_nl);
1269
- out->cur += out->opts->dump_opts.array_size;
1270
- }
1271
- if (0 < out->opts->dump_opts.indent_size) {
1272
- int i;
1273
- for (i = d2; 0 < i; i--) {
1274
- strcpy(out->cur, out->opts->dump_opts.indent_str);
1275
- out->cur += out->opts->dump_opts.indent_size;
1276
- }
1277
- }
1278
- } else {
1279
- fill_indent(out, d2);
1280
- }
1281
- dump_rails_val(rb_ary_entry(a, i), d2, out, true);
1282
- if (i < cnt) {
1283
- *out->cur++ = ',';
1284
- }
1285
- }
1286
- size = depth * out->indent + 1;
1287
- assure_size(out, size);
1288
- if (out->opts->dump_opts.use) {
1289
- if (0 < out->opts->dump_opts.array_size) {
1290
- strcpy(out->cur, out->opts->dump_opts.array_nl);
1291
- out->cur += out->opts->dump_opts.array_size;
1292
- }
1293
- if (0 < out->opts->dump_opts.indent_size) {
1294
- int i;
1295
-
1296
- for (i = depth; 0 < i; i--) {
1297
- strcpy(out->cur, out->opts->dump_opts.indent_str);
1298
- out->cur += out->opts->dump_opts.indent_size;
1299
- }
1300
- }
1301
- } else {
1302
- fill_indent(out, depth);
1303
- }
1304
- *out->cur++ = ']';
1229
+ if (out->opts->dump_opts.use) {
1230
+ size = d2 * out->opts->dump_opts.indent_size + out->opts->dump_opts.array_size + 1;
1231
+ } else {
1232
+ size = d2 * out->indent + 2;
1233
+ }
1234
+ assure_size(out, size * cnt);
1235
+ cnt--;
1236
+ for (i = 0; i <= cnt; i++) {
1237
+ if (out->opts->dump_opts.use) {
1238
+ if (0 < out->opts->dump_opts.array_size) {
1239
+ APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
1240
+ }
1241
+ if (0 < out->opts->dump_opts.indent_size) {
1242
+ int i;
1243
+ for (i = d2; 0 < i; i--) {
1244
+ APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
1245
+ }
1246
+ }
1247
+ } else {
1248
+ fill_indent(out, d2);
1249
+ }
1250
+ dump_rails_val(RARRAY_AREF(a, i), d2, out, true);
1251
+ if (i < cnt) {
1252
+ *out->cur++ = ',';
1253
+ }
1254
+ }
1255
+ size = depth * out->indent + 1;
1256
+ assure_size(out, size);
1257
+ if (out->opts->dump_opts.use) {
1258
+ if (0 < out->opts->dump_opts.array_size) {
1259
+ APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
1260
+ }
1261
+ if (0 < out->opts->dump_opts.indent_size) {
1262
+ int i;
1263
+
1264
+ for (i = depth; 0 < i; i--) {
1265
+ APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
1266
+ }
1267
+ }
1268
+ } else {
1269
+ fill_indent(out, depth);
1270
+ }
1271
+ *out->cur++ = ']';
1305
1272
  }
1306
1273
  *out->cur = '\0';
1307
1274
  }
1308
1275
 
1309
- static int
1310
- hash_cb(VALUE key, VALUE value, VALUE ov) {
1311
- Out out = (Out)ov;
1312
- int depth = out->depth;
1313
- long size;
1314
- int rtype = rb_type(key);
1276
+ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
1277
+ Out out = (Out)ov;
1278
+ int depth = out->depth;
1279
+ long size;
1280
+ int rtype = rb_type(key);
1315
1281
 
1316
1282
  if (out->omit_nil && Qnil == value) {
1317
- return ST_CONTINUE;
1283
+ return ST_CONTINUE;
1318
1284
  }
1319
1285
  if (rtype != T_STRING && rtype != T_SYMBOL) {
1320
- key = rb_funcall(key, oj_to_s_id, 0);
1321
- rtype = rb_type(key);
1286
+ key = oj_safe_string_convert(key);
1287
+ rtype = rb_type(key);
1322
1288
  }
1323
1289
  if (!out->opts->dump_opts.use) {
1324
- size = depth * out->indent + 1;
1325
- assure_size(out, size);
1326
- fill_indent(out, depth);
1327
- if (rtype == T_STRING) {
1328
- oj_dump_str(key, 0, out, false);
1329
- } else {
1330
- oj_dump_sym(key, 0, out, false);
1331
- }
1332
- *out->cur++ = ':';
1290
+ size = depth * out->indent + 1;
1291
+ assure_size(out, size);
1292
+ fill_indent(out, depth);
1293
+ if (rtype == T_STRING) {
1294
+ oj_dump_str(key, 0, out, false);
1295
+ } else {
1296
+ oj_dump_sym(key, 0, out, false);
1297
+ }
1298
+ *out->cur++ = ':';
1333
1299
  } else {
1334
- size = depth * out->opts->dump_opts.indent_size + out->opts->dump_opts.hash_size + 1;
1335
- assure_size(out, size);
1336
- if (0 < out->opts->dump_opts.hash_size) {
1337
- strcpy(out->cur, out->opts->dump_opts.hash_nl);
1338
- out->cur += out->opts->dump_opts.hash_size;
1339
- }
1340
- if (0 < out->opts->dump_opts.indent_size) {
1341
- int i;
1342
- for (i = depth; 0 < i; i--) {
1343
- strcpy(out->cur, out->opts->dump_opts.indent_str);
1344
- out->cur += out->opts->dump_opts.indent_size;
1345
- }
1346
- }
1347
- if (rtype == T_STRING) {
1348
- oj_dump_str(key, 0, out, false);
1349
- } else {
1350
- oj_dump_sym(key, 0, out, false);
1351
- }
1352
- size = out->opts->dump_opts.before_size + out->opts->dump_opts.after_size + 2;
1353
- assure_size(out, size);
1354
- if (0 < out->opts->dump_opts.before_size) {
1355
- strcpy(out->cur, out->opts->dump_opts.before_sep);
1356
- out->cur += out->opts->dump_opts.before_size;
1357
- }
1358
- *out->cur++ = ':';
1359
- if (0 < out->opts->dump_opts.after_size) {
1360
- strcpy(out->cur, out->opts->dump_opts.after_sep);
1361
- out->cur += out->opts->dump_opts.after_size;
1362
- }
1300
+ size = depth * out->opts->dump_opts.indent_size + out->opts->dump_opts.hash_size + 1;
1301
+ assure_size(out, size);
1302
+ if (0 < out->opts->dump_opts.hash_size) {
1303
+ APPEND_CHARS(out->cur, out->opts->dump_opts.hash_nl, out->opts->dump_opts.hash_size);
1304
+ }
1305
+ if (0 < out->opts->dump_opts.indent_size) {
1306
+ int i;
1307
+ for (i = depth; 0 < i; i--) {
1308
+ APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
1309
+ }
1310
+ }
1311
+ if (rtype == T_STRING) {
1312
+ oj_dump_str(key, 0, out, false);
1313
+ } else {
1314
+ oj_dump_sym(key, 0, out, false);
1315
+ }
1316
+ size = out->opts->dump_opts.before_size + out->opts->dump_opts.after_size + 2;
1317
+ assure_size(out, size);
1318
+ if (0 < out->opts->dump_opts.before_size) {
1319
+ APPEND_CHARS(out->cur, out->opts->dump_opts.before_sep, out->opts->dump_opts.before_size);
1320
+ }
1321
+ *out->cur++ = ':';
1322
+ if (0 < out->opts->dump_opts.after_size) {
1323
+ APPEND_CHARS(out->cur, out->opts->dump_opts.after_sep, out->opts->dump_opts.after_size);
1324
+ }
1363
1325
  }
1364
1326
  dump_rails_val(value, depth, out, true);
1365
- out->depth = depth;
1327
+ out->depth = depth;
1366
1328
  *out->cur++ = ',';
1367
1329
 
1368
1330
  return ST_CONTINUE;
1369
1331
  }
1370
1332
 
1371
- static void
1372
- dump_hash(VALUE obj, int depth, Out out, bool as_ok) {
1373
- int cnt;
1374
- size_t size;
1333
+ static void dump_hash(VALUE obj, int depth, Out out, bool as_ok) {
1334
+ int cnt;
1335
+ size_t size;
1375
1336
 
1376
1337
  if (Yes == out->opts->circular) {
1377
- if (0 > oj_check_circular(obj, out)) {
1378
- oj_dump_nil(Qnil, 0, out, false);
1379
- return;
1380
- }
1338
+ if (0 > oj_check_circular(obj, out)) {
1339
+ oj_dump_nil(Qnil, 0, out, false);
1340
+ return;
1341
+ }
1381
1342
  }
1382
1343
  if ((!oj_rails_hash_opt || 0 < out->argc) && as_ok && rb_respond_to(obj, oj_as_json_id)) {
1383
- dump_as_json(obj, depth, out, false);
1384
- return;
1344
+ dump_as_json(obj, depth, out, false);
1345
+ return;
1385
1346
  }
1386
- cnt = (int)RHASH_SIZE(obj);
1347
+ cnt = (int)RHASH_SIZE(obj);
1387
1348
  size = depth * out->indent + 2;
1388
1349
  assure_size(out, 2);
1389
1350
  *out->cur++ = '{';
1390
1351
  if (0 == cnt) {
1391
- *out->cur++ = '}';
1352
+ *out->cur++ = '}';
1392
1353
  } else {
1393
- out->depth = depth + 1;
1394
- rb_hash_foreach(obj, hash_cb, (VALUE)out);
1395
- if (',' == *(out->cur - 1)) {
1396
- out->cur--; // backup to overwrite last comma
1397
- }
1398
- if (!out->opts->dump_opts.use) {
1399
- assure_size(out, size);
1400
- fill_indent(out, depth);
1401
- } else {
1402
- size = depth * out->opts->dump_opts.indent_size + out->opts->dump_opts.hash_size + 1;
1403
- assure_size(out, size);
1404
- if (0 < out->opts->dump_opts.hash_size) {
1405
- strcpy(out->cur, out->opts->dump_opts.hash_nl);
1406
- out->cur += out->opts->dump_opts.hash_size;
1407
- }
1408
- if (0 < out->opts->dump_opts.indent_size) {
1409
- int i;
1410
-
1411
- for (i = depth; 0 < i; i--) {
1412
- strcpy(out->cur, out->opts->dump_opts.indent_str);
1413
- out->cur += out->opts->dump_opts.indent_size;
1414
- }
1415
- }
1416
- }
1417
- *out->cur++ = '}';
1354
+ out->depth = depth + 1;
1355
+ rb_hash_foreach(obj, hash_cb, (VALUE)out);
1356
+ if (',' == *(out->cur - 1)) {
1357
+ out->cur--; // backup to overwrite last comma
1358
+ }
1359
+ if (!out->opts->dump_opts.use) {
1360
+ assure_size(out, size);
1361
+ fill_indent(out, depth);
1362
+ } else {
1363
+ size = depth * out->opts->dump_opts.indent_size + out->opts->dump_opts.hash_size + 1;
1364
+ assure_size(out, size);
1365
+ if (0 < out->opts->dump_opts.hash_size) {
1366
+ APPEND_CHARS(out->cur, out->opts->dump_opts.hash_nl, out->opts->dump_opts.hash_size);
1367
+ }
1368
+ if (0 < out->opts->dump_opts.indent_size) {
1369
+ int i;
1370
+
1371
+ for (i = depth; 0 < i; i--) {
1372
+ APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
1373
+ }
1374
+ }
1375
+ }
1376
+ *out->cur++ = '}';
1418
1377
  }
1419
1378
  *out->cur = '\0';
1420
1379
  }
1421
1380
 
1422
- static void
1423
- dump_obj(VALUE obj, int depth, Out out, bool as_ok) {
1424
- VALUE clas;
1381
+ static void dump_obj(VALUE obj, int depth, Out out, bool as_ok) {
1382
+ VALUE clas;
1425
1383
 
1426
1384
  if (oj_code_dump(oj_compat_codes, obj, depth, out)) {
1427
- out->argc = 0;
1428
- return;
1385
+ out->argc = 0;
1386
+ return;
1429
1387
  }
1430
1388
  clas = rb_obj_class(obj);
1431
1389
  if (as_ok) {
1432
- ROpt ro;
1433
-
1434
- if (NULL != (ro = oj_rails_get_opt(out->ropts, clas)) && ro->on) {
1435
- ro->dump(obj, depth, out, as_ok);
1436
- } else if (Yes == out->opts->raw_json && rb_respond_to(obj, oj_raw_json_id)) {
1437
- oj_dump_raw_json(obj, depth, out);
1438
- } else if (rb_respond_to(obj, oj_as_json_id)) {
1439
- dump_as_json(obj, depth, out, true);
1440
- } else if (rb_respond_to(obj, oj_to_hash_id)) {
1441
- dump_to_hash(obj, depth, out);
1442
- } else if (oj_bigdecimal_class == clas) {
1443
- dump_bigdecimal(obj, depth, out, false);
1444
- } else {
1445
- oj_dump_obj_to_s(obj, out);
1446
- }
1390
+ ROpt ro;
1391
+
1392
+ if (NULL != (ro = oj_rails_get_opt(out->ropts, clas)) && ro->on) {
1393
+ ro->dump(obj, depth, out, as_ok);
1394
+ } else if (Yes == out->opts->raw_json && rb_respond_to(obj, oj_raw_json_id)) {
1395
+ oj_dump_raw_json(obj, depth, out);
1396
+ } else if (rb_respond_to(obj, oj_as_json_id)) {
1397
+ dump_as_json(obj, depth, out, true);
1398
+ } else if (rb_respond_to(obj, oj_to_hash_id)) {
1399
+ dump_to_hash(obj, depth, out);
1400
+ } else if (oj_bigdecimal_class == clas) {
1401
+ dump_bigdecimal(obj, depth, out, false);
1402
+ } else {
1403
+ oj_dump_obj_to_s(obj, out);
1404
+ }
1447
1405
  } else if (Yes == out->opts->raw_json && rb_respond_to(obj, oj_raw_json_id)) {
1448
- oj_dump_raw_json(obj, depth, out);
1406
+ oj_dump_raw_json(obj, depth, out);
1449
1407
  } else if (rb_respond_to(obj, oj_to_hash_id)) {
1450
- // Always attempt to_hash.
1451
- dump_to_hash(obj, depth, out);
1408
+ // Always attempt to_hash.
1409
+ dump_to_hash(obj, depth, out);
1452
1410
  } else if (oj_bigdecimal_class == clas) {
1453
- dump_bigdecimal(obj, depth, out, false);
1411
+ dump_bigdecimal(obj, depth, out, false);
1454
1412
  } else {
1455
- oj_dump_obj_to_s(obj, out);
1413
+ oj_dump_obj_to_s(obj, out);
1456
1414
  }
1457
1415
  }
1458
1416
 
1459
- static DumpFunc rails_funcs[] = {
1460
- NULL, // RUBY_T_NONE = 0x00,
1461
- dump_obj, // RUBY_T_OBJECT = 0x01,
1462
- oj_dump_class, // RUBY_T_CLASS = 0x02,
1463
- oj_dump_class, // RUBY_T_MODULE = 0x03,
1464
- dump_float, // RUBY_T_FLOAT = 0x04,
1465
- oj_dump_str, // RUBY_T_STRING = 0x05,
1466
- dump_regexp, // RUBY_T_REGEXP = 0x06,
1467
- //dump_as_string, // RUBY_T_REGEXP = 0x06,
1468
- dump_array, // RUBY_T_ARRAY = 0x07,
1469
- dump_hash, // RUBY_T_HASH = 0x08,
1470
- dump_obj, // RUBY_T_STRUCT = 0x09,
1471
- oj_dump_bignum, // RUBY_T_BIGNUM = 0x0a,
1472
- dump_as_string, // RUBY_T_FILE = 0x0b,
1473
- dump_obj, // RUBY_T_DATA = 0x0c,
1474
- NULL, // RUBY_T_MATCH = 0x0d,
1417
+ static DumpFunc rails_funcs[] = {
1418
+ NULL, // RUBY_T_NONE = 0x00,
1419
+ dump_obj, // RUBY_T_OBJECT = 0x01,
1420
+ oj_dump_class, // RUBY_T_CLASS = 0x02,
1421
+ oj_dump_class, // RUBY_T_MODULE = 0x03,
1422
+ dump_float, // RUBY_T_FLOAT = 0x04,
1423
+ oj_dump_str, // RUBY_T_STRING = 0x05,
1424
+ dump_regexp, // RUBY_T_REGEXP = 0x06,
1425
+ // dump_as_string, // RUBY_T_REGEXP = 0x06,
1426
+ dump_array, // RUBY_T_ARRAY = 0x07,
1427
+ dump_hash, // RUBY_T_HASH = 0x08,
1428
+ dump_obj, // RUBY_T_STRUCT = 0x09,
1429
+ oj_dump_bignum, // RUBY_T_BIGNUM = 0x0a,
1430
+ dump_as_string, // RUBY_T_FILE = 0x0b,
1431
+ dump_obj, // RUBY_T_DATA = 0x0c,
1432
+ NULL, // RUBY_T_MATCH = 0x0d,
1475
1433
  // Rails raises a stack error on Complex and Rational. It also corrupts
1476
1434
  // something which causes a segfault on the next call. Oj will not mimic
1477
1435
  // that behavior.
1478
- dump_as_string, // RUBY_T_COMPLEX = 0x0e,
1479
- dump_as_string, // RUBY_T_RATIONAL = 0x0f,
1480
- NULL, // 0x10
1481
- oj_dump_nil, // RUBY_T_NIL = 0x11,
1482
- oj_dump_true, // RUBY_T_TRUE = 0x12,
1483
- oj_dump_false, // RUBY_T_FALSE = 0x13,
1484
- oj_dump_sym, // RUBY_T_SYMBOL = 0x14,
1485
- oj_dump_fixnum, // RUBY_T_FIXNUM = 0x15,
1436
+ dump_as_string, // RUBY_T_COMPLEX = 0x0e,
1437
+ dump_as_string, // RUBY_T_RATIONAL = 0x0f,
1438
+ NULL, // 0x10
1439
+ oj_dump_nil, // RUBY_T_NIL = 0x11,
1440
+ oj_dump_true, // RUBY_T_TRUE = 0x12,
1441
+ oj_dump_false, // RUBY_T_FALSE = 0x13,
1442
+ oj_dump_sym, // RUBY_T_SYMBOL = 0x14,
1443
+ oj_dump_fixnum, // RUBY_T_FIXNUM = 0x15,
1486
1444
  };
1487
1445
 
1488
- static void
1489
- dump_rails_val(VALUE obj, int depth, Out out, bool as_ok) {
1490
- int type = rb_type(obj);
1446
+ static void dump_rails_val(VALUE obj, int depth, Out out, bool as_ok) {
1447
+ int type = rb_type(obj);
1491
1448
 
1492
- if (Yes == out->opts->trace) {
1493
- oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceIn);
1494
- }
1449
+ TRACE(out->opts->trace, "dump", obj, depth, TraceIn);
1495
1450
  if (MAX_DEPTH < depth) {
1496
- rb_raise(rb_eNoMemError, "Too deeply nested.\n");
1451
+ rb_raise(rb_eNoMemError, "Too deeply nested.\n");
1497
1452
  }
1498
1453
  if (0 < type && type <= RUBY_T_FIXNUM) {
1499
- DumpFunc f = rails_funcs[type];
1454
+ DumpFunc f = rails_funcs[type];
1500
1455
 
1501
- if (NULL != f) {
1502
- f(obj, depth, out, as_ok);
1503
- if (Yes == out->opts->trace) {
1504
- oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceOut);
1505
- }
1506
- return;
1507
- }
1456
+ if (NULL != f) {
1457
+ f(obj, depth, out, as_ok);
1458
+ TRACE(out->opts->trace, "dump", obj, depth, TraceOut);
1459
+ return;
1460
+ }
1508
1461
  }
1509
1462
  oj_dump_nil(Qnil, depth, out, false);
1510
- if (Yes == out->opts->trace) {
1511
- oj_trace("dump", Qnil, __FILE__, __LINE__, depth, TraceOut);
1512
- }
1463
+ TRACE(out->opts->trace, "dump", Qnil, depth, TraceOut);
1513
1464
  }
1514
1465
 
1515
- void
1516
- oj_dump_rails_val(VALUE obj, int depth, Out out) {
1466
+ void oj_dump_rails_val(VALUE obj, int depth, Out out) {
1517
1467
  out->opts->str_rx.head = NULL;
1518
1468
  out->opts->str_rx.tail = NULL;
1519
1469
  if (escape_html) {
1520
- out->opts->escape_mode = RailsXEsc;
1470
+ out->opts->escape_mode = RailsXEsc;
1521
1471
  } else {
1522
- out->opts->escape_mode = RailsEsc;
1472
+ out->opts->escape_mode = RailsEsc;
1523
1473
  }
1524
1474
  dump_rails_val(obj, depth, out, true);
1525
1475
  }