oj 3.13.9 → 3.16.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +101 -0
- data/README.md +13 -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 +19 -33
- data/ext/oj/code.h +2 -2
- data/ext/oj/compat.c +20 -60
- data/ext/oj/custom.c +76 -155
- data/ext/oj/debug.c +3 -9
- data/ext/oj/dump.c +203 -213
- data/ext/oj/dump.h +26 -12
- data/ext/oj/dump_compat.c +565 -642
- data/ext/oj/dump_leaf.c +17 -63
- data/ext/oj/dump_object.c +59 -181
- data/ext/oj/dump_strict.c +24 -48
- data/ext/oj/encoder.c +43 -0
- data/ext/oj/err.c +2 -13
- data/ext/oj/err.h +9 -12
- data/ext/oj/extconf.rb +18 -7
- data/ext/oj/fast.c +83 -108
- 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 +104 -81
- data/ext/oj/object.c +50 -67
- data/ext/oj/odd.c +89 -67
- data/ext/oj/odd.h +15 -15
- data/ext/oj/oj.c +171 -106
- data/ext/oj/oj.h +96 -74
- data/ext/oj/parse.c +169 -189
- data/ext/oj/parse.h +23 -24
- data/ext/oj/parser.c +89 -34
- data/ext/oj/parser.h +20 -9
- data/ext/oj/rails.c +86 -151
- data/ext/oj/rails.h +1 -1
- data/ext/oj/reader.c +12 -15
- 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 +21 -32
- 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 -22
- 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 +32 -69
- data/lib/oj/active_support_helper.rb +1 -3
- 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 +162 -150
- data/lib/oj/mimic.rb +6 -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/JsonGem.md +15 -0
- data/pages/Modes.md +6 -3
- data/pages/Options.md +10 -0
- data/pages/Rails.md +12 -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 +15 -15
- 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 +8 -6
- 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 +49 -37
- 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 +95 -43
- data/test/test_custom.rb +72 -51
- data/test/test_debian.rb +7 -10
- data/test/test_fast.rb +102 -87
- 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 +40 -32
- data/test/test_various.rb +163 -84
- data/test/test_wab.rb +48 -44
- data/test/test_writer.rb +47 -47
- data/test/tests.rb +13 -5
- data/test/tests_mimic.rb +12 -3
- data/test/tests_mimic_addition.rb +12 -3
- metadata +34 -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/parse.h
CHANGED
@@ -16,23 +16,25 @@
|
|
16
16
|
#include "val_stack.h"
|
17
17
|
|
18
18
|
struct _rxClass;
|
19
|
+
struct _parseInfo;
|
19
20
|
|
20
21
|
typedef struct _numInfo {
|
21
|
-
int64_t
|
22
|
-
int64_t
|
23
|
-
int64_t
|
24
|
-
int64_t
|
25
|
-
const char
|
26
|
-
size_t
|
27
|
-
long
|
28
|
-
|
29
|
-
int
|
30
|
-
int
|
31
|
-
int
|
32
|
-
int
|
33
|
-
int
|
34
|
-
int
|
35
|
-
|
22
|
+
int64_t i;
|
23
|
+
int64_t num;
|
24
|
+
int64_t div;
|
25
|
+
int64_t di;
|
26
|
+
const char *str;
|
27
|
+
size_t len;
|
28
|
+
long exp;
|
29
|
+
struct _parseInfo *pi;
|
30
|
+
int big;
|
31
|
+
int infinity;
|
32
|
+
int nan;
|
33
|
+
int neg;
|
34
|
+
int has_exp;
|
35
|
+
int no_big;
|
36
|
+
int bigdec_load;
|
37
|
+
} *NumInfo;
|
36
38
|
|
37
39
|
typedef struct _parseInfo {
|
38
40
|
// used for the string parser
|
@@ -54,11 +56,7 @@ typedef struct _parseInfo {
|
|
54
56
|
VALUE (*start_hash)(struct _parseInfo *pi);
|
55
57
|
void (*end_hash)(struct _parseInfo *pi);
|
56
58
|
VALUE (*hash_key)(struct _parseInfo *pi, const char *key, size_t klen);
|
57
|
-
void (*hash_set_cstr)(struct _parseInfo *pi,
|
58
|
-
Val kval,
|
59
|
-
const char * str,
|
60
|
-
size_t len,
|
61
|
-
const char * orig);
|
59
|
+
void (*hash_set_cstr)(struct _parseInfo *pi, Val kval, const char *str, size_t len, const char *orig);
|
62
60
|
void (*hash_set_num)(struct _parseInfo *pi, Val kval, NumInfo ni);
|
63
61
|
void (*hash_set_value)(struct _parseInfo *pi, Val kval, VALUE value);
|
64
62
|
|
@@ -73,11 +71,10 @@ typedef struct _parseInfo {
|
|
73
71
|
void (*add_value)(struct _parseInfo *pi, VALUE val);
|
74
72
|
VALUE err_class;
|
75
73
|
bool has_callbacks;
|
76
|
-
} *
|
74
|
+
} *ParseInfo;
|
77
75
|
|
78
|
-
extern void
|
79
|
-
extern void
|
80
|
-
oj_set_error_at(ParseInfo pi, VALUE err_clas, const char *file, int line, const char *format, ...);
|
76
|
+
extern void oj_parse2(ParseInfo pi);
|
77
|
+
extern void oj_set_error_at(ParseInfo pi, VALUE err_clas, const char *file, int line, const char *format, ...);
|
81
78
|
extern VALUE oj_pi_parse(int argc, VALUE *argv, ParseInfo pi, char *json, size_t len, int yieldOk);
|
82
79
|
extern VALUE oj_num_as_value(NumInfo ni);
|
83
80
|
|
@@ -97,6 +94,8 @@ static inline void parse_info_init(ParseInfo pi) {
|
|
97
94
|
memset(pi, 0, sizeof(struct _parseInfo));
|
98
95
|
}
|
99
96
|
|
97
|
+
extern void oj_scanner_init(void);
|
98
|
+
|
100
99
|
static inline bool empty_ok(Options options) {
|
101
100
|
switch (options->mode) {
|
102
101
|
case ObjectMode:
|
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
|
|
@@ -32,13 +32,13 @@ typedef struct _num {
|
|
32
32
|
long double dub;
|
33
33
|
int64_t fixnum; // holds all digits
|
34
34
|
uint32_t len;
|
35
|
-
int16_t div;
|
35
|
+
int16_t div; // 10^div
|
36
36
|
int16_t exp;
|
37
|
-
uint8_t shift;
|
37
|
+
uint8_t shift; // shift of fixnum to get decimal
|
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 */
|