oj 3.11.5 → 3.16.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1421 -0
- data/README.md +19 -5
- data/RELEASE_NOTES.md +61 -0
- data/ext/oj/buf.h +20 -6
- data/ext/oj/cache.c +329 -0
- data/ext/oj/cache.h +22 -0
- 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 +19 -33
- data/ext/oj/code.h +2 -2
- data/ext/oj/compat.c +27 -77
- data/ext/oj/custom.c +86 -179
- data/ext/oj/debug.c +126 -0
- data/ext/oj/dump.c +256 -249
- data/ext/oj/dump.h +26 -12
- data/ext/oj/dump_compat.c +565 -642
- data/ext/oj/dump_leaf.c +17 -63
- data/ext/oj/dump_object.c +65 -187
- data/ext/oj/dump_strict.c +27 -51
- data/ext/oj/encoder.c +43 -0
- data/ext/oj/err.c +2 -13
- data/ext/oj/err.h +24 -8
- data/ext/oj/extconf.rb +21 -6
- data/ext/oj/fast.c +149 -149
- data/ext/oj/intern.c +313 -0
- data/ext/oj/intern.h +22 -0
- data/ext/oj/mem.c +318 -0
- data/ext/oj/mem.h +53 -0
- data/ext/oj/mimic_json.c +121 -106
- data/ext/oj/object.c +85 -162
- data/ext/oj/odd.c +89 -67
- data/ext/oj/odd.h +15 -15
- data/ext/oj/oj.c +542 -411
- data/ext/oj/oj.h +99 -73
- data/ext/oj/parse.c +175 -187
- data/ext/oj/parse.h +26 -24
- data/ext/oj/parser.c +1600 -0
- data/ext/oj/parser.h +101 -0
- data/ext/oj/rails.c +112 -159
- data/ext/oj/rails.h +1 -1
- data/ext/oj/reader.c +11 -14
- data/ext/oj/reader.h +4 -2
- data/ext/oj/resolve.c +5 -24
- data/ext/oj/rxclass.c +7 -6
- data/ext/oj/rxclass.h +1 -1
- data/ext/oj/saj.c +22 -33
- data/ext/oj/saj2.c +584 -0
- data/ext/oj/saj2.h +23 -0
- data/ext/oj/scp.c +5 -28
- data/ext/oj/sparse.c +28 -72
- data/ext/oj/stream_writer.c +50 -40
- data/ext/oj/strict.c +56 -61
- data/ext/oj/string_writer.c +72 -39
- data/ext/oj/trace.h +31 -4
- data/ext/oj/usual.c +1218 -0
- data/ext/oj/usual.h +69 -0
- data/ext/oj/util.h +1 -1
- data/ext/oj/val_stack.c +14 -3
- data/ext/oj/val_stack.h +8 -7
- data/ext/oj/validate.c +46 -0
- data/ext/oj/wab.c +63 -88
- data/lib/oj/active_support_helper.rb +1 -3
- data/lib/oj/bag.rb +7 -1
- data/lib/oj/easy_hash.rb +4 -5
- data/lib/oj/error.rb +1 -2
- data/lib/oj/json.rb +162 -150
- data/lib/oj/mimic.rb +9 -7
- data/lib/oj/saj.rb +20 -6
- data/lib/oj/schandler.rb +5 -4
- data/lib/oj/state.rb +12 -8
- 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/JsonGem.md +15 -0
- data/pages/Modes.md +8 -3
- data/pages/Options.md +43 -5
- data/pages/Parser.md +309 -0
- data/pages/Rails.md +14 -2
- 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/activesupport6/encoding_test.rb +63 -28
- 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 +86 -50
- 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 +16 -45
- 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 +8 -6
- 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 +56 -38
- 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 +34 -0
- data/test/perf.rb +22 -27
- 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 +59 -0
- data/test/perf_parser.rb +183 -0
- data/test/perf_saj.rb +46 -54
- data/test/perf_scp.rb +58 -69
- data/test/perf_simple.rb +41 -39
- data/test/perf_strict.rb +74 -82
- data/test/perf_wab.rb +67 -69
- data/test/prec.rb +5 -5
- 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 +95 -43
- data/test/test_custom.rb +73 -51
- data/test/test_debian.rb +7 -10
- data/test/test_fast.rb +135 -79
- 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 +5 -5
- data/test/test_integer_range.rb +9 -9
- data/test/test_null.rb +20 -20
- data/test/test_object.rb +99 -96
- data/test/test_parser.rb +11 -0
- data/test/test_parser_debug.rb +27 -0
- data/test/test_parser_saj.rb +337 -0
- data/test/test_parser_usual.rb +251 -0
- 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 +40 -32
- data/test/test_various.rb +165 -84
- data/test/test_wab.rb +48 -44
- data/test/test_writer.rb +47 -47
- data/test/tests.rb +13 -5
- data/test/tests_mimic.rb +12 -3
- data/test/tests_mimic_addition.rb +12 -3
- metadata +74 -128
- data/ext/oj/hash.c +0 -131
- data/ext/oj/hash.h +0 -19
- data/ext/oj/hash_test.c +0 -491
- 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 -35
- data/test/baz.rb +0 -16
- data/test/zoo.rb +0 -13
data/ext/oj/dump.c
CHANGED
@@ -10,8 +10,12 @@
|
|
10
10
|
#include <stdlib.h>
|
11
11
|
#include <string.h>
|
12
12
|
#include <unistd.h>
|
13
|
+
#if !IS_WINDOWS
|
14
|
+
#include <poll.h>
|
15
|
+
#endif
|
13
16
|
|
14
17
|
#include "cache8.h"
|
18
|
+
#include "mem.h"
|
15
19
|
#include "odd.h"
|
16
20
|
#include "oj.h"
|
17
21
|
#include "trace.h"
|
@@ -29,6 +33,7 @@ static const char nan_val[] = NAN_VAL;
|
|
29
33
|
typedef unsigned long ulong;
|
30
34
|
|
31
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);
|
32
37
|
static size_t xss_friendly_size(const uint8_t *str, size_t len);
|
33
38
|
static size_t ascii_friendly_size(const uint8_t *str, size_t len);
|
34
39
|
|
@@ -56,6 +61,17 @@ static char hibit_friendly_chars[256] = "\
|
|
56
61
|
11111111111111111111111111111111\
|
57
62
|
11111111111111111111111111111111";
|
58
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
|
+
|
59
75
|
// High bit set characters are always encoded as unicode. Worse case is 3
|
60
76
|
// bytes per character in the output. That makes this conservative.
|
61
77
|
static char ascii_friendly_chars[256] = "\
|
@@ -113,49 +129,43 @@ static char rails_friendly_chars[256] = "\
|
|
113
129
|
11111111111111111111111111111111";
|
114
130
|
|
115
131
|
static void raise_strict(VALUE obj) {
|
116
|
-
rb_raise(rb_eTypeError,
|
117
|
-
"Failed to dump %s Object to JSON in strict mode.",
|
118
|
-
rb_class2name(rb_obj_class(obj)));
|
132
|
+
rb_raise(rb_eTypeError, "Failed to dump %s Object to JSON in strict mode.", rb_class2name(rb_obj_class(obj)));
|
119
133
|
}
|
120
134
|
|
121
|
-
inline static size_t
|
135
|
+
inline static size_t calculate_string_size(const uint8_t *str, size_t len, const char *table) {
|
122
136
|
size_t size = 0;
|
123
137
|
size_t i = len;
|
124
138
|
|
125
|
-
for (;
|
126
|
-
size +=
|
139
|
+
for (; 3 < i; i -= 4) {
|
140
|
+
size += table[*str++];
|
141
|
+
size += table[*str++];
|
142
|
+
size += table[*str++];
|
143
|
+
size += table[*str++];
|
144
|
+
}
|
145
|
+
for (; 0 < i; i--) {
|
146
|
+
size += table[*str++];
|
127
147
|
}
|
128
148
|
return size - len * (size_t)'0';
|
129
149
|
}
|
130
150
|
|
151
|
+
inline static size_t newline_friendly_size(const uint8_t *str, size_t len) {
|
152
|
+
return calculate_string_size(str, len, newline_friendly_chars);
|
153
|
+
}
|
154
|
+
|
131
155
|
inline static size_t hibit_friendly_size(const uint8_t *str, size_t len) {
|
132
|
-
|
133
|
-
|
156
|
+
return calculate_string_size(str, len, hibit_friendly_chars);
|
157
|
+
}
|
134
158
|
|
135
|
-
|
136
|
-
|
137
|
-
}
|
138
|
-
return size - len * (size_t)'0';
|
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);
|
139
161
|
}
|
140
162
|
|
141
163
|
inline static size_t ascii_friendly_size(const uint8_t *str, size_t len) {
|
142
|
-
|
143
|
-
size_t i = len;
|
144
|
-
|
145
|
-
for (; 0 < i; str++, i--) {
|
146
|
-
size += ascii_friendly_chars[*str];
|
147
|
-
}
|
148
|
-
return size - len * (size_t)'0';
|
164
|
+
return calculate_string_size(str, len, ascii_friendly_chars);
|
149
165
|
}
|
150
166
|
|
151
167
|
inline static size_t xss_friendly_size(const uint8_t *str, size_t len) {
|
152
|
-
|
153
|
-
size_t i = len;
|
154
|
-
|
155
|
-
for (; 0 < i; str++, i--) {
|
156
|
-
size += xss_friendly_chars[*str];
|
157
|
-
}
|
158
|
-
return size - len * (size_t)'0';
|
168
|
+
return calculate_string_size(str, len, xss_friendly_chars);
|
159
169
|
}
|
160
170
|
|
161
171
|
inline static size_t hixss_friendly_size(const uint8_t *str, size_t len) {
|
@@ -188,13 +198,18 @@ inline static long rails_xss_friendly_size(const uint8_t *str, size_t len) {
|
|
188
198
|
}
|
189
199
|
|
190
200
|
inline static size_t rails_friendly_size(const uint8_t *str, size_t len) {
|
191
|
-
|
192
|
-
size_t
|
201
|
+
long size = 0;
|
202
|
+
size_t i = len;
|
203
|
+
uint8_t hi = 0;
|
193
204
|
|
194
205
|
for (; 0 < i; str++, i--) {
|
195
206
|
size += rails_friendly_chars[*str];
|
207
|
+
hi |= *str & 0x80;
|
196
208
|
}
|
197
|
-
|
209
|
+
if (0 == hi) {
|
210
|
+
return size - len * (size_t)'0';
|
211
|
+
}
|
212
|
+
return -(size - len * (size_t)'0');
|
198
213
|
}
|
199
214
|
|
200
215
|
const char *oj_nan_str(VALUE obj, int opt, int mode, bool plus, int *lenp) {
|
@@ -247,7 +262,7 @@ inline static void dump_hex(uint8_t c, Out out) {
|
|
247
262
|
static void raise_invalid_unicode(const char *str, int len, int pos) {
|
248
263
|
char c;
|
249
264
|
char code[32];
|
250
|
-
char
|
265
|
+
char *cp = code;
|
251
266
|
int i;
|
252
267
|
uint8_t d;
|
253
268
|
|
@@ -302,16 +317,14 @@ static const char *dump_unicode(const char *str, const char *end, Out out, const
|
|
302
317
|
uint32_t c1;
|
303
318
|
|
304
319
|
code -= 0x00010000;
|
305
|
-
c1
|
306
|
-
code
|
307
|
-
|
308
|
-
*out->cur++ = 'u';
|
320
|
+
c1 = ((code >> 10) & 0x000003FF) + 0x0000D800;
|
321
|
+
code = (code & 0x000003FF) + 0x0000DC00;
|
322
|
+
APPEND_CHARS(out->cur, "\\u", 2);
|
309
323
|
for (i = 3; 0 <= i; i--) {
|
310
324
|
*out->cur++ = hex_chars[(uint8_t)(c1 >> (i * 4)) & 0x0F];
|
311
325
|
}
|
312
326
|
}
|
313
|
-
|
314
|
-
*out->cur++ = 'u';
|
327
|
+
APPEND_CHARS(out->cur, "\\u", 2);
|
315
328
|
for (i = 3; 0 <= i; i--) {
|
316
329
|
*out->cur++ = hex_chars[(uint8_t)(code >> (i * 4)) & 0x0F];
|
317
330
|
}
|
@@ -360,9 +373,7 @@ long oj_check_circular(VALUE obj, Out out) {
|
|
360
373
|
} else {
|
361
374
|
if (ObjectMode == out->opts->mode) {
|
362
375
|
assure_size(out, 18);
|
363
|
-
|
364
|
-
*out->cur++ = '^';
|
365
|
-
*out->cur++ = 'r';
|
376
|
+
APPEND_CHARS(out->cur, "\"^r", 3);
|
366
377
|
dump_ulong(id, out);
|
367
378
|
*out->cur++ = '"';
|
368
379
|
}
|
@@ -374,15 +385,14 @@ long oj_check_circular(VALUE obj, Out out) {
|
|
374
385
|
|
375
386
|
void oj_dump_time(VALUE obj, Out out, int withZone) {
|
376
387
|
char buf[64];
|
377
|
-
char
|
388
|
+
char *b = buf + sizeof(buf) - 1;
|
378
389
|
long size;
|
379
|
-
char
|
390
|
+
char *dot;
|
380
391
|
int neg = 0;
|
381
392
|
long one = 1000000000;
|
382
393
|
long long sec;
|
383
394
|
long long nsec;
|
384
395
|
|
385
|
-
#ifdef HAVE_RB_TIME_TIMESPEC
|
386
396
|
// rb_time_timespec as well as rb_time_timeeval have a bug that causes an
|
387
397
|
// exception to be raised if a time is before 1970 on 32 bit systems so
|
388
398
|
// check the timespec size and use the ruby calls if a 32 bit system.
|
@@ -392,13 +402,9 @@ void oj_dump_time(VALUE obj, Out out, int withZone) {
|
|
392
402
|
sec = (long long)ts.tv_sec;
|
393
403
|
nsec = ts.tv_nsec;
|
394
404
|
} else {
|
395
|
-
sec =
|
396
|
-
nsec =
|
405
|
+
sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
406
|
+
nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
397
407
|
}
|
398
|
-
#else
|
399
|
-
sec = rb_num2ll(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
400
|
-
nsec = rb_num2ll(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
401
|
-
#endif
|
402
408
|
|
403
409
|
*b-- = '\0';
|
404
410
|
if (withZone) {
|
@@ -464,15 +470,14 @@ void oj_dump_time(VALUE obj, Out out, int withZone) {
|
|
464
470
|
b++;
|
465
471
|
size = sizeof(buf) - (b - buf) - 1;
|
466
472
|
assure_size(out, size);
|
467
|
-
|
468
|
-
out->cur += size;
|
473
|
+
APPEND_CHARS(out->cur, b, size);
|
469
474
|
*out->cur = '\0';
|
470
475
|
}
|
471
476
|
|
472
477
|
void oj_dump_ruby_time(VALUE obj, Out out) {
|
473
|
-
volatile VALUE rstr =
|
478
|
+
volatile VALUE rstr = oj_safe_string_convert(obj);
|
474
479
|
|
475
|
-
oj_dump_cstr(
|
480
|
+
oj_dump_cstr(RSTRING_PTR(rstr), (int)RSTRING_LEN(rstr), 0, 0, out);
|
476
481
|
}
|
477
482
|
|
478
483
|
void oj_dump_xml_time(VALUE obj, Out out) {
|
@@ -485,20 +490,15 @@ void oj_dump_xml_time(VALUE obj, Out out) {
|
|
485
490
|
int tzhour, tzmin;
|
486
491
|
char tzsign = '+';
|
487
492
|
|
488
|
-
#ifdef HAVE_RB_TIME_TIMESPEC
|
489
493
|
if (16 <= sizeof(struct timespec)) {
|
490
494
|
struct timespec ts = rb_time_timespec(obj);
|
491
495
|
|
492
496
|
sec = ts.tv_sec;
|
493
497
|
nsec = ts.tv_nsec;
|
494
498
|
} else {
|
495
|
-
sec =
|
496
|
-
nsec =
|
499
|
+
sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
500
|
+
nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
497
501
|
}
|
498
|
-
#else
|
499
|
-
sec = rb_num2ll(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
500
|
-
nsec = rb_num2ll(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
501
|
-
#endif
|
502
502
|
|
503
503
|
assure_size(out, 36);
|
504
504
|
if (9 > out->opts->sec_prec) {
|
@@ -535,59 +535,39 @@ void oj_dump_xml_time(VALUE obj, Out out) {
|
|
535
535
|
}
|
536
536
|
if ((0 == nsec && !out->opts->sec_prec_set) || 0 == out->opts->sec_prec) {
|
537
537
|
if (0 == tzsecs && rb_funcall2(obj, oj_utcq_id, 0, 0)) {
|
538
|
-
sprintf(buf,
|
539
|
-
|
540
|
-
ti.year,
|
541
|
-
ti.mon,
|
542
|
-
ti.day,
|
543
|
-
ti.hour,
|
544
|
-
ti.min,
|
545
|
-
ti.sec);
|
546
|
-
oj_dump_cstr(buf, 20, 0, 0, out);
|
538
|
+
int len = sprintf(buf, "%04d-%02d-%02dT%02d:%02d:%02dZ", ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec);
|
539
|
+
oj_dump_cstr(buf, len, 0, 0, out);
|
547
540
|
} else {
|
548
|
-
sprintf(buf,
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
oj_dump_cstr(buf,
|
541
|
+
int len = sprintf(buf,
|
542
|
+
"%04d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d",
|
543
|
+
ti.year,
|
544
|
+
ti.mon,
|
545
|
+
ti.day,
|
546
|
+
ti.hour,
|
547
|
+
ti.min,
|
548
|
+
ti.sec,
|
549
|
+
tzsign,
|
550
|
+
tzhour,
|
551
|
+
tzmin);
|
552
|
+
oj_dump_cstr(buf, len, 0, 0, out);
|
560
553
|
}
|
561
554
|
} else if (0 == tzsecs && rb_funcall2(obj, oj_utcq_id, 0, 0)) {
|
562
555
|
char format[64] = "%04d-%02d-%02dT%02d:%02d:%02d.%09ldZ";
|
563
|
-
int len
|
556
|
+
int len;
|
564
557
|
|
565
558
|
if (9 > out->opts->sec_prec) {
|
566
559
|
format[32] = '0' + out->opts->sec_prec;
|
567
|
-
len -= 9 - out->opts->sec_prec;
|
568
560
|
}
|
569
|
-
sprintf(buf, format, ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec, (long)nsec);
|
561
|
+
len = sprintf(buf, format, ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec, (long)nsec);
|
570
562
|
oj_dump_cstr(buf, len, 0, 0, out);
|
571
563
|
} else {
|
572
564
|
char format[64] = "%04d-%02d-%02dT%02d:%02d:%02d.%09ld%c%02d:%02d";
|
573
|
-
int len
|
565
|
+
int len;
|
574
566
|
|
575
567
|
if (9 > out->opts->sec_prec) {
|
576
568
|
format[32] = '0' + out->opts->sec_prec;
|
577
|
-
len -= 9 - out->opts->sec_prec;
|
578
569
|
}
|
579
|
-
sprintf(buf,
|
580
|
-
format,
|
581
|
-
ti.year,
|
582
|
-
ti.mon,
|
583
|
-
ti.day,
|
584
|
-
ti.hour,
|
585
|
-
ti.min,
|
586
|
-
ti.sec,
|
587
|
-
(long)nsec,
|
588
|
-
tzsign,
|
589
|
-
tzhour,
|
590
|
-
tzmin);
|
570
|
+
len = sprintf(buf, format, ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec, (long)nsec, tzsign, tzhour, tzmin);
|
591
571
|
oj_dump_cstr(buf, len, 0, 0, out);
|
592
572
|
}
|
593
573
|
}
|
@@ -598,12 +578,8 @@ void oj_dump_obj_to_json(VALUE obj, Options copts, Out out) {
|
|
598
578
|
|
599
579
|
void oj_dump_obj_to_json_using_params(VALUE obj, Options copts, Out out, int argc, VALUE *argv) {
|
600
580
|
if (0 == out->buf) {
|
601
|
-
out
|
602
|
-
// 1 less than end plus extra for possible errors
|
603
|
-
out->end = out->buf + 4095 - BUFFER_EXTRA;
|
604
|
-
out->allocated = true;
|
581
|
+
oj_out_init(out);
|
605
582
|
}
|
606
|
-
out->cur = out->buf;
|
607
583
|
out->circ_cnt = 0;
|
608
584
|
out->opts = copts;
|
609
585
|
out->hash_cnt = 0;
|
@@ -638,38 +614,51 @@ void oj_dump_obj_to_json_using_params(VALUE obj, Options copts, Out out, int arg
|
|
638
614
|
}
|
639
615
|
|
640
616
|
void oj_write_obj_to_file(VALUE obj, const char *path, Options copts) {
|
641
|
-
char buf[4096];
|
642
617
|
struct _out out;
|
643
618
|
size_t size;
|
644
|
-
FILE
|
619
|
+
FILE *f;
|
645
620
|
int ok;
|
646
621
|
|
647
|
-
out
|
648
|
-
|
649
|
-
out.
|
650
|
-
out.omit_nil = copts->dump_opts.omit_nil;
|
622
|
+
oj_out_init(&out);
|
623
|
+
|
624
|
+
out.omit_nil = copts->dump_opts.omit_nil;
|
651
625
|
oj_dump_obj_to_json(obj, copts, &out);
|
652
626
|
size = out.cur - out.buf;
|
653
627
|
if (0 == (f = fopen(path, "w"))) {
|
654
|
-
|
655
|
-
xfree(out.buf);
|
656
|
-
}
|
628
|
+
oj_out_free(&out);
|
657
629
|
rb_raise(rb_eIOError, "%s", strerror(errno));
|
658
630
|
}
|
659
631
|
ok = (size == fwrite(out.buf, 1, size, f));
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
fclose(f);
|
632
|
+
|
633
|
+
oj_out_free(&out);
|
634
|
+
|
664
635
|
if (!ok) {
|
665
636
|
int err = ferror(f);
|
637
|
+
fclose(f);
|
666
638
|
|
667
639
|
rb_raise(rb_eIOError, "Write failed. [%d:%s]", err, strerror(err));
|
668
640
|
}
|
641
|
+
fclose(f);
|
642
|
+
}
|
643
|
+
|
644
|
+
#if !IS_WINDOWS
|
645
|
+
static void write_ready(int fd) {
|
646
|
+
struct pollfd pp;
|
647
|
+
int i;
|
648
|
+
|
649
|
+
pp.fd = fd;
|
650
|
+
pp.events = POLLERR | POLLOUT;
|
651
|
+
pp.revents = 0;
|
652
|
+
if (0 >= (i = poll(&pp, 1, 5000))) {
|
653
|
+
if (0 == i || EAGAIN == errno) {
|
654
|
+
rb_raise(rb_eIOError, "write timed out");
|
655
|
+
}
|
656
|
+
rb_raise(rb_eIOError, "write failed. %d %s.", errno, strerror(errno));
|
657
|
+
}
|
669
658
|
}
|
659
|
+
#endif
|
670
660
|
|
671
661
|
void oj_write_obj_to_stream(VALUE obj, VALUE stream, Options copts) {
|
672
|
-
char buf[4096];
|
673
662
|
struct _out out;
|
674
663
|
ssize_t size;
|
675
664
|
VALUE clas = rb_obj_class(stream);
|
@@ -678,58 +667,62 @@ void oj_write_obj_to_stream(VALUE obj, VALUE stream, Options copts) {
|
|
678
667
|
VALUE s;
|
679
668
|
#endif
|
680
669
|
|
681
|
-
out
|
682
|
-
|
683
|
-
out.
|
684
|
-
out.omit_nil = copts->dump_opts.omit_nil;
|
670
|
+
oj_out_init(&out);
|
671
|
+
|
672
|
+
out.omit_nil = copts->dump_opts.omit_nil;
|
685
673
|
oj_dump_obj_to_json(obj, copts, &out);
|
686
674
|
size = out.cur - out.buf;
|
687
675
|
if (oj_stringio_class == clas) {
|
688
676
|
rb_funcall(stream, oj_write_id, 1, rb_str_new(out.buf, size));
|
689
677
|
#if !IS_WINDOWS
|
690
|
-
} else if (rb_respond_to(stream, oj_fileno_id) &&
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
678
|
+
} else if (rb_respond_to(stream, oj_fileno_id) && Qnil != (s = rb_funcall(stream, oj_fileno_id, 0)) &&
|
679
|
+
0 != (fd = FIX2INT(s))) {
|
680
|
+
ssize_t cnt;
|
681
|
+
ssize_t total = 0;
|
682
|
+
|
683
|
+
while (true) {
|
684
|
+
if (0 > (cnt = write(fd, out.buf + total, size - total))) {
|
685
|
+
if (EAGAIN != errno) {
|
686
|
+
rb_raise(rb_eIOError, "write failed. %d %s.", errno, strerror(errno));
|
687
|
+
break;
|
688
|
+
}
|
695
689
|
}
|
696
|
-
|
690
|
+
total += cnt;
|
691
|
+
if (size <= total) {
|
692
|
+
// Completed
|
693
|
+
break;
|
694
|
+
}
|
695
|
+
write_ready(fd);
|
697
696
|
}
|
698
697
|
#endif
|
699
698
|
} else if (rb_respond_to(stream, oj_write_id)) {
|
700
699
|
rb_funcall(stream, oj_write_id, 1, rb_str_new(out.buf, size));
|
701
700
|
} else {
|
702
|
-
|
703
|
-
xfree(out.buf);
|
704
|
-
}
|
701
|
+
oj_out_free(&out);
|
705
702
|
rb_raise(rb_eArgError, "to_stream() expected an IO Object.");
|
706
703
|
}
|
707
|
-
|
708
|
-
xfree(out.buf);
|
709
|
-
}
|
704
|
+
oj_out_free(&out);
|
710
705
|
}
|
711
706
|
|
712
707
|
void oj_dump_str(VALUE obj, int depth, Out out, bool as_ok) {
|
713
|
-
|
708
|
+
int idx = RB_ENCODING_GET(obj);
|
714
709
|
|
715
|
-
if (
|
716
|
-
|
710
|
+
if (oj_utf8_encoding_index != idx) {
|
711
|
+
rb_encoding *enc = rb_enc_from_index(idx);
|
712
|
+
obj = rb_str_conv_enc(obj, enc, oj_utf8_encoding);
|
717
713
|
}
|
718
|
-
oj_dump_cstr(
|
714
|
+
oj_dump_cstr(RSTRING_PTR(obj), (int)RSTRING_LEN(obj), 0, 0, out);
|
719
715
|
}
|
720
716
|
|
721
717
|
void oj_dump_sym(VALUE obj, int depth, Out out, bool as_ok) {
|
722
|
-
|
723
|
-
// const char *sym = rb_id2name(SYM2ID(obj));
|
724
|
-
|
725
|
-
volatile VALUE s = rb_sym_to_s(obj);
|
718
|
+
volatile VALUE s = rb_sym2str(obj);
|
726
719
|
|
727
|
-
oj_dump_cstr(
|
720
|
+
oj_dump_cstr(RSTRING_PTR(s), (int)RSTRING_LEN(s), 0, 0, out);
|
728
721
|
}
|
729
722
|
|
730
723
|
static void debug_raise(const char *orig, size_t cnt, int line) {
|
731
724
|
char buf[1024];
|
732
|
-
char
|
725
|
+
char *b = buf;
|
733
726
|
const char *s = orig;
|
734
727
|
const char *s_end = s + cnt;
|
735
728
|
|
@@ -745,8 +738,11 @@ static void debug_raise(const char *orig, size_t cnt, int line) {
|
|
745
738
|
|
746
739
|
void oj_dump_raw_json(VALUE obj, int depth, Out out) {
|
747
740
|
if (oj_string_writer_class == rb_obj_class(obj)) {
|
748
|
-
StrWriter sw
|
749
|
-
size_t len
|
741
|
+
StrWriter sw;
|
742
|
+
size_t len;
|
743
|
+
|
744
|
+
sw = oj_str_writer_unwrap(obj);
|
745
|
+
len = sw->out.cur - sw->out.buf;
|
750
746
|
|
751
747
|
if (0 < len) {
|
752
748
|
len--;
|
@@ -755,22 +751,19 @@ void oj_dump_raw_json(VALUE obj, int depth, Out out) {
|
|
755
751
|
} else {
|
756
752
|
volatile VALUE jv;
|
757
753
|
|
758
|
-
|
759
|
-
oj_trace("raw_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyIn);
|
760
|
-
}
|
754
|
+
TRACE(out->opts->trace, "raw_json", obj, depth + 1, TraceRubyIn);
|
761
755
|
jv = rb_funcall(obj, oj_raw_json_id, 2, RB_INT2NUM(depth), RB_INT2NUM(out->indent));
|
762
|
-
|
763
|
-
|
764
|
-
}
|
765
|
-
oj_dump_raw(rb_string_value_ptr((VALUE *)&jv), (size_t)RSTRING_LEN(jv), out);
|
756
|
+
TRACE(out->opts->trace, "raw_json", obj, depth + 1, TraceRubyOut);
|
757
|
+
oj_dump_raw(RSTRING_PTR(jv), (size_t)RSTRING_LEN(jv), out);
|
766
758
|
}
|
767
759
|
}
|
768
760
|
|
769
761
|
void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out out) {
|
770
762
|
size_t size;
|
771
|
-
char
|
772
|
-
const char *orig
|
773
|
-
bool has_hi
|
763
|
+
char *cmap;
|
764
|
+
const char *orig = str;
|
765
|
+
bool has_hi = false;
|
766
|
+
bool do_unicode_validation = false;
|
774
767
|
|
775
768
|
switch (out->opts->escape_mode) {
|
776
769
|
case NLEsc:
|
@@ -781,13 +774,19 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
|
|
781
774
|
cmap = ascii_friendly_chars;
|
782
775
|
size = ascii_friendly_size((uint8_t *)str, cnt);
|
783
776
|
break;
|
777
|
+
case SlashEsc:
|
778
|
+
has_hi = true;
|
779
|
+
cmap = slash_friendly_chars;
|
780
|
+
size = slash_friendly_size((uint8_t *)str, cnt);
|
781
|
+
break;
|
784
782
|
case XSSEsc:
|
785
783
|
cmap = xss_friendly_chars;
|
786
784
|
size = xss_friendly_size((uint8_t *)str, cnt);
|
787
785
|
break;
|
788
786
|
case JXEsc:
|
789
|
-
cmap
|
790
|
-
size
|
787
|
+
cmap = hixss_friendly_chars;
|
788
|
+
size = hixss_friendly_size((uint8_t *)str, cnt);
|
789
|
+
do_unicode_validation = true;
|
791
790
|
break;
|
792
791
|
case RailsXEsc: {
|
793
792
|
long sz;
|
@@ -800,12 +799,22 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
|
|
800
799
|
} else {
|
801
800
|
size = (size_t)sz;
|
802
801
|
}
|
802
|
+
do_unicode_validation = true;
|
803
803
|
break;
|
804
804
|
}
|
805
|
-
case RailsEsc:
|
805
|
+
case RailsEsc: {
|
806
|
+
long sz;
|
806
807
|
cmap = rails_friendly_chars;
|
807
|
-
|
808
|
+
sz = rails_friendly_size((uint8_t *)str, cnt);
|
809
|
+
if (sz < 0) {
|
810
|
+
has_hi = true;
|
811
|
+
size = (size_t)-sz;
|
812
|
+
} else {
|
813
|
+
size = (size_t)sz;
|
814
|
+
}
|
815
|
+
do_unicode_validation = true;
|
808
816
|
break;
|
817
|
+
}
|
809
818
|
case JSONEsc:
|
810
819
|
default: cmap = hibit_friendly_chars; size = hibit_friendly_size((uint8_t *)str, cnt);
|
811
820
|
}
|
@@ -813,10 +822,7 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
|
|
813
822
|
*out->cur++ = '"';
|
814
823
|
|
815
824
|
if (escape1) {
|
816
|
-
|
817
|
-
*out->cur++ = 'u';
|
818
|
-
*out->cur++ = '0';
|
819
|
-
*out->cur++ = '0';
|
825
|
+
APPEND_CHARS(out->cur, "\\u00", 4);
|
820
826
|
dump_hex((uint8_t)*str, out);
|
821
827
|
cnt--;
|
822
828
|
size--;
|
@@ -827,9 +833,7 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
|
|
827
833
|
if (is_sym) {
|
828
834
|
*out->cur++ = ':';
|
829
835
|
}
|
830
|
-
|
831
|
-
*out->cur++ = *str;
|
832
|
-
}
|
836
|
+
APPEND_CHARS(out->cur, str, cnt);
|
833
837
|
*out->cur++ = '"';
|
834
838
|
} else {
|
835
839
|
const char *end = str + cnt;
|
@@ -841,8 +845,7 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
|
|
841
845
|
for (; str < end; str++) {
|
842
846
|
switch (cmap[(uint8_t)*str]) {
|
843
847
|
case '1':
|
844
|
-
if (
|
845
|
-
check_start <= str) {
|
848
|
+
if (do_unicode_validation && check_start <= str) {
|
846
849
|
if (0 != (0x80 & (uint8_t)*str)) {
|
847
850
|
if (0xC0 == (0xC0 & (uint8_t)*str)) {
|
848
851
|
check_start = check_unicode(str, end, orig);
|
@@ -866,11 +869,8 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
|
|
866
869
|
}
|
867
870
|
break;
|
868
871
|
case '3': // Unicode
|
869
|
-
if (0xe2 == (uint8_t)*str &&
|
870
|
-
(
|
871
|
-
2 <= end - str) {
|
872
|
-
if (0x80 == (uint8_t)str[1] &&
|
873
|
-
(0xa8 == (uint8_t)str[2] || 0xa9 == (uint8_t)str[2])) {
|
872
|
+
if (0xe2 == (uint8_t)*str && do_unicode_validation && 2 <= end - str) {
|
873
|
+
if (0x80 == (uint8_t)str[1] && (0xa8 == (uint8_t)str[2] || 0xa9 == (uint8_t)str[2])) {
|
874
874
|
str = dump_unicode(str, end, out, orig);
|
875
875
|
} else {
|
876
876
|
check_start = check_unicode(str, end, orig);
|
@@ -882,17 +882,14 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
|
|
882
882
|
break;
|
883
883
|
case '6': // control characters
|
884
884
|
if (*(uint8_t *)str < 0x80) {
|
885
|
-
*out->
|
886
|
-
|
887
|
-
|
888
|
-
|
885
|
+
if (0 == (uint8_t)*str && out->opts->dump_opts.omit_null_byte) {
|
886
|
+
break;
|
887
|
+
}
|
888
|
+
APPEND_CHARS(out->cur, "\\u00", 4);
|
889
889
|
dump_hex((uint8_t)*str, out);
|
890
890
|
} else {
|
891
|
-
if (0xe2 == (uint8_t)*str &&
|
892
|
-
(
|
893
|
-
2 <= end - str) {
|
894
|
-
if (0x80 == (uint8_t)str[1] &&
|
895
|
-
(0xa8 == (uint8_t)str[2] || 0xa9 == (uint8_t)str[2])) {
|
891
|
+
if (0xe2 == (uint8_t)*str && do_unicode_validation && 2 <= end - str) {
|
892
|
+
if (0x80 == (uint8_t)str[1] && (0xa8 == (uint8_t)str[2] || 0xa9 == (uint8_t)str[2])) {
|
896
893
|
str = dump_unicode(str, end, out, orig);
|
897
894
|
} else {
|
898
895
|
check_start = check_unicode(str, end, orig);
|
@@ -908,8 +905,7 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
|
|
908
905
|
}
|
909
906
|
*out->cur++ = '"';
|
910
907
|
}
|
911
|
-
if (
|
912
|
-
0 < str - orig && 0 != (0x80 & *(str - 1))) {
|
908
|
+
if (do_unicode_validation && 0 < str - orig && 0 != (0x80 & *(str - 1))) {
|
913
909
|
uint8_t c = (uint8_t) * (str - 1);
|
914
910
|
int i;
|
915
911
|
int scnt = (int)(str - orig);
|
@@ -959,31 +955,43 @@ void oj_dump_class(VALUE obj, int depth, Out out, bool as_ok) {
|
|
959
955
|
}
|
960
956
|
|
961
957
|
void oj_dump_obj_to_s(VALUE obj, Out out) {
|
962
|
-
volatile VALUE rstr =
|
958
|
+
volatile VALUE rstr = oj_safe_string_convert(obj);
|
963
959
|
|
964
|
-
oj_dump_cstr(
|
960
|
+
oj_dump_cstr(RSTRING_PTR(rstr), (int)RSTRING_LEN(rstr), 0, 0, out);
|
965
961
|
}
|
966
962
|
|
967
963
|
void oj_dump_raw(const char *str, size_t cnt, Out out) {
|
968
964
|
assure_size(out, cnt + 10);
|
969
|
-
|
970
|
-
out->cur += cnt;
|
965
|
+
APPEND_CHARS(out->cur, str, cnt);
|
971
966
|
*out->cur = '\0';
|
972
967
|
}
|
973
968
|
|
969
|
+
void oj_out_init(Out out) {
|
970
|
+
out->buf = out->stack_buffer;
|
971
|
+
out->cur = out->buf;
|
972
|
+
out->end = out->buf + sizeof(out->stack_buffer) - BUFFER_EXTRA;
|
973
|
+
out->allocated = false;
|
974
|
+
}
|
975
|
+
|
976
|
+
void oj_out_free(Out out) {
|
977
|
+
if (out->allocated) {
|
978
|
+
OJ_R_FREE(out->buf); // TBD
|
979
|
+
}
|
980
|
+
}
|
981
|
+
|
974
982
|
void oj_grow_out(Out out, size_t len) {
|
975
983
|
size_t size = out->end - out->buf;
|
976
984
|
long pos = out->cur - out->buf;
|
977
|
-
char
|
985
|
+
char *buf = out->buf;
|
978
986
|
|
979
987
|
size *= 2;
|
980
988
|
if (size <= len * 2 + pos) {
|
981
989
|
size += len;
|
982
990
|
}
|
983
991
|
if (out->allocated) {
|
984
|
-
|
992
|
+
OJ_R_REALLOC_N(buf, char, (size + BUFFER_EXTRA));
|
985
993
|
} else {
|
986
|
-
buf =
|
994
|
+
buf = OJ_R_ALLOC_N(char, (size + BUFFER_EXTRA));
|
987
995
|
out->allocated = true;
|
988
996
|
memcpy(buf, out->buf, out->end - out->buf + BUFFER_EXTRA);
|
989
997
|
}
|
@@ -997,37 +1005,62 @@ void oj_grow_out(Out out, size_t len) {
|
|
997
1005
|
|
998
1006
|
void oj_dump_nil(VALUE obj, int depth, Out out, bool as_ok) {
|
999
1007
|
assure_size(out, 4);
|
1000
|
-
|
1001
|
-
*out->cur
|
1002
|
-
*out->cur++ = 'l';
|
1003
|
-
*out->cur++ = 'l';
|
1004
|
-
*out->cur = '\0';
|
1008
|
+
APPEND_CHARS(out->cur, "null", 4);
|
1009
|
+
*out->cur = '\0';
|
1005
1010
|
}
|
1006
1011
|
|
1007
1012
|
void oj_dump_true(VALUE obj, int depth, Out out, bool as_ok) {
|
1008
1013
|
assure_size(out, 4);
|
1009
|
-
|
1010
|
-
*out->cur
|
1011
|
-
*out->cur++ = 'u';
|
1012
|
-
*out->cur++ = 'e';
|
1013
|
-
*out->cur = '\0';
|
1014
|
+
APPEND_CHARS(out->cur, "true", 4);
|
1015
|
+
*out->cur = '\0';
|
1014
1016
|
}
|
1015
1017
|
|
1016
1018
|
void oj_dump_false(VALUE obj, int depth, Out out, bool as_ok) {
|
1017
1019
|
assure_size(out, 5);
|
1018
|
-
|
1019
|
-
*out->cur
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1020
|
+
APPEND_CHARS(out->cur, "false", 5);
|
1021
|
+
*out->cur = '\0';
|
1022
|
+
}
|
1023
|
+
|
1024
|
+
static const char digits_table[] = "\
|
1025
|
+
00010203040506070809\
|
1026
|
+
10111213141516171819\
|
1027
|
+
20212223242526272829\
|
1028
|
+
30313233343536373839\
|
1029
|
+
40414243444546474849\
|
1030
|
+
50515253545556575859\
|
1031
|
+
60616263646566676869\
|
1032
|
+
70717273747576777879\
|
1033
|
+
80818283848586878889\
|
1034
|
+
90919293949596979899";
|
1035
|
+
|
1036
|
+
char *oj_longlong_to_string(long long num, bool negative, char *buf) {
|
1037
|
+
while (100 <= num) {
|
1038
|
+
unsigned idx = num % 100 * 2;
|
1039
|
+
*buf-- = digits_table[idx + 1];
|
1040
|
+
*buf-- = digits_table[idx];
|
1041
|
+
num /= 100;
|
1042
|
+
}
|
1043
|
+
if (num < 10) {
|
1044
|
+
*buf-- = num + '0';
|
1045
|
+
} else {
|
1046
|
+
*buf-- = digits_table[num * 2 + 1];
|
1047
|
+
*buf-- = digits_table[num * 2];
|
1048
|
+
}
|
1049
|
+
|
1050
|
+
if (negative) {
|
1051
|
+
*buf = '-';
|
1052
|
+
} else {
|
1053
|
+
buf++;
|
1054
|
+
}
|
1055
|
+
return buf;
|
1024
1056
|
}
|
1025
1057
|
|
1026
1058
|
void oj_dump_fixnum(VALUE obj, int depth, Out out, bool as_ok) {
|
1027
1059
|
char buf[32];
|
1028
|
-
char
|
1029
|
-
long long num =
|
1030
|
-
|
1060
|
+
char *b = buf + sizeof(buf) - 1;
|
1061
|
+
long long num = NUM2LL(obj);
|
1062
|
+
bool neg = false;
|
1063
|
+
size_t cnt = 0;
|
1031
1064
|
bool dump_as_string = false;
|
1032
1065
|
|
1033
1066
|
if (out->opts->int_range_max != 0 && out->opts->int_range_min != 0 &&
|
@@ -1035,7 +1068,7 @@ void oj_dump_fixnum(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1035
1068
|
dump_as_string = true;
|
1036
1069
|
}
|
1037
1070
|
if (0 > num) {
|
1038
|
-
neg =
|
1071
|
+
neg = true;
|
1039
1072
|
num = -num;
|
1040
1073
|
}
|
1041
1074
|
*b-- = '\0';
|
@@ -1044,24 +1077,16 @@ void oj_dump_fixnum(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1044
1077
|
*b-- = '"';
|
1045
1078
|
}
|
1046
1079
|
if (0 < num) {
|
1047
|
-
|
1048
|
-
*b = (num % 10) + '0';
|
1049
|
-
}
|
1050
|
-
if (neg) {
|
1051
|
-
*b = '-';
|
1052
|
-
} else {
|
1053
|
-
b++;
|
1054
|
-
}
|
1080
|
+
b = oj_longlong_to_string(num, neg, b);
|
1055
1081
|
} else {
|
1056
1082
|
*b = '0';
|
1057
1083
|
}
|
1058
1084
|
if (dump_as_string) {
|
1059
1085
|
*--b = '"';
|
1060
1086
|
}
|
1061
|
-
|
1062
|
-
|
1063
|
-
|
1064
|
-
}
|
1087
|
+
cnt = sizeof(buf) - (b - buf) - 1;
|
1088
|
+
assure_size(out, cnt);
|
1089
|
+
APPEND_CHARS(out->cur, b, cnt);
|
1065
1090
|
*out->cur = '\0';
|
1066
1091
|
}
|
1067
1092
|
|
@@ -1070,16 +1095,14 @@ void oj_dump_bignum(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1070
1095
|
int cnt = (int)RSTRING_LEN(rs);
|
1071
1096
|
bool dump_as_string = false;
|
1072
1097
|
|
1073
|
-
if (out->opts->int_range_max != 0 ||
|
1074
|
-
out->opts->int_range_min != 0) { // Bignum cannot be inside of Fixnum range
|
1098
|
+
if (out->opts->int_range_max != 0 || out->opts->int_range_min != 0) { // Bignum cannot be inside of Fixnum range
|
1075
1099
|
dump_as_string = true;
|
1076
1100
|
assure_size(out, cnt + 2);
|
1077
1101
|
*out->cur++ = '"';
|
1078
1102
|
} else {
|
1079
1103
|
assure_size(out, cnt);
|
1080
1104
|
}
|
1081
|
-
|
1082
|
-
out->cur += cnt;
|
1105
|
+
APPEND_CHARS(out->cur, RSTRING_PTR(rs), cnt);
|
1083
1106
|
if (dump_as_string) {
|
1084
1107
|
*out->cur++ = '"';
|
1085
1108
|
}
|
@@ -1089,7 +1112,7 @@ void oj_dump_bignum(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1089
1112
|
// Removed dependencies on math due to problems with CentOS 5.4.
|
1090
1113
|
void oj_dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
1091
1114
|
char buf[64];
|
1092
|
-
char
|
1115
|
+
char *b;
|
1093
1116
|
double d = rb_num2dbl(obj);
|
1094
1117
|
int cnt = 0;
|
1095
1118
|
|
@@ -1168,7 +1191,7 @@ void oj_dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1168
1191
|
} else if (isnan(d)) {
|
1169
1192
|
if (ObjectMode == out->opts->mode) {
|
1170
1193
|
strcpy(buf, nan_val);
|
1171
|
-
cnt = sizeof(
|
1194
|
+
cnt = sizeof(nan_val) - 1;
|
1172
1195
|
} else {
|
1173
1196
|
NanDump nd = out->opts->dump_opts.nan_dump;
|
1174
1197
|
|
@@ -1200,21 +1223,19 @@ void oj_dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1200
1223
|
} else if (d == (double)(long long int)d) {
|
1201
1224
|
cnt = snprintf(buf, sizeof(buf), "%.1f", d);
|
1202
1225
|
} else if (0 == out->opts->float_prec) {
|
1203
|
-
volatile VALUE rstr =
|
1226
|
+
volatile VALUE rstr = oj_safe_string_convert(obj);
|
1204
1227
|
|
1205
1228
|
cnt = (int)RSTRING_LEN(rstr);
|
1206
1229
|
if ((int)sizeof(buf) <= cnt) {
|
1207
1230
|
cnt = sizeof(buf) - 1;
|
1208
1231
|
}
|
1209
|
-
|
1232
|
+
memcpy(buf, RSTRING_PTR(rstr), cnt);
|
1210
1233
|
buf[cnt] = '\0';
|
1211
1234
|
} else {
|
1212
1235
|
cnt = oj_dump_float_printf(buf, sizeof(buf), obj, d, out->opts->float_fmt);
|
1213
1236
|
}
|
1214
1237
|
assure_size(out, cnt);
|
1215
|
-
|
1216
|
-
*out->cur++ = *b;
|
1217
|
-
}
|
1238
|
+
APPEND_CHARS(out->cur, buf, cnt);
|
1218
1239
|
*out->cur = '\0';
|
1219
1240
|
}
|
1220
1241
|
|
@@ -1224,24 +1245,10 @@ int oj_dump_float_printf(char *buf, size_t blen, VALUE obj, double d, const char
|
|
1224
1245
|
// Round off issues at 16 significant digits so check for obvious ones of
|
1225
1246
|
// 0001 and 9999.
|
1226
1247
|
if (17 <= cnt && (0 == strcmp("0001", buf + cnt - 4) || 0 == strcmp("9999", buf + cnt - 4))) {
|
1227
|
-
volatile VALUE rstr =
|
1248
|
+
volatile VALUE rstr = oj_safe_string_convert(obj);
|
1228
1249
|
|
1229
|
-
strcpy(buf,
|
1250
|
+
strcpy(buf, RSTRING_PTR(rstr));
|
1230
1251
|
cnt = (int)RSTRING_LEN(rstr);
|
1231
1252
|
}
|
1232
1253
|
return cnt;
|
1233
1254
|
}
|
1234
|
-
|
1235
|
-
bool oj_dump_ignore(Options opts, VALUE obj) {
|
1236
|
-
if (NULL != opts->ignore && (ObjectMode == opts->mode || CustomMode == opts->mode)) {
|
1237
|
-
VALUE *vp = opts->ignore;
|
1238
|
-
VALUE clas = rb_obj_class(obj);
|
1239
|
-
|
1240
|
-
for (; Qnil != *vp; vp++) {
|
1241
|
-
if (clas == *vp) {
|
1242
|
-
return true;
|
1243
|
-
}
|
1244
|
-
}
|
1245
|
-
}
|
1246
|
-
return false;
|
1247
|
-
}
|