oj 2.18.5 → 3.16.11

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