oj 3.7.4 → 3.11.2

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.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +12 -4
  3. data/ext/oj/buf.h +6 -34
  4. data/ext/oj/cache8.c +3 -3
  5. data/ext/oj/cache8.h +5 -33
  6. data/ext/oj/circarray.c +5 -9
  7. data/ext/oj/circarray.h +5 -8
  8. data/ext/oj/code.c +3 -6
  9. data/ext/oj/code.h +7 -10
  10. data/ext/oj/compat.c +11 -14
  11. data/ext/oj/custom.c +108 -75
  12. data/ext/oj/dump.c +132 -92
  13. data/ext/oj/dump.h +6 -7
  14. data/ext/oj/dump_compat.c +37 -34
  15. data/ext/oj/dump_leaf.c +3 -6
  16. data/ext/oj/dump_object.c +23 -17
  17. data/ext/oj/dump_strict.c +7 -9
  18. data/ext/oj/encode.h +6 -32
  19. data/ext/oj/err.c +2 -5
  20. data/ext/oj/err.h +6 -34
  21. data/ext/oj/extconf.rb +6 -0
  22. data/ext/oj/fast.c +39 -56
  23. data/ext/oj/hash.c +11 -39
  24. data/ext/oj/hash.h +5 -33
  25. data/ext/oj/hash_test.c +3 -31
  26. data/ext/oj/mimic_json.c +65 -44
  27. data/ext/oj/object.c +38 -69
  28. data/ext/oj/odd.c +18 -17
  29. data/ext/oj/odd.h +6 -9
  30. data/ext/oj/oj.c +139 -93
  31. data/ext/oj/oj.h +43 -35
  32. data/ext/oj/parse.c +164 -60
  33. data/ext/oj/parse.h +30 -31
  34. data/ext/oj/rails.c +119 -83
  35. data/ext/oj/rails.h +4 -7
  36. data/ext/oj/reader.c +5 -8
  37. data/ext/oj/reader.h +7 -10
  38. data/ext/oj/resolve.c +4 -7
  39. data/ext/oj/resolve.h +4 -7
  40. data/ext/oj/rxclass.c +8 -11
  41. data/ext/oj/rxclass.h +8 -11
  42. data/ext/oj/saj.c +9 -12
  43. data/ext/oj/scp.c +4 -7
  44. data/ext/oj/sparse.c +67 -33
  45. data/ext/oj/stream_writer.c +16 -15
  46. data/ext/oj/strict.c +9 -12
  47. data/ext/oj/string_writer.c +27 -8
  48. data/ext/oj/trace.c +5 -8
  49. data/ext/oj/trace.h +9 -12
  50. data/ext/oj/util.c +136 -0
  51. data/ext/oj/util.h +19 -0
  52. data/ext/oj/val_stack.c +28 -36
  53. data/ext/oj/val_stack.h +19 -50
  54. data/ext/oj/wab.c +29 -29
  55. data/lib/oj.rb +0 -8
  56. data/lib/oj/json.rb +1 -1
  57. data/lib/oj/mimic.rb +46 -2
  58. data/lib/oj/version.rb +2 -2
  59. data/pages/Modes.md +47 -45
  60. data/pages/Options.md +43 -10
  61. data/pages/Rails.md +60 -21
  62. data/pages/Security.md +1 -1
  63. data/test/activesupport5/abstract_unit.rb +45 -0
  64. data/test/activesupport5/decoding_test.rb +68 -60
  65. data/test/activesupport5/encoding_test.rb +111 -96
  66. data/test/activesupport5/encoding_test_cases.rb +33 -25
  67. data/test/activesupport5/test_helper.rb +43 -21
  68. data/test/activesupport5/time_zone_test_helpers.rb +18 -3
  69. data/test/activesupport6/abstract_unit.rb +44 -0
  70. data/test/activesupport6/decoding_test.rb +133 -0
  71. data/test/activesupport6/encoding_test.rb +507 -0
  72. data/test/activesupport6/encoding_test_cases.rb +98 -0
  73. data/test/activesupport6/test_common.rb +17 -0
  74. data/test/activesupport6/test_helper.rb +163 -0
  75. data/test/activesupport6/time_zone_test_helpers.rb +39 -0
  76. data/test/bar.rb +24 -6
  77. data/test/baz.rb +16 -0
  78. data/test/foo.rb +26 -57
  79. data/test/helper.rb +10 -0
  80. data/test/json_gem/json_common_interface_test.rb +8 -3
  81. data/test/json_gem/json_generator_test.rb +15 -3
  82. data/test/json_gem/test_helper.rb +8 -0
  83. data/test/prec.rb +23 -0
  84. data/test/sample_json.rb +1 -1
  85. data/test/test_compat.rb +21 -10
  86. data/test/test_custom.rb +135 -8
  87. data/test/test_integer_range.rb +1 -2
  88. data/test/test_object.rb +35 -2
  89. data/test/test_rails.rb +35 -0
  90. data/test/test_strict.rb +24 -1
  91. data/test/test_various.rb +52 -63
  92. data/test/test_writer.rb +19 -2
  93. data/test/tests.rb +1 -0
  94. data/test/zoo.rb +13 -0
  95. metadata +100 -75
@@ -1,13 +1,10 @@
1
- /* stream_writer.c
2
- * Copyright (c) 2012, 2017, Peter Ohler
3
- * All rights reserved.
4
- */
1
+ // Copyright (c) 2012, 2017 Peter Ohler. All rights reserved.
5
2
 
6
3
  #include <errno.h>
7
4
 
8
5
  #include <ruby.h>
9
6
 
10
- #include "oj.h"
7
+ #include "encode.h"
11
8
 
12
9
  extern VALUE Oj;
13
10
 
@@ -36,11 +33,17 @@ stream_writer_write(StreamWriter sw) {
36
33
 
37
34
  switch (sw->type) {
38
35
  case STRING_IO:
39
- rb_funcall(sw->stream, oj_write_id, 1, rb_str_new(sw->sw.out.buf, size));
40
- break;
41
- case STREAM_IO:
42
- rb_funcall(sw->stream, oj_write_id, 1, rb_str_new(sw->sw.out.buf, size));
36
+ case STREAM_IO: {
37
+ volatile VALUE rs = rb_str_new(sw->sw.out.buf, size);
38
+
39
+ // Oddly enough, when pushing ASCII characters with UTF-8 encoding or
40
+ // even ASCII-8BIT does not change the output encoding. Pushing any
41
+ // non-ASCII no matter what the encoding changes the output encoding
42
+ // to ASCII-8BIT if it the string is not forced to UTF-8 here.
43
+ rs = oj_encode(rs);
44
+ rb_funcall(sw->stream, oj_write_id, 1, rs);
43
45
  break;
46
+ }
44
47
  case FILE_IO:
45
48
  if (size != write(sw->fd, sw->sw.out.buf, size)) {
46
49
  rb_raise(rb_eIOError, "Write failed. [_%d_:%s]\n", errno, strerror(errno));
@@ -80,7 +83,7 @@ stream_writer_new(int argc, VALUE *argv, VALUE self) {
80
83
  #if !IS_WINDOWS
81
84
  VALUE s;
82
85
  #endif
83
-
86
+
84
87
  if (oj_stringio_class == clas) {
85
88
  type = STRING_IO;
86
89
  #if !IS_WINDOWS
@@ -94,14 +97,14 @@ stream_writer_new(int argc, VALUE *argv, VALUE self) {
94
97
  } else {
95
98
  rb_raise(rb_eArgError, "expected an IO Object.");
96
99
  }
97
- sw = ALLOC(struct _StreamWriter);
100
+ sw = ALLOC(struct _streamWriter);
98
101
  if (2 == argc && T_HASH == rb_type(argv[1])) {
99
102
  volatile VALUE v;
100
103
  int buf_size = 0;
101
104
 
102
105
  if (Qundef == buffer_size_sym) {
103
106
  buffer_size_sym = ID2SYM(rb_intern("buffer_size")); rb_gc_register_address(&buffer_size_sym);
104
-
107
+
105
108
  }
106
109
  if (Qnil != (v = rb_hash_lookup(argv[1], buffer_size_sym))) {
107
110
  #ifdef RUBY_INTEGER_UNIFICATION
@@ -334,7 +337,7 @@ stream_writer_flush(VALUE self) {
334
337
  }
335
338
 
336
339
  /* Document-class: Oj::StreamWriter
337
- *
340
+ *
338
341
  * Supports building a JSON document one element at a time. Build the IO stream
339
342
  * document by pushing values into the document. Pushing an array or an object
340
343
  * will create that element in the JSON document and subsequent pushes will add
@@ -353,5 +356,3 @@ oj_stream_writer_init() {
353
356
  rb_define_method(oj_stream_writer_class, "pop_all", stream_writer_pop_all, 0);
354
357
  rb_define_method(oj_stream_writer_class, "flush", stream_writer_flush, 0);
355
358
  }
356
-
357
-
data/ext/oj/strict.c CHANGED
@@ -1,7 +1,4 @@
1
- /* strict.c
2
- * Copyright (c) 2012, Peter Ohler
3
- * All rights reserved.
4
- */
1
+ // Copyright (c) 2012 Peter Ohler. All rights reserved.
5
2
 
6
3
  #include <stdlib.h>
7
4
  #include <stdio.h>
@@ -15,21 +12,21 @@
15
12
  #include "trace.h"
16
13
 
17
14
  static void
18
- hash_end(struct _ParseInfo *pi) {
15
+ hash_end(ParseInfo pi) {
19
16
  if (Yes == pi->options.trace) {
20
17
  oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
21
18
  }
22
19
  }
23
20
 
24
21
  static void
25
- array_end(struct _ParseInfo *pi) {
22
+ array_end(ParseInfo pi) {
26
23
  if (Yes == pi->options.trace) {
27
24
  oj_trace_parse_array_end(pi, __FILE__, __LINE__);
28
25
  }
29
26
  }
30
27
 
31
28
  static VALUE
32
- noop_hash_key(struct _ParseInfo *pi, const char *key, size_t klen) {
29
+ noop_hash_key(ParseInfo pi, const char *key, size_t klen) {
33
30
  return Qundef;
34
31
  }
35
32
 
@@ -100,9 +97,9 @@ hash_set_cstr(ParseInfo pi, Val parent, const char *str, size_t len, const char
100
97
  }
101
98
 
102
99
  static void
103
- hash_set_num(struct _ParseInfo *pi, Val parent, NumInfo ni) {
100
+ hash_set_num(ParseInfo pi, Val parent, NumInfo ni) {
104
101
  volatile VALUE v;
105
-
102
+
106
103
  if (ni->infinity || ni->nan) {
107
104
  oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
108
105
  }
@@ -143,7 +140,7 @@ array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
143
140
  static void
144
141
  array_append_num(ParseInfo pi, NumInfo ni) {
145
142
  volatile VALUE v;
146
-
143
+
147
144
  if (ni->infinity || ni->nan) {
148
145
  oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
149
146
  }
@@ -183,7 +180,7 @@ oj_set_strict_callbacks(ParseInfo pi) {
183
180
 
184
181
  VALUE
185
182
  oj_strict_parse(int argc, VALUE *argv, VALUE self) {
186
- struct _ParseInfo pi;
183
+ struct _parseInfo pi;
187
184
 
188
185
  parse_info_init(&pi);
189
186
  pi.options = oj_default_options;
@@ -200,7 +197,7 @@ oj_strict_parse(int argc, VALUE *argv, VALUE self) {
200
197
 
201
198
  VALUE
202
199
  oj_strict_parse_cstr(int argc, VALUE *argv, char *json, size_t len) {
203
- struct _ParseInfo pi;
200
+ struct _parseInfo pi;
204
201
 
205
202
  parse_info_init(&pi);
206
203
  pi.options = oj_default_options;
@@ -1,13 +1,12 @@
1
- /* strwriter.c
2
- * Copyright (c) 2012, 2017, Peter Ohler
3
- * All rights reserved.
4
- */
1
+ // Copyright (c) 2012, 2017 Peter Ohler. All rights reserved.
5
2
 
6
3
  #include "dump.h"
7
4
  #include "encode.h"
8
5
 
9
6
  extern VALUE Oj;
10
7
 
8
+ bool string_writer_optimized = false;
9
+
11
10
  static void
12
11
  key_check(StrWriter sw, const char *key) {
13
12
  DumpType type = sw->types[sw->depth];
@@ -152,7 +151,7 @@ oj_str_writer_push_array(StrWriter sw, const char *key) {
152
151
  void
153
152
  oj_str_writer_push_value(StrWriter sw, VALUE val, const char *key) {
154
153
  Out out = &sw->out;
155
-
154
+
156
155
  if (sw->keyWritten) {
157
156
  sw->keyWritten = 0;
158
157
  } else {
@@ -272,8 +271,8 @@ str_writer_free(void *ptr) {
272
271
  */
273
272
  static VALUE
274
273
  str_writer_new(int argc, VALUE *argv, VALUE self) {
275
- StrWriter sw = ALLOC(struct _StrWriter);
276
-
274
+ StrWriter sw = ALLOC(struct _strWriter);
275
+
277
276
  oj_str_writer_init(sw, 0);
278
277
  if (1 == argc) {
279
278
  oj_parse_options(argv[0], &sw->opts);
@@ -487,8 +486,26 @@ str_writer_to_s(VALUE self) {
487
486
  return oj_encode(rstr);
488
487
  }
489
488
 
489
+ /* Document-method: as_json
490
+ * call-seq: as_json()
491
+ *
492
+ * Returns the contents of the writer as a JSON element. If called from inside
493
+ * an array or hash by Oj the raw buffer will be used othersize a more
494
+ * inefficient parse of the contents and a return of the result is
495
+ * completed. The parse uses the trict mode.
496
+ *
497
+ * *return* [_Hash_|_Array_|_String_|_Integer_|_Float_|_True_|_False_|_nil|)
498
+ */
499
+ static VALUE
500
+ str_writer_as_json(VALUE self) {
501
+ if (string_writer_optimized) {
502
+ return self;
503
+ }
504
+ return rb_hash_new();
505
+ }
506
+
490
507
  /* Document-class: Oj::StringWriter
491
- *
508
+ *
492
509
  * Supports building a JSON document one element at a time. Build the document
493
510
  * by pushing values into the document. Pushing an array or an object will
494
511
  * create that element in the JSON document and subsequent pushes will add the
@@ -509,4 +526,6 @@ oj_string_writer_init() {
509
526
  rb_define_method(oj_string_writer_class, "pop_all", str_writer_pop_all, 0);
510
527
  rb_define_method(oj_string_writer_class, "reset", str_writer_reset, 0);
511
528
  rb_define_method(oj_string_writer_class, "to_s", str_writer_to_s, 0);
529
+ rb_define_method(oj_string_writer_class, "raw_json", str_writer_to_s, 0);
530
+ rb_define_method(oj_string_writer_class, "as_json", str_writer_as_json, 0);
512
531
  }
data/ext/oj/trace.c CHANGED
@@ -1,7 +1,4 @@
1
- /* trace.h
2
- * Copyright (c) 2018, Peter Ohler
3
- * All rights reserved.
4
- */
1
+ // Copyright (c) 2018 Peter Ohler. All rights reserved.
5
2
 
6
3
  #include "parse.h"
7
4
  #include "trace.h"
@@ -37,7 +34,7 @@ oj_trace_parse_call(const char *func, ParseInfo pi, const char *file, int line,
37
34
  char fmt[64];
38
35
  char indent[MAX_INDENT];
39
36
  int depth = (int)(stack_size(&pi->stack) * 2);
40
-
37
+
41
38
  fill_indent(indent, depth);
42
39
  sprintf(fmt, "#0:%%13s:%%3d:Oj:-:%%%ds %%s %%s\n", depth);
43
40
  printf(fmt, file, line, indent, func, rb_obj_classname(obj));
@@ -48,7 +45,7 @@ oj_trace_parse_in(const char *func, ParseInfo pi, const char *file, int line) {
48
45
  char fmt[64];
49
46
  char indent[MAX_INDENT];
50
47
  int depth = (int)(stack_size(&pi->stack) * 2);
51
-
48
+
52
49
  fill_indent(indent, depth);
53
50
  sprintf(fmt, "#0:%%13s:%%3d:Oj:}:%%%ds %%s\n", depth);
54
51
  printf(fmt, file, line, indent, func);
@@ -61,7 +58,7 @@ oj_trace_parse_hash_end(ParseInfo pi, const char *file, int line) {
61
58
  int depth = (int)(stack_size(&pi->stack) * 2 - 2);
62
59
  Val v = stack_peek(&pi->stack);
63
60
  VALUE obj = v->val;
64
-
61
+
65
62
  fill_indent(indent, depth);
66
63
  sprintf(fmt, "#0:%%13s:%%3d:Oj:{:%%%ds hash_end %%s\n", depth);
67
64
  printf(fmt, file, line, indent, rb_obj_classname(obj));
@@ -72,7 +69,7 @@ oj_trace_parse_array_end(ParseInfo pi, const char *file, int line) {
72
69
  char fmt[64];
73
70
  char indent[MAX_INDENT];
74
71
  int depth = (int)(stack_size(&pi->stack) * 2);
75
-
72
+
76
73
  fill_indent(indent, depth);
77
74
  sprintf(fmt, "#0:%%13s:%%3d:Oj:{:%%%ds array_ned\n", depth);
78
75
  printf(fmt, file, line, indent);
data/ext/oj/trace.h CHANGED
@@ -1,10 +1,7 @@
1
- /* trace.h
2
- * Copyright (c) 2018, Peter Ohler
3
- * All rights reserved.
4
- */
1
+ // Copyright (c) 2018 Peter Ohler. All rights reserved.
5
2
 
6
- #ifndef __OJ_TRACE_H__
7
- #define __OJ_TRACE_H__
3
+ #ifndef OJ_TRACE_H
4
+ #define OJ_TRACE_H
8
5
 
9
6
  #include <stdbool.h>
10
7
  #include <ruby.h>
@@ -17,12 +14,12 @@ typedef enum {
17
14
  TraceRubyOut = '<',
18
15
  } TraceWhere;
19
16
 
20
- struct _ParseInfo;
17
+ struct _parseInfo;
21
18
 
22
19
  extern void oj_trace(const char *func, VALUE obj, const char *file, int line, int depth, TraceWhere where);
23
- extern void oj_trace_parse_in(const char *func, struct _ParseInfo *pi, const char *file, int line);
24
- extern void oj_trace_parse_call(const char *func, struct _ParseInfo *pi, const char *file, int line, VALUE obj);
25
- extern void oj_trace_parse_hash_end(struct _ParseInfo *pi, const char *file, int line);
26
- extern void oj_trace_parse_array_end(struct _ParseInfo *pi, const char *file, int line);
20
+ extern void oj_trace_parse_in(const char *func, struct _parseInfo *pi, const char *file, int line);
21
+ extern void oj_trace_parse_call(const char *func, struct _parseInfo *pi, const char *file, int line, VALUE obj);
22
+ extern void oj_trace_parse_hash_end(struct _parseInfo *pi, const char *file, int line);
23
+ extern void oj_trace_parse_array_end(struct _parseInfo *pi, const char *file, int line);
27
24
 
28
- #endif /* __OJ_TRACE_H__ */
25
+ #endif /* OJ_TRACE_H */
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 = false;
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 = (int)((qc - (int64_t)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 = (int)(secs / 86400LL);
129
+ secs = secs - (int64_t)ti->day * 86400LL;
130
+ ti->day++;
131
+ ti->hour = (int)(secs / 3600LL);
132
+ secs = secs - (int64_t)ti->hour * 3600LL;
133
+ ti->min = (int)(secs / 60LL);
134
+ secs = secs - (int64_t)ti->min * 60LL;
135
+ ti->sec = (int)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 */