oj 3.13.11 → 3.15.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/CHANGELOG.md +74 -0
- data/README.md +4 -2
- data/ext/oj/buf.h +11 -6
- data/ext/oj/cache.c +25 -24
- data/ext/oj/cache8.c +10 -9
- data/ext/oj/circarray.c +8 -6
- data/ext/oj/circarray.h +2 -2
- data/ext/oj/code.c +17 -24
- data/ext/oj/code.h +2 -2
- data/ext/oj/compat.c +17 -44
- data/ext/oj/custom.c +70 -141
- data/ext/oj/debug.c +3 -9
- data/ext/oj/dump.c +128 -118
- data/ext/oj/dump.h +12 -8
- data/ext/oj/dump_compat.c +564 -641
- data/ext/oj/dump_leaf.c +17 -63
- data/ext/oj/dump_object.c +70 -199
- data/ext/oj/dump_strict.c +22 -46
- data/ext/oj/encoder.c +1 -1
- data/ext/oj/err.c +2 -13
- data/ext/oj/err.h +9 -12
- data/ext/oj/extconf.rb +14 -5
- data/ext/oj/fast.c +75 -103
- data/ext/oj/intern.c +52 -50
- data/ext/oj/intern.h +4 -8
- data/ext/oj/mem.c +318 -0
- data/ext/oj/mem.h +53 -0
- data/ext/oj/mimic_json.c +75 -47
- data/ext/oj/object.c +49 -66
- data/ext/oj/odd.c +89 -67
- data/ext/oj/odd.h +15 -15
- data/ext/oj/oj.c +140 -99
- data/ext/oj/oj.h +80 -51
- data/ext/oj/parse.c +162 -184
- data/ext/oj/parse.h +7 -10
- data/ext/oj/parser.c +89 -34
- data/ext/oj/parser.h +18 -7
- data/ext/oj/rails.c +82 -146
- data/ext/oj/rails.h +1 -1
- data/ext/oj/reader.c +11 -12
- data/ext/oj/reader.h +4 -2
- data/ext/oj/resolve.c +3 -4
- data/ext/oj/rxclass.c +6 -5
- data/ext/oj/rxclass.h +1 -1
- data/ext/oj/saj.c +20 -31
- data/ext/oj/saj2.c +329 -93
- data/ext/oj/saj2.h +23 -0
- data/ext/oj/scp.c +3 -14
- data/ext/oj/sparse.c +26 -70
- data/ext/oj/stream_writer.c +12 -22
- data/ext/oj/strict.c +20 -52
- data/ext/oj/string_writer.c +21 -21
- data/ext/oj/trace.h +31 -4
- data/ext/oj/usual.c +105 -150
- data/ext/oj/usual.h +68 -0
- data/ext/oj/util.h +1 -1
- data/ext/oj/val_stack.c +1 -1
- data/ext/oj/val_stack.h +8 -7
- data/ext/oj/validate.c +21 -26
- data/ext/oj/wab.c +31 -68
- data/lib/oj/active_support_helper.rb +0 -1
- data/lib/oj/bag.rb +7 -1
- data/lib/oj/easy_hash.rb +4 -5
- data/lib/oj/error.rb +0 -1
- data/lib/oj/json.rb +4 -2
- data/lib/oj/mimic.rb +4 -2
- data/lib/oj/saj.rb +20 -6
- data/lib/oj/state.rb +9 -6
- data/lib/oj/version.rb +1 -2
- data/lib/oj.rb +2 -0
- data/pages/Compatibility.md +1 -1
- data/pages/InstallOptions.md +20 -0
- data/pages/Options.md +10 -0
- data/test/_test_active.rb +8 -9
- data/test/_test_active_mimic.rb +7 -8
- data/test/_test_mimic_rails.rb +17 -20
- data/test/activerecord/result_test.rb +5 -6
- data/test/{activesupport5 → activesupport7}/abstract_unit.rb +16 -12
- data/test/{activesupport5 → activesupport7}/decoding_test.rb +2 -10
- data/test/{activesupport5 → activesupport7}/encoding_test.rb +20 -34
- data/test/{activesupport5 → activesupport7}/encoding_test_cases.rb +6 -0
- data/test/{activesupport5 → activesupport7}/time_zone_test_helpers.rb +8 -0
- data/test/files.rb +15 -15
- data/test/foo.rb +9 -71
- data/test/helper.rb +11 -8
- data/test/isolated/shared.rb +3 -2
- data/test/json_gem/json_addition_test.rb +2 -2
- data/test/json_gem/json_common_interface_test.rb +4 -4
- data/test/json_gem/json_encoding_test.rb +0 -0
- data/test/json_gem/json_ext_parser_test.rb +1 -0
- data/test/json_gem/json_fixtures_test.rb +3 -2
- data/test/json_gem/json_generator_test.rb +48 -36
- data/test/json_gem/json_generic_object_test.rb +11 -11
- data/test/json_gem/json_parser_test.rb +54 -47
- data/test/json_gem/json_string_matching_test.rb +9 -9
- data/test/json_gem/test_helper.rb +7 -3
- data/test/mem.rb +13 -12
- data/test/perf.rb +21 -26
- data/test/perf_compat.rb +31 -33
- data/test/perf_dump.rb +50 -0
- data/test/perf_fast.rb +80 -82
- data/test/perf_file.rb +27 -29
- data/test/perf_object.rb +65 -69
- data/test/perf_once.rb +12 -11
- data/test/perf_parser.rb +42 -48
- data/test/perf_saj.rb +46 -54
- data/test/perf_scp.rb +57 -69
- data/test/perf_simple.rb +41 -39
- data/test/perf_strict.rb +68 -70
- data/test/perf_wab.rb +67 -69
- data/test/prec.rb +3 -3
- data/test/sample/change.rb +0 -1
- data/test/sample/dir.rb +0 -1
- data/test/sample/doc.rb +0 -1
- data/test/sample/file.rb +0 -1
- data/test/sample/group.rb +0 -1
- data/test/sample/hasprops.rb +0 -1
- data/test/sample/layer.rb +0 -1
- data/test/sample/rect.rb +0 -1
- data/test/sample/shape.rb +0 -1
- data/test/sample/text.rb +0 -1
- data/test/sample.rb +16 -16
- data/test/sample_json.rb +8 -8
- data/test/test_compat.rb +76 -42
- data/test/test_custom.rb +72 -51
- data/test/test_debian.rb +7 -10
- data/test/test_fast.rb +86 -90
- data/test/test_file.rb +41 -30
- data/test/test_gc.rb +16 -5
- data/test/test_generate.rb +5 -5
- data/test/test_hash.rb +4 -4
- data/test/test_integer_range.rb +9 -9
- data/test/test_null.rb +20 -20
- data/test/test_object.rb +85 -96
- data/test/test_parser.rb +6 -22
- data/test/test_parser_debug.rb +27 -0
- data/test/test_parser_saj.rb +115 -23
- data/test/test_parser_usual.rb +6 -6
- data/test/test_rails.rb +2 -2
- data/test/test_saj.rb +10 -8
- data/test/test_scp.rb +37 -39
- data/test/test_strict.rb +30 -32
- data/test/test_various.rb +147 -99
- data/test/test_wab.rb +48 -44
- data/test/test_writer.rb +47 -47
- data/test/tests.rb +13 -4
- data/test/tests_mimic.rb +12 -3
- data/test/tests_mimic_addition.rb +12 -3
- metadata +33 -144
- data/test/activesupport4/decoding_test.rb +0 -108
- data/test/activesupport4/encoding_test.rb +0 -531
- data/test/activesupport4/test_helper.rb +0 -41
- data/test/activesupport5/test_helper.rb +0 -72
- data/test/bar.rb +0 -16
- data/test/baz.rb +0 -16
- data/test/bug.rb +0 -16
- data/test/zoo.rb +0 -13
data/ext/oj/parser.c
CHANGED
@@ -11,8 +11,8 @@
|
|
11
11
|
#define USE_THREAD_LIMIT 0
|
12
12
|
// #define USE_THREAD_LIMIT 100000
|
13
13
|
#define MAX_EXP 4932
|
14
|
-
// max in the pow_map
|
15
|
-
#define MAX_POW
|
14
|
+
// max in the pow_map which is the limit for double
|
15
|
+
#define MAX_POW 308
|
16
16
|
|
17
17
|
#define MIN_SLEEP (1000000000LL / (double)CLOCKS_PER_SEC)
|
18
18
|
// 9,223,372,036,854,775,807
|
@@ -20,7 +20,7 @@
|
|
20
20
|
#define FRAC_LIMIT 10000000000000000ULL
|
21
21
|
|
22
22
|
// Give better performance with indented JSON but worse with unindented.
|
23
|
-
|
23
|
+
// #define SPACE_JUMP
|
24
24
|
|
25
25
|
enum {
|
26
26
|
SKIP_CHAR = 'a',
|
@@ -385,7 +385,7 @@ static const byte hex_map[256] = "\
|
|
385
385
|
................................\
|
386
386
|
................................";
|
387
387
|
|
388
|
-
static long double pow_map[
|
388
|
+
static long double pow_map[309] = {
|
389
389
|
1.0L, 1.0e1L, 1.0e2L, 1.0e3L, 1.0e4L, 1.0e5L, 1.0e6L, 1.0e7L, 1.0e8L, 1.0e9L, 1.0e10L,
|
390
390
|
1.0e11L, 1.0e12L, 1.0e13L, 1.0e14L, 1.0e15L, 1.0e16L, 1.0e17L, 1.0e18L, 1.0e19L, 1.0e20L, 1.0e21L,
|
391
391
|
1.0e22L, 1.0e23L, 1.0e24L, 1.0e25L, 1.0e26L, 1.0e27L, 1.0e28L, 1.0e29L, 1.0e30L, 1.0e31L, 1.0e32L,
|
@@ -414,15 +414,7 @@ static long double pow_map[401] = {
|
|
414
414
|
1.0e275L, 1.0e276L, 1.0e277L, 1.0e278L, 1.0e279L, 1.0e280L, 1.0e281L, 1.0e282L, 1.0e283L, 1.0e284L, 1.0e285L,
|
415
415
|
1.0e286L, 1.0e287L, 1.0e288L, 1.0e289L, 1.0e290L, 1.0e291L, 1.0e292L, 1.0e293L, 1.0e294L, 1.0e295L, 1.0e296L,
|
416
416
|
1.0e297L, 1.0e298L, 1.0e299L, 1.0e300L, 1.0e301L, 1.0e302L, 1.0e303L, 1.0e304L, 1.0e305L, 1.0e306L, 1.0e307L,
|
417
|
-
1.0e308L
|
418
|
-
1.0e319L, 1.0e320L, 1.0e321L, 1.0e322L, 1.0e323L, 1.0e324L, 1.0e325L, 1.0e326L, 1.0e327L, 1.0e328L, 1.0e329L,
|
419
|
-
1.0e330L, 1.0e331L, 1.0e332L, 1.0e333L, 1.0e334L, 1.0e335L, 1.0e336L, 1.0e337L, 1.0e338L, 1.0e339L, 1.0e340L,
|
420
|
-
1.0e341L, 1.0e342L, 1.0e343L, 1.0e344L, 1.0e345L, 1.0e346L, 1.0e347L, 1.0e348L, 1.0e349L, 1.0e350L, 1.0e351L,
|
421
|
-
1.0e352L, 1.0e353L, 1.0e354L, 1.0e355L, 1.0e356L, 1.0e357L, 1.0e358L, 1.0e359L, 1.0e360L, 1.0e361L, 1.0e362L,
|
422
|
-
1.0e363L, 1.0e364L, 1.0e365L, 1.0e366L, 1.0e367L, 1.0e368L, 1.0e369L, 1.0e370L, 1.0e371L, 1.0e372L, 1.0e373L,
|
423
|
-
1.0e374L, 1.0e375L, 1.0e376L, 1.0e377L, 1.0e378L, 1.0e379L, 1.0e380L, 1.0e381L, 1.0e382L, 1.0e383L, 1.0e384L,
|
424
|
-
1.0e385L, 1.0e386L, 1.0e387L, 1.0e388L, 1.0e389L, 1.0e390L, 1.0e391L, 1.0e392L, 1.0e393L, 1.0e394L, 1.0e395L,
|
425
|
-
1.0e396L, 1.0e397L, 1.0e398L, 1.0e399L, 1.0e400L};
|
417
|
+
1.0e308L};
|
426
418
|
|
427
419
|
static VALUE parser_class;
|
428
420
|
|
@@ -541,6 +533,7 @@ static void calc_num(ojParser p) {
|
|
541
533
|
// nothing to do
|
542
534
|
break;
|
543
535
|
}
|
536
|
+
p->type = OJ_NONE;
|
544
537
|
}
|
545
538
|
|
546
539
|
static void big_change(ojParser p) {
|
@@ -606,6 +599,8 @@ static void parse(ojParser p, const byte *json) {
|
|
606
599
|
const byte *b = json;
|
607
600
|
int i;
|
608
601
|
|
602
|
+
p->line = 1;
|
603
|
+
p->col = -1;
|
609
604
|
#if DEBUG
|
610
605
|
printf("*** parse - mode: %c %s\n", p->map[256], (const char *)json);
|
611
606
|
#endif
|
@@ -660,6 +655,7 @@ static void parse(ojParser p, const byte *json) {
|
|
660
655
|
}
|
661
656
|
buf_append_string(&p->buf, (const char *)start, b - start);
|
662
657
|
if ('"' == *b) {
|
658
|
+
p->cur = b - json;
|
663
659
|
p->funcs[p->stack[p->depth]].add_str(p);
|
664
660
|
p->map = (0 == p->depth) ? value_map : after_map;
|
665
661
|
break;
|
@@ -669,12 +665,14 @@ static void parse(ojParser p, const byte *json) {
|
|
669
665
|
p->next_map = (0 == p->depth) ? value_map : after_map;
|
670
666
|
break;
|
671
667
|
case OPEN_OBJECT:
|
668
|
+
p->cur = b - json;
|
672
669
|
p->funcs[p->stack[p->depth]].open_object(p);
|
673
670
|
p->depth++;
|
674
671
|
p->stack[p->depth] = OBJECT_FUN;
|
675
672
|
p->map = key1_map;
|
676
673
|
break;
|
677
674
|
case NUM_CLOSE_OBJECT:
|
675
|
+
p->cur = b - json;
|
678
676
|
calc_num(p);
|
679
677
|
// flow through
|
680
678
|
case CLOSE_OBJECT:
|
@@ -685,15 +683,18 @@ static void parse(ojParser p, const byte *json) {
|
|
685
683
|
return;
|
686
684
|
}
|
687
685
|
p->depth--;
|
686
|
+
p->cur = b - json;
|
688
687
|
p->funcs[p->stack[p->depth]].close_object(p);
|
689
688
|
break;
|
690
689
|
case OPEN_ARRAY:
|
690
|
+
p->cur = b - json;
|
691
691
|
p->funcs[p->stack[p->depth]].open_array(p);
|
692
692
|
p->depth++;
|
693
693
|
p->stack[p->depth] = ARRAY_FUN;
|
694
694
|
p->map = value_map;
|
695
695
|
break;
|
696
696
|
case NUM_CLOSE_ARRAY:
|
697
|
+
p->cur = b - json;
|
697
698
|
calc_num(p);
|
698
699
|
// flow through
|
699
700
|
case CLOSE_ARRAY:
|
@@ -704,9 +705,11 @@ static void parse(ojParser p, const byte *json) {
|
|
704
705
|
return;
|
705
706
|
}
|
706
707
|
p->depth--;
|
708
|
+
p->cur = b - json;
|
707
709
|
p->funcs[p->stack[p->depth]].close_array(p);
|
708
710
|
break;
|
709
711
|
case NUM_COMMA:
|
712
|
+
p->cur = b - json;
|
710
713
|
calc_num(p);
|
711
714
|
if (0 < p->depth && OBJECT_FUN == p->stack[p->depth]) {
|
712
715
|
p->map = key_map;
|
@@ -868,8 +871,14 @@ static void parse(ojParser p, const byte *json) {
|
|
868
871
|
b--;
|
869
872
|
p->map = big_exp_map;
|
870
873
|
break;
|
871
|
-
case NUM_SPC:
|
872
|
-
|
874
|
+
case NUM_SPC:
|
875
|
+
p->cur = b - json;
|
876
|
+
calc_num(p);
|
877
|
+
break;
|
878
|
+
case NUM_NEWLINE:
|
879
|
+
p->cur = b - json;
|
880
|
+
calc_num(p);
|
881
|
+
b++;
|
873
882
|
#ifdef SPACE_JUMP
|
874
883
|
// for (uint32_t *sj = (uint32_t*)b; 0x20202020 == *sj; sj++) { b += 4; }
|
875
884
|
for (uint16_t *sj = (uint16_t *)b; 0x2020 == *sj; sj++) {
|
@@ -890,6 +899,7 @@ static void parse(ojParser p, const byte *json) {
|
|
890
899
|
buf_append_string(&p->buf, (const char *)start, b - start);
|
891
900
|
}
|
892
901
|
if ('"' == *b) {
|
902
|
+
p->cur = b - json;
|
893
903
|
p->funcs[p->stack[p->depth]].add_str(p);
|
894
904
|
p->map = p->next_map;
|
895
905
|
break;
|
@@ -898,6 +908,7 @@ static void parse(ojParser p, const byte *json) {
|
|
898
908
|
break;
|
899
909
|
case STR_SLASH: p->map = esc_map; break;
|
900
910
|
case STR_QUOTE:
|
911
|
+
p->cur = b - json;
|
901
912
|
p->funcs[p->stack[p->depth]].add_str(p);
|
902
913
|
p->map = p->next_map;
|
903
914
|
break;
|
@@ -975,6 +986,7 @@ static void parse(ojParser p, const byte *json) {
|
|
975
986
|
case VAL_NULL:
|
976
987
|
if ('u' == b[1] && 'l' == b[2] && 'l' == b[3]) {
|
977
988
|
b += 3;
|
989
|
+
p->cur = b - json;
|
978
990
|
p->funcs[p->stack[p->depth]].add_null(p);
|
979
991
|
p->map = (0 == p->depth) ? value_map : after_map;
|
980
992
|
break;
|
@@ -1000,6 +1012,7 @@ static void parse(ojParser p, const byte *json) {
|
|
1000
1012
|
case VAL_TRUE:
|
1001
1013
|
if ('r' == b[1] && 'u' == b[2] && 'e' == b[3]) {
|
1002
1014
|
b += 3;
|
1015
|
+
p->cur = b - json;
|
1003
1016
|
p->funcs[p->stack[p->depth]].add_true(p);
|
1004
1017
|
p->map = (0 == p->depth) ? value_map : after_map;
|
1005
1018
|
break;
|
@@ -1025,6 +1038,7 @@ static void parse(ojParser p, const byte *json) {
|
|
1025
1038
|
case VAL_FALSE:
|
1026
1039
|
if ('a' == b[1] && 'l' == b[2] && 's' == b[3] && 'e' == b[4]) {
|
1027
1040
|
b += 4;
|
1041
|
+
p->cur = b - json;
|
1028
1042
|
p->funcs[p->stack[p->depth]].add_false(p);
|
1029
1043
|
p->map = (0 == p->depth) ? value_map : after_map;
|
1030
1044
|
break;
|
@@ -1058,6 +1072,7 @@ static void parse(ojParser p, const byte *json) {
|
|
1058
1072
|
parse_error(p, "expected null");
|
1059
1073
|
return;
|
1060
1074
|
}
|
1075
|
+
p->cur = b - json;
|
1061
1076
|
p->funcs[p->stack[p->depth]].add_null(p);
|
1062
1077
|
p->map = (0 == p->depth) ? value_map : after_map;
|
1063
1078
|
}
|
@@ -1069,6 +1084,7 @@ static void parse(ojParser p, const byte *json) {
|
|
1069
1084
|
parse_error(p, "expected false");
|
1070
1085
|
return;
|
1071
1086
|
}
|
1087
|
+
p->cur = b - json;
|
1072
1088
|
p->funcs[p->stack[p->depth]].add_false(p);
|
1073
1089
|
p->map = (0 == p->depth) ? value_map : after_map;
|
1074
1090
|
}
|
@@ -1080,6 +1096,7 @@ static void parse(ojParser p, const byte *json) {
|
|
1080
1096
|
parse_error(p, "expected true");
|
1081
1097
|
return;
|
1082
1098
|
}
|
1099
|
+
p->cur = b - json;
|
1083
1100
|
p->funcs[p->stack[p->depth]].add_true(p);
|
1084
1101
|
p->map = (0 == p->depth) ? value_map : after_map;
|
1085
1102
|
}
|
@@ -1097,6 +1114,9 @@ static void parse(ojParser p, const byte *json) {
|
|
1097
1114
|
p->map = trail_map;
|
1098
1115
|
}
|
1099
1116
|
}
|
1117
|
+
if (0 < p->depth) {
|
1118
|
+
parse_error(p, "parse error, not closed");
|
1119
|
+
}
|
1100
1120
|
if (0 == p->depth) {
|
1101
1121
|
switch (p->map[256]) {
|
1102
1122
|
case '0':
|
@@ -1107,7 +1127,10 @@ static void parse(ojParser p, const byte *json) {
|
|
1107
1127
|
case 'D':
|
1108
1128
|
case 'g':
|
1109
1129
|
case 'B':
|
1110
|
-
case 'Y':
|
1130
|
+
case 'Y':
|
1131
|
+
p->cur = b - json;
|
1132
|
+
calc_num(p);
|
1133
|
+
break;
|
1111
1134
|
}
|
1112
1135
|
}
|
1113
1136
|
return;
|
@@ -1122,8 +1145,10 @@ static void parser_free(void *ptr) {
|
|
1122
1145
|
p = (ojParser)ptr;
|
1123
1146
|
buf_cleanup(&p->key);
|
1124
1147
|
buf_cleanup(&p->buf);
|
1125
|
-
p->free
|
1126
|
-
|
1148
|
+
if (NULL != p->free) {
|
1149
|
+
p->free(p);
|
1150
|
+
}
|
1151
|
+
OJ_R_FREE(ptr);
|
1127
1152
|
}
|
1128
1153
|
|
1129
1154
|
static void parser_mark(void *ptr) {
|
@@ -1133,7 +1158,9 @@ static void parser_mark(void *ptr) {
|
|
1133
1158
|
if (0 != p->reader) {
|
1134
1159
|
rb_gc_mark(p->reader);
|
1135
1160
|
}
|
1136
|
-
p->mark
|
1161
|
+
if (NULL != p->mark) {
|
1162
|
+
p->mark(p);
|
1163
|
+
}
|
1137
1164
|
}
|
1138
1165
|
}
|
1139
1166
|
|
@@ -1153,7 +1180,7 @@ static int opt_cb(VALUE rkey, VALUE value, VALUE ptr) {
|
|
1153
1180
|
rkey = rb_sym2str(rkey);
|
1154
1181
|
// fall through
|
1155
1182
|
case RUBY_T_STRING:
|
1156
|
-
key =
|
1183
|
+
key = StringValuePtr(rkey);
|
1157
1184
|
klen = RSTRING_LEN(rkey);
|
1158
1185
|
break;
|
1159
1186
|
default: rb_raise(rb_eArgError, "option keys must be a symbol or string");
|
@@ -1178,7 +1205,7 @@ static int opt_cb(VALUE rkey, VALUE value, VALUE ptr) {
|
|
1178
1205
|
* Oj::Parser.new(:usual, cache_keys: true).
|
1179
1206
|
*/
|
1180
1207
|
static VALUE parser_new(int argc, VALUE *argv, VALUE self) {
|
1181
|
-
ojParser p =
|
1208
|
+
ojParser p = OJ_R_ALLOC(struct _ojParser);
|
1182
1209
|
|
1183
1210
|
#if HAVE_RB_EXT_RACTOR_SAFE
|
1184
1211
|
// This doesn't seem to do anything.
|
@@ -1190,7 +1217,7 @@ static VALUE parser_new(int argc, VALUE *argv, VALUE self) {
|
|
1190
1217
|
p->map = value_map;
|
1191
1218
|
|
1192
1219
|
if (argc < 1) {
|
1193
|
-
|
1220
|
+
oj_set_parser_validator(p);
|
1194
1221
|
} else {
|
1195
1222
|
VALUE mode = argv[0];
|
1196
1223
|
|
@@ -1231,6 +1258,32 @@ static VALUE parser_new(int argc, VALUE *argv, VALUE self) {
|
|
1231
1258
|
return Data_Wrap_Struct(parser_class, parser_mark, parser_free, p);
|
1232
1259
|
}
|
1233
1260
|
|
1261
|
+
// Create a new parser without setting the delegate. The parser is
|
1262
|
+
// wrapped. The parser is (ojParser)DATA_PTR(value) where value is the return
|
1263
|
+
// from this function. A delegate must be added before the parser can be
|
1264
|
+
// used. Optionally oj_parser_set_options can be called if the options are not
|
1265
|
+
// set directly.
|
1266
|
+
VALUE oj_parser_new(void) {
|
1267
|
+
ojParser p = OJ_R_ALLOC(struct _ojParser);
|
1268
|
+
|
1269
|
+
#if HAVE_RB_EXT_RACTOR_SAFE
|
1270
|
+
// This doesn't seem to do anything.
|
1271
|
+
rb_ext_ractor_safe(true);
|
1272
|
+
#endif
|
1273
|
+
memset(p, 0, sizeof(struct _ojParser));
|
1274
|
+
buf_init(&p->key);
|
1275
|
+
buf_init(&p->buf);
|
1276
|
+
p->map = value_map;
|
1277
|
+
|
1278
|
+
return Data_Wrap_Struct(parser_class, parser_mark, parser_free, p);
|
1279
|
+
}
|
1280
|
+
|
1281
|
+
// Set set the options from a hash (ropts).
|
1282
|
+
void oj_parser_set_option(ojParser p, VALUE ropts) {
|
1283
|
+
Check_Type(ropts, T_HASH);
|
1284
|
+
rb_hash_foreach(ropts, opt_cb, (VALUE)p);
|
1285
|
+
}
|
1286
|
+
|
1234
1287
|
/* Document-method: method_missing(value)
|
1235
1288
|
* call-seq: method_missing(value)
|
1236
1289
|
*
|
@@ -1284,7 +1337,7 @@ static VALUE parser_new(int argc, VALUE *argv, VALUE self) {
|
|
1284
1337
|
*/
|
1285
1338
|
static VALUE parser_missing(int argc, VALUE *argv, VALUE self) {
|
1286
1339
|
ojParser p = (ojParser)DATA_PTR(self);
|
1287
|
-
const char
|
1340
|
+
const char *key = NULL;
|
1288
1341
|
volatile VALUE rkey = *argv;
|
1289
1342
|
volatile VALUE rv = Qnil;
|
1290
1343
|
|
@@ -1296,7 +1349,7 @@ static VALUE parser_missing(int argc, VALUE *argv, VALUE self) {
|
|
1296
1349
|
case RUBY_T_SYMBOL:
|
1297
1350
|
rkey = rb_sym2str(rkey);
|
1298
1351
|
// fall through
|
1299
|
-
case RUBY_T_STRING: key =
|
1352
|
+
case RUBY_T_STRING: key = StringValuePtr(rkey); break;
|
1300
1353
|
default: rb_raise(rb_eArgError, "option method must be a symbol or string");
|
1301
1354
|
}
|
1302
1355
|
if (1 < argc) {
|
@@ -1313,12 +1366,12 @@ static VALUE parser_missing(int argc, VALUE *argv, VALUE self) {
|
|
1313
1366
|
* Returns the result according to the delegate of the parser.
|
1314
1367
|
*/
|
1315
1368
|
static VALUE parser_parse(VALUE self, VALUE json) {
|
1316
|
-
ojParser
|
1369
|
+
ojParser p = (ojParser)DATA_PTR(self);
|
1370
|
+
const byte *ptr = (const byte *)StringValuePtr(json);
|
1317
1371
|
|
1318
|
-
Check_Type(json, T_STRING);
|
1319
1372
|
parser_reset(p);
|
1320
1373
|
p->start(p);
|
1321
|
-
parse(p,
|
1374
|
+
parse(p, ptr);
|
1322
1375
|
|
1323
1376
|
return p->result(p);
|
1324
1377
|
}
|
@@ -1371,8 +1424,7 @@ static VALUE parser_file(VALUE self, VALUE filename) {
|
|
1371
1424
|
const char *path;
|
1372
1425
|
int fd;
|
1373
1426
|
|
1374
|
-
|
1375
|
-
path = rb_string_value_ptr(&filename);
|
1427
|
+
path = StringValuePtr(filename);
|
1376
1428
|
|
1377
1429
|
parser_reset(p);
|
1378
1430
|
p->start(p);
|
@@ -1446,7 +1498,7 @@ static VALUE usual_parser = Qundef;
|
|
1446
1498
|
*/
|
1447
1499
|
static VALUE parser_usual(VALUE self) {
|
1448
1500
|
if (Qundef == usual_parser) {
|
1449
|
-
ojParser p =
|
1501
|
+
ojParser p = OJ_R_ALLOC(struct _ojParser);
|
1450
1502
|
|
1451
1503
|
memset(p, 0, sizeof(struct _ojParser));
|
1452
1504
|
buf_init(&p->key);
|
@@ -1464,12 +1516,12 @@ static VALUE saj_parser = Qundef;
|
|
1464
1516
|
/* Document-method: saj
|
1465
1517
|
* call-seq: saj
|
1466
1518
|
*
|
1467
|
-
* Returns the default
|
1519
|
+
* Returns the default SAJ parser. Note the default SAJ parser can not be used
|
1468
1520
|
* concurrently in more than one thread.
|
1469
1521
|
*/
|
1470
1522
|
static VALUE parser_saj(VALUE self) {
|
1471
1523
|
if (Qundef == saj_parser) {
|
1472
|
-
ojParser p =
|
1524
|
+
ojParser p = OJ_R_ALLOC(struct _ojParser);
|
1473
1525
|
|
1474
1526
|
memset(p, 0, sizeof(struct _ojParser));
|
1475
1527
|
buf_init(&p->key);
|
@@ -1491,7 +1543,7 @@ static VALUE validate_parser = Qundef;
|
|
1491
1543
|
*/
|
1492
1544
|
static VALUE parser_validate(VALUE self) {
|
1493
1545
|
if (Qundef == validate_parser) {
|
1494
|
-
ojParser p =
|
1546
|
+
ojParser p = OJ_R_ALLOC(struct _ojParser);
|
1495
1547
|
|
1496
1548
|
memset(p, 0, sizeof(struct _ojParser));
|
1497
1549
|
buf_init(&p->key);
|
@@ -1515,8 +1567,11 @@ static VALUE parser_validate(VALUE self) {
|
|
1515
1567
|
* isolates options to just the parser so that other parts of the code are not
|
1516
1568
|
* forced to use the same options.
|
1517
1569
|
*/
|
1518
|
-
void oj_parser_init() {
|
1570
|
+
void oj_parser_init(void) {
|
1519
1571
|
parser_class = rb_define_class_under(Oj, "Parser", rb_cObject);
|
1572
|
+
rb_gc_register_address(&parser_class);
|
1573
|
+
rb_undef_alloc_func(parser_class);
|
1574
|
+
|
1520
1575
|
rb_define_module_function(parser_class, "new", parser_new, -1);
|
1521
1576
|
rb_define_method(parser_class, "parse", parser_parse, 1);
|
1522
1577
|
rb_define_method(parser_class, "load", parser_load, 1);
|
data/ext/oj/parser.h
CHANGED
@@ -4,8 +4,8 @@
|
|
4
4
|
#ifndef OJ_PARSER_H
|
5
5
|
#define OJ_PARSER_H
|
6
6
|
|
7
|
-
#include <stdbool.h>
|
8
7
|
#include <ruby.h>
|
8
|
+
#include <stdbool.h>
|
9
9
|
|
10
10
|
#include "buf.h"
|
11
11
|
|
@@ -38,7 +38,7 @@ typedef struct _num {
|
|
38
38
|
bool neg;
|
39
39
|
bool exp_neg;
|
40
40
|
// for numbers as strings, reuse buf
|
41
|
-
} *
|
41
|
+
} *Num;
|
42
42
|
|
43
43
|
struct _ojParser;
|
44
44
|
|
@@ -54,11 +54,11 @@ typedef struct _funcs {
|
|
54
54
|
void (*close_array)(struct _ojParser *p);
|
55
55
|
void (*open_object)(struct _ojParser *p);
|
56
56
|
void (*close_object)(struct _ojParser *p);
|
57
|
-
} *
|
57
|
+
} *Funcs;
|
58
58
|
|
59
59
|
typedef struct _ojParser {
|
60
|
-
const char
|
61
|
-
const char
|
60
|
+
const char *map;
|
61
|
+
const char *next_map;
|
62
62
|
int depth;
|
63
63
|
unsigned char stack[1024];
|
64
64
|
|
@@ -67,7 +67,7 @@ typedef struct _ojParser {
|
|
67
67
|
struct _buf key;
|
68
68
|
struct _buf buf;
|
69
69
|
|
70
|
-
struct _funcs funcs[3];
|
70
|
+
struct _funcs funcs[3]; // indexed by XXX_FUN defines
|
71
71
|
|
72
72
|
void (*start)(struct _ojParser *p);
|
73
73
|
VALUE (*option)(struct _ojParser *p, const char *key, VALUE value);
|
@@ -80,11 +80,22 @@ typedef struct _ojParser {
|
|
80
80
|
|
81
81
|
char token[8];
|
82
82
|
long line;
|
83
|
+
long cur; // only set before call to a function
|
83
84
|
long col;
|
84
85
|
int ri;
|
85
86
|
uint32_t ucode;
|
86
87
|
ojType type; // valType
|
87
88
|
bool just_one;
|
88
|
-
} *
|
89
|
+
} *ojParser;
|
90
|
+
|
91
|
+
// Create a new parser without setting the delegate. The parser is
|
92
|
+
// wrapped. The parser is (ojParser)DATA_PTR(value) where value is the return
|
93
|
+
// from this function. A delegate must be added before the parser can be
|
94
|
+
// used. Optionally oj_parser_set_options can be called if the options are not
|
95
|
+
// set directly.
|
96
|
+
extern VALUE oj_parser_new();
|
97
|
+
|
98
|
+
// Set set the options from a hash (ropts).
|
99
|
+
extern void oj_parser_set_option(ojParser p, VALUE ropts);
|
89
100
|
|
90
101
|
#endif /* OJ_PARSER_H */
|