oj 3.7.4 → 3.13.23

Sign up to get free protection for your applications and to get access to all the features.
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
  }