sleepy_penguin 3.5.2
[sleepy_penguin.git] / ext / sleepy_penguin / value2timespec.h
blobb8f61678bd3c903ecea66886103fcea5698f72fb
1 #ifndef VALUE2TIMESPEC_H
2 #define VALUE2TIMESPEC_H
4 #include <ruby.h>
5 #include <math.h>
6 #include <time.h>
8 #ifndef NUM2TIMET
9 # define NUM2TIMET(n) NUM2LONG(n)
10 #endif
12 #ifndef RFLOAT_VALUE
13 # define RFLOAT_VALUE(v) (RFLOAT(v)->value)
14 #endif
16 static struct timespec *value2timespec(struct timespec *ts, VALUE num)
18 switch (TYPE(num)) {
19 case T_FIXNUM:
20 case T_BIGNUM:
21 ts->tv_sec = NUM2TIMET(num);
22 ts->tv_nsec = 0;
23 return ts;
24 case T_FLOAT: {
25 double orig = RFLOAT_VALUE(num);
26 double f, d;
28 d = modf(orig, &f);
29 if (d >= 0) {
30 ts->tv_nsec = (long)(d * 1e9 + 0.5);
31 } else {
32 ts->tv_nsec = (long)(-d * 1e9 + 0.5);
33 if (ts->tv_nsec > 0) {
34 ts->tv_nsec = (long)1e9 - ts->tv_nsec;
35 f -= 1;
38 ts->tv_sec = (time_t)f;
39 if (f != ts->tv_sec)
40 rb_raise(rb_eRangeError, "%f out of range", orig);
41 return ts;
44 VALUE tmp = rb_inspect(num);
45 const char *str = StringValueCStr(tmp);
46 rb_raise(rb_eTypeError, "can't convert %s into timespec", str);
48 rb_bug("rb_raise() failed, timespec failed");
49 return NULL;
52 #ifndef TIMET2NUM
53 # define TIMET2NUM(n) LONG2NUM(n)
54 #endif
56 static inline VALUE timespec2num(struct timespec *ts)
58 if (ts->tv_nsec == 0)
59 return TIMET2NUM(ts->tv_sec);
61 return rb_float_new(ts->tv_sec + ((double)ts->tv_nsec / 1e9));
64 #endif /* VALUE2TIMESPEC_H */