oj 3.7.4 → 3.11.2
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/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;
|