oj 2.18.5 → 3.0.0
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.
- checksums.yaml +4 -4
- data/README.md +33 -226
- data/ext/oj/circarray.c +0 -25
- data/ext/oj/circarray.h +0 -25
- data/ext/oj/code.c +227 -0
- data/ext/oj/code.h +40 -0
- data/ext/oj/compat.c +126 -38
- data/ext/oj/custom.c +1097 -0
- data/ext/oj/dump.c +658 -2376
- data/ext/oj/dump.h +92 -0
- data/ext/oj/dump_compat.c +937 -0
- data/ext/oj/dump_leaf.c +254 -0
- data/ext/oj/dump_object.c +810 -0
- data/ext/oj/dump_rails.c +329 -0
- data/ext/oj/dump_strict.c +416 -0
- data/ext/oj/err.c +0 -25
- data/ext/oj/err.h +8 -2
- data/ext/oj/fast.c +24 -24
- data/ext/oj/mimic_json.c +817 -0
- data/ext/oj/mimic_rails.c +806 -0
- data/ext/oj/mimic_rails.h +17 -0
- data/ext/oj/object.c +18 -72
- data/ext/oj/odd.c +0 -25
- data/ext/oj/odd.h +2 -27
- data/ext/oj/oj.c +655 -1503
- data/ext/oj/oj.h +93 -40
- data/ext/oj/parse.c +99 -46
- data/ext/oj/parse.h +12 -26
- data/ext/oj/reader.c +1 -25
- data/ext/oj/reader.h +3 -25
- data/ext/oj/resolve.c +9 -11
- data/ext/oj/resolve.h +2 -2
- data/ext/oj/rxclass.c +133 -0
- data/ext/oj/rxclass.h +27 -0
- data/ext/oj/saj.c +4 -25
- data/ext/oj/scp.c +3 -25
- data/ext/oj/sparse.c +89 -13
- data/ext/oj/stream_writer.c +301 -0
- data/ext/oj/strict.c +4 -27
- data/ext/oj/string_writer.c +480 -0
- data/ext/oj/val_stack.h +6 -2
- data/lib/oj.rb +1 -23
- data/lib/oj/easy_hash.rb +12 -4
- data/lib/oj/json.rb +172 -0
- data/lib/oj/mimic.rb +123 -18
- data/lib/oj/state.rb +131 -0
- data/lib/oj/version.rb +1 -1
- data/pages/Advanced.md +22 -0
- data/pages/Compatibility.md +25 -0
- data/pages/Custom.md +23 -0
- data/pages/Encoding.md +65 -0
- data/pages/JsonGem.md +79 -0
- data/pages/Modes.md +140 -0
- data/pages/Options.md +250 -0
- data/pages/Rails.md +60 -0
- data/pages/Security.md +20 -0
- data/test/activesupport4/decoding_test.rb +105 -0
- data/test/activesupport4/encoding_test.rb +531 -0
- data/test/activesupport4/test_helper.rb +41 -0
- data/test/activesupport5/decoding_test.rb +125 -0
- data/test/activesupport5/encoding_test.rb +483 -0
- data/test/activesupport5/encoding_test_cases.rb +90 -0
- data/test/activesupport5/test_helper.rb +50 -0
- data/test/activesupport5/time_zone_test_helpers.rb +24 -0
- data/test/json_gem/json_addition_test.rb +216 -0
- data/test/json_gem/json_common_interface_test.rb +143 -0
- data/test/json_gem/json_encoding_test.rb +109 -0
- data/test/json_gem/json_ext_parser_test.rb +20 -0
- data/test/json_gem/json_fixtures_test.rb +35 -0
- data/test/json_gem/json_generator_test.rb +383 -0
- data/test/json_gem/json_generic_object_test.rb +90 -0
- data/test/json_gem/json_parser_test.rb +470 -0
- data/test/json_gem/json_string_matching_test.rb +42 -0
- data/test/json_gem/test_helper.rb +18 -0
- data/test/perf_compat.rb +30 -28
- data/test/perf_object.rb +1 -1
- data/test/perf_strict.rb +18 -1
- data/test/sample.rb +0 -1
- data/test/test_compat.rb +169 -93
- data/test/test_custom.rb +355 -0
- data/test/test_file.rb +0 -8
- data/test/test_null.rb +376 -0
- data/test/test_object.rb +268 -3
- data/test/test_scp.rb +22 -1
- data/test/test_strict.rb +160 -4
- data/test/test_various.rb +52 -620
- data/test/tests.rb +14 -0
- data/test/tests_mimic.rb +14 -0
- data/test/tests_mimic_addition.rb +7 -0
- metadata +89 -47
- data/test/activesupport_datetime_test.rb +0 -23
- data/test/bug.rb +0 -51
- data/test/bug2.rb +0 -10
- data/test/bug3.rb +0 -46
- data/test/bug_fast.rb +0 -32
- data/test/bug_load.rb +0 -24
- data/test/crash.rb +0 -111
- data/test/curl/curl_oj.rb +0 -46
- data/test/curl/get_oj.rb +0 -24
- data/test/curl/just_curl.rb +0 -31
- data/test/curl/just_oj.rb +0 -51
- data/test/example.rb +0 -11
- data/test/foo.rb +0 -24
- data/test/io.rb +0 -48
- data/test/isolated/test_mimic_rails_datetime.rb +0 -27
- data/test/mod.rb +0 -16
- data/test/rails.rb +0 -50
- data/test/russian.rb +0 -18
- data/test/struct.rb +0 -29
- data/test/test_serializer.rb +0 -59
- data/test/write_timebars.rb +0 -31
@@ -0,0 +1,17 @@
|
|
1
|
+
/* mimic_rails.h
|
2
|
+
* Copyright (c) 2017, Peter Ohler
|
3
|
+
* All rights reserved.
|
4
|
+
*/
|
5
|
+
|
6
|
+
#ifndef __OJ_MIMIC_RAILS_H__
|
7
|
+
#define __OJ_MIMIC_RAILS_H__
|
8
|
+
|
9
|
+
#include "dump.h"
|
10
|
+
|
11
|
+
extern void oj_mimic_rails_init();
|
12
|
+
extern ROpt oj_rails_get_opt(ROptTable rot, VALUE clas);
|
13
|
+
|
14
|
+
extern bool oj_rails_hash_opt;
|
15
|
+
extern bool oj_rails_array_opt;
|
16
|
+
|
17
|
+
#endif /* __OJ_MIMIC_RAILS_H__ */
|
data/ext/oj/object.c
CHANGED
@@ -1,31 +1,6 @@
|
|
1
1
|
/* object.c
|
2
2
|
* Copyright (c) 2012, Peter Ohler
|
3
3
|
* All rights reserved.
|
4
|
-
*
|
5
|
-
* Redistribution and use in source and binary forms, with or without
|
6
|
-
* modification, are permitted provided that the following conditions are met:
|
7
|
-
*
|
8
|
-
* - Redistributions of source code must retain the above copyright notice, this
|
9
|
-
* list of conditions and the following disclaimer.
|
10
|
-
*
|
11
|
-
* - Redistributions in binary form must reproduce the above copyright notice,
|
12
|
-
* this list of conditions and the following disclaimer in the documentation
|
13
|
-
* and/or other materials provided with the distribution.
|
14
|
-
*
|
15
|
-
* - Neither the name of Peter Ohler nor the names of its contributors may be
|
16
|
-
* used to endorse or promote products derived from this software without
|
17
|
-
* specific prior written permission.
|
18
|
-
*
|
19
|
-
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
-
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
-
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
22
|
-
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
23
|
-
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
24
|
-
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
25
|
-
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
26
|
-
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
27
|
-
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
28
|
-
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
4
|
*/
|
30
5
|
|
31
6
|
#include <stdio.h>
|
@@ -96,7 +71,7 @@ str_to_value(ParseInfo pi, const char *str, size_t len, const char *orig) {
|
|
96
71
|
|
97
72
|
#if (RUBY_VERSION_MAJOR == 1 && RUBY_VERSION_MINOR == 8)
|
98
73
|
static VALUE
|
99
|
-
|
74
|
+
oj_parse_xml_time(const char *str, int len) {
|
100
75
|
return rb_funcall(rb_cTime, oj_parse_id, 1, rb_str_new(str, len));
|
101
76
|
}
|
102
77
|
#else
|
@@ -117,8 +92,8 @@ parse_num(const char *str, const char *end, int cnt) {
|
|
117
92
|
return n;
|
118
93
|
}
|
119
94
|
|
120
|
-
|
121
|
-
|
95
|
+
VALUE
|
96
|
+
oj_parse_xml_time(const char *str, int len) {
|
122
97
|
VALUE args[8];
|
123
98
|
const char *end = str + len;
|
124
99
|
int n;
|
@@ -242,8 +217,8 @@ hat_cstr(ParseInfo pi, Val parent, Val kval, const char *str, size_t len) {
|
|
242
217
|
if (2 == klen) {
|
243
218
|
switch (key[1]) {
|
244
219
|
case 'o': // object
|
245
|
-
{ // name2class sets
|
246
|
-
VALUE clas = oj_name2class(pi, str, len, Yes == pi->options.auto_define);
|
220
|
+
{ // name2class sets an error if the class is not found or created
|
221
|
+
VALUE clas = oj_name2class(pi, str, len, Yes == pi->options.auto_define, rb_eArgError);
|
247
222
|
|
248
223
|
if (Qundef != clas) {
|
249
224
|
parent->val = rb_obj_alloc(clas);
|
@@ -272,7 +247,7 @@ hat_cstr(ParseInfo pi, Val parent, Val kval, const char *str, size_t len) {
|
|
272
247
|
break;
|
273
248
|
case 'c': // class
|
274
249
|
{
|
275
|
-
VALUE clas = oj_name2class(pi, str, len, Yes == pi->options.auto_define);
|
250
|
+
VALUE clas = oj_name2class(pi, str, len, Yes == pi->options.auto_define, rb_eArgError);
|
276
251
|
|
277
252
|
if (Qundef == clas) {
|
278
253
|
return 0;
|
@@ -282,7 +257,7 @@ hat_cstr(ParseInfo pi, Val parent, Val kval, const char *str, size_t len) {
|
|
282
257
|
}
|
283
258
|
break;
|
284
259
|
case 't': // time
|
285
|
-
parent->val =
|
260
|
+
parent->val = oj_parse_xml_time(str, len);
|
286
261
|
break;
|
287
262
|
default:
|
288
263
|
return 0;
|
@@ -309,11 +284,7 @@ hat_num(ParseInfo pi, Val parent, Val kval, NumInfo ni) {
|
|
309
284
|
}
|
310
285
|
}
|
311
286
|
if (86400 == ni->exp) { // UTC time
|
312
|
-
#if HAS_NANO_TIME
|
313
287
|
parent->val = rb_time_nano_new(ni->i, (long)nsec);
|
314
|
-
#else
|
315
|
-
parent->val = rb_time_new(ni->i, (long)(nsec / 1000));
|
316
|
-
#endif
|
317
288
|
// Since the ruby C routines alway create local time, the
|
318
289
|
// offset and then a convertion to UTC keeps makes the time
|
319
290
|
// match the expected value.
|
@@ -321,24 +292,6 @@ hat_num(ParseInfo pi, Val parent, Val kval, NumInfo ni) {
|
|
321
292
|
} else if (ni->hasExp) {
|
322
293
|
time_t t = (time_t)(ni->i + ni->exp);
|
323
294
|
struct tm *st = gmtime(&t);
|
324
|
-
#if RUBY_VERSION_MAJOR == 1 && RUBY_VERSION_MINOR == 8
|
325
|
-
// The only methods that allow the UTC offset to be set in
|
326
|
-
// 1.8.7 is the parse() and xmlschema() methods. The
|
327
|
-
// xmlschema() method always returns a Time instance that is
|
328
|
-
// UTC time. (true on some platforms anyway) Time.parse()
|
329
|
-
// fails on other Ruby versions until 2.2.0.
|
330
|
-
char buf[64];
|
331
|
-
int z = (0 > ni->exp ? -ni->exp : ni->exp) / 60;
|
332
|
-
int tzhour = z / 60;
|
333
|
-
int tzmin = z - tzhour * 60;
|
334
|
-
int cnt;
|
335
|
-
|
336
|
-
cnt = sprintf(buf, "%04d-%02d-%02dT%02d:%02d:%02d.%09ld%c%02d:%02d",
|
337
|
-
1900 + st->tm_year, 1 + st->tm_mon, st->tm_mday,
|
338
|
-
st->tm_hour, st->tm_min, st->tm_sec, (long)nsec,
|
339
|
-
(0 > ni->exp ? '-' : '+'), tzhour, tzmin);
|
340
|
-
parent->val = rb_funcall(rb_cTime, oj_parse_id, 1, rb_str_new(buf, cnt));
|
341
|
-
#else
|
342
295
|
VALUE args[8];
|
343
296
|
|
344
297
|
args[0] = LONG2NUM(1900 + st->tm_year);
|
@@ -346,20 +299,11 @@ hat_num(ParseInfo pi, Val parent, Val kval, NumInfo ni) {
|
|
346
299
|
args[2] = LONG2NUM(st->tm_mday);
|
347
300
|
args[3] = LONG2NUM(st->tm_hour);
|
348
301
|
args[4] = LONG2NUM(st->tm_min);
|
349
|
-
#if NO_TIME_ROUND_PAD
|
350
|
-
args[5] = rb_float_new((double)st->tm_sec + ((double)nsec) / 1000000000.0);
|
351
|
-
#else
|
352
302
|
args[5] = rb_float_new((double)st->tm_sec + ((double)nsec + 0.5) / 1000000000.0);
|
353
|
-
#endif
|
354
303
|
args[6] = LONG2NUM(ni->exp);
|
355
304
|
parent->val = rb_funcall2(rb_cTime, oj_new_id, 7, args);
|
356
|
-
#endif
|
357
305
|
} else {
|
358
|
-
#if HAS_NANO_TIME
|
359
306
|
parent->val = rb_time_nano_new(ni->i, (long)nsec);
|
360
|
-
#else
|
361
|
-
parent->val = rb_time_new(ni->i, (long)(nsec / 1000));
|
362
|
-
#endif
|
363
307
|
}
|
364
308
|
}
|
365
309
|
break;
|
@@ -410,7 +354,7 @@ hat_value(ParseInfo pi, Val parent, const char *key, size_t klen, volatile VALUE
|
|
410
354
|
sc = rb_funcall2(rb_cStruct, oj_new_id, cnt, args);
|
411
355
|
} else {
|
412
356
|
// If struct is not defined then we let this fail and raise an exception.
|
413
|
-
sc = oj_name2struct(pi, *RARRAY_PTR(value));
|
357
|
+
sc = oj_name2struct(pi, *RARRAY_PTR(value), rb_eArgError);
|
414
358
|
}
|
415
359
|
// Create a properly initialized struct instance without calling the initialize method.
|
416
360
|
parent->val = rb_obj_alloc(sc);
|
@@ -469,8 +413,8 @@ copy_ivars(VALUE target, VALUE src) {
|
|
469
413
|
}
|
470
414
|
}
|
471
415
|
|
472
|
-
|
473
|
-
|
416
|
+
void
|
417
|
+
oj_set_obj_ivar(Val parent, Val kval, VALUE value) {
|
474
418
|
const char *key = kval->key;
|
475
419
|
int klen = kval->klen;
|
476
420
|
ID var_id;
|
@@ -552,11 +496,11 @@ hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, const char *o
|
|
552
496
|
if (4 == klen && 's' == *key && 'e' == key[1] && 'l' == key[2] && 'f' == key[3]) {
|
553
497
|
rb_funcall(parent->val, oj_replace_id, 1, str_to_value(pi, str, len, orig));
|
554
498
|
} else {
|
555
|
-
|
499
|
+
oj_set_obj_ivar(parent, kval, str_to_value(pi, str, len, orig));
|
556
500
|
}
|
557
501
|
break;
|
558
502
|
case T_OBJECT:
|
559
|
-
|
503
|
+
oj_set_obj_ivar(parent, kval, str_to_value(pi, str, len, orig));
|
560
504
|
break;
|
561
505
|
case T_CLASS:
|
562
506
|
if (0 == parent->odd_args) {
|
@@ -602,7 +546,7 @@ hash_set_num(ParseInfo pi, Val kval, NumInfo ni) {
|
|
602
546
|
!ni->infinity && !ni->neg && 1 == ni->div && 0 == ni->exp && 0 != pi->circ_array) { // fixnum
|
603
547
|
oj_circ_array_set(pi->circ_array, parent->val, ni->i);
|
604
548
|
} else {
|
605
|
-
|
549
|
+
oj_set_obj_ivar(parent, kval, oj_num_as_value(ni));
|
606
550
|
}
|
607
551
|
break;
|
608
552
|
case T_CLASS:
|
@@ -646,7 +590,7 @@ hash_set_value(ParseInfo pi, Val kval, VALUE value) {
|
|
646
590
|
if (4 == klen && 's' == *key && 'e' == key[1] && 'l' == key[2] && 'f' == key[3]) {
|
647
591
|
rb_funcall(parent->val, oj_replace_id, 1, value);
|
648
592
|
} else {
|
649
|
-
|
593
|
+
oj_set_obj_ivar(parent, kval, value);
|
650
594
|
}
|
651
595
|
} else {
|
652
596
|
if (3 <= klen && '^' == *key && '#' == key[1] && T_ARRAY == rb_type(value)) {
|
@@ -667,12 +611,12 @@ hash_set_value(ParseInfo pi, Val kval, VALUE value) {
|
|
667
611
|
if (4 == klen && 's' == *key && 'e' == key[1] && 'l' == key[2] && 'f' == key[3]) {
|
668
612
|
rb_funcall(parent->val, oj_replace_id, 1, value);
|
669
613
|
} else {
|
670
|
-
|
614
|
+
oj_set_obj_ivar(parent, kval, value);
|
671
615
|
}
|
672
616
|
break;
|
673
617
|
case T_STRING: // for subclassed strings
|
674
618
|
case T_OBJECT:
|
675
|
-
|
619
|
+
oj_set_obj_ivar(parent, kval, value);
|
676
620
|
break;
|
677
621
|
case T_MODULE:
|
678
622
|
case T_CLASS:
|
@@ -772,6 +716,7 @@ VALUE
|
|
772
716
|
oj_object_parse(int argc, VALUE *argv, VALUE self) {
|
773
717
|
struct _ParseInfo pi;
|
774
718
|
|
719
|
+
parse_info_init(&pi);
|
775
720
|
pi.options = oj_default_options;
|
776
721
|
pi.handler = Qnil;
|
777
722
|
pi.err_class = Qnil;
|
@@ -788,6 +733,7 @@ VALUE
|
|
788
733
|
oj_object_parse_cstr(int argc, VALUE *argv, char *json, size_t len) {
|
789
734
|
struct _ParseInfo pi;
|
790
735
|
|
736
|
+
parse_info_init(&pi);
|
791
737
|
pi.options = oj_default_options;
|
792
738
|
pi.handler = Qnil;
|
793
739
|
pi.err_class = Qnil;
|
data/ext/oj/odd.c
CHANGED
@@ -1,31 +1,6 @@
|
|
1
1
|
/* odd.c
|
2
2
|
* Copyright (c) 2011, Peter Ohler
|
3
3
|
* All rights reserved.
|
4
|
-
*
|
5
|
-
* Redistribution and use in source and binary forms, with or without
|
6
|
-
* modification, are permitted provided that the following conditions are met:
|
7
|
-
*
|
8
|
-
* - Redistributions of source code must retain the above copyright notice, this
|
9
|
-
* list of conditions and the following disclaimer.
|
10
|
-
*
|
11
|
-
* - Redistributions in binary form must reproduce the above copyright notice,
|
12
|
-
* this list of conditions and the following disclaimer in the documentation
|
13
|
-
* and/or other materials provided with the distribution.
|
14
|
-
*
|
15
|
-
* - Neither the name of Peter Ohler nor the names of its contributors may be
|
16
|
-
* used to endorse or promote products derived from this software without
|
17
|
-
* specific prior written permission.
|
18
|
-
*
|
19
|
-
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
-
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
-
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
22
|
-
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
23
|
-
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
24
|
-
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
25
|
-
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
26
|
-
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
27
|
-
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
28
|
-
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
4
|
*/
|
30
5
|
|
31
6
|
#include <string.h>
|
data/ext/oj/odd.h
CHANGED
@@ -1,31 +1,6 @@
|
|
1
1
|
/* odd.h
|
2
2
|
* Copyright (c) 2011, Peter Ohler
|
3
3
|
* All rights reserved.
|
4
|
-
*
|
5
|
-
* Redistribution and use in source and binary forms, with or without
|
6
|
-
* modification, are permitted provided that the following conditions are met:
|
7
|
-
*
|
8
|
-
* - Redistributions of source code must retain the above copyright notice, this
|
9
|
-
* list of conditions and the following disclaimer.
|
10
|
-
*
|
11
|
-
* - Redistributions in binary form must reproduce the above copyright notice,
|
12
|
-
* this list of conditions and the following disclaimer in the documentation
|
13
|
-
* and/or other materials provided with the distribution.
|
14
|
-
*
|
15
|
-
* - Neither the name of Peter Ohler nor the names of its contributors may be
|
16
|
-
* used to endorse or promote products derived from this software without
|
17
|
-
* specific prior written permission.
|
18
|
-
*
|
19
|
-
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
-
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
-
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
22
|
-
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
23
|
-
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
24
|
-
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
25
|
-
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
26
|
-
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
27
|
-
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
28
|
-
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
4
|
*/
|
30
5
|
|
31
6
|
#ifndef __OJ_ODD_H__
|
@@ -48,8 +23,8 @@ typedef struct _Odd {
|
|
48
23
|
int attr_cnt;
|
49
24
|
bool is_module;
|
50
25
|
bool raw;
|
51
|
-
const char *attr_names[MAX_ODD_ARGS];
|
52
|
-
ID attrs[MAX_ODD_ARGS];
|
26
|
+
const char *attr_names[MAX_ODD_ARGS]; // NULL terminated attr names
|
27
|
+
ID attrs[MAX_ODD_ARGS]; // 0 terminated attr IDs
|
53
28
|
AttrGetFunc attrFuncs[MAX_ODD_ARGS];
|
54
29
|
} *Odd;
|
55
30
|
|
data/ext/oj/oj.c
CHANGED
@@ -1,32 +1,6 @@
|
|
1
1
|
/* oj.c
|
2
2
|
* Copyright (c) 2012, Peter Ohler
|
3
|
-
*
|
4
3
|
* 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
4
|
*/
|
31
5
|
|
32
6
|
#include <stdlib.h>
|
@@ -41,8 +15,14 @@
|
|
41
15
|
#include "parse.h"
|
42
16
|
#include "hash.h"
|
43
17
|
#include "odd.h"
|
18
|
+
#include "dump.h"
|
19
|
+
#include "mimic_rails.h"
|
44
20
|
#include "encode.h"
|
45
21
|
|
22
|
+
#if !HAS_ENCODING_SUPPORT || defined(RUBINIUS_RUBY)
|
23
|
+
#define rb_eEncodingError rb_eException
|
24
|
+
#endif
|
25
|
+
|
46
26
|
typedef struct _YesNoOpt {
|
47
27
|
VALUE sym;
|
48
28
|
char *attr;
|
@@ -57,10 +37,14 @@ ID oj_array_append_id;
|
|
57
37
|
ID oj_array_end_id;
|
58
38
|
ID oj_array_start_id;
|
59
39
|
ID oj_as_json_id;
|
40
|
+
ID oj_begin_id;
|
41
|
+
ID oj_end_id;
|
42
|
+
ID oj_exclude_end_id;
|
60
43
|
ID oj_error_id;
|
61
44
|
ID oj_file_id;
|
62
45
|
ID oj_fileno_id;
|
63
46
|
ID oj_ftype_id;
|
47
|
+
ID oj_has_key_id;
|
64
48
|
ID oj_hash_end_id;
|
65
49
|
ID oj_hash_key_id;
|
66
50
|
ID oj_hash_set_id;
|
@@ -77,6 +61,7 @@ ID oj_readpartial_id;
|
|
77
61
|
ID oj_replace_id;
|
78
62
|
ID oj_stat_id;
|
79
63
|
ID oj_string_id;
|
64
|
+
ID oj_to_h_id;
|
80
65
|
ID oj_to_hash_id;
|
81
66
|
ID oj_to_json_id;
|
82
67
|
ID oj_to_s_id;
|
@@ -90,13 +75,13 @@ ID oj_utc_offset_id;
|
|
90
75
|
ID oj_utcq_id;
|
91
76
|
ID oj_write_id;
|
92
77
|
|
93
|
-
static ID has_key_id;
|
94
78
|
|
95
79
|
VALUE oj_bag_class;
|
96
80
|
VALUE oj_bigdecimal_class;
|
97
81
|
VALUE oj_cstack_class;
|
98
82
|
VALUE oj_date_class;
|
99
83
|
VALUE oj_datetime_class;
|
84
|
+
VALUE oj_enumerable_class;
|
100
85
|
VALUE oj_parse_error_class;
|
101
86
|
VALUE oj_stream_writer_class;
|
102
87
|
VALUE oj_string_writer_class;
|
@@ -105,9 +90,17 @@ VALUE oj_struct_class;
|
|
105
90
|
|
106
91
|
VALUE oj_slash_string;
|
107
92
|
|
93
|
+
VALUE oj_allow_nan_sym;
|
94
|
+
VALUE oj_array_class_sym;
|
95
|
+
VALUE oj_create_additions_sym;
|
96
|
+
VALUE oj_hash_class_sym;
|
97
|
+
VALUE oj_indent_sym;
|
98
|
+
VALUE oj_object_class_sym;
|
99
|
+
VALUE oj_quirks_mode_sym;
|
100
|
+
|
101
|
+
static VALUE allow_blank_sym;
|
108
102
|
static VALUE allow_gc_sym;
|
109
103
|
static VALUE allow_invalid_unicode_sym;
|
110
|
-
static VALUE ascii_only_sym;
|
111
104
|
static VALUE ascii_sym;
|
112
105
|
static VALUE auto_define_sym;
|
113
106
|
static VALUE auto_sym;
|
@@ -118,46 +111,38 @@ static VALUE circular_sym;
|
|
118
111
|
static VALUE class_cache_sym;
|
119
112
|
static VALUE compat_sym;
|
120
113
|
static VALUE create_id_sym;
|
114
|
+
static VALUE custom_sym;
|
115
|
+
static VALUE empty_string_sym;
|
121
116
|
static VALUE escape_mode_sym;
|
122
117
|
static VALUE float_prec_sym;
|
123
118
|
static VALUE float_sym;
|
124
|
-
static VALUE hash_class_sym;
|
125
119
|
static VALUE huge_sym;
|
126
|
-
static VALUE indent_sym;
|
127
|
-
static VALUE json_parser_error_class;
|
128
120
|
static VALUE json_sym;
|
121
|
+
static VALUE match_string_sym;
|
129
122
|
static VALUE mode_sym;
|
130
123
|
static VALUE nan_sym;
|
131
124
|
static VALUE newline_sym;
|
132
125
|
static VALUE nilnil_sym;
|
133
|
-
static VALUE empty_string_sym;
|
134
126
|
static VALUE null_sym;
|
135
127
|
static VALUE object_sym;
|
136
128
|
static VALUE omit_nil_sym;
|
137
|
-
static VALUE
|
129
|
+
static VALUE rails_sym;
|
138
130
|
static VALUE raise_sym;
|
139
131
|
static VALUE ruby_sym;
|
140
132
|
static VALUE sec_prec_sym;
|
141
133
|
static VALUE strict_sym;
|
142
134
|
static VALUE symbol_keys_sym;
|
143
135
|
static VALUE time_format_sym;
|
136
|
+
static VALUE unicode_xss_sym;
|
144
137
|
static VALUE unix_sym;
|
145
138
|
static VALUE unix_zone_sym;
|
146
139
|
static VALUE use_as_json_sym;
|
140
|
+
static VALUE use_to_hash_sym;
|
147
141
|
static VALUE use_to_json_sym;
|
148
142
|
static VALUE word_sym;
|
149
143
|
static VALUE xmlschema_sym;
|
150
144
|
static VALUE xss_safe_sym;
|
151
145
|
|
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
146
|
#if HAS_ENCODING_SUPPORT
|
162
147
|
rb_encoding *oj_utf8_encoding = 0;
|
163
148
|
#else
|
@@ -169,6 +154,7 @@ pthread_mutex_t oj_cache_mutex;
|
|
169
154
|
#elif USE_RB_MUTEX
|
170
155
|
VALUE oj_cache_mutex = Qnil;
|
171
156
|
#endif
|
157
|
+
|
172
158
|
static const char json_class[] = "json_class";
|
173
159
|
|
174
160
|
struct _Options oj_default_options = {
|
@@ -179,22 +165,26 @@ struct _Options oj_default_options = {
|
|
179
165
|
JSONEsc, // escape_mode
|
180
166
|
ObjectMode, // mode
|
181
167
|
Yes, // class_cache
|
182
|
-
|
168
|
+
UnixTime, // time_format
|
183
169
|
Yes, // bigdec_as_num
|
184
170
|
AutoDec, // bigdec_load
|
171
|
+
No, // to_hash
|
185
172
|
No, // to_json
|
186
173
|
No, // as_json
|
187
174
|
No, // nilnil
|
188
175
|
Yes, // empty_string
|
189
176
|
Yes, // allow_gc
|
190
177
|
Yes, // quirks_mode
|
191
|
-
No, // allow_invalid
|
178
|
+
No, // allow_invalid
|
179
|
+
No, // create_ok
|
180
|
+
Yes, // allow_nan
|
192
181
|
json_class, // create_id
|
193
182
|
10, // create_id_len
|
194
183
|
9, // sec_prec
|
195
|
-
|
184
|
+
16, // float_prec
|
196
185
|
"%0.15g", // float_fmt
|
197
186
|
Qnil, // hash_class
|
187
|
+
Qnil, // array_class
|
198
188
|
{ // dump_opts
|
199
189
|
false, //use
|
200
190
|
"", // indent
|
@@ -209,52 +199,60 @@ struct _Options oj_default_options = {
|
|
209
199
|
0, // array_size
|
210
200
|
AutoNan,// nan_dump
|
211
201
|
false, // omit_nil
|
202
|
+
MAX_DEPTH, // max_depth
|
203
|
+
},
|
204
|
+
{ // str_rx
|
205
|
+
NULL, // head
|
206
|
+
NULL, // tail
|
207
|
+
{ '\0' }, // err
|
212
208
|
}
|
213
209
|
};
|
214
210
|
|
215
|
-
|
216
|
-
|
217
|
-
/* call-seq: default_options() => Hash
|
211
|
+
/* Document-method: default_options()
|
212
|
+
* call-seq: default_options()
|
218
213
|
*
|
219
214
|
* Returns the default load and dump options as a Hash. The options are
|
220
|
-
* - indent
|
221
|
-
* - circular
|
222
|
-
* - auto_define
|
223
|
-
* - symbol_keys
|
224
|
-
* - escape_mode
|
225
|
-
* - class_cache
|
226
|
-
* - mode
|
227
|
-
* - time_format
|
228
|
-
* - bigdecimal_as_decimal
|
229
|
-
* - bigdecimal_load
|
230
|
-
* - create_id
|
231
|
-
* - second_precision
|
232
|
-
* - float_precision
|
233
|
-
* - use_to_json
|
234
|
-
* - use_as_json
|
235
|
-
* - nilnil
|
236
|
-
* - empty_string
|
237
|
-
* - allow_gc
|
238
|
-
* - quirks_mode
|
239
|
-
* - allow_invalid_unicode
|
240
|
-
* -
|
241
|
-
* -
|
242
|
-
* -
|
243
|
-
* -
|
244
|
-
* -
|
245
|
-
* -
|
246
|
-
* -
|
247
|
-
* -
|
248
|
-
*
|
215
|
+
* - *: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
|
216
|
+
* - *:circular* [_Boolean_|_nil_] support circular references while dumping
|
217
|
+
* - *:auto_define* [_Boolean_|_nil_] automatically define classes if they do not exist
|
218
|
+
* - *:symbol_keys* [_Boolean_|_nil_] use symbols instead of strings for hash keys
|
219
|
+
* - *:escape_mode* [_:newline_|_:json_|_:xss_safe_|_:ascii_|_unicode_xss_|_nil_] determines the characters to escape
|
220
|
+
* - *:class_cache* [_Boolean_|_nil_] cache classes for faster parsing (if dynamically modifying classes or reloading classes then don't use this)
|
221
|
+
* - *:mode* [_:object_|_:strict_|_:compat_|_:null_|_:custom_|_:rails_] load and dump modes to use for JSON
|
222
|
+
* - *:time_format* [_:unix_|_:unix_zone_|_:xmlschema_|_:ruby_] time format when dumping in :compat and :object mode
|
223
|
+
* - *:bigdecimal_as_decimal* [_Boolean_|_nil_] dump BigDecimal as a decimal number or as a String
|
224
|
+
* - *:bigdecimal_load* [_:bigdecimal_|_:float_|_:auto_] load decimals as BigDecimal instead of as a Float. :auto pick the most precise for the number of digits.
|
225
|
+
* - *:create_id* [_String_|_nil_] create id for json compatible object encoding, default is 'json_create'
|
226
|
+
* - *:second_precision* [_Fixnum_|_nil_] number of digits after the decimal when dumping the seconds portion of time
|
227
|
+
* - *:float_precision* [_Fixnum_|_nil_] number of digits of precision when dumping floats, 0 indicates use Ruby
|
228
|
+
* - *:use_to_json* [_Boolean_|_nil_] call to_json() methods on dump, default is false
|
229
|
+
* - *:use_as_json* [_Boolean_|_nil_] call as_json() methods on dump, default is false
|
230
|
+
* - *:nilnil* [_Boolean_|_nil_] if true a nil input to load will return nil and not raise an Exception
|
231
|
+
* - *:empty_string* [_Boolean_|_nil_] if true an empty input will not raise an Exception
|
232
|
+
* - *:allow_gc* [_Boolean_|_nil_] allow or prohibit GC during parsing, default is true (allow)
|
233
|
+
* - *:quirks_mode* [_true,_|_false_|_nil_] Allow single JSON values instead of documents, default is true (allow)
|
234
|
+
* - *:allow_invalid_unicode* [_true,_|_false_|_nil_] Allow invalid unicode, default is false (don't allow)
|
235
|
+
* - *:allow_nan* [_true,_|_false_|_nil_] Allow Nan, Infinity, and -Infinity to be parsed, default is true (allow)
|
236
|
+
* - *:indent_str* [_String_|_nil_] String to use for indentation, overriding the indent option is not nil
|
237
|
+
* - *:space* [_String_|_nil_] String to use for the space after the colon in JSON object fields
|
238
|
+
* - *:space_before* [_String_|_nil_] String to use before the colon separator in JSON object fields
|
239
|
+
* - *:object_nl* [_String_|_nil_] String to use after a JSON object field value
|
240
|
+
* - *:array_nl* [_String_|_nil_] String to use after a JSON array value
|
241
|
+
* - *: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.
|
242
|
+
* - *:hash_class* [_Class_|_nil_] Class to use instead of Hash on load, :object_class can also be used
|
243
|
+
* - *:array_class* [_Class_|_nil_] Class to use instead of Array on load
|
244
|
+
* - *:omit_nil* [_true_|_false_] if true Hash and Object attributes with nil values are omitted
|
245
|
+
*
|
246
|
+
* Return [_Hash_] all current option settings.
|
249
247
|
*/
|
250
248
|
static VALUE
|
251
249
|
get_def_opts(VALUE self) {
|
252
250
|
VALUE opts = rb_hash_new();
|
253
251
|
|
254
252
|
if (0 == oj_default_options.dump_opts.indent_size) {
|
255
|
-
rb_hash_aset(opts,
|
253
|
+
rb_hash_aset(opts, oj_indent_sym, INT2FIX(oj_default_options.indent));
|
256
254
|
} else {
|
257
|
-
rb_hash_aset(opts,
|
255
|
+
rb_hash_aset(opts, oj_indent_sym, rb_str_new2(oj_default_options.dump_opts.indent_str));
|
258
256
|
}
|
259
257
|
rb_hash_aset(opts, sec_prec_sym, INT2FIX(oj_default_options.sec_prec));
|
260
258
|
rb_hash_aset(opts, circular_sym, (Yes == oj_default_options.circular) ? Qtrue : ((No == oj_default_options.circular) ? Qfalse : Qnil));
|
@@ -263,18 +261,22 @@ get_def_opts(VALUE self) {
|
|
263
261
|
rb_hash_aset(opts, symbol_keys_sym, (Yes == oj_default_options.sym_key) ? Qtrue : ((No == oj_default_options.sym_key) ? Qfalse : Qnil));
|
264
262
|
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
263
|
rb_hash_aset(opts, use_to_json_sym, (Yes == oj_default_options.to_json) ? Qtrue : ((No == oj_default_options.to_json) ? Qfalse : Qnil));
|
264
|
+
rb_hash_aset(opts, use_to_hash_sym, (Yes == oj_default_options.to_hash) ? Qtrue : ((No == oj_default_options.to_hash) ? Qfalse : Qnil));
|
266
265
|
rb_hash_aset(opts, use_as_json_sym, (Yes == oj_default_options.as_json) ? Qtrue : ((No == oj_default_options.as_json) ? Qfalse : Qnil));
|
267
266
|
rb_hash_aset(opts, nilnil_sym, (Yes == oj_default_options.nilnil) ? Qtrue : ((No == oj_default_options.nilnil) ? Qfalse : Qnil));
|
268
267
|
rb_hash_aset(opts, empty_string_sym, (Yes == oj_default_options.empty_string) ? Qtrue : ((No == oj_default_options.empty_string) ? Qfalse : Qnil));
|
269
268
|
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,
|
269
|
+
rb_hash_aset(opts, oj_quirks_mode_sym, (Yes == oj_default_options.quirks_mode) ? Qtrue : ((No == oj_default_options.quirks_mode) ? Qfalse : Qnil));
|
271
270
|
rb_hash_aset(opts, allow_invalid_unicode_sym, (Yes == oj_default_options.allow_invalid) ? Qtrue : ((No == oj_default_options.allow_invalid) ? Qfalse : Qnil));
|
271
|
+
rb_hash_aset(opts, oj_allow_nan_sym, (Yes == oj_default_options.allow_nan) ? Qtrue : ((No == oj_default_options.allow_nan) ? Qfalse : Qnil));
|
272
272
|
rb_hash_aset(opts, float_prec_sym, INT2FIX(oj_default_options.float_prec));
|
273
273
|
switch (oj_default_options.mode) {
|
274
274
|
case StrictMode: rb_hash_aset(opts, mode_sym, strict_sym); break;
|
275
275
|
case CompatMode: rb_hash_aset(opts, mode_sym, compat_sym); break;
|
276
276
|
case NullMode: rb_hash_aset(opts, mode_sym, null_sym); break;
|
277
277
|
case ObjectMode:
|
278
|
+
case CustomMode: rb_hash_aset(opts, mode_sym, custom_sym); break;
|
279
|
+
case RailsMode: rb_hash_aset(opts, mode_sym, rails_sym); break;
|
278
280
|
default: rb_hash_aset(opts, mode_sym, object_sym); break;
|
279
281
|
}
|
280
282
|
switch (oj_default_options.escape_mode) {
|
@@ -282,6 +284,7 @@ get_def_opts(VALUE self) {
|
|
282
284
|
case JSONEsc: rb_hash_aset(opts, escape_mode_sym, json_sym); break;
|
283
285
|
case XSSEsc: rb_hash_aset(opts, escape_mode_sym, xss_safe_sym); break;
|
284
286
|
case ASCIIEsc: rb_hash_aset(opts, escape_mode_sym, ascii_sym); break;
|
287
|
+
case JXEsc: rb_hash_aset(opts, escape_mode_sym, unicode_xss_sym); break;
|
285
288
|
default: rb_hash_aset(opts, escape_mode_sym, json_sym); break;
|
286
289
|
}
|
287
290
|
switch (oj_default_options.time_format) {
|
@@ -298,10 +301,10 @@ get_def_opts(VALUE self) {
|
|
298
301
|
default: rb_hash_aset(opts, bigdecimal_load_sym, auto_sym); break;
|
299
302
|
}
|
300
303
|
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,
|
302
|
-
rb_hash_aset(opts,
|
303
|
-
rb_hash_aset(opts,
|
304
|
-
rb_hash_aset(opts,
|
304
|
+
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));
|
305
|
+
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));
|
306
|
+
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));
|
307
|
+
rb_hash_aset(opts, oj_array_nl_sym, (0 == oj_default_options.dump_opts.array_size) ? Qnil : rb_str_new2(oj_default_options.dump_opts.array_nl));
|
305
308
|
|
306
309
|
switch (oj_default_options.dump_opts.nan_dump) {
|
307
310
|
case NullNan: rb_hash_aset(opts, nan_sym, null_sym); break;
|
@@ -312,56 +315,46 @@ get_def_opts(VALUE self) {
|
|
312
315
|
default: rb_hash_aset(opts, nan_sym, auto_sym); break;
|
313
316
|
}
|
314
317
|
rb_hash_aset(opts, omit_nil_sym, oj_default_options.dump_opts.omit_nil ? Qtrue : Qfalse);
|
315
|
-
rb_hash_aset(opts,
|
318
|
+
rb_hash_aset(opts, oj_hash_class_sym, oj_default_options.hash_class);
|
319
|
+
rb_hash_aset(opts, oj_array_class_sym, oj_default_options.array_class);
|
316
320
|
|
317
321
|
return opts;
|
318
322
|
}
|
319
323
|
|
320
|
-
/*
|
324
|
+
/* Document-method: default_options=
|
325
|
+
* call-seq: default_options=(opts)
|
321
326
|
*
|
322
327
|
* Sets the default options for load and dump.
|
323
|
-
*
|
324
|
-
*
|
325
|
-
*
|
326
|
-
*
|
327
|
-
*
|
328
|
-
*
|
329
|
-
*
|
330
|
-
*
|
331
|
-
*
|
332
|
-
*
|
333
|
-
*
|
334
|
-
*
|
335
|
-
*
|
336
|
-
*
|
337
|
-
*
|
338
|
-
*
|
339
|
-
*
|
340
|
-
*
|
341
|
-
*
|
342
|
-
*
|
343
|
-
*
|
344
|
-
*
|
345
|
-
*
|
346
|
-
*
|
347
|
-
*
|
348
|
-
*
|
349
|
-
*
|
350
|
-
*
|
351
|
-
*
|
352
|
-
*
|
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]
|
328
|
+
* - *opts* [_Hash_] options to change
|
329
|
+
* - *:indent* [_Fixnum_|_String_|_nil_] number of spaces to indent each element in a JSON document or the String to use for identation.
|
330
|
+
* - :circular [_Boolean_|_nil_] support circular references while dumping.
|
331
|
+
* - *:auto_define* [_Boolean_|_nil_] automatically define classes if they do not exist.
|
332
|
+
* - *:symbol_keys* [_Boolean_|_nil_] convert hash keys to symbols.
|
333
|
+
* - *:class_cache* [_Boolean_|_nil_] cache classes for faster parsing.
|
334
|
+
* - *: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.
|
335
|
+
* - *:bigdecimal_as_decimal* [_Boolean_|_nil_] dump BigDecimal as a decimal number or as a String.
|
336
|
+
* - *: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.
|
337
|
+
* - *:mode* [_:object_|_:strict_|_:compat_|_:null_|_:custom_|_:rails_] 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.
|
338
|
+
* - *: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.
|
339
|
+
* - *:create_id* [_String_|_nil_] create id for json compatible object encoding
|
340
|
+
* - *:second_precision* [_Fixnum_|_nil_] number of digits after the decimal when dumping the seconds portion of time.
|
341
|
+
* - *:float_precision* [_Fixnum_|_nil_] number of digits of precision when dumping floats, 0 indicates use Ruby.
|
342
|
+
* - *:use_to_json* [_Boolean_|_nil_] call to_json() methods on dump, default is false.
|
343
|
+
* - *:use_as_json* [_Boolean_|_nil_] call as_json() methods on dump, default is false.
|
344
|
+
* - *:use_to_hash* [_Boolean_|_nil_] call to_hash() methods on dump, default is false.
|
345
|
+
* - *:nilnil* [_Boolean_|_nil_] if true a nil input to load will return nil and not raise an Exception.
|
346
|
+
* - *:allow_gc* [_Boolean_|_nil_] allow or prohibit GC during parsing, default is true (allow).
|
347
|
+
* - *:quirks_mode* [_Boolean_|_nil_] allow single JSON values instead of documents, default is true (allow).
|
348
|
+
* - *:allow_invalid_unicode* [_Boolean_|_nil_] allow invalid unicode, default is false (don't allow).
|
349
|
+
* - *:allow_nan* [_Boolean_|_nil_] allow Nan, Infinity, and -Infinity, default is true (allow).
|
350
|
+
* - *:space* [_String_|_nil_] String to use for the space after the colon in JSON object fields.
|
351
|
+
* - *:space_before* [_String_|_nil_] String to use before the colon separator in JSON object fields.
|
352
|
+
* - *:object_nl* [_String_|_nil_] String to use after a JSON object field value.
|
353
|
+
* - *:array_nl* [_String_|_nil_] String to use after a JSON array value
|
354
|
+
* - *:nan* [_:null_|_:huge_|_:word_|_:raise_] how to dump Infinity and NaN in null, strict, and compat mode. :null places a null, :huge places a huge number, :word places Infinity or NaN, :raise raises and exception, :auto uses default for each mode.
|
355
|
+
* - *:hash_class* [_Class_|_nil_] Class to use instead of Hash on load, :object_class can also be used.
|
356
|
+
* - *:array_class* [_Class_|_nil_] Class to use instead of Array on load.
|
357
|
+
* - *:omit_nil* [_true_|_false_] if true Hash and Object attributes with nil values are omitted.
|
365
358
|
*/
|
366
359
|
static VALUE
|
367
360
|
set_def_opts(VALUE self, VALUE opts) {
|
@@ -379,13 +372,17 @@ oj_parse_options(VALUE ropts, Options copts) {
|
|
379
372
|
{ symbol_keys_sym, &copts->sym_key },
|
380
373
|
{ class_cache_sym, &copts->class_cache },
|
381
374
|
{ bigdecimal_as_decimal_sym, &copts->bigdec_as_num },
|
375
|
+
{ use_to_hash_sym, &copts->to_hash },
|
382
376
|
{ use_to_json_sym, &copts->to_json },
|
383
377
|
{ use_as_json_sym, &copts->as_json },
|
384
378
|
{ nilnil_sym, &copts->nilnil },
|
379
|
+
{ allow_blank_sym, &copts->nilnil }, // same as nilnil
|
385
380
|
{ empty_string_sym, &copts->empty_string },
|
386
381
|
{ allow_gc_sym, &copts->allow_gc },
|
387
|
-
{
|
382
|
+
{ oj_quirks_mode_sym, &copts->quirks_mode },
|
388
383
|
{ allow_invalid_unicode_sym, &copts->allow_invalid },
|
384
|
+
{ oj_allow_nan_sym, &copts->allow_nan },
|
385
|
+
{ oj_create_additions_sym, &copts->create_ok },
|
389
386
|
{ Qnil, 0 }
|
390
387
|
};
|
391
388
|
YesNoOpt o;
|
@@ -395,8 +392,8 @@ oj_parse_options(VALUE ropts, Options copts) {
|
|
395
392
|
if (T_HASH != rb_type(ropts)) {
|
396
393
|
return;
|
397
394
|
}
|
398
|
-
if (Qtrue == rb_funcall(ropts,
|
399
|
-
v = rb_hash_lookup(ropts,
|
395
|
+
if (Qtrue == rb_funcall(ropts, oj_has_key_id, 1, oj_indent_sym)) {
|
396
|
+
v = rb_hash_lookup(ropts, oj_indent_sym);
|
400
397
|
switch (rb_type(v)) {
|
401
398
|
case T_NIL:
|
402
399
|
copts->dump_opts.indent_size = 0;
|
@@ -429,11 +426,10 @@ oj_parse_options(VALUE ropts, Options copts) {
|
|
429
426
|
rb_raise(rb_eArgError, ":float_precision must be a Integer.");
|
430
427
|
}
|
431
428
|
#else
|
432
|
-
if (
|
429
|
+
if (T_FIXNUM != rb_type(v)) {
|
433
430
|
rb_raise(rb_eArgError, ":float_precision must be a Fixnum.");
|
434
431
|
}
|
435
432
|
#endif
|
436
|
-
Check_Type(v, T_FIXNUM);
|
437
433
|
n = FIX2INT(v);
|
438
434
|
if (0 >= n) {
|
439
435
|
*copts->float_fmt = '\0';
|
@@ -454,7 +450,7 @@ oj_parse_options(VALUE ropts, Options copts) {
|
|
454
450
|
rb_raise(rb_eArgError, ":second_precision must be a Integer.");
|
455
451
|
}
|
456
452
|
#else
|
457
|
-
if (
|
453
|
+
if (T_FIXNUM != rb_type(v)) {
|
458
454
|
rb_raise(rb_eArgError, ":second_precision must be a Fixnum.");
|
459
455
|
}
|
460
456
|
#endif
|
@@ -471,12 +467,16 @@ oj_parse_options(VALUE ropts, Options copts) {
|
|
471
467
|
copts->mode = ObjectMode;
|
472
468
|
} else if (strict_sym == v) {
|
473
469
|
copts->mode = StrictMode;
|
474
|
-
} else if (compat_sym == v) {
|
470
|
+
} else if (compat_sym == v || json_sym == v) {
|
475
471
|
copts->mode = CompatMode;
|
476
472
|
} else if (null_sym == v) {
|
477
473
|
copts->mode = NullMode;
|
474
|
+
} else if (custom_sym == v) {
|
475
|
+
copts->mode = CustomMode;
|
476
|
+
} else if (rails_sym == v) {
|
477
|
+
copts->mode = RailsMode;
|
478
478
|
} else {
|
479
|
-
rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, or :
|
479
|
+
rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, :null, :custom, or :rails.");
|
480
480
|
}
|
481
481
|
}
|
482
482
|
if (Qnil != (v = rb_hash_lookup(ropts, time_format_sym))) {
|
@@ -501,8 +501,10 @@ oj_parse_options(VALUE ropts, Options copts) {
|
|
501
501
|
copts->escape_mode = XSSEsc;
|
502
502
|
} else if (ascii_sym == v) {
|
503
503
|
copts->escape_mode = ASCIIEsc;
|
504
|
+
} else if (unicode_xss_sym == v) {
|
505
|
+
copts->escape_mode = JXEsc;
|
504
506
|
} else {
|
505
|
-
rb_raise(rb_eArgError, ":encoding must be :newline, :json, :xss_safe, or :ascii.");
|
507
|
+
rb_raise(rb_eArgError, ":encoding must be :newline, :json, :xss_safe, :unicode_xss, or :ascii.");
|
506
508
|
}
|
507
509
|
}
|
508
510
|
if (Qnil != (v = rb_hash_lookup(ropts, bigdecimal_load_sym))) {
|
@@ -516,7 +518,7 @@ oj_parse_options(VALUE ropts, Options copts) {
|
|
516
518
|
rb_raise(rb_eArgError, ":bigdecimal_load must be :bigdecimal, :float, or :auto.");
|
517
519
|
}
|
518
520
|
}
|
519
|
-
if (Qtrue == rb_funcall(ropts,
|
521
|
+
if (Qtrue == rb_funcall(ropts, oj_has_key_id, 1, create_id_sym)) {
|
520
522
|
v = rb_hash_lookup(ropts, create_id_sym);
|
521
523
|
if (Qnil == v) {
|
522
524
|
if (json_class != oj_default_options.create_id) {
|
@@ -549,8 +551,8 @@ oj_parse_options(VALUE ropts, Options copts) {
|
|
549
551
|
}
|
550
552
|
}
|
551
553
|
}
|
552
|
-
if (Qtrue == rb_funcall(ropts,
|
553
|
-
if (Qnil == (v = rb_hash_lookup(ropts,
|
554
|
+
if (Qtrue == rb_funcall(ropts, oj_has_key_id, 1, oj_space_sym)) {
|
555
|
+
if (Qnil == (v = rb_hash_lookup(ropts, oj_space_sym))) {
|
554
556
|
copts->dump_opts.after_size = 0;
|
555
557
|
*copts->dump_opts.after_sep = '\0';
|
556
558
|
} else {
|
@@ -562,8 +564,8 @@ oj_parse_options(VALUE ropts, Options copts) {
|
|
562
564
|
copts->dump_opts.after_size = (uint8_t)len;
|
563
565
|
}
|
564
566
|
}
|
565
|
-
if (Qtrue == rb_funcall(ropts,
|
566
|
-
if (Qnil == (v = rb_hash_lookup(ropts,
|
567
|
+
if (Qtrue == rb_funcall(ropts, oj_has_key_id, 1, oj_space_before_sym)) {
|
568
|
+
if (Qnil == (v = rb_hash_lookup(ropts, oj_space_before_sym))) {
|
567
569
|
copts->dump_opts.before_size = 0;
|
568
570
|
*copts->dump_opts.before_sep = '\0';
|
569
571
|
} else {
|
@@ -575,8 +577,8 @@ oj_parse_options(VALUE ropts, Options copts) {
|
|
575
577
|
copts->dump_opts.before_size = (uint8_t)len;
|
576
578
|
}
|
577
579
|
}
|
578
|
-
if (Qtrue == rb_funcall(ropts,
|
579
|
-
if (Qnil == (v = rb_hash_lookup(ropts,
|
580
|
+
if (Qtrue == rb_funcall(ropts, oj_has_key_id, 1, oj_object_nl_sym)) {
|
581
|
+
if (Qnil == (v = rb_hash_lookup(ropts, oj_object_nl_sym))) {
|
580
582
|
copts->dump_opts.hash_size = 0;
|
581
583
|
*copts->dump_opts.hash_nl = '\0';
|
582
584
|
} else {
|
@@ -588,8 +590,8 @@ oj_parse_options(VALUE ropts, Options copts) {
|
|
588
590
|
copts->dump_opts.hash_size = (uint8_t)len;
|
589
591
|
}
|
590
592
|
}
|
591
|
-
if (Qtrue == rb_funcall(ropts,
|
592
|
-
if (Qnil == (v = rb_hash_lookup(ropts,
|
593
|
+
if (Qtrue == rb_funcall(ropts, oj_has_key_id, 1, oj_array_nl_sym)) {
|
594
|
+
if (Qnil == (v = rb_hash_lookup(ropts, oj_array_nl_sym))) {
|
593
595
|
copts->dump_opts.array_size = 0;
|
594
596
|
*copts->dump_opts.array_nl = '\0';
|
595
597
|
} else {
|
@@ -631,115 +633,76 @@ oj_parse_options(VALUE ropts, Options copts) {
|
|
631
633
|
}
|
632
634
|
}
|
633
635
|
// This is here only for backwards compatibility with the original Oj.
|
634
|
-
v = rb_hash_lookup(ropts,
|
636
|
+
v = rb_hash_lookup(ropts, oj_ascii_only_sym);
|
635
637
|
if (Qtrue == v) {
|
636
638
|
copts->escape_mode = ASCIIEsc;
|
637
639
|
} else if (Qfalse == v) {
|
638
640
|
copts->escape_mode = JSONEsc;
|
639
641
|
}
|
640
|
-
if (Qtrue == rb_funcall(ropts,
|
641
|
-
if (Qnil == (v = rb_hash_lookup(ropts,
|
642
|
+
if (Qtrue == rb_funcall(ropts, oj_has_key_id, 1, oj_hash_class_sym)) {
|
643
|
+
if (Qnil == (v = rb_hash_lookup(ropts, oj_hash_class_sym))) {
|
642
644
|
copts->hash_class = Qnil;
|
643
645
|
} else {
|
644
646
|
rb_check_type(v, T_CLASS);
|
645
647
|
copts->hash_class = v;
|
646
648
|
}
|
647
649
|
}
|
650
|
+
if (Qtrue == rb_funcall(ropts, oj_has_key_id, 1, oj_object_class_sym)) {
|
651
|
+
if (Qnil == (v = rb_hash_lookup(ropts, oj_object_class_sym))) {
|
652
|
+
copts->hash_class = Qnil;
|
653
|
+
} else {
|
654
|
+
rb_check_type(v, T_CLASS);
|
655
|
+
copts->hash_class = v;
|
656
|
+
}
|
657
|
+
}
|
658
|
+
if (Qtrue == rb_funcall(ropts, oj_has_key_id, 1, oj_array_class_sym)) {
|
659
|
+
if (Qnil == (v = rb_hash_lookup(ropts, oj_array_class_sym))) {
|
660
|
+
copts->array_class = Qnil;
|
661
|
+
} else {
|
662
|
+
rb_check_type(v, T_CLASS);
|
663
|
+
copts->array_class = v;
|
664
|
+
}
|
665
|
+
}
|
666
|
+
oj_parse_opt_match_string(&copts->str_rx, ropts);
|
648
667
|
}
|
649
668
|
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
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
|
-
*/
|
669
|
+
static int
|
670
|
+
match_string_cb(VALUE key, VALUE value, RxClass rc) {
|
671
|
+
if (T_CLASS != rb_type(value)) {
|
672
|
+
rb_raise(rb_eArgError, "for :match_string, the hash values must be a Class.");
|
673
|
+
}
|
674
|
+
switch (rb_type(key)) {
|
675
|
+
case T_REGEXP:
|
676
|
+
oj_rxclass_rappend(rc, key, value);
|
677
|
+
break;
|
678
|
+
case T_STRING:
|
679
|
+
if (0 != oj_rxclass_append(rc, StringValuePtr(key), value)) {
|
680
|
+
rb_raise(rb_eArgError, "%s", rc->err);
|
681
|
+
}
|
682
|
+
break;
|
683
|
+
default:
|
684
|
+
rb_raise(rb_eArgError, "for :match_string, keys must either a String or RegExp.");
|
685
|
+
break;
|
686
|
+
}
|
687
|
+
return ST_CONTINUE;
|
688
|
+
}
|
675
689
|
|
676
|
-
|
677
|
-
|
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
|
-
*/
|
690
|
+
void
|
691
|
+
oj_parse_opt_match_string(RxClass rc, VALUE ropts) {
|
692
|
+
VALUE v;
|
700
693
|
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
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
|
-
*/
|
694
|
+
if (Qnil != (v = rb_hash_lookup(ropts, match_string_sym))) {
|
695
|
+
rb_check_type(v, T_HASH);
|
696
|
+
// Zero out rc. Pattern are not appended but override.
|
697
|
+
rc->head = NULL;
|
698
|
+
rc->tail = NULL;
|
699
|
+
*rc->err = '\0';
|
700
|
+
rb_hash_foreach(v, match_string_cb, (VALUE)rc);
|
701
|
+
}
|
702
|
+
}
|
741
703
|
|
742
|
-
/*
|
704
|
+
/* Document-method: load
|
705
|
+
* call-seq: load(json, options) { _|_obj, start, len_|_ }
|
743
706
|
*
|
744
707
|
* Parses a JSON document String into a Object, Hash, Array, String, Fixnum,
|
745
708
|
* Float, true, false, or nil according to the default mode or the mode
|
@@ -755,12 +718,21 @@ oj_parse_options(VALUE ropts, Options copts) {
|
|
755
718
|
* a file object is passed as the first argument. A stream input will be parsed
|
756
719
|
* using a stream parser but others use the slightly faster string parser.
|
757
720
|
*
|
758
|
-
* A block can
|
759
|
-
*
|
760
|
-
* multiple JSON documents.
|
761
|
-
*
|
762
|
-
*
|
763
|
-
*
|
721
|
+
* A block can be provided with a single argument. That argument will be the
|
722
|
+
* parsed JSON document. This is useful when parsing a string that includes
|
723
|
+
* multiple JSON documents. The block can take up to 3 arguments, the parsed
|
724
|
+
* object, the position in the string or stream of the start of the JSON for
|
725
|
+
* that object, and the length of the JSON for that object plus trailing
|
726
|
+
* whitespace.
|
727
|
+
*
|
728
|
+
* - *json* [_String_|_IO_] JSON String or an Object that responds to read()
|
729
|
+
* - *options* [_Hash_] load options (same as default_options)
|
730
|
+
* - -
|
731
|
+
* - *obj* [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_] parsed object.
|
732
|
+
* - *start* [_optional, _Integer_] start position of parsed JSON for obj.
|
733
|
+
* - *len* [_optional, _Integer_] length of parsed JSON for obj.
|
734
|
+
*
|
735
|
+
* Returns [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_]
|
764
736
|
*/
|
765
737
|
static VALUE
|
766
738
|
load(int argc, VALUE *argv, VALUE self) {
|
@@ -779,21 +751,28 @@ load(int argc, VALUE *argv, VALUE self) {
|
|
779
751
|
mode = ObjectMode;
|
780
752
|
} else if (strict_sym == v) {
|
781
753
|
mode = StrictMode;
|
782
|
-
} else if (compat_sym == v) {
|
754
|
+
} else if (compat_sym == v || json_sym == v) {
|
783
755
|
mode = CompatMode;
|
784
756
|
} else if (null_sym == v) {
|
785
757
|
mode = NullMode;
|
758
|
+
} else if (custom_sym == v) {
|
759
|
+
mode = CustomMode;
|
760
|
+
} else if (rails_sym == v) {
|
761
|
+
mode = RailsMode;
|
786
762
|
} else {
|
787
|
-
rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, or :
|
763
|
+
rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, :null, :custom, or :rails.");
|
788
764
|
}
|
789
765
|
}
|
790
766
|
}
|
791
767
|
switch (mode) {
|
792
768
|
case StrictMode:
|
793
|
-
return oj_strict_parse(argc, argv, self);
|
794
769
|
case NullMode:
|
770
|
+
return oj_strict_parse(argc, argv, self);
|
795
771
|
case CompatMode:
|
772
|
+
case RailsMode:
|
796
773
|
return oj_compat_parse(argc, argv, self);
|
774
|
+
case CustomMode:
|
775
|
+
return oj_custom_parse(argc, argv, self);
|
797
776
|
case ObjectMode:
|
798
777
|
default:
|
799
778
|
break;
|
@@ -802,7 +781,7 @@ load(int argc, VALUE *argv, VALUE self) {
|
|
802
781
|
}
|
803
782
|
|
804
783
|
/* Document-method: load_file
|
805
|
-
*
|
784
|
+
* call-seq: load_file(path, options) { _|_obj, start, len_|_ }
|
806
785
|
*
|
807
786
|
* Parses a JSON document String into a Object, Hash, Array, String, Fixnum,
|
808
787
|
* Float, true, false, or nil according to the default mode or the mode
|
@@ -820,12 +799,21 @@ load(int argc, VALUE *argv, VALUE self) {
|
|
820
799
|
* This is a stream based parser which allows a large or huge file to be loaded
|
821
800
|
* without pulling the whole file into memory.
|
822
801
|
*
|
823
|
-
* A block can
|
824
|
-
*
|
825
|
-
* multiple JSON documents.
|
826
|
-
*
|
827
|
-
*
|
828
|
-
*
|
802
|
+
* A block can be provided with a single argument. That argument will be the
|
803
|
+
* parsed JSON document. This is useful when parsing a string that includes
|
804
|
+
* multiple JSON documents. The block can take up to 3 arguments, the parsed
|
805
|
+
* object, the position in the string or stream of the start of the JSON for
|
806
|
+
* that object, and the length of the JSON for that object plus trailing
|
807
|
+
* whitespace.
|
808
|
+
*
|
809
|
+
* - *path* [_String_] to a file containing a JSON document
|
810
|
+
* - *options* [_Hash_] load options (same as default_options)
|
811
|
+
* - -
|
812
|
+
* - *obj* [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_] parsed object.
|
813
|
+
* - *start* [_optional, _Integer_] start position of parsed JSON for obj.
|
814
|
+
* - *len* [_optional, _Integer_] length of parsed JSON for obj.
|
815
|
+
*
|
816
|
+
* Returns [_Object_|_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_]
|
829
817
|
*/
|
830
818
|
static VALUE
|
831
819
|
load_file(int argc, VALUE *argv, VALUE self) {
|
@@ -838,9 +826,11 @@ load_file(int argc, VALUE *argv, VALUE self) {
|
|
838
826
|
rb_raise(rb_eArgError, "Wrong number of arguments to load().");
|
839
827
|
}
|
840
828
|
Check_Type(*argv, T_STRING);
|
829
|
+
parse_info_init(&pi);
|
841
830
|
pi.options = oj_default_options;
|
842
831
|
pi.handler = Qnil;
|
843
832
|
pi.err_class = Qnil;
|
833
|
+
pi.max_depth = 0;
|
844
834
|
if (2 <= argc) {
|
845
835
|
VALUE ropts = argv[1];
|
846
836
|
VALUE v;
|
@@ -851,12 +841,16 @@ load_file(int argc, VALUE *argv, VALUE self) {
|
|
851
841
|
mode = ObjectMode;
|
852
842
|
} else if (strict_sym == v) {
|
853
843
|
mode = StrictMode;
|
854
|
-
} else if (compat_sym == v) {
|
844
|
+
} else if (compat_sym == v || json_sym == v) {
|
855
845
|
mode = CompatMode;
|
856
846
|
} else if (null_sym == v) {
|
857
847
|
mode = NullMode;
|
848
|
+
} else if (custom_sym == v) {
|
849
|
+
mode = CustomMode;
|
850
|
+
} else if (rails_sym == v) {
|
851
|
+
mode = RailsMode;
|
858
852
|
} else {
|
859
|
-
rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat,
|
853
|
+
rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, :null, :custom, :rails.");
|
860
854
|
}
|
861
855
|
}
|
862
856
|
}
|
@@ -870,6 +864,8 @@ load_file(int argc, VALUE *argv, VALUE self) {
|
|
870
864
|
return oj_pi_sparse(argc, argv, &pi, fd);
|
871
865
|
case NullMode:
|
872
866
|
case CompatMode:
|
867
|
+
case CustomMode:
|
868
|
+
case RailsMode:
|
873
869
|
oj_set_compat_callbacks(&pi);
|
874
870
|
return oj_pi_sparse(argc, argv, &pi, fd);
|
875
871
|
case ObjectMode:
|
@@ -881,21 +877,25 @@ load_file(int argc, VALUE *argv, VALUE self) {
|
|
881
877
|
return oj_pi_sparse(argc, argv, &pi, fd);
|
882
878
|
}
|
883
879
|
|
884
|
-
/*
|
880
|
+
/* Document-method: safe_load
|
881
|
+
* call-seq: safe_load(doc)
|
885
882
|
*
|
886
883
|
* Loads a JSON document in strict mode with :auto_define and :symbol_keys
|
887
884
|
* turned off. This function should be safe to use with JSON received on an
|
888
885
|
* unprotected public interface.
|
889
886
|
*
|
890
|
-
*
|
891
|
-
*
|
887
|
+
* - *doc* [_String__|_IO_] JSON String or IO to load.
|
888
|
+
*
|
889
|
+
* Returns [_Hash_|_Array_|_String_|_Fixnum_|_Bignum_|_BigDecimal_|_nil_|_True_|_False_]
|
892
890
|
*/
|
893
891
|
static VALUE
|
894
892
|
safe_load(VALUE self, VALUE doc) {
|
895
893
|
struct _ParseInfo pi;
|
896
894
|
VALUE args[1];
|
897
895
|
|
896
|
+
parse_info_init(&pi);
|
898
897
|
pi.err_class = Qnil;
|
898
|
+
pi.max_depth = 0;
|
899
899
|
pi.options = oj_default_options;
|
900
900
|
pi.options.auto_define = No;
|
901
901
|
pi.options.sym_key = No;
|
@@ -906,18 +906,20 @@ safe_load(VALUE self, VALUE doc) {
|
|
906
906
|
return oj_pi_parse(1, args, &pi, 0, 0, 1);
|
907
907
|
}
|
908
908
|
|
909
|
-
/*
|
909
|
+
/* Document-method: saj_parse
|
910
|
+
* call-seq: saj_parse(handler, io)
|
910
911
|
*
|
911
912
|
* Parses an IO stream or file containing a JSON document. Raises an exception
|
912
913
|
* if the JSON is malformed. This is a callback parser that calls the methods in
|
913
914
|
* the handler if they exist. A sample is the Oj::Saj class which can be used as
|
914
915
|
* a base class for the handler.
|
915
916
|
*
|
916
|
-
*
|
917
|
-
*
|
917
|
+
* - *handler* [_Oj::Saj_] responds to Oj::Saj methods
|
918
|
+
* - *io* [_IO_|_String_] IO Object to read from
|
918
919
|
*/
|
919
920
|
|
920
|
-
/*
|
921
|
+
/* Document-method: sc_parse
|
922
|
+
* call-seq: sc_parse(handler, io)
|
921
923
|
*
|
922
924
|
* Parses an IO stream or file containing a JSON document. Raises an exception
|
923
925
|
* if the JSON is malformed. This is a callback parser (Simple Callback Parser)
|
@@ -926,15 +928,16 @@ safe_load(VALUE self, VALUE doc) {
|
|
926
928
|
* callback parser is slightly more efficient than the Saj callback parser and
|
927
929
|
* requires less argument checking.
|
928
930
|
*
|
929
|
-
*
|
930
|
-
*
|
931
|
+
* - *handler* [_Oj_::ScHandler_] responds to Oj::ScHandler methods
|
932
|
+
* - *io* [_IO__|_String_] IO Object to read from
|
931
933
|
*/
|
932
934
|
|
933
|
-
/*
|
935
|
+
/* Document-method: dump
|
936
|
+
* call-seq: dump(obj, options)
|
934
937
|
*
|
935
938
|
* Dumps an Object (obj) to a string.
|
936
|
-
*
|
937
|
-
*
|
939
|
+
* - *obj* [_Object_] Object to serialize as an JSON document String
|
940
|
+
* - *options* [_Hash_] same as default_options
|
938
941
|
*/
|
939
942
|
static VALUE
|
940
943
|
dump(int argc, VALUE *argv, VALUE self) {
|
@@ -949,10 +952,15 @@ dump(int argc, VALUE *argv, VALUE self) {
|
|
949
952
|
if (2 == argc) {
|
950
953
|
oj_parse_options(argv[1], &copts);
|
951
954
|
}
|
955
|
+
if (CompatMode == copts.mode) {
|
956
|
+
copts.to_json = No;
|
957
|
+
copts.dump_opts.nan_dump = true;
|
958
|
+
}
|
952
959
|
out.buf = buf;
|
953
960
|
out.end = buf + sizeof(buf) - 10;
|
954
961
|
out.allocated = 0;
|
955
962
|
out.omit_nil = copts.dump_opts.omit_nil;
|
963
|
+
out.caller = CALLER_DUMP;
|
956
964
|
oj_dump_obj_to_json(*argv, &copts, &out);
|
957
965
|
if (0 == out.buf) {
|
958
966
|
rb_raise(rb_eNoMemError, "Not enough memory.");
|
@@ -965,15 +973,68 @@ dump(int argc, VALUE *argv, VALUE self) {
|
|
965
973
|
return rstr;
|
966
974
|
}
|
967
975
|
|
976
|
+
/* Document-method: to_json
|
977
|
+
* call-seq: to_json(obj, options)
|
978
|
+
*
|
979
|
+
* Dumps an Object (obj) to a string. If the object has a to_json method that
|
980
|
+
* will be called. The mode is set to :compat.
|
981
|
+
* - *obj* [_Object_] Object to serialize as an JSON document String
|
982
|
+
* - *options* [_Hash_]
|
983
|
+
* - *: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
|
984
|
+
* - *:allow_nan* [_boolean_] If true non JSON compliant words such as Nan and Infinity will be used as appropriate, default is true.
|
985
|
+
* - *:quirks_mode* [_boolean_] Allow single JSON values instead of documents, default is true (allow).
|
986
|
+
* - *:indent_str* [_String_|_nil_] String to use for indentation, overriding the indent option if not nil.
|
987
|
+
* - *:space* [_String_|_nil_] String to use for the space after the colon in JSON object fields.
|
988
|
+
* - *:space_before* [_String_|_nil_] String to use before the colon separator in JSON object fields.
|
989
|
+
* - *:object_nl* [_String_|_nil_] String to use after a JSON object field value.
|
990
|
+
* - *:array_nl* [_String_|_nil_] String to use after a JSON array value.
|
991
|
+
*
|
992
|
+
* Returns [_String_] the encoded JSON.
|
993
|
+
*/
|
994
|
+
static VALUE
|
995
|
+
to_json(int argc, VALUE *argv, VALUE self) {
|
996
|
+
char buf[4096];
|
997
|
+
struct _Out out;
|
998
|
+
struct _Options copts = oj_default_options;
|
999
|
+
VALUE rstr;
|
1000
|
+
|
1001
|
+
if (1 > argc) {
|
1002
|
+
rb_raise(rb_eArgError, "wrong number of arguments (0 for 1).");
|
1003
|
+
}
|
1004
|
+
copts.dump_opts.nan_dump = false;
|
1005
|
+
if (2 == argc) {
|
1006
|
+
oj_parse_mimic_dump_options(argv[1], &copts);
|
1007
|
+
}
|
1008
|
+
copts.mode = CompatMode;
|
1009
|
+
copts.to_json = Yes;
|
1010
|
+
out.buf = buf;
|
1011
|
+
out.end = buf + sizeof(buf) - 10;
|
1012
|
+
out.allocated = 0;
|
1013
|
+
out.omit_nil = copts.dump_opts.omit_nil;
|
1014
|
+
// For obj.to_json or generate nan is not allowed but if called from dump
|
1015
|
+
// it is.
|
1016
|
+
copts.dump_opts.nan_dump = false;
|
1017
|
+
oj_dump_obj_to_json(*argv, &copts, &out);
|
1018
|
+
if (0 == out.buf) {
|
1019
|
+
rb_raise(rb_eNoMemError, "Not enough memory.");
|
1020
|
+
}
|
1021
|
+
rstr = rb_str_new2(out.buf);
|
1022
|
+
rstr = oj_encode(rstr);
|
1023
|
+
if (out.allocated) {
|
1024
|
+
xfree(out.buf);
|
1025
|
+
}
|
1026
|
+
return rstr;
|
1027
|
+
}
|
968
1028
|
|
969
|
-
/*
|
1029
|
+
/* Document-method: to_file
|
1030
|
+
* call-seq: to_file(file_path, obj, options)
|
970
1031
|
*
|
971
1032
|
* Dumps an Object to the specified file.
|
972
|
-
*
|
973
|
-
*
|
974
|
-
*
|
975
|
-
*
|
976
|
-
*
|
1033
|
+
* - *file* [_String_] _path file path to write the JSON document to
|
1034
|
+
* - *obj* [_Object_] Object to serialize as an JSON document String
|
1035
|
+
* - *options* [_Hash_] formating options
|
1036
|
+
* - *:indent* [_Fixnum_] format expected
|
1037
|
+
* - *:circular* [_Boolean_] allow circular references, default: false
|
977
1038
|
*/
|
978
1039
|
static VALUE
|
979
1040
|
to_file(int argc, VALUE *argv, VALUE self) {
|
@@ -988,14 +1049,15 @@ to_file(int argc, VALUE *argv, VALUE self) {
|
|
988
1049
|
return Qnil;
|
989
1050
|
}
|
990
1051
|
|
991
|
-
/*
|
1052
|
+
/* Document-method: to_stream
|
1053
|
+
* call-seq: to_stream(io, obj, options)
|
992
1054
|
*
|
993
1055
|
* Dumps an Object to the specified IO stream.
|
994
|
-
*
|
995
|
-
*
|
996
|
-
*
|
997
|
-
*
|
998
|
-
*
|
1056
|
+
* - *io* [_IO_] IO stream to write the JSON document to
|
1057
|
+
* - *obj* [_Object_] Object to serialize as an JSON document String
|
1058
|
+
* - *options* [_Hash_] formating options
|
1059
|
+
* - *:indent* [_Fixnum_] format expected
|
1060
|
+
* - *:circular* [_Boolean_] allow circular references, default: false
|
999
1061
|
*/
|
1000
1062
|
static VALUE
|
1001
1063
|
to_stream(int argc, VALUE *argv, VALUE self) {
|
@@ -1009,7 +1071,8 @@ to_stream(int argc, VALUE *argv, VALUE self) {
|
|
1009
1071
|
return Qnil;
|
1010
1072
|
}
|
1011
1073
|
|
1012
|
-
/*
|
1074
|
+
/* Document-method: register_odd
|
1075
|
+
* call-seq: register_odd(clas, create_object, create_method, *members)
|
1013
1076
|
*
|
1014
1077
|
* Registers a class as special. This is useful for working around subclasses of
|
1015
1078
|
* primitive types as is done with ActiveSupport classes. The use of this
|
@@ -1017,13 +1080,10 @@ to_stream(int argc, VALUE *argv, VALUE self) {
|
|
1017
1080
|
* normal way. It is not intended as a hook for changing the output of all
|
1018
1081
|
* classes as it is not optimized for large numbers of classes.
|
1019
1082
|
*
|
1020
|
-
*
|
1021
|
-
*
|
1022
|
-
*
|
1023
|
-
*
|
1024
|
-
* order specified.
|
1025
|
-
* @param [Symbol|String] members methods used to get the member values from
|
1026
|
-
* instances of the clas
|
1083
|
+
* - *clas* [_Class__|_Module_] Class or Module to be made special
|
1084
|
+
* - *create_object* [_Object_] object to call the create method on
|
1085
|
+
* - *create_method* [_Symbol_] method on the clas that will create a new instance of the clas when given all the member values in the order specified.
|
1086
|
+
* - *members* [_Symbol__|_String_] methods used to get the member values from instances of the clas.
|
1027
1087
|
*/
|
1028
1088
|
static VALUE
|
1029
1089
|
register_odd(int argc, VALUE *argv, VALUE self) {
|
@@ -1047,7 +1107,8 @@ register_odd(int argc, VALUE *argv, VALUE self) {
|
|
1047
1107
|
return Qnil;
|
1048
1108
|
}
|
1049
1109
|
|
1050
|
-
/*
|
1110
|
+
/* Document-method: register_odd_raw
|
1111
|
+
* call-seq: register_odd_raw(clas, create_object, create_method, dump_method)
|
1051
1112
|
*
|
1052
1113
|
* Registers a class as special and expect the output to be a string that can be
|
1053
1114
|
* included in the dumped JSON directly. This is useful for working around
|
@@ -1057,13 +1118,10 @@ register_odd(int argc, VALUE *argv, VALUE self) {
|
|
1057
1118
|
* classes as it is not optimized for large numbers of classes. Be careful with
|
1058
1119
|
* this option as the JSON may be incorrect if invalid JSON is returned.
|
1059
1120
|
*
|
1060
|
-
*
|
1061
|
-
*
|
1062
|
-
*
|
1063
|
-
*
|
1064
|
-
* order specified.
|
1065
|
-
* @param [Symbol|String] dump_method method to call on the object being
|
1066
|
-
* serialized to generate the raw JSON.
|
1121
|
+
* - *clas* [_Class_|_Module_] Class or Module to be made special
|
1122
|
+
* - *create_object* [_Object_] object to call the create method on
|
1123
|
+
* - *create_method* [_Symbol_] method on the clas that will create a new instance of the clas when given all the member values in the order specified.
|
1124
|
+
* - *dump_method* [_Symbol_|_String_] method to call on the object being serialized to generate the raw JSON.
|
1067
1125
|
*/
|
1068
1126
|
static VALUE
|
1069
1127
|
register_odd_raw(int argc, VALUE *argv, VALUE self) {
|
@@ -1087,1019 +1145,215 @@ register_odd_raw(int argc, VALUE *argv, VALUE self) {
|
|
1087
1145
|
return Qnil;
|
1088
1146
|
}
|
1089
1147
|
|
1090
|
-
|
1091
|
-
|
1092
|
-
|
1148
|
+
////////////////////////////////////////////////////////////////////////////////
|
1149
|
+
// RDoc entries must be in the same file as the rb_define_method and must be
|
1150
|
+
// directly above the C method function. The extern declaration is enough to
|
1151
|
+
// get it to work.
|
1152
|
+
////////////////////////////////////////////////////////////////////////////////
|
1093
1153
|
|
1094
|
-
|
1095
|
-
|
1096
|
-
|
1097
|
-
|
1098
|
-
|
1099
|
-
|
1100
|
-
|
1101
|
-
|
1154
|
+
/* Document-method: strict_load
|
1155
|
+
* call-seq: strict_load(json, options) { _|_obj, start, len_|_ }
|
1156
|
+
*
|
1157
|
+
* Parses a JSON document String into an Hash, Array, String, Fixnum, Float,
|
1158
|
+
* true, false, or nil. It parses using a mode that is strict in that it maps
|
1159
|
+
* each primitive JSON type to a similar Ruby type. The :create_id is not
|
1160
|
+
* honored in this mode. Note that a Ruby Hash is used to represent the JSON
|
1161
|
+
* Object type. These two are not the same since the JSON Object type can have
|
1162
|
+
* repeating entries with the same key and Ruby Hash can not.
|
1163
|
+
*
|
1164
|
+
* When used with a document that has multiple JSON elements the block, if
|
1165
|
+
* any, will be yielded to. If no block then the last element read will be
|
1166
|
+
* returned.
|
1167
|
+
*
|
1168
|
+
* Raises an exception if the JSON is malformed or the classes specified are not
|
1169
|
+
* valid. If the input is not a valid JSON document (an empty string is not a
|
1170
|
+
* valid JSON document) an exception is raised.
|
1171
|
+
*
|
1172
|
+
* A block can be provided with a single argument. That argument will be the
|
1173
|
+
* parsed JSON document. This is useful when parsing a string that includes
|
1174
|
+
* multiple JSON documents. The block can take up to 3 arguments, the parsed
|
1175
|
+
* object, the position in the string or stream of the start of the JSON for
|
1176
|
+
* that object, and the length of the JSON for that object plus trailing
|
1177
|
+
* whitespace.
|
1178
|
+
*
|
1179
|
+
* - *json* [_String_|_IO_] JSON String or an Object that responds to read().
|
1180
|
+
* - *options* [_Hash_] load options (same as default_options).
|
1181
|
+
* - -
|
1182
|
+
* - *obj* [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_] parsed object.
|
1183
|
+
* - *start* [_optional, _Integer_] start position of parsed JSON for obj.
|
1184
|
+
* - *len* [_optional, _Integer_] length of parsed JSON for obj.
|
1185
|
+
*
|
1186
|
+
* Returns [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_]
|
1187
|
+
*/
|
1188
|
+
extern VALUE oj_strict_parse(int argc, VALUE *argv, VALUE self);
|
1102
1189
|
|
1103
|
-
/* Document-
|
1104
|
-
*
|
1105
|
-
*
|
1106
|
-
*
|
1107
|
-
*
|
1108
|
-
*
|
1109
|
-
*
|
1110
|
-
*
|
1190
|
+
/* Document-method: compat_load
|
1191
|
+
* call-seq: compat_load(json, options) { _|_obj, start, len_|_ }
|
1192
|
+
*
|
1193
|
+
* Parses a JSON document String into an Object, Hash, Array, String, Fixnum,
|
1194
|
+
* Float, true, false, or nil. It parses using a mode that is generally
|
1195
|
+
* compatible with other Ruby JSON parsers in that it will create objects based
|
1196
|
+
* on the :create_id value. It is not compatible in every way to every other
|
1197
|
+
* parser though as each parser has it's own variations.
|
1198
|
+
*
|
1199
|
+
* When used with a document that has multiple JSON elements the block, if
|
1200
|
+
* any, will be yielded to. If no block then the last element read will be
|
1201
|
+
* returned.
|
1202
|
+
*
|
1203
|
+
* Raises an exception if the JSON is malformed or the classes specified are not
|
1204
|
+
* valid. If the input is not a valid JSON document (an empty string is not a
|
1205
|
+
* valid JSON document) an exception is raised.
|
1206
|
+
*
|
1207
|
+
* A block can be provided with a single argument. That argument will be the
|
1208
|
+
* parsed JSON document. This is useful when parsing a string that includes
|
1209
|
+
* multiple JSON documents. The block can take up to 3 arguments, the parsed
|
1210
|
+
* object, the position in the string or stream of the start of the JSON for
|
1211
|
+
* that object, and the length of the JSON for that object plus trailing
|
1212
|
+
* whitespace.
|
1213
|
+
*
|
1214
|
+
* - *json* [_String_|_IO_] JSON String or an Object that responds to read().
|
1215
|
+
* - *options* [_Hash_] load options (same as default_options).
|
1216
|
+
* - -
|
1217
|
+
* - *obj* [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_] parsed object.
|
1218
|
+
* - *start* [_optional, _Integer_] start position of parsed JSON for obj.
|
1219
|
+
* - *len* [_optional, _Integer_] length of parsed JSON for obj.
|
1220
|
+
*
|
1221
|
+
* Returns [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_]
|
1111
1222
|
*/
|
1223
|
+
extern VALUE oj_compat_parse(int argc, VALUE *argv, VALUE self);
|
1112
1224
|
|
1113
|
-
|
1114
|
-
|
1115
|
-
|
1116
|
-
|
1117
|
-
|
1118
|
-
|
1119
|
-
|
1120
|
-
|
1121
|
-
|
1122
|
-
|
1123
|
-
|
1124
|
-
|
1125
|
-
|
1126
|
-
|
1127
|
-
|
1128
|
-
|
1129
|
-
|
1130
|
-
|
1131
|
-
|
1132
|
-
|
1225
|
+
/* Document-method: object_load
|
1226
|
+
* call-seq: object_load(json, options) { _|_obj, start, len_|_ }
|
1227
|
+
*
|
1228
|
+
* Parses a JSON document String into an Object, Hash, Array, String, Fixnum,
|
1229
|
+
* Float, true, false, or nil. In the :object mode the JSON should have been
|
1230
|
+
* generated by Oj.dump(). The parser will reconstitute the original marshalled
|
1231
|
+
* or dumped Object. The :auto_define and :circular options have meaning with
|
1232
|
+
* this parsing mode.
|
1233
|
+
*
|
1234
|
+
* Raises an exception if the JSON is malformed or the classes specified are not
|
1235
|
+
* valid. If the input is not a valid JSON document (an empty string is not a
|
1236
|
+
* valid JSON document) an exception is raised.
|
1237
|
+
*
|
1238
|
+
* Note: Oj is not able to automatically deserialize all classes that are a
|
1239
|
+
* subclass of a Ruby Exception. Only exception that take one required string
|
1240
|
+
* argument in the initialize() method are supported. This is an example of how
|
1241
|
+
* to write an Exception subclass that supports both a single string intializer
|
1242
|
+
* and an Exception as an argument. Additional optional arguments can be added
|
1243
|
+
* as well.
|
1244
|
+
*
|
1245
|
+
* The reason for this restriction has to do with a design decision on the part
|
1246
|
+
* of the Ruby developers. Exceptions are special Objects. They do not follow the
|
1247
|
+
* rules of other Objects. Exceptions have 'mesg' and a 'bt' attribute. Note that
|
1248
|
+
* these are not '@mesg' and '@bt'. They can not be set using the normal C or
|
1249
|
+
* Ruby calls. The only way I have found to set the 'mesg' attribute is through
|
1250
|
+
* the initializer. Unfortunately that means any subclass that provides a
|
1251
|
+
* different initializer can not be automatically decoded. A way around this is
|
1252
|
+
* to use a create function but this example shows an alternative.
|
1253
|
+
*
|
1254
|
+
* A block can be provided with a single argument. That argument will be the
|
1255
|
+
* parsed JSON document. This is useful when parsing a string that includes
|
1256
|
+
* multiple JSON documents. The block can take up to 3 arguments, the parsed
|
1257
|
+
* object, the position in the string or stream of the start of the JSON for
|
1258
|
+
* that object, and the length of the JSON for that object plus trailing
|
1259
|
+
* whitespace.
|
1260
|
+
*
|
1261
|
+
* - *json* [_String_|_IO_] JSON String or an Object that responds to read().
|
1262
|
+
* - *options* [_Hash_] load options (same as default_options).
|
1263
|
+
* - -
|
1264
|
+
* - *obj* [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_] parsed object.
|
1265
|
+
* - *start* [_optional, _Integer_] start position of parsed JSON for obj.
|
1266
|
+
* - *len* [_optional, _Integer_] length of parsed JSON for obj.
|
1267
|
+
*
|
1268
|
+
* Returns [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_]
|
1269
|
+
*/
|
1270
|
+
extern VALUE oj_object_parse(int argc, VALUE *argv, VALUE self);
|
1133
1271
|
|
1134
|
-
/*
|
1272
|
+
/* Document-method: add_to_json
|
1273
|
+
* call-seq: add_to_json(*args)
|
1274
|
+
*
|
1275
|
+
* Override simple to_s dump behavior in :compat mode to instead use an
|
1276
|
+
* optimized dump that includes the classname and attributes so that the
|
1277
|
+
* object can be re-created on load. The format is the same as the json gem
|
1278
|
+
* but does not use the ruby methods for encoding.
|
1279
|
+
*
|
1280
|
+
* The classes supported for optimization are: Array, BigDecimal, Complex,
|
1281
|
+
* Date, DateTime, Exception, Hash, Integer, OpenStruct, Range, Rational,
|
1282
|
+
* Regexp, Struct, and Time. Providing no classes will result in all those
|
1283
|
+
* classes being optimized.q
|
1135
1284
|
*
|
1136
|
-
*
|
1137
|
-
* @param [Hash] options formating options
|
1285
|
+
* - *args( [_Class_] zero or more classes to optimize.
|
1138
1286
|
*/
|
1139
|
-
|
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;
|
1287
|
+
extern VALUE oj_add_to_json(int argc, VALUE *argv, VALUE self);
|
1148
1288
|
|
1149
|
-
|
1150
|
-
|
1289
|
+
/* @!method remove_to_json(*args)
|
1290
|
+
*
|
1291
|
+
* Reverts back to the to_s dump behavior in :compat mode to instead use an
|
1292
|
+
* optimized dump that includes the classname and attributes so that the
|
1293
|
+
* object can be re-created on load. The format is the same as the json gem
|
1294
|
+
* but does not use the ruby methods for encoding.
|
1295
|
+
*
|
1296
|
+
* The classes supported for optimization are: Array, BigDecimal, Complex,
|
1297
|
+
* Date, DateTime, Exception, Hash, Integer, OpenStruct, Range, Rational,
|
1298
|
+
* Regexp, Struct, and Time. Providing no classes will result in all those
|
1299
|
+
* classes being reverted from the optimized mode.
|
1300
|
+
*
|
1301
|
+
* - *args* [_Class_] zero or more classes to optimize.
|
1302
|
+
*/
|
1303
|
+
extern VALUE oj_remove_to_json(int argc, VALUE *argv, VALUE self);
|
1151
1304
|
|
1152
|
-
/*
|
1305
|
+
/* Document-method: mimic_JSON
|
1306
|
+
* call-seq: mimic_JSON()
|
1307
|
+
*
|
1308
|
+
* Creates the JSON module with methods and classes to mimic the JSON gem. After
|
1309
|
+
* this method is invoked calls that expect the JSON module will use Oj instead
|
1310
|
+
* and be faster than the original JSON. Most options that could be passed to
|
1311
|
+
* the JSON methods are supported. The calls to set parser or generator will not
|
1312
|
+
* raise an Exception but will not have any effect. The method can also be
|
1313
|
+
* called after the json gem is loaded. The necessary methods on the json gem
|
1314
|
+
* will be replaced with Oj methods.
|
1315
|
+
*
|
1316
|
+
* Note that this also sets the default options of :mode to :compat and
|
1317
|
+
* :encoding to :ascii.
|
1153
1318
|
*
|
1154
|
-
*
|
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
|
1319
|
+
* Returns [_Module_] the JSON module.
|
1158
1320
|
*/
|
1159
|
-
|
1160
|
-
|
1161
|
-
|
1321
|
+
extern VALUE oj_define_mimic_json(int argc, VALUE *argv, VALUE self);
|
1322
|
+
|
1323
|
+
/* Document-method: generate
|
1324
|
+
* call-seq: generate(obj, opts=nil)
|
1325
|
+
*
|
1326
|
+
* Encode obj as a JSON String. The obj argument must be a Hash, Array, or
|
1327
|
+
* respond to to_h or to_json. Options other than those listed such as
|
1328
|
+
* +:allow_nan+ or +:max_nesting+ are ignored.
|
1329
|
+
*
|
1330
|
+
* - *obj* [_Object__|_Hash_|_Array_] object to convert to a JSON String
|
1331
|
+
* - *opts* [_Hash_] options
|
1332
|
+
* - - *:indent* [_String_] String to use for indentation.
|
1333
|
+
* - *:space* [_String_] String placed after a , or : delimiter
|
1334
|
+
* - *:space * _before [_String_] String placed before a : delimiter
|
1335
|
+
* - *:object_nl* [_String_] String placed after a JSON object
|
1336
|
+
* - *:array_nl* [_String_] String placed after a JSON array
|
1337
|
+
* - *: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.
|
1338
|
+
*
|
1339
|
+
* Returns [_String_]generated JSON.
|
1340
|
+
*/
|
1341
|
+
extern VALUE oj_mimic_generate(int argc, VALUE *argv, VALUE self);
|
1162
1342
|
|
1163
|
-
|
1164
|
-
|
1343
|
+
/*
|
1344
|
+
extern void oj_hash_test();
|
1165
1345
|
|
1346
|
+
static VALUE
|
1347
|
+
hash_test(VALUE self) {
|
1348
|
+
oj_hash_test();
|
1166
1349
|
return Qnil;
|
1167
1350
|
}
|
1351
|
+
*/
|
1168
1352
|
|
1169
|
-
|
1170
|
-
*
|
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
|
-
*/
|
1353
|
+
#if !HAS_ENCODING_SUPPORT
|
1175
1354
|
static VALUE
|
1176
|
-
|
1177
|
-
|
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)
|
1203
|
-
*
|
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)
|
1236
|
-
*
|
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)
|
1263
|
-
*
|
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
|
1269
|
-
*/
|
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
|
-
}
|
1291
|
-
|
1292
|
-
/* call-seq: pop()
|
1293
|
-
*
|
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()
|
1304
|
-
*
|
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()
|
1316
|
-
*
|
1317
|
-
* Reset the writer back to the empty state.
|
1318
|
-
*/
|
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
|
-
}
|
1331
|
-
|
1332
|
-
/* call-seq: to_s()
|
1333
|
-
*
|
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)
|
1395
|
-
*
|
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)
|
1438
|
-
*
|
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)
|
1456
|
-
*
|
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)
|
1487
|
-
*
|
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
|
1491
|
-
*/
|
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
|
-
}
|
1516
|
-
|
1517
|
-
/* call-seq: push_value(value, key=nil)
|
1518
|
-
*
|
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)
|
1549
|
-
*
|
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
|
1555
|
-
*/
|
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
|
-
}
|
1581
|
-
|
1582
|
-
/* call-seq: pop()
|
1583
|
-
*
|
1584
|
-
* Pops up a level in the JSON document closing the array or object that is
|
1585
|
-
* currently open.
|
1586
|
-
*/
|
1587
|
-
static VALUE
|
1588
|
-
stream_writer_pop(VALUE self) {
|
1589
|
-
StreamWriter sw = (StreamWriter)DATA_PTR(self);
|
1590
|
-
|
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()
|
1598
|
-
*
|
1599
|
-
* Pops all level in the JSON document closing all the array or object that is
|
1600
|
-
* currently open.
|
1601
|
-
*/
|
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
|
-
|
1983
|
-
|
1984
|
-
/* Document-method: mimic_JSON
|
1985
|
-
* call-seq: mimic_JSON() => Module
|
1986
|
-
*
|
1987
|
-
* Creates the JSON module with methods and classes to mimic the JSON gem. After
|
1988
|
-
* this method is invoked calls that expect the JSON module will use Oj instead
|
1989
|
-
* and be faster than the original JSON. Most options that could be passed to
|
1990
|
-
* the JSON methods are supported. The calls to set parser or generator will not
|
1991
|
-
* raise an Exception but will not have any effect. The method can also be
|
1992
|
-
* called after the json gem is loaded. The necessary methods on the json gem
|
1993
|
-
* will be replaced with Oj methods.
|
1994
|
-
*
|
1995
|
-
* Note that this also sets the default options of :mode to :compat and
|
1996
|
-
* :encoding to :ascii.
|
1997
|
-
*/
|
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);
|
2060
|
-
|
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;
|
2085
|
-
|
2086
|
-
return mimic;
|
2087
|
-
}
|
2088
|
-
|
2089
|
-
/*
|
2090
|
-
extern void oj_hash_test();
|
2091
|
-
|
2092
|
-
static VALUE
|
2093
|
-
hash_test(VALUE self) {
|
2094
|
-
oj_hash_test();
|
2095
|
-
return Qnil;
|
2096
|
-
}
|
2097
|
-
*/
|
2098
|
-
|
2099
|
-
#if !HAS_ENCODING_SUPPORT
|
2100
|
-
static VALUE
|
2101
|
-
iconv_encoder(VALUE x) {
|
2102
|
-
VALUE iconv;
|
1355
|
+
iconv_encoder(VALUE x) {
|
1356
|
+
VALUE iconv;
|
2103
1357
|
|
2104
1358
|
rb_require("iconv");
|
2105
1359
|
iconv = rb_const_get(rb_cObject, rb_intern("Iconv"));
|
@@ -2120,36 +1374,43 @@ protect_require(VALUE x) {
|
|
2120
1374
|
return Qnil;
|
2121
1375
|
}
|
2122
1376
|
|
2123
|
-
|
1377
|
+
/* Document-module: Oj
|
1378
|
+
*
|
1379
|
+
* Optimized JSON (Oj), as the name implies was written to provide speed
|
1380
|
+
* optimized JSON handling.
|
1381
|
+
*
|
1382
|
+
* Oj uses modes to control how object are encoded and decoded. In addition
|
1383
|
+
* global and options to methods allow additional behavior modifications. The
|
1384
|
+
* modes are:
|
1385
|
+
*
|
1386
|
+
* - *:strict* mode will only allow the 7 basic JSON types to be serialized. Any other Object
|
1387
|
+
* will raise an Exception.
|
1388
|
+
*
|
1389
|
+
* - *:null* mode is similar to the :strict mode except any Object that is not
|
1390
|
+
* one of the JSON base types is replaced by a JSON null.
|
1391
|
+
*
|
1392
|
+
* - *:object* mode will dump any Object as a JSON Object with keys that match
|
1393
|
+
* the Ruby Object's variable names without the '@' character. This is the
|
1394
|
+
* highest performance mode.
|
1395
|
+
*
|
1396
|
+
* - *:compat* or *:json* mode is the compatible mode for the json gem. It mimics
|
1397
|
+
* the json gem including the options, defaults, and restrictions.
|
1398
|
+
*
|
1399
|
+
* - *:rails* is the compatibility mode for Rails or Active support.
|
1400
|
+
*
|
1401
|
+
* - *:custom* is the most configurable mode.
|
1402
|
+
*/
|
1403
|
+
void
|
1404
|
+
Init_oj() {
|
2124
1405
|
int err = 0;
|
2125
1406
|
|
2126
1407
|
Oj = rb_define_module("Oj");
|
2127
1408
|
|
2128
1409
|
oj_cstack_class = rb_define_class_under(Oj, "CStack", rb_cObject);
|
2129
1410
|
|
2130
|
-
|
2131
|
-
|
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);
|
1411
|
+
oj_string_writer_init();
|
1412
|
+
oj_stream_writer_init();
|
2151
1413
|
|
2152
|
-
rb_require("time");
|
2153
1414
|
rb_require("date");
|
2154
1415
|
// On Rubinius the require fails but can be done from a ruby file.
|
2155
1416
|
rb_protect(protect_require, Qnil, &err);
|
@@ -2170,7 +1431,7 @@ void Init_oj() {
|
|
2170
1431
|
rb_define_module_function(Oj, "default_options", get_def_opts, 0);
|
2171
1432
|
rb_define_module_function(Oj, "default_options=", set_def_opts, 1);
|
2172
1433
|
|
2173
|
-
rb_define_module_function(Oj, "mimic_JSON",
|
1434
|
+
rb_define_module_function(Oj, "mimic_JSON", oj_define_mimic_json, -1);
|
2174
1435
|
rb_define_module_function(Oj, "load", load, -1);
|
2175
1436
|
rb_define_module_function(Oj, "load_file", load_file, -1);
|
2176
1437
|
rb_define_module_function(Oj, "safe_load", safe_load, 1);
|
@@ -2179,8 +1440,17 @@ void Init_oj() {
|
|
2179
1440
|
rb_define_module_function(Oj, "object_load", oj_object_parse, -1);
|
2180
1441
|
|
2181
1442
|
rb_define_module_function(Oj, "dump", dump, -1);
|
1443
|
+
|
2182
1444
|
rb_define_module_function(Oj, "to_file", to_file, -1);
|
2183
1445
|
rb_define_module_function(Oj, "to_stream", to_stream, -1);
|
1446
|
+
// JSON gem compatibility
|
1447
|
+
rb_define_module_function(Oj, "to_json", to_json, -1);
|
1448
|
+
rb_define_module_function(Oj, "generate", oj_mimic_generate, -1);
|
1449
|
+
rb_define_module_function(Oj, "fast_generate", oj_mimic_generate, -1);
|
1450
|
+
|
1451
|
+
rb_define_module_function(Oj, "add_to_json", oj_add_to_json, -1);
|
1452
|
+
rb_define_module_function(Oj, "remove_to_json", oj_remove_to_json, -1);
|
1453
|
+
|
2184
1454
|
rb_define_module_function(Oj, "register_odd", register_odd, -1);
|
2185
1455
|
rb_define_module_function(Oj, "register_odd_raw", register_odd_raw, -1);
|
2186
1456
|
|
@@ -2193,6 +1463,9 @@ void Init_oj() {
|
|
2193
1463
|
oj_array_start_id = rb_intern("array_start");
|
2194
1464
|
oj_as_json_id = rb_intern("as_json");
|
2195
1465
|
oj_error_id = rb_intern("error");
|
1466
|
+
oj_begin_id = rb_intern("begin");
|
1467
|
+
oj_end_id = rb_intern("end");
|
1468
|
+
oj_exclude_end_id = rb_intern("exclude_end?");
|
2196
1469
|
oj_file_id = rb_intern("file?");
|
2197
1470
|
oj_fileno_id = rb_intern("fileno");
|
2198
1471
|
oj_ftype_id = rb_intern("ftype");
|
@@ -2213,6 +1486,7 @@ void Init_oj() {
|
|
2213
1486
|
oj_stat_id = rb_intern("stat");
|
2214
1487
|
oj_string_id = rb_intern("string");
|
2215
1488
|
oj_to_hash_id = rb_intern("to_hash");
|
1489
|
+
oj_to_h_id = rb_intern("to_h");
|
2216
1490
|
oj_to_json_id = rb_intern("to_json");
|
2217
1491
|
oj_to_s_id = rb_intern("to_s");
|
2218
1492
|
oj_to_sym_id = rb_intern("to_sym");
|
@@ -2224,7 +1498,7 @@ void Init_oj() {
|
|
2224
1498
|
oj_utc_offset_id = rb_intern("utc_offset");
|
2225
1499
|
oj_utcq_id = rb_intern("utc?");
|
2226
1500
|
oj_write_id = rb_intern("write");
|
2227
|
-
|
1501
|
+
oj_has_key_id = rb_intern("has_key?");
|
2228
1502
|
|
2229
1503
|
rb_require("oj/bag");
|
2230
1504
|
rb_require("oj/error");
|
@@ -2236,64 +1510,78 @@ void Init_oj() {
|
|
2236
1510
|
oj_bigdecimal_class = rb_const_get(rb_cObject, rb_intern("BigDecimal"));
|
2237
1511
|
oj_date_class = rb_const_get(rb_cObject, rb_intern("Date"));
|
2238
1512
|
oj_datetime_class = rb_const_get(rb_cObject, rb_intern("DateTime"));
|
1513
|
+
oj_enumerable_class = rb_const_get(rb_cObject, rb_intern("Enumerable"));
|
2239
1514
|
oj_parse_error_class = rb_const_get_at(Oj, rb_intern("ParseError"));
|
2240
1515
|
oj_stringio_class = rb_const_get(rb_cObject, rb_intern("StringIO"));
|
2241
1516
|
oj_struct_class = rb_const_get(rb_cObject, rb_intern("Struct"));
|
2242
|
-
|
2243
|
-
|
2244
|
-
|
2245
|
-
|
2246
|
-
|
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);
|
1517
|
+
oj_json_parser_error_class = rb_eEncodingError; // replaced if mimic is called
|
1518
|
+
oj_json_generator_error_class = rb_eEncodingError; // replaced if mimic is called
|
1519
|
+
|
1520
|
+
allow_blank_sym = ID2SYM(rb_intern("allow_blank")); rb_gc_register_address(&allow_blank_sym);
|
1521
|
+
allow_gc_sym = ID2SYM(rb_intern("allow_gc")); rb_gc_register_address(&allow_gc_sym);
|
2274
1522
|
allow_invalid_unicode_sym = ID2SYM(rb_intern("allow_invalid_unicode"));rb_gc_register_address(&allow_invalid_unicode_sym);
|
2275
|
-
|
2276
|
-
|
2277
|
-
|
2278
|
-
|
2279
|
-
|
2280
|
-
|
2281
|
-
|
2282
|
-
|
2283
|
-
|
2284
|
-
|
2285
|
-
|
2286
|
-
|
2287
|
-
|
2288
|
-
|
2289
|
-
|
2290
|
-
|
2291
|
-
|
1523
|
+
ascii_sym = ID2SYM(rb_intern("ascii")); rb_gc_register_address(&ascii_sym);
|
1524
|
+
auto_define_sym = ID2SYM(rb_intern("auto_define")); rb_gc_register_address(&auto_define_sym);
|
1525
|
+
auto_sym = ID2SYM(rb_intern("auto")); rb_gc_register_address(&auto_sym);
|
1526
|
+
bigdecimal_as_decimal_sym = ID2SYM(rb_intern("bigdecimal_as_decimal"));rb_gc_register_address(&bigdecimal_as_decimal_sym);
|
1527
|
+
bigdecimal_load_sym = ID2SYM(rb_intern("bigdecimal_load")); rb_gc_register_address(&bigdecimal_load_sym);
|
1528
|
+
bigdecimal_sym = ID2SYM(rb_intern("bigdecimal")); rb_gc_register_address(&bigdecimal_sym);
|
1529
|
+
circular_sym = ID2SYM(rb_intern("circular")); rb_gc_register_address(&circular_sym);
|
1530
|
+
class_cache_sym = ID2SYM(rb_intern("class_cache")); rb_gc_register_address(&class_cache_sym);
|
1531
|
+
compat_sym = ID2SYM(rb_intern("compat")); rb_gc_register_address(&compat_sym);
|
1532
|
+
create_id_sym = ID2SYM(rb_intern("create_id")); rb_gc_register_address(&create_id_sym);
|
1533
|
+
custom_sym = ID2SYM(rb_intern("custom")); rb_gc_register_address(&custom_sym);
|
1534
|
+
empty_string_sym = ID2SYM(rb_intern("empty_string")); rb_gc_register_address(&empty_string_sym);
|
1535
|
+
escape_mode_sym = ID2SYM(rb_intern("escape_mode")); rb_gc_register_address(&escape_mode_sym);
|
1536
|
+
float_prec_sym = ID2SYM(rb_intern("float_precision")); rb_gc_register_address(&float_prec_sym);
|
1537
|
+
float_sym = ID2SYM(rb_intern("float")); rb_gc_register_address(&float_sym);
|
1538
|
+
huge_sym = ID2SYM(rb_intern("huge")); rb_gc_register_address(&huge_sym);
|
1539
|
+
json_sym = ID2SYM(rb_intern("json")); rb_gc_register_address(&json_sym);
|
1540
|
+
match_string_sym = ID2SYM(rb_intern("match_string")); rb_gc_register_address(&match_string_sym);
|
1541
|
+
mode_sym = ID2SYM(rb_intern("mode")); rb_gc_register_address(&mode_sym);
|
1542
|
+
nan_sym = ID2SYM(rb_intern("nan")); rb_gc_register_address(&nan_sym);
|
1543
|
+
newline_sym = ID2SYM(rb_intern("newline")); rb_gc_register_address(&newline_sym);
|
1544
|
+
nilnil_sym = ID2SYM(rb_intern("nilnil")); rb_gc_register_address(&nilnil_sym);
|
1545
|
+
null_sym = ID2SYM(rb_intern("null")); rb_gc_register_address(&null_sym);
|
1546
|
+
object_sym = ID2SYM(rb_intern("object")); rb_gc_register_address(&object_sym);
|
1547
|
+
oj_allow_nan_sym = ID2SYM(rb_intern("allow_nan")); rb_gc_register_address(&oj_allow_nan_sym);
|
1548
|
+
oj_array_class_sym = ID2SYM(rb_intern("array_class")); rb_gc_register_address(&oj_array_class_sym);
|
1549
|
+
oj_array_nl_sym = ID2SYM(rb_intern("array_nl")); rb_gc_register_address(&oj_array_nl_sym);
|
1550
|
+
oj_ascii_only_sym = ID2SYM(rb_intern("ascii_only")); rb_gc_register_address(&oj_ascii_only_sym);
|
1551
|
+
oj_create_additions_sym = ID2SYM(rb_intern("create_additions"));rb_gc_register_address(&oj_create_additions_sym);
|
1552
|
+
oj_hash_class_sym = ID2SYM(rb_intern("hash_class")); rb_gc_register_address(&oj_hash_class_sym);
|
1553
|
+
oj_indent_sym = ID2SYM(rb_intern("indent")); rb_gc_register_address(&oj_indent_sym);
|
1554
|
+
oj_max_nesting_sym = ID2SYM(rb_intern("max_nesting")); rb_gc_register_address(&oj_max_nesting_sym);
|
1555
|
+
oj_object_class_sym = ID2SYM(rb_intern("object_class")); rb_gc_register_address(&oj_object_class_sym);
|
1556
|
+
oj_object_nl_sym = ID2SYM(rb_intern("object_nl")); rb_gc_register_address(&oj_object_nl_sym);
|
1557
|
+
oj_quirks_mode_sym = ID2SYM(rb_intern("quirks_mode")); rb_gc_register_address(&oj_quirks_mode_sym);
|
1558
|
+
oj_space_before_sym = ID2SYM(rb_intern("space_before")); rb_gc_register_address(&oj_space_before_sym);
|
1559
|
+
oj_space_sym = ID2SYM(rb_intern("space")); rb_gc_register_address(&oj_space_sym);
|
1560
|
+
omit_nil_sym = ID2SYM(rb_intern("omit_nil")); rb_gc_register_address(&omit_nil_sym);
|
1561
|
+
rails_sym = ID2SYM(rb_intern("rails")); rb_gc_register_address(&rails_sym);
|
1562
|
+
raise_sym = ID2SYM(rb_intern("raise")); rb_gc_register_address(&raise_sym);
|
1563
|
+
ruby_sym = ID2SYM(rb_intern("ruby")); rb_gc_register_address(&ruby_sym);
|
1564
|
+
sec_prec_sym = ID2SYM(rb_intern("second_precision")); rb_gc_register_address(&sec_prec_sym);
|
1565
|
+
strict_sym = ID2SYM(rb_intern("strict")); rb_gc_register_address(&strict_sym);
|
1566
|
+
symbol_keys_sym = ID2SYM(rb_intern("symbol_keys")); rb_gc_register_address(&symbol_keys_sym);
|
1567
|
+
time_format_sym = ID2SYM(rb_intern("time_format")); rb_gc_register_address(&time_format_sym);
|
1568
|
+
unicode_xss_sym = ID2SYM(rb_intern("unicode_xss")); rb_gc_register_address(&unicode_xss_sym);
|
1569
|
+
unix_sym = ID2SYM(rb_intern("unix")); rb_gc_register_address(&unix_sym);
|
1570
|
+
unix_zone_sym = ID2SYM(rb_intern("unix_zone")); rb_gc_register_address(&unix_zone_sym);
|
1571
|
+
use_as_json_sym = ID2SYM(rb_intern("use_as_json")); rb_gc_register_address(&use_as_json_sym);
|
1572
|
+
use_to_hash_sym = ID2SYM(rb_intern("use_to_hash")); rb_gc_register_address(&use_to_hash_sym);
|
1573
|
+
use_to_json_sym = ID2SYM(rb_intern("use_to_json")); rb_gc_register_address(&use_to_json_sym);
|
1574
|
+
word_sym = ID2SYM(rb_intern("word")); rb_gc_register_address(&word_sym);
|
1575
|
+
xmlschema_sym = ID2SYM(rb_intern("xmlschema")); rb_gc_register_address(&xmlschema_sym);
|
1576
|
+
xss_safe_sym = ID2SYM(rb_intern("xss_safe")); rb_gc_register_address(&xss_safe_sym);
|
1577
|
+
|
1578
|
+
oj_slash_string = rb_str_new2("/"); rb_gc_register_address(&oj_slash_string);
|
2292
1579
|
|
2293
1580
|
oj_default_options.mode = ObjectMode;
|
2294
1581
|
|
2295
1582
|
oj_hash_init();
|
2296
1583
|
oj_odd_init();
|
1584
|
+
oj_mimic_rails_init();
|
2297
1585
|
|
2298
1586
|
#if USE_PTHREAD_MUTEX
|
2299
1587
|
pthread_mutex_init(&oj_cache_mutex, 0);
|
@@ -2304,139 +1592,3 @@ void Init_oj() {
|
|
2304
1592
|
oj_init_doc();
|
2305
1593
|
}
|
2306
1594
|
|
2307
|
-
// mimic JSON documentation
|
2308
|
-
|
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
|
-
*/
|