oj 3.13.11 → 3.13.12
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 +6 -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 +66 -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,16 +929,29 @@ 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
|
|
954
|
+
printf("*** grow %ld\n", len);
|
963
955
|
size *= 2;
|
964
956
|
if (size <= len * 2 + pos) {
|
965
957
|
size += len;
|
@@ -981,37 +973,28 @@ void oj_grow_out(Out out, size_t len) {
|
|
981
973
|
|
982
974
|
void oj_dump_nil(VALUE obj, int depth, Out out, bool as_ok) {
|
983
975
|
assure_size(out, 4);
|
984
|
-
|
985
|
-
*out->cur++ = 'u';
|
986
|
-
*out->cur++ = 'l';
|
987
|
-
*out->cur++ = 'l';
|
976
|
+
APPEND_CHARS(out->cur, "null", 4);
|
988
977
|
*out->cur = '\0';
|
989
978
|
}
|
990
979
|
|
991
980
|
void oj_dump_true(VALUE obj, int depth, Out out, bool as_ok) {
|
992
981
|
assure_size(out, 4);
|
993
|
-
|
994
|
-
*out->cur++ = 'r';
|
995
|
-
*out->cur++ = 'u';
|
996
|
-
*out->cur++ = 'e';
|
982
|
+
APPEND_CHARS(out->cur, "true", 4);
|
997
983
|
*out->cur = '\0';
|
998
984
|
}
|
999
985
|
|
1000
986
|
void oj_dump_false(VALUE obj, int depth, Out out, bool as_ok) {
|
1001
987
|
assure_size(out, 5);
|
1002
|
-
|
1003
|
-
*out->cur++ = 'a';
|
1004
|
-
*out->cur++ = 'l';
|
1005
|
-
*out->cur++ = 's';
|
1006
|
-
*out->cur++ = 'e';
|
988
|
+
APPEND_CHARS(out->cur, "false", 5);
|
1007
989
|
*out->cur = '\0';
|
1008
990
|
}
|
1009
991
|
|
1010
992
|
void oj_dump_fixnum(VALUE obj, int depth, Out out, bool as_ok) {
|
1011
993
|
char buf[32];
|
1012
994
|
char * b = buf + sizeof(buf) - 1;
|
1013
|
-
long long num =
|
995
|
+
long long num = NUM2LL(obj);
|
1014
996
|
int neg = 0;
|
997
|
+
size_t cnt = 0;
|
1015
998
|
bool dump_as_string = false;
|
1016
999
|
|
1017
1000
|
if (out->opts->int_range_max != 0 && out->opts->int_range_min != 0 &&
|
@@ -1042,10 +1025,9 @@ void oj_dump_fixnum(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1042
1025
|
if (dump_as_string) {
|
1043
1026
|
*--b = '"';
|
1044
1027
|
}
|
1045
|
-
|
1046
|
-
|
1047
|
-
|
1048
|
-
}
|
1028
|
+
cnt = sizeof(buf) - (b - buf) - 1;
|
1029
|
+
assure_size(out, cnt);
|
1030
|
+
APPEND_CHARS(out->cur, b, cnt);
|
1049
1031
|
*out->cur = '\0';
|
1050
1032
|
}
|
1051
1033
|
|
@@ -1061,8 +1043,7 @@ void oj_dump_bignum(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1061
1043
|
} else {
|
1062
1044
|
assure_size(out, cnt);
|
1063
1045
|
}
|
1064
|
-
|
1065
|
-
out->cur += cnt;
|
1046
|
+
APPEND_CHARS(out->cur, RSTRING_PTR(rs), cnt);
|
1066
1047
|
if (dump_as_string) {
|
1067
1048
|
*out->cur++ = '"';
|
1068
1049
|
}
|
@@ -1072,7 +1053,7 @@ void oj_dump_bignum(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1072
1053
|
// Removed dependencies on math due to problems with CentOS 5.4.
|
1073
1054
|
void oj_dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
1074
1055
|
char buf[64];
|
1075
|
-
char
|
1056
|
+
char *b;
|
1076
1057
|
double d = rb_num2dbl(obj);
|
1077
1058
|
int cnt = 0;
|
1078
1059
|
|
@@ -1195,9 +1176,7 @@ void oj_dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1195
1176
|
cnt = oj_dump_float_printf(buf, sizeof(buf), obj, d, out->opts->float_fmt);
|
1196
1177
|
}
|
1197
1178
|
assure_size(out, cnt);
|
1198
|
-
|
1199
|
-
*out->cur++ = *b;
|
1200
|
-
}
|
1179
|
+
APPEND_CHARS(out->cur, buf, cnt);
|
1201
1180
|
*out->cur = '\0';
|
1202
1181
|
}
|
1203
1182
|
|
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
|
|