oj 3.13.11 → 3.13.14
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 +14 -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 -88
- 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 +26 -24
- 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/activesupport7/abstract_unit.rb +49 -0
- data/test/activesupport7/decoding_test.rb +125 -0
- data/test/activesupport7/encoding_test.rb +486 -0
- data/test/activesupport7/encoding_test_cases.rb +104 -0
- data/test/activesupport7/time_zone_test_helpers.rb +47 -0
- data/test/bar.rb +1 -8
- data/test/foo.rb +3 -3
- data/test/json_gem/json_generator_test.rb +2 -0
- data/test/perf_dump.rb +50 -0
- data/test/test_object.rb +12 -7
- metadata +15 -17
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,34 @@ 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
|
-
|
630
|
-
fclose(f);
|
614
|
+
|
615
|
+
oj_out_free(&out);
|
616
|
+
|
631
617
|
if (!ok) {
|
632
618
|
int err = ferror(f);
|
619
|
+
fclose(f);
|
633
620
|
|
634
621
|
rb_raise(rb_eIOError, "Write failed. [%d:%s]", err, strerror(err));
|
635
622
|
}
|
623
|
+
fclose(f);
|
636
624
|
}
|
637
625
|
|
626
|
+
#if !IS_WINDOWS
|
638
627
|
static void write_ready(int fd) {
|
639
628
|
struct pollfd pp;
|
640
629
|
int i;
|
@@ -649,9 +638,9 @@ static void write_ready(int fd) {
|
|
649
638
|
rb_raise(rb_eIOError, "write failed. %d %s.", errno, strerror(errno));
|
650
639
|
}
|
651
640
|
}
|
641
|
+
#endif
|
652
642
|
|
653
643
|
void oj_write_obj_to_stream(VALUE obj, VALUE stream, Options copts) {
|
654
|
-
char buf[4096];
|
655
644
|
struct _out out;
|
656
645
|
ssize_t size;
|
657
646
|
VALUE clas = rb_obj_class(stream);
|
@@ -660,9 +649,8 @@ void oj_write_obj_to_stream(VALUE obj, VALUE stream, Options copts) {
|
|
660
649
|
VALUE s;
|
661
650
|
#endif
|
662
651
|
|
663
|
-
out
|
664
|
-
|
665
|
-
out.allocated = false;
|
652
|
+
oj_out_init(&out);
|
653
|
+
|
666
654
|
out.omit_nil = copts->dump_opts.omit_nil;
|
667
655
|
oj_dump_obj_to_json(obj, copts, &out);
|
668
656
|
size = out.cur - out.buf;
|
@@ -692,20 +680,17 @@ void oj_write_obj_to_stream(VALUE obj, VALUE stream, Options copts) {
|
|
692
680
|
} else if (rb_respond_to(stream, oj_write_id)) {
|
693
681
|
rb_funcall(stream, oj_write_id, 1, rb_str_new(out.buf, size));
|
694
682
|
} else {
|
695
|
-
|
696
|
-
xfree(out.buf);
|
697
|
-
}
|
683
|
+
oj_out_free(&out);
|
698
684
|
rb_raise(rb_eArgError, "to_stream() expected an IO Object.");
|
699
685
|
}
|
700
|
-
|
701
|
-
xfree(out.buf);
|
702
|
-
}
|
686
|
+
oj_out_free(&out);
|
703
687
|
}
|
704
688
|
|
705
689
|
void oj_dump_str(VALUE obj, int depth, Out out, bool as_ok) {
|
706
|
-
|
690
|
+
int idx = RB_ENCODING_GET(obj);
|
707
691
|
|
708
|
-
if (
|
692
|
+
if (oj_utf8_encoding_index != idx) {
|
693
|
+
rb_encoding *enc = rb_enc_from_index(idx);
|
709
694
|
obj = rb_str_conv_enc(obj, enc, oj_utf8_encoding);
|
710
695
|
}
|
711
696
|
oj_dump_cstr(RSTRING_PTR(obj), (int)RSTRING_LEN(obj), 0, 0, out);
|
@@ -719,7 +704,7 @@ void oj_dump_sym(VALUE obj, int depth, Out out, bool as_ok) {
|
|
719
704
|
|
720
705
|
static void debug_raise(const char *orig, size_t cnt, int line) {
|
721
706
|
char buf[1024];
|
722
|
-
char
|
707
|
+
char *b = buf;
|
723
708
|
const char *s = orig;
|
724
709
|
const char *s_end = s + cnt;
|
725
710
|
|
@@ -758,7 +743,7 @@ void oj_dump_raw_json(VALUE obj, int depth, Out out) {
|
|
758
743
|
|
759
744
|
void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out out) {
|
760
745
|
size_t size;
|
761
|
-
char
|
746
|
+
char *cmap;
|
762
747
|
const char *orig = str;
|
763
748
|
bool has_hi = false;
|
764
749
|
|
@@ -803,10 +788,7 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
|
|
803
788
|
*out->cur++ = '"';
|
804
789
|
|
805
790
|
if (escape1) {
|
806
|
-
|
807
|
-
*out->cur++ = 'u';
|
808
|
-
*out->cur++ = '0';
|
809
|
-
*out->cur++ = '0';
|
791
|
+
APPEND_CHARS(out->cur, "\\u00", 4);
|
810
792
|
dump_hex((uint8_t)*str, out);
|
811
793
|
cnt--;
|
812
794
|
size--;
|
@@ -817,8 +799,7 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
|
|
817
799
|
if (is_sym) {
|
818
800
|
*out->cur++ = ':';
|
819
801
|
}
|
820
|
-
|
821
|
-
out->cur += cnt;
|
802
|
+
APPEND_CHARS(out->cur, str, cnt);
|
822
803
|
*out->cur++ = '"';
|
823
804
|
} else {
|
824
805
|
const char *end = str + cnt;
|
@@ -868,10 +849,7 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
|
|
868
849
|
break;
|
869
850
|
case '6': // control characters
|
870
851
|
if (*(uint8_t *)str < 0x80) {
|
871
|
-
|
872
|
-
*out->cur++ = 'u';
|
873
|
-
*out->cur++ = '0';
|
874
|
-
*out->cur++ = '0';
|
852
|
+
APPEND_CHARS(out->cur, "\\u00", 4);
|
875
853
|
dump_hex((uint8_t)*str, out);
|
876
854
|
} else {
|
877
855
|
if (0xe2 == (uint8_t)*str &&
|
@@ -950,15 +928,27 @@ void oj_dump_obj_to_s(VALUE obj, Out out) {
|
|
950
928
|
|
951
929
|
void oj_dump_raw(const char *str, size_t cnt, Out out) {
|
952
930
|
assure_size(out, cnt + 10);
|
953
|
-
|
954
|
-
out->cur += cnt;
|
931
|
+
APPEND_CHARS(out->cur, str, cnt);
|
955
932
|
*out->cur = '\0';
|
956
933
|
}
|
957
934
|
|
935
|
+
void oj_out_init(Out out) {
|
936
|
+
out->buf = out->stack_buffer;
|
937
|
+
out->cur = out->buf;
|
938
|
+
out->end = out->buf + sizeof(out->stack_buffer) - BUFFER_EXTRA;
|
939
|
+
out->allocated = false;
|
940
|
+
}
|
941
|
+
|
942
|
+
void oj_out_free(Out out) {
|
943
|
+
if (out->allocated) {
|
944
|
+
xfree(out->buf); // TBD
|
945
|
+
}
|
946
|
+
}
|
947
|
+
|
958
948
|
void oj_grow_out(Out out, size_t len) {
|
959
949
|
size_t size = out->end - out->buf;
|
960
950
|
long pos = out->cur - out->buf;
|
961
|
-
char
|
951
|
+
char *buf = out->buf;
|
962
952
|
|
963
953
|
size *= 2;
|
964
954
|
if (size <= len * 2 + pos) {
|
@@ -981,37 +971,28 @@ void oj_grow_out(Out out, size_t len) {
|
|
981
971
|
|
982
972
|
void oj_dump_nil(VALUE obj, int depth, Out out, bool as_ok) {
|
983
973
|
assure_size(out, 4);
|
984
|
-
|
985
|
-
*out->cur++ = 'u';
|
986
|
-
*out->cur++ = 'l';
|
987
|
-
*out->cur++ = 'l';
|
974
|
+
APPEND_CHARS(out->cur, "null", 4);
|
988
975
|
*out->cur = '\0';
|
989
976
|
}
|
990
977
|
|
991
978
|
void oj_dump_true(VALUE obj, int depth, Out out, bool as_ok) {
|
992
979
|
assure_size(out, 4);
|
993
|
-
|
994
|
-
*out->cur++ = 'r';
|
995
|
-
*out->cur++ = 'u';
|
996
|
-
*out->cur++ = 'e';
|
980
|
+
APPEND_CHARS(out->cur, "true", 4);
|
997
981
|
*out->cur = '\0';
|
998
982
|
}
|
999
983
|
|
1000
984
|
void oj_dump_false(VALUE obj, int depth, Out out, bool as_ok) {
|
1001
985
|
assure_size(out, 5);
|
1002
|
-
|
1003
|
-
*out->cur++ = 'a';
|
1004
|
-
*out->cur++ = 'l';
|
1005
|
-
*out->cur++ = 's';
|
1006
|
-
*out->cur++ = 'e';
|
986
|
+
APPEND_CHARS(out->cur, "false", 5);
|
1007
987
|
*out->cur = '\0';
|
1008
988
|
}
|
1009
989
|
|
1010
990
|
void oj_dump_fixnum(VALUE obj, int depth, Out out, bool as_ok) {
|
1011
991
|
char buf[32];
|
1012
992
|
char * b = buf + sizeof(buf) - 1;
|
1013
|
-
long long num =
|
993
|
+
long long num = NUM2LL(obj);
|
1014
994
|
int neg = 0;
|
995
|
+
size_t cnt = 0;
|
1015
996
|
bool dump_as_string = false;
|
1016
997
|
|
1017
998
|
if (out->opts->int_range_max != 0 && out->opts->int_range_min != 0 &&
|
@@ -1042,10 +1023,9 @@ void oj_dump_fixnum(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1042
1023
|
if (dump_as_string) {
|
1043
1024
|
*--b = '"';
|
1044
1025
|
}
|
1045
|
-
|
1046
|
-
|
1047
|
-
|
1048
|
-
}
|
1026
|
+
cnt = sizeof(buf) - (b - buf) - 1;
|
1027
|
+
assure_size(out, cnt);
|
1028
|
+
APPEND_CHARS(out->cur, b, cnt);
|
1049
1029
|
*out->cur = '\0';
|
1050
1030
|
}
|
1051
1031
|
|
@@ -1061,8 +1041,7 @@ void oj_dump_bignum(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1061
1041
|
} else {
|
1062
1042
|
assure_size(out, cnt);
|
1063
1043
|
}
|
1064
|
-
|
1065
|
-
out->cur += cnt;
|
1044
|
+
APPEND_CHARS(out->cur, RSTRING_PTR(rs), cnt);
|
1066
1045
|
if (dump_as_string) {
|
1067
1046
|
*out->cur++ = '"';
|
1068
1047
|
}
|
@@ -1072,7 +1051,7 @@ void oj_dump_bignum(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1072
1051
|
// Removed dependencies on math due to problems with CentOS 5.4.
|
1073
1052
|
void oj_dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
1074
1053
|
char buf[64];
|
1075
|
-
char
|
1054
|
+
char *b;
|
1076
1055
|
double d = rb_num2dbl(obj);
|
1077
1056
|
int cnt = 0;
|
1078
1057
|
|
@@ -1195,9 +1174,7 @@ void oj_dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1195
1174
|
cnt = oj_dump_float_printf(buf, sizeof(buf), obj, d, out->opts->float_fmt);
|
1196
1175
|
}
|
1197
1176
|
assure_size(out, cnt);
|
1198
|
-
|
1199
|
-
*out->cur++ = *b;
|
1200
|
-
}
|
1177
|
+
APPEND_CHARS(out->cur, buf, cnt);
|
1201
1178
|
*out->cur = '\0';
|
1202
1179
|
}
|
1203
1180
|
|
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
|
|