oj 3.7.4 → 3.13.21

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