oj 3.11.8 → 3.12.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/oj/compat.c +32 -27
- data/ext/oj/custom.c +3 -15
- data/ext/oj/dump.c +39 -42
- data/ext/oj/dump_strict.c +1 -1
- data/ext/oj/hash.c +41 -4
- data/ext/oj/hash.h +2 -0
- data/ext/oj/mimic_json.c +15 -13
- data/ext/oj/object.c +33 -5
- data/ext/oj/oj.c +116 -33
- data/ext/oj/oj.h +3 -1
- data/ext/oj/parse.h +3 -0
- data/ext/oj/scp.c +4 -16
- data/ext/oj/strict.c +67 -22
- data/ext/oj/wab.c +35 -18
- data/lib/oj/mimic.rb +2 -0
- data/lib/oj/version.rb +1 -1
- data/pages/Modes.md +2 -0
- data/pages/Options.md +23 -5
- data/test/foo.rb +2 -9
- data/test/perf.rb +1 -1
- data/test/perf_scp.rb +11 -10
- data/test/perf_strict.rb +17 -23
- data/test/test_various.rb +2 -0
- metadata +3 -3
data/ext/oj/object.c
CHANGED
@@ -30,11 +30,38 @@ inline static long read_long(const char *str, size_t len) {
|
|
30
30
|
|
31
31
|
static VALUE calc_hash_key(ParseInfo pi, Val kval, char k1) {
|
32
32
|
volatile VALUE rkey;
|
33
|
+
#if 0
|
34
|
+
VALUE *slot;
|
33
35
|
|
36
|
+
if (':' == k1) {
|
37
|
+
if (Qnil == (rkey = oj_sym_hash_get(kval->key + 1, kval->klen - 1, &slot))) {
|
38
|
+
rkey = rb_str_new(kval->key + 1, kval->klen - 1);
|
39
|
+
rkey = oj_encode(rkey);
|
40
|
+
rkey = rb_str_intern(rkey);
|
41
|
+
*slot = rkey;
|
42
|
+
rb_gc_register_address(slot);
|
43
|
+
}
|
44
|
+
} else if (Yes == pi->options.sym_key) {
|
45
|
+
if (Qnil == (rkey = oj_sym_hash_get(kval->key, kval->klen, &slot))) {
|
46
|
+
rkey = rb_str_new(kval->key, kval->klen);
|
47
|
+
rkey = oj_encode(rkey);
|
48
|
+
rkey = rb_str_intern(rkey);
|
49
|
+
*slot = rkey;
|
50
|
+
rb_gc_register_address(slot);
|
51
|
+
}
|
52
|
+
} else {
|
53
|
+
if (Qnil == (rkey = oj_str_hash_get(kval->key, kval->klen, &slot))) {
|
54
|
+
rkey = rb_str_new(kval->key, kval->klen);
|
55
|
+
rkey = oj_encode(rkey);
|
56
|
+
*slot = rkey;
|
57
|
+
rb_gc_register_address(slot);
|
58
|
+
}
|
59
|
+
}
|
60
|
+
#else
|
34
61
|
if (':' == k1) {
|
35
62
|
rkey = rb_str_new(kval->key + 1, kval->klen - 1);
|
36
63
|
rkey = oj_encode(rkey);
|
37
|
-
|
64
|
+
rkey = rb_str_intern(rkey);
|
38
65
|
} else {
|
39
66
|
rkey = rb_str_new(kval->key, kval->klen);
|
40
67
|
rkey = oj_encode(rkey);
|
@@ -42,6 +69,7 @@ static VALUE calc_hash_key(ParseInfo pi, Val kval, char k1) {
|
|
42
69
|
rkey = rb_str_intern(rkey);
|
43
70
|
}
|
44
71
|
}
|
72
|
+
#endif
|
45
73
|
return rkey;
|
46
74
|
}
|
47
75
|
|
@@ -405,22 +433,22 @@ void oj_set_obj_ivar(Val parent, Val kval, VALUE value) {
|
|
405
433
|
char *buf = ALLOC_N(char, klen + 2);
|
406
434
|
|
407
435
|
if ('~' == *key) {
|
408
|
-
|
436
|
+
memcpy(buf, key + 1, klen - 1);
|
409
437
|
buf[klen - 1] = '\0';
|
410
438
|
} else {
|
411
439
|
*buf = '@';
|
412
|
-
|
440
|
+
memcpy(buf + 1, key, klen);
|
413
441
|
buf[klen + 1] = '\0';
|
414
442
|
}
|
415
443
|
var_id = rb_intern(buf);
|
416
444
|
xfree(buf);
|
417
445
|
} else {
|
418
446
|
if ('~' == *key) {
|
419
|
-
|
447
|
+
memcpy(attr, key + 1, klen - 1);
|
420
448
|
attr[klen - 1] = '\0';
|
421
449
|
} else {
|
422
450
|
*attr = '@';
|
423
|
-
|
451
|
+
memcpy(attr + 1, key, klen);
|
424
452
|
attr[klen + 1] = '\0';
|
425
453
|
}
|
426
454
|
var_id = rb_intern(attr);
|
data/ext/oj/oj.c
CHANGED
@@ -40,7 +40,6 @@ ID oj_error_id;
|
|
40
40
|
ID oj_file_id;
|
41
41
|
ID oj_fileno_id;
|
42
42
|
ID oj_ftype_id;
|
43
|
-
ID oj_has_key_id;
|
44
43
|
ID oj_hash_end_id;
|
45
44
|
ID oj_hash_key_id;
|
46
45
|
ID oj_hash_set_id;
|
@@ -106,6 +105,8 @@ static VALUE auto_sym;
|
|
106
105
|
static VALUE bigdecimal_as_decimal_sym;
|
107
106
|
static VALUE bigdecimal_load_sym;
|
108
107
|
static VALUE bigdecimal_sym;
|
108
|
+
static VALUE cache_keys_sym;
|
109
|
+
static VALUE cache_str_sym;
|
109
110
|
static VALUE circular_sym;
|
110
111
|
static VALUE class_cache_sym;
|
111
112
|
static VALUE compat_bigdecimal_sym;
|
@@ -186,6 +187,8 @@ struct _options oj_default_options = {
|
|
186
187
|
No, // safe
|
187
188
|
false, // sec_prec_set
|
188
189
|
No, // ignore_under
|
190
|
+
Yes, // cache_keys
|
191
|
+
3, // cache_str
|
189
192
|
0, // int_range_min
|
190
193
|
0, // int_range_max
|
191
194
|
oj_json_class, // create_id
|
@@ -279,9 +282,11 @@ struct _options oj_default_options = {
|
|
279
282
|
*used
|
280
283
|
* - *:array_class* [_Class_|_nil_] Class to use instead of Array on load
|
281
284
|
* - *:omit_nil* [_true_|_false_] if true Hash and Object attributes with nil values are omitted
|
282
|
-
* - *:ignore* [_nil_|
|
283
|
-
* - *:ignore_under* [
|
285
|
+
* - *:ignore* [_nil_|_Array_] either nil or an Array of classes to ignore when dumping
|
286
|
+
* - *:ignore_under* [_Boolean_] if true then attributes that start with _ are ignored when dumping in
|
284
287
|
*object or custom mode.
|
288
|
+
* - *:cache_keys* [_Boolean_] if true then hash keys are cached
|
289
|
+
* - *:cache_str* [_Fixnum_] maximum string value length to cache
|
285
290
|
* - *:integer_range* [_Range_] Dump integers outside range as strings.
|
286
291
|
* - *:trace* [_true,_|_false_] Trace all load and dump calls, default is false (trace is off)
|
287
292
|
* - *:safe* [_true,_|_false_] Safe mimic breaks JSON mimic to be safer, default is false (safe is
|
@@ -389,11 +394,17 @@ static VALUE get_def_opts(VALUE self) {
|
|
389
394
|
? Qtrue
|
390
395
|
: ((No == oj_default_options.safe) ? Qfalse : Qnil));
|
391
396
|
rb_hash_aset(opts, float_prec_sym, INT2FIX(oj_default_options.float_prec));
|
397
|
+
rb_hash_aset(opts, cache_str_sym, INT2FIX(oj_default_options.cache_str));
|
392
398
|
rb_hash_aset(opts,
|
393
399
|
ignore_under_sym,
|
394
400
|
(Yes == oj_default_options.ignore_under)
|
395
401
|
? Qtrue
|
396
402
|
: ((No == oj_default_options.ignore_under) ? Qfalse : Qnil));
|
403
|
+
rb_hash_aset(opts,
|
404
|
+
cache_keys_sym,
|
405
|
+
(Yes == oj_default_options.cache_keys)
|
406
|
+
? Qtrue
|
407
|
+
: ((No == oj_default_options.cache_keys) ? Qfalse : Qnil));
|
397
408
|
switch (oj_default_options.mode) {
|
398
409
|
case StrictMode: rb_hash_aset(opts, mode_sym, strict_sym); break;
|
399
410
|
case CompatMode: rb_hash_aset(opts, mode_sym, compat_sym); break;
|
@@ -557,6 +568,8 @@ static VALUE get_def_opts(VALUE self) {
|
|
557
568
|
* - *:ignore* [_nil_|Array] either nil or an Array of classes to ignore when dumping
|
558
569
|
* - *:ignore_under* [_Boolean_] if true then attributes that start with _ are ignored when
|
559
570
|
*dumping in object or custom mode.
|
571
|
+
* - *:cache_keys* [_Boolean_] if true then hash keys are cached
|
572
|
+
* - *:cache_str* [_Fixnum_] maximum string vsalue length to cache
|
560
573
|
* - *:integer_range* [_Range_] Dump integers outside range as strings.
|
561
574
|
* - *:trace* [_Boolean_] turn trace on or off.
|
562
575
|
* - *:safe* [_Boolean_] turn safe mimic on or off.
|
@@ -568,6 +581,14 @@ static VALUE set_def_opts(VALUE self, VALUE opts) {
|
|
568
581
|
return Qnil;
|
569
582
|
}
|
570
583
|
|
584
|
+
bool oj_hash_has_key(VALUE hash, VALUE key)
|
585
|
+
{
|
586
|
+
if (Qundef == rb_hash_lookup2(hash, key, Qundef)) {
|
587
|
+
return false;
|
588
|
+
}
|
589
|
+
return true;
|
590
|
+
}
|
591
|
+
|
571
592
|
void oj_parse_options(VALUE ropts, Options copts) {
|
572
593
|
struct _yesNoOpt ynos[] = {{circular_sym, &copts->circular},
|
573
594
|
{auto_define_sym, &copts->auto_define},
|
@@ -589,6 +610,7 @@ void oj_parse_options(VALUE ropts, Options copts) {
|
|
589
610
|
{oj_safe_sym, &copts->safe},
|
590
611
|
{ignore_under_sym, &copts->ignore_under},
|
591
612
|
{oj_create_additions_sym, &copts->create_ok},
|
613
|
+
{cache_keys_sym, &copts->cache_keys},
|
592
614
|
{Qnil, 0}};
|
593
615
|
YesNoOpt o;
|
594
616
|
volatile VALUE v;
|
@@ -597,7 +619,7 @@ void oj_parse_options(VALUE ropts, Options copts) {
|
|
597
619
|
if (T_HASH != rb_type(ropts)) {
|
598
620
|
return;
|
599
621
|
}
|
600
|
-
if (
|
622
|
+
if (oj_hash_has_key(ropts, oj_indent_sym)) {
|
601
623
|
v = rb_hash_lookup(ropts, oj_indent_sym);
|
602
624
|
switch (rb_type(v)) {
|
603
625
|
case T_NIL:
|
@@ -647,6 +669,28 @@ void oj_parse_options(VALUE ropts, Options copts) {
|
|
647
669
|
copts->float_prec = n;
|
648
670
|
}
|
649
671
|
}
|
672
|
+
if (Qnil != (v = rb_hash_lookup(ropts, cache_str_sym))) {
|
673
|
+
int n;
|
674
|
+
|
675
|
+
#ifdef RUBY_INTEGER_UNIFICATION
|
676
|
+
if (rb_cInteger != rb_obj_class(v)) {
|
677
|
+
rb_raise(rb_eArgError, ":cache_str must be a Integer.");
|
678
|
+
}
|
679
|
+
#else
|
680
|
+
if (T_FIXNUM != rb_type(v)) {
|
681
|
+
rb_raise(rb_eArgError, ":cache_str must be a Fixnum.");
|
682
|
+
}
|
683
|
+
#endif
|
684
|
+
n = FIX2INT(v);
|
685
|
+
if (0 >= n) {
|
686
|
+
copts->cache_str = 0;
|
687
|
+
} else {
|
688
|
+
if (32 < n) {
|
689
|
+
n = 32;
|
690
|
+
}
|
691
|
+
copts->cache_str = (char)n;
|
692
|
+
}
|
693
|
+
}
|
650
694
|
if (Qnil != (v = rb_hash_lookup(ropts, sec_prec_sym))) {
|
651
695
|
int n;
|
652
696
|
|
@@ -736,7 +780,7 @@ void oj_parse_options(VALUE ropts, Options copts) {
|
|
736
780
|
if (Qnil != (v = rb_hash_lookup(ropts, compat_bigdecimal_sym))) {
|
737
781
|
copts->compat_bigdec = (Qtrue == v);
|
738
782
|
}
|
739
|
-
if (
|
783
|
+
if (oj_hash_has_key(ropts, oj_decimal_class_sym)) {
|
740
784
|
v = rb_hash_lookup(ropts, oj_decimal_class_sym);
|
741
785
|
if (rb_cFloat == v) {
|
742
786
|
copts->compat_bigdec = false;
|
@@ -746,7 +790,7 @@ void oj_parse_options(VALUE ropts, Options copts) {
|
|
746
790
|
rb_raise(rb_eArgError, ":decimal_class must be BigDecimal or Float.");
|
747
791
|
}
|
748
792
|
}
|
749
|
-
if (
|
793
|
+
if (oj_hash_has_key(ropts, create_id_sym)) {
|
750
794
|
v = rb_hash_lookup(ropts, create_id_sym);
|
751
795
|
if (Qnil == v) {
|
752
796
|
if (oj_json_class != oj_default_options.create_id && NULL != copts->create_id) {
|
@@ -768,7 +812,7 @@ void oj_parse_options(VALUE ropts, Options copts) {
|
|
768
812
|
}
|
769
813
|
}
|
770
814
|
for (o = ynos; 0 != o->attr; o++) {
|
771
|
-
if (
|
815
|
+
if (oj_hash_has_key(ropts, o->sym)) {
|
772
816
|
v = rb_hash_lookup(ropts, o->sym);
|
773
817
|
if (Qnil == v) {
|
774
818
|
*o->attr = NotSet;
|
@@ -783,7 +827,7 @@ void oj_parse_options(VALUE ropts, Options copts) {
|
|
783
827
|
}
|
784
828
|
}
|
785
829
|
}
|
786
|
-
if (
|
830
|
+
if (oj_hash_has_key(ropts, oj_space_sym)) {
|
787
831
|
if (Qnil == (v = rb_hash_lookup(ropts, oj_space_sym))) {
|
788
832
|
copts->dump_opts.after_size = 0;
|
789
833
|
*copts->dump_opts.after_sep = '\0';
|
@@ -798,7 +842,7 @@ void oj_parse_options(VALUE ropts, Options copts) {
|
|
798
842
|
copts->dump_opts.after_size = (uint8_t)len;
|
799
843
|
}
|
800
844
|
}
|
801
|
-
if (
|
845
|
+
if (oj_hash_has_key(ropts, oj_space_before_sym)) {
|
802
846
|
if (Qnil == (v = rb_hash_lookup(ropts, oj_space_before_sym))) {
|
803
847
|
copts->dump_opts.before_size = 0;
|
804
848
|
*copts->dump_opts.before_sep = '\0';
|
@@ -813,7 +857,7 @@ void oj_parse_options(VALUE ropts, Options copts) {
|
|
813
857
|
copts->dump_opts.before_size = (uint8_t)len;
|
814
858
|
}
|
815
859
|
}
|
816
|
-
if (
|
860
|
+
if (oj_hash_has_key(ropts, oj_object_nl_sym)) {
|
817
861
|
if (Qnil == (v = rb_hash_lookup(ropts, oj_object_nl_sym))) {
|
818
862
|
copts->dump_opts.hash_size = 0;
|
819
863
|
*copts->dump_opts.hash_nl = '\0';
|
@@ -828,7 +872,7 @@ void oj_parse_options(VALUE ropts, Options copts) {
|
|
828
872
|
copts->dump_opts.hash_size = (uint8_t)len;
|
829
873
|
}
|
830
874
|
}
|
831
|
-
if (
|
875
|
+
if (oj_hash_has_key(ropts, oj_array_nl_sym)) {
|
832
876
|
if (Qnil == (v = rb_hash_lookup(ropts, oj_array_nl_sym))) {
|
833
877
|
copts->dump_opts.array_size = 0;
|
834
878
|
*copts->dump_opts.array_nl = '\0';
|
@@ -877,7 +921,7 @@ void oj_parse_options(VALUE ropts, Options copts) {
|
|
877
921
|
} else if (Qfalse == v) {
|
878
922
|
copts->escape_mode = JSONEsc;
|
879
923
|
}
|
880
|
-
if (
|
924
|
+
if (oj_hash_has_key(ropts, oj_hash_class_sym)) {
|
881
925
|
if (Qnil == (v = rb_hash_lookup(ropts, oj_hash_class_sym))) {
|
882
926
|
copts->hash_class = Qnil;
|
883
927
|
} else {
|
@@ -885,7 +929,7 @@ void oj_parse_options(VALUE ropts, Options copts) {
|
|
885
929
|
copts->hash_class = v;
|
886
930
|
}
|
887
931
|
}
|
888
|
-
if (
|
932
|
+
if (oj_hash_has_key(ropts, oj_object_class_sym)) {
|
889
933
|
if (Qnil == (v = rb_hash_lookup(ropts, oj_object_class_sym))) {
|
890
934
|
copts->hash_class = Qnil;
|
891
935
|
} else {
|
@@ -893,7 +937,7 @@ void oj_parse_options(VALUE ropts, Options copts) {
|
|
893
937
|
copts->hash_class = v;
|
894
938
|
}
|
895
939
|
}
|
896
|
-
if (
|
940
|
+
if (oj_hash_has_key(ropts, oj_array_class_sym)) {
|
897
941
|
if (Qnil == (v = rb_hash_lookup(ropts, oj_array_class_sym))) {
|
898
942
|
copts->array_class = Qnil;
|
899
943
|
} else {
|
@@ -902,7 +946,7 @@ void oj_parse_options(VALUE ropts, Options copts) {
|
|
902
946
|
}
|
903
947
|
}
|
904
948
|
oj_parse_opt_match_string(&copts->str_rx, ropts);
|
905
|
-
if (
|
949
|
+
if (oj_hash_has_key(ropts, ignore_sym)) {
|
906
950
|
xfree(copts->ignore);
|
907
951
|
copts->ignore = NULL;
|
908
952
|
if (Qnil != (v = rb_hash_lookup(ropts, ignore_sym))) {
|
@@ -1200,6 +1244,38 @@ static VALUE safe_load(VALUE self, VALUE doc) {
|
|
1200
1244
|
* - *io* [_IO__|_String_] IO Object to read from
|
1201
1245
|
*/
|
1202
1246
|
|
1247
|
+
struct dump_arg {
|
1248
|
+
struct _out *out;
|
1249
|
+
struct _options *copts;
|
1250
|
+
int argc;
|
1251
|
+
VALUE *argv;
|
1252
|
+
};
|
1253
|
+
|
1254
|
+
static VALUE dump_body(VALUE a)
|
1255
|
+
{
|
1256
|
+
volatile struct dump_arg *arg = (void *)a;
|
1257
|
+
VALUE rstr;
|
1258
|
+
|
1259
|
+
oj_dump_obj_to_json_using_params(*arg->argv, arg->copts, arg->out, arg->argc - 1, arg->argv + 1);
|
1260
|
+
if (0 == arg->out->buf) {
|
1261
|
+
rb_raise(rb_eNoMemError, "Not enough memory.");
|
1262
|
+
}
|
1263
|
+
rstr = rb_str_new2(arg->out->buf);
|
1264
|
+
rstr = oj_encode(rstr);
|
1265
|
+
|
1266
|
+
return rstr;
|
1267
|
+
}
|
1268
|
+
|
1269
|
+
static VALUE dump_ensure(VALUE a)
|
1270
|
+
{
|
1271
|
+
volatile struct dump_arg *arg = (void *)a;
|
1272
|
+
|
1273
|
+
if (arg->out->allocated) {
|
1274
|
+
xfree(arg->out->buf);
|
1275
|
+
}
|
1276
|
+
return Qnil;
|
1277
|
+
}
|
1278
|
+
|
1203
1279
|
/* Document-method: dump
|
1204
1280
|
* call-seq: dump(obj, options={})
|
1205
1281
|
*
|
@@ -1209,9 +1285,9 @@ static VALUE safe_load(VALUE self, VALUE doc) {
|
|
1209
1285
|
*/
|
1210
1286
|
static VALUE dump(int argc, VALUE *argv, VALUE self) {
|
1211
1287
|
char buf[4096];
|
1288
|
+
struct dump_arg arg;
|
1212
1289
|
struct _out out;
|
1213
1290
|
struct _options copts = oj_default_options;
|
1214
|
-
VALUE rstr;
|
1215
1291
|
|
1216
1292
|
if (1 > argc) {
|
1217
1293
|
rb_raise(rb_eArgError, "wrong number of arguments (0 for 1).");
|
@@ -1225,21 +1301,18 @@ static VALUE dump(int argc, VALUE *argv, VALUE self) {
|
|
1225
1301
|
if (CompatMode == copts.mode && copts.escape_mode != ASCIIEsc) {
|
1226
1302
|
copts.escape_mode = JSONEsc;
|
1227
1303
|
}
|
1228
|
-
out
|
1229
|
-
|
1230
|
-
|
1231
|
-
|
1232
|
-
|
1233
|
-
|
1234
|
-
|
1235
|
-
|
1236
|
-
|
1237
|
-
|
1238
|
-
|
1239
|
-
|
1240
|
-
xfree(out.buf);
|
1241
|
-
}
|
1242
|
-
return rstr;
|
1304
|
+
arg.out = &out;
|
1305
|
+
arg.copts = &copts;
|
1306
|
+
arg.argc = argc;
|
1307
|
+
arg.argv = argv;
|
1308
|
+
|
1309
|
+
arg.out->buf = buf;
|
1310
|
+
arg.out->end = buf + sizeof(buf) - 10;
|
1311
|
+
arg.out->allocated = false;
|
1312
|
+
arg.out->omit_nil = copts.dump_opts.omit_nil;
|
1313
|
+
arg.out->caller = CALLER_DUMP;
|
1314
|
+
|
1315
|
+
return rb_ensure(dump_body, (VALUE)&arg, dump_ensure, (VALUE)&arg);
|
1243
1316
|
}
|
1244
1317
|
|
1245
1318
|
/* Document-method: to_json
|
@@ -1636,13 +1709,20 @@ extern VALUE oj_optimize_rails(VALUE self);
|
|
1636
1709
|
|
1637
1710
|
/*
|
1638
1711
|
extern void oj_hash_test();
|
1639
|
-
|
1640
1712
|
static VALUE
|
1641
1713
|
hash_test(VALUE self) {
|
1642
1714
|
oj_hash_test();
|
1643
1715
|
return Qnil;
|
1644
1716
|
}
|
1645
1717
|
*/
|
1718
|
+
/*
|
1719
|
+
extern void oj_hash_sizes();
|
1720
|
+
static VALUE
|
1721
|
+
hash_test(VALUE self) {
|
1722
|
+
oj_hash_sizes();
|
1723
|
+
return Qnil;
|
1724
|
+
}
|
1725
|
+
*/
|
1646
1726
|
|
1647
1727
|
static VALUE protect_require(VALUE x) {
|
1648
1728
|
rb_require("time");
|
@@ -1741,7 +1821,6 @@ void Init_oj() {
|
|
1741
1821
|
oj_file_id = rb_intern("file?");
|
1742
1822
|
oj_fileno_id = rb_intern("fileno");
|
1743
1823
|
oj_ftype_id = rb_intern("ftype");
|
1744
|
-
oj_has_key_id = rb_intern("has_key?");
|
1745
1824
|
oj_hash_end_id = rb_intern("hash_end");
|
1746
1825
|
oj_hash_key_id = rb_intern("hash_key");
|
1747
1826
|
oj_hash_set_id = rb_intern("hash_set");
|
@@ -1816,6 +1895,10 @@ void Init_oj() {
|
|
1816
1895
|
rb_gc_register_address(&bigdecimal_load_sym);
|
1817
1896
|
bigdecimal_sym = ID2SYM(rb_intern("bigdecimal"));
|
1818
1897
|
rb_gc_register_address(&bigdecimal_sym);
|
1898
|
+
cache_keys_sym = ID2SYM(rb_intern("cache_keys"));
|
1899
|
+
rb_gc_register_address(&cache_keys_sym);
|
1900
|
+
cache_str_sym = ID2SYM(rb_intern("cache_str"));
|
1901
|
+
rb_gc_register_address(&cache_str_sym);
|
1819
1902
|
circular_sym = ID2SYM(rb_intern("circular"));
|
1820
1903
|
rb_gc_register_address(&circular_sym);
|
1821
1904
|
class_cache_sym = ID2SYM(rb_intern("class_cache"));
|
data/ext/oj/oj.h
CHANGED
@@ -143,6 +143,8 @@ typedef struct _options {
|
|
143
143
|
char safe; // YesNo
|
144
144
|
char sec_prec_set; // boolean (0 or 1)
|
145
145
|
char ignore_under; // YesNo - ignore attrs starting with _ if true in object and custom modes
|
146
|
+
char cache_keys; // YexNo
|
147
|
+
char cache_str; // string short than or equal to this are cache
|
146
148
|
int64_t int_range_min; // dump numbers below as string
|
147
149
|
int64_t int_range_max; // dump numbers above as string
|
148
150
|
const char * create_id; // 0 or string
|
@@ -243,6 +245,7 @@ extern VALUE oj_compat_parse_cstr(int argc, VALUE *argv, char *json, size_t len)
|
|
243
245
|
extern VALUE oj_object_parse_cstr(int argc, VALUE *argv, char *json, size_t len);
|
244
246
|
extern VALUE oj_custom_parse_cstr(int argc, VALUE *argv, char *json, size_t len);
|
245
247
|
|
248
|
+
extern bool oj_hash_has_key(VALUE hash, VALUE key);
|
246
249
|
extern void oj_parse_options(VALUE ropts, Options copts);
|
247
250
|
|
248
251
|
extern void oj_dump_obj_to_json(VALUE obj, Options copts, Out out);
|
@@ -325,7 +328,6 @@ extern ID oj_exclude_end_id;
|
|
325
328
|
extern ID oj_file_id;
|
326
329
|
extern ID oj_fileno_id;
|
327
330
|
extern ID oj_ftype_id;
|
328
|
-
extern ID oj_has_key_id;
|
329
331
|
extern ID oj_hash_end_id;
|
330
332
|
extern ID oj_hash_key_id;
|
331
333
|
extern ID oj_hash_set_id;
|
data/ext/oj/parse.h
CHANGED
@@ -90,6 +90,9 @@ extern void oj_set_wab_callbacks(ParseInfo pi);
|
|
90
90
|
extern void oj_sparse2(ParseInfo pi);
|
91
91
|
extern VALUE oj_pi_sparse(int argc, VALUE *argv, ParseInfo pi, int fd);
|
92
92
|
|
93
|
+
extern VALUE oj_cstr_to_value(const char *str, size_t len, size_t cache_str);
|
94
|
+
extern VALUE oj_calc_hash_key(ParseInfo pi, Val parent);
|
95
|
+
|
93
96
|
static inline void parse_info_init(ParseInfo pi) {
|
94
97
|
memset(pi, 0, sizeof(struct _parseInfo));
|
95
98
|
}
|
data/ext/oj/scp.c
CHANGED
@@ -9,6 +9,7 @@
|
|
9
9
|
#include <unistd.h>
|
10
10
|
|
11
11
|
#include "encode.h"
|
12
|
+
#include "hash.h"
|
12
13
|
#include "oj.h"
|
13
14
|
#include "parse.h"
|
14
15
|
|
@@ -82,19 +83,6 @@ static void end_array(ParseInfo pi) {
|
|
82
83
|
rb_funcall(pi->handler, oj_array_end_id, 0);
|
83
84
|
}
|
84
85
|
|
85
|
-
static VALUE calc_hash_key(ParseInfo pi, Val kval) {
|
86
|
-
volatile VALUE rkey = kval->key_val;
|
87
|
-
|
88
|
-
if (Qundef == rkey) {
|
89
|
-
rkey = rb_str_new(kval->key, kval->klen);
|
90
|
-
rkey = oj_encode(rkey);
|
91
|
-
if (Yes == pi->options.sym_key) {
|
92
|
-
rkey = rb_str_intern(rkey);
|
93
|
-
}
|
94
|
-
}
|
95
|
-
return rkey;
|
96
|
-
}
|
97
|
-
|
98
86
|
static VALUE hash_key(ParseInfo pi, const char *key, size_t klen) {
|
99
87
|
return rb_funcall(pi->handler, oj_hash_key_id, 1, rb_str_new(key, klen));
|
100
88
|
}
|
@@ -107,7 +95,7 @@ static void hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, c
|
|
107
95
|
oj_hash_set_id,
|
108
96
|
3,
|
109
97
|
stack_peek(&pi->stack)->val,
|
110
|
-
|
98
|
+
oj_calc_hash_key(pi, kval),
|
111
99
|
rstr);
|
112
100
|
}
|
113
101
|
|
@@ -116,7 +104,7 @@ static void hash_set_num(ParseInfo pi, Val kval, NumInfo ni) {
|
|
116
104
|
oj_hash_set_id,
|
117
105
|
3,
|
118
106
|
stack_peek(&pi->stack)->val,
|
119
|
-
|
107
|
+
oj_calc_hash_key(pi, kval),
|
120
108
|
oj_num_as_value(ni));
|
121
109
|
}
|
122
110
|
|
@@ -125,7 +113,7 @@ static void hash_set_value(ParseInfo pi, Val kval, VALUE value) {
|
|
125
113
|
oj_hash_set_id,
|
126
114
|
3,
|
127
115
|
stack_peek(&pi->stack)->val,
|
128
|
-
|
116
|
+
oj_calc_hash_key(pi, kval),
|
129
117
|
value);
|
130
118
|
}
|
131
119
|
|