oj 3.7.7 → 3.7.8
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/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.
|