oj 3.11.5 → 3.16.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +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
|
-
}
|