oj 3.9.1 → 3.16.11

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