oj 3.7.4 → 3.13.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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
  }