oj 3.7.4 → 3.13.23

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