oj 2.18.3 → 3.13.14

Sign up to get free protection for your applications and to get access to all the features.
Files changed (182) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1324 -0
  3. data/README.md +51 -204
  4. data/RELEASE_NOTES.md +61 -0
  5. data/ext/oj/buf.h +49 -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 -68
  11. data/ext/oj/circarray.h +16 -42
  12. data/ext/oj/code.c +221 -0
  13. data/ext/oj/code.h +40 -0
  14. data/ext/oj/compat.c +231 -107
  15. data/ext/oj/custom.c +1125 -0
  16. data/ext/oj/debug.c +132 -0
  17. data/ext/oj/dump.c +935 -2513
  18. data/ext/oj/dump.h +108 -0
  19. data/ext/oj/dump_compat.c +936 -0
  20. data/ext/oj/dump_leaf.c +164 -0
  21. data/ext/oj/dump_object.c +761 -0
  22. data/ext/oj/dump_strict.c +410 -0
  23. data/ext/oj/encode.h +7 -42
  24. data/ext/oj/encoder.c +43 -0
  25. data/ext/oj/err.c +40 -54
  26. data/ext/oj/err.h +52 -46
  27. data/ext/oj/extconf.rb +21 -30
  28. data/ext/oj/fast.c +1097 -1080
  29. data/ext/oj/intern.c +301 -0
  30. data/ext/oj/intern.h +26 -0
  31. data/ext/oj/mimic_json.c +893 -0
  32. data/ext/oj/object.c +549 -620
  33. data/ext/oj/odd.c +155 -167
  34. data/ext/oj/odd.h +37 -63
  35. data/ext/oj/oj.c +1661 -2063
  36. data/ext/oj/oj.h +341 -270
  37. data/ext/oj/parse.c +974 -737
  38. data/ext/oj/parse.h +105 -97
  39. data/ext/oj/parser.c +1526 -0
  40. data/ext/oj/parser.h +90 -0
  41. data/ext/oj/rails.c +1504 -0
  42. data/ext/oj/rails.h +18 -0
  43. data/ext/oj/reader.c +141 -163
  44. data/ext/oj/reader.h +75 -113
  45. data/ext/oj/resolve.c +45 -93
  46. data/ext/oj/resolve.h +7 -34
  47. data/ext/oj/rxclass.c +143 -0
  48. data/ext/oj/rxclass.h +26 -0
  49. data/ext/oj/saj.c +447 -511
  50. data/ext/oj/saj2.c +348 -0
  51. data/ext/oj/scp.c +91 -138
  52. data/ext/oj/sparse.c +793 -644
  53. data/ext/oj/stream_writer.c +331 -0
  54. data/ext/oj/strict.c +145 -109
  55. data/ext/oj/string_writer.c +493 -0
  56. data/ext/oj/trace.c +72 -0
  57. data/ext/oj/trace.h +28 -0
  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 +62 -70
  62. data/ext/oj/val_stack.h +95 -129
  63. data/ext/oj/validate.c +51 -0
  64. data/ext/oj/wab.c +622 -0
  65. data/lib/oj/bag.rb +1 -0
  66. data/lib/oj/easy_hash.rb +17 -8
  67. data/lib/oj/error.rb +10 -11
  68. data/lib/oj/json.rb +176 -0
  69. data/lib/oj/mimic.rb +158 -19
  70. data/lib/oj/state.rb +132 -0
  71. data/lib/oj/version.rb +2 -2
  72. data/lib/oj.rb +1 -31
  73. data/pages/Advanced.md +22 -0
  74. data/pages/Compatibility.md +25 -0
  75. data/pages/Custom.md +23 -0
  76. data/pages/Encoding.md +65 -0
  77. data/pages/JsonGem.md +94 -0
  78. data/pages/Modes.md +161 -0
  79. data/pages/Options.md +327 -0
  80. data/pages/Parser.md +309 -0
  81. data/pages/Rails.md +167 -0
  82. data/pages/Security.md +20 -0
  83. data/pages/WAB.md +13 -0
  84. data/test/activerecord/result_test.rb +32 -0
  85. data/test/activesupport4/decoding_test.rb +108 -0
  86. data/test/activesupport4/encoding_test.rb +531 -0
  87. data/test/activesupport4/test_helper.rb +41 -0
  88. data/test/activesupport5/abstract_unit.rb +45 -0
  89. data/test/activesupport5/decoding_test.rb +133 -0
  90. data/test/activesupport5/encoding_test.rb +500 -0
  91. data/test/activesupport5/encoding_test_cases.rb +98 -0
  92. data/test/activesupport5/test_helper.rb +72 -0
  93. data/test/activesupport5/time_zone_test_helpers.rb +39 -0
  94. data/test/activesupport6/abstract_unit.rb +44 -0
  95. data/test/activesupport6/decoding_test.rb +133 -0
  96. data/test/activesupport6/encoding_test.rb +507 -0
  97. data/test/activesupport6/encoding_test_cases.rb +98 -0
  98. data/test/activesupport6/test_common.rb +17 -0
  99. data/test/activesupport6/test_helper.rb +163 -0
  100. data/test/activesupport6/time_zone_test_helpers.rb +39 -0
  101. data/test/activesupport7/abstract_unit.rb +49 -0
  102. data/test/activesupport7/decoding_test.rb +125 -0
  103. data/test/activesupport7/encoding_test.rb +486 -0
  104. data/test/activesupport7/encoding_test_cases.rb +104 -0
  105. data/test/activesupport7/time_zone_test_helpers.rb +47 -0
  106. data/test/bar.rb +9 -0
  107. data/test/baz.rb +16 -0
  108. data/test/bug.rb +11 -46
  109. data/test/foo.rb +69 -16
  110. data/test/helper.rb +10 -1
  111. data/test/isolated/shared.rb +12 -8
  112. data/test/isolated/test_mimic_rails_after.rb +3 -3
  113. data/test/isolated/test_mimic_rails_before.rb +3 -3
  114. data/test/json_gem/json_addition_test.rb +216 -0
  115. data/test/json_gem/json_common_interface_test.rb +153 -0
  116. data/test/json_gem/json_encoding_test.rb +107 -0
  117. data/test/json_gem/json_ext_parser_test.rb +20 -0
  118. data/test/json_gem/json_fixtures_test.rb +35 -0
  119. data/test/json_gem/json_generator_test.rb +397 -0
  120. data/test/json_gem/json_generic_object_test.rb +90 -0
  121. data/test/json_gem/json_parser_test.rb +470 -0
  122. data/test/json_gem/json_string_matching_test.rb +42 -0
  123. data/test/json_gem/test_helper.rb +26 -0
  124. data/test/mem.rb +33 -0
  125. data/test/perf.rb +1 -1
  126. data/test/perf_compat.rb +30 -28
  127. data/test/perf_dump.rb +50 -0
  128. data/test/perf_object.rb +1 -1
  129. data/test/perf_once.rb +58 -0
  130. data/test/perf_parser.rb +189 -0
  131. data/test/perf_scp.rb +11 -10
  132. data/test/perf_strict.rb +30 -19
  133. data/test/perf_wab.rb +131 -0
  134. data/test/prec.rb +23 -0
  135. data/test/sample.rb +0 -1
  136. data/test/sample_json.rb +1 -1
  137. data/test/test_compat.rb +219 -102
  138. data/test/test_custom.rb +533 -0
  139. data/test/test_fast.rb +107 -35
  140. data/test/test_file.rb +19 -25
  141. data/test/test_generate.rb +21 -0
  142. data/test/test_hash.rb +11 -1
  143. data/test/test_integer_range.rb +72 -0
  144. data/test/test_null.rb +376 -0
  145. data/test/test_object.rb +357 -70
  146. data/test/test_parser.rb +27 -0
  147. data/test/test_parser_saj.rb +245 -0
  148. data/test/test_parser_usual.rb +217 -0
  149. data/test/test_rails.rb +35 -0
  150. data/test/test_saj.rb +1 -1
  151. data/test/test_scp.rb +39 -2
  152. data/test/test_strict.rb +186 -7
  153. data/test/test_various.rb +160 -774
  154. data/test/test_wab.rb +307 -0
  155. data/test/test_writer.rb +90 -2
  156. data/test/tests.rb +24 -0
  157. data/test/tests_mimic.rb +14 -0
  158. data/test/tests_mimic_addition.rb +7 -0
  159. data/test/zoo.rb +13 -0
  160. metadata +194 -56
  161. data/ext/oj/hash.c +0 -163
  162. data/ext/oj/hash.h +0 -46
  163. data/ext/oj/hash_test.c +0 -512
  164. data/test/activesupport_datetime_test.rb +0 -23
  165. data/test/bug2.rb +0 -10
  166. data/test/bug3.rb +0 -46
  167. data/test/bug_fast.rb +0 -32
  168. data/test/bug_load.rb +0 -24
  169. data/test/crash.rb +0 -111
  170. data/test/curl/curl_oj.rb +0 -46
  171. data/test/curl/get_oj.rb +0 -24
  172. data/test/curl/just_curl.rb +0 -31
  173. data/test/curl/just_oj.rb +0 -51
  174. data/test/example.rb +0 -11
  175. data/test/io.rb +0 -48
  176. data/test/isolated/test_mimic_rails_datetime.rb +0 -27
  177. data/test/mod.rb +0 -16
  178. data/test/rails.rb +0 -50
  179. data/test/russian.rb +0 -18
  180. data/test/struct.rb +0 -29
  181. data/test/test_serializer.rb +0 -59
  182. data/test/write_timebars.rb +0 -31
data/ext/oj/oj.c CHANGED
@@ -1,740 +1,1000 @@
1
- /* oj.c
2
- * Copyright (c) 2012, Peter Ohler
3
- *
4
- * All rights reserved.
5
- *
6
- * Redistribution and use in source and binary forms, with or without
7
- * modification, are permitted provided that the following conditions are met:
8
- *
9
- * - Redistributions of source code must retain the above copyright notice, this
10
- * list of conditions and the following disclaimer.
11
- *
12
- * - Redistributions in binary form must reproduce the above copyright notice,
13
- * this list of conditions and the following disclaimer in the documentation
14
- * and/or other materials provided with the distribution.
15
- *
16
- * - Neither the name of Peter Ohler nor the names of its contributors may be
17
- * used to endorse or promote products derived from this software without
18
- * specific prior written permission.
19
- *
20
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
- */
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"
31
5
 
32
- #include <stdlib.h>
33
6
  #include <errno.h>
7
+ #include <fcntl.h>
34
8
  #include <stdio.h>
9
+ #include <stdlib.h>
35
10
  #include <string.h>
36
11
  #include <sys/types.h>
37
12
  #include <unistd.h>
38
- #include <fcntl.h>
39
13
 
40
- #include "oj.h"
41
- #include "parse.h"
42
- #include "hash.h"
43
- #include "odd.h"
14
+ #include "dump.h"
44
15
  #include "encode.h"
16
+ #include "intern.h"
17
+ #include "odd.h"
18
+ #include "parse.h"
19
+ #include "rails.h"
45
20
 
46
- typedef struct _YesNoOpt {
47
- VALUE sym;
48
- char *attr;
49
- } *YesNoOpt;
21
+ typedef struct _yesNoOpt {
22
+ VALUE sym;
23
+ char *attr;
24
+ } * YesNoOpt;
50
25
 
51
26
  void Init_oj();
52
27
 
53
- VALUE Oj = Qnil;
54
-
55
- ID oj_add_value_id;
56
- ID oj_array_append_id;
57
- ID oj_array_end_id;
58
- ID oj_array_start_id;
59
- ID oj_as_json_id;
60
- ID oj_error_id;
61
- ID oj_file_id;
62
- ID oj_fileno_id;
63
- ID oj_ftype_id;
64
- ID oj_hash_end_id;
65
- ID oj_hash_key_id;
66
- ID oj_hash_set_id;
67
- ID oj_hash_start_id;
68
- ID oj_iconv_id;
69
- ID oj_instance_variables_id;
70
- ID oj_json_create_id;
71
- ID oj_length_id;
72
- ID oj_new_id;
73
- ID oj_parse_id;
74
- ID oj_pos_id;
75
- ID oj_read_id;
76
- ID oj_readpartial_id;
77
- ID oj_replace_id;
78
- ID oj_stat_id;
79
- ID oj_string_id;
80
- ID oj_to_hash_id;
81
- ID oj_to_json_id;
82
- ID oj_to_s_id;
83
- ID oj_to_sym_id;
84
- ID oj_to_time_id;
85
- ID oj_tv_nsec_id;
86
- ID oj_tv_sec_id;
87
- ID oj_tv_usec_id;
88
- ID oj_utc_id;
89
- ID oj_utc_offset_id;
90
- ID oj_utcq_id;
91
- ID oj_write_id;
92
-
93
- static ID has_key_id;
94
-
95
- VALUE oj_bag_class;
96
- VALUE oj_bigdecimal_class;
97
- VALUE oj_cstack_class;
98
- VALUE oj_date_class;
99
- VALUE oj_datetime_class;
100
- VALUE oj_parse_error_class;
101
- VALUE oj_stream_writer_class;
102
- VALUE oj_string_writer_class;
103
- VALUE oj_stringio_class;
104
- VALUE oj_struct_class;
105
-
106
- VALUE oj_slash_string;
107
-
108
- static VALUE allow_gc_sym;
109
- static VALUE allow_invalid_unicode_sym;
110
- static VALUE ascii_only_sym;
111
- static VALUE ascii_sym;
112
- static VALUE auto_define_sym;
113
- static VALUE auto_sym;
114
- static VALUE bigdecimal_as_decimal_sym;
115
- static VALUE bigdecimal_load_sym;
116
- static VALUE bigdecimal_sym;
117
- static VALUE circular_sym;
118
- static VALUE class_cache_sym;
119
- static VALUE compat_sym;
120
- static VALUE create_id_sym;
121
- static VALUE escape_mode_sym;
122
- static VALUE float_prec_sym;
123
- static VALUE float_sym;
124
- static VALUE hash_class_sym;
125
- static VALUE huge_sym;
126
- static VALUE indent_sym;
127
- static VALUE json_parser_error_class;
128
- static VALUE json_sym;
129
- static VALUE mode_sym;
130
- static VALUE nan_sym;
131
- static VALUE newline_sym;
132
- static VALUE nilnil_sym;
133
- static VALUE null_sym;
134
- static VALUE object_sym;
135
- static VALUE omit_nil_sym;
136
- static VALUE quirks_mode_sym;
137
- static VALUE raise_sym;
138
- static VALUE ruby_sym;
139
- static VALUE sec_prec_sym;
140
- static VALUE strict_sym;
141
- static VALUE symbol_keys_sym;
142
- static VALUE time_format_sym;
143
- static VALUE unix_sym;
144
- static VALUE unix_zone_sym;
145
- static VALUE use_as_json_sym;
146
- static VALUE use_to_json_sym;
147
- static VALUE word_sym;
148
- static VALUE xmlschema_sym;
149
- static VALUE xss_safe_sym;
150
-
151
- static VALUE array_nl_sym;
152
- static VALUE create_additions_sym;
153
- static VALUE object_nl_sym;
154
- static VALUE space_before_sym;
155
- static VALUE space_sym;
156
- static VALUE symbolize_names_sym;
157
-
158
- static VALUE mimic = Qnil;
159
-
160
- #if HAS_ENCODING_SUPPORT
161
- rb_encoding *oj_utf8_encoding = 0;
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_instance_variables_id;
49
+ ID oj_json_create_id;
50
+ ID oj_length_id;
51
+ ID oj_new_id;
52
+ ID oj_parse_id;
53
+ ID oj_pos_id;
54
+ ID oj_raw_json_id;
55
+ ID oj_read_id;
56
+ ID oj_readpartial_id;
57
+ ID oj_replace_id;
58
+ ID oj_stat_id;
59
+ ID oj_string_id;
60
+ ID oj_to_h_id;
61
+ ID oj_to_hash_id;
62
+ ID oj_to_json_id;
63
+ ID oj_to_s_id;
64
+ ID oj_to_sym_id;
65
+ ID oj_to_time_id;
66
+ ID oj_tv_nsec_id;
67
+ ID oj_tv_sec_id;
68
+ ID oj_tv_usec_id;
69
+ ID oj_utc_id;
70
+ ID oj_utc_offset_id;
71
+ ID oj_utcq_id;
72
+ ID oj_write_id;
73
+
74
+ VALUE oj_bag_class;
75
+ VALUE oj_bigdecimal_class;
76
+ VALUE oj_cstack_class;
77
+ VALUE oj_date_class;
78
+ VALUE oj_datetime_class;
79
+ VALUE oj_enumerable_class;
80
+ VALUE oj_parse_error_class;
81
+ VALUE oj_stream_writer_class;
82
+ VALUE oj_string_writer_class;
83
+ VALUE oj_stringio_class;
84
+ VALUE oj_struct_class;
85
+
86
+ VALUE oj_slash_string;
87
+
88
+ VALUE oj_allow_nan_sym;
89
+ VALUE oj_array_class_sym;
90
+ VALUE oj_create_additions_sym;
91
+ VALUE oj_decimal_class_sym;
92
+ VALUE oj_hash_class_sym;
93
+ VALUE oj_indent_sym;
94
+ VALUE oj_object_class_sym;
95
+ VALUE oj_quirks_mode_sym;
96
+ VALUE oj_safe_sym;
97
+ VALUE oj_symbolize_names_sym;
98
+ VALUE oj_trace_sym;
99
+
100
+ static VALUE allow_blank_sym;
101
+ static VALUE allow_gc_sym;
102
+ static VALUE allow_invalid_unicode_sym;
103
+ static VALUE ascii_sym;
104
+ static VALUE auto_define_sym;
105
+ static VALUE auto_sym;
106
+ static VALUE bigdecimal_as_decimal_sym;
107
+ static VALUE bigdecimal_load_sym;
108
+ static VALUE bigdecimal_sym;
109
+ static VALUE cache_keys_sym;
110
+ static VALUE cache_str_sym;
111
+ static VALUE cache_string_sym;
112
+ static VALUE circular_sym;
113
+ static VALUE class_cache_sym;
114
+ static VALUE compat_bigdecimal_sym;
115
+ static VALUE compat_sym;
116
+ static VALUE create_id_sym;
117
+ static VALUE custom_sym;
118
+ static VALUE empty_string_sym;
119
+ static VALUE escape_mode_sym;
120
+ static VALUE integer_range_sym;
121
+ static VALUE fast_sym;
122
+ static VALUE float_prec_sym;
123
+ static VALUE float_sym;
124
+ static VALUE huge_sym;
125
+ static VALUE ignore_sym;
126
+ static VALUE ignore_under_sym;
127
+ static VALUE json_sym;
128
+ static VALUE match_string_sym;
129
+ static VALUE mode_sym;
130
+ static VALUE nan_sym;
131
+ static VALUE newline_sym;
132
+ static VALUE nilnil_sym;
133
+ static VALUE null_sym;
134
+ static VALUE object_sym;
135
+ static VALUE omit_nil_sym;
136
+ static VALUE rails_sym;
137
+ static VALUE raise_sym;
138
+ static VALUE ruby_sym;
139
+ static VALUE sec_prec_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;
162
160
  #else
163
- VALUE oj_utf8_encoding = Qnil;
164
- #endif
165
-
166
- #if USE_PTHREAD_MUTEX
167
- pthread_mutex_t oj_cache_mutex;
168
- #elif USE_RB_MUTEX
169
161
  VALUE oj_cache_mutex = Qnil;
170
162
  #endif
171
- static const char json_class[] = "json_class";
172
-
173
- struct _Options oj_default_options = {
174
- 0, // indent
175
- No, // circular
176
- No, // auto_define
177
- No, // sym_key
178
- JSONEsc, // escape_mode
179
- ObjectMode, // mode
180
- Yes, // class_cache
181
- UnixZTime, // time_format
182
- Yes, // bigdec_as_num
183
- AutoDec, // bigdec_load
184
- No, // to_json
185
- No, // as_json
186
- No, // nilnil
187
- Yes, // allow_gc
188
- Yes, // quirks_mode
189
- No, // allow_invalid
190
- json_class, // create_id
191
- 10, // create_id_len
192
- 9, // sec_prec
193
- 15, // float_prec
194
- "%0.15g", // float_fmt
195
- Qnil, // hash_class
196
- { // dump_opts
197
- false, //use
198
- "", // indent
199
- "", // before_sep
200
- "", // after_sep
201
- "", // hash_nl
202
- "", // array_nl
203
- 0, // indent_size
204
- 0, // before_size
205
- 0, // after_size
206
- 0, // hash_size
207
- 0, // array_size
208
- AutoNan,// nan_dump
209
- false, // omit_nil
210
- }
211
- };
212
163
 
213
- static VALUE define_mimic_json(int argc, VALUE *argv, VALUE self);
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
222
+ },
223
+ {
224
+ // str_rx
225
+ NULL, // head
226
+ NULL, // tail
227
+ {'\0'}, // err
228
+ },
229
+ NULL, // ignore
230
+ };
214
231
 
215
- /* call-seq: default_options() => Hash
232
+ /* Document-method: default_options()
233
+ * call-seq: default_options()
216
234
  *
217
235
  * Returns the default load and dump options as a Hash. The options are
218
- * - 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
219
- * - circular: [true|false|nil] support circular references while dumping
220
- * - auto_define: [true|false|nil] automatically define classes if they do not exist
221
- * - symbol_keys: [true|false|nil] use symbols instead of strings for hash keys
222
- * - escape_mode: [:newline|:json|:xss_safe|:ascii|nil] determines the characters to escape
223
- * - class_cache: [true|false|nil] cache classes for faster parsing (if dynamically modifying classes or reloading classes then don't use this)
224
- * - mode: [:object|:strict|:compat|:null] load and dump modes to use for JSON
225
- * - time_format: [:unix|:unix_zone|:xmlschema|:ruby] time format when dumping in :compat and :object mode
226
- * - bigdecimal_as_decimal: [true|false|nil] dump BigDecimal as a decimal number or as a String
227
- * - bigdecimal_load: [:bigdecimal|:float|:auto] load decimals as BigDecimal instead of as a Float. :auto pick the most precise for the number of digits.
228
- * - create_id: [String|nil] create id for json compatible object encoding, default is 'json_create'
229
- * - second_precision: [Fixnum|nil] number of digits after the decimal when dumping the seconds portion of time
230
- * - float_precision: [Fixnum|nil] number of digits of precision when dumping floats, 0 indicates use Ruby
231
- * - use_to_json: [true|false|nil] call to_json() methods on dump, default is false
232
- * - use_as_json: [true|false|nil] call as_json() methods on dump, default is false
233
- * - nilnil: [true|false|nil] if true a nil input to load will return nil and not raise an Exception
234
- * - allow_gc: [true|false|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
- * - indent_str: [String|nil] String to use for indentation, overriding the indent option is not nil
238
- * - space: [String|nil] String to use for the space after the colon in JSON object fields
239
- * - space_before: [String|nil] String to use before the colon separator in JSON object fields
240
- * - object_nl: [String|nil] String to use after a JSON object field value
241
- * - array_nl: [String|nil] String to use after a JSON array value
242
- * - nan: [:null|:huge|:word|:raise|:auto] 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.
243
- * - hash_class: [Class|nil] Class to use instead of Hash on load
244
- * - omit_nil: [true|false] if true Hash and Object attributes with nil values are omitted
245
- * @return [Hash] all current option settings.
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
241
+ * - *:auto_define* [_Boolean_|_nil_] automatically define classes if they do not exist
242
+ * - *:symbol_keys* [_Boolean_|_nil_] use symbols instead of strings for hash keys
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
249
+ * - *:time_format* [_:unix_|_:unix_zone_|_:xmlschema_|_:ruby_] time format when dumping
250
+ * - *:bigdecimal_as_decimal* [_Boolean_|_nil_] dump BigDecimal as a decimal number or as a String
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
264
+ * - *:use_to_json* [_Boolean_|_nil_] call to_json() methods on dump, default is false
265
+ * - *:use_as_json* [_Boolean_|_nil_] call as_json() methods on dump, default is false
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
269
+ * - *:empty_string* [_Boolean_|_nil_] if true an empty input will not raise an Exception
270
+ * - *:allow_gc* [_Boolean_|_nil_] allow or prohibit GC during parsing, default is true (allow)
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
279
+ * - *:space* [_String_|_nil_] String to use for the space after the colon in JSON object fields
280
+ * - *:space_before* [_String_|_nil_] String to use before the colon separator in JSON object fields
281
+ * - *:object_nl* [_String_|_nil_] String to use after a JSON object field value
282
+ * - *:array_nl* [_String_|_nil_] String to use after a JSON array value
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
288
+ * - *:array_class* [_Class_|_nil_] Class to use instead of Array on load
289
+ * - *:omit_nil* [_true_|_false_] if true Hash and Object attributes with nil values are omitted
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.
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)
299
+ *
300
+ * Return [_Hash_] all current option settings.
246
301
  */
247
- static VALUE
248
- get_def_opts(VALUE self) {
249
- VALUE opts = rb_hash_new();
302
+ static VALUE get_def_opts(VALUE self) {
303
+ VALUE opts = rb_hash_new();
250
304
 
251
305
  if (0 == oj_default_options.dump_opts.indent_size) {
252
- rb_hash_aset(opts, indent_sym, INT2FIX(oj_default_options.indent));
306
+ rb_hash_aset(opts, oj_indent_sym, INT2FIX(oj_default_options.indent));
253
307
  } else {
254
- rb_hash_aset(opts, 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));
255
309
  }
256
310
  rb_hash_aset(opts, sec_prec_sym, INT2FIX(oj_default_options.sec_prec));
257
- rb_hash_aset(opts, circular_sym, (Yes == oj_default_options.circular) ? Qtrue : ((No == oj_default_options.circular) ? Qfalse : Qnil));
258
- rb_hash_aset(opts, class_cache_sym, (Yes == oj_default_options.class_cache) ? Qtrue : ((No == oj_default_options.class_cache) ? Qfalse : Qnil));
259
- rb_hash_aset(opts, auto_define_sym, (Yes == oj_default_options.auto_define) ? Qtrue : ((No == oj_default_options.auto_define) ? Qfalse : Qnil));
260
- rb_hash_aset(opts, symbol_keys_sym, (Yes == oj_default_options.sym_key) ? Qtrue : ((No == oj_default_options.sym_key) ? Qfalse : Qnil));
261
- 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));
262
- rb_hash_aset(opts, use_to_json_sym, (Yes == oj_default_options.to_json) ? Qtrue : ((No == oj_default_options.to_json) ? Qfalse : Qnil));
263
- rb_hash_aset(opts, use_as_json_sym, (Yes == oj_default_options.as_json) ? Qtrue : ((No == oj_default_options.as_json) ? Qfalse : Qnil));
264
- rb_hash_aset(opts, nilnil_sym, (Yes == oj_default_options.nilnil) ? Qtrue : ((No == oj_default_options.nilnil) ? Qfalse : Qnil));
265
- rb_hash_aset(opts, allow_gc_sym, (Yes == oj_default_options.allow_gc) ? Qtrue : ((No == oj_default_options.allow_gc) ? Qfalse : Qnil));
266
- rb_hash_aset(opts, quirks_mode_sym, (Yes == oj_default_options.quirks_mode) ? Qtrue : ((No == oj_default_options.quirks_mode) ? Qfalse : Qnil));
267
- rb_hash_aset(opts, allow_invalid_unicode_sym, (Yes == oj_default_options.allow_invalid) ? Qtrue : ((No == oj_default_options.allow_invalid) ? 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));
268
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));
269
383
  switch (oj_default_options.mode) {
270
- case StrictMode: rb_hash_aset(opts, mode_sym, strict_sym); break;
271
- case CompatMode: rb_hash_aset(opts, mode_sym, compat_sym); break;
272
- case NullMode: rb_hash_aset(opts, mode_sym, null_sym); break;
273
- case ObjectMode:
274
- default: rb_hash_aset(opts, mode_sym, object_sym); break;
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;
392
+ }
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);
275
404
  }
276
405
  switch (oj_default_options.escape_mode) {
277
- case NLEsc: rb_hash_aset(opts, escape_mode_sym, newline_sym); break;
278
- case JSONEsc: rb_hash_aset(opts, escape_mode_sym, json_sym); break;
279
- case XSSEsc: rb_hash_aset(opts, escape_mode_sym, xss_safe_sym); break;
280
- case ASCIIEsc: rb_hash_aset(opts, escape_mode_sym, ascii_sym); break;
281
- 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 XSSEsc: rb_hash_aset(opts, escape_mode_sym, xss_safe_sym); break;
409
+ case ASCIIEsc: rb_hash_aset(opts, escape_mode_sym, ascii_sym); break;
410
+ case JXEsc: rb_hash_aset(opts, escape_mode_sym, unicode_xss_sym); break;
411
+ default: rb_hash_aset(opts, escape_mode_sym, json_sym); break;
282
412
  }
283
413
  switch (oj_default_options.time_format) {
284
- case XmlTime: rb_hash_aset(opts, time_format_sym, xmlschema_sym); break;
285
- case RubyTime: rb_hash_aset(opts, time_format_sym, ruby_sym); break;
286
- case UnixZTime: rb_hash_aset(opts, time_format_sym, unix_zone_sym); break;
414
+ case XmlTime: rb_hash_aset(opts, time_format_sym, xmlschema_sym); break;
415
+ case RubyTime: rb_hash_aset(opts, time_format_sym, ruby_sym); break;
416
+ case UnixZTime: rb_hash_aset(opts, time_format_sym, unix_zone_sym); break;
287
417
  case UnixTime:
288
- default: rb_hash_aset(opts, time_format_sym, unix_sym); break;
418
+ default: rb_hash_aset(opts, time_format_sym, unix_sym); break;
289
419
  }
290
420
  switch (oj_default_options.bigdec_load) {
291
- case BigDec: rb_hash_aset(opts, bigdecimal_load_sym, bigdecimal_sym);break;
292
- case FloatDec: rb_hash_aset(opts, bigdecimal_load_sym, float_sym); break;
421
+ case BigDec: rb_hash_aset(opts, bigdecimal_load_sym, bigdecimal_sym); break;
422
+ case FloatDec: rb_hash_aset(opts, bigdecimal_load_sym, float_sym); break;
423
+ case FastDec: rb_hash_aset(opts, bigdecimal_load_sym, fast_sym); break;
293
424
  case AutoDec:
294
- default: rb_hash_aset(opts, bigdecimal_load_sym, auto_sym); break;
295
- }
296
- rb_hash_aset(opts, create_id_sym, (0 == oj_default_options.create_id) ? Qnil : rb_str_new2(oj_default_options.create_id));
297
- rb_hash_aset(opts, space_sym, (0 == oj_default_options.dump_opts.after_size) ? Qnil : rb_str_new2(oj_default_options.dump_opts.after_sep));
298
- rb_hash_aset(opts, space_before_sym, (0 == oj_default_options.dump_opts.before_size) ? Qnil : rb_str_new2(oj_default_options.dump_opts.before_sep));
299
- rb_hash_aset(opts, object_nl_sym, (0 == oj_default_options.dump_opts.hash_size) ? Qnil : rb_str_new2(oj_default_options.dump_opts.hash_nl));
300
- rb_hash_aset(opts, array_nl_sym, (0 == oj_default_options.dump_opts.array_size) ? Qnil : rb_str_new2(oj_default_options.dump_opts.array_nl));
425
+ default: rb_hash_aset(opts, bigdecimal_load_sym, auto_sym); break;
426
+ }
427
+ rb_hash_aset(opts, compat_bigdecimal_sym, oj_default_options.compat_bigdec ? Qtrue : Qfalse);
428
+ rb_hash_aset(opts,
429
+ create_id_sym,
430
+ (NULL == oj_default_options.create_id) ? Qnil : rb_str_new2(oj_default_options.create_id));
431
+ rb_hash_aset(
432
+ opts,
433
+ oj_space_sym,
434
+ (0 == oj_default_options.dump_opts.after_size) ? Qnil : rb_str_new2(oj_default_options.dump_opts.after_sep));
435
+ rb_hash_aset(
436
+ opts,
437
+ oj_space_before_sym,
438
+ (0 == oj_default_options.dump_opts.before_size) ? Qnil : rb_str_new2(oj_default_options.dump_opts.before_sep));
439
+ rb_hash_aset(
440
+ opts,
441
+ oj_object_nl_sym,
442
+ (0 == oj_default_options.dump_opts.hash_size) ? Qnil : rb_str_new2(oj_default_options.dump_opts.hash_nl));
443
+ rb_hash_aset(
444
+ opts,
445
+ oj_array_nl_sym,
446
+ (0 == oj_default_options.dump_opts.array_size) ? Qnil : rb_str_new2(oj_default_options.dump_opts.array_nl));
301
447
 
302
448
  switch (oj_default_options.dump_opts.nan_dump) {
303
- case NullNan: rb_hash_aset(opts, nan_sym, null_sym); break;
304
- case RaiseNan: rb_hash_aset(opts, nan_sym, raise_sym); break;
305
- case WordNan: rb_hash_aset(opts, nan_sym, word_sym); break;
306
- case HugeNan: rb_hash_aset(opts, nan_sym, huge_sym); break;
449
+ case NullNan: rb_hash_aset(opts, nan_sym, null_sym); break;
450
+ case RaiseNan: rb_hash_aset(opts, nan_sym, raise_sym); break;
451
+ case WordNan: rb_hash_aset(opts, nan_sym, word_sym); break;
452
+ case HugeNan: rb_hash_aset(opts, nan_sym, huge_sym); break;
307
453
  case AutoNan:
308
- default: rb_hash_aset(opts, nan_sym, auto_sym); break;
454
+ default: rb_hash_aset(opts, nan_sym, auto_sym); break;
309
455
  }
310
456
  rb_hash_aset(opts, omit_nil_sym, oj_default_options.dump_opts.omit_nil ? Qtrue : Qfalse);
311
- rb_hash_aset(opts, hash_class_sym, oj_default_options.hash_class);
312
-
457
+ rb_hash_aset(opts, oj_hash_class_sym, oj_default_options.hash_class);
458
+ rb_hash_aset(opts, oj_array_class_sym, oj_default_options.array_class);
459
+
460
+ if (NULL == oj_default_options.ignore) {
461
+ rb_hash_aset(opts, ignore_sym, Qnil);
462
+ } else {
463
+ VALUE * vp;
464
+ volatile VALUE a = rb_ary_new();
465
+
466
+ for (vp = oj_default_options.ignore; Qnil != *vp; vp++) {
467
+ rb_ary_push(a, *vp);
468
+ }
469
+ rb_hash_aset(opts, ignore_sym, a);
470
+ }
313
471
  return opts;
314
472
  }
315
473
 
316
- /* call-seq: default_options=(opts)
474
+ /* Document-method: default_options=
475
+ * call-seq: default_options=(opts)
317
476
  *
318
477
  * Sets the default options for load and dump.
319
- * @param [Hash] opts options to change
320
- * @param [Fixnum|String|nil] :indent number of spaces to indent each element in a JSON document or the String to use for identation.
321
- * @param [true|false|nil] :circular support circular references while dumping
322
- * @param [true|false|nil] :auto_define automatically define classes if they do not exist
323
- * @param [true|false|nil] :symbol_keys convert hash keys to symbols
324
- * @param [true|false|nil] :class_cache cache classes for faster parsing
325
- * @param [:newline|:json|:xss_safe|:ascii|nil] :escape mode encodes all high-bit characters as
326
- * escaped sequences if :ascii, :json is standand UTF-8 JSON encoding,
327
- * :newline is the same as :json but newlines are not escaped,
328
- * and :xss_safe escapes &, <, and >, and some others.
329
- * @param [true|false|nil] :bigdecimal_as_decimal dump BigDecimal as a decimal number or as a String
330
- * @param [:bigdecimal|:float|:auto|nil] :bigdecimal_load load decimals as BigDecimal instead of as a Float. :auto pick the most precise for the number of digits.
331
- * @param [:object|:strict|:compat|:null] load and dump mode to use for JSON
332
- * :strict raises an exception when a non-supported Object is
333
- * encountered. :compat attempts to extract variable values from an
334
- * Object using to_json() or to_hash() then it walks the Object's
335
- * variables if neither is found. The :object mode ignores to_hash()
336
- * and to_json() methods and encodes variables using code internal to
337
- * the Oj gem. The :null mode ignores non-supported Objects and
338
- * replaces them with a null.
339
- * @param [:unix|:xmlschema|:ruby] time format when dumping in :compat mode
340
- * :unix decimal number denoting the number of seconds since 1/1/1970,
341
- * :unix_zone decimal number denoting the number of seconds since 1/1/1970 plus the utc_offset in the exponent ,
342
- * :xmlschema date-time format taken from XML Schema as a String,
343
- * :ruby Time.to_s formatted String
344
- * @param [String|nil] :create_id create id for json compatible object encoding
345
- * @param [Fixnum|nil] :second_precision number of digits after the decimal when dumping the seconds portion of time
346
- * @param [Fixnum|nil] :float_precision number of digits of precision when dumping floats, 0 indicates use Ruby
347
- * @param [true|false|nil] :use_to_json call to_json() methods on dump, default is false
348
- * @param [true|false|nil] :use_as_json call as_json() methods on dump, default is false
349
- * @param [true|false|nil] :nilnil if true a nil input to load will return nil and not raise an Exception
350
- * @param [true|false|nil] :allow_gc allow or prohibit GC during parsing, default is true (allow)
351
- * @param [true|false|nil] :quirks_mode allow single JSON values instead of documents, default is true (allow)
352
- * @param [true|false|nil] :allow_invalid_unicode allow invalid unicode, default is false (don't allow)
353
- * @param [String|nil] :space String to use for the space after the colon in JSON object fields
354
- * @param [String|nil] :space_before String to use before the colon separator in JSON object fields
355
- * @param [String|nil] :object_nl String to use after a JSON object field value
356
- * @param [String|nil] :array_nl String to use after a JSON array value
357
- * @param [:null|:huge|:word|:raise] :nan 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.
358
- * @param [Class|nil] :hash_class Class to use instead of Hash on load
359
- * @param [true|false] :omit_nil if true Hash and Object attributes with nil values are omitted
360
- * @return [nil]
478
+ * - *opts* [_Hash_] options to change
479
+ * - *:indent* [_Fixnum_|_String_|_nil_] number of spaces to indent each element in a JSON
480
+ *document or the String to use for indentation.
481
+ * - :circular [_Boolean_|_nil_] support circular references while dumping.
482
+ * - *:auto_define* [_Boolean_|_nil_] automatically define classes if they do not exist.
483
+ * - *:symbol_keys* [_Boolean_|_nil_] convert hash keys to symbols.
484
+ * - *:class_cache* [_Boolean_|_nil_] cache classes for faster parsing.
485
+ * - *:escape* [_:newline_|_:json_|_:xss_safe_|_:ascii_|_unicode_xss_|_nil_] mode encodes all
486
+ *high-bit characters as escaped sequences if :ascii, :json is standand UTF-8 JSON encoding,
487
+ *:newline is the same as :json but newlines are not escaped, :unicode_xss allows unicode but
488
+ *escapes &, <, and >, and any \u20xx characters along with some others, and :xss_safe escapes &, <,
489
+ *and >, and some others.
490
+ * - *:bigdecimal_as_decimal* [_Boolean_|_nil_] dump BigDecimal as a decimal number or as a
491
+ *String.
492
+ * - *:bigdecimal_load* [_:bigdecimal_|_:float_|_:auto_|_nil_] load decimals as BigDecimal instead
493
+ *of as a Float. :auto pick the most precise for the number of digits.
494
+ * - *:compat_bigdecimal* [_true_|_false_] load decimals as BigDecimal instead of as a Float in
495
+ *compat mode.
496
+ * - *:mode* [_:object_|_:strict_|_:compat_|_:null_|_:custom_|_:rails_|_:wab_] load and dump mode
497
+ *to use for JSON :strict raises an exception when a non-supported Object is encountered. :compat
498
+ *attempts to extract variable values from an Object using to_json() or to_hash() then it walks the
499
+ *Object's variables if neither is found. The :object mode ignores to_hash() and to_json() methods
500
+ *and encodes variables using code internal to the Oj gem. The :null mode ignores non-supported
501
+ *Objects and replaces them with a null. The :custom mode honors all dump options. The :rails more
502
+ *mimics rails and Active behavior.
503
+ * - *:time_format* [_:unix_|_:xmlschema_|_:ruby_] time format when dumping in :compat mode :unix
504
+ *decimal number denoting the number of seconds since 1/1/1970, :unix_zone decimal number denoting
505
+ *the number of seconds since 1/1/1970 plus the utc_offset in the exponent, :xmlschema date-time
506
+ *format taken from XML Schema as a String, :ruby Time.to_s formatted String.
507
+ * - *:create_id* [_String_|_nil_] create id for json compatible object encoding
508
+ * - *:create_additions* [_Boolean_|_nil_] if true allow creation of instances using create_id on
509
+ *load.
510
+ * - *:second_precision* [_Fixnum_|_nil_] number of digits after the decimal when dumping the
511
+ *seconds portion of time.
512
+ * - *:float_precision* [_Fixnum_|_nil_] number of digits of precision when dumping floats, 0
513
+ *indicates use Ruby.
514
+ * - *:use_to_json* [_Boolean_|_nil_] call to_json() methods on dump, default is false.
515
+ * - *:use_as_json* [_Boolean_|_nil_] call as_json() methods on dump, default is false.
516
+ * - *:use_to_hash* [_Boolean_|_nil_] call to_hash() methods on dump, default is false.
517
+ * - *:use_raw_json* [_Boolean_|_nil_] call raw_json() methods on dump, default is false.
518
+ * - *:nilnil* [_Boolean_|_nil_] if true a nil input to load will return nil and not raise an
519
+ *Exception.
520
+ * - *:allow_gc* [_Boolean_|_nil_] allow or prohibit GC during parsing, default is true (allow).
521
+ * - *:quirks_mode* [_Boolean_|_nil_] allow single JSON values instead of documents, default is
522
+ *true (allow).
523
+ * - *:allow_invalid_unicode* [_Boolean_|_nil_] allow invalid unicode, default is false (don't
524
+ *allow).
525
+ * - *:allow_nan* [_Boolean_|_nil_] allow Nan, Infinity, and -Infinity, default is true (allow).
526
+ * - *:space* [_String_|_nil_] String to use for the space after the colon in JSON object fields.
527
+ * - *:space_before* [_String_|_nil_] String to use before the colon separator in JSON object
528
+ *fields.
529
+ * - *:object_nl* [_String_|_nil_] String to use after a JSON object field value.
530
+ * - *:array_nl* [_String_|_nil_] String to use after a JSON array value
531
+ * - *:nan* [_:null_|_:huge_|_:word_|_:raise_] how to dump Infinity and NaN in null, strict, and
532
+ *compat mode. :null places a null, :huge places a huge number, :word places Infinity or NaN, :raise
533
+ *raises and exception, :auto uses default for each mode.
534
+ * - *:hash_class* [_Class_|_nil_] Class to use instead of Hash on load, :object_class can also be
535
+ *used.
536
+ * - *:array_class* [_Class_|_nil_] Class to use instead of Array on load.
537
+ * - *:omit_nil* [_true_|_false_] if true Hash and Object attributes with nil values are omitted.
538
+ * - *:ignore* [_nil_|Array] either nil or an Array of classes to ignore when dumping
539
+ * - *:ignore_under* [_Boolean_] if true then attributes that start with _ are ignored when
540
+ *dumping in object or custom mode.
541
+ * - *:cache_keys* [_Boolean_] if true then hash keys are cached
542
+ * - *:cache_str* [_Fixnum_] maximum string value length to cache (strings less than this are cached)
543
+ * - *:integer_range* [_Range_] Dump integers outside range as strings.
544
+ * - *:trace* [_Boolean_] turn trace on or off.
545
+ * - *:safe* [_Boolean_] turn safe mimic on or off.
361
546
  */
362
- static VALUE
363
- set_def_opts(VALUE self, VALUE opts) {
547
+ static VALUE set_def_opts(VALUE self, VALUE opts) {
364
548
  Check_Type(opts, T_HASH);
365
549
  oj_parse_options(opts, &oj_default_options);
366
550
 
367
551
  return Qnil;
368
552
  }
369
553
 
370
- void
371
- oj_parse_options(VALUE ropts, Options copts) {
372
- struct _YesNoOpt ynos[] = {
373
- { circular_sym, &copts->circular },
374
- { auto_define_sym, &copts->auto_define },
375
- { symbol_keys_sym, &copts->sym_key },
376
- { class_cache_sym, &copts->class_cache },
377
- { bigdecimal_as_decimal_sym, &copts->bigdec_as_num },
378
- { use_to_json_sym, &copts->to_json },
379
- { use_as_json_sym, &copts->as_json },
380
- { nilnil_sym, &copts->nilnil },
381
- { allow_gc_sym, &copts->allow_gc },
382
- { quirks_mode_sym, &copts->quirks_mode },
383
- { allow_invalid_unicode_sym, &copts->allow_invalid },
384
- { Qnil, 0 }
385
- };
386
- YesNoOpt o;
387
- volatile VALUE v;
388
- size_t len;
389
-
390
- if (T_HASH != rb_type(ropts)) {
391
- return;
392
- }
393
- if (Qtrue == rb_funcall(ropts, has_key_id, 1, indent_sym)) {
394
- v = rb_hash_lookup(ropts, indent_sym);
395
- switch (rb_type(v)) {
396
- case T_NIL:
397
- copts->dump_opts.indent_size = 0;
398
- *copts->dump_opts.indent_str = '\0';
399
- copts->indent = 0;
400
- break;
401
- case T_FIXNUM:
402
- copts->dump_opts.indent_size = 0;
403
- *copts->dump_opts.indent_str = '\0';
404
- copts->indent = FIX2INT(v);
405
- break;
406
- case T_STRING:
407
- if (sizeof(copts->dump_opts.indent_str) <= (len = RSTRING_LEN(v))) {
408
- rb_raise(rb_eArgError, "indent string is limited to %lu characters.", sizeof(copts->dump_opts.indent_str));
409
- }
410
- strcpy(copts->dump_opts.indent_str, StringValuePtr(v));
411
- copts->dump_opts.indent_size = (uint8_t)len;
412
- copts->indent = 0;
413
- break;
414
- default:
415
- rb_raise(rb_eTypeError, "indent must be a Fixnum, String, or nil.");
416
- break;
417
- }
554
+ bool oj_hash_has_key(VALUE hash, VALUE key) {
555
+ if (Qundef == rb_hash_lookup2(hash, key, Qundef)) {
556
+ return false;
418
557
  }
419
- if (Qnil != (v = rb_hash_lookup(ropts, float_prec_sym))) {
420
- int n;
558
+ return true;
559
+ }
560
+
561
+ bool set_yesno_options(VALUE key, VALUE value, Options copts) {
562
+ struct _yesNoOpt ynos[] = {{circular_sym, &copts->circular},
563
+ {auto_define_sym, &copts->auto_define},
564
+ {symbol_keys_sym, &copts->sym_key},
565
+ {class_cache_sym, &copts->class_cache},
566
+ {bigdecimal_as_decimal_sym, &copts->bigdec_as_num},
567
+ {use_to_hash_sym, &copts->to_hash},
568
+ {use_to_json_sym, &copts->to_json},
569
+ {use_as_json_sym, &copts->as_json},
570
+ {use_raw_json_sym, &copts->raw_json},
571
+ {nilnil_sym, &copts->nilnil},
572
+ {allow_blank_sym, &copts->nilnil}, // same as nilnil
573
+ {empty_string_sym, &copts->empty_string},
574
+ {allow_gc_sym, &copts->allow_gc},
575
+ {oj_quirks_mode_sym, &copts->quirks_mode},
576
+ {allow_invalid_unicode_sym, &copts->allow_invalid},
577
+ {oj_allow_nan_sym, &copts->allow_nan},
578
+ {oj_trace_sym, &copts->trace},
579
+ {oj_safe_sym, &copts->safe},
580
+ {ignore_under_sym, &copts->ignore_under},
581
+ {oj_create_additions_sym, &copts->create_ok},
582
+ {cache_keys_sym, &copts->cache_keys},
583
+ {Qnil, 0}};
584
+ YesNoOpt o;
585
+
586
+ for (o = ynos; 0 != o->attr; o++) {
587
+ if (key == o->sym) {
588
+ if (Qnil == value) {
589
+ *o->attr = NotSet;
590
+ } else if (Qtrue == value) {
591
+ *o->attr = Yes;
592
+ } else if (Qfalse == value) {
593
+ *o->attr = No;
594
+ } else {
595
+ rb_raise(rb_eArgError, "%s must be true, false, or nil.", rb_id2name(key));
596
+ }
597
+ return true;
598
+ }
599
+ }
600
+ return false;
601
+ }
602
+
603
+ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
604
+ Options copts = (Options)opts;
605
+ size_t len;
606
+
607
+ if (set_yesno_options(k, v, copts)) {
608
+ return ST_CONTINUE;
609
+ }
610
+
611
+ if (oj_indent_sym == k) {
612
+ switch (rb_type(v)) {
613
+ case T_NIL:
614
+ copts->dump_opts.indent_size = 0;
615
+ *copts->dump_opts.indent_str = '\0';
616
+ copts->indent = 0;
617
+ break;
618
+ case T_FIXNUM:
619
+ copts->dump_opts.indent_size = 0;
620
+ *copts->dump_opts.indent_str = '\0';
621
+ copts->indent = FIX2INT(v);
622
+ break;
623
+ case T_STRING:
624
+ if (sizeof(copts->dump_opts.indent_str) <= (len = RSTRING_LEN(v))) {
625
+ rb_raise(rb_eArgError,
626
+ "indent string is limited to %lu characters.",
627
+ (unsigned long)sizeof(copts->dump_opts.indent_str));
628
+ }
629
+ strcpy(copts->dump_opts.indent_str, StringValuePtr(v));
630
+ copts->dump_opts.indent_size = (uint8_t)len;
631
+ copts->indent = 0;
632
+ break;
633
+ default: rb_raise(rb_eTypeError, "indent must be a Fixnum, String, or nil."); break;
634
+ }
635
+ } else if (float_prec_sym == k) {
636
+ int n;
421
637
 
422
638
  #ifdef RUBY_INTEGER_UNIFICATION
423
- if (rb_cInteger != rb_obj_class(v)) {
424
- rb_raise(rb_eArgError, ":float_precision must be a Integer.");
425
- }
639
+ if (rb_cInteger != rb_obj_class(v)) {
640
+ rb_raise(rb_eArgError, ":float_precision must be a Integer.");
641
+ }
426
642
  #else
427
- if (rb_cFixnum != rb_obj_class(v)) {
428
- rb_raise(rb_eArgError, ":float_precision must be a Fixnum.");
429
- }
643
+ if (T_FIXNUM != rb_type(v)) {
644
+ rb_raise(rb_eArgError, ":float_precision must be a Fixnum.");
645
+ }
430
646
  #endif
431
- Check_Type(v, T_FIXNUM);
432
- n = FIX2INT(v);
433
- if (0 >= n) {
434
- *copts->float_fmt = '\0';
435
- copts->float_prec = 0;
436
- } else {
437
- if (20 < n) {
438
- n = 20;
439
- }
440
- sprintf(copts->float_fmt, "%%0.%dg", n);
441
- copts->float_prec = n;
442
- }
443
- }
444
- if (Qnil != (v = rb_hash_lookup(ropts, sec_prec_sym))) {
445
- int n;
647
+ n = FIX2INT(v);
648
+ if (0 >= n) {
649
+ *copts->float_fmt = '\0';
650
+ copts->float_prec = 0;
651
+ } else {
652
+ if (20 < n) {
653
+ n = 20;
654
+ }
655
+ sprintf(copts->float_fmt, "%%0.%dg", n);
656
+ copts->float_prec = n;
657
+ }
658
+ } else if (cache_str_sym == k || cache_string_sym == k) {
659
+ int n;
446
660
 
447
661
  #ifdef RUBY_INTEGER_UNIFICATION
448
- if (rb_cInteger != rb_obj_class(v)) {
449
- rb_raise(rb_eArgError, ":second_precision must be a Integer.");
450
- }
662
+ if (rb_cInteger != rb_obj_class(v)) {
663
+ rb_raise(rb_eArgError, ":cache_str must be a Integer.");
664
+ }
451
665
  #else
452
- if (rb_cFixnum != rb_obj_class(v)) {
453
- rb_raise(rb_eArgError, ":second_precision must be a Fixnum.");
454
- }
666
+ if (T_FIXNUM != rb_type(v)) {
667
+ rb_raise(rb_eArgError, ":cache_str must be a Fixnum.");
668
+ }
455
669
  #endif
456
- n = NUM2INT(v);
457
- if (0 > n) {
458
- n = 0;
459
- } else if (9 < n) {
460
- n = 9;
461
- }
462
- copts->sec_prec = n;
463
- }
464
- if (Qnil != (v = rb_hash_lookup(ropts, mode_sym))) {
465
- if (object_sym == v) {
466
- copts->mode = ObjectMode;
467
- } else if (strict_sym == v) {
468
- copts->mode = StrictMode;
469
- } else if (compat_sym == v) {
470
- copts->mode = CompatMode;
471
- } else if (null_sym == v) {
472
- copts->mode = NullMode;
473
- } else {
474
- rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, or :null.");
475
- }
476
- }
477
- if (Qnil != (v = rb_hash_lookup(ropts, time_format_sym))) {
478
- if (unix_sym == v) {
479
- copts->time_format = UnixTime;
480
- } else if (unix_zone_sym == v) {
481
- copts->time_format = UnixZTime;
482
- } else if (xmlschema_sym == v) {
483
- copts->time_format = XmlTime;
484
- } else if (ruby_sym == v) {
485
- copts->time_format = RubyTime;
486
- } else {
487
- rb_raise(rb_eArgError, ":time_format must be :unix, :unix_zone, :xmlschema, or :ruby.");
488
- }
489
- }
490
- if (Qnil != (v = rb_hash_lookup(ropts, escape_mode_sym))) {
491
- if (newline_sym == v) {
492
- copts->escape_mode = NLEsc;
493
- } else if (json_sym == v) {
494
- copts->escape_mode = JSONEsc;
495
- } else if (xss_safe_sym == v) {
496
- copts->escape_mode = XSSEsc;
497
- } else if (ascii_sym == v) {
498
- copts->escape_mode = ASCIIEsc;
499
- } else {
500
- rb_raise(rb_eArgError, ":encoding must be :newline, :json, :xss_safe, or :ascii.");
501
- }
502
- }
503
- if (Qnil != (v = rb_hash_lookup(ropts, bigdecimal_load_sym))) {
504
- if (bigdecimal_sym == v || Qtrue == v) {
505
- copts->bigdec_load = BigDec;
506
- } else if (float_sym == v) {
507
- copts->bigdec_load = FloatDec;
508
- } else if (auto_sym == v || Qfalse == v) {
509
- copts->bigdec_load = AutoDec;
510
- } else {
511
- rb_raise(rb_eArgError, ":bigdecimal_load must be :bigdecimal, :float, or :auto.");
512
- }
513
- }
514
- if (Qtrue == rb_funcall(ropts, has_key_id, 1, create_id_sym)) {
515
- v = rb_hash_lookup(ropts, create_id_sym);
516
- if (Qnil == v) {
517
- if (json_class != oj_default_options.create_id) {
518
- xfree((char*)oj_default_options.create_id);
519
- }
520
- copts->create_id = NULL;
521
- copts->create_id_len = 0;
522
- } else if (T_STRING == rb_type(v)) {
523
- const char *str = StringValuePtr(v);
524
-
525
- len = RSTRING_LEN(v);
526
- if (len != copts->create_id_len ||
527
- 0 != strcmp(copts->create_id, str)) {
528
- copts->create_id = ALLOC_N(char, len + 1);
529
- strcpy((char*)copts->create_id, str);
530
- copts->create_id_len = len;
531
- }
532
- } else {
533
- rb_raise(rb_eArgError, ":create_id must be string.");
534
- }
535
- }
536
- for (o = ynos; 0 != o->attr; o++) {
537
- if (Qnil != (v = rb_hash_lookup(ropts, o->sym))) {
538
- if (Qtrue == v) {
539
- *o->attr = Yes;
540
- } else if (Qfalse == v) {
541
- *o->attr = No;
542
- } else {
543
- rb_raise(rb_eArgError, "%s must be true or false.", rb_id2name(SYM2ID(o->sym)));
544
- }
545
- }
546
- }
547
- if (Qtrue == rb_funcall(ropts, has_key_id, 1, space_sym)) {
548
- if (Qnil == (v = rb_hash_lookup(ropts, space_sym))) {
549
- copts->dump_opts.after_size = 0;
550
- *copts->dump_opts.after_sep = '\0';
551
- } else {
552
- rb_check_type(v, T_STRING);
553
- if (sizeof(copts->dump_opts.after_sep) <= (len = RSTRING_LEN(v))) {
554
- rb_raise(rb_eArgError, "space string is limited to %lu characters.", sizeof(copts->dump_opts.after_sep));
555
- }
556
- strcpy(copts->dump_opts.after_sep, StringValuePtr(v));
557
- copts->dump_opts.after_size = (uint8_t)len;
558
- }
559
- }
560
- if (Qtrue == rb_funcall(ropts, has_key_id, 1, space_before_sym)) {
561
- if (Qnil == (v = rb_hash_lookup(ropts, space_before_sym))) {
562
- copts->dump_opts.before_size = 0;
563
- *copts->dump_opts.before_sep = '\0';
564
- } else {
565
- rb_check_type(v, T_STRING);
566
- if (sizeof(copts->dump_opts.before_sep) <= (len = RSTRING_LEN(v))) {
567
- rb_raise(rb_eArgError, "sapce_before string is limited to %lu characters.", sizeof(copts->dump_opts.before_sep));
568
- }
569
- strcpy(copts->dump_opts.before_sep, StringValuePtr(v));
570
- copts->dump_opts.before_size = (uint8_t)len;
571
- }
572
- }
573
- if (Qtrue == rb_funcall(ropts, has_key_id, 1, object_nl_sym)) {
574
- if (Qnil == (v = rb_hash_lookup(ropts, object_nl_sym))) {
575
- copts->dump_opts.hash_size = 0;
576
- *copts->dump_opts.hash_nl = '\0';
577
- } else {
578
- rb_check_type(v, T_STRING);
579
- if (sizeof(copts->dump_opts.hash_nl) <= (len = RSTRING_LEN(v))) {
580
- rb_raise(rb_eArgError, "object_nl string is limited to %lu characters.", sizeof(copts->dump_opts.hash_nl));
581
- }
582
- strcpy(copts->dump_opts.hash_nl, StringValuePtr(v));
583
- copts->dump_opts.hash_size = (uint8_t)len;
584
- }
585
- }
586
- if (Qtrue == rb_funcall(ropts, has_key_id, 1, array_nl_sym)) {
587
- if (Qnil == (v = rb_hash_lookup(ropts, array_nl_sym))) {
588
- copts->dump_opts.array_size = 0;
589
- *copts->dump_opts.array_nl = '\0';
590
- } else {
591
- rb_check_type(v, T_STRING);
592
- if (sizeof(copts->dump_opts.array_nl) <= (len = RSTRING_LEN(v))) {
593
- rb_raise(rb_eArgError, "array_nl string is limited to %lu characters.", sizeof(copts->dump_opts.array_nl));
594
- }
595
- strcpy(copts->dump_opts.array_nl, StringValuePtr(v));
596
- copts->dump_opts.array_size = (uint8_t)len;
597
- }
598
- }
599
- if (Qnil != (v = rb_hash_lookup(ropts, nan_sym))) {
600
- if (null_sym == v) {
601
- copts->dump_opts.nan_dump = NullNan;
602
- } else if (huge_sym == v) {
603
- copts->dump_opts.nan_dump = HugeNan;
604
- } else if (word_sym == v) {
605
- copts->dump_opts.nan_dump = WordNan;
606
- } else if (raise_sym == v) {
607
- copts->dump_opts.nan_dump = RaiseNan;
608
- } else if (auto_sym == v) {
609
- copts->dump_opts.nan_dump = AutoNan;
610
- } else {
611
- rb_raise(rb_eArgError, ":nan must be :null, :huge, :word, :raise, or :auto.");
612
- }
670
+ n = FIX2INT(v);
671
+ if (0 >= n) {
672
+ copts->cache_str = 0;
673
+ } else {
674
+ if (32 < n) {
675
+ n = 32;
676
+ }
677
+ copts->cache_str = (char)n;
678
+ }
679
+ } else if (sec_prec_sym == k) {
680
+ int n;
681
+
682
+ #ifdef RUBY_INTEGER_UNIFICATION
683
+ if (rb_cInteger != rb_obj_class(v)) {
684
+ rb_raise(rb_eArgError, ":second_precision must be a Integer.");
685
+ }
686
+ #else
687
+ if (T_FIXNUM != rb_type(v)) {
688
+ rb_raise(rb_eArgError, ":second_precision must be a Fixnum.");
689
+ }
690
+ #endif
691
+ n = NUM2INT(v);
692
+ if (0 > n) {
693
+ n = 0;
694
+ copts->sec_prec_set = false;
695
+ } else if (9 < n) {
696
+ n = 9;
697
+ copts->sec_prec_set = true;
698
+ } else {
699
+ copts->sec_prec_set = true;
700
+ }
701
+ copts->sec_prec = n;
702
+ } else if (mode_sym == k) {
703
+ if (wab_sym == v) {
704
+ copts->mode = WabMode;
705
+ } else if (object_sym == v) {
706
+ copts->mode = ObjectMode;
707
+ } else if (strict_sym == v) {
708
+ copts->mode = StrictMode;
709
+ } else if (compat_sym == v || json_sym == v) {
710
+ copts->mode = CompatMode;
711
+ } else if (null_sym == v) {
712
+ copts->mode = NullMode;
713
+ } else if (custom_sym == v) {
714
+ copts->mode = CustomMode;
715
+ } else if (rails_sym == v) {
716
+ copts->mode = RailsMode;
717
+ } else {
718
+ rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, :null, :custom, :rails, or :wab.");
719
+ }
720
+ } else if (time_format_sym == k) {
721
+ if (unix_sym == v) {
722
+ copts->time_format = UnixTime;
723
+ } else if (unix_zone_sym == v) {
724
+ copts->time_format = UnixZTime;
725
+ } else if (xmlschema_sym == v) {
726
+ copts->time_format = XmlTime;
727
+ } else if (ruby_sym == v) {
728
+ copts->time_format = RubyTime;
729
+ } else {
730
+ rb_raise(rb_eArgError, ":time_format must be :unix, :unix_zone, :xmlschema, or :ruby.");
731
+ }
732
+ } else if (escape_mode_sym == k) {
733
+ if (newline_sym == v) {
734
+ copts->escape_mode = NLEsc;
735
+ } else if (json_sym == v) {
736
+ copts->escape_mode = JSONEsc;
737
+ } else if (xss_safe_sym == v) {
738
+ copts->escape_mode = XSSEsc;
739
+ } else if (ascii_sym == v) {
740
+ copts->escape_mode = ASCIIEsc;
741
+ } else if (unicode_xss_sym == v) {
742
+ copts->escape_mode = JXEsc;
743
+ } else {
744
+ rb_raise(rb_eArgError, ":encoding must be :newline, :json, :xss_safe, :unicode_xss, or :ascii.");
745
+ }
746
+ } else if (bigdecimal_load_sym == k) {
747
+ if (Qnil == v) {
748
+ return ST_CONTINUE;
749
+ }
750
+
751
+ if (bigdecimal_sym == v || Qtrue == v) {
752
+ copts->bigdec_load = BigDec;
753
+ } else if (float_sym == v) {
754
+ copts->bigdec_load = FloatDec;
755
+ } else if (fast_sym == v) {
756
+ copts->bigdec_load = FastDec;
757
+ } else if (auto_sym == v || Qfalse == v) {
758
+ copts->bigdec_load = AutoDec;
759
+ } else {
760
+ rb_raise(rb_eArgError, ":bigdecimal_load must be :bigdecimal, :float, or :auto.");
761
+ }
762
+ } else if (compat_bigdecimal_sym == k) {
763
+ if (Qnil == v) {
764
+ return ST_CONTINUE;
765
+ }
766
+
767
+ copts->compat_bigdec = (Qtrue == v);
768
+ } else if (oj_decimal_class_sym == k) {
769
+ if (rb_cFloat == v) {
770
+ copts->compat_bigdec = false;
771
+ } else if (oj_bigdecimal_class == v) {
772
+ copts->compat_bigdec = true;
773
+ } else {
774
+ rb_raise(rb_eArgError, ":decimal_class must be BigDecimal or Float.");
775
+ }
776
+ } else if (create_id_sym == k) {
777
+ if (Qnil == v) {
778
+ if (oj_json_class != oj_default_options.create_id && NULL != copts->create_id) {
779
+ xfree((char *)oj_default_options.create_id);
780
+ }
781
+ copts->create_id = NULL;
782
+ copts->create_id_len = 0;
783
+ } else if (T_STRING == rb_type(v)) {
784
+ const char *str = StringValuePtr(v);
785
+
786
+ len = RSTRING_LEN(v);
787
+ if (len != copts->create_id_len || 0 != strcmp(copts->create_id, str)) {
788
+ copts->create_id = ALLOC_N(char, len + 1);
789
+ strcpy((char *)copts->create_id, str);
790
+ copts->create_id_len = len;
791
+ }
792
+ } else {
793
+ rb_raise(rb_eArgError, ":create_id must be string.");
794
+ }
795
+ } else if (oj_space_sym == k) {
796
+ if (Qnil == v) {
797
+ copts->dump_opts.after_size = 0;
798
+ *copts->dump_opts.after_sep = '\0';
799
+ } else {
800
+ rb_check_type(v, T_STRING);
801
+ if (sizeof(copts->dump_opts.after_sep) <= (len = RSTRING_LEN(v))) {
802
+ rb_raise(rb_eArgError,
803
+ "space string is limited to %lu characters.",
804
+ (unsigned long)sizeof(copts->dump_opts.after_sep));
805
+ }
806
+ strcpy(copts->dump_opts.after_sep, StringValuePtr(v));
807
+ copts->dump_opts.after_size = (uint8_t)len;
808
+ }
809
+ } else if (oj_space_before_sym == k) {
810
+ if (Qnil == v) {
811
+ copts->dump_opts.before_size = 0;
812
+ *copts->dump_opts.before_sep = '\0';
813
+ } else {
814
+ rb_check_type(v, T_STRING);
815
+ if (sizeof(copts->dump_opts.before_sep) <= (len = RSTRING_LEN(v))) {
816
+ rb_raise(rb_eArgError,
817
+ "sapce_before string is limited to %lu characters.",
818
+ (unsigned long)sizeof(copts->dump_opts.before_sep));
819
+ }
820
+ strcpy(copts->dump_opts.before_sep, StringValuePtr(v));
821
+ copts->dump_opts.before_size = (uint8_t)len;
822
+ }
823
+ } else if (oj_object_nl_sym == k) {
824
+ if (Qnil == v) {
825
+ copts->dump_opts.hash_size = 0;
826
+ *copts->dump_opts.hash_nl = '\0';
827
+ } else {
828
+ rb_check_type(v, T_STRING);
829
+ if (sizeof(copts->dump_opts.hash_nl) <= (len = RSTRING_LEN(v))) {
830
+ rb_raise(rb_eArgError,
831
+ "object_nl string is limited to %lu characters.",
832
+ (unsigned long)sizeof(copts->dump_opts.hash_nl));
833
+ }
834
+ strcpy(copts->dump_opts.hash_nl, StringValuePtr(v));
835
+ copts->dump_opts.hash_size = (uint8_t)len;
836
+ }
837
+ } else if (oj_array_nl_sym == k) {
838
+ if (Qnil == v) {
839
+ copts->dump_opts.array_size = 0;
840
+ *copts->dump_opts.array_nl = '\0';
841
+ } else {
842
+ rb_check_type(v, T_STRING);
843
+ if (sizeof(copts->dump_opts.array_nl) <= (len = RSTRING_LEN(v))) {
844
+ rb_raise(rb_eArgError,
845
+ "array_nl string is limited to %lu characters.",
846
+ (unsigned long)sizeof(copts->dump_opts.array_nl));
847
+ }
848
+ strcpy(copts->dump_opts.array_nl, StringValuePtr(v));
849
+ copts->dump_opts.array_size = (uint8_t)len;
850
+ }
851
+ } else if (nan_sym == k) {
852
+ if (Qnil == v) {
853
+ return ST_CONTINUE;
854
+ }
855
+ if (null_sym == v) {
856
+ copts->dump_opts.nan_dump = NullNan;
857
+ } else if (huge_sym == v) {
858
+ copts->dump_opts.nan_dump = HugeNan;
859
+ } else if (word_sym == v) {
860
+ copts->dump_opts.nan_dump = WordNan;
861
+ } else if (raise_sym == v) {
862
+ copts->dump_opts.nan_dump = RaiseNan;
863
+ } else if (auto_sym == v) {
864
+ copts->dump_opts.nan_dump = AutoNan;
865
+ } else {
866
+ rb_raise(rb_eArgError, ":nan must be :null, :huge, :word, :raise, or :auto.");
867
+ }
868
+ } else if (omit_nil_sym == k) {
869
+ if (Qnil == v) {
870
+ return ST_CONTINUE;
871
+ }
872
+ if (Qtrue == v) {
873
+ copts->dump_opts.omit_nil = true;
874
+ } else if (Qfalse == v) {
875
+ copts->dump_opts.omit_nil = false;
876
+ } else {
877
+ rb_raise(rb_eArgError, ":omit_nil must be true or false.");
878
+ }
879
+ } else if (oj_ascii_only_sym == k) {
880
+ // This is here only for backwards compatibility with the original Oj.
881
+ if (Qtrue == v) {
882
+ copts->escape_mode = ASCIIEsc;
883
+ } else if (Qfalse == v) {
884
+ copts->escape_mode = JSONEsc;
885
+ }
886
+ } else if (oj_hash_class_sym == k) {
887
+ if (Qnil == v) {
888
+ copts->hash_class = Qnil;
889
+ } else {
890
+ rb_check_type(v, T_CLASS);
891
+ copts->hash_class = v;
892
+ }
893
+ } else if (oj_object_class_sym == k) {
894
+ if (Qnil == v) {
895
+ copts->hash_class = Qnil;
896
+ } else {
897
+ rb_check_type(v, T_CLASS);
898
+ copts->hash_class = v;
899
+ }
900
+ } else if (oj_array_class_sym == k) {
901
+ if (Qnil == v) {
902
+ copts->array_class = Qnil;
903
+ } else {
904
+ rb_check_type(v, T_CLASS);
905
+ copts->array_class = v;
906
+ }
907
+ } else if (ignore_sym == k) {
908
+ xfree(copts->ignore);
909
+ copts->ignore = NULL;
910
+ if (Qnil != v) {
911
+ int cnt;
912
+
913
+ rb_check_type(v, T_ARRAY);
914
+ cnt = (int)RARRAY_LEN(v);
915
+ if (0 < cnt) {
916
+ int i;
917
+
918
+ copts->ignore = ALLOC_N(VALUE, cnt + 1);
919
+ for (i = 0; i < cnt; i++) {
920
+ copts->ignore[i] = RARRAY_AREF(v, i);
921
+ }
922
+ copts->ignore[i] = Qnil;
923
+ }
924
+ }
925
+ } else if (integer_range_sym == k) {
926
+ if (Qnil == v) {
927
+ return ST_CONTINUE;
928
+ }
929
+ if (TYPE(v) == T_STRUCT && rb_obj_class(v) == rb_cRange) {
930
+ VALUE min = rb_funcall(v, oj_begin_id, 0);
931
+ VALUE max = rb_funcall(v, oj_end_id, 0);
932
+
933
+ if (TYPE(min) != T_FIXNUM || TYPE(max) != T_FIXNUM) {
934
+ rb_raise(rb_eArgError, ":integer_range range bounds is not Fixnum.");
935
+ }
936
+
937
+ copts->int_range_min = FIX2LONG(min);
938
+ copts->int_range_max = FIX2LONG(max);
939
+ } else if (Qfalse != v) {
940
+ rb_raise(rb_eArgError, ":integer_range must be a range of Fixnum.");
941
+ }
942
+ } else if (symbol_keys_sym == k || oj_symbolize_names_sym == k) {
943
+ if (Qnil == v) {
944
+ return ST_CONTINUE;
945
+ }
946
+ copts->sym_key = (Qtrue == v) ? Yes : No;
613
947
  }
614
- copts->dump_opts.use = (0 < copts->dump_opts.indent_size ||
615
- 0 < copts->dump_opts.after_size ||
616
- 0 < copts->dump_opts.before_size ||
617
- 0 < copts->dump_opts.hash_size ||
618
- 0 < copts->dump_opts.array_size);
619
- if (Qnil != (v = rb_hash_lookup(ropts, omit_nil_sym))) {
620
- if (Qtrue == v) {
621
- copts->dump_opts.omit_nil = true;
622
- } else if (Qfalse == v) {
623
- copts->dump_opts.omit_nil = false;
624
- } else {
625
- rb_raise(rb_eArgError, ":omit_nil must be true or false.");
626
- }
948
+ return ST_CONTINUE;
949
+ }
950
+
951
+ void oj_parse_options(VALUE ropts, Options copts) {
952
+ if (T_HASH != rb_type(ropts)) {
953
+ return;
627
954
  }
628
- // This is here only for backwards compatibility with the original Oj.
629
- v = rb_hash_lookup(ropts, ascii_only_sym);
630
- if (Qtrue == v) {
631
- copts->escape_mode = ASCIIEsc;
632
- } else if (Qfalse == v) {
633
- copts->escape_mode = JSONEsc;
955
+
956
+ rb_hash_foreach(ropts, parse_options_cb, (VALUE)copts);
957
+ oj_parse_opt_match_string(&copts->str_rx, ropts);
958
+
959
+ copts->dump_opts.use = (0 < copts->dump_opts.indent_size || 0 < copts->dump_opts.after_size ||
960
+ 0 < copts->dump_opts.before_size || 0 < copts->dump_opts.hash_size ||
961
+ 0 < copts->dump_opts.array_size);
962
+ return;
963
+ }
964
+
965
+ static int match_string_cb(VALUE key, VALUE value, VALUE rx) {
966
+ RxClass rc = (RxClass)rx;
967
+
968
+ if (T_CLASS != rb_type(value)) {
969
+ rb_raise(rb_eArgError, "for :match_string, the hash values must be a Class.");
634
970
  }
635
- if (Qtrue == rb_funcall(ropts, has_key_id, 1, hash_class_sym)) {
636
- if (Qnil == (v = rb_hash_lookup(ropts, hash_class_sym))) {
637
- copts->hash_class = Qnil;
638
- } else {
639
- rb_check_type(v, T_CLASS);
640
- copts->hash_class = v;
641
- }
971
+ switch (rb_type(key)) {
972
+ case T_REGEXP: oj_rxclass_rappend(rc, key, value); break;
973
+ case T_STRING:
974
+ if (0 != oj_rxclass_append(rc, StringValuePtr(key), value)) {
975
+ rb_raise(rb_eArgError, "%s", rc->err);
976
+ }
977
+ break;
978
+ default: rb_raise(rb_eArgError, "for :match_string, keys must either a String or RegExp."); break;
642
979
  }
980
+ return ST_CONTINUE;
643
981
  }
644
982
 
645
- /* Document-method: strict_load
646
- * call-seq: strict_load(json, options) => Hash, Array, String, Fixnum, Float, true, false, or nil
647
- *
648
- * Parses a JSON document String into an Hash, Array, String, Fixnum, Float,
649
- * true, false, or nil. It parses using a mode that is strict in that it maps
650
- * each primitive JSON type to a similar Ruby type. The :create_id is not
651
- * honored in this mode. Note that a Ruby Hash is used to represent the JSON
652
- * Object type. These two are not the same since the JSON Object type can have
653
- * repeating entries with the same key and Ruby Hash can not.
654
- *
655
- * When used with a document that has multiple JSON elements the block, if
656
- * any, will be yielded to. If no block then the last element read will be
657
- * returned.
658
- *
659
- * Raises an exception if the JSON is malformed or the classes specified are not
660
- * valid. If the input is not a valid JSON document (an empty string is not a
661
- * valid JSON document) an exception is raised.
662
- *
663
- * A block can also be provided with a single argument. That argument will be
664
- * the parsed JSON document. This is useful when parsing a string that includes
665
- * multiple JSON documents.
666
- *
667
- * @param [String|IO] json JSON String or an Object that responds to read()
668
- * @param [Hash] options load options (same as default_options)
669
- */
670
-
671
- /* Document-method: compat_load
672
- * call-seq: compat_load(json, options) => Object, Hash, Array, String, Fixnum, Float, true, false, or nil
673
- *
674
- * Parses a JSON document String into an Object, Hash, Array, String, Fixnum,
675
- * Float, true, false, or nil. It parses using a mode that is generally
676
- * compatible with other Ruby JSON parsers in that it will create objects based
677
- * on the :create_id value. It is not compatible in every way to every other
678
- * parser though as each parser has it's own variations.
679
- *
680
- * When used with a document that has multiple JSON elements the block, if
681
- * any, will be yielded to. If no block then the last element read will be
682
- * returned.
683
- *
684
- * Raises an exception if the JSON is malformed or the classes specified are not
685
- * valid. If the input is not a valid JSON document (an empty string is not a
686
- * valid JSON document) an exception is raised.
687
- *
688
- * A block can also be provided with a single argument. That argument will be
689
- * the parsed JSON document. This is useful when parsing a string that includes
690
- * multiple JSON documents.
691
- *
692
- * @param [String|IO] json JSON String or an Object that responds to read()
693
- * @param [Hash] options load options (same as default_options)
694
- */
983
+ void oj_parse_opt_match_string(RxClass rc, VALUE ropts) {
984
+ VALUE v;
695
985
 
696
- /* Document-method: object_load
697
- * call-seq: object_load(json, options) => Object, Hash, Array, String, Fixnum, Float, true, false, or nil
698
- *
699
- * Parses a JSON document String into an Object, Hash, Array, String, Fixnum,
700
- * Float, true, false, or nil. In the :object mode the JSON should have been
701
- * generated by Oj.dump(). The parser will reconstitute the original marshalled
702
- * or dumped Object. The :auto_define and :circular options have meaning with
703
- * this parsing mode.
704
- *
705
- * When used with a document that has multiple JSON elements the block, if
706
- * any, will be yielded to. If no block then the last element read will be
707
- * returned.
708
- *
709
- * Raises an exception if the JSON is malformed or the classes specified are not
710
- * valid. If the input is not a valid JSON document (an empty string is not a
711
- * valid JSON document) an exception is raised.
712
- *
713
- * Note: Oj is not able to automatically deserialize all classes that are a
714
- * subclass of a Ruby Exception. Only exception that take one required string
715
- * argument in the initialize() method are supported. This is an example of how
716
- * to write an Exception subclass that supports both a single string intializer
717
- * and an Exception as an argument. Additional optional arguments can be added
718
- * as well.
719
- *
720
- * The reason for this restriction has to do with a design decision on the part
721
- * of the Ruby developers. Exceptions are special Objects. They do not follow the
722
- * rules of other Objects. Exceptions have 'mesg' and a 'bt' attribute. Note that
723
- * these are not '@mesg' and '@bt'. They can not be set using the normal C or
724
- * Ruby calls. The only way I have found to set the 'mesg' attribute is through
725
- * the initializer. Unfortunately that means any subclass that provides a
726
- * different initializer can not be automatically decoded. A way around this is
727
- * to use a create function but this example shows an alternative.
728
- *
729
- * A block can also be provided with a single argument. That argument will be
730
- * the parsed JSON document. This is useful when parsing a string that includes
731
- * multiple JSON documents.
732
- *
733
- * @param [String|IO] json JSON String or an Object that responds to read()
734
- * @param [Hash] options load options (same as default_options)
735
- */
986
+ if (Qnil != (v = rb_hash_lookup(ropts, match_string_sym))) {
987
+ rb_check_type(v, T_HASH);
988
+ // Zero out rc. Pattern are not appended but override.
989
+ rc->head = NULL;
990
+ rc->tail = NULL;
991
+ *rc->err = '\0';
992
+ rb_hash_foreach(v, match_string_cb, (VALUE)rc);
993
+ }
994
+ }
736
995
 
737
- /* call-seq: load(json, options) => Object, Hash, Array, String, Fixnum, Float, true, false, or nil
996
+ /* Document-method: load
997
+ * call-seq: load(json, options={}) { _|_obj, start, len_|_ }
738
998
  *
739
999
  * Parses a JSON document String into a Object, Hash, Array, String, Fixnum,
740
1000
  * Float, true, false, or nil according to the default mode or the mode
@@ -750,54 +1010,71 @@ oj_parse_options(VALUE ropts, Options copts) {
750
1010
  * a file object is passed as the first argument. A stream input will be parsed
751
1011
  * using a stream parser but others use the slightly faster string parser.
752
1012
  *
753
- * A block can also be provided with a single argument. That argument will be
754
- * the parsed JSON document. This is useful when parsing a string that includes
755
- * multiple JSON documents.
1013
+ * A block can be provided with a single argument. That argument will be the
1014
+ * parsed JSON document. This is useful when parsing a string that includes
1015
+ * multiple JSON documents. The block can take up to 3 arguments, the parsed
1016
+ * object, the position in the string or stream of the start of the JSON for
1017
+ * that object, and the length of the JSON for that object plus trailing
1018
+ * whitespace.
1019
+ *
1020
+ * - *json* [_String_|_IO_] JSON String or an Object that responds to read()
1021
+ * - *options* [_Hash_] load options (same as default_options)
1022
+ * - *obj* [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_] parsed object.
1023
+ * - *start* [_optional, _Integer_] start position of parsed JSON for obj.
1024
+ * - *len* [_optional, _Integer_] length of parsed JSON for obj.
756
1025
  *
757
- * @param [String|IO] json JSON String or an Object that responds to read()
758
- * @param [Hash] options load options (same as default_options)
1026
+ * Returns [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_]
759
1027
  */
760
- static VALUE
761
- load(int argc, VALUE *argv, VALUE self) {
762
- Mode mode = oj_default_options.mode;
1028
+ static VALUE load(int argc, VALUE *argv, VALUE self) {
1029
+ Mode mode = oj_default_options.mode;
763
1030
 
764
1031
  if (1 > argc) {
765
- rb_raise(rb_eArgError, "Wrong number of arguments to load().");
1032
+ rb_raise(rb_eArgError, "Wrong number of arguments to load().");
766
1033
  }
767
1034
  if (2 <= argc) {
768
- VALUE ropts = argv[1];
769
- VALUE v;
770
-
771
- Check_Type(ropts, T_HASH);
772
- if (Qnil != (v = rb_hash_lookup(ropts, mode_sym))) {
773
- if (object_sym == v) {
774
- mode = ObjectMode;
775
- } else if (strict_sym == v) {
776
- mode = StrictMode;
777
- } else if (compat_sym == v) {
778
- mode = CompatMode;
779
- } else if (null_sym == v) {
780
- mode = NullMode;
781
- } else {
782
- rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, or :null.");
783
- }
784
- }
1035
+ VALUE ropts = argv[1];
1036
+ VALUE v;
1037
+
1038
+ if (Qnil != ropts || CompatMode != mode) {
1039
+ Check_Type(ropts, T_HASH);
1040
+ if (Qnil != (v = rb_hash_lookup(ropts, mode_sym))) {
1041
+ if (object_sym == v) {
1042
+ mode = ObjectMode;
1043
+ } else if (strict_sym == v) {
1044
+ mode = StrictMode;
1045
+ } else if (compat_sym == v || json_sym == v) {
1046
+ mode = CompatMode;
1047
+ } else if (null_sym == v) {
1048
+ mode = NullMode;
1049
+ } else if (custom_sym == v) {
1050
+ mode = CustomMode;
1051
+ } else if (rails_sym == v) {
1052
+ mode = RailsMode;
1053
+ } else if (wab_sym == v) {
1054
+ mode = WabMode;
1055
+ } else {
1056
+ rb_raise(rb_eArgError,
1057
+ ":mode must be :object, :strict, :compat, :null, :custom, :rails, or "
1058
+ ":wab.");
1059
+ }
1060
+ }
1061
+ }
785
1062
  }
786
1063
  switch (mode) {
787
1064
  case StrictMode:
788
- return oj_strict_parse(argc, argv, self);
789
- case NullMode:
1065
+ case NullMode: return oj_strict_parse(argc, argv, self);
790
1066
  case CompatMode:
791
- return oj_compat_parse(argc, argv, self);
1067
+ case RailsMode: return oj_compat_parse(argc, argv, self);
1068
+ case CustomMode: return oj_custom_parse(argc, argv, self);
1069
+ case WabMode: return oj_wab_parse(argc, argv, self);
792
1070
  case ObjectMode:
793
- default:
794
- break;
1071
+ default: break;
795
1072
  }
796
1073
  return oj_object_parse(argc, argv, self);
797
1074
  }
798
1075
 
799
1076
  /* Document-method: load_file
800
- * call-seq: load_file(path, options) => Object, Hash, Array, String, Fixnum, Float, true, false, or nil
1077
+ * call-seq: load_file(path, options={}) { _|_obj, start, len_|_ }
801
1078
  *
802
1079
  * Parses a JSON document String into a Object, Hash, Array, String, Fixnum,
803
1080
  * Float, true, false, or nil according to the default mode or the mode
@@ -815,104 +1092,122 @@ load(int argc, VALUE *argv, VALUE self) {
815
1092
  * This is a stream based parser which allows a large or huge file to be loaded
816
1093
  * without pulling the whole file into memory.
817
1094
  *
818
- * A block can also be provided with a single argument. That argument will be
819
- * the parsed JSON document. This is useful when parsing a string that includes
820
- * multiple JSON documents.
1095
+ * A block can be provided with a single argument. That argument will be the
1096
+ * parsed JSON document. This is useful when parsing a string that includes
1097
+ * multiple JSON documents. The block can take up to 3 arguments, the parsed
1098
+ * object, the position in the string or stream of the start of the JSON for
1099
+ * that object, and the length of the JSON for that object plus trailing
1100
+ * whitespace.
1101
+ *
1102
+ * - *path* [_String_] to a file containing a JSON document
1103
+ * - *options* [_Hash_] load options (same as default_options)
1104
+ * - *obj* [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_] parsed object.
1105
+ * - *start* [_optional, _Integer_] start position of parsed JSON for obj.
1106
+ * - *len* [_optional, _Integer_] length of parsed JSON for obj.
821
1107
  *
822
- * @param [String] path path to a file containing a JSON document
823
- * @param [Hash] options load options (same as default_options)
1108
+ * Returns [_Object_|_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_]
824
1109
  */
825
- static VALUE
826
- load_file(int argc, VALUE *argv, VALUE self) {
827
- char *path;
828
- int fd;
829
- Mode mode = oj_default_options.mode;
830
- struct _ParseInfo pi;
1110
+ static VALUE load_file(int argc, VALUE *argv, VALUE self) {
1111
+ char * path;
1112
+ int fd;
1113
+ Mode mode = oj_default_options.mode;
1114
+ struct _parseInfo pi;
831
1115
 
832
1116
  if (1 > argc) {
833
- rb_raise(rb_eArgError, "Wrong number of arguments to load().");
1117
+ rb_raise(rb_eArgError, "Wrong number of arguments to load().");
834
1118
  }
835
1119
  Check_Type(*argv, T_STRING);
836
- pi.options = oj_default_options;
837
- pi.handler = Qnil;
1120
+ parse_info_init(&pi);
1121
+ pi.options = oj_default_options;
1122
+ pi.handler = Qnil;
838
1123
  pi.err_class = Qnil;
1124
+ pi.max_depth = 0;
839
1125
  if (2 <= argc) {
840
- VALUE ropts = argv[1];
841
- VALUE v;
842
-
843
- Check_Type(ropts, T_HASH);
844
- if (Qnil != (v = rb_hash_lookup(ropts, mode_sym))) {
845
- if (object_sym == v) {
846
- mode = ObjectMode;
847
- } else if (strict_sym == v) {
848
- mode = StrictMode;
849
- } else if (compat_sym == v) {
850
- mode = CompatMode;
851
- } else if (null_sym == v) {
852
- mode = NullMode;
853
- } else {
854
- rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, or :null.");
855
- }
856
- }
1126
+ VALUE ropts = argv[1];
1127
+ VALUE v;
1128
+
1129
+ Check_Type(ropts, T_HASH);
1130
+ if (Qnil != (v = rb_hash_lookup(ropts, mode_sym))) {
1131
+ if (object_sym == v) {
1132
+ mode = ObjectMode;
1133
+ } else if (strict_sym == v) {
1134
+ mode = StrictMode;
1135
+ } else if (compat_sym == v || json_sym == v) {
1136
+ mode = CompatMode;
1137
+ } else if (null_sym == v) {
1138
+ mode = NullMode;
1139
+ } else if (custom_sym == v) {
1140
+ mode = CustomMode;
1141
+ } else if (rails_sym == v) {
1142
+ mode = RailsMode;
1143
+ } else if (wab_sym == v) {
1144
+ mode = WabMode;
1145
+ } else {
1146
+ rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, :null, :custom, :rails, or :wab.");
1147
+ }
1148
+ }
857
1149
  }
858
1150
  path = StringValuePtr(*argv);
859
1151
  if (0 == (fd = open(path, O_RDONLY))) {
860
- rb_raise(rb_eIOError, "%s", strerror(errno));
1152
+ rb_raise(rb_eIOError, "%s", strerror(errno));
861
1153
  }
862
1154
  switch (mode) {
863
1155
  case StrictMode:
864
- oj_set_strict_callbacks(&pi);
865
- return oj_pi_sparse(argc, argv, &pi, fd);
866
- case NullMode:
1156
+ case NullMode: oj_set_strict_callbacks(&pi); return oj_pi_sparse(argc, argv, &pi, fd);
1157
+ case CustomMode: oj_set_custom_callbacks(&pi); return oj_pi_sparse(argc, argv, &pi, fd);
867
1158
  case CompatMode:
868
- oj_set_compat_callbacks(&pi);
869
- return oj_pi_sparse(argc, argv, &pi, fd);
1159
+ case RailsMode: oj_set_compat_callbacks(&pi); return oj_pi_sparse(argc, argv, &pi, fd);
1160
+ case WabMode: oj_set_wab_callbacks(&pi); return oj_pi_sparse(argc, argv, &pi, fd);
870
1161
  case ObjectMode:
871
- default:
872
- break;
1162
+ default: break;
873
1163
  }
874
1164
  oj_set_object_callbacks(&pi);
875
1165
 
876
1166
  return oj_pi_sparse(argc, argv, &pi, fd);
877
1167
  }
878
1168
 
879
- /* call-seq: safe_load(doc)
1169
+ /* Document-method: safe_load
1170
+ * call-seq: safe_load(doc)
880
1171
  *
881
1172
  * Loads a JSON document in strict mode with :auto_define and :symbol_keys
882
1173
  * turned off. This function should be safe to use with JSON received on an
883
1174
  * unprotected public interface.
884
1175
  *
885
- * @param [String|IO] doc JSON String or IO to load
886
- * @return [Hash|Array|String|Fixnum|Bignum|BigDecimal|nil|True|False]
1176
+ * - *doc* [_String__|_IO_] JSON String or IO to load.
1177
+ *
1178
+ * Returns [_Hash_|_Array_|_String_|_Fixnum_|_Bignum_|_BigDecimal_|_nil_|_True_|_False_]
887
1179
  */
888
- static VALUE
889
- safe_load(VALUE self, VALUE doc) {
890
- struct _ParseInfo pi;
891
- VALUE args[1];
892
-
893
- pi.err_class = Qnil;
894
- pi.options = oj_default_options;
1180
+ static VALUE safe_load(VALUE self, VALUE doc) {
1181
+ struct _parseInfo pi;
1182
+ VALUE args[1];
1183
+
1184
+ parse_info_init(&pi);
1185
+ pi.err_class = Qnil;
1186
+ pi.max_depth = 0;
1187
+ pi.options = oj_default_options;
895
1188
  pi.options.auto_define = No;
896
- pi.options.sym_key = No;
897
- pi.options.mode = StrictMode;
1189
+ pi.options.sym_key = No;
1190
+ pi.options.mode = StrictMode;
898
1191
  oj_set_strict_callbacks(&pi);
899
1192
  *args = doc;
900
1193
 
901
1194
  return oj_pi_parse(1, args, &pi, 0, 0, 1);
902
1195
  }
903
1196
 
904
- /* call-seq: saj_parse(handler, io)
1197
+ /* Document-method: saj_parse
1198
+ * call-seq: saj_parse(handler, io)
905
1199
  *
906
1200
  * Parses an IO stream or file containing a JSON document. Raises an exception
907
1201
  * if the JSON is malformed. This is a callback parser that calls the methods in
908
1202
  * the handler if they exist. A sample is the Oj::Saj class which can be used as
909
1203
  * a base class for the handler.
910
1204
  *
911
- * @param [Oj::Saj] handler responds to Oj::Saj methods
912
- * @param [IO|String] io IO Object to read from
1205
+ * - *handler* [_Oj::Saj_] responds to Oj::Saj methods
1206
+ * - *io* [_IO_|_String_] IO Object to read from
913
1207
  */
914
1208
 
915
- /* call-seq: sc_parse(handler, io)
1209
+ /* Document-method: sc_parse
1210
+ * call-seq: sc_parse(handler, io)
916
1211
  *
917
1212
  * Parses an IO stream or file containing a JSON document. Raises an exception
918
1213
  * if the JSON is malformed. This is a callback parser (Simple Callback Parser)
@@ -921,61 +1216,149 @@ safe_load(VALUE self, VALUE doc) {
921
1216
  * callback parser is slightly more efficient than the Saj callback parser and
922
1217
  * requires less argument checking.
923
1218
  *
924
- * @param [Oj::ScHandler] handler responds to Oj::ScHandler methods
925
- * @param [IO|String] io IO Object to read from
1219
+ * - *handler* [_Oj_::ScHandler_] responds to Oj::ScHandler methods
1220
+ * - *io* [_IO__|_String_] IO Object to read from
926
1221
  */
927
1222
 
928
- /* call-seq: dump(obj, options) => json-string
1223
+ struct dump_arg {
1224
+ struct _out * out;
1225
+ struct _options *copts;
1226
+ int argc;
1227
+ VALUE * argv;
1228
+ };
1229
+
1230
+ static VALUE dump_body(VALUE a) {
1231
+ volatile struct dump_arg *arg = (void *)a;
1232
+ VALUE rstr;
1233
+
1234
+ oj_dump_obj_to_json_using_params(*arg->argv, arg->copts, arg->out, arg->argc - 1, arg->argv + 1);
1235
+ if (0 == arg->out->buf) {
1236
+ rb_raise(rb_eNoMemError, "Not enough memory.");
1237
+ }
1238
+ rstr = rb_str_new2(arg->out->buf);
1239
+ rstr = oj_encode(rstr);
1240
+
1241
+ return rstr;
1242
+ }
1243
+
1244
+ static VALUE dump_ensure(VALUE a) {
1245
+ volatile struct dump_arg *arg = (void *)a;
1246
+
1247
+ oj_out_free(arg->out);
1248
+
1249
+ return Qnil;
1250
+ }
1251
+
1252
+ /* Document-method: dump
1253
+ * call-seq: dump(obj, options={})
929
1254
  *
930
1255
  * Dumps an Object (obj) to a string.
931
- * @param [Object] obj Object to serialize as an JSON document String
932
- * @param [Hash] options same as default_options
1256
+ * - *obj* [_Object_] Object to serialize as an JSON document String
1257
+ * - *options* [_Hash_] same as default_options
933
1258
  */
934
- static VALUE
935
- dump(int argc, VALUE *argv, VALUE self) {
936
- char buf[4096];
937
- struct _Out out;
938
- struct _Options copts = oj_default_options;
939
- VALUE rstr;
1259
+ static VALUE dump(int argc, VALUE *argv, VALUE self) {
1260
+ struct dump_arg arg;
1261
+ struct _out out;
1262
+ struct _options copts = oj_default_options;
1263
+
1264
+ if (1 > argc) {
1265
+ rb_raise(rb_eArgError, "wrong number of arguments (0 for 1).");
1266
+ }
1267
+ if (CompatMode == copts.mode) {
1268
+ copts.dump_opts.nan_dump = WordNan;
1269
+ }
1270
+ if (2 == argc) {
1271
+ oj_parse_options(argv[1], &copts);
1272
+ }
1273
+ if (CompatMode == copts.mode && copts.escape_mode != ASCIIEsc) {
1274
+ copts.escape_mode = JSONEsc;
1275
+ }
1276
+ arg.out = &out;
1277
+ arg.copts = &copts;
1278
+ arg.argc = argc;
1279
+ arg.argv = argv;
1280
+
1281
+ oj_out_init(arg.out);
1282
+
1283
+ arg.out->omit_nil = copts.dump_opts.omit_nil;
1284
+ arg.out->caller = CALLER_DUMP;
1285
+
1286
+ return rb_ensure(dump_body, (VALUE)&arg, dump_ensure, (VALUE)&arg);
1287
+ }
1288
+
1289
+ /* Document-method: to_json
1290
+ * call-seq: to_json(obj, options)
1291
+ *
1292
+ * Dumps an Object (obj) to a string. If the object has a to_json method that
1293
+ * will be called. The mode is set to :compat.
1294
+ * - *obj* [_Object_] Object to serialize as an JSON document String
1295
+ * - *options* [_Hash_]
1296
+ * - *:max_nesting* [_boolean_] It true nesting is limited to 100. The option to detect circular
1297
+ * references is available but is not compatible with the json gem., default is false
1298
+ * - *:allow_nan* [_boolean_] If true non JSON compliant words such as Nan and Infinity will be
1299
+ * used as appropriate, default is true.
1300
+ * - *:quirks_mode* [_boolean_] Allow single JSON values instead of documents, default is true
1301
+ * (allow).
1302
+ * - *:indent* [_String_|_nil_] String to use for indentation, overriding the indent option if not
1303
+ * nil.
1304
+ * - *:space* [_String_|_nil_] String to use for the space after the colon in JSON object fields.
1305
+ * - *:space_before* [_String_|_nil_] String to use before the colon separator in JSON object
1306
+ * fields.
1307
+ * - *:object_nl* [_String_|_nil_] String to use after a JSON object field value.
1308
+ * - *:array_nl* [_String_|_nil_] String to use after a JSON array value.
1309
+ * - *:trace* [_Boolean_] If true trace is turned on.
1310
+ *
1311
+ * Returns [_String_] the encoded JSON.
1312
+ */
1313
+ static VALUE to_json(int argc, VALUE *argv, VALUE self) {
1314
+ struct _out out;
1315
+ struct _options copts = oj_default_options;
1316
+ VALUE rstr;
940
1317
 
941
1318
  if (1 > argc) {
942
- rb_raise(rb_eArgError, "wrong number of arguments (0 for 1).");
1319
+ rb_raise(rb_eArgError, "wrong number of arguments (0 for 1).");
943
1320
  }
1321
+ copts.escape_mode = JXEsc;
1322
+ copts.dump_opts.nan_dump = RaiseNan;
944
1323
  if (2 == argc) {
945
- oj_parse_options(argv[1], &copts);
1324
+ oj_parse_mimic_dump_options(argv[1], &copts);
946
1325
  }
947
- out.buf = buf;
948
- out.end = buf + sizeof(buf) - 10;
949
- out.allocated = 0;
950
- out.omit_nil = copts.dump_opts.omit_nil;
951
- oj_dump_obj_to_json(*argv, &copts, &out);
1326
+ copts.mode = CompatMode;
1327
+ copts.to_json = Yes;
1328
+
1329
+ oj_out_init(&out);
1330
+
1331
+ out.omit_nil = copts.dump_opts.omit_nil;
1332
+ // For obj.to_json or generate nan is not allowed but if called from dump
1333
+ // it is.
1334
+ oj_dump_obj_to_json_using_params(*argv, &copts, &out, argc - 1, argv + 1);
1335
+
952
1336
  if (0 == out.buf) {
953
- rb_raise(rb_eNoMemError, "Not enough memory.");
1337
+ rb_raise(rb_eNoMemError, "Not enough memory.");
954
1338
  }
955
1339
  rstr = rb_str_new2(out.buf);
956
1340
  rstr = oj_encode(rstr);
957
- if (out.allocated) {
958
- xfree(out.buf);
959
- }
1341
+
1342
+ oj_out_free(&out);
1343
+
960
1344
  return rstr;
961
1345
  }
962
1346
 
963
-
964
- /* call-seq: to_file(file_path, obj, options)
1347
+ /* Document-method: to_file
1348
+ * call-seq: to_file(file_path, obj, options={})
965
1349
  *
966
1350
  * Dumps an Object to the specified file.
967
- * @param [String] file_path file path to write the JSON document to
968
- * @param [Object] obj Object to serialize as an JSON document String
969
- * @param [Hash] options formating options
970
- * @param [Fixnum] :indent format expected
971
- * @param [true|false] :circular allow circular references, default: false
1351
+ * - *file* [_String_] _path file path to write the JSON document to
1352
+ * - *obj* [_Object_] Object to serialize as an JSON document String
1353
+ * - *options* [_Hash_] formatting options
1354
+ * - *:indent* [_Fixnum_] format expected
1355
+ * - *:circular* [_Boolean_] allow circular references, default: false
972
1356
  */
973
- static VALUE
974
- to_file(int argc, VALUE *argv, VALUE self) {
975
- struct _Options copts = oj_default_options;
976
-
1357
+ static VALUE to_file(int argc, VALUE *argv, VALUE self) {
1358
+ struct _options copts = oj_default_options;
1359
+
977
1360
  if (3 == argc) {
978
- oj_parse_options(argv[2], &copts);
1361
+ oj_parse_options(argv[2], &copts);
979
1362
  }
980
1363
  Check_Type(*argv, T_STRING);
981
1364
  oj_write_obj_to_file(argv[1], StringValuePtr(*argv), &copts);
@@ -983,28 +1366,29 @@ to_file(int argc, VALUE *argv, VALUE self) {
983
1366
  return Qnil;
984
1367
  }
985
1368
 
986
- /* call-seq: to_stream(io, obj, options)
1369
+ /* Document-method: to_stream
1370
+ * call-seq: to_stream(io, obj, options={})
987
1371
  *
988
1372
  * Dumps an Object to the specified IO stream.
989
- * @param [IO] io IO stream to write the JSON document to
990
- * @param [Object] obj Object to serialize as an JSON document String
991
- * @param [Hash] options formating options
992
- * @param [Fixnum] :indent format expected
993
- * @param [true|false] :circular allow circular references, default: false
1373
+ * - *io* [_IO_] IO stream to write the JSON document to
1374
+ * - *obj* [_Object_] Object to serialize as an JSON document String
1375
+ * - *options* [_Hash_] formatting options
1376
+ * - *:indent* [_Fixnum_] format expected
1377
+ * - *:circular* [_Boolean_] allow circular references, default: false
994
1378
  */
995
- static VALUE
996
- to_stream(int argc, VALUE *argv, VALUE self) {
997
- struct _Options copts = oj_default_options;
998
-
1379
+ static VALUE to_stream(int argc, VALUE *argv, VALUE self) {
1380
+ struct _options copts = oj_default_options;
1381
+
999
1382
  if (3 == argc) {
1000
- oj_parse_options(argv[2], &copts);
1383
+ oj_parse_options(argv[2], &copts);
1001
1384
  }
1002
1385
  oj_write_obj_to_stream(argv[1], *argv, &copts);
1003
1386
 
1004
1387
  return Qnil;
1005
1388
  }
1006
1389
 
1007
- /* call-seq: register_odd(clas, create_object, create_method, *members)
1390
+ /* Document-method: register_odd
1391
+ * call-seq: register_odd(clas, create_object, create_method, *members)
1008
1392
  *
1009
1393
  * Registers a class as special. This is useful for working around subclasses of
1010
1394
  * primitive types as is done with ActiveSupport classes. The use of this
@@ -1012,37 +1396,33 @@ to_stream(int argc, VALUE *argv, VALUE self) {
1012
1396
  * normal way. It is not intended as a hook for changing the output of all
1013
1397
  * classes as it is not optimized for large numbers of classes.
1014
1398
  *
1015
- * @param [Class|Module] clas Class or Module to be made special
1016
- * @param [Object] create_object object to call the create method on
1017
- * @param [Symbol] create_method method on the clas that will create a new
1018
- * instance of the clas when given all the member values in the
1019
- * order specified.
1020
- * @param [Symbol|String] members methods used to get the member values from
1021
- * instances of the clas
1399
+ * - *clas* [_Class__|_Module_] Class or Module to be made special
1400
+ * - *create_object* [_Object_] object to call the create method on
1401
+ * - *create_method* [_Symbol_] method on the clas that will create a new instance of the clas when
1402
+ * given all the member values in the order specified.
1403
+ * - *members* [_Symbol__|_String_] methods used to get the member values from instances of the
1404
+ * clas.
1022
1405
  */
1023
- static VALUE
1024
- register_odd(int argc, VALUE *argv, VALUE self) {
1406
+ static VALUE register_odd(int argc, VALUE *argv, VALUE self) {
1025
1407
  if (3 > argc) {
1026
- rb_raise(rb_eArgError, "incorrect number of arguments.");
1408
+ rb_raise(rb_eArgError, "incorrect number of arguments.");
1027
1409
  }
1028
1410
  switch (rb_type(*argv)) {
1029
1411
  case T_CLASS:
1030
- case T_MODULE:
1031
- break;
1032
- default:
1033
- rb_raise(rb_eTypeError, "expected a class or module.");
1034
- break;
1412
+ case T_MODULE: break;
1413
+ default: rb_raise(rb_eTypeError, "expected a class or module."); break;
1035
1414
  }
1036
1415
  Check_Type(argv[2], T_SYMBOL);
1037
1416
  if (MAX_ODD_ARGS < argc - 2) {
1038
- rb_raise(rb_eArgError, "too many members.");
1417
+ rb_raise(rb_eArgError, "too many members.");
1039
1418
  }
1040
1419
  oj_reg_odd(argv[0], argv[1], argv[2], argc - 3, argv + 3, false);
1041
1420
 
1042
1421
  return Qnil;
1043
1422
  }
1044
1423
 
1045
- /* call-seq: register_odd_raw(clas, create_object, create_method, dump_method)
1424
+ /* Document-method: register_odd_raw
1425
+ * call-seq: register_odd_raw(clas, create_object, create_method, dump_method)
1046
1426
  *
1047
1427
  * Registers a class as special and expect the output to be a string that can be
1048
1428
  * included in the dumped JSON directly. This is useful for working around
@@ -1052,930 +1432,206 @@ register_odd(int argc, VALUE *argv, VALUE self) {
1052
1432
  * classes as it is not optimized for large numbers of classes. Be careful with
1053
1433
  * this option as the JSON may be incorrect if invalid JSON is returned.
1054
1434
  *
1055
- * @param [Class|Module] clas Class or Module to be made special
1056
- * @param [Object] create_object object to call the create method on
1057
- * @param [Symbol] create_method method on the clas that will create a new
1058
- * instance of the clas when given all the member values in the
1059
- * order specified.
1060
- * @param [Symbol|String] dump_method method to call on the object being
1061
- * serialized to generate the raw JSON.
1435
+ * - *clas* [_Class_|_Module_] Class or Module to be made special
1436
+ * - *create_object* [_Object_] object to call the create method on
1437
+ * - *create_method* [_Symbol_] method on the clas that will create a new instance of the clas when
1438
+ *given all the member values in the order specified.
1439
+ * - *dump_method* [_Symbol_|_String_] method to call on the object being serialized to generate the
1440
+ *raw JSON.
1062
1441
  */
1063
- static VALUE
1064
- register_odd_raw(int argc, VALUE *argv, VALUE self) {
1442
+ static VALUE register_odd_raw(int argc, VALUE *argv, VALUE self) {
1065
1443
  if (3 > argc) {
1066
- rb_raise(rb_eArgError, "incorrect number of arguments.");
1444
+ rb_raise(rb_eArgError, "incorrect number of arguments.");
1067
1445
  }
1068
1446
  switch (rb_type(*argv)) {
1069
1447
  case T_CLASS:
1070
- case T_MODULE:
1071
- break;
1072
- default:
1073
- rb_raise(rb_eTypeError, "expected a class or module.");
1074
- break;
1448
+ case T_MODULE: break;
1449
+ default: rb_raise(rb_eTypeError, "expected a class or module."); break;
1075
1450
  }
1076
1451
  Check_Type(argv[2], T_SYMBOL);
1077
1452
  if (MAX_ODD_ARGS < argc - 2) {
1078
- rb_raise(rb_eArgError, "too many members.");
1453
+ rb_raise(rb_eArgError, "too many members.");
1079
1454
  }
1080
1455
  oj_reg_odd(argv[0], argv[1], argv[2], 1, argv + 3, true);
1081
1456
 
1082
1457
  return Qnil;
1083
1458
  }
1084
1459
 
1085
- static void
1086
- str_writer_free(void *ptr) {
1087
- StrWriter sw;
1088
-
1089
- if (0 == ptr) {
1090
- return;
1091
- }
1092
- sw = (StrWriter)ptr;
1093
- xfree(sw->out.buf);
1094
- xfree(sw->types);
1095
- xfree(ptr);
1096
- }
1097
-
1098
- /* Document-class: Oj::StringWriter
1099
- *
1100
- * Supports building a JSON document one element at a time. Build the document
1101
- * by pushing values into the document. Pushing an array or an object will
1102
- * create that element in the JSON document and subsequent pushes will add the
1103
- * elements to that array or object until a pop() is called. When complete
1104
- * calling to_s() will return the JSON document. Note tha calling to_s() before
1105
- * construction is complete will return the document in it's current state.
1106
- */
1107
-
1108
- static void
1109
- str_writer_init(StrWriter sw) {
1110
- sw->opts = oj_default_options;
1111
- sw->depth = 0;
1112
- sw->types = ALLOC_N(char, 256);
1113
- sw->types_end = sw->types + 256;
1114
- *sw->types = '\0';
1115
- sw->keyWritten = 0;
1116
-
1117
- sw->out.buf = ALLOC_N(char, 4096);
1118
- sw->out.end = sw->out.buf + 4086;
1119
- sw->out.allocated = 1;
1120
- sw->out.cur = sw->out.buf;
1121
- *sw->out.cur = '\0';
1122
- sw->out.circ_cnt = 0;
1123
- sw->out.hash_cnt = 0;
1124
- sw->out.opts = &sw->opts;
1125
- sw->out.indent = sw->opts.indent;
1126
- sw->out.depth = 0;
1127
- }
1460
+ ////////////////////////////////////////////////////////////////////////////////
1461
+ // RDoc entries must be in the same file as the rb_define_method and must be
1462
+ // directly above the C method function. The extern declaration is enough to
1463
+ // get it to work.
1464
+ ////////////////////////////////////////////////////////////////////////////////
1128
1465
 
1129
- /* call-seq: new(options)
1466
+ /* Document-method: strict_load
1467
+ * call-seq: strict_load(json, options) { _|_obj, start, len_|_ }
1130
1468
  *
1131
- * Creates a new StringWriter.
1132
- * @param [Hash] options formating options
1133
- */
1134
- static VALUE
1135
- str_writer_new(int argc, VALUE *argv, VALUE self) {
1136
- StrWriter sw = ALLOC(struct _StrWriter);
1137
-
1138
- str_writer_init(sw);
1139
- if (1 == argc) {
1140
- oj_parse_options(argv[0], &sw->opts);
1141
- }
1142
- sw->out.indent = sw->opts.indent;
1143
-
1144
- return Data_Wrap_Struct(oj_string_writer_class, 0, str_writer_free, sw);
1145
- }
1146
-
1147
- /* call-seq: push_key(key)
1469
+ * Parses a JSON document String into an Hash, Array, String, Fixnum, Float,
1470
+ * true, false, or nil. It parses using a mode that is strict in that it maps
1471
+ * each primitive JSON type to a similar Ruby type. The :create_id is not
1472
+ * honored in this mode. Note that a Ruby Hash is used to represent the JSON
1473
+ * Object type. These two are not the same since the JSON Object type can have
1474
+ * repeating entries with the same key and Ruby Hash can not.
1148
1475
  *
1149
- * Pushes a key onto the JSON document. The key will be used for the next push
1150
- * if currently in a JSON object and ignored otherwise. If a key is provided on
1151
- * the next push then that new key will be ignored.
1152
- * @param [String] key the key pending for the next push
1153
- */
1154
- static VALUE
1155
- str_writer_push_key(VALUE self, VALUE key) {
1156
- StrWriter sw = (StrWriter)DATA_PTR(self);
1157
-
1158
- rb_check_type(key, T_STRING);
1159
- oj_str_writer_push_key(sw, StringValuePtr(key));
1160
-
1161
- return Qnil;
1162
- }
1163
-
1164
- /* call-seq: push_object(key=nil)
1476
+ * When used with a document that has multiple JSON elements the block, if
1477
+ * any, will be yielded to. If no block then the last element read will be
1478
+ * returned.
1165
1479
  *
1166
- * Pushes an object onto the JSON document. Future pushes will be to this object
1167
- * until a pop() is called.
1168
- * @param [String] key the key if adding to an object in the JSON document
1169
- */
1170
- static VALUE
1171
- str_writer_push_object(int argc, VALUE *argv, VALUE self) {
1172
- StrWriter sw = (StrWriter)DATA_PTR(self);
1173
-
1174
- switch (argc) {
1175
- case 0:
1176
- oj_str_writer_push_object(sw, 0);
1177
- break;
1178
- case 1:
1179
- if (Qnil == argv[0]) {
1180
- oj_str_writer_push_object(sw, 0);
1181
- } else {
1182
- rb_check_type(argv[0], T_STRING);
1183
- oj_str_writer_push_object(sw, StringValuePtr(argv[0]));
1184
- }
1185
- break;
1186
- default:
1187
- rb_raise(rb_eArgError, "Wrong number of argument to 'push_object'.");
1188
- break;
1189
- }
1190
- if (rb_block_given_p()) {
1191
- rb_yield(Qnil);
1192
- oj_str_writer_pop(sw);
1193
- }
1194
- return Qnil;
1195
- }
1196
-
1197
- /* call-seq: push_array(key=nil)
1480
+ * Raises an exception if the JSON is malformed or the classes specified are not
1481
+ * valid. If the input is not a valid JSON document (an empty string is not a
1482
+ * valid JSON document) an exception is raised.
1198
1483
  *
1199
- * Pushes an array onto the JSON document. Future pushes will be to this object
1200
- * until a pop() is called.
1201
- * @param [String] key the key if adding to an object in the JSON document
1202
- */
1203
- static VALUE
1204
- str_writer_push_array(int argc, VALUE *argv, VALUE self) {
1205
- StrWriter sw = (StrWriter)DATA_PTR(self);
1206
-
1207
- switch (argc) {
1208
- case 0:
1209
- oj_str_writer_push_array(sw, 0);
1210
- break;
1211
- case 1:
1212
- if (Qnil == argv[0]) {
1213
- oj_str_writer_push_array(sw, 0);
1214
- } else {
1215
- rb_check_type(argv[0], T_STRING);
1216
- oj_str_writer_push_array(sw, StringValuePtr(argv[0]));
1217
- }
1218
- break;
1219
- default:
1220
- rb_raise(rb_eArgError, "Wrong number of argument to 'push_object'.");
1221
- break;
1222
- }
1223
- if (rb_block_given_p()) {
1224
- rb_yield(Qnil);
1225
- oj_str_writer_pop(sw);
1226
- }
1227
- return Qnil;
1228
- }
1229
-
1230
- /* call-seq: push_value(value, key=nil)
1484
+ * A block can be provided with a single argument. That argument will be the
1485
+ * parsed JSON document. This is useful when parsing a string that includes
1486
+ * multiple JSON documents. The block can take up to 3 arguments, the parsed
1487
+ * object, the position in the string or stream of the start of the JSON for
1488
+ * that object, and the length of the JSON for that object plus trailing
1489
+ * whitespace.
1231
1490
  *
1232
- * Pushes a value onto the JSON document.
1233
- * @param [Object] value value to add to the JSON document
1234
- * @param [String] key the key if adding to an object in the JSON document
1235
- */
1236
- static VALUE
1237
- str_writer_push_value(int argc, VALUE *argv, VALUE self) {
1238
- switch (argc) {
1239
- case 1:
1240
- oj_str_writer_push_value((StrWriter)DATA_PTR(self), *argv, 0);
1241
- break;
1242
- case 2:
1243
- if (Qnil == argv[1]) {
1244
- oj_str_writer_push_value((StrWriter)DATA_PTR(self), *argv, 0);
1245
- } else {
1246
- rb_check_type(argv[1], T_STRING);
1247
- oj_str_writer_push_value((StrWriter)DATA_PTR(self), *argv, StringValuePtr(argv[1]));
1248
- }
1249
- break;
1250
- default:
1251
- rb_raise(rb_eArgError, "Wrong number of argument to 'push_value'.");
1252
- break;
1253
- }
1254
- return Qnil;
1255
- }
1256
-
1257
- /* call-seq: push_json(value, key=nil)
1491
+ * - *json* [_String_|_IO_] JSON String or an Object that responds to read().
1492
+ * - *options* [_Hash_] load options (same as default_options).
1493
+ * - *obj* [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_] parsed object.
1494
+ * - *start* [_optional, _Integer_] start position of parsed JSON for obj.
1495
+ * - *len* [_optional, _Integer_] length of parsed JSON for obj.
1258
1496
  *
1259
- * Pushes a string onto the JSON document. The String must be a valid JSON
1260
- * encoded string. No additional checking is done to verify the validity of the
1261
- * string.
1262
- * @param [String] value JSON document to add to the JSON document
1263
- * @param [String] key the key if adding to an object in the JSON document
1497
+ * Returns [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_]
1264
1498
  */
1265
- static VALUE
1266
- str_writer_push_json(int argc, VALUE *argv, VALUE self) {
1267
- rb_check_type(argv[0], T_STRING);
1268
- switch (argc) {
1269
- case 1:
1270
- oj_str_writer_push_json((StrWriter)DATA_PTR(self), StringValuePtr(*argv), 0);
1271
- break;
1272
- case 2:
1273
- if (Qnil == argv[1]) {
1274
- oj_str_writer_push_json((StrWriter)DATA_PTR(self), StringValuePtr(*argv), 0);
1275
- } else {
1276
- rb_check_type(argv[1], T_STRING);
1277
- oj_str_writer_push_json((StrWriter)DATA_PTR(self), StringValuePtr(*argv), StringValuePtr(argv[1]));
1278
- }
1279
- break;
1280
- default:
1281
- rb_raise(rb_eArgError, "Wrong number of argument to 'push_json'.");
1282
- break;
1283
- }
1284
- return Qnil;
1285
- }
1499
+ extern VALUE oj_strict_parse(int argc, VALUE *argv, VALUE self);
1286
1500
 
1287
- /* call-seq: pop()
1501
+ /* Document-method: compat_load
1502
+ * call-seq: compat_load(json, options) { _|_obj, start, len_|_ }
1288
1503
  *
1289
- * Pops up a level in the JSON document closing the array or object that is
1290
- * currently open.
1291
- */
1292
- static VALUE
1293
- str_writer_pop(VALUE self) {
1294
- oj_str_writer_pop((StrWriter)DATA_PTR(self));
1295
- return Qnil;
1296
- }
1297
-
1298
- /* call-seq: pop_all()
1504
+ * Parses a JSON document String into an Object, Hash, Array, String, Fixnum,
1505
+ * Float, true, false, or nil. It parses using a mode that is generally
1506
+ * compatible with other Ruby JSON parsers in that it will create objects based
1507
+ * on the :create_id value. It is not compatible in every way to every other
1508
+ * parser though as each parser has it's own variations.
1299
1509
  *
1300
- * Pops all level in the JSON document closing all the array or object that is
1301
- * currently open.
1302
- */
1303
- static VALUE
1304
- str_writer_pop_all(VALUE self) {
1305
- oj_str_writer_pop_all((StrWriter)DATA_PTR(self));
1306
-
1307
- return Qnil;
1308
- }
1309
-
1310
- /* call-seq: reset()
1510
+ * When used with a document that has multiple JSON elements the block, if
1511
+ * any, will be yielded to. If no block then the last element read will be
1512
+ * returned.
1513
+ *
1514
+ * Raises an exception if the JSON is malformed or the classes specified are not
1515
+ * valid. If the input is not a valid JSON document (an empty string is not a
1516
+ * valid JSON document) an exception is raised.
1517
+ *
1518
+ * A block can be provided with a single argument. That argument will be the
1519
+ * parsed JSON document. This is useful when parsing a string that includes
1520
+ * multiple JSON documents. The block can take up to 3 arguments, the parsed
1521
+ * object, the position in the string or stream of the start of the JSON for
1522
+ * that object, and the length of the JSON for that object plus trailing
1523
+ * whitespace.
1524
+ *
1525
+ * - *json* [_String_|_IO_] JSON String or an Object that responds to read().
1526
+ * - *options* [_Hash_] load options (same as default_options).
1527
+ * - *obj* [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_] parsed object.
1528
+ * - *start* [_optional, _Integer_] start position of parsed JSON for obj.
1529
+ * - *len* [_optional, _Integer_] length of parsed JSON for obj.
1311
1530
  *
1312
- * Reset the writer back to the empty state.
1531
+ * Returns [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_]
1313
1532
  */
1314
- static VALUE
1315
- str_writer_reset(VALUE self) {
1316
- StrWriter sw = (StrWriter)DATA_PTR(self);
1317
-
1318
- sw->depth = 0;
1319
- *sw->types = '\0';
1320
- sw->keyWritten = 0;
1321
- sw->out.cur = sw->out.buf;
1322
- *sw->out.cur = '\0';
1533
+ extern VALUE oj_compat_parse(int argc, VALUE *argv, VALUE self);
1323
1534
 
1324
- return Qnil;
1325
- }
1326
-
1327
- /* call-seq: to_s()
1535
+ /* Document-method: object_load
1536
+ * call-seq: object_load(json, options) { _|_obj, start, len_|_ }
1328
1537
  *
1329
- * Returns the JSON document string in what ever state the construction is at.
1330
- */
1331
- static VALUE
1332
- str_writer_to_s(VALUE self) {
1333
- StrWriter sw = (StrWriter)DATA_PTR(self);
1334
- VALUE rstr = rb_str_new(sw->out.buf, sw->out.cur - sw->out.buf);
1335
-
1336
- return oj_encode(rstr);
1337
- }
1338
-
1339
- // StreamWriter
1340
-
1341
- /* Document-class: Oj::StreamWriter
1342
- *
1343
- * Supports building a JSON document one element at a time. Build the IO stream
1344
- * document by pushing values into the document. Pushing an array or an object
1345
- * will create that element in the JSON document and subsequent pushes will add
1346
- * the elements to that array or object until a pop() is called.
1347
- */
1348
-
1349
- static void
1350
- stream_writer_free(void *ptr) {
1351
- StreamWriter sw;
1352
-
1353
- if (0 == ptr) {
1354
- return;
1355
- }
1356
- sw = (StreamWriter)ptr;
1357
- xfree(sw->sw.out.buf);
1358
- xfree(sw->sw.types);
1359
- xfree(ptr);
1360
- }
1361
-
1362
- static void
1363
- stream_writer_write(StreamWriter sw) {
1364
- ssize_t size = sw->sw.out.cur - sw->sw.out.buf;
1365
-
1366
- switch (sw->type) {
1367
- case STRING_IO:
1368
- rb_funcall(sw->stream, oj_write_id, 1, rb_str_new(sw->sw.out.buf, size));
1369
- break;
1370
- case STREAM_IO:
1371
- rb_funcall(sw->stream, oj_write_id, 1, rb_str_new(sw->sw.out.buf, size));
1372
- break;
1373
- case FILE_IO:
1374
- if (size != write(sw->fd, sw->sw.out.buf, size)) {
1375
- rb_raise(rb_eIOError, "Write failed. [%d:%s]\n", errno, strerror(errno));
1376
- }
1377
- break;
1378
- default:
1379
- rb_raise(rb_eArgError, "expected an IO Object.");
1380
- }
1381
- }
1382
-
1383
- static void
1384
- stream_writer_reset_buf(StreamWriter sw) {
1385
- sw->sw.out.cur = sw->sw.out.buf;
1386
- *sw->sw.out.cur = '\0';
1387
- }
1388
-
1389
- /* call-seq: new(io, options)
1538
+ * Parses a JSON document String into an Object, Hash, Array, String, Fixnum,
1539
+ * Float, true, false, or nil. In the :object mode the JSON should have been
1540
+ * generated by Oj.dump(). The parser will reconstitute the original marshalled
1541
+ * or dumped Object. The :auto_define and :circular options have meaning with
1542
+ * this parsing mode.
1390
1543
  *
1391
- * Creates a new StreamWriter.
1392
- * @param [IO] io stream to write to
1393
- * @param [Hash] options formating options
1394
- */
1395
- static VALUE
1396
- stream_writer_new(int argc, VALUE *argv, VALUE self) {
1397
- StreamWriterType type = STREAM_IO;
1398
- int fd = 0;
1399
- VALUE stream = argv[0];
1400
- VALUE clas = rb_obj_class(stream);
1401
- StreamWriter sw;
1402
- #if !IS_WINDOWS
1403
- VALUE s;
1404
- #endif
1405
-
1406
- if (oj_stringio_class == clas) {
1407
- type = STRING_IO;
1408
- #if !IS_WINDOWS
1409
- } else if (rb_respond_to(stream, oj_fileno_id) &&
1410
- Qnil != (s = rb_funcall(stream, oj_fileno_id, 0)) &&
1411
- 0 != (fd = FIX2INT(s))) {
1412
- type = FILE_IO;
1413
- #endif
1414
- } else if (rb_respond_to(stream, oj_write_id)) {
1415
- type = STREAM_IO;
1416
- } else {
1417
- rb_raise(rb_eArgError, "expected an IO Object.");
1418
- }
1419
- sw = ALLOC(struct _StreamWriter);
1420
- str_writer_init(&sw->sw);
1421
- if (2 == argc) {
1422
- oj_parse_options(argv[1], &sw->sw.opts);
1423
- }
1424
- sw->sw.out.indent = sw->sw.opts.indent;
1425
- sw->stream = stream;
1426
- sw->type = type;
1427
- sw->fd = fd;
1428
-
1429
- return Data_Wrap_Struct(oj_stream_writer_class, 0, stream_writer_free, sw);
1430
- }
1431
-
1432
- /* call-seq: push_key(key)
1544
+ * Raises an exception if the JSON is malformed or the classes specified are not
1545
+ * valid. If the input is not a valid JSON document (an empty string is not a
1546
+ * valid JSON document) an exception is raised.
1433
1547
  *
1434
- * Pushes a key onto the JSON document. The key will be used for the next push
1435
- * if currently in a JSON object and ignored otherwise. If a key is provided on
1436
- * the next push then that new key will be ignored.
1437
- * @param [String] key the key pending for the next push
1438
- */
1439
- static VALUE
1440
- stream_writer_push_key(VALUE self, VALUE key) {
1441
- StreamWriter sw = (StreamWriter)DATA_PTR(self);
1442
-
1443
- rb_check_type(key, T_STRING);
1444
- stream_writer_reset_buf(sw);
1445
- oj_str_writer_push_key(&sw->sw, StringValuePtr(key));
1446
- stream_writer_write(sw);
1447
- return Qnil;
1448
- }
1449
-
1450
- /* call-seq: push_object(key=nil)
1548
+ * A block can be provided with a single argument. That argument will be the
1549
+ * parsed JSON document. This is useful when parsing a string that includes
1550
+ * multiple JSON documents. The block can take up to 3 arguments, the parsed
1551
+ * object, the position in the string or stream of the start of the JSON for
1552
+ * that object, and the length of the JSON for that object plus trailing
1553
+ * whitespace.
1451
1554
  *
1452
- * Pushes an object onto the JSON document. Future pushes will be to this object
1453
- * until a pop() is called.
1454
- * @param [String] key the key if adding to an object in the JSON document
1455
- */
1456
- static VALUE
1457
- stream_writer_push_object(int argc, VALUE *argv, VALUE self) {
1458
- StreamWriter sw = (StreamWriter)DATA_PTR(self);
1459
-
1460
- stream_writer_reset_buf(sw);
1461
- switch (argc) {
1462
- case 0:
1463
- oj_str_writer_push_object(&sw->sw, 0);
1464
- break;
1465
- case 1:
1466
- if (Qnil == argv[0]) {
1467
- oj_str_writer_push_object(&sw->sw, 0);
1468
- } else {
1469
- rb_check_type(argv[0], T_STRING);
1470
- oj_str_writer_push_object(&sw->sw, StringValuePtr(argv[0]));
1471
- }
1472
- break;
1473
- default:
1474
- rb_raise(rb_eArgError, "Wrong number of argument to 'push_object'.");
1475
- break;
1476
- }
1477
- stream_writer_write(sw);
1478
- return Qnil;
1479
- }
1480
-
1481
- /* call-seq: push_array(key=nil)
1555
+ * - *json* [_String_|_IO_] JSON String or an Object that responds to read().
1556
+ * - *options* [_Hash_] load options (same as default_options).
1557
+ * - *obj* [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_] parsed object.
1558
+ * - *start* [_optional, _Integer_] start position of parsed JSON for obj.
1559
+ * - *len* [_optional, _Integer_] length of parsed JSON for obj.
1482
1560
  *
1483
- * Pushes an array onto the JSON document. Future pushes will be to this object
1484
- * until a pop() is called.
1485
- * @param [String] key the key if adding to an object in the JSON document
1561
+ * Returns [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_]
1486
1562
  */
1487
- static VALUE
1488
- stream_writer_push_array(int argc, VALUE *argv, VALUE self) {
1489
- StreamWriter sw = (StreamWriter)DATA_PTR(self);
1490
-
1491
- stream_writer_reset_buf(sw);
1492
- switch (argc) {
1493
- case 0:
1494
- oj_str_writer_push_array(&sw->sw, 0);
1495
- break;
1496
- case 1:
1497
- if (Qnil == argv[0]) {
1498
- oj_str_writer_push_array(&sw->sw, 0);
1499
- } else {
1500
- rb_check_type(argv[0], T_STRING);
1501
- oj_str_writer_push_array(&sw->sw, StringValuePtr(argv[0]));
1502
- }
1503
- break;
1504
- default:
1505
- rb_raise(rb_eArgError, "Wrong number of argument to 'push_object'.");
1506
- break;
1507
- }
1508
- stream_writer_write(sw);
1509
- return Qnil;
1510
- }
1563
+ extern VALUE oj_object_parse(int argc, VALUE *argv, VALUE self);
1511
1564
 
1512
- /* call-seq: push_value(value, key=nil)
1565
+ /* Document-method: wab_load
1566
+ * call-seq: wab_load(json, options) { _|_obj, start, len_|_ }
1513
1567
  *
1514
- * Pushes a value onto the JSON document.
1515
- * @param [Object] value value to add to the JSON document
1516
- * @param [String] key the key if adding to an object in the JSON document
1517
- */
1518
- static VALUE
1519
- stream_writer_push_value(int argc, VALUE *argv, VALUE self) {
1520
- StreamWriter sw = (StreamWriter)DATA_PTR(self);
1521
-
1522
- stream_writer_reset_buf(sw);
1523
- switch (argc) {
1524
- case 1:
1525
- oj_str_writer_push_value((StrWriter)DATA_PTR(self), *argv, 0);
1526
- break;
1527
- case 2:
1528
- if (Qnil == argv[0]) {
1529
- oj_str_writer_push_value((StrWriter)DATA_PTR(self), *argv, 0);
1530
- } else {
1531
- rb_check_type(argv[1], T_STRING);
1532
- oj_str_writer_push_value((StrWriter)DATA_PTR(self), *argv, StringValuePtr(argv[1]));
1533
- }
1534
- break;
1535
- default:
1536
- rb_raise(rb_eArgError, "Wrong number of argument to 'push_value'.");
1537
- break;
1538
- }
1539
- stream_writer_write(sw);
1540
- return Qnil;
1541
- }
1542
-
1543
- /* call-seq: push_json(value, key=nil)
1568
+ * Parses a JSON document String into an Hash, Array, String, Fixnum, Float,
1569
+ * true, false, or nil. It parses using a mode that is :wab in that it maps
1570
+ * each primitive JSON type to a similar Ruby type. The :create_id is not
1571
+ * honored in this mode. Note that a Ruby Hash is used to represent the JSON
1572
+ * Object type. These two are not the same since the JSON Object type can have
1573
+ * repeating entries with the same key and Ruby Hash can not.
1574
+ *
1575
+ * When used with a document that has multiple JSON elements the block, if
1576
+ * any, will be yielded to. If no block then the last element read will be
1577
+ * returned.
1544
1578
  *
1545
- * Pushes a string onto the JSON document. The String must be a valid JSON
1546
- * encoded string. No additional checking is done to verify the validity of the
1547
- * string.
1548
- * @param [Object] value value to add to the JSON document
1549
- * @param [String] key the key if adding to an object in the JSON document
1579
+ * Raises an exception if the JSON is malformed or the classes specified are not
1580
+ * valid. If the input is not a valid JSON document (an empty string is not a
1581
+ * valid JSON document) an exception is raised.
1582
+ *
1583
+ * A block can be provided with a single argument. That argument will be the
1584
+ * parsed JSON document. This is useful when parsing a string that includes
1585
+ * multiple JSON documents. The block can take up to 3 arguments, the parsed
1586
+ * object, the position in the string or stream of the start of the JSON for
1587
+ * that object, and the length of the JSON for that object plus trailing
1588
+ * whitespace.
1589
+ *
1590
+ * - *json* [_String_|_IO_] JSON String or an Object that responds to read().
1591
+ * - *options* [_Hash_] load options (same as default_options).
1592
+ * - *obj* [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_] parsed object.
1593
+ * - *start* [_optional, _Integer_] start position of parsed JSON for obj.
1594
+ * - *len* [_optional, _Integer_] length of parsed JSON for obj.
1595
+ *
1596
+ * Returns [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_]
1550
1597
  */
1551
- static VALUE
1552
- stream_writer_push_json(int argc, VALUE *argv, VALUE self) {
1553
- StreamWriter sw = (StreamWriter)DATA_PTR(self);
1554
-
1555
- rb_check_type(argv[0], T_STRING);
1556
- stream_writer_reset_buf(sw);
1557
- switch (argc) {
1558
- case 1:
1559
- oj_str_writer_push_json((StrWriter)DATA_PTR(self), StringValuePtr(*argv), 0);
1560
- break;
1561
- case 2:
1562
- if (Qnil == argv[0]) {
1563
- oj_str_writer_push_json((StrWriter)DATA_PTR(self), StringValuePtr(*argv), 0);
1564
- } else {
1565
- rb_check_type(argv[1], T_STRING);
1566
- oj_str_writer_push_json((StrWriter)DATA_PTR(self), StringValuePtr(*argv), StringValuePtr(argv[1]));
1567
- }
1568
- break;
1569
- default:
1570
- rb_raise(rb_eArgError, "Wrong number of argument to 'push_json'.");
1571
- break;
1572
- }
1573
- stream_writer_write(sw);
1574
- return Qnil;
1575
- }
1598
+ extern VALUE oj_wab_parse(int argc, VALUE *argv, VALUE self);
1576
1599
 
1577
- /* call-seq: pop()
1600
+ /* Document-method: add_to_json
1601
+ * call-seq: add_to_json(*args)
1602
+ *
1603
+ * Override simple to_s dump behavior in :compat mode to instead use an
1604
+ * optimized dump that includes the classname and attributes so that the
1605
+ * object can be re-created on load. The format is the same as the json gem
1606
+ * but does not use the ruby methods for encoding.
1578
1607
  *
1579
- * Pops up a level in the JSON document closing the array or object that is
1580
- * currently open.
1608
+ * The classes supported for optimization are: Array, BigDecimal, Complex,
1609
+ * Date, DateTime, Exception, Hash, Integer, OpenStruct, Range, Rational,
1610
+ * Regexp, Struct, and Time. Providing no classes will result in all those
1611
+ * classes being optimized.q
1612
+ *
1613
+ * - *args( [_Class_] zero or more classes to optimize.
1581
1614
  */
1582
- static VALUE
1583
- stream_writer_pop(VALUE self) {
1584
- StreamWriter sw = (StreamWriter)DATA_PTR(self);
1585
-
1586
- stream_writer_reset_buf(sw);
1587
- oj_str_writer_pop(&sw->sw);
1588
- stream_writer_write(sw);
1589
- return Qnil;
1590
- }
1615
+ extern VALUE oj_add_to_json(int argc, VALUE *argv, VALUE self);
1591
1616
 
1592
- /* call-seq: pop_all()
1617
+ /* @!method remove_to_json(*args)
1593
1618
  *
1594
- * Pops all level in the JSON document closing all the array or object that is
1595
- * currently open.
1619
+ * Reverts back to the to_s dump behavior in :compat mode to instead use an
1620
+ * optimized dump that includes the classname and attributes so that the
1621
+ * object can be re-created on load. The format is the same as the json gem
1622
+ * but does not use the ruby methods for encoding.
1623
+ *
1624
+ * The classes supported for optimization are: Array, BigDecimal, Complex,
1625
+ * Date, DateTime, Exception, Hash, Integer, OpenStruct, Range, Rational,
1626
+ * Regexp, Struct, and Time. Providing no classes will result in all those
1627
+ * classes being reverted from the optimized mode.
1628
+ *
1629
+ * - *args* [_Class_] zero or more classes to optimize.
1596
1630
  */
1597
- static VALUE
1598
- stream_writer_pop_all(VALUE self) {
1599
- StreamWriter sw = (StreamWriter)DATA_PTR(self);
1600
-
1601
- stream_writer_reset_buf(sw);
1602
- oj_str_writer_pop_all(&sw->sw);
1603
- stream_writer_write(sw);
1604
-
1605
- return Qnil;
1606
- }
1607
-
1608
- // Mimic JSON section
1609
-
1610
- static VALUE
1611
- mimic_dump(int argc, VALUE *argv, VALUE self) {
1612
- char buf[4096];
1613
- struct _Out out;
1614
- struct _Options copts = oj_default_options;
1615
- VALUE rstr;
1616
-
1617
- out.buf = buf;
1618
- out.end = buf + sizeof(buf) - 10;
1619
- out.allocated = 0;
1620
- out.omit_nil = copts.dump_opts.omit_nil;
1621
- oj_dump_obj_to_json(*argv, &copts, &out);
1622
- if (0 == out.buf) {
1623
- rb_raise(rb_eNoMemError, "Not enough memory.");
1624
- }
1625
- rstr = rb_str_new2(out.buf);
1626
- rstr = oj_encode(rstr);
1627
- if (2 <= argc && Qnil != argv[1]) {
1628
- VALUE io = argv[1];
1629
- VALUE args[1];
1630
-
1631
- *args = rstr;
1632
- rb_funcall2(io, oj_write_id, 1, args);
1633
- rstr = io;
1634
- }
1635
- if (out.allocated) {
1636
- xfree(out.buf);
1637
- }
1638
- return rstr;
1639
- }
1640
-
1641
- // This is the signature for the hash_foreach callback also.
1642
- static int
1643
- mimic_walk(VALUE key, VALUE obj, VALUE proc) {
1644
- switch (rb_type(obj)) {
1645
- case T_HASH:
1646
- rb_hash_foreach(obj, mimic_walk, proc);
1647
- break;
1648
- case T_ARRAY:
1649
- {
1650
- size_t cnt = RARRAY_LEN(obj);
1651
- size_t i;
1652
-
1653
- for (i = 0; i < cnt; i++) {
1654
- mimic_walk(Qnil, rb_ary_entry(obj, i), proc);
1655
- }
1656
- break;
1657
- }
1658
- default:
1659
- break;
1660
- }
1661
- if (Qnil == proc) {
1662
- if (rb_block_given_p()) {
1663
- rb_yield(obj);
1664
- }
1665
- } else {
1666
- #if HAS_PROC_WITH_BLOCK
1667
- VALUE args[1];
1668
-
1669
- *args = obj;
1670
- rb_proc_call_with_block(proc, 1, args, Qnil);
1671
- #else
1672
- rb_raise(rb_eNotImpError, "Calling a Proc with a block not supported in this version. Use func() {|x| } syntax instead.");
1673
- #endif
1674
- }
1675
- return ST_CONTINUE;
1676
- }
1677
-
1678
- static VALUE
1679
- mimic_load(int argc, VALUE *argv, VALUE self) {
1680
- struct _ParseInfo pi;
1681
- VALUE obj;
1682
- VALUE p = Qnil;
1683
-
1684
- pi.err_class = json_parser_error_class;
1685
- pi.options = oj_default_options;
1686
- oj_set_compat_callbacks(&pi);
1687
-
1688
- obj = oj_pi_parse(argc, argv, &pi, 0, 0, 0);
1689
- if (2 <= argc) {
1690
- p = argv[1];
1691
- }
1692
- mimic_walk(Qnil, obj, p);
1693
-
1694
- return obj;
1695
- }
1696
-
1697
- static VALUE
1698
- mimic_dump_load(int argc, VALUE *argv, VALUE self) {
1699
- if (1 > argc) {
1700
- rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)");
1701
- } else if (T_STRING == rb_type(*argv)) {
1702
- return mimic_load(argc, argv, self);
1703
- } else {
1704
- return mimic_dump(argc, argv, self);
1705
- }
1706
- return Qnil;
1707
- }
1708
-
1709
- static VALUE
1710
- mimic_generate_core(int argc, VALUE *argv, Options copts) {
1711
- char buf[4096];
1712
- struct _Out out;
1713
- VALUE rstr;
1714
-
1715
- out.buf = buf;
1716
- out.end = buf + sizeof(buf) - 10;
1717
- out.allocated = 0;
1718
- out.omit_nil = copts->dump_opts.omit_nil;
1719
- if (2 == argc && Qnil != argv[1]) {
1720
- VALUE ropts = argv[1];
1721
- VALUE v;
1722
- size_t len;
1723
-
1724
- if (T_HASH != rb_type(ropts)) {
1725
- rb_raise(rb_eArgError, "options must be a hash.");
1726
- }
1727
- if (Qnil != (v = rb_hash_lookup(ropts, indent_sym))) { // TBD fixnum also ok
1728
- rb_check_type(v, T_STRING);
1729
- if (sizeof(copts->dump_opts.indent_str) <= (len = RSTRING_LEN(v))) {
1730
- rb_raise(rb_eArgError, "indent string is limited to %lu characters.", sizeof(copts->dump_opts.indent_str));
1731
- }
1732
- strcpy(copts->dump_opts.indent_str, StringValuePtr(v));
1733
- copts->dump_opts.indent_size = (uint8_t)len;
1734
- copts->dump_opts.use = true;
1735
- }
1736
- if (Qnil != (v = rb_hash_lookup(ropts, space_sym))) {
1737
- rb_check_type(v, T_STRING);
1738
- if (sizeof(copts->dump_opts.after_sep) <= (len = RSTRING_LEN(v))) {
1739
- rb_raise(rb_eArgError, "space string is limited to %lu characters.", sizeof(copts->dump_opts.after_sep));
1740
- }
1741
- strcpy(copts->dump_opts.after_sep, StringValuePtr(v));
1742
- copts->dump_opts.after_size = (uint8_t)len;
1743
- copts->dump_opts.use = true;
1744
- }
1745
- if (Qnil != (v = rb_hash_lookup(ropts, space_before_sym))) {
1746
- rb_check_type(v, T_STRING);
1747
- if (sizeof(copts->dump_opts.before_sep) <= (len = RSTRING_LEN(v))) {
1748
- rb_raise(rb_eArgError, "space_before string is limited to %lu characters.", sizeof(copts->dump_opts.before_sep));
1749
- }
1750
- strcpy(copts->dump_opts.before_sep, StringValuePtr(v));
1751
- copts->dump_opts.before_size = (uint8_t)len;
1752
- copts->dump_opts.use = true;
1753
- }
1754
- if (Qnil != (v = rb_hash_lookup(ropts, object_nl_sym))) {
1755
- rb_check_type(v, T_STRING);
1756
- if (sizeof(copts->dump_opts.hash_nl) <= (len = RSTRING_LEN(v))) {
1757
- rb_raise(rb_eArgError, "object_nl string is limited to %lu characters.", sizeof(copts->dump_opts.hash_nl));
1758
- }
1759
- strcpy(copts->dump_opts.hash_nl, StringValuePtr(v));
1760
- copts->dump_opts.hash_size = (uint8_t)len;
1761
- copts->dump_opts.use = true;
1762
- }
1763
- if (Qnil != (v = rb_hash_lookup(ropts, array_nl_sym))) {
1764
- rb_check_type(v, T_STRING);
1765
- if (sizeof(copts->dump_opts.array_nl) <= (len = RSTRING_LEN(v))) {
1766
- rb_raise(rb_eArgError, "array_nl string is limited to %lu characters.", sizeof(copts->dump_opts.array_nl));
1767
- }
1768
- strcpy(copts->dump_opts.array_nl, StringValuePtr(v));
1769
- copts->dump_opts.array_size = (uint8_t)len;
1770
- copts->dump_opts.use = true;
1771
- }
1772
- if (Qnil != (v = rb_hash_lookup(ropts, ascii_only_sym))) {
1773
- // generate seems to assume anything except nil and false are true.
1774
- if (Qfalse == v || Qnil == v) {
1775
- copts->escape_mode = JSONEsc;
1776
- } else {
1777
- copts->escape_mode = ASCIIEsc;
1778
- }
1779
- }
1780
- // :allow_nan is not supported as Oj always allows_nan
1781
- // :max_nesting is always set to 100
1782
- }
1783
- oj_dump_obj_to_json(*argv, copts, &out);
1784
- if (0 == out.buf) {
1785
- rb_raise(rb_eNoMemError, "Not enough memory.");
1786
- }
1787
- rstr = rb_str_new2(out.buf);
1788
- rstr = oj_encode(rstr);
1789
- if (out.allocated) {
1790
- xfree(out.buf);
1791
- }
1792
- return rstr;
1793
- }
1794
-
1795
- static VALUE
1796
- mimic_generate(int argc, VALUE *argv, VALUE self) {
1797
- struct _Options copts = oj_default_options;
1798
-
1799
- return mimic_generate_core(argc, argv, &copts);
1800
- }
1801
-
1802
- static VALUE
1803
- mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
1804
- struct _Options copts = oj_default_options;
1805
-
1806
- strcpy(copts.dump_opts.indent_str, " ");
1807
- copts.dump_opts.indent_size = (uint8_t)strlen(copts.dump_opts.indent_str);
1808
- strcpy(copts.dump_opts.before_sep, " ");
1809
- copts.dump_opts.before_size = (uint8_t)strlen(copts.dump_opts.before_sep);
1810
- strcpy(copts.dump_opts.after_sep, " ");
1811
- copts.dump_opts.after_size = (uint8_t)strlen(copts.dump_opts.after_sep);
1812
- strcpy(copts.dump_opts.hash_nl, "\n");
1813
- copts.dump_opts.hash_size = (uint8_t)strlen(copts.dump_opts.hash_nl);
1814
- strcpy(copts.dump_opts.array_nl, "\n");
1815
- copts.dump_opts.array_size = (uint8_t)strlen(copts.dump_opts.array_nl);
1816
- copts.dump_opts.use = true;
1817
-
1818
- return mimic_generate_core(argc, argv, &copts);
1819
- }
1820
-
1821
- static VALUE
1822
- mimic_parse(int argc, VALUE *argv, VALUE self) {
1823
- struct _ParseInfo pi;
1824
- VALUE args[1];
1825
-
1826
- if (argc < 1) {
1827
- rb_raise(rb_eArgError, "Wrong number of arguments to parse.");
1828
- }
1829
- oj_set_compat_callbacks(&pi);
1830
- pi.err_class = json_parser_error_class;
1831
- pi.options = oj_default_options;
1832
- pi.options.auto_define = No;
1833
- pi.options.quirks_mode = No;
1834
- pi.options.allow_invalid = No;
1835
-
1836
- if (2 <= argc) {
1837
- VALUE ropts = argv[1];
1838
- VALUE v;
1839
-
1840
- if (T_HASH != rb_type(ropts)) {
1841
- rb_raise(rb_eArgError, "options must be a hash.");
1842
- }
1843
- if (Qnil != (v = rb_hash_lookup(ropts, symbolize_names_sym))) {
1844
- pi.options.sym_key = (Qtrue == v) ? Yes : No;
1845
- }
1846
-
1847
- if (Qnil != (v = rb_hash_lookup(ropts, quirks_mode_sym))) {
1848
- pi.options.quirks_mode = (Qtrue == v) ? Yes : No;
1849
- }
1850
-
1851
- if (Qnil != (v = rb_hash_lookup(ropts, create_additions_sym))) {
1852
- if (Qfalse == v) {
1853
- oj_set_strict_callbacks(&pi);
1854
- }
1855
- }
1856
- // :allow_nan is not supported as Oj always allows nan
1857
- // :max_nesting is ignored as Oj has not nesting limit
1858
- // :object_class is always Hash
1859
- // :array_class is always Array
1860
- }
1861
- *args = *argv;
1862
-
1863
- return oj_pi_parse(1, args, &pi, 0, 0, 0);
1864
- }
1865
-
1866
- static VALUE
1867
- mimic_recurse_proc(VALUE self, VALUE obj) {
1868
- rb_need_block();
1869
- mimic_walk(Qnil, obj, Qnil);
1870
-
1871
- return Qnil;
1872
- }
1873
-
1874
- static VALUE
1875
- no_op1(VALUE self, VALUE obj) {
1876
- return Qnil;
1877
- }
1878
-
1879
- static VALUE
1880
- mimic_set_create_id(VALUE self, VALUE id) {
1881
- Check_Type(id, T_STRING);
1882
-
1883
- if (0 != oj_default_options.create_id) {
1884
- if (json_class != oj_default_options.create_id) {
1885
- xfree((char*)oj_default_options.create_id);
1886
- }
1887
- oj_default_options.create_id = 0;
1888
- oj_default_options.create_id_len = 0;
1889
- }
1890
- if (Qnil != id) {
1891
- size_t len = RSTRING_LEN(id) + 1;
1892
-
1893
- oj_default_options.create_id = ALLOC_N(char, len);
1894
- strcpy((char*)oj_default_options.create_id, StringValuePtr(id));
1895
- oj_default_options.create_id_len = len - 1;
1896
- }
1897
- return id;
1898
- }
1899
-
1900
- static VALUE
1901
- mimic_create_id(VALUE self) {
1902
- if (0 != oj_default_options.create_id) {
1903
- return oj_encode(rb_str_new_cstr(oj_default_options.create_id));
1904
- }
1905
- return rb_str_new_cstr(json_class);
1906
- }
1907
-
1908
- static struct _Options mimic_object_to_json_options = {
1909
- 0, // indent
1910
- No, // circular
1911
- No, // auto_define
1912
- No, // sym_key
1913
- JSONEsc, // escape_mode
1914
- CompatMode, // mode
1915
- No, // class_cache
1916
- RubyTime, // time_format
1917
- No, // bigdec_as_num
1918
- FloatDec, // bigdec_load
1919
- No, // to_json
1920
- Yes, // as_json
1921
- Yes, // nilnil
1922
- Yes, // allow_gc
1923
- Yes, // quirks_mode
1924
- No, // allow_invalid
1925
- json_class, // create_id
1926
- 10, // create_id_len
1927
- 9, // sec_prec
1928
- 15, // float_prec
1929
- "%0.15g", // float_fmt
1930
- Qnil, // hash_class
1931
- { // dump_opts
1932
- false, //use
1933
- "", // indent
1934
- "", // before_sep
1935
- "", // after_sep
1936
- "", // hash_nl
1937
- "", // array_nl
1938
- 0, // indent_size
1939
- 0, // before_size
1940
- 0, // after_size
1941
- 0, // hash_size
1942
- 0, // array_size
1943
- AutoNan,// nan_dump
1944
- false, // omit_nil
1945
- }
1946
- };
1947
-
1948
- static VALUE
1949
- mimic_object_to_json(int argc, VALUE *argv, VALUE self) {
1950
- char buf[4096];
1951
- struct _Out out;
1952
- VALUE rstr;
1953
- struct _Options copts = oj_default_options;
1954
-
1955
- out.buf = buf;
1956
- out.end = buf + sizeof(buf) - 10;
1957
- out.allocated = 0;
1958
- out.omit_nil = copts.dump_opts.omit_nil;
1959
- // Have to turn off to_json to avoid the Active Support recursion problem.
1960
- copts.to_json = No;
1961
- // To be strict the mimic_object_to_json_options should be used but people
1962
- // seem to prefer the option of changing that.
1963
- //oj_dump_obj_to_json(self, &mimic_object_to_json_options, &out);
1964
- oj_dump_obj_to_json_using_params(self, &copts, &out, argc, argv);
1965
- if (0 == out.buf) {
1966
- rb_raise(rb_eNoMemError, "Not enough memory.");
1967
- }
1968
- rstr = rb_str_new2(out.buf);
1969
- rstr = oj_encode(rstr);
1970
- if (out.allocated) {
1971
- xfree(out.buf);
1972
- }
1973
- return rstr;
1974
- }
1975
-
1631
+ extern VALUE oj_remove_to_json(int argc, VALUE *argv, VALUE self);
1976
1632
 
1977
1633
  /* Document-method: mimic_JSON
1978
- * call-seq: mimic_JSON() => Module
1634
+ * call-seq: mimic_JSON()
1979
1635
  *
1980
1636
  * Creates the JSON module with methods and classes to mimic the JSON gem. After
1981
1637
  * this method is invoked calls that expect the JSON module will use Oj instead
@@ -1986,238 +1642,203 @@ mimic_object_to_json(int argc, VALUE *argv, VALUE self) {
1986
1642
  * will be replaced with Oj methods.
1987
1643
  *
1988
1644
  * Note that this also sets the default options of :mode to :compat and
1989
- * :encoding to :ascii.
1645
+ * :encoding to :unicode_xss.
1646
+ *
1647
+ * Returns [_Module_] the JSON module.
1990
1648
  */
1991
- static VALUE
1992
- define_mimic_json(int argc, VALUE *argv, VALUE self) {
1993
- VALUE ext;
1994
- VALUE dummy;
1995
- VALUE verbose;
1996
- VALUE json_error;
1997
-
1998
- // Either set the paths to indicate JSON has been loaded or replaces the
1999
- // methods if it has been loaded.
2000
- if (rb_const_defined_at(rb_cObject, rb_intern("JSON"))) {
2001
- mimic = rb_const_get_at(rb_cObject, rb_intern("JSON"));
2002
- } else {
2003
- mimic = rb_define_module("JSON");
2004
- }
2005
- verbose = rb_gv_get("$VERBOSE");
2006
- rb_gv_set("$VERBOSE", Qfalse);
2007
- rb_define_module_function(rb_cObject, "JSON", mimic_dump_load, -1);
2008
- if (rb_const_defined_at(mimic, rb_intern("Ext"))) {
2009
- ext = rb_const_get_at(mimic, rb_intern("Ext"));
2010
- } else {
2011
- ext = rb_define_module_under(mimic, "Ext");
2012
- }
2013
- if (!rb_const_defined_at(ext, rb_intern("Parser"))) {
2014
- dummy = rb_define_class_under(ext, "Parser", rb_cObject);
2015
- }
2016
- if (!rb_const_defined_at(ext, rb_intern("Generator"))) {
2017
- dummy = rb_define_class_under(ext, "Generator", rb_cObject);
2018
- }
2019
- // convince Ruby that the json gem has already been loaded
2020
- dummy = rb_gv_get("$LOADED_FEATURES");
2021
- if (rb_type(dummy) == T_ARRAY) {
2022
- rb_ary_push(dummy, rb_str_new2("json"));
2023
- if (0 < argc) {
2024
- VALUE mimic_args[1];
2025
-
2026
- *mimic_args = *argv;
2027
- rb_funcall2(Oj, rb_intern("mimic_loaded"), 1, mimic_args);
2028
- } else {
2029
- rb_funcall2(Oj, rb_intern("mimic_loaded"), 0, 0);
2030
- }
2031
- }
2032
- rb_define_module_function(mimic, "parser=", no_op1, 1);
2033
- rb_define_module_function(mimic, "generator=", no_op1, 1);
2034
- rb_define_module_function(mimic, "create_id=", mimic_set_create_id, 1);
2035
- rb_define_module_function(mimic, "create_id", mimic_create_id, 0);
2036
-
2037
- rb_define_module_function(mimic, "dump", mimic_dump, -1);
2038
- rb_define_module_function(mimic, "load", mimic_load, -1);
2039
- rb_define_module_function(mimic, "restore", mimic_load, -1);
2040
- rb_define_module_function(mimic, "recurse_proc", mimic_recurse_proc, 1);
2041
- rb_define_module_function(mimic, "[]", mimic_dump_load, -1);
2042
-
2043
- rb_define_module_function(mimic, "generate", mimic_generate, -1);
2044
- rb_define_module_function(mimic, "fast_generate", mimic_generate, -1);
2045
- rb_define_module_function(mimic, "pretty_generate", mimic_pretty_generate, -1);
2046
- /* for older versions of JSON, the deprecated unparse methods */
2047
- rb_define_module_function(mimic, "unparse", mimic_generate, -1);
2048
- rb_define_module_function(mimic, "fast_unparse", mimic_generate, -1);
2049
- rb_define_module_function(mimic, "pretty_unparse", mimic_pretty_generate, -1);
2050
-
2051
- rb_define_module_function(mimic, "parse", mimic_parse, -1);
2052
- rb_define_module_function(mimic, "parse!", mimic_parse, -1);
2053
-
2054
- rb_define_method(rb_cObject, "to_json", mimic_object_to_json, -1);
1649
+ extern VALUE oj_define_mimic_json(int argc, VALUE *argv, VALUE self);
2055
1650
 
2056
- rb_gv_set("$VERBOSE", verbose);
2057
-
2058
- create_additions_sym = ID2SYM(rb_intern("create_additions")); rb_gc_register_address(&create_additions_sym);
2059
- symbolize_names_sym = ID2SYM(rb_intern("symbolize_names")); rb_gc_register_address(&symbolize_names_sym);
2060
-
2061
- if (rb_const_defined_at(mimic, rb_intern("JSONError"))) {
2062
- json_error = rb_const_get(mimic, rb_intern("JSONError"));
2063
- } else {
2064
- json_error = rb_define_class_under(mimic, "JSONError", rb_eStandardError);
2065
- }
2066
- if (rb_const_defined_at(mimic, rb_intern("ParserError"))) {
2067
- json_parser_error_class = rb_const_get(mimic, rb_intern("ParserError"));
2068
- } else {
2069
- json_parser_error_class = rb_define_class_under(mimic, "ParserError", json_error);
2070
- }
2071
-
2072
- if (!rb_const_defined_at(mimic, rb_intern("State"))) {
2073
- rb_define_class_under(mimic, "State", rb_cObject);
2074
- }
2075
-
2076
- oj_default_options = mimic_object_to_json_options;
2077
- oj_default_options.to_json = Yes;
1651
+ /* Document-method: generate
1652
+ * call-seq: generate(obj, opts=nil)
1653
+ *
1654
+ * Encode obj as a JSON String. The obj argument must be a Hash, Array, or
1655
+ * respond to to_h or to_json. Options other than those listed such as
1656
+ * +:allow_nan+ or +:max_nesting+ are ignored. Calling this method will call
1657
+ * Oj.mimic_JSON if it is not already called.
1658
+ *
1659
+ * - *obj* [_Object__|_Hash_|_Array_] object to convert to a JSON String
1660
+ * - *opts* [_Hash_] options
1661
+ * - *:indent* [_String_] String to use for indentation.
1662
+ * - *:space* [_String_] String placed after a , or : delimiter
1663
+ * - *:space_before* [_String_] String placed before a : delimiter
1664
+ * - *:object_nl* [_String_] String placed after a JSON object
1665
+ * - *:array_nl* [_String_] String placed after a JSON array
1666
+ * - *:ascii_only* [_Boolean_] if not nil or false then use only ascii characters in the output.
1667
+ * Note JSON.generate does support this even if it is not documented.
1668
+ *
1669
+ * Returns [_String_]generated JSON.
1670
+ */
1671
+ extern VALUE oj_mimic_generate(int argc, VALUE *argv, VALUE self);
2078
1672
 
2079
- return mimic;
2080
- }
1673
+ /* Document-module: Oj.optimize_rails()
1674
+ *
1675
+ * Sets the Oj as the Rails encoder and decoder. Oj::Rails.optimize is also
1676
+ * called.
1677
+ */
1678
+ extern VALUE oj_optimize_rails(VALUE self);
2081
1679
 
2082
1680
  /*
2083
1681
  extern void oj_hash_test();
2084
-
2085
1682
  static VALUE
2086
1683
  hash_test(VALUE self) {
2087
1684
  oj_hash_test();
2088
1685
  return Qnil;
2089
1686
  }
2090
1687
  */
2091
-
2092
- #if !HAS_ENCODING_SUPPORT
1688
+ /*
1689
+ extern void oj_hash_sizes();
2093
1690
  static VALUE
2094
- iconv_encoder(VALUE x) {
2095
- VALUE iconv;
2096
-
2097
- rb_require("iconv");
2098
- iconv = rb_const_get(rb_cObject, rb_intern("Iconv"));
2099
-
2100
- return rb_funcall(iconv, rb_intern("new"), 2, rb_str_new2("ASCII//TRANSLIT"), rb_str_new2("UTF-8"));
1691
+ hash_test(VALUE self) {
1692
+ oj_hash_sizes();
1693
+ return Qnil;
2101
1694
  }
1695
+ */
2102
1696
 
2103
- static VALUE
2104
- iconv_rescue(VALUE x) {
1697
+ static VALUE protect_require(VALUE x) {
1698
+ rb_require("time");
1699
+ rb_require("bigdecimal");
2105
1700
  return Qnil;
2106
1701
  }
2107
- #endif
1702
+
1703
+ extern void print_all_odds(const char *label);
2108
1704
 
2109
1705
  static VALUE
2110
- protect_require(VALUE x) {
2111
- rb_require("time");
2112
- rb_require("bigdecimal");
1706
+ debug_odd(VALUE self, VALUE label) {
1707
+ print_all_odds(RSTRING_PTR(label));
2113
1708
  return Qnil;
2114
1709
  }
2115
1710
 
2116
- void Init_oj() {
2117
- int err = 0;
2118
1711
 
1712
+ /* Document-module: Oj
1713
+ *
1714
+ * Optimized JSON (Oj), as the name implies was written to provide speed
1715
+ * optimized JSON handling.
1716
+ *
1717
+ * Oj uses modes to control how object are encoded and decoded. In addition
1718
+ * global and options to methods allow additional behavior modifications. The
1719
+ * modes are:
1720
+ *
1721
+ * - *:strict* mode will only allow the 7 basic JSON types to be serialized. Any other Object
1722
+ * will raise an Exception.
1723
+ *
1724
+ * - *:null* mode is similar to the :strict mode except any Object that is not
1725
+ * one of the JSON base types is replaced by a JSON null.
1726
+ *
1727
+ * - *:object* mode will dump any Object as a JSON Object with keys that match
1728
+ * the Ruby Object's variable names without the '@' character. This is the
1729
+ * highest performance mode.
1730
+ *
1731
+ * - *:compat* or *:json* mode is the compatible mode for the json gem. It mimics
1732
+ * the json gem including the options, defaults, and restrictions.
1733
+ *
1734
+ * - *:rails* is the compatibility mode for Rails or Active support.
1735
+ *
1736
+ * - *:custom* is the most configurable mode.
1737
+ *
1738
+ * - *:wab* specifically for WAB data exchange.
1739
+ */
1740
+ void Init_oj(void) {
1741
+ int err = 0;
1742
+
1743
+ #if HAVE_RB_EXT_RACTOR_SAFE
1744
+ rb_ext_ractor_safe(true);
1745
+ #endif
2119
1746
  Oj = rb_define_module("Oj");
1747
+ rb_gc_register_address(&Oj);
2120
1748
 
2121
1749
  oj_cstack_class = rb_define_class_under(Oj, "CStack", rb_cObject);
1750
+ rb_gc_register_address(&oj_cstack_class);
2122
1751
 
2123
- oj_string_writer_class = rb_define_class_under(Oj, "StringWriter", rb_cObject);
2124
- rb_define_module_function(oj_string_writer_class, "new", str_writer_new, -1);
2125
- rb_define_method(oj_string_writer_class, "push_key", str_writer_push_key, 1);
2126
- rb_define_method(oj_string_writer_class, "push_object", str_writer_push_object, -1);
2127
- rb_define_method(oj_string_writer_class, "push_array", str_writer_push_array, -1);
2128
- rb_define_method(oj_string_writer_class, "push_value", str_writer_push_value, -1);
2129
- rb_define_method(oj_string_writer_class, "push_json", str_writer_push_json, -1);
2130
- rb_define_method(oj_string_writer_class, "pop", str_writer_pop, 0);
2131
- rb_define_method(oj_string_writer_class, "pop_all", str_writer_pop_all, 0);
2132
- rb_define_method(oj_string_writer_class, "reset", str_writer_reset, 0);
2133
- rb_define_method(oj_string_writer_class, "to_s", str_writer_to_s, 0);
2134
-
2135
- oj_stream_writer_class = rb_define_class_under(Oj, "StreamWriter", rb_cObject);
2136
- rb_define_module_function(oj_stream_writer_class, "new", stream_writer_new, -1);
2137
- rb_define_method(oj_stream_writer_class, "push_key", stream_writer_push_key, 1);
2138
- rb_define_method(oj_stream_writer_class, "push_object", stream_writer_push_object, -1);
2139
- rb_define_method(oj_stream_writer_class, "push_array", stream_writer_push_array, -1);
2140
- rb_define_method(oj_stream_writer_class, "push_value", stream_writer_push_value, -1);
2141
- rb_define_method(oj_stream_writer_class, "push_json", stream_writer_push_json, -1);
2142
- rb_define_method(oj_stream_writer_class, "pop", stream_writer_pop, 0);
2143
- rb_define_method(oj_stream_writer_class, "pop_all", stream_writer_pop_all, 0);
1752
+ rb_undef_alloc_func(oj_cstack_class);
1753
+
1754
+ oj_string_writer_init();
1755
+ oj_stream_writer_init();
2144
1756
 
2145
- rb_require("time");
2146
1757
  rb_require("date");
2147
1758
  // On Rubinius the require fails but can be done from a ruby file.
2148
1759
  rb_protect(protect_require, Qnil, &err);
2149
- #if NEEDS_RATIONAL
2150
- rb_require("rational");
2151
- #endif
2152
1760
  rb_require("stringio");
2153
- #if HAS_ENCODING_SUPPORT
2154
- oj_utf8_encoding = rb_enc_find("UTF-8");
2155
- #else
2156
- // need an option to turn this on
2157
- oj_utf8_encoding = rb_rescue(iconv_encoder, Qnil, iconv_rescue, Qnil);
2158
- oj_utf8_encoding = Qnil;
2159
- #endif
1761
+ oj_utf8_encoding_index = rb_enc_find_index("UTF-8");
1762
+ oj_utf8_encoding = rb_enc_from_index(oj_utf8_encoding_index);
2160
1763
 
2161
- //rb_define_module_function(Oj, "hash_test", hash_test, 0);
1764
+ // rb_define_module_function(Oj, "hash_test", hash_test, 0);
1765
+ rb_define_module_function(Oj, "debug_odd", debug_odd, 1);
2162
1766
 
2163
1767
  rb_define_module_function(Oj, "default_options", get_def_opts, 0);
2164
1768
  rb_define_module_function(Oj, "default_options=", set_def_opts, 1);
2165
1769
 
2166
- rb_define_module_function(Oj, "mimic_JSON", define_mimic_json, -1);
1770
+ rb_define_module_function(Oj, "mimic_JSON", oj_define_mimic_json, -1);
2167
1771
  rb_define_module_function(Oj, "load", load, -1);
2168
1772
  rb_define_module_function(Oj, "load_file", load_file, -1);
2169
1773
  rb_define_module_function(Oj, "safe_load", safe_load, 1);
2170
1774
  rb_define_module_function(Oj, "strict_load", oj_strict_parse, -1);
2171
1775
  rb_define_module_function(Oj, "compat_load", oj_compat_parse, -1);
2172
1776
  rb_define_module_function(Oj, "object_load", oj_object_parse, -1);
1777
+ rb_define_module_function(Oj, "wab_load", oj_wab_parse, -1);
2173
1778
 
2174
1779
  rb_define_module_function(Oj, "dump", dump, -1);
1780
+
2175
1781
  rb_define_module_function(Oj, "to_file", to_file, -1);
2176
1782
  rb_define_module_function(Oj, "to_stream", to_stream, -1);
1783
+ // JSON gem compatibility
1784
+ rb_define_module_function(Oj, "to_json", to_json, -1);
1785
+ rb_define_module_function(Oj, "generate", oj_mimic_generate, -1);
1786
+ rb_define_module_function(Oj, "fast_generate", oj_mimic_generate, -1);
1787
+
1788
+ rb_define_module_function(Oj, "add_to_json", oj_add_to_json, -1);
1789
+ rb_define_module_function(Oj, "remove_to_json", oj_remove_to_json, -1);
1790
+
2177
1791
  rb_define_module_function(Oj, "register_odd", register_odd, -1);
2178
1792
  rb_define_module_function(Oj, "register_odd_raw", register_odd_raw, -1);
2179
1793
 
2180
1794
  rb_define_module_function(Oj, "saj_parse", oj_saj_parse, -1);
2181
1795
  rb_define_module_function(Oj, "sc_parse", oj_sc_parse, -1);
2182
1796
 
2183
- oj_add_value_id = rb_intern("add_value");
2184
- oj_array_append_id = rb_intern("array_append");
2185
- oj_array_end_id = rb_intern("array_end");
2186
- oj_array_start_id = rb_intern("array_start");
2187
- oj_as_json_id = rb_intern("as_json");
2188
- oj_error_id = rb_intern("error");
2189
- oj_file_id = rb_intern("file?");
2190
- oj_fileno_id = rb_intern("fileno");
2191
- oj_ftype_id = rb_intern("ftype");
2192
- oj_hash_end_id = rb_intern("hash_end");
2193
- oj_hash_key_id = rb_intern("hash_key");
2194
- oj_hash_set_id = rb_intern("hash_set");
2195
- oj_hash_start_id = rb_intern("hash_start");
2196
- oj_iconv_id = rb_intern("iconv");
1797
+ rb_define_module_function(Oj, "optimize_rails", oj_optimize_rails, 0);
1798
+
1799
+ oj_add_value_id = rb_intern("add_value");
1800
+ oj_array_append_id = rb_intern("array_append");
1801
+ oj_array_end_id = rb_intern("array_end");
1802
+ oj_array_start_id = rb_intern("array_start");
1803
+ oj_as_json_id = rb_intern("as_json");
1804
+ oj_begin_id = rb_intern("begin");
1805
+ oj_bigdecimal_id = rb_intern("BigDecimal");
1806
+ oj_end_id = rb_intern("end");
1807
+ oj_error_id = rb_intern("error");
1808
+ oj_exclude_end_id = rb_intern("exclude_end?");
1809
+ oj_file_id = rb_intern("file?");
1810
+ oj_fileno_id = rb_intern("fileno");
1811
+ oj_ftype_id = rb_intern("ftype");
1812
+ oj_hash_end_id = rb_intern("hash_end");
1813
+ oj_hash_key_id = rb_intern("hash_key");
1814
+ oj_hash_set_id = rb_intern("hash_set");
1815
+ oj_hash_start_id = rb_intern("hash_start");
1816
+ oj_iconv_id = rb_intern("iconv");
2197
1817
  oj_instance_variables_id = rb_intern("instance_variables");
2198
- oj_json_create_id = rb_intern("json_create");
2199
- oj_length_id = rb_intern("length");
2200
- oj_new_id = rb_intern("new");
2201
- oj_parse_id = rb_intern("parse");
2202
- oj_pos_id = rb_intern("pos");
2203
- oj_read_id = rb_intern("read");
2204
- oj_readpartial_id = rb_intern("readpartial");
2205
- oj_replace_id = rb_intern("replace");
2206
- oj_stat_id = rb_intern("stat");
2207
- oj_string_id = rb_intern("string");
2208
- oj_to_hash_id = rb_intern("to_hash");
2209
- oj_to_json_id = rb_intern("to_json");
2210
- oj_to_s_id = rb_intern("to_s");
2211
- oj_to_sym_id = rb_intern("to_sym");
2212
- oj_to_time_id = rb_intern("to_time");
2213
- oj_tv_nsec_id = rb_intern("tv_nsec");
2214
- oj_tv_sec_id = rb_intern("tv_sec");
2215
- oj_tv_usec_id = rb_intern("tv_usec");
2216
- oj_utc_id = rb_intern("utc");
2217
- oj_utc_offset_id = rb_intern("utc_offset");
2218
- oj_utcq_id = rb_intern("utc?");
2219
- oj_write_id = rb_intern("write");
2220
- has_key_id = rb_intern("has_key?");
1818
+ oj_json_create_id = rb_intern("json_create");
1819
+ oj_length_id = rb_intern("length");
1820
+ oj_new_id = rb_intern("new");
1821
+ oj_parse_id = rb_intern("parse");
1822
+ oj_pos_id = rb_intern("pos");
1823
+ oj_raw_json_id = rb_intern("raw_json");
1824
+ oj_read_id = rb_intern("read");
1825
+ oj_readpartial_id = rb_intern("readpartial");
1826
+ oj_replace_id = rb_intern("replace");
1827
+ oj_stat_id = rb_intern("stat");
1828
+ oj_string_id = rb_intern("string");
1829
+ oj_to_h_id = rb_intern("to_h");
1830
+ oj_to_hash_id = rb_intern("to_hash");
1831
+ oj_to_json_id = rb_intern("to_json");
1832
+ oj_to_s_id = rb_intern("to_s");
1833
+ oj_to_sym_id = rb_intern("to_sym");
1834
+ oj_to_time_id = rb_intern("to_time");
1835
+ oj_tv_nsec_id = rb_intern("tv_nsec");
1836
+ oj_tv_sec_id = rb_intern("tv_sec");
1837
+ oj_tv_usec_id = rb_intern("tv_usec");
1838
+ oj_utc_id = rb_intern("utc");
1839
+ oj_utc_offset_id = rb_intern("utc_offset");
1840
+ oj_utcq_id = rb_intern("utc?");
1841
+ oj_write_id = rb_intern("write");
2221
1842
 
2222
1843
  rb_require("oj/bag");
2223
1844
  rb_require("oj/error");
@@ -2226,209 +1847,186 @@ void Init_oj() {
2226
1847
  rb_require("oj/schandler");
2227
1848
 
2228
1849
  oj_bag_class = rb_const_get_at(Oj, rb_intern("Bag"));
1850
+ rb_gc_register_mark_object(oj_bag_class);
2229
1851
  oj_bigdecimal_class = rb_const_get(rb_cObject, rb_intern("BigDecimal"));
1852
+ rb_gc_register_mark_object(oj_bigdecimal_class);
2230
1853
  oj_date_class = rb_const_get(rb_cObject, rb_intern("Date"));
1854
+ rb_gc_register_mark_object(oj_date_class);
2231
1855
  oj_datetime_class = rb_const_get(rb_cObject, rb_intern("DateTime"));
1856
+ rb_gc_register_mark_object(oj_datetime_class);
1857
+ oj_enumerable_class = rb_const_get(rb_cObject, rb_intern("Enumerable"));
1858
+ rb_gc_register_mark_object(oj_enumerable_class);
2232
1859
  oj_parse_error_class = rb_const_get_at(Oj, rb_intern("ParseError"));
1860
+ rb_gc_register_mark_object(oj_parse_error_class);
2233
1861
  oj_stringio_class = rb_const_get(rb_cObject, rb_intern("StringIO"));
1862
+ rb_gc_register_mark_object(oj_stringio_class);
2234
1863
  oj_struct_class = rb_const_get(rb_cObject, rb_intern("Struct"));
2235
- json_parser_error_class = Qnil; // replaced if mimic is called
2236
-
2237
- allow_gc_sym = ID2SYM(rb_intern("allow_gc")); rb_gc_register_address(&allow_gc_sym);
2238
- array_nl_sym = ID2SYM(rb_intern("array_nl")); rb_gc_register_address(&array_nl_sym);
2239
- ascii_only_sym = ID2SYM(rb_intern("ascii_only")); rb_gc_register_address(&ascii_only_sym);
2240
- ascii_sym = ID2SYM(rb_intern("ascii")); rb_gc_register_address(&ascii_sym);
2241
- auto_define_sym = ID2SYM(rb_intern("auto_define")); rb_gc_register_address(&auto_define_sym);
2242
- auto_sym = ID2SYM(rb_intern("auto")); rb_gc_register_address(&auto_sym);
2243
- bigdecimal_as_decimal_sym = ID2SYM(rb_intern("bigdecimal_as_decimal"));rb_gc_register_address(&bigdecimal_as_decimal_sym);
2244
- bigdecimal_load_sym = ID2SYM(rb_intern("bigdecimal_load"));rb_gc_register_address(&bigdecimal_load_sym);
2245
- bigdecimal_sym = ID2SYM(rb_intern("bigdecimal")); rb_gc_register_address(&bigdecimal_sym);
2246
- circular_sym = ID2SYM(rb_intern("circular")); rb_gc_register_address(&circular_sym);
2247
- class_cache_sym = ID2SYM(rb_intern("class_cache")); rb_gc_register_address(&class_cache_sym);
2248
- compat_sym = ID2SYM(rb_intern("compat")); rb_gc_register_address(&compat_sym);
2249
- create_id_sym = ID2SYM(rb_intern("create_id")); rb_gc_register_address(&create_id_sym);
2250
- escape_mode_sym = ID2SYM(rb_intern("escape_mode")); rb_gc_register_address(&escape_mode_sym);
2251
- float_prec_sym = ID2SYM(rb_intern("float_precision"));rb_gc_register_address(&float_prec_sym);
2252
- float_sym = ID2SYM(rb_intern("float")); rb_gc_register_address(&float_sym);
2253
- hash_class_sym = ID2SYM(rb_intern("hash_class")); rb_gc_register_address(&hash_class_sym);
2254
- huge_sym = ID2SYM(rb_intern("huge")); rb_gc_register_address(&huge_sym);
2255
- indent_sym = ID2SYM(rb_intern("indent")); rb_gc_register_address(&indent_sym);
2256
- json_sym = ID2SYM(rb_intern("json")); rb_gc_register_address(&json_sym);
2257
- mode_sym = ID2SYM(rb_intern("mode")); rb_gc_register_address(&mode_sym);
2258
- nan_sym = ID2SYM(rb_intern("nan")); rb_gc_register_address(&nan_sym);
2259
- newline_sym = ID2SYM(rb_intern("newline")); rb_gc_register_address(&newline_sym);
2260
- nilnil_sym = ID2SYM(rb_intern("nilnil")); rb_gc_register_address(&nilnil_sym);
2261
- null_sym = ID2SYM(rb_intern("null")); rb_gc_register_address(&null_sym);
2262
- object_nl_sym = ID2SYM(rb_intern("object_nl")); rb_gc_register_address(&object_nl_sym);
2263
- object_sym = ID2SYM(rb_intern("object")); rb_gc_register_address(&object_sym);
2264
- omit_nil_sym = ID2SYM(rb_intern("omit_nil")); rb_gc_register_address(&omit_nil_sym);
2265
- quirks_mode_sym = ID2SYM(rb_intern("quirks_mode")); rb_gc_register_address(&quirks_mode_sym);
2266
- allow_invalid_unicode_sym = ID2SYM(rb_intern("allow_invalid_unicode"));rb_gc_register_address(&allow_invalid_unicode_sym);
2267
- raise_sym = ID2SYM(rb_intern("raise")); rb_gc_register_address(&raise_sym);
2268
- ruby_sym = ID2SYM(rb_intern("ruby")); rb_gc_register_address(&ruby_sym);
2269
- sec_prec_sym = ID2SYM(rb_intern("second_precision"));rb_gc_register_address(&sec_prec_sym);
2270
- space_before_sym = ID2SYM(rb_intern("space_before"));rb_gc_register_address(&space_before_sym);
2271
- space_sym = ID2SYM(rb_intern("space")); rb_gc_register_address(&space_sym);
2272
- strict_sym = ID2SYM(rb_intern("strict")); rb_gc_register_address(&strict_sym);
2273
- symbol_keys_sym = ID2SYM(rb_intern("symbol_keys")); rb_gc_register_address(&symbol_keys_sym);
2274
- time_format_sym = ID2SYM(rb_intern("time_format")); rb_gc_register_address(&time_format_sym);
2275
- unix_sym = ID2SYM(rb_intern("unix")); rb_gc_register_address(&unix_sym);
2276
- unix_zone_sym = ID2SYM(rb_intern("unix_zone")); rb_gc_register_address(&unix_zone_sym);
2277
- use_as_json_sym = ID2SYM(rb_intern("use_as_json")); rb_gc_register_address(&use_as_json_sym);
2278
- use_to_json_sym = ID2SYM(rb_intern("use_to_json")); rb_gc_register_address(&use_to_json_sym);
2279
- word_sym = ID2SYM(rb_intern("word")); rb_gc_register_address(&word_sym);
2280
- xmlschema_sym = ID2SYM(rb_intern("xmlschema")); rb_gc_register_address(&xmlschema_sym);
2281
- xss_safe_sym = ID2SYM(rb_intern("xss_safe")); rb_gc_register_address(&xss_safe_sym);
2282
-
2283
- oj_slash_string = rb_str_new2("/"); rb_gc_register_address(&oj_slash_string);
1864
+ rb_gc_register_mark_object(oj_struct_class);
1865
+ oj_json_parser_error_class = rb_eEncodingError; // replaced if mimic is called
1866
+ oj_json_generator_error_class = rb_eEncodingError; // replaced if mimic is called
1867
+
1868
+ allow_blank_sym = ID2SYM(rb_intern("allow_blank"));
1869
+ rb_gc_register_address(&allow_blank_sym);
1870
+ allow_gc_sym = ID2SYM(rb_intern("allow_gc"));
1871
+ rb_gc_register_address(&allow_gc_sym);
1872
+ allow_invalid_unicode_sym = ID2SYM(rb_intern("allow_invalid_unicode"));
1873
+ rb_gc_register_address(&allow_invalid_unicode_sym);
1874
+ ascii_sym = ID2SYM(rb_intern("ascii"));
1875
+ rb_gc_register_address(&ascii_sym);
1876
+ auto_define_sym = ID2SYM(rb_intern("auto_define"));
1877
+ rb_gc_register_address(&auto_define_sym);
1878
+ auto_sym = ID2SYM(rb_intern("auto"));
1879
+ rb_gc_register_address(&auto_sym);
1880
+ bigdecimal_as_decimal_sym = ID2SYM(rb_intern("bigdecimal_as_decimal"));
1881
+ rb_gc_register_address(&bigdecimal_as_decimal_sym);
1882
+ bigdecimal_load_sym = ID2SYM(rb_intern("bigdecimal_load"));
1883
+ rb_gc_register_address(&bigdecimal_load_sym);
1884
+ bigdecimal_sym = ID2SYM(rb_intern("bigdecimal"));
1885
+ rb_gc_register_address(&bigdecimal_sym);
1886
+ cache_keys_sym = ID2SYM(rb_intern("cache_keys"));
1887
+ rb_gc_register_address(&cache_keys_sym);
1888
+ cache_str_sym = ID2SYM(rb_intern("cache_str"));
1889
+ rb_gc_register_address(&cache_str_sym);
1890
+ cache_string_sym = ID2SYM(rb_intern("cache_string"));
1891
+ rb_gc_register_address(&cache_string_sym);
1892
+ circular_sym = ID2SYM(rb_intern("circular"));
1893
+ rb_gc_register_address(&circular_sym);
1894
+ class_cache_sym = ID2SYM(rb_intern("class_cache"));
1895
+ rb_gc_register_address(&class_cache_sym);
1896
+ compat_bigdecimal_sym = ID2SYM(rb_intern("compat_bigdecimal"));
1897
+ rb_gc_register_address(&compat_bigdecimal_sym);
1898
+ compat_sym = ID2SYM(rb_intern("compat"));
1899
+ rb_gc_register_address(&compat_sym);
1900
+ create_id_sym = ID2SYM(rb_intern("create_id"));
1901
+ rb_gc_register_address(&create_id_sym);
1902
+ custom_sym = ID2SYM(rb_intern("custom"));
1903
+ rb_gc_register_address(&custom_sym);
1904
+ empty_string_sym = ID2SYM(rb_intern("empty_string"));
1905
+ rb_gc_register_address(&empty_string_sym);
1906
+ escape_mode_sym = ID2SYM(rb_intern("escape_mode"));
1907
+ rb_gc_register_address(&escape_mode_sym);
1908
+ integer_range_sym = ID2SYM(rb_intern("integer_range"));
1909
+ rb_gc_register_address(&integer_range_sym);
1910
+ fast_sym = ID2SYM(rb_intern("fast"));
1911
+ rb_gc_register_address(&fast_sym);
1912
+ float_prec_sym = ID2SYM(rb_intern("float_precision"));
1913
+ rb_gc_register_address(&float_prec_sym);
1914
+ float_sym = ID2SYM(rb_intern("float"));
1915
+ rb_gc_register_address(&float_sym);
1916
+ huge_sym = ID2SYM(rb_intern("huge"));
1917
+ rb_gc_register_address(&huge_sym);
1918
+ ignore_sym = ID2SYM(rb_intern("ignore"));
1919
+ rb_gc_register_address(&ignore_sym);
1920
+ ignore_under_sym = ID2SYM(rb_intern("ignore_under"));
1921
+ rb_gc_register_address(&ignore_under_sym);
1922
+ json_sym = ID2SYM(rb_intern("json"));
1923
+ rb_gc_register_address(&json_sym);
1924
+ match_string_sym = ID2SYM(rb_intern("match_string"));
1925
+ rb_gc_register_address(&match_string_sym);
1926
+ mode_sym = ID2SYM(rb_intern("mode"));
1927
+ rb_gc_register_address(&mode_sym);
1928
+ nan_sym = ID2SYM(rb_intern("nan"));
1929
+ rb_gc_register_address(&nan_sym);
1930
+ newline_sym = ID2SYM(rb_intern("newline"));
1931
+ rb_gc_register_address(&newline_sym);
1932
+ nilnil_sym = ID2SYM(rb_intern("nilnil"));
1933
+ rb_gc_register_address(&nilnil_sym);
1934
+ null_sym = ID2SYM(rb_intern("null"));
1935
+ rb_gc_register_address(&null_sym);
1936
+ object_sym = ID2SYM(rb_intern("object"));
1937
+ rb_gc_register_address(&object_sym);
1938
+ oj_allow_nan_sym = ID2SYM(rb_intern("allow_nan"));
1939
+ rb_gc_register_address(&oj_allow_nan_sym);
1940
+ oj_array_class_sym = ID2SYM(rb_intern("array_class"));
1941
+ rb_gc_register_address(&oj_array_class_sym);
1942
+ oj_array_nl_sym = ID2SYM(rb_intern("array_nl"));
1943
+ rb_gc_register_address(&oj_array_nl_sym);
1944
+ oj_ascii_only_sym = ID2SYM(rb_intern("ascii_only"));
1945
+ rb_gc_register_address(&oj_ascii_only_sym);
1946
+ oj_create_additions_sym = ID2SYM(rb_intern("create_additions"));
1947
+ rb_gc_register_address(&oj_create_additions_sym);
1948
+ oj_decimal_class_sym = ID2SYM(rb_intern("decimal_class"));
1949
+ rb_gc_register_address(&oj_decimal_class_sym);
1950
+ oj_hash_class_sym = ID2SYM(rb_intern("hash_class"));
1951
+ rb_gc_register_address(&oj_hash_class_sym);
1952
+ oj_indent_sym = ID2SYM(rb_intern("indent"));
1953
+ rb_gc_register_address(&oj_indent_sym);
1954
+ oj_max_nesting_sym = ID2SYM(rb_intern("max_nesting"));
1955
+ rb_gc_register_address(&oj_max_nesting_sym);
1956
+ oj_object_class_sym = ID2SYM(rb_intern("object_class"));
1957
+ rb_gc_register_address(&oj_object_class_sym);
1958
+ oj_object_nl_sym = ID2SYM(rb_intern("object_nl"));
1959
+ rb_gc_register_address(&oj_object_nl_sym);
1960
+ oj_quirks_mode_sym = ID2SYM(rb_intern("quirks_mode"));
1961
+ rb_gc_register_address(&oj_quirks_mode_sym);
1962
+ oj_safe_sym = ID2SYM(rb_intern("safe"));
1963
+ rb_gc_register_address(&oj_safe_sym);
1964
+ oj_space_before_sym = ID2SYM(rb_intern("space_before"));
1965
+ rb_gc_register_address(&oj_space_before_sym);
1966
+ oj_space_sym = ID2SYM(rb_intern("space"));
1967
+ rb_gc_register_address(&oj_space_sym);
1968
+ oj_trace_sym = ID2SYM(rb_intern("trace"));
1969
+ rb_gc_register_address(&oj_trace_sym);
1970
+ omit_nil_sym = ID2SYM(rb_intern("omit_nil"));
1971
+ rb_gc_register_address(&omit_nil_sym);
1972
+ rails_sym = ID2SYM(rb_intern("rails"));
1973
+ rb_gc_register_address(&rails_sym);
1974
+ raise_sym = ID2SYM(rb_intern("raise"));
1975
+ rb_gc_register_address(&raise_sym);
1976
+ ruby_sym = ID2SYM(rb_intern("ruby"));
1977
+ rb_gc_register_address(&ruby_sym);
1978
+ sec_prec_sym = ID2SYM(rb_intern("second_precision"));
1979
+ rb_gc_register_address(&sec_prec_sym);
1980
+ strict_sym = ID2SYM(rb_intern("strict"));
1981
+ rb_gc_register_address(&strict_sym);
1982
+ symbol_keys_sym = ID2SYM(rb_intern("symbol_keys"));
1983
+ rb_gc_register_address(&symbol_keys_sym);
1984
+ oj_symbolize_names_sym = ID2SYM(rb_intern("symbolize_names"));
1985
+ rb_gc_register_address(&oj_symbolize_names_sym);
1986
+ time_format_sym = ID2SYM(rb_intern("time_format"));
1987
+ rb_gc_register_address(&time_format_sym);
1988
+ unicode_xss_sym = ID2SYM(rb_intern("unicode_xss"));
1989
+ rb_gc_register_address(&unicode_xss_sym);
1990
+ unix_sym = ID2SYM(rb_intern("unix"));
1991
+ rb_gc_register_address(&unix_sym);
1992
+ unix_zone_sym = ID2SYM(rb_intern("unix_zone"));
1993
+ rb_gc_register_address(&unix_zone_sym);
1994
+ use_as_json_sym = ID2SYM(rb_intern("use_as_json"));
1995
+ rb_gc_register_address(&use_as_json_sym);
1996
+ use_raw_json_sym = ID2SYM(rb_intern("use_raw_json"));
1997
+ rb_gc_register_address(&use_raw_json_sym);
1998
+ use_to_hash_sym = ID2SYM(rb_intern("use_to_hash"));
1999
+ rb_gc_register_address(&use_to_hash_sym);
2000
+ use_to_json_sym = ID2SYM(rb_intern("use_to_json"));
2001
+ rb_gc_register_address(&use_to_json_sym);
2002
+ wab_sym = ID2SYM(rb_intern("wab"));
2003
+ rb_gc_register_address(&wab_sym);
2004
+ word_sym = ID2SYM(rb_intern("word"));
2005
+ rb_gc_register_address(&word_sym);
2006
+ xmlschema_sym = ID2SYM(rb_intern("xmlschema"));
2007
+ rb_gc_register_address(&xmlschema_sym);
2008
+ xss_safe_sym = ID2SYM(rb_intern("xss_safe"));
2009
+ rb_gc_register_address(&xss_safe_sym);
2010
+
2011
+ oj_slash_string = rb_str_new2("/");
2012
+ rb_gc_register_address(&oj_slash_string);
2013
+ OBJ_FREEZE(oj_slash_string);
2284
2014
 
2285
2015
  oj_default_options.mode = ObjectMode;
2286
2016
 
2287
2017
  oj_hash_init();
2288
2018
  oj_odd_init();
2019
+ oj_mimic_rails_init();
2289
2020
 
2290
- #if USE_PTHREAD_MUTEX
2291
- pthread_mutex_init(&oj_cache_mutex, 0);
2292
- #elif USE_RB_MUTEX
2021
+ #ifdef HAVE_PTHREAD_MUTEX_INIT
2022
+ if (0 != (err = pthread_mutex_init(&oj_cache_mutex, 0))) {
2023
+ rb_raise(rb_eException, "failed to initialize a mutex. %s", strerror(err));
2024
+ }
2025
+ #else
2293
2026
  oj_cache_mutex = rb_mutex_new();
2294
2027
  rb_gc_register_address(&oj_cache_mutex);
2295
2028
  #endif
2296
2029
  oj_init_doc();
2297
- }
2298
-
2299
- // mimic JSON documentation
2300
2030
 
2301
- /* Document-module: JSON
2302
- *
2303
- * JSON is a JSON parser. This module when defined by the Oj module is a
2304
- * faster replacement for the original.
2305
- */
2306
- /* Document-module: JSON::Ext
2307
- *
2308
- * The Ext module is a placeholder in the mimic JSON module used for
2309
- * compatibility only.
2310
- */
2311
- /* Document-class: JSON::Ext::Parser
2312
- *
2313
- * The JSON::Ext::Parser is a placeholder in the mimic JSON module used for
2314
- * compatibility only.
2315
- */
2316
- /* Document-class: JSON::Ext::Generator
2317
- *
2318
- * The JSON::Ext::Generator is a placeholder in the mimic JSON module used for
2319
- * compatibility only.
2320
- */
2321
-
2322
- /* Document-method: create_id=
2323
- * call-seq: create_id=(id) -> String
2324
- *
2325
- * Sets the create_id tag to look for in JSON document. That key triggers the
2326
- * creation of a class with the same name.
2327
- *
2328
- * @param [nil|String] id new create_id
2329
- * @return the id
2330
- */
2331
- /* Document-method: parser=
2332
- * call-seq: parser=(parser) -> nil
2333
- *
2334
- * Does nothing other than provide compatibiltiy.
2335
- * @param [Object] parser ignored
2336
- */
2337
- /* Document-method: generator=
2338
- * call-seq: generator=(generator) -> nil
2339
- *
2340
- * Does nothing other than provide compatibiltiy.
2341
- * @param [Object] generator ignored
2342
- */
2343
- /* Document-method: dump
2344
- * call-seq: dump(obj, anIO=nil, limit = nil) -> String
2345
- *
2346
- * Encodes an object as a JSON String.
2347
- *
2348
- * @param [Object] obj object to convert to encode as JSON
2349
- * @param [IO] anIO an IO that allows writing
2350
- * @param [Fixnum] limit ignored
2351
- */
2352
- /* Document-method: load
2353
- * call-seq: load(source, proc=nil) -> Object
2354
- *
2355
- * Loads a Ruby Object from a JSON source that can be either a String or an
2356
- * IO. If Proc is given or a block is providedit is called with each nested
2357
- * element of the loaded Object.
2358
- *
2359
- * @param [String|IO] source JSON source
2360
- * @param [Proc] proc to yield to on each element or nil
2361
- */
2362
- /* Document-method: restore
2363
- * call-seq: restore(source, proc=nil) -> Object
2364
- *
2365
- * Loads a Ruby Object from a JSON source that can be either a String or an
2366
- * IO. If Proc is given or a block is providedit is called with each nested
2367
- * element of the loaded Object.
2368
- *
2369
- * @param [String|IO] source JSON source
2370
- * @param [Proc] proc to yield to on each element or nil
2371
- */
2372
- /* Document-method: recurse_proc
2373
- * call-seq: recurse_proc(obj, &proc) -> nil
2374
- *
2375
- * Yields to the proc for every element in the obj recursivly.
2376
- *
2377
- * @param [Hash|Array] obj object to walk
2378
- * @param [Proc] proc to yield to on each element
2379
- */
2380
- /* Document-method: []
2381
- * call-seq: [](obj, opts={}) -> Object
2382
- *
2383
- * If the obj argument is a String then it is assumed to be a JSON String and
2384
- * parsed otherwise the obj is encoded as a JSON String.
2385
- *
2386
- * @param [String|Hash|Array] obj object to convert
2387
- * @param [Hash] opts same options as either generate or parse
2388
- */
2389
- /* Document-method: generate
2390
- * call-seq: generate(obj, opts=nil) -> String
2391
- *
2392
- * Encode obj as a JSON String. The obj argument must be a Hash, Array, or
2393
- * respond to to_h or to_json. Options other than those listed such as
2394
- * +:allow_nan+ or +:max_nesting+ are ignored.
2395
- *
2396
- * @param [Object|Hash|Array] obj object to convert to a JSON String
2397
- * @param [Hash] opts options
2398
- * @param [String] :indent String to use for indentation
2399
- * @param [String] :space String placed after a , or : delimiter
2400
- * @param [String] :space_before String placed before a : delimiter
2401
- * @param [String] :object_nl String placed after a JSON object
2402
- * @param [String] :array_nl String placed after a JSON array
2403
- * @param [true|false] :ascii_only if not nil or false then use only ascii
2404
- * characters in the output. Note JSON.generate does
2405
- * support this even if it is not documented.
2406
- */
2407
- /* Document-method: fast_generate
2408
- * call-seq: fast_generate(obj, opts=nil) -> String
2409
- * Same as generate().
2410
- * @see generate
2411
- */
2412
- /* Document-method: pretty_generate
2413
- * call-seq: pretty_generate(obj, opts=nil) -> String
2414
- * Same as generate() but with different defaults for the spacing options.
2415
- * @see generate
2416
- */
2417
- /* Document-method: parse
2418
- * call-seq: parse(source, opts=nil) -> Object
2419
- *
2420
- * Parses a JSON String or IO into a Ruby Object. Options other than those
2421
- * listed such as +:allow_nan+ or +:max_nesting+ are ignored. +:object_class+ and
2422
- * +:array_object+ are not supported.
2423
- *
2424
- * @param [String|IO] source source to parse
2425
- * @param [Hash] opts options
2426
- * @param [true|false] :symbolize_names flag indicating JSON object keys should be Symbols instead of Strings
2427
- * @param [true|false] :create_additions flag indicating a key matching +create_id+ in a JSON object should trigger the creation of Ruby Object
2428
- * @see create_id=
2429
- */
2430
- /* Document-method: parse!
2431
- * call-seq: parse!(source, opts=nil) -> Object
2432
- * Same as parse().
2433
- * @see parse
2434
- */
2031
+ oj_parser_init();
2032
+ }