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/oj.c CHANGED
@@ -1,371 +1,495 @@
1
1
  // Copyright (c) 2012 Peter Ohler. All rights reserved.
2
+ // Licensed under the MIT License. See LICENSE file in the project root for license details.
3
+
4
+ #include "oj.h"
2
5
 
3
- #include <stdlib.h>
4
6
  #include <errno.h>
7
+ #include <fcntl.h>
5
8
  #include <stdio.h>
9
+ #include <stdlib.h>
6
10
  #include <string.h>
7
11
  #include <sys/types.h>
8
12
  #include <unistd.h>
9
- #include <fcntl.h>
10
13
 
11
- #include "oj.h"
12
- #include "parse.h"
13
- #include "hash.h"
14
- #include "odd.h"
15
14
  #include "dump.h"
16
- #include "rails.h"
17
15
  #include "encode.h"
16
+ #include "intern.h"
17
+ #include "mem.h"
18
+ #include "odd.h"
19
+ #include "parse.h"
20
+ #include "rails.h"
18
21
 
19
22
  typedef struct _yesNoOpt {
20
- VALUE sym;
21
- char *attr;
23
+ VALUE sym;
24
+ char *attr;
22
25
  } *YesNoOpt;
23
26
 
24
27
  void Init_oj();
25
28
 
26
- VALUE Oj = Qnil;
27
-
28
- ID oj_add_value_id;
29
- ID oj_array_append_id;
30
- ID oj_array_end_id;
31
- ID oj_array_start_id;
32
- ID oj_as_json_id;
33
- ID oj_begin_id;
34
- ID oj_bigdecimal_id;
35
- ID oj_end_id;
36
- ID oj_exclude_end_id;
37
- ID oj_error_id;
38
- ID oj_file_id;
39
- ID oj_fileno_id;
40
- ID oj_ftype_id;
41
- ID oj_has_key_id;
42
- ID oj_hash_end_id;
43
- ID oj_hash_key_id;
44
- ID oj_hash_set_id;
45
- ID oj_hash_start_id;
46
- ID oj_iconv_id;
47
- ID oj_instance_variables_id;
48
- ID oj_json_create_id;
49
- ID oj_length_id;
50
- ID oj_new_id;
51
- ID oj_parse_id;
52
- ID oj_pos_id;
53
- ID oj_raw_json_id;
54
- ID oj_read_id;
55
- ID oj_readpartial_id;
56
- ID oj_replace_id;
57
- ID oj_stat_id;
58
- ID oj_string_id;
59
- ID oj_to_h_id;
60
- ID oj_to_hash_id;
61
- ID oj_to_json_id;
62
- ID oj_to_s_id;
63
- ID oj_to_sym_id;
64
- ID oj_to_time_id;
65
- ID oj_tv_nsec_id;
66
- ID oj_tv_sec_id;
67
- ID oj_tv_usec_id;
68
- ID oj_utc_id;
69
- ID oj_utc_offset_id;
70
- ID oj_utcq_id;
71
- ID oj_write_id;
72
-
73
-
74
- VALUE oj_bag_class;
75
- VALUE oj_bigdecimal_class;
76
- VALUE oj_cstack_class;
77
- VALUE oj_date_class;
78
- VALUE oj_datetime_class;
79
- VALUE oj_enumerable_class;
80
- VALUE oj_parse_error_class;
81
- VALUE oj_stream_writer_class;
82
- VALUE oj_string_writer_class;
83
- VALUE oj_stringio_class;
84
- VALUE oj_struct_class;
85
-
86
- VALUE oj_slash_string;
87
-
88
- VALUE oj_allow_nan_sym;
89
- VALUE oj_array_class_sym;
90
- VALUE oj_create_additions_sym;
91
- VALUE oj_decimal_class_sym;
92
- VALUE oj_hash_class_sym;
93
- VALUE oj_indent_sym;
94
- VALUE oj_object_class_sym;
95
- VALUE oj_quirks_mode_sym;
96
- VALUE oj_safe_sym;
97
- VALUE oj_trace_sym;
98
-
99
- static VALUE allow_blank_sym;
100
- static VALUE allow_gc_sym;
101
- static VALUE allow_invalid_unicode_sym;
102
- static VALUE ascii_sym;
103
- static VALUE auto_define_sym;
104
- static VALUE auto_sym;
105
- static VALUE bigdecimal_as_decimal_sym;
106
- static VALUE bigdecimal_load_sym;
107
- static VALUE bigdecimal_sym;
108
- static VALUE circular_sym;
109
- static VALUE class_cache_sym;
110
- static VALUE compat_bigdecimal_sym;
111
- static VALUE compat_sym;
112
- static VALUE create_id_sym;
113
- static VALUE custom_sym;
114
- static VALUE empty_string_sym;
115
- static VALUE escape_mode_sym;
116
- static VALUE integer_range_sym;
117
- static VALUE fast_sym;
118
- static VALUE float_prec_sym;
119
- static VALUE float_sym;
120
- static VALUE huge_sym;
121
- static VALUE ignore_sym;
122
- static VALUE ignore_under_sym;
123
- static VALUE json_sym;
124
- static VALUE match_string_sym;
125
- static VALUE mode_sym;
126
- static VALUE nan_sym;
127
- static VALUE newline_sym;
128
- static VALUE nilnil_sym;
129
- static VALUE null_sym;
130
- static VALUE object_sym;
131
- static VALUE omit_nil_sym;
132
- static VALUE rails_sym;
133
- static VALUE raise_sym;
134
- static VALUE ruby_sym;
135
- static VALUE sec_prec_sym;
136
- static VALUE strict_sym;
137
- static VALUE symbol_keys_sym;
138
- static VALUE time_format_sym;
139
- static VALUE unicode_xss_sym;
140
- static VALUE unix_sym;
141
- static VALUE unix_zone_sym;
142
- static VALUE use_as_json_sym;
143
- static VALUE use_raw_json_sym;
144
- static VALUE use_to_hash_sym;
145
- static VALUE use_to_json_sym;
146
- static VALUE wab_sym;
147
- static VALUE word_sym;
148
- static VALUE xmlschema_sym;
149
- static VALUE xss_safe_sym;
150
-
151
- rb_encoding *oj_utf8_encoding = 0;
29
+ VALUE Oj = Qnil;
30
+
31
+ ID oj_add_value_id;
32
+ ID oj_array_append_id;
33
+ ID oj_array_end_id;
34
+ ID oj_array_start_id;
35
+ ID oj_as_json_id;
36
+ ID oj_begin_id;
37
+ ID oj_bigdecimal_id;
38
+ ID oj_end_id;
39
+ ID oj_eofq_id;
40
+ ID oj_exclude_end_id;
41
+ ID oj_error_id;
42
+ ID oj_file_id;
43
+ ID oj_fileno_id;
44
+ ID oj_ftype_id;
45
+ ID oj_hash_end_id;
46
+ ID oj_hash_key_id;
47
+ ID oj_hash_set_id;
48
+ ID oj_hash_start_id;
49
+ ID oj_iconv_id;
50
+ ID oj_json_create_id;
51
+ ID oj_length_id;
52
+ ID oj_new_id;
53
+ ID oj_parse_id;
54
+ ID oj_plus_id;
55
+ ID oj_pos_id;
56
+ ID oj_raw_json_id;
57
+ ID oj_read_id;
58
+ ID oj_readpartial_id;
59
+ ID oj_replace_id;
60
+ ID oj_stat_id;
61
+ ID oj_string_id;
62
+ ID oj_to_h_id;
63
+ ID oj_to_hash_id;
64
+ ID oj_to_json_id;
65
+ ID oj_to_s_id;
66
+ ID oj_to_sym_id;
67
+ ID oj_to_time_id;
68
+ ID oj_tv_nsec_id;
69
+ ID oj_tv_sec_id;
70
+ ID oj_tv_usec_id;
71
+ ID oj_utc_id;
72
+ ID oj_utc_offset_id;
73
+ ID oj_utcq_id;
74
+ ID oj_write_id;
75
+
76
+ VALUE oj_bag_class;
77
+ VALUE oj_bigdecimal_class;
78
+ VALUE oj_cstack_class;
79
+ VALUE oj_date_class;
80
+ VALUE oj_datetime_class;
81
+ VALUE oj_enumerable_class;
82
+ VALUE oj_parse_error_class;
83
+ VALUE oj_stream_writer_class;
84
+ VALUE oj_string_writer_class;
85
+ VALUE oj_stringio_class;
86
+ VALUE oj_struct_class;
87
+
88
+ VALUE oj_slash_string;
89
+
90
+ VALUE oj_allow_nan_sym;
91
+ VALUE oj_array_class_sym;
92
+ VALUE oj_create_additions_sym;
93
+ VALUE oj_decimal_class_sym;
94
+ VALUE oj_hash_class_sym;
95
+ VALUE oj_indent_sym;
96
+ VALUE oj_object_class_sym;
97
+ VALUE oj_quirks_mode_sym;
98
+ VALUE oj_safe_sym;
99
+ VALUE oj_symbolize_names_sym;
100
+ VALUE oj_trace_sym;
101
+
102
+ static VALUE allow_blank_sym;
103
+ static VALUE allow_gc_sym;
104
+ static VALUE allow_invalid_unicode_sym;
105
+ static VALUE ascii_sym;
106
+ static VALUE auto_define_sym;
107
+ static VALUE auto_sym;
108
+ static VALUE bigdecimal_as_decimal_sym;
109
+ static VALUE bigdecimal_load_sym;
110
+ static VALUE bigdecimal_sym;
111
+ static VALUE cache_keys_sym;
112
+ static VALUE cache_str_sym;
113
+ static VALUE cache_string_sym;
114
+ static VALUE circular_sym;
115
+ static VALUE class_cache_sym;
116
+ static VALUE compat_bigdecimal_sym;
117
+ static VALUE compat_sym;
118
+ static VALUE create_id_sym;
119
+ static VALUE custom_sym;
120
+ static VALUE empty_string_sym;
121
+ static VALUE escape_mode_sym;
122
+ static VALUE integer_range_sym;
123
+ static VALUE fast_sym;
124
+ static VALUE float_prec_sym;
125
+ static VALUE float_format_sym;
126
+ static VALUE float_sym;
127
+ static VALUE huge_sym;
128
+ static VALUE ignore_sym;
129
+ static VALUE ignore_under_sym;
130
+ static VALUE json_sym;
131
+ static VALUE match_string_sym;
132
+ static VALUE mode_sym;
133
+ static VALUE nan_sym;
134
+ static VALUE newline_sym;
135
+ static VALUE nilnil_sym;
136
+ static VALUE null_sym;
137
+ static VALUE object_sym;
138
+ static VALUE omit_null_byte_sym;
139
+ static VALUE omit_nil_sym;
140
+ static VALUE rails_sym;
141
+ static VALUE raise_sym;
142
+ static VALUE ruby_sym;
143
+ static VALUE sec_prec_sym;
144
+ static VALUE slash_sym;
145
+ static VALUE strict_sym;
146
+ static VALUE symbol_keys_sym;
147
+ static VALUE time_format_sym;
148
+ static VALUE unicode_xss_sym;
149
+ static VALUE unix_sym;
150
+ static VALUE unix_zone_sym;
151
+ static VALUE use_as_json_sym;
152
+ static VALUE use_raw_json_sym;
153
+ static VALUE use_to_hash_sym;
154
+ static VALUE use_to_json_sym;
155
+ static VALUE wab_sym;
156
+ static VALUE word_sym;
157
+ static VALUE xmlschema_sym;
158
+ static VALUE xss_safe_sym;
159
+
160
+ rb_encoding *oj_utf8_encoding = 0;
161
+ int oj_utf8_encoding_index = 0;
152
162
 
153
163
  #ifdef HAVE_PTHREAD_MUTEX_INIT
154
- pthread_mutex_t oj_cache_mutex;
164
+ pthread_mutex_t oj_cache_mutex;
155
165
  #else
156
166
  VALUE oj_cache_mutex = Qnil;
157
167
  #endif
158
168
 
159
- const char oj_json_class[] = "json_class";
160
-
161
- struct _options oj_default_options = {
162
- 0, // indent
163
- No, // circular
164
- No, // auto_define
165
- No, // sym_key
166
- JSONEsc, // escape_mode
167
- ObjectMode, // mode
168
- Yes, // class_cache
169
- UnixTime, // time_format
170
- NotSet, // bigdec_as_num
171
- AutoDec, // bigdec_load
172
- false, // compat_bigdec
173
- No, // to_hash
174
- No, // to_json
175
- No, // as_json
176
- No, // raw_json
177
- No, // nilnil
178
- Yes, // empty_string
179
- Yes, // allow_gc
180
- Yes, // quirks_mode
181
- No, // allow_invalid
182
- No, // create_ok
183
- Yes, // allow_nan
184
- No, // trace
185
- No, // safe
186
- false, // sec_prec_set
187
- No, // ignore_under
188
- 0, // int_range_min
189
- 0, // int_range_max
190
- oj_json_class, // create_id
191
- 10, // create_id_len
192
- 9, // sec_prec
193
- 16, // float_prec
194
- "%0.15g", // float_fmt
195
- Qnil, // hash_class
196
- Qnil, // array_class
197
- { // dump_opts
198
- false, //use
199
- "", // indent
200
- "", // before_sep
201
- "", // after_sep
202
- "", // hash_nl
203
- "", // array_nl
204
- 0, // indent_size
205
- 0, // before_size
206
- 0, // after_size
207
- 0, // hash_size
208
- 0, // array_size
209
- AutoNan,// nan_dump
210
- false, // omit_nil
211
- MAX_DEPTH, // max_depth
169
+ extern void oj_parser_init();
170
+
171
+ const char oj_json_class[] = "json_class";
172
+
173
+ struct _options oj_default_options = {
174
+ 0, // indent
175
+ No, // circular
176
+ No, // auto_define
177
+ No, // sym_key
178
+ JSONEsc, // escape_mode
179
+ ObjectMode, // mode
180
+ Yes, // class_cache
181
+ UnixTime, // time_format
182
+ NotSet, // bigdec_as_num
183
+ AutoDec, // bigdec_load
184
+ false, // compat_bigdec
185
+ No, // to_hash
186
+ No, // to_json
187
+ No, // as_json
188
+ No, // raw_json
189
+ No, // nilnil
190
+ Yes, // empty_string
191
+ Yes, // allow_gc
192
+ Yes, // quirks_mode
193
+ No, // allow_invalid
194
+ No, // create_ok
195
+ Yes, // allow_nan
196
+ No, // trace
197
+ No, // safe
198
+ false, // sec_prec_set
199
+ No, // ignore_under
200
+ Yes, // cache_keys
201
+ 0, // cache_str
202
+ 0, // int_range_min
203
+ 0, // int_range_max
204
+ oj_json_class, // create_id
205
+ 10, // create_id_len
206
+ 9, // sec_prec
207
+ 16, // float_prec
208
+ "%0.15g", // float_fmt
209
+ Qnil, // hash_class
210
+ Qnil, // array_class
211
+ {
212
+ // dump_opts
213
+ false, // use
214
+ "", // indent
215
+ "", // before_sep
216
+ "", // after_sep
217
+ "", // hash_nl
218
+ "", // array_nl
219
+ 0, // indent_size
220
+ 0, // before_size
221
+ 0, // after_size
222
+ 0, // hash_size
223
+ 0, // array_size
224
+ AutoNan, // nan_dump
225
+ false, // omit_nil
226
+ false, // omit_null_byte
227
+ MAX_DEPTH, // max_depth
212
228
  },
213
- { // str_rx
214
- NULL, // head
215
- NULL, // tail
216
- { '\0' }, // err
229
+ {
230
+ // str_rx
231
+ NULL, // head
232
+ NULL, // tail
233
+ {'\0'}, // err
217
234
  },
218
- NULL, // ignore
235
+ NULL,
219
236
  };
220
237
 
221
238
  /* Document-method: default_options()
222
239
  * call-seq: default_options()
223
240
  *
224
241
  * Returns the default load and dump options as a Hash. The options are
225
- * - *:indent* [_Fixnum_|_String_|_nil_] number of spaces to indent each element in an JSON document, zero or nil is no newline between JSON elements, negative indicates no newline between top level JSON elements in a stream, a String indicates the string should be used for indentation
226
- * - *:circular* [_Boolean_|_nil_] support circular references while dumping
242
+ * - *:indent* [_Fixnum_|_String_|_nil_] number of spaces to indent each element
243
+ * in an JSON document, zero or nil is no newline between JSON elements,
244
+ * negative indicates no newline between top level JSON elements in a stream,
245
+ * a String indicates the string should be used for indentation
246
+ * - *:circular* [_Boolean_|_nil_] support circular references while dumping as
247
+ * well as shared references
227
248
  * - *:auto_define* [_Boolean_|_nil_] automatically define classes if they do not exist
228
249
  * - *:symbol_keys* [_Boolean_|_nil_] use symbols instead of strings for hash keys
229
- * - *:escape_mode* [_:newline_|_:json_|_:xss_safe_|_:ascii_|_unicode_xss_|_nil_] determines the characters to escape
230
- * - *:class_cache* [_Boolean_|_nil_] cache classes for faster parsing (if dynamically modifying classes or reloading classes then don't use this)
231
- * - *:mode* [_:object_|_:strict_|_:compat_|_:null_|_:custom_|_:rails_|_:wab_] load and dump modes to use for JSON
250
+ * - *:escape_mode* [_:newline_|_:json_|_:slash_|_:xss_safe_|_:ascii_|_:unicode_xss_|_nil_]
251
+ * determines the characters to escape
252
+ * - *:class_cache* [_Boolean_|_nil_] cache classes for faster parsing (if dynamically
253
+ * modifying classes or reloading classes then don't use this)
254
+ * - *:mode* [_:object_|_:strict_|_:compat_|_:null_|_:custom_|_:rails_|_:wab_] load and
255
+ * dump modes to use for JSON
232
256
  * - *:time_format* [_:unix_|_:unix_zone_|_:xmlschema_|_:ruby_] time format when dumping
233
- * - *:bigdecimal_as_decimal* [_Boolean_|_nil_] dump BigDecimal as a decimal number or as a String
234
- * - *:bigdecimal_load* [_:bigdecimal_|_:float_|_:auto_|_:fast_] load decimals as BigDecimal instead of as a Float. :auto pick the most precise for the number of digits. :float should be the same as ruby. :fast may require rounding but is must faster.
235
- * - *:compat_bigdecimal* [_true_|_false_] load decimals as BigDecimal instead of as a Float when in compat or rails mode.
236
- * - *:create_id* [_String_|_nil_] create id for json compatible object encoding, default is 'json_class'
237
- * - *:create_additions* [_Boolean_|_nil_] if true allow creation of instances using create_id on load.
238
- * - *:second_precision* [_Fixnum_|_nil_] number of digits after the decimal when dumping the seconds portion of time
239
- * - *:float_precision* [_Fixnum_|_nil_] number of digits of precision when dumping floats, 0 indicates use Ruby
257
+ * - *:bigdecimal_as_decimal* [_Boolean_|_nil_] dump BigDecimal as a decimal number or
258
+ * as a String
259
+ * - *:bigdecimal_load* [_:bigdecimal_|_:float_|_:auto_|_:fast_|_:ruby_] load decimals
260
+ * as BigDecimal instead of as a Float. :auto pick the most precise for the number
261
+ * of digits. :float should be the same as ruby. :fast may require rounding but is
262
+ * must faster.
263
+ * - *:compat_bigdecimal* [_true_|_false_] load decimals as BigDecimal instead of as
264
+ * a Float when in compat or rails mode.
265
+ * - *:create_id* [_String_|_nil_] create id for json compatible object encoding,
266
+ * default is 'json_class'
267
+ * - *:create_additions* [_Boolean_|_nil_] if true allow creation of instances using
268
+ * create_id on load.
269
+ * - *:second_precision* [_Fixnum_|_nil_] number of digits after the decimal when
270
+ * dumping the seconds portion of time
271
+ * - *:float_precision* [_Fixnum_|_nil_] number of digits of precision when dumping
272
+ * floats, 0 indicates use Ruby
273
+ * - *:float_format* [_String_] the C printf format string for printing floats.
274
+ * Default follows the float_precision and will be changed if float_precision is
275
+ * changed. The string can be no more than 6 bytes.
240
276
  * - *:use_to_json* [_Boolean_|_nil_] call to_json() methods on dump, default is false
241
277
  * - *:use_as_json* [_Boolean_|_nil_] call as_json() methods on dump, default is false
242
278
  * - *:use_raw_json* [_Boolean_|_nil_] call raw_json() methods on dump, default is false
243
- * - *:nilnil* [_Boolean_|_nil_] if true a nil input to load will return nil and not raise an Exception
279
+ * - *:nilnil* [_Boolean_|_nil_] if true a nil input to load will return nil and
280
+ * not raise an Exception
244
281
  * - *:empty_string* [_Boolean_|_nil_] if true an empty input will not raise an Exception
245
282
  * - *:allow_gc* [_Boolean_|_nil_] allow or prohibit GC during parsing, default is true (allow)
246
- * - *:quirks_mode* [_true,_|_false_|_nil_] Allow single JSON values instead of documents, default is true (allow)
247
- * - *:allow_invalid_unicode* [_true,_|_false_|_nil_] Allow invalid unicode, default is false (don't allow)
248
- * - *:allow_nan* [_true,_|_false_|_nil_] Allow Nan, Infinity, and -Infinity to be parsed, default is true (allow)
249
- * - *:indent_str* [_String_|_nil_] String to use for indentation, overriding the indent option is not nil
250
- * - *:space* [_String_|_nil_] String to use for the space after the colon in JSON object fields
251
- * - *:space_before* [_String_|_nil_] String to use before the colon separator in JSON object fields
283
+ * - *:quirks_mode* [_true,_|_false_|_nil_] Allow single JSON values instead of
284
+ * documents, default is true (allow)
285
+ * - *:allow_invalid_unicode* [_true,_|_false_|_nil_] Allow invalid unicode,
286
+ * default is false (don't allow)
287
+ * - *:allow_nan* [_true,_|_false_|_nil_] Allow Nan, Infinity, and -Infinity to
288
+ * be parsed, default is true (allow)
289
+ * - *:indent_str* [_String_|_nil_] String to use for indentation, overriding the
290
+ * indent option is not nil
291
+ * - *:space* [_String_|_nil_] String to use for the space after the colon in JSON
292
+ * object fields
293
+ * - *:space_before* [_String_|_nil_] String to use before the colon separator in
294
+ * JSON object fields
252
295
  * - *:object_nl* [_String_|_nil_] String to use after a JSON object field value
253
296
  * - *:array_nl* [_String_|_nil_] String to use after a JSON array value
254
- * - *:nan* [_:null_|_:huge_|_:word_|_:raise_|_:auto_] how to dump Infinity and NaN. :null places a null, :huge places a huge number, :word places Infinity or NaN, :raise raises and exception, :auto uses default for each mode.
255
- * - *:hash_class* [_Class_|_nil_] Class to use instead of Hash on load, :object_class can also be used
297
+ * - *:nan* [_:null_|_:huge_|_:word_|_:raise_|_:auto_] how to dump Infinity and
298
+ * NaN. :null places a null, :huge places a huge number, :word places Infinity
299
+ * or NaN, :raise raises and exception, :auto uses default for each mode.
300
+ * - *:hash_class* [_Class_|_nil_] Class to use instead of Hash on load,
301
+ * :object_class can also be used
256
302
  * - *:array_class* [_Class_|_nil_] Class to use instead of Array on load
257
- * - *:omit_nil* [_true_|_false_] if true Hash and Object attributes with nil values are omitted
258
- * - *:ignore* [_nil_|Array] either nil or an Array of classes to ignore when dumping
259
- * - *:ignore_under* [Boolean] if true then attributes that start with _ are ignored when dumping in object or custom mode.
303
+ * - *:omit_nil* [_true_|_false_] if true Hash and Object attributes with nil
304
+ * values are omitted
305
+ * - *:omit_null_byte* [_true_|_false_] if true null bytes in strings will be
306
+ * omitted when dumping
307
+ * - *:ignore* [_nil_|_Array_] either nil or an Array of classes to ignore when dumping
308
+ * - *:ignore_under* [_Boolean_] if true then attributes that start with _ are
309
+ * ignored when dumping in object or custom mode.
310
+ * - *:cache_keys* [_Boolean_] if true then hash keys are cached if less than 35 bytes.
311
+ * - *:cache_str* [_Fixnum_] maximum string value length to cache (strings less
312
+ * than this are cached)
260
313
  * - *:integer_range* [_Range_] Dump integers outside range as strings.
261
- * - *:trace* [_true,_|_false_] Trace all load and dump calls, default is false (trace is off)
262
- * - *:safe* [_true,_|_false_] Safe mimic breaks JSON mimic to be safer, default is false (safe is off)
314
+ * - *:trace* [_true,_|_false_] Trace all load and dump calls, default is false
315
+ * (trace is off)
316
+ * - *:safe* [_true,_|_false_] Safe mimic breaks JSON mimic to be safer, default
317
+ * is false (safe is off)
263
318
  *
264
319
  * Return [_Hash_] all current option settings.
265
320
  */
266
- static VALUE
267
- get_def_opts(VALUE self) {
268
- VALUE opts = rb_hash_new();
321
+ static VALUE get_def_opts(VALUE self) {
322
+ VALUE opts = rb_hash_new();
269
323
 
270
324
  if (0 == oj_default_options.dump_opts.indent_size) {
271
- rb_hash_aset(opts, oj_indent_sym, INT2FIX(oj_default_options.indent));
325
+ rb_hash_aset(opts, oj_indent_sym, INT2FIX(oj_default_options.indent));
272
326
  } else {
273
- rb_hash_aset(opts, oj_indent_sym, rb_str_new2(oj_default_options.dump_opts.indent_str));
327
+ rb_hash_aset(opts, oj_indent_sym, rb_str_new2(oj_default_options.dump_opts.indent_str));
274
328
  }
275
329
  rb_hash_aset(opts, sec_prec_sym, INT2FIX(oj_default_options.sec_prec));
276
- rb_hash_aset(opts, circular_sym, (Yes == oj_default_options.circular) ? Qtrue : ((No == oj_default_options.circular) ? Qfalse : Qnil));
277
- rb_hash_aset(opts, class_cache_sym, (Yes == oj_default_options.class_cache) ? Qtrue : ((No == oj_default_options.class_cache) ? Qfalse : Qnil));
278
- rb_hash_aset(opts, auto_define_sym, (Yes == oj_default_options.auto_define) ? Qtrue : ((No == oj_default_options.auto_define) ? Qfalse : Qnil));
279
- rb_hash_aset(opts, symbol_keys_sym, (Yes == oj_default_options.sym_key) ? Qtrue : ((No == oj_default_options.sym_key) ? Qfalse : Qnil));
280
- rb_hash_aset(opts, bigdecimal_as_decimal_sym, (Yes == oj_default_options.bigdec_as_num) ? Qtrue : ((No == oj_default_options.bigdec_as_num) ? Qfalse : Qnil));
281
- rb_hash_aset(opts, oj_create_additions_sym, (Yes == oj_default_options.create_ok) ? Qtrue : ((No == oj_default_options.create_ok) ? Qfalse : Qnil));
282
- rb_hash_aset(opts, use_to_json_sym, (Yes == oj_default_options.to_json) ? Qtrue : ((No == oj_default_options.to_json) ? Qfalse : Qnil));
283
- rb_hash_aset(opts, use_to_hash_sym, (Yes == oj_default_options.to_hash) ? Qtrue : ((No == oj_default_options.to_hash) ? Qfalse : Qnil));
284
- rb_hash_aset(opts, use_as_json_sym, (Yes == oj_default_options.as_json) ? Qtrue : ((No == oj_default_options.as_json) ? Qfalse : Qnil));
285
- rb_hash_aset(opts, use_raw_json_sym, (Yes == oj_default_options.raw_json) ? Qtrue : ((No == oj_default_options.raw_json) ? Qfalse : Qnil));
286
- rb_hash_aset(opts, nilnil_sym, (Yes == oj_default_options.nilnil) ? Qtrue : ((No == oj_default_options.nilnil) ? Qfalse : Qnil));
287
- rb_hash_aset(opts, empty_string_sym, (Yes == oj_default_options.empty_string) ? Qtrue : ((No == oj_default_options.empty_string) ? Qfalse : Qnil));
288
- rb_hash_aset(opts, allow_gc_sym, (Yes == oj_default_options.allow_gc) ? Qtrue : ((No == oj_default_options.allow_gc) ? Qfalse : Qnil));
289
- rb_hash_aset(opts, oj_quirks_mode_sym, (Yes == oj_default_options.quirks_mode) ? Qtrue : ((No == oj_default_options.quirks_mode) ? Qfalse : Qnil));
290
- rb_hash_aset(opts, allow_invalid_unicode_sym, (Yes == oj_default_options.allow_invalid) ? Qtrue : ((No == oj_default_options.allow_invalid) ? Qfalse : Qnil));
291
- rb_hash_aset(opts, oj_allow_nan_sym, (Yes == oj_default_options.allow_nan) ? Qtrue : ((No == oj_default_options.allow_nan) ? Qfalse : Qnil));
292
- rb_hash_aset(opts, oj_trace_sym, (Yes == oj_default_options.trace) ? Qtrue : ((No == oj_default_options.trace) ? Qfalse : Qnil));
293
- rb_hash_aset(opts, oj_safe_sym, (Yes == oj_default_options.safe) ? Qtrue : ((No == oj_default_options.safe) ? Qfalse : Qnil));
330
+ rb_hash_aset(opts,
331
+ circular_sym,
332
+ (Yes == oj_default_options.circular) ? Qtrue : ((No == oj_default_options.circular) ? Qfalse : Qnil));
333
+ rb_hash_aset(
334
+ opts,
335
+ class_cache_sym,
336
+ (Yes == oj_default_options.class_cache) ? Qtrue : ((No == oj_default_options.class_cache) ? Qfalse : Qnil));
337
+ rb_hash_aset(
338
+ opts,
339
+ auto_define_sym,
340
+ (Yes == oj_default_options.auto_define) ? Qtrue : ((No == oj_default_options.auto_define) ? Qfalse : Qnil));
341
+ rb_hash_aset(opts,
342
+ symbol_keys_sym,
343
+ (Yes == oj_default_options.sym_key) ? Qtrue : ((No == oj_default_options.sym_key) ? Qfalse : Qnil));
344
+ rb_hash_aset(
345
+ opts,
346
+ bigdecimal_as_decimal_sym,
347
+ (Yes == oj_default_options.bigdec_as_num) ? Qtrue : ((No == oj_default_options.bigdec_as_num) ? Qfalse : Qnil));
348
+ rb_hash_aset(
349
+ opts,
350
+ oj_create_additions_sym,
351
+ (Yes == oj_default_options.create_ok) ? Qtrue : ((No == oj_default_options.create_ok) ? Qfalse : Qnil));
352
+ rb_hash_aset(opts,
353
+ use_to_json_sym,
354
+ (Yes == oj_default_options.to_json) ? Qtrue : ((No == oj_default_options.to_json) ? Qfalse : Qnil));
355
+ rb_hash_aset(opts,
356
+ use_to_hash_sym,
357
+ (Yes == oj_default_options.to_hash) ? Qtrue : ((No == oj_default_options.to_hash) ? Qfalse : Qnil));
358
+ rb_hash_aset(opts,
359
+ use_as_json_sym,
360
+ (Yes == oj_default_options.as_json) ? Qtrue : ((No == oj_default_options.as_json) ? Qfalse : Qnil));
361
+ rb_hash_aset(opts,
362
+ use_raw_json_sym,
363
+ (Yes == oj_default_options.raw_json) ? Qtrue : ((No == oj_default_options.raw_json) ? Qfalse : Qnil));
364
+ rb_hash_aset(opts,
365
+ nilnil_sym,
366
+ (Yes == oj_default_options.nilnil) ? Qtrue : ((No == oj_default_options.nilnil) ? Qfalse : Qnil));
367
+ rb_hash_aset(
368
+ opts,
369
+ empty_string_sym,
370
+ (Yes == oj_default_options.empty_string) ? Qtrue : ((No == oj_default_options.empty_string) ? Qfalse : Qnil));
371
+ rb_hash_aset(opts,
372
+ allow_gc_sym,
373
+ (Yes == oj_default_options.allow_gc) ? Qtrue : ((No == oj_default_options.allow_gc) ? Qfalse : Qnil));
374
+ rb_hash_aset(
375
+ opts,
376
+ oj_quirks_mode_sym,
377
+ (Yes == oj_default_options.quirks_mode) ? Qtrue : ((No == oj_default_options.quirks_mode) ? Qfalse : Qnil));
378
+ rb_hash_aset(
379
+ opts,
380
+ allow_invalid_unicode_sym,
381
+ (Yes == oj_default_options.allow_invalid) ? Qtrue : ((No == oj_default_options.allow_invalid) ? Qfalse : Qnil));
382
+ rb_hash_aset(
383
+ opts,
384
+ oj_allow_nan_sym,
385
+ (Yes == oj_default_options.allow_nan) ? Qtrue : ((No == oj_default_options.allow_nan) ? Qfalse : Qnil));
386
+ rb_hash_aset(opts,
387
+ oj_trace_sym,
388
+ (Yes == oj_default_options.trace) ? Qtrue : ((No == oj_default_options.trace) ? Qfalse : Qnil));
389
+ rb_hash_aset(opts,
390
+ oj_safe_sym,
391
+ (Yes == oj_default_options.safe) ? Qtrue : ((No == oj_default_options.safe) ? Qfalse : Qnil));
294
392
  rb_hash_aset(opts, float_prec_sym, INT2FIX(oj_default_options.float_prec));
295
- rb_hash_aset(opts, ignore_under_sym, (Yes == oj_default_options.ignore_under) ? Qtrue : ((No == oj_default_options.ignore_under) ? Qfalse : Qnil));
393
+ rb_hash_aset(opts, float_format_sym, rb_str_new_cstr(oj_default_options.float_fmt));
394
+ rb_hash_aset(opts, cache_str_sym, INT2FIX(oj_default_options.cache_str));
395
+ rb_hash_aset(
396
+ opts,
397
+ ignore_under_sym,
398
+ (Yes == oj_default_options.ignore_under) ? Qtrue : ((No == oj_default_options.ignore_under) ? Qfalse : Qnil));
399
+ rb_hash_aset(
400
+ opts,
401
+ cache_keys_sym,
402
+ (Yes == oj_default_options.cache_keys) ? Qtrue : ((No == oj_default_options.cache_keys) ? Qfalse : Qnil));
403
+
296
404
  switch (oj_default_options.mode) {
297
- case StrictMode: rb_hash_aset(opts, mode_sym, strict_sym); break;
298
- case CompatMode: rb_hash_aset(opts, mode_sym, compat_sym); break;
299
- case NullMode: rb_hash_aset(opts, mode_sym, null_sym); break;
300
- case ObjectMode: rb_hash_aset(opts, mode_sym, object_sym); break;
301
- case CustomMode: rb_hash_aset(opts, mode_sym, custom_sym); break;
302
- case RailsMode: rb_hash_aset(opts, mode_sym, rails_sym); break;
303
- case WabMode: rb_hash_aset(opts, mode_sym, wab_sym); break;
304
- default: rb_hash_aset(opts, mode_sym, object_sym); break;
405
+ case StrictMode: rb_hash_aset(opts, mode_sym, strict_sym); break;
406
+ case CompatMode: rb_hash_aset(opts, mode_sym, compat_sym); break;
407
+ case NullMode: rb_hash_aset(opts, mode_sym, null_sym); break;
408
+ case ObjectMode: rb_hash_aset(opts, mode_sym, object_sym); break;
409
+ case CustomMode: rb_hash_aset(opts, mode_sym, custom_sym); break;
410
+ case RailsMode: rb_hash_aset(opts, mode_sym, rails_sym); break;
411
+ case WabMode: rb_hash_aset(opts, mode_sym, wab_sym); break;
412
+ default: rb_hash_aset(opts, mode_sym, object_sym); break;
305
413
  }
306
414
 
307
415
  if (oj_default_options.int_range_max != 0 || oj_default_options.int_range_min != 0) {
308
- VALUE range = rb_obj_alloc(rb_cRange);
309
- VALUE min = LONG2FIX(oj_default_options.int_range_min);
310
- VALUE max = LONG2FIX(oj_default_options.int_range_max);
416
+ VALUE range = rb_obj_alloc(rb_cRange);
417
+ VALUE min = LONG2FIX(oj_default_options.int_range_min);
418
+ VALUE max = LONG2FIX(oj_default_options.int_range_max);
311
419
 
312
- rb_ivar_set(range, oj_begin_id, min);
313
- rb_ivar_set(range, oj_end_id, max);
314
- rb_hash_aset(opts, integer_range_sym, range);
420
+ rb_ivar_set(range, oj_begin_id, min);
421
+ rb_ivar_set(range, oj_end_id, max);
422
+ rb_hash_aset(opts, integer_range_sym, range);
315
423
  } else {
316
- rb_hash_aset(opts, integer_range_sym, Qnil);
424
+ rb_hash_aset(opts, integer_range_sym, Qnil);
317
425
  }
318
426
  switch (oj_default_options.escape_mode) {
319
- case NLEsc: rb_hash_aset(opts, escape_mode_sym, newline_sym); break;
320
- case JSONEsc: rb_hash_aset(opts, escape_mode_sym, json_sym); break;
321
- case XSSEsc: rb_hash_aset(opts, escape_mode_sym, xss_safe_sym); break;
322
- case ASCIIEsc: rb_hash_aset(opts, escape_mode_sym, ascii_sym); break;
323
- case JXEsc: rb_hash_aset(opts, escape_mode_sym, unicode_xss_sym); break;
324
- default: rb_hash_aset(opts, escape_mode_sym, json_sym); break;
427
+ case NLEsc: rb_hash_aset(opts, escape_mode_sym, newline_sym); break;
428
+ case JSONEsc: rb_hash_aset(opts, escape_mode_sym, json_sym); break;
429
+ case SlashEsc: rb_hash_aset(opts, escape_mode_sym, slash_sym); break;
430
+ case XSSEsc: rb_hash_aset(opts, escape_mode_sym, xss_safe_sym); break;
431
+ case ASCIIEsc: rb_hash_aset(opts, escape_mode_sym, ascii_sym); break;
432
+ case JXEsc: rb_hash_aset(opts, escape_mode_sym, unicode_xss_sym); break;
433
+ default: rb_hash_aset(opts, escape_mode_sym, json_sym); break;
325
434
  }
326
435
  switch (oj_default_options.time_format) {
327
- case XmlTime: rb_hash_aset(opts, time_format_sym, xmlschema_sym); break;
328
- case RubyTime: rb_hash_aset(opts, time_format_sym, ruby_sym); break;
329
- case UnixZTime: rb_hash_aset(opts, time_format_sym, unix_zone_sym); break;
436
+ case XmlTime: rb_hash_aset(opts, time_format_sym, xmlschema_sym); break;
437
+ case RubyTime: rb_hash_aset(opts, time_format_sym, ruby_sym); break;
438
+ case UnixZTime: rb_hash_aset(opts, time_format_sym, unix_zone_sym); break;
330
439
  case UnixTime:
331
- default: rb_hash_aset(opts, time_format_sym, unix_sym); break;
440
+ default: rb_hash_aset(opts, time_format_sym, unix_sym); break;
332
441
  }
333
442
  switch (oj_default_options.bigdec_load) {
334
- case BigDec: rb_hash_aset(opts, bigdecimal_load_sym, bigdecimal_sym);break;
335
- case FloatDec: rb_hash_aset(opts, bigdecimal_load_sym, float_sym); break;
336
- case FastDec: rb_hash_aset(opts, bigdecimal_load_sym, fast_sym); break;
443
+ case BigDec: rb_hash_aset(opts, bigdecimal_load_sym, bigdecimal_sym); break;
444
+ case FloatDec: rb_hash_aset(opts, bigdecimal_load_sym, float_sym); break;
445
+ case FastDec: rb_hash_aset(opts, bigdecimal_load_sym, fast_sym); break;
337
446
  case AutoDec:
338
- default: rb_hash_aset(opts, bigdecimal_load_sym, auto_sym); break;
447
+ default: rb_hash_aset(opts, bigdecimal_load_sym, auto_sym); break;
339
448
  }
340
449
  rb_hash_aset(opts, compat_bigdecimal_sym, oj_default_options.compat_bigdec ? Qtrue : Qfalse);
341
- rb_hash_aset(opts, create_id_sym, (NULL == oj_default_options.create_id) ? Qnil : rb_str_new2(oj_default_options.create_id));
342
- rb_hash_aset(opts, oj_space_sym, (0 == oj_default_options.dump_opts.after_size) ? Qnil : rb_str_new2(oj_default_options.dump_opts.after_sep));
343
- rb_hash_aset(opts, oj_space_before_sym, (0 == oj_default_options.dump_opts.before_size) ? Qnil : rb_str_new2(oj_default_options.dump_opts.before_sep));
344
- rb_hash_aset(opts, oj_object_nl_sym, (0 == oj_default_options.dump_opts.hash_size) ? Qnil : rb_str_new2(oj_default_options.dump_opts.hash_nl));
345
- rb_hash_aset(opts, oj_array_nl_sym, (0 == oj_default_options.dump_opts.array_size) ? Qnil : rb_str_new2(oj_default_options.dump_opts.array_nl));
450
+ rb_hash_aset(opts,
451
+ create_id_sym,
452
+ (NULL == oj_default_options.create_id) ? Qnil : rb_str_new2(oj_default_options.create_id));
453
+ rb_hash_aset(
454
+ opts,
455
+ oj_space_sym,
456
+ (0 == oj_default_options.dump_opts.after_size) ? Qnil : rb_str_new2(oj_default_options.dump_opts.after_sep));
457
+ rb_hash_aset(
458
+ opts,
459
+ oj_space_before_sym,
460
+ (0 == oj_default_options.dump_opts.before_size) ? Qnil : rb_str_new2(oj_default_options.dump_opts.before_sep));
461
+ rb_hash_aset(
462
+ opts,
463
+ oj_object_nl_sym,
464
+ (0 == oj_default_options.dump_opts.hash_size) ? Qnil : rb_str_new2(oj_default_options.dump_opts.hash_nl));
465
+ rb_hash_aset(
466
+ opts,
467
+ oj_array_nl_sym,
468
+ (0 == oj_default_options.dump_opts.array_size) ? Qnil : rb_str_new2(oj_default_options.dump_opts.array_nl));
346
469
 
347
470
  switch (oj_default_options.dump_opts.nan_dump) {
348
- case NullNan: rb_hash_aset(opts, nan_sym, null_sym); break;
349
- case RaiseNan: rb_hash_aset(opts, nan_sym, raise_sym); break;
350
- case WordNan: rb_hash_aset(opts, nan_sym, word_sym); break;
351
- case HugeNan: rb_hash_aset(opts, nan_sym, huge_sym); break;
471
+ case NullNan: rb_hash_aset(opts, nan_sym, null_sym); break;
472
+ case RaiseNan: rb_hash_aset(opts, nan_sym, raise_sym); break;
473
+ case WordNan: rb_hash_aset(opts, nan_sym, word_sym); break;
474
+ case HugeNan: rb_hash_aset(opts, nan_sym, huge_sym); break;
352
475
  case AutoNan:
353
- default: rb_hash_aset(opts, nan_sym, auto_sym); break;
476
+ default: rb_hash_aset(opts, nan_sym, auto_sym); break;
354
477
  }
355
478
  rb_hash_aset(opts, omit_nil_sym, oj_default_options.dump_opts.omit_nil ? Qtrue : Qfalse);
479
+ rb_hash_aset(opts, omit_null_byte_sym, oj_default_options.dump_opts.omit_null_byte ? Qtrue : Qfalse);
356
480
  rb_hash_aset(opts, oj_hash_class_sym, oj_default_options.hash_class);
357
481
  rb_hash_aset(opts, oj_array_class_sym, oj_default_options.array_class);
358
482
 
359
483
  if (NULL == oj_default_options.ignore) {
360
- rb_hash_aset(opts, ignore_sym, Qnil);
484
+ rb_hash_aset(opts, ignore_sym, Qnil);
361
485
  } else {
362
- VALUE *vp;
363
- volatile VALUE a = rb_ary_new();
486
+ VALUE *vp;
487
+ volatile VALUE a = rb_ary_new();
364
488
 
365
- for (vp = oj_default_options.ignore; Qnil != *vp; vp++) {
366
- rb_ary_push(a, *vp);
367
- }
368
- rb_hash_aset(opts, ignore_sym, a);
489
+ for (vp = oj_default_options.ignore; Qnil != *vp; vp++) {
490
+ rb_ary_push(a, *vp);
491
+ }
492
+ rb_hash_aset(opts, ignore_sym, a);
369
493
  }
370
494
  return opts;
371
495
  }
@@ -375,20 +499,44 @@ get_def_opts(VALUE self) {
375
499
  *
376
500
  * Sets the default options for load and dump.
377
501
  * - *opts* [_Hash_] options to change
378
- * - *:indent* [_Fixnum_|_String_|_nil_] number of spaces to indent each element in a JSON document or the String to use for identation.
502
+ * - *:indent* [_Fixnum_|_String_|_nil_] number of spaces to indent each element
503
+ * in a JSON document or the String to use for indentation.
379
504
  * - :circular [_Boolean_|_nil_] support circular references while dumping.
380
505
  * - *:auto_define* [_Boolean_|_nil_] automatically define classes if they do not exist.
381
506
  * - *:symbol_keys* [_Boolean_|_nil_] convert hash keys to symbols.
382
507
  * - *:class_cache* [_Boolean_|_nil_] cache classes for faster parsing.
383
- * - *:escape* [_:newline_|_:json_|_:xss_safe_|_:ascii_|_unicode_xss_|_nil_] mode encodes all high-bit characters as escaped sequences if :ascii, :json is standand UTF-8 JSON encoding, :newline is the same as :json but newlines are not escaped, :unicode_xss allows unicode but escapes &, <, and >, and any \u20xx characters along with some others, and :xss_safe escapes &, <, and >, and some others.
384
- * - *:bigdecimal_as_decimal* [_Boolean_|_nil_] dump BigDecimal as a decimal number or as a String.
385
- * - *:bigdecimal_load* [_:bigdecimal_|_:float_|_:auto_|_nil_] load decimals as BigDecimal instead of as a Float. :auto pick the most precise for the number of digits.
386
- * - *:compat_bigdecimal* [_true_|_false_] load decimals as BigDecimal instead of as a Float in compat mode.
387
- * - *:mode* [_:object_|_:strict_|_:compat_|_:null_|_:custom_|_:rails_|_:wab_] load and dump mode to use for JSON :strict raises an exception when a non-supported Object is encountered. :compat attempts to extract variable values from an Object using to_json() or to_hash() then it walks the Object's variables if neither is found. The :object mode ignores to_hash() and to_json() methods and encodes variables using code internal to the Oj gem. The :null mode ignores non-supported Objects and replaces them with a null. The :custom mode honors all dump options. The :rails more mimics rails and Active behavior.
388
- * - *:time_format* [_:unix_|_:xmlschema_|_:ruby_] time format when dumping in :compat mode :unix decimal number denoting the number of seconds since 1/1/1970, :unix_zone decimal number denoting the number of seconds since 1/1/1970 plus the utc_offset in the exponent, :xmlschema date-time format taken from XML Schema as a String, :ruby Time.to_s formatted String.
508
+ * - *:escape* [_:newline_|_:json_|_:xss_safe_|_:ascii_|_unicode_xss_|_nil_]
509
+ * mode encodes all high-bit characters as escaped sequences if :ascii, :json
510
+ * is standand UTF-8 JSON encoding, :newline is the same as :json but newlines
511
+ * are not escaped, :unicode_xss allows unicode but escapes &, <, and >, and
512
+ * any \u20xx characters along with some others, and :xss_safe escapes &, <,
513
+ * and >, and some others.
514
+ * - *:bigdecimal_as_decimal* [_Boolean_|_nil_] dump BigDecimal as a decimal
515
+ * number or as a String.
516
+ * - *:bigdecimal_load* [_:bigdecimal_|_:float_|_:auto_|_nil_] load decimals as
517
+ * BigDecimal instead of as a Float. :auto pick the most precise for the number of digits.
518
+ * - *:compat_bigdecimal* [_true_|_false_] load decimals as BigDecimal instead
519
+ * of as a Float in compat mode.
520
+ * - *:mode* [_:object_|_:strict_|_:compat_|_:null_|_:custom_|_:rails_|_:wab_] load
521
+ * and dump mode to use for JSON :strict raises an exception when a non-supported
522
+ * Object is encountered. :compat attempts to extract variable values from an
523
+ * Object using to_json() or to_hash() then it walks the Object's variables if
524
+ * neither is found. The :object mode ignores to_hash() and to_json() methods
525
+ * and encodes variables using code internal to the Oj gem. The :null mode
526
+ * ignores non-supported Objects and replaces them with a null. The :custom
527
+ * mode honors all dump options. The :rails more mimics rails and Active behavior.
528
+ * - *:time_format* [_:unix_|_:xmlschema_|_:ruby_] time format when dumping in :compat
529
+ * mode :unix decimal number denoting the number of seconds since 1/1/1970,
530
+ * :unix_zone decimal number denoting the number of seconds since 1/1/1970
531
+ * plus the utc_offset in the exponent, :xmlschema date-time format taken
532
+ * from XML Schema as a String, :ruby Time.to_s formatted String.
389
533
  * - *:create_id* [_String_|_nil_] create id for json compatible object encoding
390
534
  * - *:create_additions* [_Boolean_|_nil_] if true allow creation of instances using create_id on load.
391
- * - *:second_precision* [_Fixnum_|_nil_] number of digits after the decimal when dumping the seconds portion of time.
535
+ * - *:second_precision* [_Fixnum_|_nil_] number of digits after the decimal
536
+ * when dumping the seconds portion of time.
537
+ * - *:float_format* [_String_] the C printf format string for printing floats.
538
+ * Default follows the float_precision and will be changed if float_precision
539
+ * is changed. The string can be no more than 6 bytes.
392
540
  * - *:float_precision* [_Fixnum_|_nil_] number of digits of precision when dumping floats, 0 indicates use Ruby.
393
541
  * - *:use_to_json* [_Boolean_|_nil_] call to_json() methods on dump, default is false.
394
542
  * - *:use_as_json* [_Boolean_|_nil_] call as_json() methods on dump, default is false.
@@ -403,424 +551,478 @@ get_def_opts(VALUE self) {
403
551
  * - *:space_before* [_String_|_nil_] String to use before the colon separator in JSON object fields.
404
552
  * - *:object_nl* [_String_|_nil_] String to use after a JSON object field value.
405
553
  * - *:array_nl* [_String_|_nil_] String to use after a JSON array value
406
- * - *:nan* [_:null_|_:huge_|_:word_|_:raise_] how to dump Infinity and NaN in null, strict, and compat mode. :null places a null, :huge places a huge number, :word places Infinity or NaN, :raise raises and exception, :auto uses default for each mode.
554
+ * - *:nan* [_:null_|_:huge_|_:word_|_:raise_] how to dump Infinity and NaN in null,
555
+ * strict, and compat mode. :null places a null, :huge places a huge number, :word
556
+ * places Infinity or NaN, :raise raises and exception, :auto uses default for each mode.
407
557
  * - *:hash_class* [_Class_|_nil_] Class to use instead of Hash on load, :object_class can also be used.
408
558
  * - *:array_class* [_Class_|_nil_] Class to use instead of Array on load.
409
559
  * - *:omit_nil* [_true_|_false_] if true Hash and Object attributes with nil values are omitted.
410
560
  * - *:ignore* [_nil_|Array] either nil or an Array of classes to ignore when dumping
411
- * - *:ignore_under* [_Boolean_] if true then attributes that start with _ are ignored when dumping in object or custom mode.
561
+ * - *:ignore_under* [_Boolean_] if true then attributes that start with _ are
562
+ * ignored when dumping in object or custom mode.
563
+ * - *:cache_keys* [_Boolean_] if true then hash keys are cached
564
+ * - *:cache_str* [_Fixnum_] maximum string value length to cache (strings less than this are cached)
412
565
  * - *:integer_range* [_Range_] Dump integers outside range as strings.
413
566
  * - *:trace* [_Boolean_] turn trace on or off.
414
567
  * - *:safe* [_Boolean_] turn safe mimic on or off.
415
568
  */
416
- static VALUE
417
- set_def_opts(VALUE self, VALUE opts) {
569
+ static VALUE set_def_opts(VALUE self, VALUE opts) {
418
570
  Check_Type(opts, T_HASH);
419
571
  oj_parse_options(opts, &oj_default_options);
420
572
 
421
573
  return Qnil;
422
574
  }
423
575
 
424
- void
425
- oj_parse_options(VALUE ropts, Options copts) {
426
- struct _yesNoOpt ynos[] = {
427
- { circular_sym, &copts->circular },
428
- { auto_define_sym, &copts->auto_define },
429
- { symbol_keys_sym, &copts->sym_key },
430
- { class_cache_sym, &copts->class_cache },
431
- { bigdecimal_as_decimal_sym, &copts->bigdec_as_num },
432
- { use_to_hash_sym, &copts->to_hash },
433
- { use_to_json_sym, &copts->to_json },
434
- { use_as_json_sym, &copts->as_json },
435
- { use_raw_json_sym, &copts->raw_json },
436
- { nilnil_sym, &copts->nilnil },
437
- { allow_blank_sym, &copts->nilnil }, // same as nilnil
438
- { empty_string_sym, &copts->empty_string },
439
- { allow_gc_sym, &copts->allow_gc },
440
- { oj_quirks_mode_sym, &copts->quirks_mode },
441
- { allow_invalid_unicode_sym, &copts->allow_invalid },
442
- { oj_allow_nan_sym, &copts->allow_nan },
443
- { oj_trace_sym, &copts->trace },
444
- { oj_safe_sym, &copts->safe },
445
- { ignore_under_sym, &copts->ignore_under },
446
- { oj_create_additions_sym, &copts->create_ok },
447
- { Qnil, 0 }
448
- };
449
- YesNoOpt o;
450
- volatile VALUE v;
451
- size_t len;
452
-
453
- if (T_HASH != rb_type(ropts)) {
454
- return;
576
+ bool oj_hash_has_key(VALUE hash, VALUE key) {
577
+ if (Qundef == rb_hash_lookup2(hash, key, Qundef)) {
578
+ return false;
455
579
  }
456
- if (Qtrue == rb_funcall(ropts, oj_has_key_id, 1, oj_indent_sym)) {
457
- v = rb_hash_lookup(ropts, oj_indent_sym);
458
- switch (rb_type(v)) {
459
- case T_NIL:
460
- copts->dump_opts.indent_size = 0;
461
- *copts->dump_opts.indent_str = '\0';
462
- copts->indent = 0;
463
- break;
464
- case T_FIXNUM:
465
- copts->dump_opts.indent_size = 0;
466
- *copts->dump_opts.indent_str = '\0';
467
- copts->indent = FIX2INT(v);
468
- break;
469
- case T_STRING:
470
- if (sizeof(copts->dump_opts.indent_str) <= (len = RSTRING_LEN(v))) {
471
- rb_raise(rb_eArgError, "indent string is limited to %lu characters.", (unsigned long)sizeof(copts->dump_opts.indent_str));
472
- }
473
- strcpy(copts->dump_opts.indent_str, StringValuePtr(v));
474
- copts->dump_opts.indent_size = (uint8_t)len;
475
- copts->indent = 0;
476
- break;
477
- default:
478
- rb_raise(rb_eTypeError, "indent must be a Fixnum, String, or nil.");
479
- break;
480
- }
481
- }
482
- if (Qnil != (v = rb_hash_lookup(ropts, float_prec_sym))) {
483
- int n;
580
+ return true;
581
+ }
484
582
 
485
- #ifdef RUBY_INTEGER_UNIFICATION
486
- if (rb_cInteger != rb_obj_class(v)) {
487
- rb_raise(rb_eArgError, ":float_precision must be a Integer.");
488
- }
489
- #else
490
- if (T_FIXNUM != rb_type(v)) {
491
- rb_raise(rb_eArgError, ":float_precision must be a Fixnum.");
492
- }
493
- #endif
494
- n = FIX2INT(v);
495
- if (0 >= n) {
496
- *copts->float_fmt = '\0';
497
- copts->float_prec = 0;
498
- } else {
499
- if (20 < n) {
500
- n = 20;
501
- }
502
- sprintf(copts->float_fmt, "%%0.%dg", n);
503
- copts->float_prec = n;
504
- }
505
- }
506
- if (Qnil != (v = rb_hash_lookup(ropts, sec_prec_sym))) {
507
- int n;
583
+ bool set_yesno_options(VALUE key, VALUE value, Options copts) {
584
+ struct _yesNoOpt ynos[] = {{circular_sym, &copts->circular},
585
+ {auto_define_sym, &copts->auto_define},
586
+ {symbol_keys_sym, &copts->sym_key},
587
+ {class_cache_sym, &copts->class_cache},
588
+ {bigdecimal_as_decimal_sym, &copts->bigdec_as_num},
589
+ {use_to_hash_sym, &copts->to_hash},
590
+ {use_to_json_sym, &copts->to_json},
591
+ {use_as_json_sym, &copts->as_json},
592
+ {use_raw_json_sym, &copts->raw_json},
593
+ {nilnil_sym, &copts->nilnil},
594
+ {allow_blank_sym, &copts->nilnil}, // same as nilnil
595
+ {empty_string_sym, &copts->empty_string},
596
+ {allow_gc_sym, &copts->allow_gc},
597
+ {oj_quirks_mode_sym, &copts->quirks_mode},
598
+ {allow_invalid_unicode_sym, &copts->allow_invalid},
599
+ {oj_allow_nan_sym, &copts->allow_nan},
600
+ {oj_trace_sym, &copts->trace},
601
+ {oj_safe_sym, &copts->safe},
602
+ {ignore_under_sym, &copts->ignore_under},
603
+ {oj_create_additions_sym, &copts->create_ok},
604
+ {cache_keys_sym, &copts->cache_keys},
605
+ {Qnil, 0}};
606
+ YesNoOpt o;
508
607
 
509
- #ifdef RUBY_INTEGER_UNIFICATION
510
- if (rb_cInteger != rb_obj_class(v)) {
511
- rb_raise(rb_eArgError, ":second_precision must be a Integer.");
512
- }
513
- #else
514
- if (T_FIXNUM != rb_type(v)) {
515
- rb_raise(rb_eArgError, ":second_precision must be a Fixnum.");
516
- }
517
- #endif
518
- n = NUM2INT(v);
519
- if (0 > n) {
520
- n = 0;
521
- copts->sec_prec_set = false;
522
- } else if (9 < n) {
523
- n = 9;
524
- copts->sec_prec_set = true;
525
- } else {
526
- copts->sec_prec_set = true;
527
- }
528
- copts->sec_prec = n;
529
- }
530
- if (Qnil != (v = rb_hash_lookup(ropts, mode_sym))) {
531
- if (wab_sym == v) {
532
- copts->mode = WabMode;
533
- } else if (object_sym == v) {
534
- copts->mode = ObjectMode;
535
- } else if (strict_sym == v) {
536
- copts->mode = StrictMode;
537
- } else if (compat_sym == v || json_sym == v) {
538
- copts->mode = CompatMode;
539
- } else if (null_sym == v) {
540
- copts->mode = NullMode;
541
- } else if (custom_sym == v) {
542
- copts->mode = CustomMode;
543
- } else if (rails_sym == v) {
544
- copts->mode = RailsMode;
545
- } else {
546
- rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, :null, :custom, :rails, or :wab.");
547
- }
548
- }
549
- if (Qnil != (v = rb_hash_lookup(ropts, time_format_sym))) {
550
- if (unix_sym == v) {
551
- copts->time_format = UnixTime;
552
- } else if (unix_zone_sym == v) {
553
- copts->time_format = UnixZTime;
554
- } else if (xmlschema_sym == v) {
555
- copts->time_format = XmlTime;
556
- } else if (ruby_sym == v) {
557
- copts->time_format = RubyTime;
558
- } else {
559
- rb_raise(rb_eArgError, ":time_format must be :unix, :unix_zone, :xmlschema, or :ruby.");
560
- }
561
- }
562
- if (Qnil != (v = rb_hash_lookup(ropts, escape_mode_sym))) {
563
- if (newline_sym == v) {
564
- copts->escape_mode = NLEsc;
565
- } else if (json_sym == v) {
566
- copts->escape_mode = JSONEsc;
567
- } else if (xss_safe_sym == v) {
568
- copts->escape_mode = XSSEsc;
569
- } else if (ascii_sym == v) {
570
- copts->escape_mode = ASCIIEsc;
571
- } else if (unicode_xss_sym == v) {
572
- copts->escape_mode = JXEsc;
573
- } else {
574
- rb_raise(rb_eArgError, ":encoding must be :newline, :json, :xss_safe, :unicode_xss, or :ascii.");
575
- }
576
- }
577
- if (Qnil != (v = rb_hash_lookup(ropts, bigdecimal_load_sym))) {
578
- if (bigdecimal_sym == v || Qtrue == v) {
579
- copts->bigdec_load = BigDec;
580
- } else if (float_sym == v) {
581
- copts->bigdec_load = FloatDec;
582
- } else if (fast_sym == v) {
583
- copts->bigdec_load = FastDec;
584
- } else if (auto_sym == v || Qfalse == v) {
585
- copts->bigdec_load = AutoDec;
586
- } else {
587
- rb_raise(rb_eArgError, ":bigdecimal_load must be :bigdecimal, :float, or :auto.");
588
- }
589
- }
590
- if (Qnil != (v = rb_hash_lookup(ropts, compat_bigdecimal_sym))) {
591
- copts->compat_bigdec = (Qtrue == v);
592
- }
593
- if (Qtrue == rb_funcall(ropts, oj_has_key_id, 1, oj_decimal_class_sym)) {
594
- v = rb_hash_lookup(ropts, oj_decimal_class_sym);
595
- if (rb_cFloat == v) {
596
- copts->compat_bigdec = FloatDec;
597
- } else if (oj_bigdecimal_class == v) {
598
- copts->compat_bigdec = BigDec;
599
- } else if (Qnil == v) {
600
- copts->compat_bigdec = AutoDec;
601
- } else {
602
- rb_raise(rb_eArgError, ":decimal_class must be BigDecimal, Float, or nil.");
603
- }
604
- }
605
- if (Qtrue == rb_funcall(ropts, oj_has_key_id, 1, create_id_sym)) {
606
- v = rb_hash_lookup(ropts, create_id_sym);
607
- if (Qnil == v) {
608
- if (oj_json_class != oj_default_options.create_id && NULL != copts->create_id) {
609
- xfree((char*)oj_default_options.create_id);
610
- }
611
- copts->create_id = NULL;
612
- copts->create_id_len = 0;
613
- } else if (T_STRING == rb_type(v)) {
614
- const char *str = StringValuePtr(v);
615
-
616
- len = RSTRING_LEN(v);
617
- if (len != copts->create_id_len ||
618
- 0 != strcmp(copts->create_id, str)) {
619
- copts->create_id = ALLOC_N(char, len + 1);
620
- strcpy((char*)copts->create_id, str);
621
- copts->create_id_len = len;
622
- }
623
- } else {
624
- rb_raise(rb_eArgError, ":create_id must be string.");
625
- }
626
- }
627
608
  for (o = ynos; 0 != o->attr; o++) {
628
- if (Qtrue == rb_funcall(ropts, oj_has_key_id, 1, o->sym)) {
629
- v = rb_hash_lookup(ropts, o->sym);
630
- if (Qnil == v) {
631
- *o->attr = NotSet;
632
- } else if (Qtrue == v) {
633
- *o->attr = Yes;
634
- } else if (Qfalse == v) {
635
- *o->attr = No;
636
- } else {
637
- rb_raise(rb_eArgError, "%s must be true, false, or nil.", rb_id2name(SYM2ID(o->sym)));
638
- }
639
- }
640
- }
641
- if (Qtrue == rb_funcall(ropts, oj_has_key_id, 1, oj_space_sym)) {
642
- if (Qnil == (v = rb_hash_lookup(ropts, oj_space_sym))) {
643
- copts->dump_opts.after_size = 0;
644
- *copts->dump_opts.after_sep = '\0';
645
- } else {
646
- rb_check_type(v, T_STRING);
647
- if (sizeof(copts->dump_opts.after_sep) <= (len = RSTRING_LEN(v))) {
648
- rb_raise(rb_eArgError, "space string is limited to %lu characters.", (unsigned long)sizeof(copts->dump_opts.after_sep));
649
- }
650
- strcpy(copts->dump_opts.after_sep, StringValuePtr(v));
651
- copts->dump_opts.after_size = (uint8_t)len;
652
- }
653
- }
654
- if (Qtrue == rb_funcall(ropts, oj_has_key_id, 1, oj_space_before_sym)) {
655
- if (Qnil == (v = rb_hash_lookup(ropts, oj_space_before_sym))) {
656
- copts->dump_opts.before_size = 0;
657
- *copts->dump_opts.before_sep = '\0';
658
- } else {
659
- rb_check_type(v, T_STRING);
660
- if (sizeof(copts->dump_opts.before_sep) <= (len = RSTRING_LEN(v))) {
661
- rb_raise(rb_eArgError, "sapce_before string is limited to %lu characters.", (unsigned long)sizeof(copts->dump_opts.before_sep));
662
- }
663
- strcpy(copts->dump_opts.before_sep, StringValuePtr(v));
664
- copts->dump_opts.before_size = (uint8_t)len;
665
- }
666
- }
667
- if (Qtrue == rb_funcall(ropts, oj_has_key_id, 1, oj_object_nl_sym)) {
668
- if (Qnil == (v = rb_hash_lookup(ropts, oj_object_nl_sym))) {
669
- copts->dump_opts.hash_size = 0;
670
- *copts->dump_opts.hash_nl = '\0';
671
- } else {
672
- rb_check_type(v, T_STRING);
673
- if (sizeof(copts->dump_opts.hash_nl) <= (len = RSTRING_LEN(v))) {
674
- rb_raise(rb_eArgError, "object_nl string is limited to %lu characters.", (unsigned long)sizeof(copts->dump_opts.hash_nl));
675
- }
676
- strcpy(copts->dump_opts.hash_nl, StringValuePtr(v));
677
- copts->dump_opts.hash_size = (uint8_t)len;
678
- }
609
+ if (key == o->sym) {
610
+ if (Qnil == value) {
611
+ *o->attr = NotSet;
612
+ } else if (Qtrue == value) {
613
+ *o->attr = Yes;
614
+ } else if (Qfalse == value) {
615
+ *o->attr = No;
616
+ } else {
617
+ rb_raise(rb_eArgError, "%s must be true, false, or nil.", rb_id2name(key));
618
+ }
619
+ return true;
620
+ }
679
621
  }
680
- if (Qtrue == rb_funcall(ropts, oj_has_key_id, 1, oj_array_nl_sym)) {
681
- if (Qnil == (v = rb_hash_lookup(ropts, oj_array_nl_sym))) {
682
- copts->dump_opts.array_size = 0;
683
- *copts->dump_opts.array_nl = '\0';
684
- } else {
685
- rb_check_type(v, T_STRING);
686
- if (sizeof(copts->dump_opts.array_nl) <= (len = RSTRING_LEN(v))) {
687
- rb_raise(rb_eArgError, "array_nl string is limited to %lu characters.", (unsigned long)sizeof(copts->dump_opts.array_nl));
688
- }
689
- strcpy(copts->dump_opts.array_nl, StringValuePtr(v));
690
- copts->dump_opts.array_size = (uint8_t)len;
691
- }
692
- }
693
- if (Qnil != (v = rb_hash_lookup(ropts, nan_sym))) {
694
- if (null_sym == v) {
695
- copts->dump_opts.nan_dump = NullNan;
696
- } else if (huge_sym == v) {
697
- copts->dump_opts.nan_dump = HugeNan;
698
- } else if (word_sym == v) {
699
- copts->dump_opts.nan_dump = WordNan;
700
- } else if (raise_sym == v) {
701
- copts->dump_opts.nan_dump = RaiseNan;
702
- } else if (auto_sym == v) {
703
- copts->dump_opts.nan_dump = AutoNan;
704
- } else {
705
- rb_raise(rb_eArgError, ":nan must be :null, :huge, :word, :raise, or :auto.");
706
- }
707
- }
708
- copts->dump_opts.use = (0 < copts->dump_opts.indent_size ||
709
- 0 < copts->dump_opts.after_size ||
710
- 0 < copts->dump_opts.before_size ||
711
- 0 < copts->dump_opts.hash_size ||
712
- 0 < copts->dump_opts.array_size);
713
- if (Qnil != (v = rb_hash_lookup(ropts, omit_nil_sym))) {
714
- if (Qtrue == v) {
715
- copts->dump_opts.omit_nil = true;
716
- } else if (Qfalse == v) {
717
- copts->dump_opts.omit_nil = false;
718
- } else {
719
- rb_raise(rb_eArgError, ":omit_nil must be true or false.");
720
- }
721
- }
722
- // This is here only for backwards compatibility with the original Oj.
723
- v = rb_hash_lookup(ropts, oj_ascii_only_sym);
724
- if (Qtrue == v) {
725
- copts->escape_mode = ASCIIEsc;
726
- } else if (Qfalse == v) {
727
- copts->escape_mode = JSONEsc;
728
- }
729
- if (Qtrue == rb_funcall(ropts, oj_has_key_id, 1, oj_hash_class_sym)) {
730
- if (Qnil == (v = rb_hash_lookup(ropts, oj_hash_class_sym))) {
731
- copts->hash_class = Qnil;
732
- } else {
733
- rb_check_type(v, T_CLASS);
734
- copts->hash_class = v;
735
- }
622
+ return false;
623
+ }
624
+
625
+ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
626
+ Options copts = (Options)opts;
627
+ size_t len;
628
+
629
+ if (set_yesno_options(k, v, copts)) {
630
+ return ST_CONTINUE;
736
631
  }
737
- if (Qtrue == rb_funcall(ropts, oj_has_key_id, 1, oj_object_class_sym)) {
738
- if (Qnil == (v = rb_hash_lookup(ropts, oj_object_class_sym))) {
739
- copts->hash_class = Qnil;
740
- } else {
741
- rb_check_type(v, T_CLASS);
742
- copts->hash_class = v;
743
- }
632
+ if (oj_indent_sym == k) {
633
+ switch (rb_type(v)) {
634
+ case T_NIL:
635
+ copts->dump_opts.indent_size = 0;
636
+ *copts->dump_opts.indent_str = '\0';
637
+ copts->indent = 0;
638
+ break;
639
+ case T_FIXNUM:
640
+ copts->dump_opts.indent_size = 0;
641
+ *copts->dump_opts.indent_str = '\0';
642
+ copts->indent = FIX2INT(v);
643
+ break;
644
+ case T_STRING:
645
+ if (sizeof(copts->dump_opts.indent_str) <= (len = RSTRING_LEN(v))) {
646
+ rb_raise(rb_eArgError,
647
+ "indent string is limited to %lu characters.",
648
+ (unsigned long)sizeof(copts->dump_opts.indent_str));
649
+ }
650
+ strcpy(copts->dump_opts.indent_str, StringValuePtr(v));
651
+ copts->dump_opts.indent_size = (uint8_t)len;
652
+ copts->indent = 0;
653
+ break;
654
+ default: rb_raise(rb_eTypeError, "indent must be a Fixnum, String, or nil."); break;
655
+ }
656
+ } else if (float_prec_sym == k) {
657
+ int n;
658
+
659
+ if (rb_cInteger != rb_obj_class(v)) {
660
+ rb_raise(rb_eArgError, ":float_precision must be a Integer.");
661
+ }
662
+ n = FIX2INT(v);
663
+ if (0 >= n) {
664
+ *copts->float_fmt = '\0';
665
+ copts->float_prec = 0;
666
+ } else {
667
+ if (20 < n) {
668
+ n = 20;
669
+ }
670
+ sprintf(copts->float_fmt, "%%0.%dg", n);
671
+ copts->float_prec = n;
672
+ }
673
+ } else if (cache_str_sym == k || cache_string_sym == k) {
674
+ int n;
675
+
676
+ if (rb_cInteger != rb_obj_class(v)) {
677
+ rb_raise(rb_eArgError, ":cache_str must be a Integer.");
678
+ }
679
+ n = FIX2INT(v);
680
+ if (0 >= n) {
681
+ copts->cache_str = 0;
682
+ } else {
683
+ if (32 < n) {
684
+ n = 32;
685
+ }
686
+ copts->cache_str = (char)n;
687
+ }
688
+ } else if (sec_prec_sym == k) {
689
+ int n;
690
+
691
+ if (rb_cInteger != rb_obj_class(v)) {
692
+ rb_raise(rb_eArgError, ":second_precision must be a Integer.");
693
+ }
694
+ n = NUM2INT(v);
695
+ if (0 > n) {
696
+ n = 0;
697
+ copts->sec_prec_set = false;
698
+ } else if (9 < n) {
699
+ n = 9;
700
+ copts->sec_prec_set = true;
701
+ } else {
702
+ copts->sec_prec_set = true;
703
+ }
704
+ copts->sec_prec = n;
705
+ } else if (mode_sym == k) {
706
+ if (wab_sym == v) {
707
+ copts->mode = WabMode;
708
+ } else if (object_sym == v) {
709
+ copts->mode = ObjectMode;
710
+ } else if (strict_sym == v) {
711
+ copts->mode = StrictMode;
712
+ } else if (compat_sym == v || json_sym == v) {
713
+ copts->mode = CompatMode;
714
+ } else if (null_sym == v) {
715
+ copts->mode = NullMode;
716
+ } else if (custom_sym == v) {
717
+ copts->mode = CustomMode;
718
+ } else if (rails_sym == v) {
719
+ copts->mode = RailsMode;
720
+ } else {
721
+ rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, :null, :custom, :rails, or :wab.");
722
+ }
723
+ } else if (time_format_sym == k) {
724
+ if (unix_sym == v) {
725
+ copts->time_format = UnixTime;
726
+ } else if (unix_zone_sym == v) {
727
+ copts->time_format = UnixZTime;
728
+ } else if (xmlschema_sym == v) {
729
+ copts->time_format = XmlTime;
730
+ } else if (ruby_sym == v) {
731
+ copts->time_format = RubyTime;
732
+ } else {
733
+ rb_raise(rb_eArgError, ":time_format must be :unix, :unix_zone, :xmlschema, or :ruby.");
734
+ }
735
+ } else if (escape_mode_sym == k) {
736
+ if (newline_sym == v) {
737
+ copts->escape_mode = NLEsc;
738
+ } else if (json_sym == v) {
739
+ copts->escape_mode = JSONEsc;
740
+ } else if (slash_sym == v) {
741
+ copts->escape_mode = SlashEsc;
742
+ } else if (xss_safe_sym == v) {
743
+ copts->escape_mode = XSSEsc;
744
+ } else if (ascii_sym == v) {
745
+ copts->escape_mode = ASCIIEsc;
746
+ } else if (unicode_xss_sym == v) {
747
+ copts->escape_mode = JXEsc;
748
+ } else {
749
+ rb_raise(rb_eArgError, ":encoding must be :newline, :json, :xss_safe, :unicode_xss, or :ascii.");
750
+ }
751
+ } else if (bigdecimal_load_sym == k) {
752
+ if (Qnil == v) {
753
+ return ST_CONTINUE;
754
+ }
755
+
756
+ if (bigdecimal_sym == v || Qtrue == v) {
757
+ copts->bigdec_load = BigDec;
758
+ } else if (float_sym == v) {
759
+ copts->bigdec_load = FloatDec;
760
+ } else if (fast_sym == v) {
761
+ copts->bigdec_load = FastDec;
762
+ } else if (auto_sym == v || Qfalse == v) {
763
+ copts->bigdec_load = AutoDec;
764
+ } else {
765
+ rb_raise(rb_eArgError, ":bigdecimal_load must be :bigdecimal, :float, or :auto.");
766
+ }
767
+ } else if (compat_bigdecimal_sym == k) {
768
+ if (Qnil == v) {
769
+ return ST_CONTINUE;
770
+ }
771
+ copts->compat_bigdec = (Qtrue == v);
772
+ } else if (oj_decimal_class_sym == k) {
773
+ if (rb_cFloat == v) {
774
+ copts->compat_bigdec = false;
775
+ } else if (oj_bigdecimal_class == v) {
776
+ copts->compat_bigdec = true;
777
+ } else {
778
+ rb_raise(rb_eArgError, ":decimal_class must be BigDecimal or Float.");
779
+ }
780
+ } else if (create_id_sym == k) {
781
+ if (Qnil == v) {
782
+ if (oj_json_class != oj_default_options.create_id && NULL != copts->create_id) {
783
+ OJ_R_FREE((char *)oj_default_options.create_id);
784
+ }
785
+ copts->create_id = NULL;
786
+ copts->create_id_len = 0;
787
+ } else if (T_STRING == rb_type(v)) {
788
+ const char *str = StringValuePtr(v);
789
+
790
+ len = RSTRING_LEN(v);
791
+ if (len != copts->create_id_len || 0 != strcmp(copts->create_id, str)) {
792
+ copts->create_id = OJ_R_ALLOC_N(char, len + 1);
793
+ strcpy((char *)copts->create_id, str);
794
+ copts->create_id_len = len;
795
+ }
796
+ } else {
797
+ rb_raise(rb_eArgError, ":create_id must be string.");
798
+ }
799
+ } else if (oj_space_sym == k) {
800
+ if (Qnil == v) {
801
+ copts->dump_opts.after_size = 0;
802
+ *copts->dump_opts.after_sep = '\0';
803
+ } else {
804
+ rb_check_type(v, T_STRING);
805
+ if (sizeof(copts->dump_opts.after_sep) <= (len = RSTRING_LEN(v))) {
806
+ rb_raise(rb_eArgError,
807
+ "space string is limited to %lu characters.",
808
+ (unsigned long)sizeof(copts->dump_opts.after_sep));
809
+ }
810
+ strcpy(copts->dump_opts.after_sep, StringValuePtr(v));
811
+ copts->dump_opts.after_size = (uint8_t)len;
812
+ }
813
+ } else if (oj_space_before_sym == k) {
814
+ if (Qnil == v) {
815
+ copts->dump_opts.before_size = 0;
816
+ *copts->dump_opts.before_sep = '\0';
817
+ } else {
818
+ rb_check_type(v, T_STRING);
819
+ if (sizeof(copts->dump_opts.before_sep) <= (len = RSTRING_LEN(v))) {
820
+ rb_raise(rb_eArgError,
821
+ "sapce_before string is limited to %lu characters.",
822
+ (unsigned long)sizeof(copts->dump_opts.before_sep));
823
+ }
824
+ strcpy(copts->dump_opts.before_sep, StringValuePtr(v));
825
+ copts->dump_opts.before_size = (uint8_t)len;
826
+ }
827
+ } else if (oj_object_nl_sym == k) {
828
+ if (Qnil == v) {
829
+ copts->dump_opts.hash_size = 0;
830
+ *copts->dump_opts.hash_nl = '\0';
831
+ } else {
832
+ rb_check_type(v, T_STRING);
833
+ if (sizeof(copts->dump_opts.hash_nl) <= (len = RSTRING_LEN(v))) {
834
+ rb_raise(rb_eArgError,
835
+ "object_nl string is limited to %lu characters.",
836
+ (unsigned long)sizeof(copts->dump_opts.hash_nl));
837
+ }
838
+ strcpy(copts->dump_opts.hash_nl, StringValuePtr(v));
839
+ copts->dump_opts.hash_size = (uint8_t)len;
840
+ }
841
+ } else if (oj_array_nl_sym == k) {
842
+ if (Qnil == v) {
843
+ copts->dump_opts.array_size = 0;
844
+ *copts->dump_opts.array_nl = '\0';
845
+ } else {
846
+ rb_check_type(v, T_STRING);
847
+ if (sizeof(copts->dump_opts.array_nl) <= (len = RSTRING_LEN(v))) {
848
+ rb_raise(rb_eArgError,
849
+ "array_nl string is limited to %lu characters.",
850
+ (unsigned long)sizeof(copts->dump_opts.array_nl));
851
+ }
852
+ strcpy(copts->dump_opts.array_nl, StringValuePtr(v));
853
+ copts->dump_opts.array_size = (uint8_t)len;
854
+ }
855
+ } else if (nan_sym == k) {
856
+ if (Qnil == v) {
857
+ return ST_CONTINUE;
858
+ }
859
+ if (null_sym == v) {
860
+ copts->dump_opts.nan_dump = NullNan;
861
+ } else if (huge_sym == v) {
862
+ copts->dump_opts.nan_dump = HugeNan;
863
+ } else if (word_sym == v) {
864
+ copts->dump_opts.nan_dump = WordNan;
865
+ } else if (raise_sym == v) {
866
+ copts->dump_opts.nan_dump = RaiseNan;
867
+ } else if (auto_sym == v) {
868
+ copts->dump_opts.nan_dump = AutoNan;
869
+ } else {
870
+ rb_raise(rb_eArgError, ":nan must be :null, :huge, :word, :raise, or :auto.");
871
+ }
872
+ } else if (omit_nil_sym == k) {
873
+ if (Qnil == v) {
874
+ return ST_CONTINUE;
875
+ }
876
+ if (Qtrue == v) {
877
+ copts->dump_opts.omit_nil = true;
878
+ } else if (Qfalse == v) {
879
+ copts->dump_opts.omit_nil = false;
880
+ } else {
881
+ rb_raise(rb_eArgError, ":omit_nil must be true or false.");
882
+ }
883
+ } else if (omit_null_byte_sym == k) {
884
+ if (Qnil == v) {
885
+ return ST_CONTINUE;
886
+ }
887
+ if (Qtrue == v) {
888
+ copts->dump_opts.omit_null_byte = true;
889
+ } else if (Qfalse == v) {
890
+ copts->dump_opts.omit_null_byte = false;
891
+ } else {
892
+ rb_raise(rb_eArgError, ":omit_null_byte must be true or false.");
893
+ }
894
+ } else if (oj_ascii_only_sym == k) {
895
+ // This is here only for backwards compatibility with the original Oj.
896
+ if (Qtrue == v) {
897
+ copts->escape_mode = ASCIIEsc;
898
+ } else if (Qfalse == v) {
899
+ copts->escape_mode = JSONEsc;
900
+ }
901
+ } else if (oj_hash_class_sym == k) {
902
+ if (Qnil == v) {
903
+ copts->hash_class = Qnil;
904
+ } else {
905
+ rb_check_type(v, T_CLASS);
906
+ copts->hash_class = v;
907
+ }
908
+ } else if (oj_object_class_sym == k) {
909
+ if (Qnil == v) {
910
+ copts->hash_class = Qnil;
911
+ } else {
912
+ rb_check_type(v, T_CLASS);
913
+ copts->hash_class = v;
914
+ }
915
+ } else if (oj_array_class_sym == k) {
916
+ if (Qnil == v) {
917
+ copts->array_class = Qnil;
918
+ } else {
919
+ rb_check_type(v, T_CLASS);
920
+ copts->array_class = v;
921
+ }
922
+ } else if (ignore_sym == k) {
923
+ OJ_R_FREE(copts->ignore);
924
+ copts->ignore = NULL;
925
+ if (Qnil != v) {
926
+ int cnt;
927
+
928
+ rb_check_type(v, T_ARRAY);
929
+ cnt = (int)RARRAY_LEN(v);
930
+ if (0 < cnt) {
931
+ int i;
932
+
933
+ copts->ignore = OJ_R_ALLOC_N(VALUE, cnt + 1);
934
+ for (i = 0; i < cnt; i++) {
935
+ copts->ignore[i] = RARRAY_AREF(v, i);
936
+ }
937
+ copts->ignore[i] = Qnil;
938
+ }
939
+ }
940
+ } else if (integer_range_sym == k) {
941
+ if (Qnil == v) {
942
+ return ST_CONTINUE;
943
+ }
944
+ if (rb_obj_class(v) == rb_cRange) {
945
+ VALUE min = rb_funcall(v, oj_begin_id, 0);
946
+ VALUE max = rb_funcall(v, oj_end_id, 0);
947
+
948
+ if (TYPE(min) != T_FIXNUM || TYPE(max) != T_FIXNUM) {
949
+ rb_raise(rb_eArgError, ":integer_range range bounds is not Fixnum.");
950
+ }
951
+
952
+ copts->int_range_min = FIX2LONG(min);
953
+ copts->int_range_max = FIX2LONG(max);
954
+ } else if (Qfalse != v) {
955
+ rb_raise(rb_eArgError, ":integer_range must be a range of Fixnum.");
956
+ }
957
+ } else if (symbol_keys_sym == k || oj_symbolize_names_sym == k) {
958
+ if (Qnil == v) {
959
+ return ST_CONTINUE;
960
+ }
961
+ copts->sym_key = (Qtrue == v) ? Yes : No;
962
+
963
+ } else if (oj_max_nesting_sym == k) {
964
+ if (Qtrue == v) {
965
+ copts->dump_opts.max_depth = 100;
966
+ } else if (Qfalse == v || Qnil == v) {
967
+ copts->dump_opts.max_depth = MAX_DEPTH;
968
+ } else if (T_FIXNUM == rb_type(v)) {
969
+ copts->dump_opts.max_depth = NUM2INT(v);
970
+ if (0 >= copts->dump_opts.max_depth) {
971
+ copts->dump_opts.max_depth = MAX_DEPTH;
972
+ }
973
+ }
974
+ } else if (float_format_sym == k) {
975
+ rb_check_type(v, T_STRING);
976
+ if (6 < (int)RSTRING_LEN(v)) {
977
+ rb_raise(rb_eArgError, ":float_format must be 6 bytes or less.");
978
+ }
979
+ strncpy(copts->float_fmt, RSTRING_PTR(v), (size_t)RSTRING_LEN(v));
980
+ copts->float_fmt[RSTRING_LEN(v)] = '\0';
744
981
  }
745
- if (Qtrue == rb_funcall(ropts, oj_has_key_id, 1, oj_array_class_sym)) {
746
- if (Qnil == (v = rb_hash_lookup(ropts, oj_array_class_sym))) {
747
- copts->array_class = Qnil;
748
- } else {
749
- rb_check_type(v, T_CLASS);
750
- copts->array_class = v;
751
- }
982
+ return ST_CONTINUE;
983
+ }
984
+
985
+ void oj_parse_options(VALUE ropts, Options copts) {
986
+ if (T_HASH != rb_type(ropts)) {
987
+ return;
752
988
  }
989
+ rb_hash_foreach(ropts, parse_options_cb, (VALUE)copts);
753
990
  oj_parse_opt_match_string(&copts->str_rx, ropts);
754
- if (Qtrue == rb_funcall(ropts, oj_has_key_id, 1, ignore_sym)) {
755
- xfree(copts->ignore);
756
- copts->ignore = NULL;
757
- if (Qnil != (v = rb_hash_lookup(ropts, ignore_sym))) {
758
- int cnt;
759
-
760
- rb_check_type(v, T_ARRAY);
761
- cnt = (int)RARRAY_LEN(v);
762
- if (0 < cnt) {
763
- int i;
764
-
765
- copts->ignore = ALLOC_N(VALUE, cnt + 1);
766
- for (i = 0; i < cnt; i++) {
767
- copts->ignore[i] = rb_ary_entry(v, i);
768
- }
769
- copts->ignore[i] = Qnil;
770
- }
771
- }
772
- }
773
- if (Qnil != (v = rb_hash_lookup(ropts, integer_range_sym))) {
774
- if (TYPE(v) == T_STRUCT && rb_obj_class(v) == rb_cRange) {
775
- VALUE min = rb_funcall(v, oj_begin_id, 0);
776
- VALUE max = rb_funcall(v, oj_end_id, 0);
777
-
778
- if (TYPE(min) != T_FIXNUM || TYPE(max) != T_FIXNUM) {
779
- rb_raise(rb_eArgError, ":integer_range range bounds is not Fixnum.");
780
- }
781
-
782
- copts->int_range_min = FIX2LONG(min);
783
- copts->int_range_max = FIX2LONG(max);
784
- } else if (Qfalse != v) {
785
- rb_raise(rb_eArgError, ":integer_range must be a range of Fixnum.");
786
- }
787
- }
991
+
992
+ copts->dump_opts.use = (0 < copts->dump_opts.indent_size || 0 < copts->dump_opts.after_size ||
993
+ 0 < copts->dump_opts.before_size || 0 < copts->dump_opts.hash_size ||
994
+ 0 < copts->dump_opts.array_size);
995
+ return;
788
996
  }
789
997
 
790
- static int
791
- match_string_cb(VALUE key, VALUE value, VALUE rx) {
792
- RxClass rc = (RxClass)rx;
998
+ static int match_string_cb(VALUE key, VALUE value, VALUE rx) {
999
+ RxClass rc = (RxClass)rx;
793
1000
 
794
1001
  if (T_CLASS != rb_type(value)) {
795
- rb_raise(rb_eArgError, "for :match_string, the hash values must be a Class.");
1002
+ rb_raise(rb_eArgError, "for :match_string, the hash values must be a Class.");
796
1003
  }
797
1004
  switch (rb_type(key)) {
798
- case T_REGEXP:
799
- oj_rxclass_rappend(rc, key, value);
800
- break;
1005
+ case T_REGEXP: oj_rxclass_rappend(rc, key, value); break;
801
1006
  case T_STRING:
802
- if (0 != oj_rxclass_append(rc, StringValuePtr(key), value)) {
803
- rb_raise(rb_eArgError, "%s", rc->err);
804
- }
805
- break;
806
- default:
807
- rb_raise(rb_eArgError, "for :match_string, keys must either a String or RegExp.");
808
- break;
1007
+ if (0 != oj_rxclass_append(rc, StringValuePtr(key), value)) {
1008
+ rb_raise(rb_eArgError, "%s", rc->err);
1009
+ }
1010
+ break;
1011
+ default: rb_raise(rb_eArgError, "for :match_string, keys must either a String or RegExp."); break;
809
1012
  }
810
1013
  return ST_CONTINUE;
811
1014
  }
812
1015
 
813
- void
814
- oj_parse_opt_match_string(RxClass rc, VALUE ropts) {
815
- VALUE v;
1016
+ void oj_parse_opt_match_string(RxClass rc, VALUE ropts) {
1017
+ VALUE v;
816
1018
 
817
1019
  if (Qnil != (v = rb_hash_lookup(ropts, match_string_sym))) {
818
- rb_check_type(v, T_HASH);
819
- // Zero out rc. Pattern are not appended but override.
820
- rc->head = NULL;
821
- rc->tail = NULL;
822
- *rc->err = '\0';
823
- rb_hash_foreach(v, match_string_cb, (VALUE)rc);
1020
+ rb_check_type(v, T_HASH);
1021
+ // Zero out rc. Pattern are not appended but override.
1022
+ rc->head = NULL;
1023
+ rc->tail = NULL;
1024
+ *rc->err = '\0';
1025
+ rb_hash_foreach(v, match_string_cb, (VALUE)rc);
824
1026
  }
825
1027
  }
826
1028
 
@@ -856,54 +1058,50 @@ oj_parse_opt_match_string(RxClass rc, VALUE ropts) {
856
1058
  *
857
1059
  * Returns [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_]
858
1060
  */
859
- static VALUE
860
- load(int argc, VALUE *argv, VALUE self) {
861
- Mode mode = oj_default_options.mode;
1061
+ static VALUE load(int argc, VALUE *argv, VALUE self) {
1062
+ Mode mode = oj_default_options.mode;
862
1063
 
863
1064
  if (1 > argc) {
864
- rb_raise(rb_eArgError, "Wrong number of arguments to load().");
1065
+ rb_raise(rb_eArgError, "Wrong number of arguments to load().");
865
1066
  }
866
1067
  if (2 <= argc) {
867
- VALUE ropts = argv[1];
868
- VALUE v;
869
-
870
- if (Qnil != ropts || CompatMode != mode) {
871
- Check_Type(ropts, T_HASH);
872
- if (Qnil != (v = rb_hash_lookup(ropts, mode_sym))) {
873
- if (object_sym == v) {
874
- mode = ObjectMode;
875
- } else if (strict_sym == v) {
876
- mode = StrictMode;
877
- } else if (compat_sym == v || json_sym == v) {
878
- mode = CompatMode;
879
- } else if (null_sym == v) {
880
- mode = NullMode;
881
- } else if (custom_sym == v) {
882
- mode = CustomMode;
883
- } else if (rails_sym == v) {
884
- mode = RailsMode;
885
- } else if (wab_sym == v) {
886
- mode = WabMode;
887
- } else {
888
- rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, :null, :custom, :rails, or :wab.");
889
- }
890
- }
891
- }
1068
+ VALUE ropts = argv[1];
1069
+ VALUE v;
1070
+
1071
+ if (Qnil != ropts || CompatMode != mode) {
1072
+ Check_Type(ropts, T_HASH);
1073
+ if (Qnil != (v = rb_hash_lookup(ropts, mode_sym))) {
1074
+ if (object_sym == v) {
1075
+ mode = ObjectMode;
1076
+ } else if (strict_sym == v) {
1077
+ mode = StrictMode;
1078
+ } else if (compat_sym == v || json_sym == v) {
1079
+ mode = CompatMode;
1080
+ } else if (null_sym == v) {
1081
+ mode = NullMode;
1082
+ } else if (custom_sym == v) {
1083
+ mode = CustomMode;
1084
+ } else if (rails_sym == v) {
1085
+ mode = RailsMode;
1086
+ } else if (wab_sym == v) {
1087
+ mode = WabMode;
1088
+ } else {
1089
+ rb_raise(rb_eArgError,
1090
+ ":mode must be :object, :strict, :compat, :null, :custom, :rails, or "
1091
+ ":wab.");
1092
+ }
1093
+ }
1094
+ }
892
1095
  }
893
1096
  switch (mode) {
894
1097
  case StrictMode:
895
- case NullMode:
896
- return oj_strict_parse(argc, argv, self);
1098
+ case NullMode: return oj_strict_parse(argc, argv, self);
897
1099
  case CompatMode:
898
- case RailsMode:
899
- return oj_compat_parse(argc, argv, self);
900
- case CustomMode:
901
- return oj_custom_parse(argc, argv, self);
902
- case WabMode:
903
- return oj_wab_parse(argc, argv, self);
1100
+ case RailsMode: return oj_compat_parse(argc, argv, self);
1101
+ case CustomMode: return oj_custom_parse(argc, argv, self);
1102
+ case WabMode: return oj_wab_parse(argc, argv, self);
904
1103
  case ObjectMode:
905
- default:
906
- break;
1104
+ default: break;
907
1105
  }
908
1106
  return oj_object_parse(argc, argv, self);
909
1107
  }
@@ -942,69 +1140,68 @@ load(int argc, VALUE *argv, VALUE self) {
942
1140
  *
943
1141
  * Returns [_Object_|_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_]
944
1142
  */
945
- static VALUE
946
- load_file(int argc, VALUE *argv, VALUE self) {
947
- char *path;
948
- int fd;
949
- Mode mode = oj_default_options.mode;
950
- struct _parseInfo pi;
1143
+ static VALUE load_file(int argc, VALUE *argv, VALUE self) {
1144
+ char *path;
1145
+ int fd;
1146
+ Mode mode = oj_default_options.mode;
1147
+ struct _parseInfo pi;
951
1148
 
952
1149
  if (1 > argc) {
953
- rb_raise(rb_eArgError, "Wrong number of arguments to load().");
1150
+ rb_raise(rb_eArgError, "Wrong number of arguments to load().");
954
1151
  }
955
- Check_Type(*argv, T_STRING);
1152
+ path = StringValuePtr(*argv);
956
1153
  parse_info_init(&pi);
957
- pi.options = oj_default_options;
958
- pi.handler = Qnil;
1154
+ pi.options = oj_default_options;
1155
+ pi.handler = Qnil;
959
1156
  pi.err_class = Qnil;
960
1157
  pi.max_depth = 0;
961
1158
  if (2 <= argc) {
962
- VALUE ropts = argv[1];
963
- VALUE v;
964
-
965
- Check_Type(ropts, T_HASH);
966
- if (Qnil != (v = rb_hash_lookup(ropts, mode_sym))) {
967
- if (object_sym == v) {
968
- mode = ObjectMode;
969
- } else if (strict_sym == v) {
970
- mode = StrictMode;
971
- } else if (compat_sym == v || json_sym == v) {
972
- mode = CompatMode;
973
- } else if (null_sym == v) {
974
- mode = NullMode;
975
- } else if (custom_sym == v) {
976
- mode = CustomMode;
977
- } else if (rails_sym == v) {
978
- mode = RailsMode;
979
- } else if (wab_sym == v) {
980
- mode = WabMode;
981
- } else {
982
- rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, :null, :custom, :rails, or :wab.");
983
- }
984
- }
1159
+ VALUE ropts = argv[1];
1160
+ VALUE v;
1161
+
1162
+ Check_Type(ropts, T_HASH);
1163
+ if (Qnil != (v = rb_hash_lookup(ropts, mode_sym))) {
1164
+ if (object_sym == v) {
1165
+ mode = ObjectMode;
1166
+ } else if (strict_sym == v) {
1167
+ mode = StrictMode;
1168
+ } else if (compat_sym == v || json_sym == v) {
1169
+ mode = CompatMode;
1170
+ } else if (null_sym == v) {
1171
+ mode = NullMode;
1172
+ } else if (custom_sym == v) {
1173
+ mode = CustomMode;
1174
+ } else if (rails_sym == v) {
1175
+ mode = RailsMode;
1176
+ } else if (wab_sym == v) {
1177
+ mode = WabMode;
1178
+ } else {
1179
+ rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, :null, :custom, :rails, or :wab.");
1180
+ }
1181
+ }
985
1182
  }
986
- path = StringValuePtr(*argv);
987
- if (0 == (fd = open(path, O_RDONLY))) {
988
- rb_raise(rb_eIOError, "%s", strerror(errno));
1183
+ #ifdef _WIN32
1184
+ {
1185
+ WCHAR *wide_path;
1186
+ wide_path = rb_w32_mbstr_to_wstr(CP_UTF8, path, -1, NULL);
1187
+ fd = rb_w32_wopen(wide_path, O_RDONLY);
1188
+ OJ_FREE(wide_path);
1189
+ }
1190
+ #else
1191
+ fd = open(path, O_RDONLY);
1192
+ #endif
1193
+ if (0 == fd) {
1194
+ rb_raise(rb_eIOError, "%s", strerror(errno));
989
1195
  }
990
1196
  switch (mode) {
991
1197
  case StrictMode:
992
- case NullMode:
993
- oj_set_strict_callbacks(&pi);
994
- return oj_pi_sparse(argc, argv, &pi, fd);
995
- case CustomMode:
996
- oj_set_custom_callbacks(&pi);
997
- return oj_pi_sparse(argc, argv, &pi, fd);
1198
+ case NullMode: oj_set_strict_callbacks(&pi); return oj_pi_sparse(argc, argv, &pi, fd);
1199
+ case CustomMode: oj_set_custom_callbacks(&pi); return oj_pi_sparse(argc, argv, &pi, fd);
998
1200
  case CompatMode:
999
- case RailsMode:
1000
- oj_set_compat_callbacks(&pi);
1001
- return oj_pi_sparse(argc, argv, &pi, fd);
1002
- case WabMode:
1003
- oj_set_wab_callbacks(&pi);
1004
- return oj_pi_sparse(argc, argv, &pi, fd);
1201
+ case RailsMode: oj_set_compat_callbacks(&pi); return oj_pi_sparse(argc, argv, &pi, fd);
1202
+ case WabMode: oj_set_wab_callbacks(&pi); return oj_pi_sparse(argc, argv, &pi, fd);
1005
1203
  case ObjectMode:
1006
- default:
1007
- break;
1204
+ default: break;
1008
1205
  }
1009
1206
  oj_set_object_callbacks(&pi);
1010
1207
 
@@ -1022,18 +1219,17 @@ load_file(int argc, VALUE *argv, VALUE self) {
1022
1219
  *
1023
1220
  * Returns [_Hash_|_Array_|_String_|_Fixnum_|_Bignum_|_BigDecimal_|_nil_|_True_|_False_]
1024
1221
  */
1025
- static VALUE
1026
- safe_load(VALUE self, VALUE doc) {
1027
- struct _parseInfo pi;
1028
- VALUE args[1];
1222
+ static VALUE safe_load(VALUE self, VALUE doc) {
1223
+ struct _parseInfo pi;
1224
+ VALUE args[1];
1029
1225
 
1030
1226
  parse_info_init(&pi);
1031
- pi.err_class = Qnil;
1032
- pi.max_depth = 0;
1033
- pi.options = oj_default_options;
1227
+ pi.err_class = Qnil;
1228
+ pi.max_depth = 0;
1229
+ pi.options = oj_default_options;
1034
1230
  pi.options.auto_define = No;
1035
- pi.options.sym_key = No;
1036
- pi.options.mode = StrictMode;
1231
+ pi.options.sym_key = No;
1232
+ pi.options.mode = StrictMode;
1037
1233
  oj_set_strict_callbacks(&pi);
1038
1234
  *args = doc;
1039
1235
 
@@ -1066,6 +1262,35 @@ safe_load(VALUE self, VALUE doc) {
1066
1262
  * - *io* [_IO__|_String_] IO Object to read from
1067
1263
  */
1068
1264
 
1265
+ struct dump_arg {
1266
+ struct _out *out;
1267
+ struct _options *copts;
1268
+ int argc;
1269
+ VALUE *argv;
1270
+ };
1271
+
1272
+ static VALUE dump_body(VALUE a) {
1273
+ volatile struct dump_arg *arg = (void *)a;
1274
+ VALUE rstr;
1275
+
1276
+ oj_dump_obj_to_json_using_params(*arg->argv, arg->copts, arg->out, arg->argc - 1, arg->argv + 1);
1277
+ if (0 == arg->out->buf) {
1278
+ rb_raise(rb_eNoMemError, "Not enough memory.");
1279
+ }
1280
+ rstr = rb_str_new2(arg->out->buf);
1281
+ rstr = oj_encode(rstr);
1282
+
1283
+ return rstr;
1284
+ }
1285
+
1286
+ static VALUE dump_ensure(VALUE a) {
1287
+ volatile struct dump_arg *arg = (void *)a;
1288
+
1289
+ oj_out_free(arg->out);
1290
+
1291
+ return Qnil;
1292
+ }
1293
+
1069
1294
  /* Document-method: dump
1070
1295
  * call-seq: dump(obj, options={})
1071
1296
  *
@@ -1073,40 +1298,34 @@ safe_load(VALUE self, VALUE doc) {
1073
1298
  * - *obj* [_Object_] Object to serialize as an JSON document String
1074
1299
  * - *options* [_Hash_] same as default_options
1075
1300
  */
1076
- static VALUE
1077
- dump(int argc, VALUE *argv, VALUE self) {
1078
- char buf[4096];
1079
- struct _out out;
1080
- struct _options copts = oj_default_options;
1081
- VALUE rstr;
1301
+ static VALUE dump(int argc, VALUE *argv, VALUE self) {
1302
+ struct dump_arg arg;
1303
+ struct _out out;
1304
+ struct _options copts = oj_default_options;
1082
1305
 
1083
1306
  if (1 > argc) {
1084
- rb_raise(rb_eArgError, "wrong number of arguments (0 for 1).");
1307
+ rb_raise(rb_eArgError, "wrong number of arguments (0 for 1).");
1085
1308
  }
1086
1309
  if (CompatMode == copts.mode) {
1087
- copts.dump_opts.nan_dump = WordNan;
1310
+ copts.dump_opts.nan_dump = WordNan;
1088
1311
  }
1089
1312
  if (2 == argc) {
1090
- oj_parse_options(argv[1], &copts);
1313
+ oj_parse_options(argv[1], &copts);
1091
1314
  }
1092
1315
  if (CompatMode == copts.mode && copts.escape_mode != ASCIIEsc) {
1093
- copts.escape_mode = JSONEsc;
1094
- }
1095
- out.buf = buf;
1096
- out.end = buf + sizeof(buf) - 10;
1097
- out.allocated = false;
1098
- out.omit_nil = copts.dump_opts.omit_nil;
1099
- out.caller = CALLER_DUMP;
1100
- oj_dump_obj_to_json_using_params(*argv, &copts, &out, argc - 1,argv + 1);
1101
- if (0 == out.buf) {
1102
- rb_raise(rb_eNoMemError, "Not enough memory.");
1103
- }
1104
- rstr = rb_str_new2(out.buf);
1105
- rstr = oj_encode(rstr);
1106
- if (out.allocated) {
1107
- xfree(out.buf);
1316
+ copts.escape_mode = JSONEsc;
1108
1317
  }
1109
- return rstr;
1318
+ arg.out = &out;
1319
+ arg.copts = &copts;
1320
+ arg.argc = argc;
1321
+ arg.argv = argv;
1322
+
1323
+ oj_out_init(arg.out);
1324
+
1325
+ arg.out->omit_nil = copts.dump_opts.omit_nil;
1326
+ arg.out->omit_null_byte = copts.dump_opts.omit_null_byte;
1327
+
1328
+ return rb_ensure(dump_body, (VALUE)&arg, dump_ensure, (VALUE)&arg);
1110
1329
  }
1111
1330
 
1112
1331
  /* Document-method: to_json
@@ -1116,8 +1335,12 @@ dump(int argc, VALUE *argv, VALUE self) {
1116
1335
  * will be called. The mode is set to :compat.
1117
1336
  * - *obj* [_Object_] Object to serialize as an JSON document String
1118
1337
  * - *options* [_Hash_]
1119
- * - *:max_nesting* [_boolean_] It true nesting is limited to 100. The option to detect circular references is available but is not compatible with the json gem., default is false
1120
- * - *:allow_nan* [_boolean_] If true non JSON compliant words such as Nan and Infinity will be used as appropriate, default is true.
1338
+ * - *:max_nesting* [_Fixnum_|_boolean_] It true nesting is limited to 100.
1339
+ * If a Fixnum nesting is set to the provided value. The option to detect
1340
+ * circular references is available but is not compatible with the json gem.,
1341
+ * default is false or unlimited.
1342
+ * - *:allow_nan* [_boolean_] If true non JSON compliant words such as Nan and
1343
+ * Infinity will be used as appropriate, default is true.
1121
1344
  * - *:quirks_mode* [_boolean_] Allow single JSON values instead of documents, default is true (allow).
1122
1345
  * - *:indent* [_String_|_nil_] String to use for indentation, overriding the indent option if not nil.
1123
1346
  * - *:space* [_String_|_nil_] String to use for the space after the colon in JSON object fields.
@@ -1128,39 +1351,38 @@ dump(int argc, VALUE *argv, VALUE self) {
1128
1351
  *
1129
1352
  * Returns [_String_] the encoded JSON.
1130
1353
  */
1131
- static VALUE
1132
- to_json(int argc, VALUE *argv, VALUE self) {
1133
- char buf[4096];
1134
- struct _out out;
1135
- struct _options copts = oj_default_options;
1136
- VALUE rstr;
1354
+ static VALUE to_json(int argc, VALUE *argv, VALUE self) {
1355
+ struct _out out;
1356
+ struct _options copts = oj_default_options;
1357
+ VALUE rstr;
1137
1358
 
1138
1359
  if (1 > argc) {
1139
- rb_raise(rb_eArgError, "wrong number of arguments (0 for 1).");
1360
+ rb_raise(rb_eArgError, "wrong number of arguments (0 for 1).");
1140
1361
  }
1141
- copts.escape_mode = JXEsc;
1362
+ copts.escape_mode = JXEsc;
1142
1363
  copts.dump_opts.nan_dump = RaiseNan;
1143
1364
  if (2 == argc) {
1144
- oj_parse_mimic_dump_options(argv[1], &copts);
1365
+ oj_parse_mimic_dump_options(argv[1], &copts);
1145
1366
  }
1146
- copts.mode = CompatMode;
1367
+ copts.mode = CompatMode;
1147
1368
  copts.to_json = Yes;
1148
- out.buf = buf;
1149
- out.end = buf + sizeof(buf) - 10;
1150
- out.allocated = false;
1151
- out.omit_nil = copts.dump_opts.omit_nil;
1369
+
1370
+ oj_out_init(&out);
1371
+
1372
+ out.omit_nil = copts.dump_opts.omit_nil;
1373
+ out.omit_null_byte = copts.dump_opts.omit_null_byte;
1152
1374
  // For obj.to_json or generate nan is not allowed but if called from dump
1153
1375
  // it is.
1154
1376
  oj_dump_obj_to_json_using_params(*argv, &copts, &out, argc - 1, argv + 1);
1155
1377
 
1156
1378
  if (0 == out.buf) {
1157
- rb_raise(rb_eNoMemError, "Not enough memory.");
1379
+ rb_raise(rb_eNoMemError, "Not enough memory.");
1158
1380
  }
1159
1381
  rstr = rb_str_new2(out.buf);
1160
1382
  rstr = oj_encode(rstr);
1161
- if (out.allocated) {
1162
- xfree(out.buf);
1163
- }
1383
+
1384
+ oj_out_free(&out);
1385
+
1164
1386
  return rstr;
1165
1387
  }
1166
1388
 
@@ -1170,18 +1392,16 @@ to_json(int argc, VALUE *argv, VALUE self) {
1170
1392
  * Dumps an Object to the specified file.
1171
1393
  * - *file* [_String_] _path file path to write the JSON document to
1172
1394
  * - *obj* [_Object_] Object to serialize as an JSON document String
1173
- * - *options* [_Hash_] formating options
1395
+ * - *options* [_Hash_] formatting options
1174
1396
  * - *:indent* [_Fixnum_] format expected
1175
1397
  * - *:circular* [_Boolean_] allow circular references, default: false
1176
1398
  */
1177
- static VALUE
1178
- to_file(int argc, VALUE *argv, VALUE self) {
1179
- struct _options copts = oj_default_options;
1399
+ static VALUE to_file(int argc, VALUE *argv, VALUE self) {
1400
+ struct _options copts = oj_default_options;
1180
1401
 
1181
1402
  if (3 == argc) {
1182
- oj_parse_options(argv[2], &copts);
1403
+ oj_parse_options(argv[2], &copts);
1183
1404
  }
1184
- Check_Type(*argv, T_STRING);
1185
1405
  oj_write_obj_to_file(argv[1], StringValuePtr(*argv), &copts);
1186
1406
 
1187
1407
  return Qnil;
@@ -1193,16 +1413,15 @@ to_file(int argc, VALUE *argv, VALUE self) {
1193
1413
  * Dumps an Object to the specified IO stream.
1194
1414
  * - *io* [_IO_] IO stream to write the JSON document to
1195
1415
  * - *obj* [_Object_] Object to serialize as an JSON document String
1196
- * - *options* [_Hash_] formating options
1416
+ * - *options* [_Hash_] formatting options
1197
1417
  * - *:indent* [_Fixnum_] format expected
1198
1418
  * - *:circular* [_Boolean_] allow circular references, default: false
1199
1419
  */
1200
- static VALUE
1201
- to_stream(int argc, VALUE *argv, VALUE self) {
1202
- struct _options copts = oj_default_options;
1420
+ static VALUE to_stream(int argc, VALUE *argv, VALUE self) {
1421
+ struct _options copts = oj_default_options;
1203
1422
 
1204
1423
  if (3 == argc) {
1205
- oj_parse_options(argv[2], &copts);
1424
+ oj_parse_options(argv[2], &copts);
1206
1425
  }
1207
1426
  oj_write_obj_to_stream(argv[1], *argv, &copts);
1208
1427
 
@@ -1220,25 +1439,23 @@ to_stream(int argc, VALUE *argv, VALUE self) {
1220
1439
  *
1221
1440
  * - *clas* [_Class__|_Module_] Class or Module to be made special
1222
1441
  * - *create_object* [_Object_] object to call the create method on
1223
- * - *create_method* [_Symbol_] method on the clas that will create a new instance of the clas when given all the member values in the order specified.
1224
- * - *members* [_Symbol__|_String_] methods used to get the member values from instances of the clas.
1442
+ * - *create_method* [_Symbol_] method on the clas that will create a new instance
1443
+ * of the clas when given all the member values in the order specified.
1444
+ * - *members* [_Symbol__|_String_] methods used to get the member values from
1445
+ * instances of the clas.
1225
1446
  */
1226
- static VALUE
1227
- register_odd(int argc, VALUE *argv, VALUE self) {
1447
+ static VALUE register_odd(int argc, VALUE *argv, VALUE self) {
1228
1448
  if (3 > argc) {
1229
- rb_raise(rb_eArgError, "incorrect number of arguments.");
1449
+ rb_raise(rb_eArgError, "incorrect number of arguments.");
1230
1450
  }
1231
1451
  switch (rb_type(*argv)) {
1232
1452
  case T_CLASS:
1233
- case T_MODULE:
1234
- break;
1235
- default:
1236
- rb_raise(rb_eTypeError, "expected a class or module.");
1237
- break;
1453
+ case T_MODULE: break;
1454
+ default: rb_raise(rb_eTypeError, "expected a class or module."); break;
1238
1455
  }
1239
1456
  Check_Type(argv[2], T_SYMBOL);
1240
1457
  if (MAX_ODD_ARGS < argc - 2) {
1241
- rb_raise(rb_eArgError, "too many members.");
1458
+ rb_raise(rb_eArgError, "too many members.");
1242
1459
  }
1243
1460
  oj_reg_odd(argv[0], argv[1], argv[2], argc - 3, argv + 3, false);
1244
1461
 
@@ -1258,25 +1475,23 @@ register_odd(int argc, VALUE *argv, VALUE self) {
1258
1475
  *
1259
1476
  * - *clas* [_Class_|_Module_] Class or Module to be made special
1260
1477
  * - *create_object* [_Object_] object to call the create method on
1261
- * - *create_method* [_Symbol_] method on the clas that will create a new instance of the clas when given all the member values in the order specified.
1262
- * - *dump_method* [_Symbol_|_String_] method to call on the object being serialized to generate the raw JSON.
1478
+ * - *create_method* [_Symbol_] method on the clas that will create a new instance
1479
+ * of the clas when given all the member values in the order specified.
1480
+ * - *dump_method* [_Symbol_|_String_] method to call on the object being
1481
+ * serialized to generate the raw JSON.
1263
1482
  */
1264
- static VALUE
1265
- register_odd_raw(int argc, VALUE *argv, VALUE self) {
1483
+ static VALUE register_odd_raw(int argc, VALUE *argv, VALUE self) {
1266
1484
  if (3 > argc) {
1267
- rb_raise(rb_eArgError, "incorrect number of arguments.");
1485
+ rb_raise(rb_eArgError, "incorrect number of arguments.");
1268
1486
  }
1269
1487
  switch (rb_type(*argv)) {
1270
1488
  case T_CLASS:
1271
- case T_MODULE:
1272
- break;
1273
- default:
1274
- rb_raise(rb_eTypeError, "expected a class or module.");
1275
- break;
1489
+ case T_MODULE: break;
1490
+ default: rb_raise(rb_eTypeError, "expected a class or module."); break;
1276
1491
  }
1277
1492
  Check_Type(argv[2], T_SYMBOL);
1278
1493
  if (MAX_ODD_ARGS < argc - 2) {
1279
- rb_raise(rb_eArgError, "too many members.");
1494
+ rb_raise(rb_eArgError, "too many members.");
1280
1495
  }
1281
1496
  oj_reg_odd(argv[0], argv[1], argv[2], 1, argv + 3, true);
1282
1497
 
@@ -1322,7 +1537,7 @@ register_odd_raw(int argc, VALUE *argv, VALUE self) {
1322
1537
  *
1323
1538
  * Returns [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_]
1324
1539
  */
1325
- extern VALUE oj_strict_parse(int argc, VALUE *argv, VALUE self);
1540
+ extern VALUE oj_strict_parse(int argc, VALUE *argv, VALUE self);
1326
1541
 
1327
1542
  /* Document-method: compat_load
1328
1543
  * call-seq: compat_load(json, options) { _|_obj, start, len_|_ }
@@ -1356,7 +1571,7 @@ extern VALUE oj_strict_parse(int argc, VALUE *argv, VALUE self);
1356
1571
  *
1357
1572
  * Returns [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_]
1358
1573
  */
1359
- extern VALUE oj_compat_parse(int argc, VALUE *argv, VALUE self);
1574
+ extern VALUE oj_compat_parse(int argc, VALUE *argv, VALUE self);
1360
1575
 
1361
1576
  /* Document-method: object_load
1362
1577
  * call-seq: object_load(json, options) { _|_obj, start, len_|_ }
@@ -1386,7 +1601,7 @@ extern VALUE oj_compat_parse(int argc, VALUE *argv, VALUE self);
1386
1601
  *
1387
1602
  * Returns [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_]
1388
1603
  */
1389
- extern VALUE oj_object_parse(int argc, VALUE *argv, VALUE self);
1604
+ extern VALUE oj_object_parse(int argc, VALUE *argv, VALUE self);
1390
1605
 
1391
1606
  /* Document-method: wab_load
1392
1607
  * call-seq: wab_load(json, options) { _|_obj, start, len_|_ }
@@ -1421,7 +1636,7 @@ extern VALUE oj_object_parse(int argc, VALUE *argv, VALUE self);
1421
1636
  *
1422
1637
  * Returns [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_]
1423
1638
  */
1424
- extern VALUE oj_wab_parse(int argc, VALUE *argv, VALUE self);
1639
+ extern VALUE oj_wab_parse(int argc, VALUE *argv, VALUE self);
1425
1640
 
1426
1641
  /* Document-method: add_to_json
1427
1642
  * call-seq: add_to_json(*args)
@@ -1438,7 +1653,7 @@ extern VALUE oj_wab_parse(int argc, VALUE *argv, VALUE self);
1438
1653
  *
1439
1654
  * - *args( [_Class_] zero or more classes to optimize.
1440
1655
  */
1441
- extern VALUE oj_add_to_json(int argc, VALUE *argv, VALUE self);
1656
+ extern VALUE oj_add_to_json(int argc, VALUE *argv, VALUE self);
1442
1657
 
1443
1658
  /* @!method remove_to_json(*args)
1444
1659
  *
@@ -1454,7 +1669,7 @@ extern VALUE oj_add_to_json(int argc, VALUE *argv, VALUE self);
1454
1669
  *
1455
1670
  * - *args* [_Class_] zero or more classes to optimize.
1456
1671
  */
1457
- extern VALUE oj_remove_to_json(int argc, VALUE *argv, VALUE self);
1672
+ extern VALUE oj_remove_to_json(int argc, VALUE *argv, VALUE self);
1458
1673
 
1459
1674
  /* Document-method: mimic_JSON
1460
1675
  * call-seq: mimic_JSON()
@@ -1472,14 +1687,15 @@ extern VALUE oj_remove_to_json(int argc, VALUE *argv, VALUE self);
1472
1687
  *
1473
1688
  * Returns [_Module_] the JSON module.
1474
1689
  */
1475
- extern VALUE oj_define_mimic_json(int argc, VALUE *argv, VALUE self);
1690
+ extern VALUE oj_define_mimic_json(int argc, VALUE *argv, VALUE self);
1476
1691
 
1477
1692
  /* Document-method: generate
1478
1693
  * call-seq: generate(obj, opts=nil)
1479
1694
  *
1480
1695
  * Encode obj as a JSON String. The obj argument must be a Hash, Array, or
1481
1696
  * respond to to_h or to_json. Options other than those listed such as
1482
- * +:allow_nan+ or +:max_nesting+ are ignored.
1697
+ * +:allow_nan+ or +:max_nesting+ are ignored. Calling this method will call
1698
+ * Oj.mimic_JSON if it is not already called.
1483
1699
  *
1484
1700
  * - *obj* [_Object__|_Hash_|_Array_] object to convert to a JSON String
1485
1701
  * - *opts* [_Hash_] options
@@ -1488,36 +1704,55 @@ extern VALUE oj_define_mimic_json(int argc, VALUE *argv, VALUE self);
1488
1704
  * - *:space_before* [_String_] String placed before a : delimiter
1489
1705
  * - *:object_nl* [_String_] String placed after a JSON object
1490
1706
  * - *:array_nl* [_String_] String placed after a JSON array
1491
- * - *:ascii_only* [_Boolean_] if not nil or false then use only ascii characters in the output. Note JSON.generate does support this even if it is not documented.
1707
+ * - *:ascii_only* [_Boolean_] if not nil or false then use only ascii characters
1708
+ * in the output. Note JSON.generate does support this even if it is not documented.
1492
1709
  *
1493
1710
  * Returns [_String_]generated JSON.
1494
1711
  */
1495
- extern VALUE oj_mimic_generate(int argc, VALUE *argv, VALUE self);
1712
+ extern VALUE oj_mimic_generate(int argc, VALUE *argv, VALUE self);
1496
1713
 
1497
1714
  /* Document-module: Oj.optimize_rails()
1498
1715
  *
1499
1716
  * Sets the Oj as the Rails encoder and decoder. Oj::Rails.optimize is also
1500
1717
  * called.
1501
1718
  */
1502
- extern VALUE oj_optimize_rails(VALUE self);
1719
+ extern VALUE oj_optimize_rails(VALUE self);
1503
1720
 
1504
1721
  /*
1505
1722
  extern void oj_hash_test();
1506
-
1507
1723
  static VALUE
1508
1724
  hash_test(VALUE self) {
1509
1725
  oj_hash_test();
1510
1726
  return Qnil;
1511
1727
  }
1512
1728
  */
1513
-
1729
+ /*
1730
+ extern void oj_hash_sizes();
1514
1731
  static VALUE
1515
- protect_require(VALUE x) {
1732
+ hash_test(VALUE self) {
1733
+ oj_hash_sizes();
1734
+ return Qnil;
1735
+ }
1736
+ */
1737
+
1738
+ static VALUE protect_require(VALUE x) {
1516
1739
  rb_require("time");
1517
1740
  rb_require("bigdecimal");
1518
1741
  return Qnil;
1519
1742
  }
1520
1743
 
1744
+ extern void print_all_odds(const char *label);
1745
+
1746
+ static VALUE debug_odd(VALUE self, VALUE label) {
1747
+ print_all_odds(RSTRING_PTR(label));
1748
+ return Qnil;
1749
+ }
1750
+
1751
+ static VALUE mem_report(VALUE self) {
1752
+ oj_mem_report();
1753
+ return Qnil;
1754
+ }
1755
+
1521
1756
  /* Document-module: Oj
1522
1757
  *
1523
1758
  * Optimized JSON (Oj), as the name implies was written to provide speed
@@ -1527,8 +1762,8 @@ protect_require(VALUE x) {
1527
1762
  * global and options to methods allow additional behavior modifications. The
1528
1763
  * modes are:
1529
1764
  *
1530
- * - *:strict* mode will only allow the 7 basic JSON types to be serialized. Any other Object
1531
- * will raise an Exception.
1765
+ * - *:strict* mode will only allow the 7 basic JSON types to be serialized.
1766
+ * Any other Object will raise an Exception.
1532
1767
  *
1533
1768
  * - *:null* mode is similar to the :strict mode except any Object that is not
1534
1769
  * one of the JSON base types is replaced by a JSON null.
@@ -1546,13 +1781,19 @@ protect_require(VALUE x) {
1546
1781
  *
1547
1782
  * - *:wab* specifically for WAB data exchange.
1548
1783
  */
1549
- void
1550
- Init_oj() {
1551
- int err = 0;
1784
+ void Init_oj(void) {
1785
+ int err = 0;
1552
1786
 
1787
+ #if HAVE_RB_EXT_RACTOR_SAFE
1788
+ rb_ext_ractor_safe(true);
1789
+ #endif
1553
1790
  Oj = rb_define_module("Oj");
1791
+ rb_gc_register_address(&Oj);
1554
1792
 
1555
1793
  oj_cstack_class = rb_define_class_under(Oj, "CStack", rb_cObject);
1794
+ rb_gc_register_address(&oj_cstack_class);
1795
+
1796
+ rb_undef_alloc_func(oj_cstack_class);
1556
1797
 
1557
1798
  oj_string_writer_init();
1558
1799
  oj_stream_writer_init();
@@ -1561,9 +1802,11 @@ Init_oj() {
1561
1802
  // On Rubinius the require fails but can be done from a ruby file.
1562
1803
  rb_protect(protect_require, Qnil, &err);
1563
1804
  rb_require("stringio");
1564
- oj_utf8_encoding = rb_enc_find("UTF-8");
1805
+ oj_utf8_encoding_index = rb_enc_find_index("UTF-8");
1806
+ oj_utf8_encoding = rb_enc_from_index(oj_utf8_encoding_index);
1565
1807
 
1566
- //rb_define_module_function(Oj, "hash_test", hash_test, 0);
1808
+ // rb_define_module_function(Oj, "hash_test", hash_test, 0);
1809
+ rb_define_module_function(Oj, "debug_odd", debug_odd, 1);
1567
1810
 
1568
1811
  rb_define_module_function(Oj, "default_options", get_def_opts, 0);
1569
1812
  rb_define_module_function(Oj, "default_options=", set_def_opts, 1);
@@ -1597,50 +1840,52 @@ Init_oj() {
1597
1840
 
1598
1841
  rb_define_module_function(Oj, "optimize_rails", oj_optimize_rails, 0);
1599
1842
 
1600
- oj_add_value_id = rb_intern("add_value");
1843
+ rb_define_module_function(Oj, "mem_report", mem_report, 0);
1844
+
1845
+ oj_add_value_id = rb_intern("add_value");
1601
1846
  oj_array_append_id = rb_intern("array_append");
1602
- oj_array_end_id = rb_intern("array_end");
1603
- oj_array_start_id = rb_intern("array_start");
1604
- oj_as_json_id = rb_intern("as_json");
1605
- oj_begin_id = rb_intern("begin");
1606
- oj_bigdecimal_id = rb_intern("BigDecimal");
1607
- oj_end_id = rb_intern("end");
1608
- oj_error_id = rb_intern("error");
1609
- oj_exclude_end_id = rb_intern("exclude_end?");
1610
- oj_file_id = rb_intern("file?");
1611
- oj_fileno_id = rb_intern("fileno");
1612
- oj_ftype_id = rb_intern("ftype");
1613
- oj_has_key_id = rb_intern("has_key?");
1614
- oj_hash_end_id = rb_intern("hash_end");
1615
- oj_hash_key_id = rb_intern("hash_key");
1616
- oj_hash_set_id = rb_intern("hash_set");
1617
- oj_hash_start_id = rb_intern("hash_start");
1618
- oj_iconv_id = rb_intern("iconv");
1619
- oj_instance_variables_id = rb_intern("instance_variables");
1620
- oj_json_create_id = rb_intern("json_create");
1621
- oj_length_id = rb_intern("length");
1622
- oj_new_id = rb_intern("new");
1623
- oj_parse_id = rb_intern("parse");
1624
- oj_pos_id = rb_intern("pos");
1625
- oj_raw_json_id = rb_intern("raw_json");
1626
- oj_read_id = rb_intern("read");
1627
- oj_readpartial_id = rb_intern("readpartial");
1628
- oj_replace_id = rb_intern("replace");
1629
- oj_stat_id = rb_intern("stat");
1630
- oj_string_id = rb_intern("string");
1631
- oj_to_h_id = rb_intern("to_h");
1632
- oj_to_hash_id = rb_intern("to_hash");
1633
- oj_to_json_id = rb_intern("to_json");
1634
- oj_to_s_id = rb_intern("to_s");
1635
- oj_to_sym_id = rb_intern("to_sym");
1636
- oj_to_time_id = rb_intern("to_time");
1637
- oj_tv_nsec_id = rb_intern("tv_nsec");
1638
- oj_tv_sec_id = rb_intern("tv_sec");
1639
- oj_tv_usec_id = rb_intern("tv_usec");
1640
- oj_utc_id = rb_intern("utc");
1641
- oj_utc_offset_id = rb_intern("utc_offset");
1642
- oj_utcq_id = rb_intern("utc?");
1643
- oj_write_id = rb_intern("write");
1847
+ oj_array_end_id = rb_intern("array_end");
1848
+ oj_array_start_id = rb_intern("array_start");
1849
+ oj_as_json_id = rb_intern("as_json");
1850
+ oj_begin_id = rb_intern("begin");
1851
+ oj_bigdecimal_id = rb_intern("BigDecimal");
1852
+ oj_end_id = rb_intern("end");
1853
+ oj_eofq_id = rb_intern("eof?");
1854
+ oj_error_id = rb_intern("error");
1855
+ oj_exclude_end_id = rb_intern("exclude_end?");
1856
+ oj_file_id = rb_intern("file?");
1857
+ oj_fileno_id = rb_intern("fileno");
1858
+ oj_ftype_id = rb_intern("ftype");
1859
+ oj_hash_end_id = rb_intern("hash_end");
1860
+ oj_hash_key_id = rb_intern("hash_key");
1861
+ oj_hash_set_id = rb_intern("hash_set");
1862
+ oj_hash_start_id = rb_intern("hash_start");
1863
+ oj_iconv_id = rb_intern("iconv");
1864
+ oj_json_create_id = rb_intern("json_create");
1865
+ oj_length_id = rb_intern("length");
1866
+ oj_new_id = rb_intern("new");
1867
+ oj_parse_id = rb_intern("parse");
1868
+ oj_plus_id = rb_intern("+");
1869
+ oj_pos_id = rb_intern("pos");
1870
+ oj_raw_json_id = rb_intern("raw_json");
1871
+ oj_read_id = rb_intern("read");
1872
+ oj_readpartial_id = rb_intern("readpartial");
1873
+ oj_replace_id = rb_intern("replace");
1874
+ oj_stat_id = rb_intern("stat");
1875
+ oj_string_id = rb_intern("string");
1876
+ oj_to_h_id = rb_intern("to_h");
1877
+ oj_to_hash_id = rb_intern("to_hash");
1878
+ oj_to_json_id = rb_intern("to_json");
1879
+ oj_to_s_id = rb_intern("to_s");
1880
+ oj_to_sym_id = rb_intern("to_sym");
1881
+ oj_to_time_id = rb_intern("to_time");
1882
+ oj_tv_nsec_id = rb_intern("tv_nsec");
1883
+ oj_tv_sec_id = rb_intern("tv_sec");
1884
+ oj_tv_usec_id = rb_intern("tv_usec");
1885
+ oj_utc_id = rb_intern("utc");
1886
+ oj_utc_offset_id = rb_intern("utc_offset");
1887
+ oj_utcq_id = rb_intern("utc?");
1888
+ oj_write_id = rb_intern("write");
1644
1889
 
1645
1890
  rb_require("oj/bag");
1646
1891
  rb_require("oj/error");
@@ -1649,85 +1894,175 @@ Init_oj() {
1649
1894
  rb_require("oj/schandler");
1650
1895
 
1651
1896
  oj_bag_class = rb_const_get_at(Oj, rb_intern("Bag"));
1897
+ rb_gc_register_mark_object(oj_bag_class);
1652
1898
  oj_bigdecimal_class = rb_const_get(rb_cObject, rb_intern("BigDecimal"));
1899
+ rb_gc_register_mark_object(oj_bigdecimal_class);
1653
1900
  oj_date_class = rb_const_get(rb_cObject, rb_intern("Date"));
1901
+ rb_gc_register_mark_object(oj_date_class);
1654
1902
  oj_datetime_class = rb_const_get(rb_cObject, rb_intern("DateTime"));
1903
+ rb_gc_register_mark_object(oj_datetime_class);
1655
1904
  oj_enumerable_class = rb_const_get(rb_cObject, rb_intern("Enumerable"));
1905
+ rb_gc_register_mark_object(oj_enumerable_class);
1656
1906
  oj_parse_error_class = rb_const_get_at(Oj, rb_intern("ParseError"));
1907
+ rb_gc_register_mark_object(oj_parse_error_class);
1657
1908
  oj_stringio_class = rb_const_get(rb_cObject, rb_intern("StringIO"));
1909
+ rb_gc_register_mark_object(oj_stringio_class);
1658
1910
  oj_struct_class = rb_const_get(rb_cObject, rb_intern("Struct"));
1659
- oj_json_parser_error_class = rb_eEncodingError; // replaced if mimic is called
1660
- oj_json_generator_error_class = rb_eEncodingError; // replaced if mimic is called
1661
-
1662
- allow_blank_sym = ID2SYM(rb_intern("allow_blank")); rb_gc_register_address(&allow_blank_sym);
1663
- allow_gc_sym = ID2SYM(rb_intern("allow_gc")); rb_gc_register_address(&allow_gc_sym);
1664
- allow_invalid_unicode_sym = ID2SYM(rb_intern("allow_invalid_unicode"));rb_gc_register_address(&allow_invalid_unicode_sym);
1665
- ascii_sym = ID2SYM(rb_intern("ascii")); rb_gc_register_address(&ascii_sym);
1666
- auto_define_sym = ID2SYM(rb_intern("auto_define")); rb_gc_register_address(&auto_define_sym);
1667
- auto_sym = ID2SYM(rb_intern("auto")); rb_gc_register_address(&auto_sym);
1668
- bigdecimal_as_decimal_sym = ID2SYM(rb_intern("bigdecimal_as_decimal"));rb_gc_register_address(&bigdecimal_as_decimal_sym);
1669
- bigdecimal_load_sym = ID2SYM(rb_intern("bigdecimal_load")); rb_gc_register_address(&bigdecimal_load_sym);
1670
- bigdecimal_sym = ID2SYM(rb_intern("bigdecimal")); rb_gc_register_address(&bigdecimal_sym);
1671
- circular_sym = ID2SYM(rb_intern("circular")); rb_gc_register_address(&circular_sym);
1672
- class_cache_sym = ID2SYM(rb_intern("class_cache")); rb_gc_register_address(&class_cache_sym);
1673
- compat_bigdecimal_sym = ID2SYM(rb_intern("compat_bigdecimal"));rb_gc_register_address(&compat_bigdecimal_sym);
1674
- compat_sym = ID2SYM(rb_intern("compat")); rb_gc_register_address(&compat_sym);
1675
- create_id_sym = ID2SYM(rb_intern("create_id")); rb_gc_register_address(&create_id_sym);
1676
- custom_sym = ID2SYM(rb_intern("custom")); rb_gc_register_address(&custom_sym);
1677
- empty_string_sym = ID2SYM(rb_intern("empty_string")); rb_gc_register_address(&empty_string_sym);
1678
- escape_mode_sym = ID2SYM(rb_intern("escape_mode")); rb_gc_register_address(&escape_mode_sym);
1679
- integer_range_sym = ID2SYM(rb_intern("integer_range")); rb_gc_register_address(&integer_range_sym);
1680
- fast_sym = ID2SYM(rb_intern("fast")); rb_gc_register_address(&fast_sym);
1681
- float_prec_sym = ID2SYM(rb_intern("float_precision")); rb_gc_register_address(&float_prec_sym);
1682
- float_sym = ID2SYM(rb_intern("float")); rb_gc_register_address(&float_sym);
1683
- huge_sym = ID2SYM(rb_intern("huge")); rb_gc_register_address(&huge_sym);
1684
- ignore_sym = ID2SYM(rb_intern("ignore")); rb_gc_register_address(&ignore_sym);
1685
- ignore_under_sym = ID2SYM(rb_intern("ignore_under")); rb_gc_register_address(&ignore_under_sym);
1686
- json_sym = ID2SYM(rb_intern("json")); rb_gc_register_address(&json_sym);
1687
- match_string_sym = ID2SYM(rb_intern("match_string")); rb_gc_register_address(&match_string_sym);
1688
- mode_sym = ID2SYM(rb_intern("mode")); rb_gc_register_address(&mode_sym);
1689
- nan_sym = ID2SYM(rb_intern("nan")); rb_gc_register_address(&nan_sym);
1690
- newline_sym = ID2SYM(rb_intern("newline")); rb_gc_register_address(&newline_sym);
1691
- nilnil_sym = ID2SYM(rb_intern("nilnil")); rb_gc_register_address(&nilnil_sym);
1692
- null_sym = ID2SYM(rb_intern("null")); rb_gc_register_address(&null_sym);
1693
- object_sym = ID2SYM(rb_intern("object")); rb_gc_register_address(&object_sym);
1694
- oj_allow_nan_sym = ID2SYM(rb_intern("allow_nan")); rb_gc_register_address(&oj_allow_nan_sym);
1695
- oj_array_class_sym = ID2SYM(rb_intern("array_class")); rb_gc_register_address(&oj_array_class_sym);
1696
- oj_array_nl_sym = ID2SYM(rb_intern("array_nl")); rb_gc_register_address(&oj_array_nl_sym);
1697
- oj_ascii_only_sym = ID2SYM(rb_intern("ascii_only")); rb_gc_register_address(&oj_ascii_only_sym);
1698
- oj_create_additions_sym = ID2SYM(rb_intern("create_additions"));rb_gc_register_address(&oj_create_additions_sym);
1699
- oj_decimal_class_sym = ID2SYM(rb_intern("decimal_class")); rb_gc_register_address(&oj_decimal_class_sym);
1700
- oj_hash_class_sym = ID2SYM(rb_intern("hash_class")); rb_gc_register_address(&oj_hash_class_sym);
1701
- oj_indent_sym = ID2SYM(rb_intern("indent")); rb_gc_register_address(&oj_indent_sym);
1702
- oj_max_nesting_sym = ID2SYM(rb_intern("max_nesting")); rb_gc_register_address(&oj_max_nesting_sym);
1703
- oj_object_class_sym = ID2SYM(rb_intern("object_class")); rb_gc_register_address(&oj_object_class_sym);
1704
- oj_object_nl_sym = ID2SYM(rb_intern("object_nl")); rb_gc_register_address(&oj_object_nl_sym);
1705
- oj_quirks_mode_sym = ID2SYM(rb_intern("quirks_mode")); rb_gc_register_address(&oj_quirks_mode_sym);
1706
- oj_safe_sym = ID2SYM(rb_intern("safe")); rb_gc_register_address(&oj_safe_sym);
1707
- oj_space_before_sym = ID2SYM(rb_intern("space_before")); rb_gc_register_address(&oj_space_before_sym);
1708
- oj_space_sym = ID2SYM(rb_intern("space")); rb_gc_register_address(&oj_space_sym);
1709
- oj_trace_sym = ID2SYM(rb_intern("trace")); rb_gc_register_address(&oj_trace_sym);
1710
- omit_nil_sym = ID2SYM(rb_intern("omit_nil")); rb_gc_register_address(&omit_nil_sym);
1711
- rails_sym = ID2SYM(rb_intern("rails")); rb_gc_register_address(&rails_sym);
1712
- raise_sym = ID2SYM(rb_intern("raise")); rb_gc_register_address(&raise_sym);
1713
- ruby_sym = ID2SYM(rb_intern("ruby")); rb_gc_register_address(&ruby_sym);
1714
- sec_prec_sym = ID2SYM(rb_intern("second_precision")); rb_gc_register_address(&sec_prec_sym);
1715
- strict_sym = ID2SYM(rb_intern("strict")); rb_gc_register_address(&strict_sym);
1716
- symbol_keys_sym = ID2SYM(rb_intern("symbol_keys")); rb_gc_register_address(&symbol_keys_sym);
1717
- time_format_sym = ID2SYM(rb_intern("time_format")); rb_gc_register_address(&time_format_sym);
1718
- unicode_xss_sym = ID2SYM(rb_intern("unicode_xss")); rb_gc_register_address(&unicode_xss_sym);
1719
- unix_sym = ID2SYM(rb_intern("unix")); rb_gc_register_address(&unix_sym);
1720
- unix_zone_sym = ID2SYM(rb_intern("unix_zone")); rb_gc_register_address(&unix_zone_sym);
1721
- use_as_json_sym = ID2SYM(rb_intern("use_as_json")); rb_gc_register_address(&use_as_json_sym);
1722
- use_raw_json_sym = ID2SYM(rb_intern("use_raw_json")); rb_gc_register_address(&use_raw_json_sym);
1723
- use_to_hash_sym = ID2SYM(rb_intern("use_to_hash")); rb_gc_register_address(&use_to_hash_sym);
1724
- use_to_json_sym = ID2SYM(rb_intern("use_to_json")); rb_gc_register_address(&use_to_json_sym);
1725
- wab_sym = ID2SYM(rb_intern("wab")); rb_gc_register_address(&wab_sym);
1726
- word_sym = ID2SYM(rb_intern("word")); rb_gc_register_address(&word_sym);
1727
- xmlschema_sym = ID2SYM(rb_intern("xmlschema")); rb_gc_register_address(&xmlschema_sym);
1728
- xss_safe_sym = ID2SYM(rb_intern("xss_safe")); rb_gc_register_address(&xss_safe_sym);
1729
-
1730
- oj_slash_string = rb_str_new2("/"); rb_gc_register_address(&oj_slash_string);
1911
+ rb_gc_register_mark_object(oj_struct_class);
1912
+ oj_json_parser_error_class = rb_eEncodingError; // replaced if mimic is called
1913
+ oj_json_generator_error_class = rb_eEncodingError; // replaced if mimic is called
1914
+
1915
+ allow_blank_sym = ID2SYM(rb_intern("allow_blank"));
1916
+ rb_gc_register_address(&allow_blank_sym);
1917
+ allow_gc_sym = ID2SYM(rb_intern("allow_gc"));
1918
+ rb_gc_register_address(&allow_gc_sym);
1919
+ allow_invalid_unicode_sym = ID2SYM(rb_intern("allow_invalid_unicode"));
1920
+ rb_gc_register_address(&allow_invalid_unicode_sym);
1921
+ ascii_sym = ID2SYM(rb_intern("ascii"));
1922
+ rb_gc_register_address(&ascii_sym);
1923
+ auto_define_sym = ID2SYM(rb_intern("auto_define"));
1924
+ rb_gc_register_address(&auto_define_sym);
1925
+ auto_sym = ID2SYM(rb_intern("auto"));
1926
+ rb_gc_register_address(&auto_sym);
1927
+ bigdecimal_as_decimal_sym = ID2SYM(rb_intern("bigdecimal_as_decimal"));
1928
+ rb_gc_register_address(&bigdecimal_as_decimal_sym);
1929
+ bigdecimal_load_sym = ID2SYM(rb_intern("bigdecimal_load"));
1930
+ rb_gc_register_address(&bigdecimal_load_sym);
1931
+ bigdecimal_sym = ID2SYM(rb_intern("bigdecimal"));
1932
+ rb_gc_register_address(&bigdecimal_sym);
1933
+ cache_keys_sym = ID2SYM(rb_intern("cache_keys"));
1934
+ rb_gc_register_address(&cache_keys_sym);
1935
+ cache_str_sym = ID2SYM(rb_intern("cache_str"));
1936
+ rb_gc_register_address(&cache_str_sym);
1937
+ cache_string_sym = ID2SYM(rb_intern("cache_string"));
1938
+ rb_gc_register_address(&cache_string_sym);
1939
+ circular_sym = ID2SYM(rb_intern("circular"));
1940
+ rb_gc_register_address(&circular_sym);
1941
+ class_cache_sym = ID2SYM(rb_intern("class_cache"));
1942
+ rb_gc_register_address(&class_cache_sym);
1943
+ compat_bigdecimal_sym = ID2SYM(rb_intern("compat_bigdecimal"));
1944
+ rb_gc_register_address(&compat_bigdecimal_sym);
1945
+ compat_sym = ID2SYM(rb_intern("compat"));
1946
+ rb_gc_register_address(&compat_sym);
1947
+ create_id_sym = ID2SYM(rb_intern("create_id"));
1948
+ rb_gc_register_address(&create_id_sym);
1949
+ custom_sym = ID2SYM(rb_intern("custom"));
1950
+ rb_gc_register_address(&custom_sym);
1951
+ empty_string_sym = ID2SYM(rb_intern("empty_string"));
1952
+ rb_gc_register_address(&empty_string_sym);
1953
+ escape_mode_sym = ID2SYM(rb_intern("escape_mode"));
1954
+ rb_gc_register_address(&escape_mode_sym);
1955
+ integer_range_sym = ID2SYM(rb_intern("integer_range"));
1956
+ rb_gc_register_address(&integer_range_sym);
1957
+ fast_sym = ID2SYM(rb_intern("fast"));
1958
+ rb_gc_register_address(&fast_sym);
1959
+ float_format_sym = ID2SYM(rb_intern("float_format"));
1960
+ rb_gc_register_address(&float_format_sym);
1961
+ float_prec_sym = ID2SYM(rb_intern("float_precision"));
1962
+ rb_gc_register_address(&float_prec_sym);
1963
+ float_sym = ID2SYM(rb_intern("float"));
1964
+ rb_gc_register_address(&float_sym);
1965
+ huge_sym = ID2SYM(rb_intern("huge"));
1966
+ rb_gc_register_address(&huge_sym);
1967
+ ignore_sym = ID2SYM(rb_intern("ignore"));
1968
+ rb_gc_register_address(&ignore_sym);
1969
+ ignore_under_sym = ID2SYM(rb_intern("ignore_under"));
1970
+ rb_gc_register_address(&ignore_under_sym);
1971
+ json_sym = ID2SYM(rb_intern("json"));
1972
+ rb_gc_register_address(&json_sym);
1973
+ match_string_sym = ID2SYM(rb_intern("match_string"));
1974
+ rb_gc_register_address(&match_string_sym);
1975
+ mode_sym = ID2SYM(rb_intern("mode"));
1976
+ rb_gc_register_address(&mode_sym);
1977
+ nan_sym = ID2SYM(rb_intern("nan"));
1978
+ rb_gc_register_address(&nan_sym);
1979
+ newline_sym = ID2SYM(rb_intern("newline"));
1980
+ rb_gc_register_address(&newline_sym);
1981
+ nilnil_sym = ID2SYM(rb_intern("nilnil"));
1982
+ rb_gc_register_address(&nilnil_sym);
1983
+ null_sym = ID2SYM(rb_intern("null"));
1984
+ rb_gc_register_address(&null_sym);
1985
+ object_sym = ID2SYM(rb_intern("object"));
1986
+ rb_gc_register_address(&object_sym);
1987
+ oj_allow_nan_sym = ID2SYM(rb_intern("allow_nan"));
1988
+ rb_gc_register_address(&oj_allow_nan_sym);
1989
+ oj_array_class_sym = ID2SYM(rb_intern("array_class"));
1990
+ rb_gc_register_address(&oj_array_class_sym);
1991
+ oj_array_nl_sym = ID2SYM(rb_intern("array_nl"));
1992
+ rb_gc_register_address(&oj_array_nl_sym);
1993
+ oj_ascii_only_sym = ID2SYM(rb_intern("ascii_only"));
1994
+ rb_gc_register_address(&oj_ascii_only_sym);
1995
+ oj_create_additions_sym = ID2SYM(rb_intern("create_additions"));
1996
+ rb_gc_register_address(&oj_create_additions_sym);
1997
+ oj_decimal_class_sym = ID2SYM(rb_intern("decimal_class"));
1998
+ rb_gc_register_address(&oj_decimal_class_sym);
1999
+ oj_hash_class_sym = ID2SYM(rb_intern("hash_class"));
2000
+ rb_gc_register_address(&oj_hash_class_sym);
2001
+ oj_indent_sym = ID2SYM(rb_intern("indent"));
2002
+ rb_gc_register_address(&oj_indent_sym);
2003
+ oj_max_nesting_sym = ID2SYM(rb_intern("max_nesting"));
2004
+ rb_gc_register_address(&oj_max_nesting_sym);
2005
+ oj_object_class_sym = ID2SYM(rb_intern("object_class"));
2006
+ rb_gc_register_address(&oj_object_class_sym);
2007
+ oj_object_nl_sym = ID2SYM(rb_intern("object_nl"));
2008
+ rb_gc_register_address(&oj_object_nl_sym);
2009
+ oj_quirks_mode_sym = ID2SYM(rb_intern("quirks_mode"));
2010
+ rb_gc_register_address(&oj_quirks_mode_sym);
2011
+ oj_safe_sym = ID2SYM(rb_intern("safe"));
2012
+ rb_gc_register_address(&oj_safe_sym);
2013
+ omit_null_byte_sym = ID2SYM(rb_intern("omit_null_byte"));
2014
+ rb_gc_register_address(&omit_null_byte_sym);
2015
+ oj_space_before_sym = ID2SYM(rb_intern("space_before"));
2016
+ rb_gc_register_address(&oj_space_before_sym);
2017
+ oj_space_sym = ID2SYM(rb_intern("space"));
2018
+ rb_gc_register_address(&oj_space_sym);
2019
+ oj_trace_sym = ID2SYM(rb_intern("trace"));
2020
+ rb_gc_register_address(&oj_trace_sym);
2021
+ omit_nil_sym = ID2SYM(rb_intern("omit_nil"));
2022
+ rb_gc_register_address(&omit_nil_sym);
2023
+ rails_sym = ID2SYM(rb_intern("rails"));
2024
+ rb_gc_register_address(&rails_sym);
2025
+ raise_sym = ID2SYM(rb_intern("raise"));
2026
+ rb_gc_register_address(&raise_sym);
2027
+ ruby_sym = ID2SYM(rb_intern("ruby"));
2028
+ rb_gc_register_address(&ruby_sym);
2029
+ sec_prec_sym = ID2SYM(rb_intern("second_precision"));
2030
+ rb_gc_register_address(&sec_prec_sym);
2031
+ slash_sym = ID2SYM(rb_intern("slash"));
2032
+ rb_gc_register_address(&slash_sym);
2033
+ strict_sym = ID2SYM(rb_intern("strict"));
2034
+ rb_gc_register_address(&strict_sym);
2035
+ symbol_keys_sym = ID2SYM(rb_intern("symbol_keys"));
2036
+ rb_gc_register_address(&symbol_keys_sym);
2037
+ oj_symbolize_names_sym = ID2SYM(rb_intern("symbolize_names"));
2038
+ rb_gc_register_address(&oj_symbolize_names_sym);
2039
+ time_format_sym = ID2SYM(rb_intern("time_format"));
2040
+ rb_gc_register_address(&time_format_sym);
2041
+ unicode_xss_sym = ID2SYM(rb_intern("unicode_xss"));
2042
+ rb_gc_register_address(&unicode_xss_sym);
2043
+ unix_sym = ID2SYM(rb_intern("unix"));
2044
+ rb_gc_register_address(&unix_sym);
2045
+ unix_zone_sym = ID2SYM(rb_intern("unix_zone"));
2046
+ rb_gc_register_address(&unix_zone_sym);
2047
+ use_as_json_sym = ID2SYM(rb_intern("use_as_json"));
2048
+ rb_gc_register_address(&use_as_json_sym);
2049
+ use_raw_json_sym = ID2SYM(rb_intern("use_raw_json"));
2050
+ rb_gc_register_address(&use_raw_json_sym);
2051
+ use_to_hash_sym = ID2SYM(rb_intern("use_to_hash"));
2052
+ rb_gc_register_address(&use_to_hash_sym);
2053
+ use_to_json_sym = ID2SYM(rb_intern("use_to_json"));
2054
+ rb_gc_register_address(&use_to_json_sym);
2055
+ wab_sym = ID2SYM(rb_intern("wab"));
2056
+ rb_gc_register_address(&wab_sym);
2057
+ word_sym = ID2SYM(rb_intern("word"));
2058
+ rb_gc_register_address(&word_sym);
2059
+ xmlschema_sym = ID2SYM(rb_intern("xmlschema"));
2060
+ rb_gc_register_address(&xmlschema_sym);
2061
+ xss_safe_sym = ID2SYM(rb_intern("xss_safe"));
2062
+ rb_gc_register_address(&xss_safe_sym);
2063
+
2064
+ oj_slash_string = rb_str_new2("/");
2065
+ rb_gc_register_address(&oj_slash_string);
1731
2066
  OBJ_FREEZE(oj_slash_string);
1732
2067
 
1733
2068
  oj_default_options.mode = ObjectMode;
@@ -1738,11 +2073,14 @@ Init_oj() {
1738
2073
 
1739
2074
  #ifdef HAVE_PTHREAD_MUTEX_INIT
1740
2075
  if (0 != (err = pthread_mutex_init(&oj_cache_mutex, 0))) {
1741
- rb_raise(rb_eException, "failed to initialize a mutex. %s", strerror(err));
2076
+ rb_raise(rb_eException, "failed to initialize a mutex. %s", strerror(err));
1742
2077
  }
1743
2078
  #else
1744
2079
  oj_cache_mutex = rb_mutex_new();
1745
2080
  rb_gc_register_address(&oj_cache_mutex);
1746
2081
  #endif
1747
2082
  oj_init_doc();
2083
+
2084
+ oj_parser_init();
2085
+ oj_scanner_init();
1748
2086
  }