oj 3.7.4 → 3.11.2

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 (95) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +12 -4
  3. data/ext/oj/buf.h +6 -34
  4. data/ext/oj/cache8.c +3 -3
  5. data/ext/oj/cache8.h +5 -33
  6. data/ext/oj/circarray.c +5 -9
  7. data/ext/oj/circarray.h +5 -8
  8. data/ext/oj/code.c +3 -6
  9. data/ext/oj/code.h +7 -10
  10. data/ext/oj/compat.c +11 -14
  11. data/ext/oj/custom.c +108 -75
  12. data/ext/oj/dump.c +132 -92
  13. data/ext/oj/dump.h +6 -7
  14. data/ext/oj/dump_compat.c +37 -34
  15. data/ext/oj/dump_leaf.c +3 -6
  16. data/ext/oj/dump_object.c +23 -17
  17. data/ext/oj/dump_strict.c +7 -9
  18. data/ext/oj/encode.h +6 -32
  19. data/ext/oj/err.c +2 -5
  20. data/ext/oj/err.h +6 -34
  21. data/ext/oj/extconf.rb +6 -0
  22. data/ext/oj/fast.c +39 -56
  23. data/ext/oj/hash.c +11 -39
  24. data/ext/oj/hash.h +5 -33
  25. data/ext/oj/hash_test.c +3 -31
  26. data/ext/oj/mimic_json.c +65 -44
  27. data/ext/oj/object.c +38 -69
  28. data/ext/oj/odd.c +18 -17
  29. data/ext/oj/odd.h +6 -9
  30. data/ext/oj/oj.c +139 -93
  31. data/ext/oj/oj.h +43 -35
  32. data/ext/oj/parse.c +164 -60
  33. data/ext/oj/parse.h +30 -31
  34. data/ext/oj/rails.c +119 -83
  35. data/ext/oj/rails.h +4 -7
  36. data/ext/oj/reader.c +5 -8
  37. data/ext/oj/reader.h +7 -10
  38. data/ext/oj/resolve.c +4 -7
  39. data/ext/oj/resolve.h +4 -7
  40. data/ext/oj/rxclass.c +8 -11
  41. data/ext/oj/rxclass.h +8 -11
  42. data/ext/oj/saj.c +9 -12
  43. data/ext/oj/scp.c +4 -7
  44. data/ext/oj/sparse.c +67 -33
  45. data/ext/oj/stream_writer.c +16 -15
  46. data/ext/oj/strict.c +9 -12
  47. data/ext/oj/string_writer.c +27 -8
  48. data/ext/oj/trace.c +5 -8
  49. data/ext/oj/trace.h +9 -12
  50. data/ext/oj/util.c +136 -0
  51. data/ext/oj/util.h +19 -0
  52. data/ext/oj/val_stack.c +28 -36
  53. data/ext/oj/val_stack.h +19 -50
  54. data/ext/oj/wab.c +29 -29
  55. data/lib/oj.rb +0 -8
  56. data/lib/oj/json.rb +1 -1
  57. data/lib/oj/mimic.rb +46 -2
  58. data/lib/oj/version.rb +2 -2
  59. data/pages/Modes.md +47 -45
  60. data/pages/Options.md +43 -10
  61. data/pages/Rails.md +60 -21
  62. data/pages/Security.md +1 -1
  63. data/test/activesupport5/abstract_unit.rb +45 -0
  64. data/test/activesupport5/decoding_test.rb +68 -60
  65. data/test/activesupport5/encoding_test.rb +111 -96
  66. data/test/activesupport5/encoding_test_cases.rb +33 -25
  67. data/test/activesupport5/test_helper.rb +43 -21
  68. data/test/activesupport5/time_zone_test_helpers.rb +18 -3
  69. data/test/activesupport6/abstract_unit.rb +44 -0
  70. data/test/activesupport6/decoding_test.rb +133 -0
  71. data/test/activesupport6/encoding_test.rb +507 -0
  72. data/test/activesupport6/encoding_test_cases.rb +98 -0
  73. data/test/activesupport6/test_common.rb +17 -0
  74. data/test/activesupport6/test_helper.rb +163 -0
  75. data/test/activesupport6/time_zone_test_helpers.rb +39 -0
  76. data/test/bar.rb +24 -6
  77. data/test/baz.rb +16 -0
  78. data/test/foo.rb +26 -57
  79. data/test/helper.rb +10 -0
  80. data/test/json_gem/json_common_interface_test.rb +8 -3
  81. data/test/json_gem/json_generator_test.rb +15 -3
  82. data/test/json_gem/test_helper.rb +8 -0
  83. data/test/prec.rb +23 -0
  84. data/test/sample_json.rb +1 -1
  85. data/test/test_compat.rb +21 -10
  86. data/test/test_custom.rb +135 -8
  87. data/test/test_integer_range.rb +1 -2
  88. data/test/test_object.rb +35 -2
  89. data/test/test_rails.rb +35 -0
  90. data/test/test_strict.rb +24 -1
  91. data/test/test_various.rb +52 -63
  92. data/test/test_writer.rb +19 -2
  93. data/test/tests.rb +1 -0
  94. data/test/zoo.rb +13 -0
  95. metadata +100 -75
data/ext/oj/odd.c CHANGED
@@ -1,14 +1,11 @@
1
- /* odd.c
2
- * Copyright (c) 2011, Peter Ohler
3
- * All rights reserved.
4
- */
1
+ // Copyright (c) 2011 Peter Ohler. All rights reserved.
5
2
 
6
3
  #include <string.h>
7
4
 
8
5
  #include "odd.h"
9
6
 
10
- static struct _Odd _odds[4]; // bump up if new initial Odd classes are added
11
- static struct _Odd *odds = _odds;
7
+ static struct _odd _odds[4]; // bump up if new initial Odd classes are added
8
+ static struct _odd *odds = _odds;
12
9
  static long odd_cnt = 0;
13
10
  static ID sec_id;
14
11
  static ID sec_fraction_id;
@@ -38,11 +35,11 @@ set_class(Odd odd, const char *classname) {
38
35
 
39
36
  static VALUE
40
37
  get_datetime_secs(VALUE obj) {
41
- VALUE rsecs = rb_funcall(obj, sec_id, 0);
42
- VALUE rfrac = rb_funcall(obj, sec_fraction_id, 0);
43
- long sec = NUM2LONG(rsecs);
44
- long long num = rb_num2ll(rb_funcall(rfrac, numerator_id, 0));
45
- long long den = rb_num2ll(rb_funcall(rfrac, denominator_id, 0));
38
+ volatile VALUE rsecs = rb_funcall(obj, sec_id, 0);
39
+ volatile VALUE rfrac = rb_funcall(obj, sec_fraction_id, 0);
40
+ long sec = NUM2LONG(rsecs);
41
+ long long num = rb_num2ll(rb_funcall(rfrac, numerator_id, 0));
42
+ long long den = rb_num2ll(rb_funcall(rfrac, denominator_id, 0));
46
43
 
47
44
  num += sec * den;
48
45
 
@@ -152,7 +149,7 @@ oj_get_oddc(const char *classname, size_t len) {
152
149
 
153
150
  OddArgs
154
151
  oj_odd_alloc_args(Odd odd) {
155
- OddArgs oa = ALLOC_N(struct _OddArgs, 1);
152
+ OddArgs oa = ALLOC_N(struct _oddArgs, 1);
156
153
  VALUE *a;
157
154
  int i;
158
155
 
@@ -191,15 +188,17 @@ oj_reg_odd(VALUE clas, VALUE create_object, VALUE create_method, int mcnt, VALUE
191
188
  AttrGetFunc *fp;
192
189
 
193
190
  if (_odds == odds) {
194
- odds = ALLOC_N(struct _Odd, odd_cnt + 1);
191
+ odds = ALLOC_N(struct _odd, odd_cnt + 1);
195
192
 
196
- memcpy(odds, _odds, sizeof(struct _Odd) * odd_cnt);
193
+ memcpy(odds, _odds, sizeof(struct _odd) * odd_cnt);
197
194
  } else {
198
- REALLOC_N(odds, struct _Odd, odd_cnt + 1);
195
+ REALLOC_N(odds, struct _odd, odd_cnt + 1);
199
196
  }
200
197
  odd = odds + odd_cnt;
201
198
  odd->clas = clas;
202
- odd->classname = strdup(rb_class2name(clas));
199
+ if (NULL == (odd->classname = strdup(rb_class2name(clas)))) {
200
+ rb_raise(rb_eNoMemError, "for attribute name.");
201
+ }
203
202
  odd->clen = strlen(odd->classname);
204
203
  odd->create_obj = create_object;
205
204
  odd->create_op = SYM2ID(create_method);
@@ -210,7 +209,9 @@ oj_reg_odd(VALUE clas, VALUE create_object, VALUE create_method, int mcnt, VALUE
210
209
  *fp = 0;
211
210
  switch (rb_type(*members)) {
212
211
  case T_STRING:
213
- *np = strdup(rb_string_value_ptr(members));
212
+ if (NULL == (*np = strdup(rb_string_value_ptr(members)))) {
213
+ rb_raise(rb_eNoMemError, "for attribute name.");
214
+ }
214
215
  break;
215
216
  case T_SYMBOL:
216
217
  *np = rb_id2name(SYM2ID(*members));
data/ext/oj/odd.h CHANGED
@@ -1,10 +1,7 @@
1
- /* odd.h
2
- * Copyright (c) 2011, Peter Ohler
3
- * All rights reserved.
4
- */
1
+ // Copyright (c) 2011 Peter Ohler. All rights reserved.
5
2
 
6
- #ifndef __OJ_ODD_H__
7
- #define __OJ_ODD_H__
3
+ #ifndef OJ_ODD_H
4
+ #define OJ_ODD_H
8
5
 
9
6
  #include <stdbool.h>
10
7
 
@@ -14,7 +11,7 @@
14
11
 
15
12
  typedef VALUE (*AttrGetFunc)(VALUE obj);
16
13
 
17
- typedef struct _Odd {
14
+ typedef struct _odd {
18
15
  const char *classname;
19
16
  size_t clen;
20
17
  VALUE clas; // Ruby class or module
@@ -28,7 +25,7 @@ typedef struct _Odd {
28
25
  AttrGetFunc attrFuncs[MAX_ODD_ARGS];
29
26
  } *Odd;
30
27
 
31
- typedef struct _OddArgs {
28
+ typedef struct _oddArgs {
32
29
  Odd odd;
33
30
  VALUE args[MAX_ODD_ARGS];
34
31
  } *OddArgs;
@@ -41,4 +38,4 @@ extern void oj_odd_free(OddArgs args);
41
38
  extern int oj_odd_set_arg(OddArgs args, const char *key, size_t klen, VALUE value);
42
39
  extern void oj_reg_odd(VALUE clas, VALUE create_object, VALUE create_method, int mcnt, VALUE *members, bool raw);
43
40
 
44
- #endif /* __OJ_ODD_H__ */
41
+ #endif /* OJ_ODD_H */
data/ext/oj/oj.c CHANGED
@@ -1,7 +1,4 @@
1
- /* oj.c
2
- * Copyright (c) 2012, Peter Ohler
3
- * All rights reserved.
4
- */
1
+ // Copyright (c) 2012 Peter Ohler. All rights reserved.
5
2
 
6
3
  #include <stdlib.h>
7
4
  #include <errno.h>
@@ -19,7 +16,7 @@
19
16
  #include "rails.h"
20
17
  #include "encode.h"
21
18
 
22
- typedef struct _YesNoOpt {
19
+ typedef struct _yesNoOpt {
23
20
  VALUE sym;
24
21
  char *attr;
25
22
  } *YesNoOpt;
@@ -53,6 +50,7 @@ ID oj_length_id;
53
50
  ID oj_new_id;
54
51
  ID oj_parse_id;
55
52
  ID oj_pos_id;
53
+ ID oj_raw_json_id;
56
54
  ID oj_read_id;
57
55
  ID oj_readpartial_id;
58
56
  ID oj_replace_id;
@@ -90,10 +88,12 @@ VALUE oj_slash_string;
90
88
  VALUE oj_allow_nan_sym;
91
89
  VALUE oj_array_class_sym;
92
90
  VALUE oj_create_additions_sym;
91
+ VALUE oj_decimal_class_sym;
93
92
  VALUE oj_hash_class_sym;
94
93
  VALUE oj_indent_sym;
95
94
  VALUE oj_object_class_sym;
96
95
  VALUE oj_quirks_mode_sym;
96
+ VALUE oj_safe_sym;
97
97
  VALUE oj_trace_sym;
98
98
 
99
99
  static VALUE allow_blank_sym;
@@ -107,16 +107,19 @@ static VALUE bigdecimal_load_sym;
107
107
  static VALUE bigdecimal_sym;
108
108
  static VALUE circular_sym;
109
109
  static VALUE class_cache_sym;
110
+ static VALUE compat_bigdecimal_sym;
110
111
  static VALUE compat_sym;
111
112
  static VALUE create_id_sym;
112
113
  static VALUE custom_sym;
113
114
  static VALUE empty_string_sym;
114
115
  static VALUE escape_mode_sym;
115
116
  static VALUE integer_range_sym;
117
+ static VALUE fast_sym;
116
118
  static VALUE float_prec_sym;
117
119
  static VALUE float_sym;
118
120
  static VALUE huge_sym;
119
121
  static VALUE ignore_sym;
122
+ static VALUE ignore_under_sym;
120
123
  static VALUE json_sym;
121
124
  static VALUE match_string_sym;
122
125
  static VALUE mode_sym;
@@ -137,6 +140,7 @@ static VALUE unicode_xss_sym;
137
140
  static VALUE unix_sym;
138
141
  static VALUE unix_zone_sym;
139
142
  static VALUE use_as_json_sym;
143
+ static VALUE use_raw_json_sym;
140
144
  static VALUE use_to_hash_sym;
141
145
  static VALUE use_to_json_sym;
142
146
  static VALUE wab_sym;
@@ -146,7 +150,7 @@ static VALUE xss_safe_sym;
146
150
 
147
151
  rb_encoding *oj_utf8_encoding = 0;
148
152
 
149
- #if HAVE_LIBPTHREAD
153
+ #ifdef HAVE_PTHREAD_MUTEX_INIT
150
154
  pthread_mutex_t oj_cache_mutex;
151
155
  #else
152
156
  VALUE oj_cache_mutex = Qnil;
@@ -154,7 +158,7 @@ VALUE oj_cache_mutex = Qnil;
154
158
 
155
159
  const char oj_json_class[] = "json_class";
156
160
 
157
- struct _Options oj_default_options = {
161
+ struct _options oj_default_options = {
158
162
  0, // indent
159
163
  No, // circular
160
164
  No, // auto_define
@@ -165,9 +169,11 @@ struct _Options oj_default_options = {
165
169
  UnixTime, // time_format
166
170
  NotSet, // bigdec_as_num
167
171
  AutoDec, // bigdec_load
172
+ false, // compat_bigdec
168
173
  No, // to_hash
169
174
  No, // to_json
170
175
  No, // as_json
176
+ No, // raw_json
171
177
  No, // nilnil
172
178
  Yes, // empty_string
173
179
  Yes, // allow_gc
@@ -176,8 +182,11 @@ struct _Options oj_default_options = {
176
182
  No, // create_ok
177
183
  Yes, // allow_nan
178
184
  No, // trace
179
- 0, // integer_range_min
180
- 0, // integer_range_max
185
+ No, // safe
186
+ false, // sec_prec_set
187
+ No, // ignore_under
188
+ 0, // int_range_min
189
+ 0, // int_range_max
181
190
  oj_json_class, // create_id
182
191
  10, // create_id_len
183
192
  9, // sec_prec
@@ -222,13 +231,15 @@ struct _Options oj_default_options = {
222
231
  * - *:mode* [_:object_|_:strict_|_:compat_|_:null_|_:custom_|_:rails_|_:wab_] load and dump modes to use for JSON
223
232
  * - *:time_format* [_:unix_|_:unix_zone_|_:xmlschema_|_:ruby_] time format when dumping
224
233
  * - *:bigdecimal_as_decimal* [_Boolean_|_nil_] dump BigDecimal as a decimal number or as a String
225
- * - *:bigdecimal_load* [_:bigdecimal_|_:float_|_:auto_] load decimals as BigDecimal instead of as a Float. :auto pick the most precise for the number of digits.
234
+ * - *:bigdecimal_load* [_:bigdecimal_|_:float_|_:auto_|_:fast_] load decimals as BigDecimal instead of as a Float. :auto pick the most precise for the number of digits. :float should be the same as ruby. :fast may require rounding but is must faster.
235
+ * - *:compat_bigdecimal* [_true_|_false_] load decimals as BigDecimal instead of as a Float when in compat or rails mode.
226
236
  * - *:create_id* [_String_|_nil_] create id for json compatible object encoding, default is 'json_class'
227
237
  * - *:create_additions* [_Boolean_|_nil_] if true allow creation of instances using create_id on load.
228
238
  * - *:second_precision* [_Fixnum_|_nil_] number of digits after the decimal when dumping the seconds portion of time
229
239
  * - *:float_precision* [_Fixnum_|_nil_] number of digits of precision when dumping floats, 0 indicates use Ruby
230
240
  * - *:use_to_json* [_Boolean_|_nil_] call to_json() methods on dump, default is false
231
241
  * - *:use_as_json* [_Boolean_|_nil_] call as_json() methods on dump, default is false
242
+ * - *:use_raw_json* [_Boolean_|_nil_] call raw_json() methods on dump, default is false
232
243
  * - *:nilnil* [_Boolean_|_nil_] if true a nil input to load will return nil and not raise an Exception
233
244
  * - *:empty_string* [_Boolean_|_nil_] if true an empty input will not raise an Exception
234
245
  * - *:allow_gc* [_Boolean_|_nil_] allow or prohibit GC during parsing, default is true (allow)
@@ -245,8 +256,10 @@ struct _Options oj_default_options = {
245
256
  * - *:array_class* [_Class_|_nil_] Class to use instead of Array on load
246
257
  * - *:omit_nil* [_true_|_false_] if true Hash and Object attributes with nil values are omitted
247
258
  * - *:ignore* [_nil_|Array] either nil or an Array of classes to ignore when dumping
248
- * - *:integer_range* [_Range_] Dump integers outside range as strings.
259
+ * - *:ignore_under* [Boolean] if true then attributes that start with _ are ignored when dumping in object or custom mode.
260
+ * - *:integer_range* [_Range_] Dump integers outside range as strings.
249
261
  * - *:trace* [_true,_|_false_] Trace all load and dump calls, default is false (trace is off)
262
+ * - *:safe* [_true,_|_false_] Safe mimic breaks JSON mimic to be safer, default is false (safe is off)
250
263
  *
251
264
  * Return [_Hash_] all current option settings.
252
265
  */
@@ -269,6 +282,7 @@ get_def_opts(VALUE self) {
269
282
  rb_hash_aset(opts, use_to_json_sym, (Yes == oj_default_options.to_json) ? Qtrue : ((No == oj_default_options.to_json) ? Qfalse : Qnil));
270
283
  rb_hash_aset(opts, use_to_hash_sym, (Yes == oj_default_options.to_hash) ? Qtrue : ((No == oj_default_options.to_hash) ? Qfalse : Qnil));
271
284
  rb_hash_aset(opts, use_as_json_sym, (Yes == oj_default_options.as_json) ? Qtrue : ((No == oj_default_options.as_json) ? Qfalse : Qnil));
285
+ rb_hash_aset(opts, use_raw_json_sym, (Yes == oj_default_options.raw_json) ? Qtrue : ((No == oj_default_options.raw_json) ? Qfalse : Qnil));
272
286
  rb_hash_aset(opts, nilnil_sym, (Yes == oj_default_options.nilnil) ? Qtrue : ((No == oj_default_options.nilnil) ? Qfalse : Qnil));
273
287
  rb_hash_aset(opts, empty_string_sym, (Yes == oj_default_options.empty_string) ? Qtrue : ((No == oj_default_options.empty_string) ? Qfalse : Qnil));
274
288
  rb_hash_aset(opts, allow_gc_sym, (Yes == oj_default_options.allow_gc) ? Qtrue : ((No == oj_default_options.allow_gc) ? Qfalse : Qnil));
@@ -276,7 +290,9 @@ get_def_opts(VALUE self) {
276
290
  rb_hash_aset(opts, allow_invalid_unicode_sym, (Yes == oj_default_options.allow_invalid) ? Qtrue : ((No == oj_default_options.allow_invalid) ? Qfalse : Qnil));
277
291
  rb_hash_aset(opts, oj_allow_nan_sym, (Yes == oj_default_options.allow_nan) ? Qtrue : ((No == oj_default_options.allow_nan) ? Qfalse : Qnil));
278
292
  rb_hash_aset(opts, oj_trace_sym, (Yes == oj_default_options.trace) ? Qtrue : ((No == oj_default_options.trace) ? Qfalse : Qnil));
293
+ rb_hash_aset(opts, oj_safe_sym, (Yes == oj_default_options.safe) ? Qtrue : ((No == oj_default_options.safe) ? Qfalse : Qnil));
279
294
  rb_hash_aset(opts, float_prec_sym, INT2FIX(oj_default_options.float_prec));
295
+ rb_hash_aset(opts, ignore_under_sym, (Yes == oj_default_options.ignore_under) ? Qtrue : ((No == oj_default_options.ignore_under) ? Qfalse : Qnil));
280
296
  switch (oj_default_options.mode) {
281
297
  case StrictMode: rb_hash_aset(opts, mode_sym, strict_sym); break;
282
298
  case CompatMode: rb_hash_aset(opts, mode_sym, compat_sym); break;
@@ -287,17 +303,17 @@ get_def_opts(VALUE self) {
287
303
  case WabMode: rb_hash_aset(opts, mode_sym, wab_sym); break;
288
304
  default: rb_hash_aset(opts, mode_sym, object_sym); break;
289
305
  }
290
-
291
- if (oj_default_options.integer_range_max != 0 || oj_default_options.integer_range_min != 0) {
292
- VALUE range = rb_obj_alloc(rb_cRange);
293
- VALUE min = LONG2FIX(oj_default_options.integer_range_min);
294
- VALUE max = LONG2FIX(oj_default_options.integer_range_max);
295
- rb_ivar_set(range, oj_begin_id, min);
296
- rb_ivar_set(range, oj_end_id, max);
297
- rb_hash_aset(opts, integer_range_sym, range);
298
- }
299
- else {
300
- rb_hash_aset(opts, integer_range_sym, Qnil);
306
+
307
+ if (oj_default_options.int_range_max != 0 || oj_default_options.int_range_min != 0) {
308
+ VALUE range = rb_obj_alloc(rb_cRange);
309
+ VALUE min = LONG2FIX(oj_default_options.int_range_min);
310
+ VALUE max = LONG2FIX(oj_default_options.int_range_max);
311
+
312
+ rb_ivar_set(range, oj_begin_id, min);
313
+ rb_ivar_set(range, oj_end_id, max);
314
+ rb_hash_aset(opts, integer_range_sym, range);
315
+ } else {
316
+ rb_hash_aset(opts, integer_range_sym, Qnil);
301
317
  }
302
318
  switch (oj_default_options.escape_mode) {
303
319
  case NLEsc: rb_hash_aset(opts, escape_mode_sym, newline_sym); break;
@@ -317,10 +333,12 @@ get_def_opts(VALUE self) {
317
333
  switch (oj_default_options.bigdec_load) {
318
334
  case BigDec: rb_hash_aset(opts, bigdecimal_load_sym, bigdecimal_sym);break;
319
335
  case FloatDec: rb_hash_aset(opts, bigdecimal_load_sym, float_sym); break;
336
+ case FastDec: rb_hash_aset(opts, bigdecimal_load_sym, fast_sym); break;
320
337
  case AutoDec:
321
338
  default: rb_hash_aset(opts, bigdecimal_load_sym, auto_sym); break;
322
339
  }
323
- rb_hash_aset(opts, create_id_sym, (0 == oj_default_options.create_id) ? Qnil : rb_str_new2(oj_default_options.create_id));
340
+ rb_hash_aset(opts, compat_bigdecimal_sym, oj_default_options.compat_bigdec ? Qtrue : Qfalse);
341
+ rb_hash_aset(opts, create_id_sym, (NULL == oj_default_options.create_id) ? Qnil : rb_str_new2(oj_default_options.create_id));
324
342
  rb_hash_aset(opts, oj_space_sym, (0 == oj_default_options.dump_opts.after_size) ? Qnil : rb_str_new2(oj_default_options.dump_opts.after_sep));
325
343
  rb_hash_aset(opts, oj_space_before_sym, (0 == oj_default_options.dump_opts.before_size) ? Qnil : rb_str_new2(oj_default_options.dump_opts.before_sep));
326
344
  rb_hash_aset(opts, oj_object_nl_sym, (0 == oj_default_options.dump_opts.hash_size) ? Qnil : rb_str_new2(oj_default_options.dump_opts.hash_nl));
@@ -343,7 +361,7 @@ get_def_opts(VALUE self) {
343
361
  } else {
344
362
  VALUE *vp;
345
363
  volatile VALUE a = rb_ary_new();
346
-
364
+
347
365
  for (vp = oj_default_options.ignore; Qnil != *vp; vp++) {
348
366
  rb_ary_push(a, *vp);
349
367
  }
@@ -365,6 +383,7 @@ get_def_opts(VALUE self) {
365
383
  * - *:escape* [_:newline_|_:json_|_:xss_safe_|_:ascii_|_unicode_xss_|_nil_] mode encodes all high-bit characters as escaped sequences if :ascii, :json is standand UTF-8 JSON encoding, :newline is the same as :json but newlines are not escaped, :unicode_xss allows unicode but escapes &, <, and >, and any \u20xx characters along with some others, and :xss_safe escapes &, <, and >, and some others.
366
384
  * - *:bigdecimal_as_decimal* [_Boolean_|_nil_] dump BigDecimal as a decimal number or as a String.
367
385
  * - *:bigdecimal_load* [_:bigdecimal_|_:float_|_:auto_|_nil_] load decimals as BigDecimal instead of as a Float. :auto pick the most precise for the number of digits.
386
+ * - *:compat_bigdecimal* [_true_|_false_] load decimals as BigDecimal instead of as a Float in compat mode.
368
387
  * - *:mode* [_:object_|_:strict_|_:compat_|_:null_|_:custom_|_:rails_|_:wab_] load and dump mode to use for JSON :strict raises an exception when a non-supported Object is encountered. :compat attempts to extract variable values from an Object using to_json() or to_hash() then it walks the Object's variables if neither is found. The :object mode ignores to_hash() and to_json() methods and encodes variables using code internal to the Oj gem. The :null mode ignores non-supported Objects and replaces them with a null. The :custom mode honors all dump options. The :rails more mimics rails and Active behavior.
369
388
  * - *:time_format* [_:unix_|_:xmlschema_|_:ruby_] time format when dumping in :compat mode :unix decimal number denoting the number of seconds since 1/1/1970, :unix_zone decimal number denoting the number of seconds since 1/1/1970 plus the utc_offset in the exponent, :xmlschema date-time format taken from XML Schema as a String, :ruby Time.to_s formatted String.
370
389
  * - *:create_id* [_String_|_nil_] create id for json compatible object encoding
@@ -374,6 +393,7 @@ get_def_opts(VALUE self) {
374
393
  * - *:use_to_json* [_Boolean_|_nil_] call to_json() methods on dump, default is false.
375
394
  * - *:use_as_json* [_Boolean_|_nil_] call as_json() methods on dump, default is false.
376
395
  * - *:use_to_hash* [_Boolean_|_nil_] call to_hash() methods on dump, default is false.
396
+ * - *:use_raw_json* [_Boolean_|_nil_] call raw_json() methods on dump, default is false.
377
397
  * - *:nilnil* [_Boolean_|_nil_] if true a nil input to load will return nil and not raise an Exception.
378
398
  * - *:allow_gc* [_Boolean_|_nil_] allow or prohibit GC during parsing, default is true (allow).
379
399
  * - *:quirks_mode* [_Boolean_|_nil_] allow single JSON values instead of documents, default is true (allow).
@@ -388,8 +408,10 @@ get_def_opts(VALUE self) {
388
408
  * - *:array_class* [_Class_|_nil_] Class to use instead of Array on load.
389
409
  * - *:omit_nil* [_true_|_false_] if true Hash and Object attributes with nil values are omitted.
390
410
  * - *:ignore* [_nil_|Array] either nil or an Array of classes to ignore when dumping
391
- * - *:integer_range* [_Range_] Dump integers outside range as strings.
411
+ * - *:ignore_under* [_Boolean_] if true then attributes that start with _ are ignored when dumping in object or custom mode.
412
+ * - *:integer_range* [_Range_] Dump integers outside range as strings.
392
413
  * - *:trace* [_Boolean_] turn trace on or off.
414
+ * - *:safe* [_Boolean_] turn safe mimic on or off.
393
415
  */
394
416
  static VALUE
395
417
  set_def_opts(VALUE self, VALUE opts) {
@@ -401,7 +423,7 @@ set_def_opts(VALUE self, VALUE opts) {
401
423
 
402
424
  void
403
425
  oj_parse_options(VALUE ropts, Options copts) {
404
- struct _YesNoOpt ynos[] = {
426
+ struct _yesNoOpt ynos[] = {
405
427
  { circular_sym, &copts->circular },
406
428
  { auto_define_sym, &copts->auto_define },
407
429
  { symbol_keys_sym, &copts->sym_key },
@@ -410,6 +432,7 @@ oj_parse_options(VALUE ropts, Options copts) {
410
432
  { use_to_hash_sym, &copts->to_hash },
411
433
  { use_to_json_sym, &copts->to_json },
412
434
  { use_as_json_sym, &copts->as_json },
435
+ { use_raw_json_sym, &copts->raw_json },
413
436
  { nilnil_sym, &copts->nilnil },
414
437
  { allow_blank_sym, &copts->nilnil }, // same as nilnil
415
438
  { empty_string_sym, &copts->empty_string },
@@ -418,13 +441,15 @@ oj_parse_options(VALUE ropts, Options copts) {
418
441
  { allow_invalid_unicode_sym, &copts->allow_invalid },
419
442
  { oj_allow_nan_sym, &copts->allow_nan },
420
443
  { oj_trace_sym, &copts->trace },
444
+ { oj_safe_sym, &copts->safe },
445
+ { ignore_under_sym, &copts->ignore_under },
421
446
  { oj_create_additions_sym, &copts->create_ok },
422
447
  { Qnil, 0 }
423
448
  };
424
449
  YesNoOpt o;
425
450
  volatile VALUE v;
426
451
  size_t len;
427
-
452
+
428
453
  if (T_HASH != rb_type(ropts)) {
429
454
  return;
430
455
  }
@@ -493,8 +518,12 @@ oj_parse_options(VALUE ropts, Options copts) {
493
518
  n = NUM2INT(v);
494
519
  if (0 > n) {
495
520
  n = 0;
521
+ copts->sec_prec_set = false;
496
522
  } else if (9 < n) {
497
523
  n = 9;
524
+ copts->sec_prec_set = true;
525
+ } else {
526
+ copts->sec_prec_set = true;
498
527
  }
499
528
  copts->sec_prec = n;
500
529
  }
@@ -550,12 +579,27 @@ oj_parse_options(VALUE ropts, Options copts) {
550
579
  copts->bigdec_load = BigDec;
551
580
  } else if (float_sym == v) {
552
581
  copts->bigdec_load = FloatDec;
582
+ } else if (fast_sym == v) {
583
+ copts->bigdec_load = FastDec;
553
584
  } else if (auto_sym == v || Qfalse == v) {
554
585
  copts->bigdec_load = AutoDec;
555
586
  } else {
556
587
  rb_raise(rb_eArgError, ":bigdecimal_load must be :bigdecimal, :float, or :auto.");
557
588
  }
558
589
  }
590
+ if (Qnil != (v = rb_hash_lookup(ropts, compat_bigdecimal_sym))) {
591
+ copts->compat_bigdec = (Qtrue == v);
592
+ }
593
+ if (Qtrue == rb_funcall(ropts, oj_has_key_id, 1, oj_decimal_class_sym)) {
594
+ v = rb_hash_lookup(ropts, oj_decimal_class_sym);
595
+ if (rb_cFloat == v) {
596
+ copts->compat_bigdec = false;
597
+ } else if (oj_bigdecimal_class == v) {
598
+ copts->compat_bigdec = true;
599
+ } else {
600
+ rb_raise(rb_eArgError, ":decimal_class must be BigDecimal or Float.");
601
+ }
602
+ }
559
603
  if (Qtrue == rb_funcall(ropts, oj_has_key_id, 1, create_id_sym)) {
560
604
  v = rb_hash_lookup(ropts, create_id_sym);
561
605
  if (Qnil == v) {
@@ -715,7 +759,7 @@ oj_parse_options(VALUE ropts, Options copts) {
715
759
  cnt = (int)RARRAY_LEN(v);
716
760
  if (0 < cnt) {
717
761
  int i;
718
-
762
+
719
763
  copts->ignore = ALLOC_N(VALUE, cnt + 1);
720
764
  for (i = 0; i < cnt; i++) {
721
765
  copts->ignore[i] = rb_ary_entry(v, i);
@@ -725,24 +769,26 @@ oj_parse_options(VALUE ropts, Options copts) {
725
769
  }
726
770
  }
727
771
  if (Qnil != (v = rb_hash_lookup(ropts, integer_range_sym))) {
728
- if (TYPE(v) == T_STRUCT && rb_obj_class(v) == rb_cRange) {
729
- VALUE min = rb_funcall(v, oj_begin_id, 0);
730
- VALUE max = rb_funcall(v, oj_end_id, 0);
731
-
732
- if (TYPE(min) != T_FIXNUM || TYPE(max) != T_FIXNUM) {
733
- rb_raise(rb_eArgError, ":integer_range range bounds is not Fixnum.");
734
- }
735
-
736
- copts->integer_range_min = FIX2LONG(min);
737
- copts->integer_range_max = FIX2LONG(max);
738
- } else if (Qfalse != v) {
739
- rb_raise(rb_eArgError, ":integer_range must be a range of Fixnum.");
740
- }
772
+ if (TYPE(v) == T_STRUCT && rb_obj_class(v) == rb_cRange) {
773
+ VALUE min = rb_funcall(v, oj_begin_id, 0);
774
+ VALUE max = rb_funcall(v, oj_end_id, 0);
775
+
776
+ if (TYPE(min) != T_FIXNUM || TYPE(max) != T_FIXNUM) {
777
+ rb_raise(rb_eArgError, ":integer_range range bounds is not Fixnum.");
778
+ }
779
+
780
+ copts->int_range_min = FIX2LONG(min);
781
+ copts->int_range_max = FIX2LONG(max);
782
+ } else if (Qfalse != v) {
783
+ rb_raise(rb_eArgError, ":integer_range must be a range of Fixnum.");
784
+ }
741
785
  }
742
786
  }
743
787
 
744
788
  static int
745
- match_string_cb(VALUE key, VALUE value, RxClass rc) {
789
+ match_string_cb(VALUE key, VALUE value, VALUE rx) {
790
+ RxClass rc = (RxClass)rx;
791
+
746
792
  if (T_CLASS != rb_type(value)) {
747
793
  rb_raise(rb_eArgError, "for :match_string, the hash values must be a Class.");
748
794
  }
@@ -777,7 +823,7 @@ oj_parse_opt_match_string(RxClass rc, VALUE ropts) {
777
823
  }
778
824
 
779
825
  /* Document-method: load
780
- * call-seq: load(json, options) { _|_obj, start, len_|_ }
826
+ * call-seq: load(json, options={}) { _|_obj, start, len_|_ }
781
827
  *
782
828
  * Parses a JSON document String into a Object, Hash, Array, String, Fixnum,
783
829
  * Float, true, false, or nil according to the default mode or the mode
@@ -802,11 +848,10 @@ oj_parse_opt_match_string(RxClass rc, VALUE ropts) {
802
848
  *
803
849
  * - *json* [_String_|_IO_] JSON String or an Object that responds to read()
804
850
  * - *options* [_Hash_] load options (same as default_options)
805
- * - -
806
851
  * - *obj* [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_] parsed object.
807
852
  * - *start* [_optional, _Integer_] start position of parsed JSON for obj.
808
853
  * - *len* [_optional, _Integer_] length of parsed JSON for obj.
809
- *
854
+ *
810
855
  * Returns [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_]
811
856
  */
812
857
  static VALUE
@@ -862,7 +907,7 @@ load(int argc, VALUE *argv, VALUE self) {
862
907
  }
863
908
 
864
909
  /* Document-method: load_file
865
- * call-seq: load_file(path, options) { _|_obj, start, len_|_ }
910
+ * call-seq: load_file(path, options={}) { _|_obj, start, len_|_ }
866
911
  *
867
912
  * Parses a JSON document String into a Object, Hash, Array, String, Fixnum,
868
913
  * Float, true, false, or nil according to the default mode or the mode
@@ -889,7 +934,6 @@ load(int argc, VALUE *argv, VALUE self) {
889
934
  *
890
935
  * - *path* [_String_] to a file containing a JSON document
891
936
  * - *options* [_Hash_] load options (same as default_options)
892
- * - -
893
937
  * - *obj* [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_] parsed object.
894
938
  * - *start* [_optional, _Integer_] start position of parsed JSON for obj.
895
939
  * - *len* [_optional, _Integer_] length of parsed JSON for obj.
@@ -901,7 +945,7 @@ load_file(int argc, VALUE *argv, VALUE self) {
901
945
  char *path;
902
946
  int fd;
903
947
  Mode mode = oj_default_options.mode;
904
- struct _ParseInfo pi;
948
+ struct _parseInfo pi;
905
949
 
906
950
  if (1 > argc) {
907
951
  rb_raise(rb_eArgError, "Wrong number of arguments to load().");
@@ -943,11 +987,13 @@ load_file(int argc, VALUE *argv, VALUE self) {
943
987
  }
944
988
  switch (mode) {
945
989
  case StrictMode:
990
+ case NullMode:
946
991
  oj_set_strict_callbacks(&pi);
947
992
  return oj_pi_sparse(argc, argv, &pi, fd);
948
- case NullMode:
949
- case CompatMode:
950
993
  case CustomMode:
994
+ oj_set_custom_callbacks(&pi);
995
+ return oj_pi_sparse(argc, argv, &pi, fd);
996
+ case CompatMode:
951
997
  case RailsMode:
952
998
  oj_set_compat_callbacks(&pi);
953
999
  return oj_pi_sparse(argc, argv, &pi, fd);
@@ -976,7 +1022,7 @@ load_file(int argc, VALUE *argv, VALUE self) {
976
1022
  */
977
1023
  static VALUE
978
1024
  safe_load(VALUE self, VALUE doc) {
979
- struct _ParseInfo pi;
1025
+ struct _parseInfo pi;
980
1026
  VALUE args[1];
981
1027
 
982
1028
  parse_info_init(&pi);
@@ -1019,7 +1065,7 @@ safe_load(VALUE self, VALUE doc) {
1019
1065
  */
1020
1066
 
1021
1067
  /* Document-method: dump
1022
- * call-seq: dump(obj, options)
1068
+ * call-seq: dump(obj, options={})
1023
1069
  *
1024
1070
  * Dumps an Object (obj) to a string.
1025
1071
  * - *obj* [_Object_] Object to serialize as an JSON document String
@@ -1028,8 +1074,8 @@ safe_load(VALUE self, VALUE doc) {
1028
1074
  static VALUE
1029
1075
  dump(int argc, VALUE *argv, VALUE self) {
1030
1076
  char buf[4096];
1031
- struct _Out out;
1032
- struct _Options copts = oj_default_options;
1077
+ struct _out out;
1078
+ struct _options copts = oj_default_options;
1033
1079
  VALUE rstr;
1034
1080
 
1035
1081
  if (1 > argc) {
@@ -1041,6 +1087,9 @@ dump(int argc, VALUE *argv, VALUE self) {
1041
1087
  if (2 == argc) {
1042
1088
  oj_parse_options(argv[1], &copts);
1043
1089
  }
1090
+ if (CompatMode == copts.mode && copts.escape_mode != ASCIIEsc) {
1091
+ copts.escape_mode = JSONEsc;
1092
+ }
1044
1093
  out.buf = buf;
1045
1094
  out.end = buf + sizeof(buf) - 10;
1046
1095
  out.allocated = false;
@@ -1064,7 +1113,7 @@ dump(int argc, VALUE *argv, VALUE self) {
1064
1113
  * Dumps an Object (obj) to a string. If the object has a to_json method that
1065
1114
  * will be called. The mode is set to :compat.
1066
1115
  * - *obj* [_Object_] Object to serialize as an JSON document String
1067
- * - *options* [_Hash_]
1116
+ * - *options* [_Hash_]
1068
1117
  * - *:max_nesting* [_boolean_] It true nesting is limited to 100. The option to detect circular references is available but is not compatible with the json gem., default is false
1069
1118
  * - *:allow_nan* [_boolean_] If true non JSON compliant words such as Nan and Infinity will be used as appropriate, default is true.
1070
1119
  * - *:quirks_mode* [_boolean_] Allow single JSON values instead of documents, default is true (allow).
@@ -1080,8 +1129,8 @@ dump(int argc, VALUE *argv, VALUE self) {
1080
1129
  static VALUE
1081
1130
  to_json(int argc, VALUE *argv, VALUE self) {
1082
1131
  char buf[4096];
1083
- struct _Out out;
1084
- struct _Options copts = oj_default_options;
1132
+ struct _out out;
1133
+ struct _options copts = oj_default_options;
1085
1134
  VALUE rstr;
1086
1135
 
1087
1136
  if (1 > argc) {
@@ -1114,7 +1163,7 @@ to_json(int argc, VALUE *argv, VALUE self) {
1114
1163
  }
1115
1164
 
1116
1165
  /* Document-method: to_file
1117
- * call-seq: to_file(file_path, obj, options)
1166
+ * call-seq: to_file(file_path, obj, options={})
1118
1167
  *
1119
1168
  * Dumps an Object to the specified file.
1120
1169
  * - *file* [_String_] _path file path to write the JSON document to
@@ -1125,8 +1174,8 @@ to_json(int argc, VALUE *argv, VALUE self) {
1125
1174
  */
1126
1175
  static VALUE
1127
1176
  to_file(int argc, VALUE *argv, VALUE self) {
1128
- struct _Options copts = oj_default_options;
1129
-
1177
+ struct _options copts = oj_default_options;
1178
+
1130
1179
  if (3 == argc) {
1131
1180
  oj_parse_options(argv[2], &copts);
1132
1181
  }
@@ -1137,7 +1186,7 @@ to_file(int argc, VALUE *argv, VALUE self) {
1137
1186
  }
1138
1187
 
1139
1188
  /* Document-method: to_stream
1140
- * call-seq: to_stream(io, obj, options)
1189
+ * call-seq: to_stream(io, obj, options={})
1141
1190
  *
1142
1191
  * Dumps an Object to the specified IO stream.
1143
1192
  * - *io* [_IO_] IO stream to write the JSON document to
@@ -1148,8 +1197,8 @@ to_file(int argc, VALUE *argv, VALUE self) {
1148
1197
  */
1149
1198
  static VALUE
1150
1199
  to_stream(int argc, VALUE *argv, VALUE self) {
1151
- struct _Options copts = oj_default_options;
1152
-
1200
+ struct _options copts = oj_default_options;
1201
+
1153
1202
  if (3 == argc) {
1154
1203
  oj_parse_options(argv[2], &copts);
1155
1204
  }
@@ -1265,7 +1314,6 @@ register_odd_raw(int argc, VALUE *argv, VALUE self) {
1265
1314
  *
1266
1315
  * - *json* [_String_|_IO_] JSON String or an Object that responds to read().
1267
1316
  * - *options* [_Hash_] load options (same as default_options).
1268
- * - -
1269
1317
  * - *obj* [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_] parsed object.
1270
1318
  * - *start* [_optional, _Integer_] start position of parsed JSON for obj.
1271
1319
  * - *len* [_optional, _Integer_] length of parsed JSON for obj.
@@ -1300,7 +1348,6 @@ extern VALUE oj_strict_parse(int argc, VALUE *argv, VALUE self);
1300
1348
  *
1301
1349
  * - *json* [_String_|_IO_] JSON String or an Object that responds to read().
1302
1350
  * - *options* [_Hash_] load options (same as default_options).
1303
- * - -
1304
1351
  * - *obj* [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_] parsed object.
1305
1352
  * - *start* [_optional, _Integer_] start position of parsed JSON for obj.
1306
1353
  * - *len* [_optional, _Integer_] length of parsed JSON for obj.
@@ -1322,22 +1369,6 @@ extern VALUE oj_compat_parse(int argc, VALUE *argv, VALUE self);
1322
1369
  * valid. If the input is not a valid JSON document (an empty string is not a
1323
1370
  * valid JSON document) an exception is raised.
1324
1371
  *
1325
- * Note: Oj is not able to automatically deserialize all classes that are a
1326
- * subclass of a Ruby Exception. Only exception that take one required string
1327
- * argument in the initialize() method are supported. This is an example of how
1328
- * to write an Exception subclass that supports both a single string intializer
1329
- * and an Exception as an argument. Additional optional arguments can be added
1330
- * as well.
1331
- *
1332
- * The reason for this restriction has to do with a design decision on the part
1333
- * of the Ruby developers. Exceptions are special Objects. They do not follow the
1334
- * rules of other Objects. Exceptions have 'mesg' and a 'bt' attribute. Note that
1335
- * these are not '@mesg' and '@bt'. They can not be set using the normal C or
1336
- * Ruby calls. The only way I have found to set the 'mesg' attribute is through
1337
- * the initializer. Unfortunately that means any subclass that provides a
1338
- * different initializer can not be automatically decoded. A way around this is
1339
- * to use a create function but this example shows an alternative.
1340
- *
1341
1372
  * A block can be provided with a single argument. That argument will be the
1342
1373
  * parsed JSON document. This is useful when parsing a string that includes
1343
1374
  * multiple JSON documents. The block can take up to 3 arguments, the parsed
@@ -1347,7 +1378,6 @@ extern VALUE oj_compat_parse(int argc, VALUE *argv, VALUE self);
1347
1378
  *
1348
1379
  * - *json* [_String_|_IO_] JSON String or an Object that responds to read().
1349
1380
  * - *options* [_Hash_] load options (same as default_options).
1350
- * - -
1351
1381
  * - *obj* [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_] parsed object.
1352
1382
  * - *start* [_optional, _Integer_] start position of parsed JSON for obj.
1353
1383
  * - *len* [_optional, _Integer_] length of parsed JSON for obj.
@@ -1383,7 +1413,6 @@ extern VALUE oj_object_parse(int argc, VALUE *argv, VALUE self);
1383
1413
  *
1384
1414
  * - *json* [_String_|_IO_] JSON String or an Object that responds to read().
1385
1415
  * - *options* [_Hash_] load options (same as default_options).
1386
- * - -
1387
1416
  * - *obj* [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_] parsed object.
1388
1417
  * - *start* [_optional, _Integer_] start position of parsed JSON for obj.
1389
1418
  * - *len* [_optional, _Integer_] length of parsed JSON for obj.
@@ -1445,16 +1474,16 @@ extern VALUE oj_define_mimic_json(int argc, VALUE *argv, VALUE self);
1445
1474
 
1446
1475
  /* Document-method: generate
1447
1476
  * call-seq: generate(obj, opts=nil)
1448
- *
1477
+ *
1449
1478
  * Encode obj as a JSON String. The obj argument must be a Hash, Array, or
1450
1479
  * respond to to_h or to_json. Options other than those listed such as
1451
1480
  * +:allow_nan+ or +:max_nesting+ are ignored.
1452
- *
1481
+ *
1453
1482
  * - *obj* [_Object__|_Hash_|_Array_] object to convert to a JSON String
1454
1483
  * - *opts* [_Hash_] options
1455
- * - - *:indent* [_String_] String to use for indentation.
1484
+ * - *:indent* [_String_] String to use for indentation.
1456
1485
  * - *:space* [_String_] String placed after a , or : delimiter
1457
- * - *:space * _before [_String_] String placed before a : delimiter
1486
+ * - *:space_before* [_String_] String placed before a : delimiter
1458
1487
  * - *:object_nl* [_String_] String placed after a JSON object
1459
1488
  * - *:array_nl* [_String_] String placed after a JSON array
1460
1489
  * - *:ascii_only* [_Boolean_] if not nil or false then use only ascii characters in the output. Note JSON.generate does support this even if it is not documented.
@@ -1497,15 +1526,15 @@ protect_require(VALUE x) {
1497
1526
  * modes are:
1498
1527
  *
1499
1528
  * - *:strict* mode will only allow the 7 basic JSON types to be serialized. Any other Object
1500
- * will raise an Exception.
1501
- *
1529
+ * will raise an Exception.
1530
+ *
1502
1531
  * - *:null* mode is similar to the :strict mode except any Object that is not
1503
1532
  * one of the JSON base types is replaced by a JSON null.
1504
- *
1533
+ *
1505
1534
  * - *:object* mode will dump any Object as a JSON Object with keys that match
1506
1535
  * the Ruby Object's variable names without the '@' character. This is the
1507
1536
  * highest performance mode.
1508
- *
1537
+ *
1509
1538
  * - *:compat* or *:json* mode is the compatible mode for the json gem. It mimics
1510
1539
  * the json gem including the options, defaults, and restrictions.
1511
1540
  *
@@ -1591,6 +1620,7 @@ Init_oj() {
1591
1620
  oj_new_id = rb_intern("new");
1592
1621
  oj_parse_id = rb_intern("parse");
1593
1622
  oj_pos_id = rb_intern("pos");
1623
+ oj_raw_json_id = rb_intern("raw_json");
1594
1624
  oj_read_id = rb_intern("read");
1595
1625
  oj_readpartial_id = rb_intern("readpartial");
1596
1626
  oj_replace_id = rb_intern("replace");
@@ -1617,13 +1647,21 @@ Init_oj() {
1617
1647
  rb_require("oj/schandler");
1618
1648
 
1619
1649
  oj_bag_class = rb_const_get_at(Oj, rb_intern("Bag"));
1650
+ rb_gc_register_mark_object(oj_bag_class);
1620
1651
  oj_bigdecimal_class = rb_const_get(rb_cObject, rb_intern("BigDecimal"));
1652
+ rb_gc_register_mark_object(oj_bigdecimal_class);
1621
1653
  oj_date_class = rb_const_get(rb_cObject, rb_intern("Date"));
1654
+ rb_gc_register_mark_object(oj_date_class);
1622
1655
  oj_datetime_class = rb_const_get(rb_cObject, rb_intern("DateTime"));
1656
+ rb_gc_register_mark_object(oj_datetime_class);
1623
1657
  oj_enumerable_class = rb_const_get(rb_cObject, rb_intern("Enumerable"));
1658
+ rb_gc_register_mark_object(oj_enumerable_class);
1624
1659
  oj_parse_error_class = rb_const_get_at(Oj, rb_intern("ParseError"));
1660
+ rb_gc_register_mark_object(oj_parse_error_class);
1625
1661
  oj_stringio_class = rb_const_get(rb_cObject, rb_intern("StringIO"));
1662
+ rb_gc_register_mark_object(oj_stringio_class);
1626
1663
  oj_struct_class = rb_const_get(rb_cObject, rb_intern("Struct"));
1664
+ rb_gc_register_mark_object(oj_struct_class);
1627
1665
  oj_json_parser_error_class = rb_eEncodingError; // replaced if mimic is called
1628
1666
  oj_json_generator_error_class = rb_eEncodingError; // replaced if mimic is called
1629
1667
 
@@ -1638,16 +1676,19 @@ Init_oj() {
1638
1676
  bigdecimal_sym = ID2SYM(rb_intern("bigdecimal")); rb_gc_register_address(&bigdecimal_sym);
1639
1677
  circular_sym = ID2SYM(rb_intern("circular")); rb_gc_register_address(&circular_sym);
1640
1678
  class_cache_sym = ID2SYM(rb_intern("class_cache")); rb_gc_register_address(&class_cache_sym);
1679
+ compat_bigdecimal_sym = ID2SYM(rb_intern("compat_bigdecimal"));rb_gc_register_address(&compat_bigdecimal_sym);
1641
1680
  compat_sym = ID2SYM(rb_intern("compat")); rb_gc_register_address(&compat_sym);
1642
1681
  create_id_sym = ID2SYM(rb_intern("create_id")); rb_gc_register_address(&create_id_sym);
1643
1682
  custom_sym = ID2SYM(rb_intern("custom")); rb_gc_register_address(&custom_sym);
1644
1683
  empty_string_sym = ID2SYM(rb_intern("empty_string")); rb_gc_register_address(&empty_string_sym);
1645
1684
  escape_mode_sym = ID2SYM(rb_intern("escape_mode")); rb_gc_register_address(&escape_mode_sym);
1646
1685
  integer_range_sym = ID2SYM(rb_intern("integer_range")); rb_gc_register_address(&integer_range_sym);
1686
+ fast_sym = ID2SYM(rb_intern("fast")); rb_gc_register_address(&fast_sym);
1647
1687
  float_prec_sym = ID2SYM(rb_intern("float_precision")); rb_gc_register_address(&float_prec_sym);
1648
1688
  float_sym = ID2SYM(rb_intern("float")); rb_gc_register_address(&float_sym);
1649
1689
  huge_sym = ID2SYM(rb_intern("huge")); rb_gc_register_address(&huge_sym);
1650
1690
  ignore_sym = ID2SYM(rb_intern("ignore")); rb_gc_register_address(&ignore_sym);
1691
+ ignore_under_sym = ID2SYM(rb_intern("ignore_under")); rb_gc_register_address(&ignore_under_sym);
1651
1692
  json_sym = ID2SYM(rb_intern("json")); rb_gc_register_address(&json_sym);
1652
1693
  match_string_sym = ID2SYM(rb_intern("match_string")); rb_gc_register_address(&match_string_sym);
1653
1694
  mode_sym = ID2SYM(rb_intern("mode")); rb_gc_register_address(&mode_sym);
@@ -1661,12 +1702,14 @@ Init_oj() {
1661
1702
  oj_array_nl_sym = ID2SYM(rb_intern("array_nl")); rb_gc_register_address(&oj_array_nl_sym);
1662
1703
  oj_ascii_only_sym = ID2SYM(rb_intern("ascii_only")); rb_gc_register_address(&oj_ascii_only_sym);
1663
1704
  oj_create_additions_sym = ID2SYM(rb_intern("create_additions"));rb_gc_register_address(&oj_create_additions_sym);
1705
+ oj_decimal_class_sym = ID2SYM(rb_intern("decimal_class")); rb_gc_register_address(&oj_decimal_class_sym);
1664
1706
  oj_hash_class_sym = ID2SYM(rb_intern("hash_class")); rb_gc_register_address(&oj_hash_class_sym);
1665
1707
  oj_indent_sym = ID2SYM(rb_intern("indent")); rb_gc_register_address(&oj_indent_sym);
1666
1708
  oj_max_nesting_sym = ID2SYM(rb_intern("max_nesting")); rb_gc_register_address(&oj_max_nesting_sym);
1667
1709
  oj_object_class_sym = ID2SYM(rb_intern("object_class")); rb_gc_register_address(&oj_object_class_sym);
1668
1710
  oj_object_nl_sym = ID2SYM(rb_intern("object_nl")); rb_gc_register_address(&oj_object_nl_sym);
1669
1711
  oj_quirks_mode_sym = ID2SYM(rb_intern("quirks_mode")); rb_gc_register_address(&oj_quirks_mode_sym);
1712
+ oj_safe_sym = ID2SYM(rb_intern("safe")); rb_gc_register_address(&oj_safe_sym);
1670
1713
  oj_space_before_sym = ID2SYM(rb_intern("space_before")); rb_gc_register_address(&oj_space_before_sym);
1671
1714
  oj_space_sym = ID2SYM(rb_intern("space")); rb_gc_register_address(&oj_space_sym);
1672
1715
  oj_trace_sym = ID2SYM(rb_intern("trace")); rb_gc_register_address(&oj_trace_sym);
@@ -1682,6 +1725,7 @@ Init_oj() {
1682
1725
  unix_sym = ID2SYM(rb_intern("unix")); rb_gc_register_address(&unix_sym);
1683
1726
  unix_zone_sym = ID2SYM(rb_intern("unix_zone")); rb_gc_register_address(&unix_zone_sym);
1684
1727
  use_as_json_sym = ID2SYM(rb_intern("use_as_json")); rb_gc_register_address(&use_as_json_sym);
1728
+ use_raw_json_sym = ID2SYM(rb_intern("use_raw_json")); rb_gc_register_address(&use_raw_json_sym);
1685
1729
  use_to_hash_sym = ID2SYM(rb_intern("use_to_hash")); rb_gc_register_address(&use_to_hash_sym);
1686
1730
  use_to_json_sym = ID2SYM(rb_intern("use_to_json")); rb_gc_register_address(&use_to_json_sym);
1687
1731
  wab_sym = ID2SYM(rb_intern("wab")); rb_gc_register_address(&wab_sym);
@@ -1698,8 +1742,10 @@ Init_oj() {
1698
1742
  oj_odd_init();
1699
1743
  oj_mimic_rails_init();
1700
1744
 
1701
- #if HAVE_LIBPTHREAD
1702
- pthread_mutex_init(&oj_cache_mutex, 0);
1745
+ #ifdef HAVE_PTHREAD_MUTEX_INIT
1746
+ if (0 != (err = pthread_mutex_init(&oj_cache_mutex, 0))) {
1747
+ rb_raise(rb_eException, "failed to initialize a mutex. %s", strerror(err));
1748
+ }
1703
1749
  #else
1704
1750
  oj_cache_mutex = rb_mutex_new();
1705
1751
  rb_gc_register_address(&oj_cache_mutex);