oj 3.13.11 → 3.15.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +74 -0
- data/README.md +4 -2
- data/ext/oj/buf.h +11 -6
- data/ext/oj/cache.c +25 -24
- data/ext/oj/cache8.c +10 -9
- data/ext/oj/circarray.c +8 -6
- data/ext/oj/circarray.h +2 -2
- data/ext/oj/code.c +17 -24
- data/ext/oj/code.h +2 -2
- data/ext/oj/compat.c +17 -44
- data/ext/oj/custom.c +70 -141
- data/ext/oj/debug.c +3 -9
- data/ext/oj/dump.c +128 -118
- data/ext/oj/dump.h +12 -8
- data/ext/oj/dump_compat.c +564 -641
- data/ext/oj/dump_leaf.c +17 -63
- data/ext/oj/dump_object.c +70 -199
- data/ext/oj/dump_strict.c +22 -46
- data/ext/oj/encoder.c +1 -1
- data/ext/oj/err.c +2 -13
- data/ext/oj/err.h +9 -12
- data/ext/oj/extconf.rb +14 -5
- data/ext/oj/fast.c +75 -103
- data/ext/oj/intern.c +52 -50
- data/ext/oj/intern.h +4 -8
- data/ext/oj/mem.c +318 -0
- data/ext/oj/mem.h +53 -0
- data/ext/oj/mimic_json.c +75 -47
- data/ext/oj/object.c +49 -66
- data/ext/oj/odd.c +89 -67
- data/ext/oj/odd.h +15 -15
- data/ext/oj/oj.c +140 -99
- data/ext/oj/oj.h +80 -51
- data/ext/oj/parse.c +162 -184
- data/ext/oj/parse.h +7 -10
- data/ext/oj/parser.c +89 -34
- data/ext/oj/parser.h +18 -7
- data/ext/oj/rails.c +82 -146
- data/ext/oj/rails.h +1 -1
- data/ext/oj/reader.c +11 -12
- data/ext/oj/reader.h +4 -2
- data/ext/oj/resolve.c +3 -4
- data/ext/oj/rxclass.c +6 -5
- data/ext/oj/rxclass.h +1 -1
- data/ext/oj/saj.c +20 -31
- data/ext/oj/saj2.c +329 -93
- data/ext/oj/saj2.h +23 -0
- data/ext/oj/scp.c +3 -14
- data/ext/oj/sparse.c +26 -70
- data/ext/oj/stream_writer.c +12 -22
- data/ext/oj/strict.c +20 -52
- data/ext/oj/string_writer.c +21 -21
- data/ext/oj/trace.h +31 -4
- data/ext/oj/usual.c +105 -150
- data/ext/oj/usual.h +68 -0
- data/ext/oj/util.h +1 -1
- data/ext/oj/val_stack.c +1 -1
- data/ext/oj/val_stack.h +8 -7
- data/ext/oj/validate.c +21 -26
- data/ext/oj/wab.c +31 -68
- data/lib/oj/active_support_helper.rb +0 -1
- data/lib/oj/bag.rb +7 -1
- data/lib/oj/easy_hash.rb +4 -5
- data/lib/oj/error.rb +0 -1
- data/lib/oj/json.rb +4 -2
- data/lib/oj/mimic.rb +4 -2
- data/lib/oj/saj.rb +20 -6
- data/lib/oj/state.rb +9 -6
- data/lib/oj/version.rb +1 -2
- data/lib/oj.rb +2 -0
- data/pages/Compatibility.md +1 -1
- data/pages/InstallOptions.md +20 -0
- data/pages/Options.md +10 -0
- data/test/_test_active.rb +8 -9
- data/test/_test_active_mimic.rb +7 -8
- data/test/_test_mimic_rails.rb +17 -20
- data/test/activerecord/result_test.rb +5 -6
- data/test/{activesupport5 → activesupport7}/abstract_unit.rb +16 -12
- data/test/{activesupport5 → activesupport7}/decoding_test.rb +2 -10
- data/test/{activesupport5 → activesupport7}/encoding_test.rb +20 -34
- data/test/{activesupport5 → activesupport7}/encoding_test_cases.rb +6 -0
- data/test/{activesupport5 → activesupport7}/time_zone_test_helpers.rb +8 -0
- data/test/files.rb +15 -15
- data/test/foo.rb +9 -71
- data/test/helper.rb +11 -8
- data/test/isolated/shared.rb +3 -2
- data/test/json_gem/json_addition_test.rb +2 -2
- data/test/json_gem/json_common_interface_test.rb +4 -4
- data/test/json_gem/json_encoding_test.rb +0 -0
- data/test/json_gem/json_ext_parser_test.rb +1 -0
- data/test/json_gem/json_fixtures_test.rb +3 -2
- data/test/json_gem/json_generator_test.rb +48 -36
- data/test/json_gem/json_generic_object_test.rb +11 -11
- data/test/json_gem/json_parser_test.rb +54 -47
- data/test/json_gem/json_string_matching_test.rb +9 -9
- data/test/json_gem/test_helper.rb +7 -3
- data/test/mem.rb +13 -12
- data/test/perf.rb +21 -26
- data/test/perf_compat.rb +31 -33
- data/test/perf_dump.rb +50 -0
- data/test/perf_fast.rb +80 -82
- data/test/perf_file.rb +27 -29
- data/test/perf_object.rb +65 -69
- data/test/perf_once.rb +12 -11
- data/test/perf_parser.rb +42 -48
- data/test/perf_saj.rb +46 -54
- data/test/perf_scp.rb +57 -69
- data/test/perf_simple.rb +41 -39
- data/test/perf_strict.rb +68 -70
- data/test/perf_wab.rb +67 -69
- data/test/prec.rb +3 -3
- data/test/sample/change.rb +0 -1
- data/test/sample/dir.rb +0 -1
- data/test/sample/doc.rb +0 -1
- data/test/sample/file.rb +0 -1
- data/test/sample/group.rb +0 -1
- data/test/sample/hasprops.rb +0 -1
- data/test/sample/layer.rb +0 -1
- data/test/sample/rect.rb +0 -1
- data/test/sample/shape.rb +0 -1
- data/test/sample/text.rb +0 -1
- data/test/sample.rb +16 -16
- data/test/sample_json.rb +8 -8
- data/test/test_compat.rb +76 -42
- data/test/test_custom.rb +72 -51
- data/test/test_debian.rb +7 -10
- data/test/test_fast.rb +86 -90
- data/test/test_file.rb +41 -30
- data/test/test_gc.rb +16 -5
- data/test/test_generate.rb +5 -5
- data/test/test_hash.rb +4 -4
- data/test/test_integer_range.rb +9 -9
- data/test/test_null.rb +20 -20
- data/test/test_object.rb +85 -96
- data/test/test_parser.rb +6 -22
- data/test/test_parser_debug.rb +27 -0
- data/test/test_parser_saj.rb +115 -23
- data/test/test_parser_usual.rb +6 -6
- data/test/test_rails.rb +2 -2
- data/test/test_saj.rb +10 -8
- data/test/test_scp.rb +37 -39
- data/test/test_strict.rb +30 -32
- data/test/test_various.rb +147 -99
- data/test/test_wab.rb +48 -44
- data/test/test_writer.rb +47 -47
- data/test/tests.rb +13 -4
- data/test/tests_mimic.rb +12 -3
- data/test/tests_mimic_addition.rb +12 -3
- metadata +33 -144
- data/test/activesupport4/decoding_test.rb +0 -108
- data/test/activesupport4/encoding_test.rb +0 -531
- data/test/activesupport4/test_helper.rb +0 -41
- data/test/activesupport5/test_helper.rb +0 -72
- data/test/bar.rb +0 -16
- data/test/baz.rb +0 -16
- data/test/bug.rb +0 -16
- data/test/zoo.rb +0 -13
data/ext/oj/debug.c
CHANGED
@@ -30,9 +30,7 @@ static void add_int(struct _ojParser *p) {
|
|
30
30
|
switch (p->stack[p->depth]) {
|
31
31
|
case TOP_FUN: printf("*** add_int %lld at top\n", (long long)p->num.fixnum); break;
|
32
32
|
case ARRAY_FUN: printf("*** add_int %lld to array\n", (long long)p->num.fixnum); break;
|
33
|
-
case OBJECT_FUN:
|
34
|
-
printf("*** add_int %lld with '%s'\n", (long long)p->num.fixnum, buf_str(&p->key));
|
35
|
-
break;
|
33
|
+
case OBJECT_FUN: printf("*** add_int %lld with '%s'\n", (long long)p->num.fixnum, buf_str(&p->key)); break;
|
36
34
|
}
|
37
35
|
}
|
38
36
|
|
@@ -48,9 +46,7 @@ static void add_big(struct _ojParser *p) {
|
|
48
46
|
switch (p->stack[p->depth]) {
|
49
47
|
case TOP_FUN: printf("*** add_big %s at top\n", buf_str(&p->buf)); break;
|
50
48
|
case ARRAY_FUN: printf("*** add_big %s to array\n", buf_str(&p->buf)); break;
|
51
|
-
case OBJECT_FUN:
|
52
|
-
printf("*** add_big %s with '%s'\n", buf_str(&p->buf), buf_str(&p->key));
|
53
|
-
break;
|
49
|
+
case OBJECT_FUN: printf("*** add_big %s with '%s'\n", buf_str(&p->buf), buf_str(&p->key)); break;
|
54
50
|
}
|
55
51
|
}
|
56
52
|
|
@@ -58,9 +54,7 @@ static void add_str(struct _ojParser *p) {
|
|
58
54
|
switch (p->stack[p->depth]) {
|
59
55
|
case TOP_FUN: printf("*** add_str '%s' at top\n", buf_str(&p->buf)); break;
|
60
56
|
case ARRAY_FUN: printf("*** add_str '%s' to array\n", buf_str(&p->buf)); break;
|
61
|
-
case OBJECT_FUN:
|
62
|
-
printf("*** add_str '%s' with '%s'\n", buf_str(&p->buf), buf_str(&p->key));
|
63
|
-
break;
|
57
|
+
case OBJECT_FUN: printf("*** add_str '%s' with '%s'\n", buf_str(&p->buf), buf_str(&p->key)); break;
|
64
58
|
}
|
65
59
|
}
|
66
60
|
|
data/ext/oj/dump.c
CHANGED
@@ -15,6 +15,7 @@
|
|
15
15
|
#endif
|
16
16
|
|
17
17
|
#include "cache8.h"
|
18
|
+
#include "mem.h"
|
18
19
|
#include "odd.h"
|
19
20
|
#include "oj.h"
|
20
21
|
#include "trace.h"
|
@@ -32,6 +33,7 @@ static const char nan_val[] = NAN_VAL;
|
|
32
33
|
typedef unsigned long ulong;
|
33
34
|
|
34
35
|
static size_t hibit_friendly_size(const uint8_t *str, size_t len);
|
36
|
+
static size_t slash_friendly_size(const uint8_t *str, size_t len);
|
35
37
|
static size_t xss_friendly_size(const uint8_t *str, size_t len);
|
36
38
|
static size_t ascii_friendly_size(const uint8_t *str, size_t len);
|
37
39
|
|
@@ -59,6 +61,17 @@ static char hibit_friendly_chars[256] = "\
|
|
59
61
|
11111111111111111111111111111111\
|
60
62
|
11111111111111111111111111111111";
|
61
63
|
|
64
|
+
// JSON standard but escape forward slashes `/`
|
65
|
+
static char slash_friendly_chars[256] = "\
|
66
|
+
66666666222622666666666666666666\
|
67
|
+
11211111111111121111111111111111\
|
68
|
+
11111111111111111111111111112111\
|
69
|
+
11111111111111111111111111111111\
|
70
|
+
11111111111111111111111111111111\
|
71
|
+
11111111111111111111111111111111\
|
72
|
+
11111111111111111111111111111111\
|
73
|
+
11111111111111111111111111111111";
|
74
|
+
|
62
75
|
// High bit set characters are always encoded as unicode. Worse case is 3
|
63
76
|
// bytes per character in the output. That makes this conservative.
|
64
77
|
static char ascii_friendly_chars[256] = "\
|
@@ -143,6 +156,10 @@ inline static size_t hibit_friendly_size(const uint8_t *str, size_t len) {
|
|
143
156
|
return calculate_string_size(str, len, hibit_friendly_chars);
|
144
157
|
}
|
145
158
|
|
159
|
+
inline static size_t slash_friendly_size(const uint8_t *str, size_t len) {
|
160
|
+
return calculate_string_size(str, len, slash_friendly_chars);
|
161
|
+
}
|
162
|
+
|
146
163
|
inline static size_t ascii_friendly_size(const uint8_t *str, size_t len) {
|
147
164
|
return calculate_string_size(str, len, ascii_friendly_chars);
|
148
165
|
}
|
@@ -234,7 +251,7 @@ inline static void dump_hex(uint8_t c, Out out) {
|
|
234
251
|
static void raise_invalid_unicode(const char *str, int len, int pos) {
|
235
252
|
char c;
|
236
253
|
char code[32];
|
237
|
-
char
|
254
|
+
char *cp = code;
|
238
255
|
int i;
|
239
256
|
uint8_t d;
|
240
257
|
|
@@ -289,16 +306,14 @@ static const char *dump_unicode(const char *str, const char *end, Out out, const
|
|
289
306
|
uint32_t c1;
|
290
307
|
|
291
308
|
code -= 0x00010000;
|
292
|
-
c1
|
293
|
-
code
|
294
|
-
|
295
|
-
*out->cur++ = 'u';
|
309
|
+
c1 = ((code >> 10) & 0x000003FF) + 0x0000D800;
|
310
|
+
code = (code & 0x000003FF) + 0x0000DC00;
|
311
|
+
APPEND_CHARS(out->cur, "\\u", 2);
|
296
312
|
for (i = 3; 0 <= i; i--) {
|
297
313
|
*out->cur++ = hex_chars[(uint8_t)(c1 >> (i * 4)) & 0x0F];
|
298
314
|
}
|
299
315
|
}
|
300
|
-
|
301
|
-
*out->cur++ = 'u';
|
316
|
+
APPEND_CHARS(out->cur, "\\u", 2);
|
302
317
|
for (i = 3; 0 <= i; i--) {
|
303
318
|
*out->cur++ = hex_chars[(uint8_t)(code >> (i * 4)) & 0x0F];
|
304
319
|
}
|
@@ -347,9 +362,7 @@ long oj_check_circular(VALUE obj, Out out) {
|
|
347
362
|
} else {
|
348
363
|
if (ObjectMode == out->opts->mode) {
|
349
364
|
assure_size(out, 18);
|
350
|
-
|
351
|
-
*out->cur++ = '^';
|
352
|
-
*out->cur++ = 'r';
|
365
|
+
APPEND_CHARS(out->cur, "\"^r", 3);
|
353
366
|
dump_ulong(id, out);
|
354
367
|
*out->cur++ = '"';
|
355
368
|
}
|
@@ -361,15 +374,14 @@ long oj_check_circular(VALUE obj, Out out) {
|
|
361
374
|
|
362
375
|
void oj_dump_time(VALUE obj, Out out, int withZone) {
|
363
376
|
char buf[64];
|
364
|
-
char
|
377
|
+
char *b = buf + sizeof(buf) - 1;
|
365
378
|
long size;
|
366
|
-
char
|
379
|
+
char *dot;
|
367
380
|
int neg = 0;
|
368
381
|
long one = 1000000000;
|
369
382
|
long long sec;
|
370
383
|
long long nsec;
|
371
384
|
|
372
|
-
#ifdef HAVE_RB_TIME_TIMESPEC
|
373
385
|
// rb_time_timespec as well as rb_time_timeeval have a bug that causes an
|
374
386
|
// exception to be raised if a time is before 1970 on 32 bit systems so
|
375
387
|
// check the timespec size and use the ruby calls if a 32 bit system.
|
@@ -379,13 +391,9 @@ void oj_dump_time(VALUE obj, Out out, int withZone) {
|
|
379
391
|
sec = (long long)ts.tv_sec;
|
380
392
|
nsec = ts.tv_nsec;
|
381
393
|
} else {
|
382
|
-
sec =
|
383
|
-
nsec =
|
394
|
+
sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
395
|
+
nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
384
396
|
}
|
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
397
|
|
390
398
|
*b-- = '\0';
|
391
399
|
if (withZone) {
|
@@ -451,13 +459,12 @@ void oj_dump_time(VALUE obj, Out out, int withZone) {
|
|
451
459
|
b++;
|
452
460
|
size = sizeof(buf) - (b - buf) - 1;
|
453
461
|
assure_size(out, size);
|
454
|
-
|
455
|
-
out->cur += size;
|
462
|
+
APPEND_CHARS(out->cur, b, size);
|
456
463
|
*out->cur = '\0';
|
457
464
|
}
|
458
465
|
|
459
466
|
void oj_dump_ruby_time(VALUE obj, Out out) {
|
460
|
-
volatile VALUE rstr =
|
467
|
+
volatile VALUE rstr = oj_safe_string_convert(obj);
|
461
468
|
|
462
469
|
oj_dump_cstr(RSTRING_PTR(rstr), (int)RSTRING_LEN(rstr), 0, 0, out);
|
463
470
|
}
|
@@ -472,20 +479,15 @@ void oj_dump_xml_time(VALUE obj, Out out) {
|
|
472
479
|
int tzhour, tzmin;
|
473
480
|
char tzsign = '+';
|
474
481
|
|
475
|
-
#ifdef HAVE_RB_TIME_TIMESPEC
|
476
482
|
if (16 <= sizeof(struct timespec)) {
|
477
483
|
struct timespec ts = rb_time_timespec(obj);
|
478
484
|
|
479
485
|
sec = ts.tv_sec;
|
480
486
|
nsec = ts.tv_nsec;
|
481
487
|
} else {
|
482
|
-
sec =
|
483
|
-
nsec =
|
488
|
+
sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
489
|
+
nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
484
490
|
}
|
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
491
|
|
490
492
|
assure_size(out, 36);
|
491
493
|
if (9 > out->opts->sec_prec) {
|
@@ -565,12 +567,8 @@ void oj_dump_obj_to_json(VALUE obj, Options copts, Out out) {
|
|
565
567
|
|
566
568
|
void oj_dump_obj_to_json_using_params(VALUE obj, Options copts, Out out, int argc, VALUE *argv) {
|
567
569
|
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;
|
570
|
+
oj_out_init(out);
|
572
571
|
}
|
573
|
-
out->cur = out->buf;
|
574
572
|
out->circ_cnt = 0;
|
575
573
|
out->opts = copts;
|
576
574
|
out->hash_cnt = 0;
|
@@ -605,36 +603,34 @@ void oj_dump_obj_to_json_using_params(VALUE obj, Options copts, Out out, int arg
|
|
605
603
|
}
|
606
604
|
|
607
605
|
void oj_write_obj_to_file(VALUE obj, const char *path, Options copts) {
|
608
|
-
char buf[4096];
|
609
606
|
struct _out out;
|
610
607
|
size_t size;
|
611
|
-
FILE
|
608
|
+
FILE *f;
|
612
609
|
int ok;
|
613
610
|
|
614
|
-
out
|
615
|
-
|
616
|
-
out.
|
617
|
-
out.omit_nil = copts->dump_opts.omit_nil;
|
611
|
+
oj_out_init(&out);
|
612
|
+
|
613
|
+
out.omit_nil = copts->dump_opts.omit_nil;
|
618
614
|
oj_dump_obj_to_json(obj, copts, &out);
|
619
615
|
size = out.cur - out.buf;
|
620
616
|
if (0 == (f = fopen(path, "w"))) {
|
621
|
-
|
622
|
-
xfree(out.buf);
|
623
|
-
}
|
617
|
+
oj_out_free(&out);
|
624
618
|
rb_raise(rb_eIOError, "%s", strerror(errno));
|
625
619
|
}
|
626
620
|
ok = (size == fwrite(out.buf, 1, size, f));
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
fclose(f);
|
621
|
+
|
622
|
+
oj_out_free(&out);
|
623
|
+
|
631
624
|
if (!ok) {
|
632
625
|
int err = ferror(f);
|
626
|
+
fclose(f);
|
633
627
|
|
634
628
|
rb_raise(rb_eIOError, "Write failed. [%d:%s]", err, strerror(err));
|
635
629
|
}
|
630
|
+
fclose(f);
|
636
631
|
}
|
637
632
|
|
633
|
+
#if !IS_WINDOWS
|
638
634
|
static void write_ready(int fd) {
|
639
635
|
struct pollfd pp;
|
640
636
|
int i;
|
@@ -649,9 +645,9 @@ static void write_ready(int fd) {
|
|
649
645
|
rb_raise(rb_eIOError, "write failed. %d %s.", errno, strerror(errno));
|
650
646
|
}
|
651
647
|
}
|
648
|
+
#endif
|
652
649
|
|
653
650
|
void oj_write_obj_to_stream(VALUE obj, VALUE stream, Options copts) {
|
654
|
-
char buf[4096];
|
655
651
|
struct _out out;
|
656
652
|
ssize_t size;
|
657
653
|
VALUE clas = rb_obj_class(stream);
|
@@ -660,10 +656,9 @@ void oj_write_obj_to_stream(VALUE obj, VALUE stream, Options copts) {
|
|
660
656
|
VALUE s;
|
661
657
|
#endif
|
662
658
|
|
663
|
-
out
|
664
|
-
|
665
|
-
out.
|
666
|
-
out.omit_nil = copts->dump_opts.omit_nil;
|
659
|
+
oj_out_init(&out);
|
660
|
+
|
661
|
+
out.omit_nil = copts->dump_opts.omit_nil;
|
667
662
|
oj_dump_obj_to_json(obj, copts, &out);
|
668
663
|
size = out.cur - out.buf;
|
669
664
|
if (oj_stringio_class == clas) {
|
@@ -692,21 +687,18 @@ void oj_write_obj_to_stream(VALUE obj, VALUE stream, Options copts) {
|
|
692
687
|
} else if (rb_respond_to(stream, oj_write_id)) {
|
693
688
|
rb_funcall(stream, oj_write_id, 1, rb_str_new(out.buf, size));
|
694
689
|
} else {
|
695
|
-
|
696
|
-
xfree(out.buf);
|
697
|
-
}
|
690
|
+
oj_out_free(&out);
|
698
691
|
rb_raise(rb_eArgError, "to_stream() expected an IO Object.");
|
699
692
|
}
|
700
|
-
|
701
|
-
xfree(out.buf);
|
702
|
-
}
|
693
|
+
oj_out_free(&out);
|
703
694
|
}
|
704
695
|
|
705
696
|
void oj_dump_str(VALUE obj, int depth, Out out, bool as_ok) {
|
706
|
-
|
697
|
+
int idx = RB_ENCODING_GET(obj);
|
707
698
|
|
708
|
-
if (
|
709
|
-
|
699
|
+
if (oj_utf8_encoding_index != idx) {
|
700
|
+
rb_encoding *enc = rb_enc_from_index(idx);
|
701
|
+
obj = rb_str_conv_enc(obj, enc, oj_utf8_encoding);
|
710
702
|
}
|
711
703
|
oj_dump_cstr(RSTRING_PTR(obj), (int)RSTRING_LEN(obj), 0, 0, out);
|
712
704
|
}
|
@@ -719,7 +711,7 @@ void oj_dump_sym(VALUE obj, int depth, Out out, bool as_ok) {
|
|
719
711
|
|
720
712
|
static void debug_raise(const char *orig, size_t cnt, int line) {
|
721
713
|
char buf[1024];
|
722
|
-
char
|
714
|
+
char *b = buf;
|
723
715
|
const char *s = orig;
|
724
716
|
const char *s_end = s + cnt;
|
725
717
|
|
@@ -745,20 +737,16 @@ void oj_dump_raw_json(VALUE obj, int depth, Out out) {
|
|
745
737
|
} else {
|
746
738
|
volatile VALUE jv;
|
747
739
|
|
748
|
-
|
749
|
-
oj_trace("raw_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyIn);
|
750
|
-
}
|
740
|
+
TRACE(out->opts->trace, "raw_json", obj, depth + 1, TraceRubyIn);
|
751
741
|
jv = rb_funcall(obj, oj_raw_json_id, 2, RB_INT2NUM(depth), RB_INT2NUM(out->indent));
|
752
|
-
|
753
|
-
oj_trace("raw_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyOut);
|
754
|
-
}
|
742
|
+
TRACE(out->opts->trace, "raw_json", obj, depth + 1, TraceRubyOut);
|
755
743
|
oj_dump_raw(RSTRING_PTR(jv), (size_t)RSTRING_LEN(jv), out);
|
756
744
|
}
|
757
745
|
}
|
758
746
|
|
759
747
|
void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out out) {
|
760
748
|
size_t size;
|
761
|
-
char
|
749
|
+
char *cmap;
|
762
750
|
const char *orig = str;
|
763
751
|
bool has_hi = false;
|
764
752
|
|
@@ -771,6 +759,11 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
|
|
771
759
|
cmap = ascii_friendly_chars;
|
772
760
|
size = ascii_friendly_size((uint8_t *)str, cnt);
|
773
761
|
break;
|
762
|
+
case SlashEsc:
|
763
|
+
has_hi = true;
|
764
|
+
cmap = slash_friendly_chars;
|
765
|
+
size = slash_friendly_size((uint8_t *)str, cnt);
|
766
|
+
break;
|
774
767
|
case XSSEsc:
|
775
768
|
cmap = xss_friendly_chars;
|
776
769
|
size = xss_friendly_size((uint8_t *)str, cnt);
|
@@ -803,10 +796,7 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
|
|
803
796
|
*out->cur++ = '"';
|
804
797
|
|
805
798
|
if (escape1) {
|
806
|
-
|
807
|
-
*out->cur++ = 'u';
|
808
|
-
*out->cur++ = '0';
|
809
|
-
*out->cur++ = '0';
|
799
|
+
APPEND_CHARS(out->cur, "\\u00", 4);
|
810
800
|
dump_hex((uint8_t)*str, out);
|
811
801
|
cnt--;
|
812
802
|
size--;
|
@@ -817,8 +807,7 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
|
|
817
807
|
if (is_sym) {
|
818
808
|
*out->cur++ = ':';
|
819
809
|
}
|
820
|
-
|
821
|
-
out->cur += cnt;
|
810
|
+
APPEND_CHARS(out->cur, str, cnt);
|
822
811
|
*out->cur++ = '"';
|
823
812
|
} else {
|
824
813
|
const char *end = str + cnt;
|
@@ -868,10 +857,10 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
|
|
868
857
|
break;
|
869
858
|
case '6': // control characters
|
870
859
|
if (*(uint8_t *)str < 0x80) {
|
871
|
-
*out->
|
872
|
-
|
873
|
-
|
874
|
-
|
860
|
+
if (0 == (uint8_t)*str && out->opts->dump_opts.omit_null_byte) {
|
861
|
+
break;
|
862
|
+
}
|
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 &&
|
@@ -943,31 +932,43 @@ void oj_dump_class(VALUE obj, int depth, Out out, bool as_ok) {
|
|
943
932
|
}
|
944
933
|
|
945
934
|
void oj_dump_obj_to_s(VALUE obj, Out out) {
|
946
|
-
volatile VALUE rstr =
|
935
|
+
volatile VALUE rstr = oj_safe_string_convert(obj);
|
947
936
|
|
948
937
|
oj_dump_cstr(RSTRING_PTR(rstr), (int)RSTRING_LEN(rstr), 0, 0, out);
|
949
938
|
}
|
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
|
+
OJ_R_FREE(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) {
|
965
966
|
size += len;
|
966
967
|
}
|
967
968
|
if (out->allocated) {
|
968
|
-
|
969
|
+
OJ_R_REALLOC_N(buf, char, (size + BUFFER_EXTRA));
|
969
970
|
} else {
|
970
|
-
buf =
|
971
|
+
buf = OJ_R_ALLOC_N(char, (size + BUFFER_EXTRA));
|
971
972
|
out->allocated = true;
|
972
973
|
memcpy(buf, out->buf, out->end - out->buf + BUFFER_EXTRA);
|
973
974
|
}
|
@@ -981,37 +982,40 @@ 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
|
986
|
-
*out->cur++ = 'l';
|
987
|
-
*out->cur++ = 'l';
|
988
|
-
*out->cur = '\0';
|
985
|
+
APPEND_CHARS(out->cur, "null", 4);
|
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
|
995
|
-
*out->cur++ = 'u';
|
996
|
-
*out->cur++ = 'e';
|
997
|
-
*out->cur = '\0';
|
991
|
+
APPEND_CHARS(out->cur, "true", 4);
|
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
|
1004
|
-
*out->cur++ = 'l';
|
1005
|
-
*out->cur++ = 's';
|
1006
|
-
*out->cur++ = 'e';
|
1007
|
-
*out->cur = '\0';
|
997
|
+
APPEND_CHARS(out->cur, "false", 5);
|
998
|
+
*out->cur = '\0';
|
1008
999
|
}
|
1009
1000
|
|
1001
|
+
static const char digits_table[] = "\
|
1002
|
+
00010203040506070809\
|
1003
|
+
10111213141516171819\
|
1004
|
+
20212223242526272829\
|
1005
|
+
30313233343536373839\
|
1006
|
+
40414243444546474849\
|
1007
|
+
50515253545556575859\
|
1008
|
+
60616263646566676869\
|
1009
|
+
70717273747576777879\
|
1010
|
+
80818283848586878889\
|
1011
|
+
90919293949596979899";
|
1012
|
+
|
1010
1013
|
void oj_dump_fixnum(VALUE obj, int depth, Out out, bool as_ok) {
|
1011
1014
|
char buf[32];
|
1012
|
-
char
|
1013
|
-
long long num =
|
1015
|
+
char *b = buf + sizeof(buf) - 1;
|
1016
|
+
long long num = NUM2LL(obj);
|
1014
1017
|
int neg = 0;
|
1018
|
+
size_t cnt = 0;
|
1015
1019
|
bool dump_as_string = false;
|
1016
1020
|
|
1017
1021
|
if (out->opts->int_range_max != 0 && out->opts->int_range_min != 0 &&
|
@@ -1028,9 +1032,19 @@ void oj_dump_fixnum(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1028
1032
|
*b-- = '"';
|
1029
1033
|
}
|
1030
1034
|
if (0 < num) {
|
1031
|
-
|
1032
|
-
|
1035
|
+
while (100 <= num) {
|
1036
|
+
unsigned idx = num % 100 * 2;
|
1037
|
+
*b-- = digits_table[idx + 1];
|
1038
|
+
*b-- = digits_table[idx];
|
1039
|
+
num /= 100;
|
1040
|
+
}
|
1041
|
+
if (num < 10) {
|
1042
|
+
*b-- = num + '0';
|
1043
|
+
} else {
|
1044
|
+
*b-- = digits_table[num * 2 + 1];
|
1045
|
+
*b-- = digits_table[num * 2];
|
1033
1046
|
}
|
1047
|
+
|
1034
1048
|
if (neg) {
|
1035
1049
|
*b = '-';
|
1036
1050
|
} else {
|
@@ -1042,10 +1056,9 @@ void oj_dump_fixnum(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1042
1056
|
if (dump_as_string) {
|
1043
1057
|
*--b = '"';
|
1044
1058
|
}
|
1045
|
-
|
1046
|
-
|
1047
|
-
|
1048
|
-
}
|
1059
|
+
cnt = sizeof(buf) - (b - buf) - 1;
|
1060
|
+
assure_size(out, cnt);
|
1061
|
+
APPEND_CHARS(out->cur, b, cnt);
|
1049
1062
|
*out->cur = '\0';
|
1050
1063
|
}
|
1051
1064
|
|
@@ -1061,8 +1074,7 @@ void oj_dump_bignum(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1061
1074
|
} else {
|
1062
1075
|
assure_size(out, cnt);
|
1063
1076
|
}
|
1064
|
-
|
1065
|
-
out->cur += cnt;
|
1077
|
+
APPEND_CHARS(out->cur, RSTRING_PTR(rs), cnt);
|
1066
1078
|
if (dump_as_string) {
|
1067
1079
|
*out->cur++ = '"';
|
1068
1080
|
}
|
@@ -1072,7 +1084,7 @@ void oj_dump_bignum(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1072
1084
|
// Removed dependencies on math due to problems with CentOS 5.4.
|
1073
1085
|
void oj_dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
1074
1086
|
char buf[64];
|
1075
|
-
char
|
1087
|
+
char *b;
|
1076
1088
|
double d = rb_num2dbl(obj);
|
1077
1089
|
int cnt = 0;
|
1078
1090
|
|
@@ -1151,7 +1163,7 @@ void oj_dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1151
1163
|
} else if (isnan(d)) {
|
1152
1164
|
if (ObjectMode == out->opts->mode) {
|
1153
1165
|
strcpy(buf, nan_val);
|
1154
|
-
cnt = sizeof(
|
1166
|
+
cnt = sizeof(nan_val) - 1;
|
1155
1167
|
} else {
|
1156
1168
|
NanDump nd = out->opts->dump_opts.nan_dump;
|
1157
1169
|
|
@@ -1183,7 +1195,7 @@ void oj_dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1183
1195
|
} else if (d == (double)(long long int)d) {
|
1184
1196
|
cnt = snprintf(buf, sizeof(buf), "%.1f", d);
|
1185
1197
|
} else if (0 == out->opts->float_prec) {
|
1186
|
-
volatile VALUE rstr =
|
1198
|
+
volatile VALUE rstr = oj_safe_string_convert(obj);
|
1187
1199
|
|
1188
1200
|
cnt = (int)RSTRING_LEN(rstr);
|
1189
1201
|
if ((int)sizeof(buf) <= cnt) {
|
@@ -1195,9 +1207,7 @@ void oj_dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1195
1207
|
cnt = oj_dump_float_printf(buf, sizeof(buf), obj, d, out->opts->float_fmt);
|
1196
1208
|
}
|
1197
1209
|
assure_size(out, cnt);
|
1198
|
-
|
1199
|
-
*out->cur++ = *b;
|
1200
|
-
}
|
1210
|
+
APPEND_CHARS(out->cur, buf, cnt);
|
1201
1211
|
*out->cur = '\0';
|
1202
1212
|
}
|
1203
1213
|
|
@@ -1207,7 +1217,7 @@ int oj_dump_float_printf(char *buf, size_t blen, VALUE obj, double d, const char
|
|
1207
1217
|
// Round off issues at 16 significant digits so check for obvious ones of
|
1208
1218
|
// 0001 and 9999.
|
1209
1219
|
if (17 <= cnt && (0 == strcmp("0001", buf + cnt - 4) || 0 == strcmp("9999", buf + cnt - 4))) {
|
1210
|
-
volatile VALUE rstr =
|
1220
|
+
volatile VALUE rstr = oj_safe_string_convert(obj);
|
1211
1221
|
|
1212
1222
|
strcpy(buf, RSTRING_PTR(rstr));
|
1213
1223
|
cnt = (int)RSTRING_LEN(rstr);
|
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
|
|