oj 3.7.7 → 3.7.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/oj/custom.c +14 -10
- data/ext/oj/dump.c +17 -40
- data/ext/oj/fast.c +11 -0
- data/ext/oj/object.c +23 -26
- data/ext/oj/odd.c +5 -5
- data/ext/oj/rails.c +10 -21
- data/ext/oj/util.c +136 -0
- data/ext/oj/util.h +19 -0
- data/ext/oj/val_stack.c +16 -2
- data/ext/oj/val_stack.h +4 -7
- data/ext/oj/wab.c +8 -9
- data/lib/oj/version.rb +1 -1
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5008cd86952b184d31350d5e84256ca433e3dafe672c04400cd8d74bbc6190f4
|
4
|
+
data.tar.gz: 620b94ba6107477d17eda4d2f3558f1aa98d3c6635bdbb16443ba2b5868aeb57
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c1641f5af216aab8948c70c5c0e75f6f9fc6db9de5eca5cafad65b7fc6b877cded31bbf9f5b0fdb438217bfeae7c04cb880ec1b560771e0b341a0f1292f3c1e3
|
7
|
+
data.tar.gz: 1e3a1f8ee9b47fb8004cc53992ae68e5cceb055a53daecc73771ebccf3d3edcefeaac70e58f740279482e49eca89f32d38866a3412d67efdb9738f4e80c8c2e2
|
data/ext/oj/custom.c
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
* All rights reserved.
|
4
4
|
*/
|
5
5
|
|
6
|
+
#include <stdint.h>
|
6
7
|
#include <stdio.h>
|
7
8
|
|
8
9
|
#include "code.h"
|
@@ -15,6 +16,7 @@
|
|
15
16
|
#include "parse.h"
|
16
17
|
#include "resolve.h"
|
17
18
|
#include "trace.h"
|
19
|
+
#include "util.h"
|
18
20
|
|
19
21
|
extern void oj_set_obj_ivar(Val parent, Val kval, VALUE value);
|
20
22
|
extern VALUE oj_parse_xml_time(const char *str, int len); // from object.c
|
@@ -1058,16 +1060,18 @@ hash_set_num(struct _parseInfo *pi, Val kval, NumInfo ni) {
|
|
1058
1060
|
// match the expected value.
|
1059
1061
|
parent->val = rb_funcall2(parent->val, oj_utc_id, 0, 0);
|
1060
1062
|
} else if (ni->hasExp) {
|
1061
|
-
|
1062
|
-
struct
|
1063
|
-
VALUE
|
1064
|
-
|
1065
|
-
|
1066
|
-
|
1067
|
-
args[
|
1068
|
-
args[
|
1069
|
-
args[
|
1070
|
-
args[
|
1063
|
+
int64_t t = (int64_t)(ni->i + ni->exp);
|
1064
|
+
struct _timeInfo ti;
|
1065
|
+
VALUE args[8];
|
1066
|
+
|
1067
|
+
sec_as_time(t, &ti);
|
1068
|
+
|
1069
|
+
args[0] = LONG2NUM(ti.year);
|
1070
|
+
args[1] = LONG2NUM(ti.mon);
|
1071
|
+
args[2] = LONG2NUM(ti.day);
|
1072
|
+
args[3] = LONG2NUM(ti.hour);
|
1073
|
+
args[4] = LONG2NUM(ti.min);
|
1074
|
+
args[5] = rb_float_new((double)ti.sec + ((double)nsec + 0.5) / 1000000000.0);
|
1071
1075
|
args[6] = LONG2NUM(ni->exp);
|
1072
1076
|
parent->val = rb_funcall2(rb_cTime, oj_new_id, 7, args);
|
1073
1077
|
} else {
|
data/ext/oj/dump.c
CHANGED
@@ -3,22 +3,19 @@
|
|
3
3
|
* All rights reserved.
|
4
4
|
*/
|
5
5
|
|
6
|
-
#include <stdlib.h>
|
7
6
|
#include <errno.h>
|
8
|
-
#
|
9
|
-
#include <
|
10
|
-
#endif
|
11
|
-
#include <time.h>
|
7
|
+
#include <math.h>
|
8
|
+
#include <stdint.h>
|
12
9
|
#include <stdio.h>
|
10
|
+
#include <stdlib.h>
|
13
11
|
#include <string.h>
|
14
|
-
#include <math.h>
|
15
12
|
#include <unistd.h>
|
16
|
-
#include <errno.h>
|
17
13
|
|
18
14
|
#include "oj.h"
|
19
15
|
#include "cache8.h"
|
20
16
|
#include "dump.h"
|
21
17
|
#include "odd.h"
|
18
|
+
#include "util.h"
|
22
19
|
|
23
20
|
// Workaround in case INFINITY is not defined in math.h or if the OS is CentOS
|
24
21
|
#define OJ_INFINITY (1.0/0.0)
|
@@ -493,14 +490,14 @@ oj_dump_ruby_time(VALUE obj, Out out) {
|
|
493
490
|
|
494
491
|
void
|
495
492
|
oj_dump_xml_time(VALUE obj, Out out) {
|
496
|
-
char
|
497
|
-
struct
|
498
|
-
long
|
499
|
-
|
500
|
-
long long
|
501
|
-
long
|
502
|
-
int
|
503
|
-
char
|
493
|
+
char buf[64];
|
494
|
+
struct _timeInfo ti;
|
495
|
+
long one = 1000000000;
|
496
|
+
int64_t sec;
|
497
|
+
long long nsec;
|
498
|
+
long tzsecs = NUM2LONG(rb_funcall2(obj, oj_utc_offset_id, 0, 0));
|
499
|
+
int tzhour, tzmin;
|
500
|
+
char tzsign = '+';
|
504
501
|
|
505
502
|
#ifdef HAVE_RB_TIME_TIMESPEC
|
506
503
|
if (16 <= sizeof(struct timespec)) {
|
@@ -541,8 +538,7 @@ oj_dump_xml_time(VALUE obj, Out out) {
|
|
541
538
|
// 2012-01-05T23:58:07.123456000+09:00
|
542
539
|
//tm = localtime(&sec);
|
543
540
|
sec += tzsecs;
|
544
|
-
|
545
|
-
#if 1
|
541
|
+
sec_as_time((int64_t)sec, &ti);
|
546
542
|
if (0 > tzsecs) {
|
547
543
|
tzsign = '-';
|
548
544
|
tzhour = (int)(tzsecs / -3600);
|
@@ -551,26 +547,12 @@ oj_dump_xml_time(VALUE obj, Out out) {
|
|
551
547
|
tzhour = (int)(tzsecs / 3600);
|
552
548
|
tzmin = (int)(tzsecs / 60) - (tzhour * 60);
|
553
549
|
}
|
554
|
-
#else
|
555
|
-
if (0 > tm->tm_gmtoff) {
|
556
|
-
tzsign = '-';
|
557
|
-
tzhour = (int)(tm->tm_gmtoff / -3600);
|
558
|
-
tzmin = (int)(tm->tm_gmtoff / -60) - (tzhour * 60);
|
559
|
-
} else {
|
560
|
-
tzhour = (int)(tm->tm_gmtoff / 3600);
|
561
|
-
tzmin = (int)(tm->tm_gmtoff / 60) - (tzhour * 60);
|
562
|
-
}
|
563
|
-
#endif
|
564
550
|
if (0 == nsec || 0 == out->opts->sec_prec) {
|
565
551
|
if (0 == tzsecs && rb_funcall2(obj, oj_utcq_id, 0, 0)) {
|
566
|
-
sprintf(buf, "%04d-%02d-%02dT%02d:%02d:%02dZ",
|
567
|
-
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
|
568
|
-
tm->tm_hour, tm->tm_min, tm->tm_sec);
|
552
|
+
sprintf(buf, "%04d-%02d-%02dT%02d:%02d:%02dZ", ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec);
|
569
553
|
oj_dump_cstr(buf, 20, 0, 0, out);
|
570
554
|
} else {
|
571
|
-
sprintf(buf, "%04d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d",
|
572
|
-
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
|
573
|
-
tm->tm_hour, tm->tm_min, tm->tm_sec,
|
555
|
+
sprintf(buf, "%04d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d", ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec,
|
574
556
|
tzsign, tzhour, tzmin);
|
575
557
|
oj_dump_cstr(buf, 25, 0, 0, out);
|
576
558
|
}
|
@@ -582,9 +564,7 @@ oj_dump_xml_time(VALUE obj, Out out) {
|
|
582
564
|
format[32] = '0' + out->opts->sec_prec;
|
583
565
|
len -= 9 - out->opts->sec_prec;
|
584
566
|
}
|
585
|
-
sprintf(buf, format,
|
586
|
-
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
|
587
|
-
tm->tm_hour, tm->tm_min, tm->tm_sec, (long)nsec);
|
567
|
+
sprintf(buf, format, ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec, (long)nsec);
|
588
568
|
oj_dump_cstr(buf, len, 0, 0, out);
|
589
569
|
} else {
|
590
570
|
char format[64] = "%04d-%02d-%02dT%02d:%02d:%02d.%09ld%c%02d:%02d";
|
@@ -594,10 +574,7 @@ oj_dump_xml_time(VALUE obj, Out out) {
|
|
594
574
|
format[32] = '0' + out->opts->sec_prec;
|
595
575
|
len -= 9 - out->opts->sec_prec;
|
596
576
|
}
|
597
|
-
sprintf(buf, format,
|
598
|
-
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
|
599
|
-
tm->tm_hour, tm->tm_min, tm->tm_sec, (long)nsec,
|
600
|
-
tzsign, tzhour, tzmin);
|
577
|
+
sprintf(buf, format, ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec, (long)nsec, tzsign, tzhour, tzmin);
|
601
578
|
oj_dump_cstr(buf, len, 0, 0, out);
|
602
579
|
}
|
603
580
|
}
|
data/ext/oj/fast.c
CHANGED
@@ -819,6 +819,8 @@ parse_json(VALUE clas, char *json, bool given, bool allocated) {
|
|
819
819
|
int ex = 0;
|
820
820
|
volatile VALUE self;
|
821
821
|
|
822
|
+
// TBD are both needed? is stack allocation ever needed?
|
823
|
+
|
822
824
|
if (given) {
|
823
825
|
doc = ALLOCA_N(struct _doc, 1);
|
824
826
|
} else {
|
@@ -862,6 +864,7 @@ parse_json(VALUE clas, char *json, bool given, bool allocated) {
|
|
862
864
|
if (allocated && 0 != ex) { // will jump so caller will not free
|
863
865
|
xfree(json);
|
864
866
|
}
|
867
|
+
rb_gc_enable();
|
865
868
|
} else {
|
866
869
|
result = doc->self;
|
867
870
|
}
|
@@ -1165,8 +1168,14 @@ doc_open(VALUE clas, VALUE str) {
|
|
1165
1168
|
} else {
|
1166
1169
|
json = ALLOCA_N(char, len);
|
1167
1170
|
}
|
1171
|
+
// It should not be necessaary to stop GC but if it is not stopped and a
|
1172
|
+
// large string is parsed that string is corrupted or freed during
|
1173
|
+
// parsing. I'm not sure what is going on exactly but disabling GC avoids
|
1174
|
+
// the issue.
|
1175
|
+
rb_gc_disable();
|
1168
1176
|
memcpy(json, StringValuePtr(str), len);
|
1169
1177
|
obj = parse_json(clas, json, given, allocate);
|
1178
|
+
rb_gc_enable();
|
1170
1179
|
if (given && allocate) {
|
1171
1180
|
xfree(json);
|
1172
1181
|
}
|
@@ -1222,7 +1231,9 @@ doc_open_file(VALUE clas, VALUE filename) {
|
|
1222
1231
|
}
|
1223
1232
|
fclose(f);
|
1224
1233
|
json[len] = '\0';
|
1234
|
+
rb_gc_disable();
|
1225
1235
|
obj = parse_json(clas, json, given, allocate);
|
1236
|
+
rb_gc_enable();
|
1226
1237
|
if (given && allocate) {
|
1227
1238
|
xfree(json);
|
1228
1239
|
}
|
data/ext/oj/object.c
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
* All rights reserved.
|
4
4
|
*/
|
5
5
|
|
6
|
+
#include <stdint.h>
|
6
7
|
#include <stdio.h>
|
7
8
|
#include <time.h>
|
8
9
|
|
@@ -14,6 +15,7 @@
|
|
14
15
|
#include "odd.h"
|
15
16
|
#include "encode.h"
|
16
17
|
#include "trace.h"
|
18
|
+
#include "util.h"
|
17
19
|
|
18
20
|
inline static long
|
19
21
|
read_long(const char *str, size_t len) {
|
@@ -291,24 +293,19 @@ hat_num(ParseInfo pi, Val parent, Val kval, NumInfo ni) {
|
|
291
293
|
// match the expected value.
|
292
294
|
parent->val = rb_funcall2(parent->val, oj_utc_id, 0, 0);
|
293
295
|
} else if (ni->hasExp) {
|
294
|
-
|
295
|
-
struct
|
296
|
-
VALUE
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
args[4] = LONG2NUM(st->tm_min);
|
308
|
-
args[5] = rb_float_new((double)st->tm_sec + ((double)nsec + 0.5) / 1000000000.0);
|
309
|
-
args[6] = LONG2NUM(ni->exp);
|
310
|
-
parent->val = rb_funcall2(rb_cTime, oj_new_id, 7, args);
|
311
|
-
}
|
296
|
+
int64_t t = (int64_t)(ni->i + ni->exp);
|
297
|
+
struct _timeInfo ti;
|
298
|
+
VALUE args[8];
|
299
|
+
|
300
|
+
sec_as_time(t, &ti);
|
301
|
+
args[0] = LONG2NUM((long)(ti.year));
|
302
|
+
args[1] = LONG2NUM(ti.mon);
|
303
|
+
args[2] = LONG2NUM(ti.day);
|
304
|
+
args[3] = LONG2NUM(ti.hour);
|
305
|
+
args[4] = LONG2NUM(ti.min);
|
306
|
+
args[5] = rb_float_new((double)ti.sec + ((double)nsec + 0.5) / 1000000000.0);
|
307
|
+
args[6] = LONG2NUM(ni->exp);
|
308
|
+
parent->val = rb_funcall2(rb_cTime, oj_new_id, 7, args);
|
312
309
|
} else {
|
313
310
|
parent->val = rb_time_nano_new(ni->i, (long)nsec);
|
314
311
|
}
|
@@ -462,7 +459,7 @@ hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, const char *o
|
|
462
459
|
WHICH_TYPE:
|
463
460
|
switch (rb_type(parent->val)) {
|
464
461
|
case T_NIL:
|
465
|
-
parent->odd_args =
|
462
|
+
parent->odd_args = NULL; // make sure it is NULL in case not odd
|
466
463
|
if ('^' != *key || !hat_cstr(pi, parent, kval, str, len)) {
|
467
464
|
parent->val = rb_hash_new();
|
468
465
|
goto WHICH_TYPE;
|
@@ -484,7 +481,7 @@ hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, const char *o
|
|
484
481
|
oj_set_obj_ivar(parent, kval, rval);
|
485
482
|
break;
|
486
483
|
case T_CLASS:
|
487
|
-
if (
|
484
|
+
if (NULL == parent->odd_args) {
|
488
485
|
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "%s is not an odd class", rb_class2name(rb_obj_class(parent->val)));
|
489
486
|
return;
|
490
487
|
} else {
|
@@ -520,7 +517,7 @@ hash_set_num(ParseInfo pi, Val kval, NumInfo ni) {
|
|
520
517
|
WHICH_TYPE:
|
521
518
|
switch (rb_type(parent->val)) {
|
522
519
|
case T_NIL:
|
523
|
-
parent->odd_args =
|
520
|
+
parent->odd_args = NULL; // make sure it is NULL in case not odd
|
524
521
|
if ('^' != *key || !hat_num(pi, parent, kval, ni)) {
|
525
522
|
parent->val = rb_hash_new();
|
526
523
|
goto WHICH_TYPE;
|
@@ -540,7 +537,7 @@ hash_set_num(ParseInfo pi, Val kval, NumInfo ni) {
|
|
540
537
|
}
|
541
538
|
break;
|
542
539
|
case T_CLASS:
|
543
|
-
if (
|
540
|
+
if (NULL == parent->odd_args) {
|
544
541
|
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "%s is not an odd class", rb_class2name(rb_obj_class(parent->val)));
|
545
542
|
return;
|
546
543
|
} else {
|
@@ -575,7 +572,7 @@ hash_set_value(ParseInfo pi, Val kval, VALUE value) {
|
|
575
572
|
WHICH_TYPE:
|
576
573
|
switch (rb_type(parent->val)) {
|
577
574
|
case T_NIL:
|
578
|
-
parent->odd_args =
|
575
|
+
parent->odd_args = NULL; // make sure it is NULL in case not odd
|
579
576
|
if ('^' != *key || !hat_value(pi, parent, key, klen, value)) {
|
580
577
|
parent->val = rb_hash_new();
|
581
578
|
goto WHICH_TYPE;
|
@@ -616,7 +613,7 @@ hash_set_value(ParseInfo pi, Val kval, VALUE value) {
|
|
616
613
|
break;
|
617
614
|
case T_MODULE:
|
618
615
|
case T_CLASS:
|
619
|
-
if (
|
616
|
+
if (NULL == parent->odd_args) {
|
620
617
|
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "%s is not an odd class", rb_class2name(rb_obj_class(parent->val)));
|
621
618
|
return;
|
622
619
|
} else if (0 != oj_odd_set_arg(parent->odd_args, key, klen, value)) {
|
@@ -653,12 +650,12 @@ end_hash(ParseInfo pi) {
|
|
653
650
|
|
654
651
|
if (Qnil == parent->val) {
|
655
652
|
parent->val = rb_hash_new();
|
656
|
-
} else if (
|
653
|
+
} else if (NULL != parent->odd_args) {
|
657
654
|
OddArgs oa = parent->odd_args;
|
658
655
|
|
659
656
|
parent->val = rb_funcall2(oa->odd->create_obj, oa->odd->create_op, oa->odd->attr_cnt, oa->args);
|
660
657
|
oj_odd_free(oa);
|
661
|
-
parent->odd_args =
|
658
|
+
parent->odd_args = NULL;
|
662
659
|
}
|
663
660
|
if (Yes == pi->options.trace) {
|
664
661
|
oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
|
data/ext/oj/odd.c
CHANGED
@@ -38,11 +38,11 @@ set_class(Odd odd, const char *classname) {
|
|
38
38
|
|
39
39
|
static VALUE
|
40
40
|
get_datetime_secs(VALUE obj) {
|
41
|
-
VALUE rsecs = rb_funcall(obj, sec_id, 0);
|
42
|
-
VALUE rfrac = rb_funcall(obj, sec_fraction_id, 0);
|
43
|
-
long
|
44
|
-
long long
|
45
|
-
long long
|
41
|
+
volatile VALUE rsecs = rb_funcall(obj, sec_id, 0);
|
42
|
+
volatile VALUE rfrac = rb_funcall(obj, sec_fraction_id, 0);
|
43
|
+
long sec = NUM2LONG(rsecs);
|
44
|
+
long long num = rb_num2ll(rb_funcall(rfrac, numerator_id, 0));
|
45
|
+
long long den = rb_num2ll(rb_funcall(rfrac, denominator_id, 0));
|
46
46
|
|
47
47
|
num += sec * den;
|
48
48
|
|
data/ext/oj/rails.c
CHANGED
@@ -8,6 +8,7 @@
|
|
8
8
|
#include "code.h"
|
9
9
|
#include "encode.h"
|
10
10
|
#include "trace.h"
|
11
|
+
#include "util.h"
|
11
12
|
|
12
13
|
#define OJ_INFINITY (1.0/0.0)
|
13
14
|
|
@@ -221,9 +222,9 @@ dump_bigdecimal(VALUE obj, int depth, Out out, bool as_ok) {
|
|
221
222
|
}
|
222
223
|
|
223
224
|
static void
|
224
|
-
dump_sec_nano(VALUE obj,
|
225
|
+
dump_sec_nano(VALUE obj, int64_t sec, long nsec, Out out) {
|
225
226
|
char buf[64];
|
226
|
-
struct
|
227
|
+
struct _timeInfo ti;
|
227
228
|
long one = 1000000000;
|
228
229
|
long tzsecs = NUM2LONG(rb_funcall2(obj, oj_utc_offset_id, 0, 0));
|
229
230
|
int tzhour, tzmin;
|
@@ -248,7 +249,7 @@ dump_sec_nano(VALUE obj, time_t sec, long nsec, Out out) {
|
|
248
249
|
}
|
249
250
|
// 2012-01-05T23:58:07.123456000+09:00 or 2012/01/05 23:58:07 +0900
|
250
251
|
sec += tzsecs;
|
251
|
-
|
252
|
+
sec_as_time(sec, &ti);
|
252
253
|
if (0 > tzsecs) {
|
253
254
|
tzsign = '-';
|
254
255
|
tzhour = (int)(tzsecs / -3600);
|
@@ -258,19 +259,12 @@ dump_sec_nano(VALUE obj, time_t sec, long nsec, Out out) {
|
|
258
259
|
tzmin = (int)(tzsecs / 60) - (tzhour * 60);
|
259
260
|
}
|
260
261
|
if (!xml_time) {
|
261
|
-
len = sprintf(buf, "%04d/%02d/%02d %02d:%02d:%02d %c%02d%02d",
|
262
|
-
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
|
263
|
-
tm->tm_hour, tm->tm_min, tm->tm_sec, tzsign, tzhour, tzmin);
|
262
|
+
len = sprintf(buf, "%04d/%02d/%02d %02d:%02d:%02d %c%02d%02d", ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec, tzsign, tzhour, tzmin);
|
264
263
|
} else if (0 == out->opts->sec_prec) {
|
265
264
|
if (0 == tzsecs && rb_funcall2(obj, oj_utcq_id, 0, 0)) {
|
266
|
-
len = sprintf(buf, "%04d-%02d-%02dT%02d:%02d:%02dZ",
|
267
|
-
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
|
268
|
-
tm->tm_hour, tm->tm_min, tm->tm_sec);
|
265
|
+
len = sprintf(buf, "%04d-%02d-%02dT%02d:%02d:%02dZ", ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec);
|
269
266
|
} else {
|
270
|
-
len = sprintf(buf, "%04d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d",
|
271
|
-
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
|
272
|
-
tm->tm_hour, tm->tm_min, tm->tm_sec,
|
273
|
-
tzsign, tzhour, tzmin);
|
267
|
+
len = sprintf(buf, "%04d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d", ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec, tzsign, tzhour, tzmin);
|
274
268
|
}
|
275
269
|
} else if (0 == tzsecs && rb_funcall2(obj, oj_utcq_id, 0, 0)) {
|
276
270
|
char format[64] = "%04d-%02d-%02dT%02d:%02d:%02d.%09ldZ";
|
@@ -280,9 +274,7 @@ dump_sec_nano(VALUE obj, time_t sec, long nsec, Out out) {
|
|
280
274
|
format[32] = '0' + out->opts->sec_prec;
|
281
275
|
len -= 9 - out->opts->sec_prec;
|
282
276
|
}
|
283
|
-
len = sprintf(buf, format,
|
284
|
-
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
|
285
|
-
tm->tm_hour, tm->tm_min, tm->tm_sec, nsec);
|
277
|
+
len = sprintf(buf, format, ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec, nsec);
|
286
278
|
} else {
|
287
279
|
char format[64] = "%04d-%02d-%02dT%02d:%02d:%02d.%09ld%c%02d:%02d";
|
288
280
|
|
@@ -291,10 +283,7 @@ dump_sec_nano(VALUE obj, time_t sec, long nsec, Out out) {
|
|
291
283
|
format[32] = '0' + out->opts->sec_prec;
|
292
284
|
len -= 9 - out->opts->sec_prec;
|
293
285
|
}
|
294
|
-
len = sprintf(buf, format,
|
295
|
-
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
|
296
|
-
tm->tm_hour, tm->tm_min, tm->tm_sec, nsec,
|
297
|
-
tzsign, tzhour, tzmin);
|
286
|
+
len = sprintf(buf, format, ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec, nsec, tzsign, tzhour, tzmin);
|
298
287
|
}
|
299
288
|
oj_dump_cstr(buf, len, 0, 0, out);
|
300
289
|
}
|
@@ -323,7 +312,7 @@ dump_time(VALUE obj, int depth, Out out, bool as_ok) {
|
|
323
312
|
|
324
313
|
static void
|
325
314
|
dump_timewithzone(VALUE obj, int depth, Out out, bool as_ok) {
|
326
|
-
|
315
|
+
int64_t sec = NUM2LONG(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
327
316
|
long long nsec = 0;
|
328
317
|
|
329
318
|
if (rb_respond_to(obj, oj_tv_nsec_id)) {
|
data/ext/oj/util.c
ADDED
@@ -0,0 +1,136 @@
|
|
1
|
+
// Copyright (c) 2019, Peter Ohler, All rights reserved.
|
2
|
+
|
3
|
+
#include "util.h"
|
4
|
+
|
5
|
+
#include <stdbool.h>
|
6
|
+
#include <stdint.h>
|
7
|
+
#include <stdio.h>
|
8
|
+
#include <string.h>
|
9
|
+
#include <time.h>
|
10
|
+
|
11
|
+
#define SECS_PER_DAY 86400LL
|
12
|
+
#define SECS_PER_YEAR 31536000LL
|
13
|
+
#define SECS_PER_LEAP 31622400LL
|
14
|
+
#define SECS_PER_QUAD_YEAR (SECS_PER_YEAR * 3 + SECS_PER_LEAP)
|
15
|
+
#define SECS_PER_CENT (SECS_PER_QUAD_YEAR * 24 + SECS_PER_YEAR * 4)
|
16
|
+
#define SECS_PER_LEAP_CENT (SECS_PER_CENT + SECS_PER_DAY)
|
17
|
+
#define SECS_PER_QUAD_CENT (SECS_PER_CENT * 4 + SECS_PER_DAY)
|
18
|
+
|
19
|
+
static int64_t eom_secs[] = {
|
20
|
+
2678400, // January (31)
|
21
|
+
5097600, // February (28) 2419200 2505600
|
22
|
+
7776000, // March (31)
|
23
|
+
10368000, // April (30 2592000
|
24
|
+
13046400, // May (31)
|
25
|
+
15638400, // June (30)
|
26
|
+
18316800, // July (31)
|
27
|
+
20995200, // August (31)
|
28
|
+
23587200, // September (30)
|
29
|
+
26265600, // October (31)
|
30
|
+
28857600, // November (30)
|
31
|
+
31536000, // December (31)
|
32
|
+
};
|
33
|
+
|
34
|
+
static int64_t eom_leap_secs[] = {
|
35
|
+
2678400, // January (31)
|
36
|
+
5184000, // February (28) 2419200 2505600
|
37
|
+
7862400, // March (31)
|
38
|
+
10454400, // April (30 2592000
|
39
|
+
13132800, // May (31)
|
40
|
+
15724800, // June (30)
|
41
|
+
18403200, // July (31)
|
42
|
+
21081600, // August (31)
|
43
|
+
23673600, // September (30)
|
44
|
+
26352000, // October (31)
|
45
|
+
28944000, // November (30)
|
46
|
+
31622400, // December (31)
|
47
|
+
};
|
48
|
+
|
49
|
+
|
50
|
+
void
|
51
|
+
sec_as_time(int64_t secs, TimeInfo ti) {
|
52
|
+
int64_t qc = 0;
|
53
|
+
int64_t c = 0;
|
54
|
+
int64_t qy = 0;
|
55
|
+
int64_t y = 0;
|
56
|
+
bool leap = false;
|
57
|
+
int64_t *ms;
|
58
|
+
int m;
|
59
|
+
int shift = 0;
|
60
|
+
|
61
|
+
secs += 62167219200LL; // normalize to first day of the year 0
|
62
|
+
if (secs < 0) {
|
63
|
+
shift = -secs / SECS_PER_QUAD_CENT;
|
64
|
+
shift++;
|
65
|
+
secs += shift * SECS_PER_QUAD_CENT;
|
66
|
+
}
|
67
|
+
qc = secs / SECS_PER_QUAD_CENT;
|
68
|
+
secs = secs - qc * SECS_PER_QUAD_CENT;
|
69
|
+
if (secs < SECS_PER_LEAP) {
|
70
|
+
leap = true;
|
71
|
+
} else if (secs < SECS_PER_QUAD_YEAR) {
|
72
|
+
if (SECS_PER_LEAP <= secs) {
|
73
|
+
secs -= SECS_PER_LEAP;
|
74
|
+
y = secs / SECS_PER_YEAR;
|
75
|
+
secs = secs - y * SECS_PER_YEAR;
|
76
|
+
y++;
|
77
|
+
leap = true;
|
78
|
+
}
|
79
|
+
} else if (secs < SECS_PER_LEAP_CENT) { // first century in 400 years is a leap century (one extra day)
|
80
|
+
qy = secs / SECS_PER_QUAD_YEAR;
|
81
|
+
secs = secs - qy * SECS_PER_QUAD_YEAR;
|
82
|
+
if (secs < SECS_PER_LEAP) {
|
83
|
+
leap = true;
|
84
|
+
} else {
|
85
|
+
secs -= SECS_PER_LEAP;
|
86
|
+
y = secs / SECS_PER_YEAR;
|
87
|
+
secs = secs - y * SECS_PER_YEAR;
|
88
|
+
y++;
|
89
|
+
}
|
90
|
+
} else {
|
91
|
+
secs -= SECS_PER_LEAP_CENT;
|
92
|
+
c = secs / SECS_PER_CENT;
|
93
|
+
secs = secs - c * SECS_PER_CENT;
|
94
|
+
c++;
|
95
|
+
if (secs < SECS_PER_YEAR * 4) {
|
96
|
+
y = secs / SECS_PER_YEAR;
|
97
|
+
secs = secs - y * SECS_PER_YEAR;
|
98
|
+
} else {
|
99
|
+
secs -= SECS_PER_YEAR * 4;
|
100
|
+
qy = secs / SECS_PER_QUAD_YEAR;
|
101
|
+
secs = secs - qy * SECS_PER_QUAD_YEAR;
|
102
|
+
qy++;
|
103
|
+
if (secs < SECS_PER_LEAP) {
|
104
|
+
leap = true;
|
105
|
+
} else {
|
106
|
+
secs -= SECS_PER_LEAP;
|
107
|
+
y = secs / SECS_PER_YEAR;
|
108
|
+
secs = secs - y * SECS_PER_YEAR;
|
109
|
+
y++;
|
110
|
+
}
|
111
|
+
}
|
112
|
+
}
|
113
|
+
ti->year = (qc - shift) * 400 + c * 100 + qy * 4 + y;
|
114
|
+
if (leap) {
|
115
|
+
ms = eom_leap_secs;
|
116
|
+
} else {
|
117
|
+
ms = eom_secs;
|
118
|
+
}
|
119
|
+
for (m = 1; m <= 12; m++, ms++) {
|
120
|
+
if (secs < *ms) {
|
121
|
+
if (1 < m) {
|
122
|
+
secs -= *(ms - 1);
|
123
|
+
}
|
124
|
+
ti->mon = m;
|
125
|
+
break;
|
126
|
+
}
|
127
|
+
}
|
128
|
+
ti->day = secs / 86400LL;
|
129
|
+
secs = secs - (int64_t)ti->day * 86400LL;
|
130
|
+
ti->day++;
|
131
|
+
ti->hour = secs / 3600LL;
|
132
|
+
secs = secs - (int64_t)ti->hour * 3600LL;
|
133
|
+
ti->min = secs / 60LL;
|
134
|
+
secs = secs - (int64_t)ti->min * 60LL;
|
135
|
+
ti->sec = secs;
|
136
|
+
}
|
data/ext/oj/util.h
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
// Copyright (c) 2019, Peter Ohler, All rights reserved.
|
2
|
+
|
3
|
+
#ifndef OJ_UTIL_H
|
4
|
+
#define OJ_UTIL_H
|
5
|
+
|
6
|
+
#include <stdint.h>
|
7
|
+
|
8
|
+
typedef struct _timeInfo {
|
9
|
+
int sec;
|
10
|
+
int min;
|
11
|
+
int hour;
|
12
|
+
int day;
|
13
|
+
int mon;
|
14
|
+
int year;
|
15
|
+
} *TimeInfo;
|
16
|
+
|
17
|
+
extern void sec_as_time(int64_t secs, TimeInfo ti);
|
18
|
+
|
19
|
+
#endif /* OJ_UTIL_H */
|
data/ext/oj/val_stack.c
CHANGED
@@ -31,6 +31,7 @@
|
|
31
31
|
#include <string.h>
|
32
32
|
|
33
33
|
#include "oj.h"
|
34
|
+
#include "odd.h"
|
34
35
|
#include "val_stack.h"
|
35
36
|
|
36
37
|
static void
|
@@ -54,6 +55,16 @@ mark(void *ptr) {
|
|
54
55
|
if (Qnil != v->key_val && Qundef != v->key_val) {
|
55
56
|
rb_gc_mark(v->key_val);
|
56
57
|
}
|
58
|
+
if (NULL != v->odd_args) {
|
59
|
+
VALUE *a;
|
60
|
+
int i;
|
61
|
+
|
62
|
+
for (i = v->odd_args->odd->attr_cnt, a = v->odd_args->args; 0 < i; i--, a++) {
|
63
|
+
if (Qnil != *a) {
|
64
|
+
rb_gc_mark(*a);
|
65
|
+
}
|
66
|
+
}
|
67
|
+
}
|
57
68
|
}
|
58
69
|
#if HAVE_LIBPTHREAD
|
59
70
|
pthread_mutex_unlock(&stack->mutex);
|
@@ -77,12 +88,15 @@ oj_stack_init(ValStack stack) {
|
|
77
88
|
stack->end = stack->base + sizeof(stack->base) / sizeof(struct _val);
|
78
89
|
stack->tail = stack->head;
|
79
90
|
stack->head->val = Qundef;
|
80
|
-
stack->head->key =
|
91
|
+
stack->head->key = NULL;
|
81
92
|
stack->head->key_val = Qundef;
|
82
|
-
stack->head->classname =
|
93
|
+
stack->head->classname = NULL;
|
94
|
+
stack->head->odd_args = NULL;
|
95
|
+
stack->head->clas = Qundef;
|
83
96
|
stack->head->klen = 0;
|
84
97
|
stack->head->clen = 0;
|
85
98
|
stack->head->next = NEXT_NONE;
|
99
|
+
|
86
100
|
return Data_Wrap_Struct(oj_cstack_class, mark, 0, stack);
|
87
101
|
}
|
88
102
|
|
data/ext/oj/val_stack.h
CHANGED
@@ -57,13 +57,9 @@ typedef struct _val {
|
|
57
57
|
const char *key;
|
58
58
|
char karray[32];
|
59
59
|
volatile VALUE key_val;
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
VALUE clas;
|
64
|
-
};
|
65
|
-
OddArgs odd_args;
|
66
|
-
};
|
60
|
+
const char *classname;
|
61
|
+
VALUE clas;
|
62
|
+
OddArgs odd_args;
|
67
63
|
uint16_t klen;
|
68
64
|
uint16_t clen;
|
69
65
|
char next; // ValNext
|
@@ -132,6 +128,7 @@ stack_push(ValStack stack, VALUE val, ValNext next) {
|
|
132
128
|
stack->tail->next = next;
|
133
129
|
stack->tail->classname = NULL;
|
134
130
|
stack->tail->clas = Qundef;
|
131
|
+
stack->tail->odd_args = NULL;
|
135
132
|
stack->tail->key = 0;
|
136
133
|
stack->tail->key_val = Qundef;
|
137
134
|
stack->tail->clen = 0;
|
data/ext/oj/wab.c
CHANGED
@@ -15,6 +15,7 @@
|
|
15
15
|
#include "encode.h"
|
16
16
|
#include "dump.h"
|
17
17
|
#include "trace.h"
|
18
|
+
#include "util.h"
|
18
19
|
|
19
20
|
// Workaround in case INFINITY is not defined in math.h or if the OS is CentOS
|
20
21
|
#define OJ_INFINITY (1.0/0.0)
|
@@ -193,11 +194,11 @@ dump_hash(VALUE obj, int depth, Out out, bool as_ok) {
|
|
193
194
|
|
194
195
|
static void
|
195
196
|
dump_time(VALUE obj, Out out) {
|
196
|
-
char
|
197
|
-
struct
|
198
|
-
int
|
199
|
-
time_t
|
200
|
-
long long
|
197
|
+
char buf[64];
|
198
|
+
struct _timeInfo ti;
|
199
|
+
int len;
|
200
|
+
time_t sec;
|
201
|
+
long long nsec;
|
201
202
|
|
202
203
|
#ifdef HAVE_RB_TIME_TIMESPEC
|
203
204
|
if (16 <= sizeof(struct timespec)) {
|
@@ -216,11 +217,9 @@ dump_time(VALUE obj, Out out) {
|
|
216
217
|
|
217
218
|
assure_size(out, 36);
|
218
219
|
// 2012-01-05T23:58:07.123456000Z
|
219
|
-
|
220
|
+
sec_as_time(sec, &ti);
|
220
221
|
|
221
|
-
len = sprintf(buf, "%04d-%02d-%02dT%02d:%02d:%02d.%09ldZ",
|
222
|
-
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
|
223
|
-
tm->tm_hour, tm->tm_min, tm->tm_sec, (long)nsec);
|
222
|
+
len = sprintf(buf, "%04d-%02d-%02dT%02d:%02d:%02d.%09ldZ", ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec, (long)nsec);
|
224
223
|
oj_dump_cstr(buf, len, 0, 0, out);
|
225
224
|
}
|
226
225
|
|
data/lib/oj/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oj
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.7.
|
4
|
+
version: 3.7.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Ohler
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-01-
|
11
|
+
date: 2019-01-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake-compiler
|
@@ -139,6 +139,8 @@ files:
|
|
139
139
|
- ext/oj/string_writer.c
|
140
140
|
- ext/oj/trace.c
|
141
141
|
- ext/oj/trace.h
|
142
|
+
- ext/oj/util.c
|
143
|
+
- ext/oj/util.h
|
142
144
|
- ext/oj/val_stack.c
|
143
145
|
- ext/oj/val_stack.h
|
144
146
|
- ext/oj/wab.c
|
@@ -271,8 +273,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
271
273
|
- !ruby/object:Gem::Version
|
272
274
|
version: '0'
|
273
275
|
requirements: []
|
274
|
-
|
275
|
-
rubygems_version: 2.7.6
|
276
|
+
rubygems_version: 3.0.1
|
276
277
|
signing_key:
|
277
278
|
specification_version: 4
|
278
279
|
summary: A fast JSON parser and serializer.
|