oj 3.13.11 → 3.13.13
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/ext/oj/circarray.c +1 -1
- data/ext/oj/code.c +15 -22
- data/ext/oj/custom.c +28 -55
- data/ext/oj/dump.c +65 -87
- data/ext/oj/dump.h +12 -8
- data/ext/oj/dump_compat.c +43 -80
- data/ext/oj/dump_leaf.c +14 -58
- data/ext/oj/dump_object.c +28 -96
- data/ext/oj/dump_strict.c +12 -24
- data/ext/oj/fast.c +9 -9
- data/ext/oj/intern.c +9 -2
- data/ext/oj/intern.h +1 -1
- data/ext/oj/mimic_json.c +25 -23
- data/ext/oj/odd.c +83 -63
- data/ext/oj/odd.h +13 -13
- data/ext/oj/oj.c +28 -16
- data/ext/oj/oj.h +20 -2
- data/ext/oj/parse.c +3 -2
- data/ext/oj/parser.c +10 -15
- data/ext/oj/rails.c +38 -57
- data/ext/oj/rails.h +1 -1
- data/ext/oj/reader.c +2 -0
- data/ext/oj/saj.c +11 -23
- data/ext/oj/stream_writer.c +3 -1
- data/ext/oj/string_writer.c +12 -5
- data/ext/oj/wab.c +8 -8
- data/lib/oj/version.rb +1 -1
- data/test/bar.rb +1 -8
- data/test/foo.rb +3 -3
- data/test/perf_dump.rb +50 -0
- data/test/test_object.rb +12 -7
- metadata +5 -3
data/ext/oj/dump.c
CHANGED
@@ -234,7 +234,7 @@ inline static void dump_hex(uint8_t c, Out out) {
|
|
234
234
|
static void raise_invalid_unicode(const char *str, int len, int pos) {
|
235
235
|
char c;
|
236
236
|
char code[32];
|
237
|
-
char
|
237
|
+
char *cp = code;
|
238
238
|
int i;
|
239
239
|
uint8_t d;
|
240
240
|
|
@@ -291,14 +291,12 @@ static const char *dump_unicode(const char *str, const char *end, Out out, const
|
|
291
291
|
code -= 0x00010000;
|
292
292
|
c1 = ((code >> 10) & 0x000003FF) + 0x0000D800;
|
293
293
|
code = (code & 0x000003FF) + 0x0000DC00;
|
294
|
-
|
295
|
-
*out->cur++ = 'u';
|
294
|
+
APPEND_CHARS(out->cur, "\\u", 2);
|
296
295
|
for (i = 3; 0 <= i; i--) {
|
297
296
|
*out->cur++ = hex_chars[(uint8_t)(c1 >> (i * 4)) & 0x0F];
|
298
297
|
}
|
299
298
|
}
|
300
|
-
|
301
|
-
*out->cur++ = 'u';
|
299
|
+
APPEND_CHARS(out->cur, "\\u", 2);
|
302
300
|
for (i = 3; 0 <= i; i--) {
|
303
301
|
*out->cur++ = hex_chars[(uint8_t)(code >> (i * 4)) & 0x0F];
|
304
302
|
}
|
@@ -347,9 +345,7 @@ long oj_check_circular(VALUE obj, Out out) {
|
|
347
345
|
} else {
|
348
346
|
if (ObjectMode == out->opts->mode) {
|
349
347
|
assure_size(out, 18);
|
350
|
-
|
351
|
-
*out->cur++ = '^';
|
352
|
-
*out->cur++ = 'r';
|
348
|
+
APPEND_CHARS(out->cur, "\"^r", 3);
|
353
349
|
dump_ulong(id, out);
|
354
350
|
*out->cur++ = '"';
|
355
351
|
}
|
@@ -361,9 +357,9 @@ long oj_check_circular(VALUE obj, Out out) {
|
|
361
357
|
|
362
358
|
void oj_dump_time(VALUE obj, Out out, int withZone) {
|
363
359
|
char buf[64];
|
364
|
-
char
|
360
|
+
char *b = buf + sizeof(buf) - 1;
|
365
361
|
long size;
|
366
|
-
char
|
362
|
+
char *dot;
|
367
363
|
int neg = 0;
|
368
364
|
long one = 1000000000;
|
369
365
|
long long sec;
|
@@ -379,12 +375,12 @@ void oj_dump_time(VALUE obj, Out out, int withZone) {
|
|
379
375
|
sec = (long long)ts.tv_sec;
|
380
376
|
nsec = ts.tv_nsec;
|
381
377
|
} else {
|
382
|
-
sec =
|
383
|
-
nsec =
|
378
|
+
sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
379
|
+
nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
384
380
|
}
|
385
381
|
#else
|
386
|
-
sec =
|
387
|
-
nsec =
|
382
|
+
sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
383
|
+
nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
388
384
|
#endif
|
389
385
|
|
390
386
|
*b-- = '\0';
|
@@ -451,8 +447,7 @@ void oj_dump_time(VALUE obj, Out out, int withZone) {
|
|
451
447
|
b++;
|
452
448
|
size = sizeof(buf) - (b - buf) - 1;
|
453
449
|
assure_size(out, size);
|
454
|
-
|
455
|
-
out->cur += size;
|
450
|
+
APPEND_CHARS(out->cur, b, size);
|
456
451
|
*out->cur = '\0';
|
457
452
|
}
|
458
453
|
|
@@ -479,12 +474,12 @@ void oj_dump_xml_time(VALUE obj, Out out) {
|
|
479
474
|
sec = ts.tv_sec;
|
480
475
|
nsec = ts.tv_nsec;
|
481
476
|
} else {
|
482
|
-
sec =
|
483
|
-
nsec =
|
477
|
+
sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
478
|
+
nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
484
479
|
}
|
485
480
|
#else
|
486
|
-
sec =
|
487
|
-
nsec =
|
481
|
+
sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
482
|
+
nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
488
483
|
#endif
|
489
484
|
|
490
485
|
assure_size(out, 36);
|
@@ -565,12 +560,8 @@ void oj_dump_obj_to_json(VALUE obj, Options copts, Out out) {
|
|
565
560
|
|
566
561
|
void oj_dump_obj_to_json_using_params(VALUE obj, Options copts, Out out, int argc, VALUE *argv) {
|
567
562
|
if (0 == out->buf) {
|
568
|
-
out
|
569
|
-
// 1 less than end plus extra for possible errors
|
570
|
-
out->end = out->buf + 4095 - BUFFER_EXTRA;
|
571
|
-
out->allocated = true;
|
563
|
+
oj_out_init(out);
|
572
564
|
}
|
573
|
-
out->cur = out->buf;
|
574
565
|
out->circ_cnt = 0;
|
575
566
|
out->opts = copts;
|
576
567
|
out->hash_cnt = 0;
|
@@ -605,36 +596,35 @@ void oj_dump_obj_to_json_using_params(VALUE obj, Options copts, Out out, int arg
|
|
605
596
|
}
|
606
597
|
|
607
598
|
void oj_write_obj_to_file(VALUE obj, const char *path, Options copts) {
|
608
|
-
char buf[4096];
|
609
599
|
struct _out out;
|
610
600
|
size_t size;
|
611
|
-
FILE
|
601
|
+
FILE *f;
|
612
602
|
int ok;
|
613
603
|
|
614
|
-
out
|
615
|
-
|
616
|
-
out.allocated = false;
|
604
|
+
oj_out_init(&out);
|
605
|
+
|
617
606
|
out.omit_nil = copts->dump_opts.omit_nil;
|
618
607
|
oj_dump_obj_to_json(obj, copts, &out);
|
619
608
|
size = out.cur - out.buf;
|
620
609
|
if (0 == (f = fopen(path, "w"))) {
|
621
|
-
|
622
|
-
xfree(out.buf);
|
623
|
-
}
|
610
|
+
oj_out_free(&out);
|
624
611
|
rb_raise(rb_eIOError, "%s", strerror(errno));
|
625
612
|
}
|
626
613
|
ok = (size == fwrite(out.buf, 1, size, f));
|
627
|
-
|
628
|
-
|
629
|
-
|
614
|
+
|
615
|
+
oj_out_free(&out);
|
616
|
+
|
630
617
|
fclose(f);
|
631
618
|
if (!ok) {
|
632
619
|
int err = ferror(f);
|
620
|
+
fclose(f);
|
633
621
|
|
634
622
|
rb_raise(rb_eIOError, "Write failed. [%d:%s]", err, strerror(err));
|
635
623
|
}
|
624
|
+
fclose(f);
|
636
625
|
}
|
637
626
|
|
627
|
+
#if !IS_WINDOWS
|
638
628
|
static void write_ready(int fd) {
|
639
629
|
struct pollfd pp;
|
640
630
|
int i;
|
@@ -649,9 +639,9 @@ static void write_ready(int fd) {
|
|
649
639
|
rb_raise(rb_eIOError, "write failed. %d %s.", errno, strerror(errno));
|
650
640
|
}
|
651
641
|
}
|
642
|
+
#endif
|
652
643
|
|
653
644
|
void oj_write_obj_to_stream(VALUE obj, VALUE stream, Options copts) {
|
654
|
-
char buf[4096];
|
655
645
|
struct _out out;
|
656
646
|
ssize_t size;
|
657
647
|
VALUE clas = rb_obj_class(stream);
|
@@ -660,9 +650,8 @@ void oj_write_obj_to_stream(VALUE obj, VALUE stream, Options copts) {
|
|
660
650
|
VALUE s;
|
661
651
|
#endif
|
662
652
|
|
663
|
-
out
|
664
|
-
|
665
|
-
out.allocated = false;
|
653
|
+
oj_out_init(&out);
|
654
|
+
|
666
655
|
out.omit_nil = copts->dump_opts.omit_nil;
|
667
656
|
oj_dump_obj_to_json(obj, copts, &out);
|
668
657
|
size = out.cur - out.buf;
|
@@ -692,20 +681,17 @@ void oj_write_obj_to_stream(VALUE obj, VALUE stream, Options copts) {
|
|
692
681
|
} else if (rb_respond_to(stream, oj_write_id)) {
|
693
682
|
rb_funcall(stream, oj_write_id, 1, rb_str_new(out.buf, size));
|
694
683
|
} else {
|
695
|
-
|
696
|
-
xfree(out.buf);
|
697
|
-
}
|
684
|
+
oj_out_free(&out);
|
698
685
|
rb_raise(rb_eArgError, "to_stream() expected an IO Object.");
|
699
686
|
}
|
700
|
-
|
701
|
-
xfree(out.buf);
|
702
|
-
}
|
687
|
+
oj_out_free(&out);
|
703
688
|
}
|
704
689
|
|
705
690
|
void oj_dump_str(VALUE obj, int depth, Out out, bool as_ok) {
|
706
|
-
|
691
|
+
int idx = RB_ENCODING_GET(obj);
|
707
692
|
|
708
|
-
if (
|
693
|
+
if (oj_utf8_encoding_index != idx) {
|
694
|
+
rb_encoding *enc = rb_enc_from_index(idx);
|
709
695
|
obj = rb_str_conv_enc(obj, enc, oj_utf8_encoding);
|
710
696
|
}
|
711
697
|
oj_dump_cstr(RSTRING_PTR(obj), (int)RSTRING_LEN(obj), 0, 0, out);
|
@@ -719,7 +705,7 @@ void oj_dump_sym(VALUE obj, int depth, Out out, bool as_ok) {
|
|
719
705
|
|
720
706
|
static void debug_raise(const char *orig, size_t cnt, int line) {
|
721
707
|
char buf[1024];
|
722
|
-
char
|
708
|
+
char *b = buf;
|
723
709
|
const char *s = orig;
|
724
710
|
const char *s_end = s + cnt;
|
725
711
|
|
@@ -758,7 +744,7 @@ void oj_dump_raw_json(VALUE obj, int depth, Out out) {
|
|
758
744
|
|
759
745
|
void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out out) {
|
760
746
|
size_t size;
|
761
|
-
char
|
747
|
+
char *cmap;
|
762
748
|
const char *orig = str;
|
763
749
|
bool has_hi = false;
|
764
750
|
|
@@ -803,10 +789,7 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
|
|
803
789
|
*out->cur++ = '"';
|
804
790
|
|
805
791
|
if (escape1) {
|
806
|
-
|
807
|
-
*out->cur++ = 'u';
|
808
|
-
*out->cur++ = '0';
|
809
|
-
*out->cur++ = '0';
|
792
|
+
APPEND_CHARS(out->cur, "\\u00", 4);
|
810
793
|
dump_hex((uint8_t)*str, out);
|
811
794
|
cnt--;
|
812
795
|
size--;
|
@@ -817,8 +800,7 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
|
|
817
800
|
if (is_sym) {
|
818
801
|
*out->cur++ = ':';
|
819
802
|
}
|
820
|
-
|
821
|
-
out->cur += cnt;
|
803
|
+
APPEND_CHARS(out->cur, str, cnt);
|
822
804
|
*out->cur++ = '"';
|
823
805
|
} else {
|
824
806
|
const char *end = str + cnt;
|
@@ -868,10 +850,7 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
|
|
868
850
|
break;
|
869
851
|
case '6': // control characters
|
870
852
|
if (*(uint8_t *)str < 0x80) {
|
871
|
-
|
872
|
-
*out->cur++ = 'u';
|
873
|
-
*out->cur++ = '0';
|
874
|
-
*out->cur++ = '0';
|
853
|
+
APPEND_CHARS(out->cur, "\\u00", 4);
|
875
854
|
dump_hex((uint8_t)*str, out);
|
876
855
|
} else {
|
877
856
|
if (0xe2 == (uint8_t)*str &&
|
@@ -950,15 +929,27 @@ void oj_dump_obj_to_s(VALUE obj, Out out) {
|
|
950
929
|
|
951
930
|
void oj_dump_raw(const char *str, size_t cnt, Out out) {
|
952
931
|
assure_size(out, cnt + 10);
|
953
|
-
|
954
|
-
out->cur += cnt;
|
932
|
+
APPEND_CHARS(out->cur, str, cnt);
|
955
933
|
*out->cur = '\0';
|
956
934
|
}
|
957
935
|
|
936
|
+
void oj_out_init(Out out) {
|
937
|
+
out->buf = out->stack_buffer;
|
938
|
+
out->cur = out->buf;
|
939
|
+
out->end = out->buf + sizeof(out->stack_buffer) - BUFFER_EXTRA;
|
940
|
+
out->allocated = false;
|
941
|
+
}
|
942
|
+
|
943
|
+
void oj_out_free(Out out) {
|
944
|
+
if (out->allocated) {
|
945
|
+
xfree(out->buf); // TBD
|
946
|
+
}
|
947
|
+
}
|
948
|
+
|
958
949
|
void oj_grow_out(Out out, size_t len) {
|
959
950
|
size_t size = out->end - out->buf;
|
960
951
|
long pos = out->cur - out->buf;
|
961
|
-
char
|
952
|
+
char *buf = out->buf;
|
962
953
|
|
963
954
|
size *= 2;
|
964
955
|
if (size <= len * 2 + pos) {
|
@@ -981,37 +972,28 @@ void oj_grow_out(Out out, size_t len) {
|
|
981
972
|
|
982
973
|
void oj_dump_nil(VALUE obj, int depth, Out out, bool as_ok) {
|
983
974
|
assure_size(out, 4);
|
984
|
-
|
985
|
-
*out->cur++ = 'u';
|
986
|
-
*out->cur++ = 'l';
|
987
|
-
*out->cur++ = 'l';
|
975
|
+
APPEND_CHARS(out->cur, "null", 4);
|
988
976
|
*out->cur = '\0';
|
989
977
|
}
|
990
978
|
|
991
979
|
void oj_dump_true(VALUE obj, int depth, Out out, bool as_ok) {
|
992
980
|
assure_size(out, 4);
|
993
|
-
|
994
|
-
*out->cur++ = 'r';
|
995
|
-
*out->cur++ = 'u';
|
996
|
-
*out->cur++ = 'e';
|
981
|
+
APPEND_CHARS(out->cur, "true", 4);
|
997
982
|
*out->cur = '\0';
|
998
983
|
}
|
999
984
|
|
1000
985
|
void oj_dump_false(VALUE obj, int depth, Out out, bool as_ok) {
|
1001
986
|
assure_size(out, 5);
|
1002
|
-
|
1003
|
-
*out->cur++ = 'a';
|
1004
|
-
*out->cur++ = 'l';
|
1005
|
-
*out->cur++ = 's';
|
1006
|
-
*out->cur++ = 'e';
|
987
|
+
APPEND_CHARS(out->cur, "false", 5);
|
1007
988
|
*out->cur = '\0';
|
1008
989
|
}
|
1009
990
|
|
1010
991
|
void oj_dump_fixnum(VALUE obj, int depth, Out out, bool as_ok) {
|
1011
992
|
char buf[32];
|
1012
993
|
char * b = buf + sizeof(buf) - 1;
|
1013
|
-
long long num =
|
994
|
+
long long num = NUM2LL(obj);
|
1014
995
|
int neg = 0;
|
996
|
+
size_t cnt = 0;
|
1015
997
|
bool dump_as_string = false;
|
1016
998
|
|
1017
999
|
if (out->opts->int_range_max != 0 && out->opts->int_range_min != 0 &&
|
@@ -1042,10 +1024,9 @@ void oj_dump_fixnum(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1042
1024
|
if (dump_as_string) {
|
1043
1025
|
*--b = '"';
|
1044
1026
|
}
|
1045
|
-
|
1046
|
-
|
1047
|
-
|
1048
|
-
}
|
1027
|
+
cnt = sizeof(buf) - (b - buf) - 1;
|
1028
|
+
assure_size(out, cnt);
|
1029
|
+
APPEND_CHARS(out->cur, b, cnt);
|
1049
1030
|
*out->cur = '\0';
|
1050
1031
|
}
|
1051
1032
|
|
@@ -1061,8 +1042,7 @@ void oj_dump_bignum(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1061
1042
|
} else {
|
1062
1043
|
assure_size(out, cnt);
|
1063
1044
|
}
|
1064
|
-
|
1065
|
-
out->cur += cnt;
|
1045
|
+
APPEND_CHARS(out->cur, RSTRING_PTR(rs), cnt);
|
1066
1046
|
if (dump_as_string) {
|
1067
1047
|
*out->cur++ = '"';
|
1068
1048
|
}
|
@@ -1072,7 +1052,7 @@ void oj_dump_bignum(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1072
1052
|
// Removed dependencies on math due to problems with CentOS 5.4.
|
1073
1053
|
void oj_dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
1074
1054
|
char buf[64];
|
1075
|
-
char
|
1055
|
+
char *b;
|
1076
1056
|
double d = rb_num2dbl(obj);
|
1077
1057
|
int cnt = 0;
|
1078
1058
|
|
@@ -1195,9 +1175,7 @@ void oj_dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1195
1175
|
cnt = oj_dump_float_printf(buf, sizeof(buf), obj, d, out->opts->float_fmt);
|
1196
1176
|
}
|
1197
1177
|
assure_size(out, cnt);
|
1198
|
-
|
1199
|
-
*out->cur++ = *b;
|
1200
|
-
}
|
1178
|
+
APPEND_CHARS(out->cur, buf, cnt);
|
1201
1179
|
*out->cur = '\0';
|
1202
1180
|
}
|
1203
1181
|
|
data/ext/oj/dump.h
CHANGED
@@ -32,6 +32,11 @@ extern void oj_dump_obj_to_s(VALUE obj, Out out);
|
|
32
32
|
|
33
33
|
extern const char *oj_nan_str(VALUE obj, int opt, int mode, bool plus, int *lenp);
|
34
34
|
|
35
|
+
// initialize an out buffer with the provided stack allocated memory
|
36
|
+
extern void oj_out_init(Out out);
|
37
|
+
// clean up the out buffer if it uses heap allocated memory
|
38
|
+
extern void oj_out_free(Out out);
|
39
|
+
|
35
40
|
extern void oj_grow_out(Out out, size_t len);
|
36
41
|
extern long oj_check_circular(VALUE obj, Out out);
|
37
42
|
|
@@ -62,9 +67,8 @@ inline static void fill_indent(Out out, int cnt) {
|
|
62
67
|
if (0 < out->indent) {
|
63
68
|
cnt *= out->indent;
|
64
69
|
*out->cur++ = '\n';
|
65
|
-
|
66
|
-
|
67
|
-
}
|
70
|
+
memset(out->cur, ' ', cnt);
|
71
|
+
out->cur += cnt;
|
68
72
|
}
|
69
73
|
}
|
70
74
|
|
@@ -83,8 +87,9 @@ inline static bool dump_ignore(Options opts, VALUE obj) {
|
|
83
87
|
}
|
84
88
|
|
85
89
|
inline static void dump_ulong(unsigned long num, Out out) {
|
86
|
-
char
|
87
|
-
char
|
90
|
+
char buf[32];
|
91
|
+
char *b = buf + sizeof(buf) - 1;
|
92
|
+
size_t cnt = 0;
|
88
93
|
|
89
94
|
*b-- = '\0';
|
90
95
|
if (0 < num) {
|
@@ -95,9 +100,8 @@ inline static void dump_ulong(unsigned long num, Out out) {
|
|
95
100
|
} else {
|
96
101
|
*b = '0';
|
97
102
|
}
|
98
|
-
|
99
|
-
|
100
|
-
}
|
103
|
+
cnt = sizeof(buf) - (b - buf) - 1;
|
104
|
+
APPEND_CHARS(out->cur, b, cnt);
|
101
105
|
*out->cur = '\0';
|
102
106
|
}
|
103
107
|
|