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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 389ece68dade91713fa132445f6b5d7cefdef5b6e7787a8b66f530c13173271c
4
- data.tar.gz: 49d899629ebbb41cb5b545400262f1644b93140c62b57f7f8c7ef98200ad2bb9
3
+ metadata.gz: 5008cd86952b184d31350d5e84256ca433e3dafe672c04400cd8d74bbc6190f4
4
+ data.tar.gz: 620b94ba6107477d17eda4d2f3558f1aa98d3c6635bdbb16443ba2b5868aeb57
5
5
  SHA512:
6
- metadata.gz: 15c6bd0b3324687ef248e2f67270bab76b1c70da8e92b54dc474082ae717d601142a745a7e365b3ffdf82c1b6fbb12d72cdb7db3cdefb34a50b3eaf28c941786
7
- data.tar.gz: 28fa1bb71e89c195ccb840d6c4b639ffc5c2244eba48aa69aab07cc76757b954ddffbe83801eb6624745ab21c73e5493c4858cbcbfa630f6a3df2a5a2d3899b8
6
+ metadata.gz: c1641f5af216aab8948c70c5c0e75f6f9fc6db9de5eca5cafad65b7fc6b877cded31bbf9f5b0fdb438217bfeae7c04cb880ec1b560771e0b341a0f1292f3c1e3
7
+ data.tar.gz: 1e3a1f8ee9b47fb8004cc53992ae68e5cceb055a53daecc73771ebccf3d3edcefeaac70e58f740279482e49eca89f32d38866a3412d67efdb9738f4e80c8c2e2
@@ -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
- time_t t = (time_t)(ni->i + ni->exp);
1062
- struct tm *st = gmtime(&t);
1063
- VALUE args[8];
1064
-
1065
- args[0] = LONG2NUM(1900 + st->tm_year);
1066
- args[1] = LONG2NUM(1 + st->tm_mon);
1067
- args[2] = LONG2NUM(st->tm_mday);
1068
- args[3] = LONG2NUM(st->tm_hour);
1069
- args[4] = LONG2NUM(st->tm_min);
1070
- args[5] = rb_float_new((double)st->tm_sec + ((double)nsec + 0.5) / 1000000000.0);
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 {
@@ -3,22 +3,19 @@
3
3
  * All rights reserved.
4
4
  */
5
5
 
6
- #include <stdlib.h>
7
6
  #include <errno.h>
8
- #if !IS_WINDOWS
9
- #include <sys/time.h>
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 buf[64];
497
- struct tm *tm;
498
- long one = 1000000000;
499
- time_t sec;
500
- long long nsec;
501
- long tzsecs = NUM2LONG(rb_funcall2(obj, oj_utc_offset_id, 0, 0));
502
- int tzhour, tzmin;
503
- char tzsign = '+';
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
- tm = gmtime(&sec);
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
  }
@@ -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
  }
@@ -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
- time_t t = (time_t)(ni->i + ni->exp);
295
- struct tm *st = gmtime(&t);
296
- VALUE args[8];
297
-
298
- // Windows does not support dates before 1970 so ignore
299
- // the zone and do the best we can.
300
- if (NULL == st) {
301
- parent->val = rb_time_nano_new(ni->i, (long)nsec);
302
- } else {
303
- args[0] = LONG2NUM((long)(1900 + st->tm_year));
304
- args[1] = LONG2NUM(1 + st->tm_mon);
305
- args[2] = LONG2NUM(st->tm_mday);
306
- args[3] = LONG2NUM(st->tm_hour);
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 = 0; // make sure it is 0 in case not odd
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 (0 == parent->odd_args) {
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 = 0; // make sure it is 0 in case not odd
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 (0 == parent->odd_args) {
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 = 0; // make sure it is 0 in case not odd
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 (0 == parent->odd_args) {
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 (0 != parent->odd_args) {
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 = 0;
658
+ parent->odd_args = NULL;
662
659
  }
663
660
  if (Yes == pi->options.trace) {
664
661
  oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
@@ -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 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));
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
 
@@ -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, time_t sec, long nsec, Out out) {
225
+ dump_sec_nano(VALUE obj, int64_t sec, long nsec, Out out) {
225
226
  char buf[64];
226
- struct tm *tm;
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
- tm = gmtime(&sec);
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
- time_t sec = NUM2LONG(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
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)) {
@@ -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
+ }
@@ -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 */
@@ -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 = 0;
91
+ stack->head->key = NULL;
81
92
  stack->head->key_val = Qundef;
82
- stack->head->classname = 0;
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
 
@@ -57,13 +57,9 @@ typedef struct _val {
57
57
  const char *key;
58
58
  char karray[32];
59
59
  volatile VALUE key_val;
60
- union {
61
- struct {
62
- const char *classname;
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;
@@ -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 buf[64];
197
- struct tm *tm;
198
- int len;
199
- time_t sec;
200
- long long nsec;
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
- tm = gmtime(&sec);
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
 
@@ -1,5 +1,5 @@
1
1
 
2
2
  module Oj
3
3
  # Current version of the module.
4
- VERSION = '3.7.7'
4
+ VERSION = '3.7.8'
5
5
  end
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.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-15 00:00:00.000000000 Z
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
- rubyforge_project:
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.