oj 3.13.11 → 3.13.23
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 +50 -0
- data/README.md +2 -0
- data/ext/oj/buf.h +4 -0
- data/ext/oj/circarray.c +1 -1
- data/ext/oj/code.c +15 -22
- data/ext/oj/compat.c +10 -10
- data/ext/oj/custom.c +62 -108
- data/ext/oj/dump.c +85 -97
- data/ext/oj/dump.h +12 -8
- data/ext/oj/dump_compat.c +46 -88
- data/ext/oj/dump_leaf.c +14 -58
- data/ext/oj/dump_object.c +33 -156
- data/ext/oj/dump_strict.c +17 -29
- data/ext/oj/extconf.rb +5 -4
- data/ext/oj/fast.c +24 -22
- data/ext/oj/intern.c +15 -11
- data/ext/oj/intern.h +1 -1
- data/ext/oj/mimic_json.c +44 -32
- data/ext/oj/object.c +42 -41
- data/ext/oj/odd.c +83 -63
- data/ext/oj/odd.h +13 -13
- data/ext/oj/oj.c +57 -22
- data/ext/oj/oj.h +24 -3
- data/ext/oj/parse.c +114 -78
- data/ext/oj/parse.h +2 -0
- data/ext/oj/parser.c +77 -21
- data/ext/oj/parser.h +12 -0
- data/ext/oj/rails.c +41 -65
- data/ext/oj/rails.h +1 -1
- data/ext/oj/reader.c +2 -0
- data/ext/oj/saj.c +11 -23
- data/ext/oj/saj2.c +333 -85
- data/ext/oj/saj2.h +23 -0
- data/ext/oj/sparse.c +4 -0
- data/ext/oj/stream_writer.c +3 -1
- data/ext/oj/strict.c +13 -13
- data/ext/oj/string_writer.c +12 -5
- data/ext/oj/usual.c +82 -129
- data/ext/oj/usual.h +68 -0
- data/ext/oj/val_stack.c +1 -1
- data/ext/oj/validate.c +21 -26
- data/ext/oj/wab.c +21 -26
- data/lib/oj/saj.rb +20 -6
- data/lib/oj/state.rb +1 -1
- data/lib/oj/version.rb +1 -1
- data/pages/Compatibility.md +1 -1
- data/pages/Options.md +6 -0
- 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 +3 -8
- data/test/foo.rb +3 -3
- data/test/helper.rb +8 -2
- data/test/json_gem/json_generator_test.rb +5 -4
- data/test/json_gem/json_parser_test.rb +8 -1
- data/test/json_gem/test_helper.rb +7 -3
- data/test/perf_dump.rb +50 -0
- data/test/test_compat.rb +25 -0
- data/test/test_custom.rb +13 -2
- data/test/test_file.rb +23 -7
- data/test/test_gc.rb +11 -0
- data/test/test_object.rb +8 -10
- data/test/test_parser.rb +3 -19
- data/test/test_parser_debug.rb +27 -0
- data/test/test_parser_saj.rb +92 -2
- data/test/test_scp.rb +2 -4
- data/test/test_strict.rb +2 -0
- data/test/test_various.rb +8 -3
- data/test/test_wab.rb +2 -0
- data/test/tests.rb +9 -0
- data/test/tests_mimic.rb +9 -0
- data/test/tests_mimic_addition.rb +9 -0
- metadata +13 -116
data/ext/oj/dump.c
CHANGED
@@ -32,6 +32,7 @@ static const char nan_val[] = NAN_VAL;
|
|
32
32
|
typedef unsigned long ulong;
|
33
33
|
|
34
34
|
static size_t hibit_friendly_size(const uint8_t *str, size_t len);
|
35
|
+
static size_t slash_friendly_size(const uint8_t *str, size_t len);
|
35
36
|
static size_t xss_friendly_size(const uint8_t *str, size_t len);
|
36
37
|
static size_t ascii_friendly_size(const uint8_t *str, size_t len);
|
37
38
|
|
@@ -59,6 +60,17 @@ static char hibit_friendly_chars[256] = "\
|
|
59
60
|
11111111111111111111111111111111\
|
60
61
|
11111111111111111111111111111111";
|
61
62
|
|
63
|
+
// JSON standard but escape forward slashes `/`
|
64
|
+
static char slash_friendly_chars[256] = "\
|
65
|
+
66666666222622666666666666666666\
|
66
|
+
11211111111111121111111111111111\
|
67
|
+
11111111111111111111111111112111\
|
68
|
+
11111111111111111111111111111111\
|
69
|
+
11111111111111111111111111111111\
|
70
|
+
11111111111111111111111111111111\
|
71
|
+
11111111111111111111111111111111\
|
72
|
+
11111111111111111111111111111111";
|
73
|
+
|
62
74
|
// High bit set characters are always encoded as unicode. Worse case is 3
|
63
75
|
// bytes per character in the output. That makes this conservative.
|
64
76
|
static char ascii_friendly_chars[256] = "\
|
@@ -143,6 +155,10 @@ inline static size_t hibit_friendly_size(const uint8_t *str, size_t len) {
|
|
143
155
|
return calculate_string_size(str, len, hibit_friendly_chars);
|
144
156
|
}
|
145
157
|
|
158
|
+
inline static size_t slash_friendly_size(const uint8_t *str, size_t len) {
|
159
|
+
return calculate_string_size(str, len, slash_friendly_chars);
|
160
|
+
}
|
161
|
+
|
146
162
|
inline static size_t ascii_friendly_size(const uint8_t *str, size_t len) {
|
147
163
|
return calculate_string_size(str, len, ascii_friendly_chars);
|
148
164
|
}
|
@@ -234,7 +250,7 @@ inline static void dump_hex(uint8_t c, Out out) {
|
|
234
250
|
static void raise_invalid_unicode(const char *str, int len, int pos) {
|
235
251
|
char c;
|
236
252
|
char code[32];
|
237
|
-
char
|
253
|
+
char *cp = code;
|
238
254
|
int i;
|
239
255
|
uint8_t d;
|
240
256
|
|
@@ -291,14 +307,12 @@ static const char *dump_unicode(const char *str, const char *end, Out out, const
|
|
291
307
|
code -= 0x00010000;
|
292
308
|
c1 = ((code >> 10) & 0x000003FF) + 0x0000D800;
|
293
309
|
code = (code & 0x000003FF) + 0x0000DC00;
|
294
|
-
|
295
|
-
*out->cur++ = 'u';
|
310
|
+
APPEND_CHARS(out->cur, "\\u", 2);
|
296
311
|
for (i = 3; 0 <= i; i--) {
|
297
312
|
*out->cur++ = hex_chars[(uint8_t)(c1 >> (i * 4)) & 0x0F];
|
298
313
|
}
|
299
314
|
}
|
300
|
-
|
301
|
-
*out->cur++ = 'u';
|
315
|
+
APPEND_CHARS(out->cur, "\\u", 2);
|
302
316
|
for (i = 3; 0 <= i; i--) {
|
303
317
|
*out->cur++ = hex_chars[(uint8_t)(code >> (i * 4)) & 0x0F];
|
304
318
|
}
|
@@ -347,9 +361,7 @@ long oj_check_circular(VALUE obj, Out out) {
|
|
347
361
|
} else {
|
348
362
|
if (ObjectMode == out->opts->mode) {
|
349
363
|
assure_size(out, 18);
|
350
|
-
|
351
|
-
*out->cur++ = '^';
|
352
|
-
*out->cur++ = 'r';
|
364
|
+
APPEND_CHARS(out->cur, "\"^r", 3);
|
353
365
|
dump_ulong(id, out);
|
354
366
|
*out->cur++ = '"';
|
355
367
|
}
|
@@ -361,15 +373,14 @@ long oj_check_circular(VALUE obj, Out out) {
|
|
361
373
|
|
362
374
|
void oj_dump_time(VALUE obj, Out out, int withZone) {
|
363
375
|
char buf[64];
|
364
|
-
char
|
376
|
+
char *b = buf + sizeof(buf) - 1;
|
365
377
|
long size;
|
366
|
-
char
|
378
|
+
char *dot;
|
367
379
|
int neg = 0;
|
368
380
|
long one = 1000000000;
|
369
381
|
long long sec;
|
370
382
|
long long nsec;
|
371
383
|
|
372
|
-
#ifdef HAVE_RB_TIME_TIMESPEC
|
373
384
|
// rb_time_timespec as well as rb_time_timeeval have a bug that causes an
|
374
385
|
// exception to be raised if a time is before 1970 on 32 bit systems so
|
375
386
|
// check the timespec size and use the ruby calls if a 32 bit system.
|
@@ -379,13 +390,9 @@ void oj_dump_time(VALUE obj, Out out, int withZone) {
|
|
379
390
|
sec = (long long)ts.tv_sec;
|
380
391
|
nsec = ts.tv_nsec;
|
381
392
|
} else {
|
382
|
-
sec =
|
383
|
-
nsec =
|
393
|
+
sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
394
|
+
nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
384
395
|
}
|
385
|
-
#else
|
386
|
-
sec = rb_num2ll(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
387
|
-
nsec = rb_num2ll(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
388
|
-
#endif
|
389
396
|
|
390
397
|
*b-- = '\0';
|
391
398
|
if (withZone) {
|
@@ -451,8 +458,7 @@ void oj_dump_time(VALUE obj, Out out, int withZone) {
|
|
451
458
|
b++;
|
452
459
|
size = sizeof(buf) - (b - buf) - 1;
|
453
460
|
assure_size(out, size);
|
454
|
-
|
455
|
-
out->cur += size;
|
461
|
+
APPEND_CHARS(out->cur, b, size);
|
456
462
|
*out->cur = '\0';
|
457
463
|
}
|
458
464
|
|
@@ -472,20 +478,15 @@ void oj_dump_xml_time(VALUE obj, Out out) {
|
|
472
478
|
int tzhour, tzmin;
|
473
479
|
char tzsign = '+';
|
474
480
|
|
475
|
-
#ifdef HAVE_RB_TIME_TIMESPEC
|
476
481
|
if (16 <= sizeof(struct timespec)) {
|
477
482
|
struct timespec ts = rb_time_timespec(obj);
|
478
483
|
|
479
484
|
sec = ts.tv_sec;
|
480
485
|
nsec = ts.tv_nsec;
|
481
486
|
} else {
|
482
|
-
sec =
|
483
|
-
nsec =
|
487
|
+
sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
488
|
+
nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
484
489
|
}
|
485
|
-
#else
|
486
|
-
sec = rb_num2ll(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
487
|
-
nsec = rb_num2ll(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
488
|
-
#endif
|
489
490
|
|
490
491
|
assure_size(out, 36);
|
491
492
|
if (9 > out->opts->sec_prec) {
|
@@ -565,12 +566,8 @@ void oj_dump_obj_to_json(VALUE obj, Options copts, Out out) {
|
|
565
566
|
|
566
567
|
void oj_dump_obj_to_json_using_params(VALUE obj, Options copts, Out out, int argc, VALUE *argv) {
|
567
568
|
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;
|
569
|
+
oj_out_init(out);
|
572
570
|
}
|
573
|
-
out->cur = out->buf;
|
574
571
|
out->circ_cnt = 0;
|
575
572
|
out->opts = copts;
|
576
573
|
out->hash_cnt = 0;
|
@@ -605,36 +602,34 @@ void oj_dump_obj_to_json_using_params(VALUE obj, Options copts, Out out, int arg
|
|
605
602
|
}
|
606
603
|
|
607
604
|
void oj_write_obj_to_file(VALUE obj, const char *path, Options copts) {
|
608
|
-
char buf[4096];
|
609
605
|
struct _out out;
|
610
606
|
size_t size;
|
611
|
-
FILE
|
607
|
+
FILE *f;
|
612
608
|
int ok;
|
613
609
|
|
614
|
-
out
|
615
|
-
|
616
|
-
out.allocated = false;
|
610
|
+
oj_out_init(&out);
|
611
|
+
|
617
612
|
out.omit_nil = copts->dump_opts.omit_nil;
|
618
613
|
oj_dump_obj_to_json(obj, copts, &out);
|
619
614
|
size = out.cur - out.buf;
|
620
615
|
if (0 == (f = fopen(path, "w"))) {
|
621
|
-
|
622
|
-
xfree(out.buf);
|
623
|
-
}
|
616
|
+
oj_out_free(&out);
|
624
617
|
rb_raise(rb_eIOError, "%s", strerror(errno));
|
625
618
|
}
|
626
619
|
ok = (size == fwrite(out.buf, 1, size, f));
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
fclose(f);
|
620
|
+
|
621
|
+
oj_out_free(&out);
|
622
|
+
|
631
623
|
if (!ok) {
|
632
624
|
int err = ferror(f);
|
625
|
+
fclose(f);
|
633
626
|
|
634
627
|
rb_raise(rb_eIOError, "Write failed. [%d:%s]", err, strerror(err));
|
635
628
|
}
|
629
|
+
fclose(f);
|
636
630
|
}
|
637
631
|
|
632
|
+
#if !IS_WINDOWS
|
638
633
|
static void write_ready(int fd) {
|
639
634
|
struct pollfd pp;
|
640
635
|
int i;
|
@@ -649,9 +644,9 @@ static void write_ready(int fd) {
|
|
649
644
|
rb_raise(rb_eIOError, "write failed. %d %s.", errno, strerror(errno));
|
650
645
|
}
|
651
646
|
}
|
647
|
+
#endif
|
652
648
|
|
653
649
|
void oj_write_obj_to_stream(VALUE obj, VALUE stream, Options copts) {
|
654
|
-
char buf[4096];
|
655
650
|
struct _out out;
|
656
651
|
ssize_t size;
|
657
652
|
VALUE clas = rb_obj_class(stream);
|
@@ -660,9 +655,8 @@ void oj_write_obj_to_stream(VALUE obj, VALUE stream, Options copts) {
|
|
660
655
|
VALUE s;
|
661
656
|
#endif
|
662
657
|
|
663
|
-
out
|
664
|
-
|
665
|
-
out.allocated = false;
|
658
|
+
oj_out_init(&out);
|
659
|
+
|
666
660
|
out.omit_nil = copts->dump_opts.omit_nil;
|
667
661
|
oj_dump_obj_to_json(obj, copts, &out);
|
668
662
|
size = out.cur - out.buf;
|
@@ -692,20 +686,17 @@ void oj_write_obj_to_stream(VALUE obj, VALUE stream, Options copts) {
|
|
692
686
|
} else if (rb_respond_to(stream, oj_write_id)) {
|
693
687
|
rb_funcall(stream, oj_write_id, 1, rb_str_new(out.buf, size));
|
694
688
|
} else {
|
695
|
-
|
696
|
-
xfree(out.buf);
|
697
|
-
}
|
689
|
+
oj_out_free(&out);
|
698
690
|
rb_raise(rb_eArgError, "to_stream() expected an IO Object.");
|
699
691
|
}
|
700
|
-
|
701
|
-
xfree(out.buf);
|
702
|
-
}
|
692
|
+
oj_out_free(&out);
|
703
693
|
}
|
704
694
|
|
705
695
|
void oj_dump_str(VALUE obj, int depth, Out out, bool as_ok) {
|
706
|
-
|
696
|
+
int idx = RB_ENCODING_GET(obj);
|
707
697
|
|
708
|
-
if (
|
698
|
+
if (oj_utf8_encoding_index != idx) {
|
699
|
+
rb_encoding *enc = rb_enc_from_index(idx);
|
709
700
|
obj = rb_str_conv_enc(obj, enc, oj_utf8_encoding);
|
710
701
|
}
|
711
702
|
oj_dump_cstr(RSTRING_PTR(obj), (int)RSTRING_LEN(obj), 0, 0, out);
|
@@ -719,7 +710,7 @@ void oj_dump_sym(VALUE obj, int depth, Out out, bool as_ok) {
|
|
719
710
|
|
720
711
|
static void debug_raise(const char *orig, size_t cnt, int line) {
|
721
712
|
char buf[1024];
|
722
|
-
char
|
713
|
+
char *b = buf;
|
723
714
|
const char *s = orig;
|
724
715
|
const char *s_end = s + cnt;
|
725
716
|
|
@@ -745,11 +736,11 @@ void oj_dump_raw_json(VALUE obj, int depth, Out out) {
|
|
745
736
|
} else {
|
746
737
|
volatile VALUE jv;
|
747
738
|
|
748
|
-
if (Yes == out->opts->trace) {
|
739
|
+
if (RB_UNLIKELY(Yes == out->opts->trace)) {
|
749
740
|
oj_trace("raw_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyIn);
|
750
741
|
}
|
751
742
|
jv = rb_funcall(obj, oj_raw_json_id, 2, RB_INT2NUM(depth), RB_INT2NUM(out->indent));
|
752
|
-
if (Yes == out->opts->trace) {
|
743
|
+
if (RB_UNLIKELY(Yes == out->opts->trace)) {
|
753
744
|
oj_trace("raw_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyOut);
|
754
745
|
}
|
755
746
|
oj_dump_raw(RSTRING_PTR(jv), (size_t)RSTRING_LEN(jv), out);
|
@@ -758,7 +749,7 @@ void oj_dump_raw_json(VALUE obj, int depth, Out out) {
|
|
758
749
|
|
759
750
|
void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out out) {
|
760
751
|
size_t size;
|
761
|
-
char
|
752
|
+
char *cmap;
|
762
753
|
const char *orig = str;
|
763
754
|
bool has_hi = false;
|
764
755
|
|
@@ -771,6 +762,11 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
|
|
771
762
|
cmap = ascii_friendly_chars;
|
772
763
|
size = ascii_friendly_size((uint8_t *)str, cnt);
|
773
764
|
break;
|
765
|
+
case SlashEsc:
|
766
|
+
has_hi = true;
|
767
|
+
cmap = slash_friendly_chars;
|
768
|
+
size = slash_friendly_size((uint8_t *)str, cnt);
|
769
|
+
break;
|
774
770
|
case XSSEsc:
|
775
771
|
cmap = xss_friendly_chars;
|
776
772
|
size = xss_friendly_size((uint8_t *)str, cnt);
|
@@ -803,10 +799,7 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
|
|
803
799
|
*out->cur++ = '"';
|
804
800
|
|
805
801
|
if (escape1) {
|
806
|
-
|
807
|
-
*out->cur++ = 'u';
|
808
|
-
*out->cur++ = '0';
|
809
|
-
*out->cur++ = '0';
|
802
|
+
APPEND_CHARS(out->cur, "\\u00", 4);
|
810
803
|
dump_hex((uint8_t)*str, out);
|
811
804
|
cnt--;
|
812
805
|
size--;
|
@@ -817,8 +810,7 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
|
|
817
810
|
if (is_sym) {
|
818
811
|
*out->cur++ = ':';
|
819
812
|
}
|
820
|
-
|
821
|
-
out->cur += cnt;
|
813
|
+
APPEND_CHARS(out->cur, str, cnt);
|
822
814
|
*out->cur++ = '"';
|
823
815
|
} else {
|
824
816
|
const char *end = str + cnt;
|
@@ -868,10 +860,7 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
|
|
868
860
|
break;
|
869
861
|
case '6': // control characters
|
870
862
|
if (*(uint8_t *)str < 0x80) {
|
871
|
-
|
872
|
-
*out->cur++ = 'u';
|
873
|
-
*out->cur++ = '0';
|
874
|
-
*out->cur++ = '0';
|
863
|
+
APPEND_CHARS(out->cur, "\\u00", 4);
|
875
864
|
dump_hex((uint8_t)*str, out);
|
876
865
|
} else {
|
877
866
|
if (0xe2 == (uint8_t)*str &&
|
@@ -950,15 +939,27 @@ void oj_dump_obj_to_s(VALUE obj, Out out) {
|
|
950
939
|
|
951
940
|
void oj_dump_raw(const char *str, size_t cnt, Out out) {
|
952
941
|
assure_size(out, cnt + 10);
|
953
|
-
|
954
|
-
out->cur += cnt;
|
942
|
+
APPEND_CHARS(out->cur, str, cnt);
|
955
943
|
*out->cur = '\0';
|
956
944
|
}
|
957
945
|
|
946
|
+
void oj_out_init(Out out) {
|
947
|
+
out->buf = out->stack_buffer;
|
948
|
+
out->cur = out->buf;
|
949
|
+
out->end = out->buf + sizeof(out->stack_buffer) - BUFFER_EXTRA;
|
950
|
+
out->allocated = false;
|
951
|
+
}
|
952
|
+
|
953
|
+
void oj_out_free(Out out) {
|
954
|
+
if (out->allocated) {
|
955
|
+
xfree(out->buf); // TBD
|
956
|
+
}
|
957
|
+
}
|
958
|
+
|
958
959
|
void oj_grow_out(Out out, size_t len) {
|
959
960
|
size_t size = out->end - out->buf;
|
960
961
|
long pos = out->cur - out->buf;
|
961
|
-
char
|
962
|
+
char *buf = out->buf;
|
962
963
|
|
963
964
|
size *= 2;
|
964
965
|
if (size <= len * 2 + pos) {
|
@@ -981,37 +982,28 @@ void oj_grow_out(Out out, size_t len) {
|
|
981
982
|
|
982
983
|
void oj_dump_nil(VALUE obj, int depth, Out out, bool as_ok) {
|
983
984
|
assure_size(out, 4);
|
984
|
-
|
985
|
-
*out->cur++ = 'u';
|
986
|
-
*out->cur++ = 'l';
|
987
|
-
*out->cur++ = 'l';
|
985
|
+
APPEND_CHARS(out->cur, "null", 4);
|
988
986
|
*out->cur = '\0';
|
989
987
|
}
|
990
988
|
|
991
989
|
void oj_dump_true(VALUE obj, int depth, Out out, bool as_ok) {
|
992
990
|
assure_size(out, 4);
|
993
|
-
|
994
|
-
*out->cur++ = 'r';
|
995
|
-
*out->cur++ = 'u';
|
996
|
-
*out->cur++ = 'e';
|
991
|
+
APPEND_CHARS(out->cur, "true", 4);
|
997
992
|
*out->cur = '\0';
|
998
993
|
}
|
999
994
|
|
1000
995
|
void oj_dump_false(VALUE obj, int depth, Out out, bool as_ok) {
|
1001
996
|
assure_size(out, 5);
|
1002
|
-
|
1003
|
-
*out->cur++ = 'a';
|
1004
|
-
*out->cur++ = 'l';
|
1005
|
-
*out->cur++ = 's';
|
1006
|
-
*out->cur++ = 'e';
|
997
|
+
APPEND_CHARS(out->cur, "false", 5);
|
1007
998
|
*out->cur = '\0';
|
1008
999
|
}
|
1009
1000
|
|
1010
1001
|
void oj_dump_fixnum(VALUE obj, int depth, Out out, bool as_ok) {
|
1011
1002
|
char buf[32];
|
1012
1003
|
char * b = buf + sizeof(buf) - 1;
|
1013
|
-
long long num =
|
1004
|
+
long long num = NUM2LL(obj);
|
1014
1005
|
int neg = 0;
|
1006
|
+
size_t cnt = 0;
|
1015
1007
|
bool dump_as_string = false;
|
1016
1008
|
|
1017
1009
|
if (out->opts->int_range_max != 0 && out->opts->int_range_min != 0 &&
|
@@ -1042,10 +1034,9 @@ void oj_dump_fixnum(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1042
1034
|
if (dump_as_string) {
|
1043
1035
|
*--b = '"';
|
1044
1036
|
}
|
1045
|
-
|
1046
|
-
|
1047
|
-
|
1048
|
-
}
|
1037
|
+
cnt = sizeof(buf) - (b - buf) - 1;
|
1038
|
+
assure_size(out, cnt);
|
1039
|
+
APPEND_CHARS(out->cur, b, cnt);
|
1049
1040
|
*out->cur = '\0';
|
1050
1041
|
}
|
1051
1042
|
|
@@ -1061,8 +1052,7 @@ void oj_dump_bignum(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1061
1052
|
} else {
|
1062
1053
|
assure_size(out, cnt);
|
1063
1054
|
}
|
1064
|
-
|
1065
|
-
out->cur += cnt;
|
1055
|
+
APPEND_CHARS(out->cur, RSTRING_PTR(rs), cnt);
|
1066
1056
|
if (dump_as_string) {
|
1067
1057
|
*out->cur++ = '"';
|
1068
1058
|
}
|
@@ -1072,7 +1062,7 @@ void oj_dump_bignum(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1072
1062
|
// Removed dependencies on math due to problems with CentOS 5.4.
|
1073
1063
|
void oj_dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
1074
1064
|
char buf[64];
|
1075
|
-
char
|
1065
|
+
char *b;
|
1076
1066
|
double d = rb_num2dbl(obj);
|
1077
1067
|
int cnt = 0;
|
1078
1068
|
|
@@ -1151,7 +1141,7 @@ void oj_dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1151
1141
|
} else if (isnan(d)) {
|
1152
1142
|
if (ObjectMode == out->opts->mode) {
|
1153
1143
|
strcpy(buf, nan_val);
|
1154
|
-
cnt = sizeof(
|
1144
|
+
cnt = sizeof(nan_val) - 1;
|
1155
1145
|
} else {
|
1156
1146
|
NanDump nd = out->opts->dump_opts.nan_dump;
|
1157
1147
|
|
@@ -1195,9 +1185,7 @@ void oj_dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1195
1185
|
cnt = oj_dump_float_printf(buf, sizeof(buf), obj, d, out->opts->float_fmt);
|
1196
1186
|
}
|
1197
1187
|
assure_size(out, cnt);
|
1198
|
-
|
1199
|
-
*out->cur++ = *b;
|
1200
|
-
}
|
1188
|
+
APPEND_CHARS(out->cur, buf, cnt);
|
1201
1189
|
*out->cur = '\0';
|
1202
1190
|
}
|
1203
1191
|
|
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
|
|