oj 3.13.21 → 3.13.22
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +2 -0
- data/ext/oj/custom.c +21 -40
- data/ext/oj/fast.c +15 -13
- data/ext/oj/intern.c +6 -9
- data/ext/oj/introspect.c +96 -0
- data/ext/oj/object.c +33 -32
- data/ext/oj/oj.c +9 -1
- data/ext/oj/oj.h +3 -0
- data/ext/oj/parser.c +26 -0
- data/ext/oj/parser.h +11 -0
- data/ext/oj/saj2.c +56 -62
- data/ext/oj/saj2.h +23 -0
- data/ext/oj/usual.c +82 -129
- data/ext/oj/usual.h +68 -0
- data/ext/oj/val_stack.c +1 -1
- data/lib/oj/state.rb +1 -1
- data/lib/oj/version.rb +1 -1
- data/test/json_gem/json_generator_test.rb +3 -4
- data/test/json_gem/json_parser_test.rb +1 -3
- data/test/test_custom.rb +9 -10
- data/test/test_file.rb +3 -10
- data/test/test_gc.rb +0 -2
- data/test/test_integer_range.rb +0 -6
- data/test/test_object.rb +3 -48
- data/test/test_parser.rb +3 -19
- data/test/test_parser_debug.rb +27 -0
- data/test/test_scp.rb +2 -4
- data/test/test_various.rb +2 -3
- data/test/tests.rb +9 -0
- data/test/tests_mimic.rb +9 -0
- data/test/tests_mimic_addition.rb +9 -0
- metadata +6 -2
data/ext/oj/usual.c
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
#include "cache.h"
|
4
4
|
#include "oj.h"
|
5
5
|
#include "parser.h"
|
6
|
+
#include "usual.h"
|
6
7
|
|
7
8
|
// The Usual delegate builds Ruby objects during parsing. It makes use of
|
8
9
|
// three stacks. The first is the value stack. This is where parsed values are
|
@@ -28,61 +29,6 @@
|
|
28
29
|
|
29
30
|
#define DEBUG 0
|
30
31
|
|
31
|
-
// Used to mark the start of each Hash, Array, or Object. The members point at
|
32
|
-
// positions of the start in the value stack and if not an Array into the key
|
33
|
-
// stack.
|
34
|
-
typedef struct _col {
|
35
|
-
long vi; // value stack index
|
36
|
-
long ki; // key stack index if an hash else -1 for an array
|
37
|
-
} * Col;
|
38
|
-
|
39
|
-
typedef union _key {
|
40
|
-
struct {
|
41
|
-
int16_t len;
|
42
|
-
char buf[30];
|
43
|
-
};
|
44
|
-
struct {
|
45
|
-
int16_t xlen; // should be the same as len
|
46
|
-
char * key;
|
47
|
-
};
|
48
|
-
} * Key;
|
49
|
-
|
50
|
-
#define MISS_AUTO 'A'
|
51
|
-
#define MISS_RAISE 'R'
|
52
|
-
#define MISS_IGNORE 'I'
|
53
|
-
|
54
|
-
typedef struct _delegate {
|
55
|
-
VALUE *vhead;
|
56
|
-
VALUE *vtail;
|
57
|
-
VALUE *vend;
|
58
|
-
|
59
|
-
Col chead;
|
60
|
-
Col ctail;
|
61
|
-
Col cend;
|
62
|
-
|
63
|
-
Key khead;
|
64
|
-
Key ktail;
|
65
|
-
Key kend;
|
66
|
-
|
67
|
-
VALUE (*get_key)(ojParser p, Key kp);
|
68
|
-
struct _cache *key_cache; // same as str_cache or sym_cache
|
69
|
-
struct _cache *str_cache;
|
70
|
-
struct _cache *sym_cache;
|
71
|
-
struct _cache *class_cache;
|
72
|
-
struct _cache *attr_cache;
|
73
|
-
|
74
|
-
VALUE array_class;
|
75
|
-
VALUE hash_class;
|
76
|
-
|
77
|
-
char * create_id;
|
78
|
-
uint8_t create_id_len;
|
79
|
-
uint8_t cache_str;
|
80
|
-
uint8_t cache_xrate;
|
81
|
-
uint8_t miss_class;
|
82
|
-
bool cache_keys;
|
83
|
-
bool ignore_json_create;
|
84
|
-
} * Delegate;
|
85
|
-
|
86
32
|
static ID to_f_id = 0;
|
87
33
|
static ID ltlt_id = 0;
|
88
34
|
static ID hset_id = 0;
|
@@ -178,7 +124,7 @@ static VALUE form_class_auto(const char *str, size_t len) {
|
|
178
124
|
return resolve_classpath(str, len, true);
|
179
125
|
}
|
180
126
|
|
181
|
-
static void assure_cstack(
|
127
|
+
static void assure_cstack(Usual d) {
|
182
128
|
if (d->cend <= d->ctail + 1) {
|
183
129
|
size_t cap = d->cend - d->chead;
|
184
130
|
long pos = d->ctail - d->chead;
|
@@ -191,7 +137,7 @@ static void assure_cstack(Delegate d) {
|
|
191
137
|
}
|
192
138
|
|
193
139
|
static void push(ojParser p, VALUE v) {
|
194
|
-
|
140
|
+
Usual d = (Usual)p->ctx;
|
195
141
|
|
196
142
|
if (d->vend <= d->vtail) {
|
197
143
|
size_t cap = d->vend - d->vhead;
|
@@ -207,7 +153,7 @@ static void push(ojParser p, VALUE v) {
|
|
207
153
|
}
|
208
154
|
|
209
155
|
static VALUE cache_key(ojParser p, Key kp) {
|
210
|
-
|
156
|
+
Usual d = (Usual)p->ctx;
|
211
157
|
|
212
158
|
if ((size_t)kp->len < sizeof(kp->buf)) {
|
213
159
|
return cache_intern(d->key_cache, kp->buf, kp->len);
|
@@ -230,7 +176,7 @@ static VALUE sym_key(ojParser p, Key kp) {
|
|
230
176
|
}
|
231
177
|
|
232
178
|
static ID get_attr_id(ojParser p, Key kp) {
|
233
|
-
|
179
|
+
Usual d = (Usual)p->ctx;
|
234
180
|
|
235
181
|
if ((size_t)kp->len < sizeof(kp->buf)) {
|
236
182
|
return (ID)cache_intern(d->attr_cache, kp->buf, kp->len);
|
@@ -239,7 +185,7 @@ static ID get_attr_id(ojParser p, Key kp) {
|
|
239
185
|
}
|
240
186
|
|
241
187
|
static void push_key(ojParser p) {
|
242
|
-
|
188
|
+
Usual d = (Usual)p->ctx;
|
243
189
|
size_t klen = buf_len(&p->key);
|
244
190
|
const char *key = buf_str(&p->key);
|
245
191
|
|
@@ -263,7 +209,7 @@ static void push_key(ojParser p) {
|
|
263
209
|
}
|
264
210
|
|
265
211
|
static void push2(ojParser p, VALUE v) {
|
266
|
-
|
212
|
+
Usual d = (Usual)p->ctx;
|
267
213
|
|
268
214
|
if (d->vend <= d->vtail + 1) {
|
269
215
|
size_t cap = d->vend - d->vhead;
|
@@ -281,7 +227,7 @@ static void push2(ojParser p, VALUE v) {
|
|
281
227
|
}
|
282
228
|
|
283
229
|
static void open_object(ojParser p) {
|
284
|
-
|
230
|
+
Usual d = (Usual)p->ctx;
|
285
231
|
|
286
232
|
assure_cstack(d);
|
287
233
|
d->ctail->vi = d->vtail - d->vhead;
|
@@ -291,7 +237,7 @@ static void open_object(ojParser p) {
|
|
291
237
|
}
|
292
238
|
|
293
239
|
static void open_object_key(ojParser p) {
|
294
|
-
|
240
|
+
Usual d = (Usual)p->ctx;
|
295
241
|
|
296
242
|
push_key(p);
|
297
243
|
assure_cstack(d);
|
@@ -302,7 +248,7 @@ static void open_object_key(ojParser p) {
|
|
302
248
|
}
|
303
249
|
|
304
250
|
static void open_array(ojParser p) {
|
305
|
-
|
251
|
+
Usual d = (Usual)p->ctx;
|
306
252
|
|
307
253
|
assure_cstack(d);
|
308
254
|
d->ctail->vi = d->vtail - d->vhead;
|
@@ -312,7 +258,7 @@ static void open_array(ojParser p) {
|
|
312
258
|
}
|
313
259
|
|
314
260
|
static void open_array_key(ojParser p) {
|
315
|
-
|
261
|
+
Usual d = (Usual)p->ctx;
|
316
262
|
|
317
263
|
push_key(p);
|
318
264
|
assure_cstack(d);
|
@@ -324,7 +270,7 @@ static void open_array_key(ojParser p) {
|
|
324
270
|
|
325
271
|
static void close_object(ojParser p) {
|
326
272
|
VALUE * vp;
|
327
|
-
|
273
|
+
Usual d = (Usual)p->ctx;
|
328
274
|
|
329
275
|
d->ctail--;
|
330
276
|
|
@@ -357,7 +303,7 @@ static void close_object(ojParser p) {
|
|
357
303
|
|
358
304
|
static void close_object_class(ojParser p) {
|
359
305
|
VALUE * vp;
|
360
|
-
|
306
|
+
Usual d = (Usual)p->ctx;
|
361
307
|
|
362
308
|
d->ctail--;
|
363
309
|
|
@@ -380,7 +326,7 @@ static void close_object_class(ojParser p) {
|
|
380
326
|
|
381
327
|
static void close_object_create(ojParser p) {
|
382
328
|
VALUE * vp;
|
383
|
-
|
329
|
+
Usual d = (Usual)p->ctx;
|
384
330
|
|
385
331
|
d->ctail--;
|
386
332
|
|
@@ -459,7 +405,7 @@ static void close_object_create(ojParser p) {
|
|
459
405
|
}
|
460
406
|
|
461
407
|
static void close_array(ojParser p) {
|
462
|
-
|
408
|
+
Usual d = (Usual)p->ctx;
|
463
409
|
|
464
410
|
d->ctail--;
|
465
411
|
VALUE * head = d->vhead + d->ctail->vi + 1;
|
@@ -472,7 +418,7 @@ static void close_array(ojParser p) {
|
|
472
418
|
|
473
419
|
static void close_array_class(ojParser p) {
|
474
420
|
VALUE * vp;
|
475
|
-
|
421
|
+
Usual d = (Usual)p->ctx;
|
476
422
|
|
477
423
|
d->ctail--;
|
478
424
|
VALUE * head = d->vhead + d->ctail->vi + 1;
|
@@ -585,7 +531,7 @@ static void add_big_as_ruby_key(ojParser p) {
|
|
585
531
|
}
|
586
532
|
|
587
533
|
static void add_str(ojParser p) {
|
588
|
-
|
534
|
+
Usual d = (Usual)p->ctx;
|
589
535
|
volatile VALUE rstr;
|
590
536
|
const char * str = buf_str(&p->buf);
|
591
537
|
size_t len = buf_len(&p->buf);
|
@@ -599,7 +545,7 @@ static void add_str(ojParser p) {
|
|
599
545
|
}
|
600
546
|
|
601
547
|
static void add_str_key(ojParser p) {
|
602
|
-
|
548
|
+
Usual d = (Usual)p->ctx;
|
603
549
|
volatile VALUE rstr;
|
604
550
|
const char * str = buf_str(&p->buf);
|
605
551
|
size_t len = buf_len(&p->buf);
|
@@ -614,7 +560,7 @@ static void add_str_key(ojParser p) {
|
|
614
560
|
}
|
615
561
|
|
616
562
|
static void add_str_key_create(ojParser p) {
|
617
|
-
|
563
|
+
Usual d = (Usual)p->ctx;
|
618
564
|
volatile VALUE rstr;
|
619
565
|
const char * str = buf_str(&p->buf);
|
620
566
|
size_t len = buf_len(&p->buf);
|
@@ -648,7 +594,7 @@ static void add_str_key_create(ojParser p) {
|
|
648
594
|
}
|
649
595
|
|
650
596
|
static VALUE result(ojParser p) {
|
651
|
-
|
597
|
+
Usual d = (Usual)p->ctx;
|
652
598
|
|
653
599
|
if (d->vhead < d->vtail) {
|
654
600
|
return *d->vhead;
|
@@ -657,7 +603,7 @@ static VALUE result(ojParser p) {
|
|
657
603
|
}
|
658
604
|
|
659
605
|
static void start(ojParser p) {
|
660
|
-
|
606
|
+
Usual d = (Usual)p->ctx;
|
661
607
|
|
662
608
|
d->vtail = d->vhead;
|
663
609
|
d->ctail = d->chead;
|
@@ -665,7 +611,7 @@ static void start(ojParser p) {
|
|
665
611
|
}
|
666
612
|
|
667
613
|
static void dfree(ojParser p) {
|
668
|
-
|
614
|
+
Usual d = (Usual)p->ctx;
|
669
615
|
|
670
616
|
cache_free(d->str_cache);
|
671
617
|
cache_free(d->attr_cache);
|
@@ -684,10 +630,10 @@ static void dfree(ojParser p) {
|
|
684
630
|
}
|
685
631
|
|
686
632
|
static void mark(ojParser p) {
|
687
|
-
if (NULL == p->ctx) {
|
633
|
+
if (NULL == p || NULL == p->ctx) {
|
688
634
|
return;
|
689
635
|
}
|
690
|
-
|
636
|
+
Usual d = (Usual)p->ctx;
|
691
637
|
VALUE * vp;
|
692
638
|
|
693
639
|
if (NULL == d) {
|
@@ -720,13 +666,13 @@ struct opt {
|
|
720
666
|
};
|
721
667
|
|
722
668
|
static VALUE opt_array_class(ojParser p, VALUE value) {
|
723
|
-
|
669
|
+
Usual d = (Usual)p->ctx;
|
724
670
|
|
725
671
|
return d->array_class;
|
726
672
|
}
|
727
673
|
|
728
674
|
static VALUE opt_array_class_set(ojParser p, VALUE value) {
|
729
|
-
|
675
|
+
Usual d = (Usual)p->ctx;
|
730
676
|
|
731
677
|
if (Qnil == value) {
|
732
678
|
p->funcs[TOP_FUN].close_array = close_array;
|
@@ -747,13 +693,13 @@ static VALUE opt_array_class_set(ojParser p, VALUE value) {
|
|
747
693
|
}
|
748
694
|
|
749
695
|
static VALUE opt_cache_keys(ojParser p, VALUE value) {
|
750
|
-
|
696
|
+
Usual d = (Usual)p->ctx;
|
751
697
|
|
752
698
|
return d->cache_keys ? Qtrue : Qfalse;
|
753
699
|
}
|
754
700
|
|
755
701
|
static VALUE opt_cache_keys_set(ojParser p, VALUE value) {
|
756
|
-
|
702
|
+
Usual d = (Usual)p->ctx;
|
757
703
|
|
758
704
|
if (Qtrue == value) {
|
759
705
|
d->cache_keys = true;
|
@@ -775,13 +721,13 @@ static VALUE opt_cache_keys_set(ojParser p, VALUE value) {
|
|
775
721
|
}
|
776
722
|
|
777
723
|
static VALUE opt_cache_strings(ojParser p, VALUE value) {
|
778
|
-
|
724
|
+
Usual d = (Usual)p->ctx;
|
779
725
|
|
780
726
|
return INT2NUM((int)d->cache_str);
|
781
727
|
}
|
782
728
|
|
783
729
|
static VALUE opt_cache_strings_set(ojParser p, VALUE value) {
|
784
|
-
|
730
|
+
Usual d = (Usual)p->ctx;
|
785
731
|
int limit = NUM2INT(value);
|
786
732
|
|
787
733
|
if (CACHE_MAX_KEY < limit) {
|
@@ -795,13 +741,13 @@ static VALUE opt_cache_strings_set(ojParser p, VALUE value) {
|
|
795
741
|
}
|
796
742
|
|
797
743
|
static VALUE opt_cache_expunge(ojParser p, VALUE value) {
|
798
|
-
|
744
|
+
Usual d = (Usual)p->ctx;
|
799
745
|
|
800
746
|
return INT2NUM((int)d->cache_xrate);
|
801
747
|
}
|
802
748
|
|
803
749
|
static VALUE opt_cache_expunge_set(ojParser p, VALUE value) {
|
804
|
-
|
750
|
+
Usual d = (Usual)p->ctx;
|
805
751
|
int rate = NUM2INT(value);
|
806
752
|
|
807
753
|
if (rate < 0) {
|
@@ -819,13 +765,13 @@ static VALUE opt_cache_expunge_set(ojParser p, VALUE value) {
|
|
819
765
|
}
|
820
766
|
|
821
767
|
static VALUE opt_capacity(ojParser p, VALUE value) {
|
822
|
-
|
768
|
+
Usual d = (Usual)p->ctx;
|
823
769
|
|
824
770
|
return ULONG2NUM(d->vend - d->vhead);
|
825
771
|
}
|
826
772
|
|
827
773
|
static VALUE opt_capacity_set(ojParser p, VALUE value) {
|
828
|
-
|
774
|
+
Usual d = (Usual)p->ctx;
|
829
775
|
long cap = NUM2LONG(value);
|
830
776
|
|
831
777
|
if (d->vend - d->vhead < cap) {
|
@@ -846,13 +792,13 @@ static VALUE opt_capacity_set(ojParser p, VALUE value) {
|
|
846
792
|
}
|
847
793
|
|
848
794
|
static VALUE opt_class_cache(ojParser p, VALUE value) {
|
849
|
-
|
795
|
+
Usual d = (Usual)p->ctx;
|
850
796
|
|
851
797
|
return (NULL != d->class_cache) ? Qtrue : Qfalse;
|
852
798
|
}
|
853
799
|
|
854
800
|
static VALUE opt_class_cache_set(ojParser p, VALUE value) {
|
855
|
-
|
801
|
+
Usual d = (Usual)p->ctx;
|
856
802
|
|
857
803
|
if (Qtrue == value) {
|
858
804
|
if (NULL == d->class_cache) {
|
@@ -866,7 +812,7 @@ static VALUE opt_class_cache_set(ojParser p, VALUE value) {
|
|
866
812
|
}
|
867
813
|
|
868
814
|
static VALUE opt_create_id(ojParser p, VALUE value) {
|
869
|
-
|
815
|
+
Usual d = (Usual)p->ctx;
|
870
816
|
|
871
817
|
if (NULL == d->create_id) {
|
872
818
|
return Qnil;
|
@@ -875,7 +821,7 @@ static VALUE opt_create_id(ojParser p, VALUE value) {
|
|
875
821
|
}
|
876
822
|
|
877
823
|
static VALUE opt_create_id_set(ojParser p, VALUE value) {
|
878
|
-
|
824
|
+
Usual d = (Usual)p->ctx;
|
879
825
|
|
880
826
|
if (Qnil == value) {
|
881
827
|
d->create_id = NULL;
|
@@ -985,13 +931,13 @@ static VALUE opt_decimal_set(ojParser p, VALUE value) {
|
|
985
931
|
}
|
986
932
|
|
987
933
|
static VALUE opt_hash_class(ojParser p, VALUE value) {
|
988
|
-
|
934
|
+
Usual d = (Usual)p->ctx;
|
989
935
|
|
990
936
|
return d->hash_class;
|
991
937
|
}
|
992
938
|
|
993
939
|
static VALUE opt_hash_class_set(ojParser p, VALUE value) {
|
994
|
-
|
940
|
+
Usual d = (Usual)p->ctx;
|
995
941
|
|
996
942
|
if (Qnil != value) {
|
997
943
|
rb_check_type(value, T_CLASS);
|
@@ -1015,13 +961,13 @@ static VALUE opt_hash_class_set(ojParser p, VALUE value) {
|
|
1015
961
|
}
|
1016
962
|
|
1017
963
|
static VALUE opt_ignore_json_create(ojParser p, VALUE value) {
|
1018
|
-
|
964
|
+
Usual d = (Usual)p->ctx;
|
1019
965
|
|
1020
966
|
return d->ignore_json_create ? Qtrue : Qfalse;
|
1021
967
|
}
|
1022
968
|
|
1023
969
|
static VALUE opt_ignore_json_create_set(ojParser p, VALUE value) {
|
1024
|
-
|
970
|
+
Usual d = (Usual)p->ctx;
|
1025
971
|
|
1026
972
|
d->ignore_json_create = (Qtrue == value);
|
1027
973
|
|
@@ -1029,7 +975,7 @@ static VALUE opt_ignore_json_create_set(ojParser p, VALUE value) {
|
|
1029
975
|
}
|
1030
976
|
|
1031
977
|
static VALUE opt_missing_class(ojParser p, VALUE value) {
|
1032
|
-
|
978
|
+
Usual d = (Usual)p->ctx;
|
1033
979
|
|
1034
980
|
switch (d->miss_class) {
|
1035
981
|
case MISS_AUTO: return ID2SYM(rb_intern("auto"));
|
@@ -1040,7 +986,7 @@ static VALUE opt_missing_class(ojParser p, VALUE value) {
|
|
1040
986
|
}
|
1041
987
|
|
1042
988
|
static VALUE opt_missing_class_set(ojParser p, VALUE value) {
|
1043
|
-
|
989
|
+
Usual d = (Usual)p->ctx;
|
1044
990
|
const char * mode;
|
1045
991
|
volatile VALUE s;
|
1046
992
|
|
@@ -1091,13 +1037,13 @@ static VALUE opt_omit_null_set(ojParser p, VALUE value) {
|
|
1091
1037
|
}
|
1092
1038
|
|
1093
1039
|
static VALUE opt_symbol_keys(ojParser p, VALUE value) {
|
1094
|
-
|
1040
|
+
Usual d = (Usual)p->ctx;
|
1095
1041
|
|
1096
1042
|
return (NULL != d->sym_cache) ? Qtrue : Qfalse;
|
1097
1043
|
}
|
1098
1044
|
|
1099
1045
|
static VALUE opt_symbol_keys_set(ojParser p, VALUE value) {
|
1100
|
-
|
1046
|
+
Usual d = (Usual)p->ctx;
|
1101
1047
|
|
1102
1048
|
if (Qtrue == value) {
|
1103
1049
|
d->sym_cache = cache_create(0, form_sym, true, false);
|
@@ -1121,33 +1067,33 @@ static VALUE opt_symbol_keys_set(ojParser p, VALUE value) {
|
|
1121
1067
|
static VALUE option(ojParser p, const char *key, VALUE value) {
|
1122
1068
|
struct opt *op;
|
1123
1069
|
struct opt opts[] = {
|
1124
|
-
|
1125
|
-
|
1126
|
-
|
1127
|
-
|
1128
|
-
|
1129
|
-
|
1130
|
-
|
1131
|
-
|
1132
|
-
|
1133
|
-
|
1134
|
-
|
1135
|
-
|
1136
|
-
|
1137
|
-
|
1138
|
-
|
1139
|
-
|
1140
|
-
|
1141
|
-
|
1142
|
-
|
1143
|
-
|
1144
|
-
|
1145
|
-
|
1146
|
-
|
1147
|
-
|
1148
|
-
|
1149
|
-
|
1150
|
-
|
1070
|
+
{.name = "array_class", .func = opt_array_class},
|
1071
|
+
{.name = "array_class=", .func = opt_array_class_set},
|
1072
|
+
{.name = "cache_keys", .func = opt_cache_keys},
|
1073
|
+
{.name = "cache_keys=", .func = opt_cache_keys_set},
|
1074
|
+
{.name = "cache_strings", .func = opt_cache_strings},
|
1075
|
+
{.name = "cache_strings=", .func = opt_cache_strings_set},
|
1076
|
+
{.name = "cache_expunge", .func = opt_cache_expunge},
|
1077
|
+
{.name = "cache_expunge=", .func = opt_cache_expunge_set},
|
1078
|
+
{.name = "capacity", .func = opt_capacity},
|
1079
|
+
{.name = "capacity=", .func = opt_capacity_set},
|
1080
|
+
{.name = "class_cache", .func = opt_class_cache},
|
1081
|
+
{.name = "class_cache=", .func = opt_class_cache_set},
|
1082
|
+
{.name = "create_id", .func = opt_create_id},
|
1083
|
+
{.name = "create_id=", .func = opt_create_id_set},
|
1084
|
+
{.name = "decimal", .func = opt_decimal},
|
1085
|
+
{.name = "decimal=", .func = opt_decimal_set},
|
1086
|
+
{.name = "hash_class", .func = opt_hash_class},
|
1087
|
+
{.name = "hash_class=", .func = opt_hash_class_set},
|
1088
|
+
{.name = "ignore_json_create", .func = opt_ignore_json_create},
|
1089
|
+
{.name = "ignore_json_create=", .func = opt_ignore_json_create_set},
|
1090
|
+
{.name = "missing_class", .func = opt_missing_class},
|
1091
|
+
{.name = "missing_class=", .func = opt_missing_class_set},
|
1092
|
+
{.name = "omit_null", .func = opt_omit_null},
|
1093
|
+
{.name = "omit_null=", .func = opt_omit_null_set},
|
1094
|
+
{.name = "symbol_keys", .func = opt_symbol_keys},
|
1095
|
+
{.name = "symbol_keys=", .func = opt_symbol_keys_set},
|
1096
|
+
{.name = NULL},
|
1151
1097
|
};
|
1152
1098
|
|
1153
1099
|
for (op = opts; NULL != op->name; op++) {
|
@@ -1162,8 +1108,7 @@ static VALUE option(ojParser p, const char *key, VALUE value) {
|
|
1162
1108
|
|
1163
1109
|
///// the set up //////////////////////////////////////////////////////////////
|
1164
1110
|
|
1165
|
-
void
|
1166
|
-
Delegate d = ALLOC(struct _delegate);
|
1111
|
+
void oj_init_usual(ojParser p, Usual d) {
|
1167
1112
|
int cap = 4096;
|
1168
1113
|
|
1169
1114
|
d->vhead = ALLOC_N(VALUE, cap);
|
@@ -1235,6 +1180,8 @@ void oj_set_parser_usual(ojParser p) {
|
|
1235
1180
|
d->class_cache = NULL;
|
1236
1181
|
d->key_cache = d->str_cache;
|
1237
1182
|
|
1183
|
+
// The parser fields are set but the functions can be replaced by a
|
1184
|
+
// delegate that wraps the usual delegate.
|
1238
1185
|
p->ctx = (void *)d;
|
1239
1186
|
p->option = option;
|
1240
1187
|
p->result = result;
|
@@ -1252,3 +1199,9 @@ void oj_set_parser_usual(ojParser p) {
|
|
1252
1199
|
hset_id = rb_intern("[]=");
|
1253
1200
|
}
|
1254
1201
|
}
|
1202
|
+
|
1203
|
+
void oj_set_parser_usual(ojParser p) {
|
1204
|
+
Usual d = ALLOC(struct _usual);
|
1205
|
+
|
1206
|
+
oj_init_usual(p, d);
|
1207
|
+
}
|
data/ext/oj/usual.h
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
// Copyright (c) 2022, Peter Ohler, All rights reserved.
|
2
|
+
|
3
|
+
#include <ruby.h>
|
4
|
+
#include <stdbool.h>
|
5
|
+
#include <stdint.h>
|
6
|
+
|
7
|
+
struct _cache;
|
8
|
+
struct _ojParser;
|
9
|
+
|
10
|
+
// Used to mark the start of each Hash, Array, or Object. The members point at
|
11
|
+
// positions of the start in the value stack and if not an Array into the key
|
12
|
+
// stack.
|
13
|
+
typedef struct _col {
|
14
|
+
long vi; // value stack index
|
15
|
+
long ki; // key stack index if an hash else -1 for an array
|
16
|
+
} * Col;
|
17
|
+
|
18
|
+
typedef union _key {
|
19
|
+
struct {
|
20
|
+
int16_t len;
|
21
|
+
char buf[30];
|
22
|
+
};
|
23
|
+
struct {
|
24
|
+
int16_t xlen; // should be the same as len
|
25
|
+
char * key;
|
26
|
+
};
|
27
|
+
} * Key;
|
28
|
+
|
29
|
+
#define MISS_AUTO 'A'
|
30
|
+
#define MISS_RAISE 'R'
|
31
|
+
#define MISS_IGNORE 'I'
|
32
|
+
|
33
|
+
typedef struct _usual {
|
34
|
+
VALUE *vhead;
|
35
|
+
VALUE *vtail;
|
36
|
+
VALUE *vend;
|
37
|
+
|
38
|
+
Col chead;
|
39
|
+
Col ctail;
|
40
|
+
Col cend;
|
41
|
+
|
42
|
+
Key khead;
|
43
|
+
Key ktail;
|
44
|
+
Key kend;
|
45
|
+
|
46
|
+
VALUE (*get_key)(ojParser p, Key kp);
|
47
|
+
struct _cache *key_cache; // same as str_cache or sym_cache
|
48
|
+
struct _cache *str_cache;
|
49
|
+
struct _cache *sym_cache;
|
50
|
+
struct _cache *class_cache;
|
51
|
+
struct _cache *attr_cache;
|
52
|
+
|
53
|
+
VALUE array_class;
|
54
|
+
VALUE hash_class;
|
55
|
+
|
56
|
+
char * create_id;
|
57
|
+
uint8_t create_id_len;
|
58
|
+
uint8_t cache_str;
|
59
|
+
uint8_t cache_xrate;
|
60
|
+
uint8_t miss_class;
|
61
|
+
bool cache_keys;
|
62
|
+
bool ignore_json_create;
|
63
|
+
} * Usual;
|
64
|
+
|
65
|
+
// Initialize the parser with the usual delegate. If the usual delegate is
|
66
|
+
// wrapped then this function is called first and then the parser functions
|
67
|
+
// can be replaced.
|
68
|
+
extern void oj_init_usual(struct _ojParser *p, Usual d);
|
data/ext/oj/val_stack.c
CHANGED
data/lib/oj/state.rb
CHANGED
@@ -80,7 +80,7 @@ module JSON
|
|
80
80
|
# @param [Symbol] m method symbol
|
81
81
|
# @return [Boolean] true for any method that matches an instance
|
82
82
|
# variable reader, otherwise false.
|
83
|
-
def respond_to?(m)
|
83
|
+
def respond_to?(m, include_all = false)
|
84
84
|
return true if super
|
85
85
|
return true if has_key?(key)
|
86
86
|
return true if has_key?(key.to_s)
|
data/lib/oj/version.rb
CHANGED
@@ -294,7 +294,9 @@ EOT
|
|
294
294
|
assert_equal '2', state.indent
|
295
295
|
end
|
296
296
|
|
297
|
-
if defined?(JSON::Ext::Generator)
|
297
|
+
if defined?(JSON::Ext::Generator) && Process.respond_to?(:fork)
|
298
|
+
# forking to avoid modifying core class of a parent process and
|
299
|
+
# introducing race conditions of tests are run in parallel
|
298
300
|
def test_broken_bignum # [ruby-core:38867]
|
299
301
|
pid = fork do
|
300
302
|
x = 1 << 64
|
@@ -311,9 +313,6 @@ EOT
|
|
311
313
|
end
|
312
314
|
_, status = Process.waitpid2(pid)
|
313
315
|
assert status.success?
|
314
|
-
rescue NotImplementedError
|
315
|
-
# forking to avoid modifying core class of a parent process and
|
316
|
-
# introducing race conditions of tests are run in parallel
|
317
316
|
end
|
318
317
|
end
|
319
318
|
|
@@ -24,8 +24,6 @@ class JSONParserTest < Test::Unit::TestCase
|
|
24
24
|
end if defined?(Encoding::UTF_16)
|
25
25
|
|
26
26
|
def test_error_message_encoding
|
27
|
-
omit 'TruffleRuby causes NameError(<uninitialized constant JSON::Ext>)' if RUBY_ENGINE == 'truffleruby'
|
28
|
-
|
29
27
|
bug10705 = '[ruby-core:67386] [Bug #10705]'
|
30
28
|
json = ".\"\xE2\x88\x9A\"".force_encoding(Encoding::UTF_8)
|
31
29
|
e = assert_raise(JSON::ParserError) {
|
@@ -33,7 +31,7 @@ class JSONParserTest < Test::Unit::TestCase
|
|
33
31
|
}
|
34
32
|
assert_equal(Encoding::UTF_8, e.message.encoding, bug10705)
|
35
33
|
assert_include(e.message, json, bug10705)
|
36
|
-
end if defined?(Encoding::UTF_8)
|
34
|
+
end if defined?(Encoding::UTF_8) and defined?(JSON::Ext::Parser)
|
37
35
|
|
38
36
|
def test_parsing
|
39
37
|
parser = JSON::Parser.new('"test"')
|