oj 3.7.4 → 3.11.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +12 -4
- data/ext/oj/buf.h +6 -34
- data/ext/oj/cache8.c +3 -3
- data/ext/oj/cache8.h +5 -33
- data/ext/oj/circarray.c +5 -9
- data/ext/oj/circarray.h +5 -8
- data/ext/oj/code.c +3 -6
- data/ext/oj/code.h +7 -10
- data/ext/oj/compat.c +11 -14
- data/ext/oj/custom.c +108 -75
- data/ext/oj/dump.c +132 -92
- data/ext/oj/dump.h +6 -7
- data/ext/oj/dump_compat.c +37 -34
- data/ext/oj/dump_leaf.c +3 -6
- data/ext/oj/dump_object.c +23 -17
- data/ext/oj/dump_strict.c +7 -9
- data/ext/oj/encode.h +6 -32
- data/ext/oj/err.c +2 -5
- data/ext/oj/err.h +6 -34
- data/ext/oj/extconf.rb +6 -0
- data/ext/oj/fast.c +39 -56
- data/ext/oj/hash.c +11 -39
- data/ext/oj/hash.h +5 -33
- data/ext/oj/hash_test.c +3 -31
- data/ext/oj/mimic_json.c +65 -44
- data/ext/oj/object.c +38 -69
- data/ext/oj/odd.c +18 -17
- data/ext/oj/odd.h +6 -9
- data/ext/oj/oj.c +139 -93
- data/ext/oj/oj.h +43 -35
- data/ext/oj/parse.c +164 -60
- data/ext/oj/parse.h +30 -31
- data/ext/oj/rails.c +119 -83
- data/ext/oj/rails.h +4 -7
- data/ext/oj/reader.c +5 -8
- data/ext/oj/reader.h +7 -10
- data/ext/oj/resolve.c +4 -7
- data/ext/oj/resolve.h +4 -7
- data/ext/oj/rxclass.c +8 -11
- data/ext/oj/rxclass.h +8 -11
- data/ext/oj/saj.c +9 -12
- data/ext/oj/scp.c +4 -7
- data/ext/oj/sparse.c +67 -33
- data/ext/oj/stream_writer.c +16 -15
- data/ext/oj/strict.c +9 -12
- data/ext/oj/string_writer.c +27 -8
- data/ext/oj/trace.c +5 -8
- data/ext/oj/trace.h +9 -12
- data/ext/oj/util.c +136 -0
- data/ext/oj/util.h +19 -0
- data/ext/oj/val_stack.c +28 -36
- data/ext/oj/val_stack.h +19 -50
- data/ext/oj/wab.c +29 -29
- data/lib/oj.rb +0 -8
- data/lib/oj/json.rb +1 -1
- data/lib/oj/mimic.rb +46 -2
- data/lib/oj/version.rb +2 -2
- data/pages/Modes.md +47 -45
- data/pages/Options.md +43 -10
- data/pages/Rails.md +60 -21
- data/pages/Security.md +1 -1
- data/test/activesupport5/abstract_unit.rb +45 -0
- data/test/activesupport5/decoding_test.rb +68 -60
- data/test/activesupport5/encoding_test.rb +111 -96
- data/test/activesupport5/encoding_test_cases.rb +33 -25
- data/test/activesupport5/test_helper.rb +43 -21
- data/test/activesupport5/time_zone_test_helpers.rb +18 -3
- data/test/activesupport6/abstract_unit.rb +44 -0
- data/test/activesupport6/decoding_test.rb +133 -0
- data/test/activesupport6/encoding_test.rb +507 -0
- data/test/activesupport6/encoding_test_cases.rb +98 -0
- data/test/activesupport6/test_common.rb +17 -0
- data/test/activesupport6/test_helper.rb +163 -0
- data/test/activesupport6/time_zone_test_helpers.rb +39 -0
- data/test/bar.rb +24 -6
- data/test/baz.rb +16 -0
- data/test/foo.rb +26 -57
- data/test/helper.rb +10 -0
- data/test/json_gem/json_common_interface_test.rb +8 -3
- data/test/json_gem/json_generator_test.rb +15 -3
- data/test/json_gem/test_helper.rb +8 -0
- data/test/prec.rb +23 -0
- data/test/sample_json.rb +1 -1
- data/test/test_compat.rb +21 -10
- data/test/test_custom.rb +135 -8
- data/test/test_integer_range.rb +1 -2
- data/test/test_object.rb +35 -2
- data/test/test_rails.rb +35 -0
- data/test/test_strict.rb +24 -1
- data/test/test_various.rb +52 -63
- data/test/test_writer.rb +19 -2
- data/test/tests.rb +1 -0
- data/test/zoo.rb +13 -0
- metadata +100 -75
data/ext/oj/dump.c
CHANGED
@@ -1,24 +1,19 @@
|
|
1
|
-
|
2
|
-
* Copyright (c) 2012, 2017, Peter Ohler
|
3
|
-
* All rights reserved.
|
4
|
-
*/
|
1
|
+
// Copyright (c) 2012, 2017 Peter Ohler. All rights reserved.
|
5
2
|
|
6
|
-
#include <stdlib.h>
|
7
3
|
#include <errno.h>
|
8
|
-
#
|
9
|
-
#include <
|
10
|
-
#endif
|
11
|
-
#include <time.h>
|
4
|
+
#include <math.h>
|
5
|
+
#include <stdint.h>
|
12
6
|
#include <stdio.h>
|
7
|
+
#include <stdlib.h>
|
13
8
|
#include <string.h>
|
14
|
-
#include <math.h>
|
15
9
|
#include <unistd.h>
|
16
|
-
#include <errno.h>
|
17
10
|
|
18
11
|
#include "oj.h"
|
19
12
|
#include "cache8.h"
|
20
13
|
#include "dump.h"
|
21
14
|
#include "odd.h"
|
15
|
+
#include "trace.h"
|
16
|
+
#include "util.h"
|
22
17
|
|
23
18
|
// Workaround in case INFINITY is not defined in math.h or if the OS is CentOS
|
24
19
|
#define OJ_INFINITY (1.0/0.0)
|
@@ -85,6 +80,17 @@ static char xss_friendly_chars[256] = "\
|
|
85
80
|
// JSON XSS combo
|
86
81
|
static char hixss_friendly_chars[256] = "\
|
87
82
|
66666666222622666666666666666666\
|
83
|
+
11211111111111111111111111111111\
|
84
|
+
11111111111111111111111111112111\
|
85
|
+
11111111111111111111111111111111\
|
86
|
+
11111111111111111111111111111111\
|
87
|
+
11111111111111111111111111111111\
|
88
|
+
11111111111111111111111111111111\
|
89
|
+
11611111111111111111111111111111";
|
90
|
+
|
91
|
+
// Rails XSS combo
|
92
|
+
static char rails_xss_friendly_chars[256] = "\
|
93
|
+
66666666222622666666666666666666\
|
88
94
|
11211161111111111111111111116161\
|
89
95
|
11111111111111111111111111112111\
|
90
96
|
11111111111111111111111111111111\
|
@@ -102,7 +108,7 @@ static char rails_friendly_chars[256] = "\
|
|
102
108
|
11111111111111111111111111111111\
|
103
109
|
11111111111111111111111111111111\
|
104
110
|
11111111111111111111111111111111\
|
105
|
-
|
111
|
+
11111111111111111111111111111111";
|
106
112
|
|
107
113
|
static void
|
108
114
|
raise_strict(VALUE obj) {
|
@@ -158,7 +164,7 @@ hixss_friendly_size(const uint8_t *str, size_t len) {
|
|
158
164
|
size_t size = 0;
|
159
165
|
size_t i = len;
|
160
166
|
bool check = false;
|
161
|
-
|
167
|
+
|
162
168
|
for (; 0 < i; str++, i--) {
|
163
169
|
size += hixss_friendly_chars[*str];
|
164
170
|
if (0 != (0x80 & *str)) {
|
@@ -168,6 +174,22 @@ hixss_friendly_size(const uint8_t *str, size_t len) {
|
|
168
174
|
return size - len * (size_t)'0' + check;
|
169
175
|
}
|
170
176
|
|
177
|
+
inline static long
|
178
|
+
rails_xss_friendly_size(const uint8_t *str, size_t len) {
|
179
|
+
long size = 0;
|
180
|
+
size_t i = len;
|
181
|
+
uint8_t hi = 0;
|
182
|
+
|
183
|
+
for (; 0 < i; str++, i--) {
|
184
|
+
size += rails_xss_friendly_chars[*str];
|
185
|
+
hi |= *str & 0x80;
|
186
|
+
}
|
187
|
+
if (0 == hi) {
|
188
|
+
return size - len * (size_t)'0';
|
189
|
+
}
|
190
|
+
return -(size - len * (size_t)'0');
|
191
|
+
}
|
192
|
+
|
171
193
|
inline static size_t
|
172
194
|
rails_friendly_size(const uint8_t *str, size_t len) {
|
173
195
|
size_t size = 0;
|
@@ -182,7 +204,7 @@ rails_friendly_size(const uint8_t *str, size_t len) {
|
|
182
204
|
const char*
|
183
205
|
oj_nan_str(VALUE obj, int opt, int mode, bool plus, int *lenp) {
|
184
206
|
const char *str = NULL;
|
185
|
-
|
207
|
+
|
186
208
|
if (AutoNan == opt) {
|
187
209
|
switch (mode) {
|
188
210
|
case CompatMode: opt = WordNan; break;
|
@@ -232,7 +254,6 @@ dump_hex(uint8_t c, Out out) {
|
|
232
254
|
|
233
255
|
static void
|
234
256
|
raise_invalid_unicode(const char *str, int len, int pos) {
|
235
|
-
char buf[len + 1];
|
236
257
|
char c;
|
237
258
|
char code[32];
|
238
259
|
char *cp = code;
|
@@ -251,8 +272,7 @@ raise_invalid_unicode(const char *str, int len, int pos) {
|
|
251
272
|
cp--;
|
252
273
|
*cp++ = ']';
|
253
274
|
*cp = '\0';
|
254
|
-
|
255
|
-
rb_raise(oj_json_generator_error_class, "Invalid Unicode %s at %d in '%s'", code, pos, buf);
|
275
|
+
rb_raise(oj_json_generator_error_class, "Invalid Unicode %s at %d", code, pos);
|
256
276
|
}
|
257
277
|
|
258
278
|
static const char*
|
@@ -304,7 +324,7 @@ dump_unicode(const char *str, const char *end, Out out, const char *orig) {
|
|
304
324
|
*out->cur++ = 'u';
|
305
325
|
for (i = 3; 0 <= i; i--) {
|
306
326
|
*out->cur++ = hex_chars[(uint8_t)(code >> (i * 4)) & 0x0F];
|
307
|
-
}
|
327
|
+
}
|
308
328
|
return str - 1;
|
309
329
|
}
|
310
330
|
|
@@ -312,7 +332,7 @@ static const char*
|
|
312
332
|
check_unicode(const char *str, const char *end, const char *orig) {
|
313
333
|
uint8_t b = *(uint8_t*)str;
|
314
334
|
int cnt = 0;
|
315
|
-
|
335
|
+
|
316
336
|
if (0xC0 == (0xE0 & b)) {
|
317
337
|
cnt = 1;
|
318
338
|
} else if (0xE0 == (0xF0 & b)) {
|
@@ -376,11 +396,17 @@ oj_dump_time(VALUE obj, Out out, int withZone) {
|
|
376
396
|
long long nsec;
|
377
397
|
|
378
398
|
#ifdef HAVE_RB_TIME_TIMESPEC
|
379
|
-
|
399
|
+
// rb_time_timespec as well as rb_time_timeeval have a bug that causes an
|
400
|
+
// exception to be raised if a time is before 1970 on 32 bit systems so
|
401
|
+
// check the timespec size and use the ruby calls if a 32 bit system.
|
402
|
+
if (16 <= sizeof(struct timespec)) {
|
380
403
|
struct timespec ts = rb_time_timespec(obj);
|
381
404
|
|
382
405
|
sec = (long long)ts.tv_sec;
|
383
406
|
nsec = ts.tv_nsec;
|
407
|
+
} else {
|
408
|
+
sec = rb_num2ll(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
409
|
+
nsec = rb_num2ll(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
384
410
|
}
|
385
411
|
#else
|
386
412
|
sec = rb_num2ll(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
@@ -465,20 +491,24 @@ oj_dump_ruby_time(VALUE obj, Out out) {
|
|
465
491
|
|
466
492
|
void
|
467
493
|
oj_dump_xml_time(VALUE obj, Out out) {
|
468
|
-
char
|
469
|
-
struct
|
470
|
-
long
|
471
|
-
|
472
|
-
long long
|
473
|
-
long
|
474
|
-
int
|
475
|
-
char
|
494
|
+
char buf[64];
|
495
|
+
struct _timeInfo ti;
|
496
|
+
long one = 1000000000;
|
497
|
+
int64_t sec;
|
498
|
+
long long nsec;
|
499
|
+
long tzsecs = NUM2LONG(rb_funcall2(obj, oj_utc_offset_id, 0, 0));
|
500
|
+
int tzhour, tzmin;
|
501
|
+
char tzsign = '+';
|
476
502
|
|
477
503
|
#ifdef HAVE_RB_TIME_TIMESPEC
|
478
|
-
{
|
504
|
+
if (16 <= sizeof(struct timespec)) {
|
479
505
|
struct timespec ts = rb_time_timespec(obj);
|
506
|
+
|
480
507
|
sec = ts.tv_sec;
|
481
508
|
nsec = ts.tv_nsec;
|
509
|
+
} else {
|
510
|
+
sec = rb_num2ll(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
511
|
+
nsec = rb_num2ll(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
482
512
|
}
|
483
513
|
#else
|
484
514
|
sec = rb_num2ll(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
@@ -509,8 +539,7 @@ oj_dump_xml_time(VALUE obj, Out out) {
|
|
509
539
|
// 2012-01-05T23:58:07.123456000+09:00
|
510
540
|
//tm = localtime(&sec);
|
511
541
|
sec += tzsecs;
|
512
|
-
|
513
|
-
#if 1
|
542
|
+
sec_as_time((int64_t)sec, &ti);
|
514
543
|
if (0 > tzsecs) {
|
515
544
|
tzsign = '-';
|
516
545
|
tzhour = (int)(tzsecs / -3600);
|
@@ -519,26 +548,12 @@ oj_dump_xml_time(VALUE obj, Out out) {
|
|
519
548
|
tzhour = (int)(tzsecs / 3600);
|
520
549
|
tzmin = (int)(tzsecs / 60) - (tzhour * 60);
|
521
550
|
}
|
522
|
-
|
523
|
-
if (0 > tm->tm_gmtoff) {
|
524
|
-
tzsign = '-';
|
525
|
-
tzhour = (int)(tm->tm_gmtoff / -3600);
|
526
|
-
tzmin = (int)(tm->tm_gmtoff / -60) - (tzhour * 60);
|
527
|
-
} else {
|
528
|
-
tzhour = (int)(tm->tm_gmtoff / 3600);
|
529
|
-
tzmin = (int)(tm->tm_gmtoff / 60) - (tzhour * 60);
|
530
|
-
}
|
531
|
-
#endif
|
532
|
-
if (0 == nsec || 0 == out->opts->sec_prec) {
|
551
|
+
if ((0 == nsec && !out->opts->sec_prec_set) || 0 == out->opts->sec_prec) {
|
533
552
|
if (0 == tzsecs && rb_funcall2(obj, oj_utcq_id, 0, 0)) {
|
534
|
-
sprintf(buf, "%04d-%02d-%02dT%02d:%02d:%02dZ",
|
535
|
-
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
|
536
|
-
tm->tm_hour, tm->tm_min, tm->tm_sec);
|
553
|
+
sprintf(buf, "%04d-%02d-%02dT%02d:%02d:%02dZ", ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec);
|
537
554
|
oj_dump_cstr(buf, 20, 0, 0, out);
|
538
555
|
} else {
|
539
|
-
sprintf(buf, "%04d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d",
|
540
|
-
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
|
541
|
-
tm->tm_hour, tm->tm_min, tm->tm_sec,
|
556
|
+
sprintf(buf, "%04d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d", ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec,
|
542
557
|
tzsign, tzhour, tzmin);
|
543
558
|
oj_dump_cstr(buf, 25, 0, 0, out);
|
544
559
|
}
|
@@ -550,9 +565,7 @@ oj_dump_xml_time(VALUE obj, Out out) {
|
|
550
565
|
format[32] = '0' + out->opts->sec_prec;
|
551
566
|
len -= 9 - out->opts->sec_prec;
|
552
567
|
}
|
553
|
-
sprintf(buf, format,
|
554
|
-
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
|
555
|
-
tm->tm_hour, tm->tm_min, tm->tm_sec, (long)nsec);
|
568
|
+
sprintf(buf, format, ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec, (long)nsec);
|
556
569
|
oj_dump_cstr(buf, len, 0, 0, out);
|
557
570
|
} else {
|
558
571
|
char format[64] = "%04d-%02d-%02dT%02d:%02d:%02d.%09ld%c%02d:%02d";
|
@@ -562,10 +575,7 @@ oj_dump_xml_time(VALUE obj, Out out) {
|
|
562
575
|
format[32] = '0' + out->opts->sec_prec;
|
563
576
|
len -= 9 - out->opts->sec_prec;
|
564
577
|
}
|
565
|
-
sprintf(buf, format,
|
566
|
-
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
|
567
|
-
tm->tm_hour, tm->tm_min, tm->tm_sec, (long)nsec,
|
568
|
-
tzsign, tzhour, tzmin);
|
578
|
+
sprintf(buf, format, ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec, (long)nsec, tzsign, tzhour, tzmin);
|
569
579
|
oj_dump_cstr(buf, len, 0, 0, out);
|
570
580
|
}
|
571
581
|
}
|
@@ -622,7 +632,7 @@ oj_dump_obj_to_json_using_params(VALUE obj, Options copts, Out out, int argc, VA
|
|
622
632
|
void
|
623
633
|
oj_write_obj_to_file(VALUE obj, const char *path, Options copts) {
|
624
634
|
char buf[4096];
|
625
|
-
struct
|
635
|
+
struct _out out;
|
626
636
|
size_t size;
|
627
637
|
FILE *f;
|
628
638
|
int ok;
|
@@ -654,7 +664,7 @@ oj_write_obj_to_file(VALUE obj, const char *path, Options copts) {
|
|
654
664
|
void
|
655
665
|
oj_write_obj_to_stream(VALUE obj, VALUE stream, Options copts) {
|
656
666
|
char buf[4096];
|
657
|
-
struct
|
667
|
+
struct _out out;
|
658
668
|
ssize_t size;
|
659
669
|
VALUE clas = rb_obj_class(stream);
|
660
670
|
#if !IS_WINDOWS
|
@@ -731,11 +741,36 @@ debug_raise(const char *orig, size_t cnt, int line) {
|
|
731
741
|
rb_raise(oj_json_generator_error_class, "Partial character in string. %s @ %d", buf, line);
|
732
742
|
}
|
733
743
|
|
744
|
+
void
|
745
|
+
oj_dump_raw_json(VALUE obj, int depth, Out out) {
|
746
|
+
if (oj_string_writer_class == rb_obj_class(obj)) {
|
747
|
+
StrWriter sw = (StrWriter)DATA_PTR(obj);
|
748
|
+
size_t len = sw->out.cur - sw->out.buf;
|
749
|
+
|
750
|
+
if (0 < len) {
|
751
|
+
len--;
|
752
|
+
}
|
753
|
+
oj_dump_raw(sw->out.buf, len, out);
|
754
|
+
} else {
|
755
|
+
volatile VALUE jv;
|
756
|
+
|
757
|
+
if (Yes == out->opts->trace) {
|
758
|
+
oj_trace("raw_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyIn);
|
759
|
+
}
|
760
|
+
jv = rb_funcall(obj, oj_raw_json_id, 2, RB_INT2NUM(depth), RB_INT2NUM(out->indent));
|
761
|
+
if (Yes == out->opts->trace) {
|
762
|
+
oj_trace("raw_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyOut);
|
763
|
+
}
|
764
|
+
oj_dump_raw(rb_string_value_ptr((VALUE*)&jv), (size_t)RSTRING_LEN(jv), out);
|
765
|
+
}
|
766
|
+
}
|
767
|
+
|
734
768
|
void
|
735
769
|
oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out out) {
|
736
770
|
size_t size;
|
737
771
|
char *cmap;
|
738
772
|
const char *orig = str;
|
773
|
+
bool has_hi = false;
|
739
774
|
|
740
775
|
switch (out->opts->escape_mode) {
|
741
776
|
case NLEsc:
|
@@ -754,6 +789,19 @@ oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out out) {
|
|
754
789
|
cmap = hixss_friendly_chars;
|
755
790
|
size = hixss_friendly_size((uint8_t*)str, cnt);
|
756
791
|
break;
|
792
|
+
case RailsXEsc: {
|
793
|
+
long sz;
|
794
|
+
|
795
|
+
cmap = rails_xss_friendly_chars;
|
796
|
+
sz = rails_xss_friendly_size((uint8_t*)str, cnt);
|
797
|
+
if (sz < 0) {
|
798
|
+
has_hi = true;
|
799
|
+
size = (size_t)-sz;
|
800
|
+
} else {
|
801
|
+
size = (size_t)sz;
|
802
|
+
}
|
803
|
+
break;
|
804
|
+
}
|
757
805
|
case RailsEsc:
|
758
806
|
cmap = rails_friendly_chars;
|
759
807
|
size = rails_friendly_size((uint8_t*)str, cnt);
|
@@ -777,7 +825,7 @@ oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out out) {
|
|
777
825
|
str++;
|
778
826
|
is_sym = 0; // just to make sure
|
779
827
|
}
|
780
|
-
if (cnt == size) {
|
828
|
+
if (cnt == size && !has_hi) {
|
781
829
|
if (is_sym) {
|
782
830
|
*out->cur++ = ':';
|
783
831
|
}
|
@@ -788,14 +836,14 @@ oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out out) {
|
|
788
836
|
} else {
|
789
837
|
const char *end = str + cnt;
|
790
838
|
const char *check_start = str;
|
791
|
-
|
839
|
+
|
792
840
|
if (is_sym) {
|
793
841
|
*out->cur++ = ':';
|
794
842
|
}
|
795
843
|
for (; str < end; str++) {
|
796
844
|
switch (cmap[(uint8_t)*str]) {
|
797
845
|
case '1':
|
798
|
-
if (JXEsc == out->opts->escape_mode && check_start <= str) {
|
846
|
+
if ((JXEsc == out->opts->escape_mode || RailsXEsc == out->opts->escape_mode) && check_start <= str) {
|
799
847
|
if (0 != (0x80 & (uint8_t)*str)) {
|
800
848
|
if (0xC0 == (0xC0 & (uint8_t)*str)) {
|
801
849
|
check_start = check_unicode(str, end, orig);
|
@@ -819,7 +867,7 @@ oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out out) {
|
|
819
867
|
}
|
820
868
|
break;
|
821
869
|
case '3': // Unicode
|
822
|
-
if (0xe2 == (uint8_t)*str && JXEsc == out->opts->escape_mode && 2 <= end - str) {
|
870
|
+
if (0xe2 == (uint8_t)*str && (JXEsc == out->opts->escape_mode || RailsXEsc == out->opts->escape_mode) && 2 <= end - str) {
|
823
871
|
if (0x80 == (uint8_t)str[1] && (0xa8 == (uint8_t)str[2] || 0xa9 == (uint8_t)str[2])) {
|
824
872
|
str = dump_unicode(str, end, out, orig);
|
825
873
|
} else {
|
@@ -838,7 +886,7 @@ oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out out) {
|
|
838
886
|
*out->cur++ = '0';
|
839
887
|
dump_hex((uint8_t)*str, out);
|
840
888
|
} else {
|
841
|
-
if (0xe2 == (uint8_t)*str && JXEsc == out->opts->escape_mode && 2 <= end - str) {
|
889
|
+
if (0xe2 == (uint8_t)*str && (JXEsc == out->opts->escape_mode || RailsXEsc == out->opts->escape_mode) && 2 <= end - str) {
|
842
890
|
if (0x80 == (uint8_t)str[1] && (0xa8 == (uint8_t)str[2] || 0xa9 == (uint8_t)str[2])) {
|
843
891
|
str = dump_unicode(str, end, out, orig);
|
844
892
|
} else {
|
@@ -854,13 +902,13 @@ oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out out) {
|
|
854
902
|
break; // ignore, should never happen if the table is correct
|
855
903
|
}
|
856
904
|
}
|
857
|
-
*out->cur++ = '"';
|
905
|
+
*out->cur++ = '"';
|
858
906
|
}
|
859
|
-
if (JXEsc == out->opts->escape_mode && 0 < str - orig && 0 != (0x80 & *(str - 1))) {
|
907
|
+
if ((JXEsc == out->opts->escape_mode || RailsXEsc == out->opts->escape_mode) && 0 < str - orig && 0 != (0x80 & *(str - 1))) {
|
860
908
|
uint8_t c = (uint8_t)*(str - 1);
|
861
909
|
int i;
|
862
910
|
int scnt = (int)(str - orig);
|
863
|
-
|
911
|
+
|
864
912
|
// Last utf-8 characters must be 0x10xxxxxx. The start must be
|
865
913
|
// 0x110xxxxx for 2 characters, 0x1110xxxx for 3, and 0x11110xxx for
|
866
914
|
// 4.
|
@@ -926,7 +974,7 @@ oj_grow_out(Out out, size_t len) {
|
|
926
974
|
size_t size = out->end - out->buf;
|
927
975
|
long pos = out->cur - out->buf;
|
928
976
|
char *buf = out->buf;
|
929
|
-
|
977
|
+
|
930
978
|
size *= 2;
|
931
979
|
if (size <= len * 2 + pos) {
|
932
980
|
size += len;
|
@@ -983,24 +1031,21 @@ oj_dump_fixnum(VALUE obj, int depth, Out out, bool as_ok) {
|
|
983
1031
|
char *b = buf + sizeof(buf) - 1;
|
984
1032
|
long long num = rb_num2ll(obj);
|
985
1033
|
int neg = 0;
|
986
|
-
|
1034
|
+
bool dump_as_string = false;
|
987
1035
|
|
988
|
-
|
989
|
-
|
1036
|
+
if (out->opts->int_range_max != 0 && out->opts->int_range_min != 0 &&
|
1037
|
+
(out->opts->int_range_max < num || out->opts->int_range_min > num)) {
|
990
1038
|
dump_as_string = true;
|
991
|
-
|
992
|
-
|
1039
|
+
}
|
993
1040
|
if (0 > num) {
|
994
1041
|
neg = 1;
|
995
1042
|
num = -num;
|
996
1043
|
}
|
997
|
-
|
998
1044
|
*b-- = '\0';
|
999
1045
|
|
1000
|
-
|
1046
|
+
if (dump_as_string) {
|
1001
1047
|
*b-- = '"';
|
1002
|
-
|
1003
|
-
|
1048
|
+
}
|
1004
1049
|
if (0 < num) {
|
1005
1050
|
for (; 0 < num; num /= 10, b--) {
|
1006
1051
|
*b = (num % 10) + '0';
|
@@ -1013,11 +1058,9 @@ oj_dump_fixnum(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1013
1058
|
} else {
|
1014
1059
|
*b = '0';
|
1015
1060
|
}
|
1016
|
-
|
1017
|
-
if (dump_as_string) {
|
1061
|
+
if (dump_as_string) {
|
1018
1062
|
*--b = '"';
|
1019
|
-
|
1020
|
-
|
1063
|
+
}
|
1021
1064
|
assure_size(out, (sizeof(buf) - (b - buf)));
|
1022
1065
|
for (; '\0' != *b; b++) {
|
1023
1066
|
*out->cur++ = *b;
|
@@ -1029,23 +1072,20 @@ void
|
|
1029
1072
|
oj_dump_bignum(VALUE obj, int depth, Out out, bool as_ok) {
|
1030
1073
|
volatile VALUE rs = rb_big2str(obj, 10);
|
1031
1074
|
int cnt = (int)RSTRING_LEN(rs);
|
1032
|
-
|
1075
|
+
bool dump_as_string = false;
|
1033
1076
|
|
1034
|
-
|
1035
|
-
dump_as_string = true;
|
1077
|
+
if (out->opts->int_range_max != 0 || out->opts->int_range_min != 0) { // Bignum cannot be inside of Fixnum range
|
1078
|
+
dump_as_string = true;
|
1036
1079
|
assure_size(out, cnt + 2);
|
1037
1080
|
*out->cur++ = '"';
|
1038
|
-
|
1081
|
+
} else {
|
1039
1082
|
assure_size(out, cnt);
|
1040
|
-
|
1041
|
-
|
1083
|
+
}
|
1042
1084
|
memcpy(out->cur, rb_string_value_ptr((VALUE*)&rs), cnt);
|
1043
1085
|
out->cur += cnt;
|
1044
|
-
|
1045
|
-
if(dump_as_string) {
|
1086
|
+
if (dump_as_string) {
|
1046
1087
|
*out->cur++ = '"';
|
1047
|
-
|
1048
|
-
|
1088
|
+
}
|
1049
1089
|
*out->cur = '\0';
|
1050
1090
|
}
|
1051
1091
|
|
@@ -1070,7 +1110,7 @@ oj_dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1070
1110
|
cnt = sizeof(inf_val) - 1;
|
1071
1111
|
} else {
|
1072
1112
|
NanDump nd = out->opts->dump_opts.nan_dump;
|
1073
|
-
|
1113
|
+
|
1074
1114
|
if (AutoNan == nd) {
|
1075
1115
|
switch (out->opts->mode) {
|
1076
1116
|
case CompatMode: nd = WordNan; break;
|
@@ -1105,7 +1145,7 @@ oj_dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1105
1145
|
cnt = sizeof(ninf_val) - 1;
|
1106
1146
|
} else {
|
1107
1147
|
NanDump nd = out->opts->dump_opts.nan_dump;
|
1108
|
-
|
1148
|
+
|
1109
1149
|
if (AutoNan == nd) {
|
1110
1150
|
switch (out->opts->mode) {
|
1111
1151
|
case CompatMode: nd = WordNan; break;
|
@@ -1139,7 +1179,7 @@ oj_dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1139
1179
|
cnt = sizeof(ninf_val) - 1;
|
1140
1180
|
} else {
|
1141
1181
|
NanDump nd = out->opts->dump_opts.nan_dump;
|
1142
|
-
|
1182
|
+
|
1143
1183
|
if (AutoNan == nd) {
|
1144
1184
|
switch (out->opts->mode) {
|
1145
1185
|
case ObjectMode: nd = HugeNan; break;
|