summaryrefslogtreecommitdiffhomepage
path: root/mrbgems/mruby-time
diff options
context:
space:
mode:
Diffstat (limited to 'mrbgems/mruby-time')
-rw-r--r--mrbgems/mruby-time/src/time.c109
1 files changed, 69 insertions, 40 deletions
diff --git a/mrbgems/mruby-time/src/time.c b/mrbgems/mruby-time/src/time.c
index 19ce32832..43d87e5ff 100644
--- a/mrbgems/mruby-time/src/time.c
+++ b/mrbgems/mruby-time/src/time.c
@@ -183,7 +183,7 @@ static const struct mrb_data_type mrb_time_type = { "Time", mrb_free };
/** Updates the datetime of a mrb_time based on it's timezone and
seconds setting. Returns self on success, NULL of failure. */
static struct mrb_time*
-mrb_time_update_datetime(struct mrb_time *self)
+time_update_datetime(mrb_state *mrb, struct mrb_time *self)
{
struct tm *aid;
@@ -193,7 +193,11 @@ mrb_time_update_datetime(struct mrb_time *self)
else {
aid = localtime_r(&self->sec, &self->datetime);
}
- if (!aid) return NULL;
+ if (!aid) {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "%S out of Time range", mrb_float_value(mrb, (mrb_float)self->sec));
+ /* not reached */
+ return NULL;
+ }
#ifdef NO_GMTIME_R
self->datetime = *aid; /* copy data */
#endif
@@ -213,7 +217,7 @@ static struct mrb_time*
time_alloc(mrb_state *mrb, double sec, double usec, enum mrb_timezone timezone)
{
struct mrb_time *tm;
- time_t tsec;
+ time_t tsec = 0;
if (sizeof(time_t) == 4 && (sec > (double)INT32_MAX || (double)INT32_MIN > sec)) {
goto out_of_range;
@@ -238,7 +242,7 @@ time_alloc(mrb_state *mrb, double sec, double usec, enum mrb_timezone timezone)
tm->usec -= 1000000;
}
tm->timezone = timezone;
- mrb_time_update_datetime(tm);
+ time_update_datetime(mrb, tm);
return tm;
}
@@ -290,7 +294,7 @@ current_mrb_time(mrb_state *mrb)
}
#endif
tm->timezone = MRB_TIMEZONE_LOCAL;
- mrb_time_update_datetime(tm);
+ time_update_datetime(mrb, tm);
return tm;
}
@@ -328,6 +332,15 @@ time_mktime(mrb_state *mrb, mrb_int ayear, mrb_int amonth, mrb_int aday,
nowtime.tm_min = (int)amin;
nowtime.tm_sec = (int)asec;
nowtime.tm_isdst = -1;
+
+ if (nowtime.tm_mon < 0 || nowtime.tm_mon > 11
+ || nowtime.tm_mday < 1 || nowtime.tm_mday > 31
+ || nowtime.tm_hour < 0 || nowtime.tm_hour > 24
+ || (nowtime.tm_hour == 24 && (nowtime.tm_min > 0 || nowtime.tm_sec > 0))
+ || nowtime.tm_min < 0 || nowtime.tm_min > 59
+ || nowtime.tm_sec < 0 || nowtime.tm_sec > 60)
+ mrb_raise(mrb, E_RUNTIME_ERROR, "argument out of range");
+
if (timezone == MRB_TIMEZONE_UTC) {
nowsecs = timegm(&nowtime);
}
@@ -368,6 +381,17 @@ mrb_time_local(mrb_state *mrb, mrb_value self)
time_mktime(mrb, ayear, amonth, aday, ahour, amin, asec, ausec, MRB_TIMEZONE_LOCAL));
}
+static struct mrb_time*
+time_get_ptr(mrb_state *mrb, mrb_value time)
+{
+ struct mrb_time *tm;
+
+ tm = DATA_GET_PTR(mrb, time, &mrb_time_type, struct mrb_time);
+ if (!tm) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "uninitialized time");
+ }
+ return tm;
+}
static mrb_value
mrb_time_eq(mrb_state *mrb, mrb_value self)
@@ -377,7 +401,7 @@ mrb_time_eq(mrb_state *mrb, mrb_value self)
mrb_bool eq_p;
mrb_get_args(mrb, "o", &other);
- tm1 = DATA_CHECK_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
+ tm1 = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
tm2 = DATA_CHECK_GET_PTR(mrb, other, &mrb_time_type, struct mrb_time);
eq_p = tm1 && tm2 && tm1->sec == tm2->sec && tm1->usec == tm2->usec;
@@ -391,7 +415,7 @@ mrb_time_cmp(mrb_state *mrb, mrb_value self)
struct mrb_time *tm1, *tm2;
mrb_get_args(mrb, "o", &other);
- tm1 = DATA_CHECK_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
+ tm1 = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
tm2 = DATA_CHECK_GET_PTR(mrb, other, &mrb_time_type, struct mrb_time);
if (!tm1 || !tm2) return mrb_nil_value();
if (tm1->sec > tm2->sec) {
@@ -417,7 +441,7 @@ mrb_time_plus(mrb_state *mrb, mrb_value self)
struct mrb_time *tm;
mrb_get_args(mrb, "f", &f);
- tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
+ tm = time_get_ptr(mrb, self);
return mrb_time_make(mrb, mrb_obj_class(mrb, self), (double)tm->sec+f, (double)tm->usec, tm->timezone);
}
@@ -429,8 +453,7 @@ mrb_time_minus(mrb_state *mrb, mrb_value self)
struct mrb_time *tm, *tm2;
mrb_get_args(mrb, "o", &other);
- tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
-
+ tm = time_get_ptr(mrb, self);
tm2 = DATA_CHECK_GET_PTR(mrb, other, &mrb_time_type, struct mrb_time);
if (tm2) {
f = (mrb_float)(tm->sec - tm2->sec)
@@ -450,7 +473,7 @@ mrb_time_wday(mrb_state *mrb, mrb_value self)
{
struct mrb_time *tm;
- tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
+ tm = time_get_ptr(mrb, self);
return mrb_fixnum_value(tm->datetime.tm_wday);
}
@@ -461,7 +484,7 @@ mrb_time_yday(mrb_state *mrb, mrb_value self)
{
struct mrb_time *tm;
- tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
+ tm = time_get_ptr(mrb, self);
return mrb_fixnum_value(tm->datetime.tm_yday + 1);
}
@@ -472,7 +495,7 @@ mrb_time_year(mrb_state *mrb, mrb_value self)
{
struct mrb_time *tm;
- tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
+ tm = time_get_ptr(mrb, self);
return mrb_fixnum_value(tm->datetime.tm_year + 1900);
}
@@ -483,7 +506,7 @@ mrb_time_zone(mrb_state *mrb, mrb_value self)
{
struct mrb_time *tm;
- tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
+ tm = time_get_ptr(mrb, self);
if (tm->timezone <= MRB_TIMEZONE_NONE) return mrb_nil_value();
if (tm->timezone >= MRB_TIMEZONE_LAST) return mrb_nil_value();
return mrb_str_new_static(mrb,
@@ -501,7 +524,7 @@ mrb_time_asctime(mrb_state *mrb, mrb_value self)
char buf[256];
int len;
- tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
+ tm = time_get_ptr(mrb, self);
d = &tm->datetime;
len = snprintf(buf, sizeof(buf), "%s %s %02d %02d:%02d:%02d %s%d",
wday_names[d->tm_wday], mon_names[d->tm_mon], d->tm_mday,
@@ -518,8 +541,7 @@ mrb_time_day(mrb_state *mrb, mrb_value self)
{
struct mrb_time *tm;
- tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
- if (!tm) return mrb_nil_value();
+ tm = time_get_ptr(mrb, self);
return mrb_fixnum_value(tm->datetime.tm_mday);
}
@@ -531,7 +553,7 @@ mrb_time_dst_p(mrb_state *mrb, mrb_value self)
{
struct mrb_time *tm;
- tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
+ tm = time_get_ptr(mrb, self);
return mrb_bool_value(tm->datetime.tm_isdst);
}
@@ -543,11 +565,11 @@ mrb_time_getutc(mrb_state *mrb, mrb_value self)
{
struct mrb_time *tm, *tm2;
- tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
+ tm = time_get_ptr(mrb, self);
tm2 = (struct mrb_time *)mrb_malloc(mrb, sizeof(*tm));
*tm2 = *tm;
tm2->timezone = MRB_TIMEZONE_UTC;
- mrb_time_update_datetime(tm2);
+ time_update_datetime(mrb, tm2);
return mrb_time_wrap(mrb, mrb_obj_class(mrb, self), tm2);
}
@@ -558,11 +580,11 @@ mrb_time_getlocal(mrb_state *mrb, mrb_value self)
{
struct mrb_time *tm, *tm2;
- tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
+ tm = time_get_ptr(mrb, self);
tm2 = (struct mrb_time *)mrb_malloc(mrb, sizeof(*tm));
*tm2 = *tm;
tm2->timezone = MRB_TIMEZONE_LOCAL;
- mrb_time_update_datetime(tm2);
+ time_update_datetime(mrb, tm2);
return mrb_time_wrap(mrb, mrb_obj_class(mrb, self), tm2);
}
@@ -573,7 +595,7 @@ mrb_time_hour(mrb_state *mrb, mrb_value self)
{
struct mrb_time *tm;
- tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
+ tm = time_get_ptr(mrb, self);
return mrb_fixnum_value(tm->datetime.tm_hour);
}
@@ -587,14 +609,14 @@ mrb_time_initialize(mrb_state *mrb, mrb_value self)
int n;
struct mrb_time *tm;
+ n = mrb_get_args(mrb, "|iiiiiii",
+ &ayear, &amonth, &aday, &ahour, &amin, &asec, &ausec);
tm = (struct mrb_time*)DATA_PTR(self);
if (tm) {
mrb_free(mrb, tm);
}
mrb_data_init(self, NULL, &mrb_time_type);
- n = mrb_get_args(mrb, "|iiiiiii",
- &ayear, &amonth, &aday, &ahour, &amin, &asec, &ausec);
if (n == 0) {
tm = current_mrb_time(mrb);
}
@@ -611,16 +633,23 @@ static mrb_value
mrb_time_initialize_copy(mrb_state *mrb, mrb_value copy)
{
mrb_value src;
+ struct mrb_time *t1, *t2;
mrb_get_args(mrb, "o", &src);
if (mrb_obj_equal(mrb, copy, src)) return copy;
if (!mrb_obj_is_instance_of(mrb, src, mrb_obj_class(mrb, copy))) {
mrb_raise(mrb, E_TYPE_ERROR, "wrong argument class");
}
- if (!DATA_PTR(copy)) {
- mrb_data_init(copy, mrb_malloc(mrb, sizeof(struct mrb_time)), &mrb_time_type);
+ t1 = (struct mrb_time *)DATA_PTR(copy);
+ t2 = (struct mrb_time *)DATA_PTR(src);
+ if (!t2) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "uninitialized time");
+ }
+ if (!t1) {
+ t1 = (struct mrb_time *)mrb_malloc(mrb, sizeof(struct mrb_time));
+ mrb_data_init(copy, t1, &mrb_time_type);
}
- *(struct mrb_time *)DATA_PTR(copy) = *(struct mrb_time *)DATA_PTR(src);
+ *t1 = *t2;
return copy;
}
@@ -631,9 +660,9 @@ mrb_time_localtime(mrb_state *mrb, mrb_value self)
{
struct mrb_time *tm;
- tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
+ tm = time_get_ptr(mrb, self);
tm->timezone = MRB_TIMEZONE_LOCAL;
- mrb_time_update_datetime(tm);
+ time_update_datetime(mrb, tm);
return self;
}
@@ -644,7 +673,7 @@ mrb_time_mday(mrb_state *mrb, mrb_value self)
{
struct mrb_time *tm;
- tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
+ tm = time_get_ptr(mrb, self);
return mrb_fixnum_value(tm->datetime.tm_mday);
}
@@ -655,7 +684,7 @@ mrb_time_min(mrb_state *mrb, mrb_value self)
{
struct mrb_time *tm;
- tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
+ tm = time_get_ptr(mrb, self);
return mrb_fixnum_value(tm->datetime.tm_min);
}
@@ -666,7 +695,7 @@ mrb_time_mon(mrb_state *mrb, mrb_value self)
{
struct mrb_time *tm;
- tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
+ tm = time_get_ptr(mrb, self);
return mrb_fixnum_value(tm->datetime.tm_mon + 1);
}
@@ -677,7 +706,7 @@ mrb_time_sec(mrb_state *mrb, mrb_value self)
{
struct mrb_time *tm;
- tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
+ tm = time_get_ptr(mrb, self);
return mrb_fixnum_value(tm->datetime.tm_sec);
}
@@ -689,7 +718,7 @@ mrb_time_to_f(mrb_state *mrb, mrb_value self)
{
struct mrb_time *tm;
- tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
+ tm = time_get_ptr(mrb, self);
return mrb_float_value(mrb, (mrb_float)tm->sec + (mrb_float)tm->usec/1.0e6);
}
@@ -700,7 +729,7 @@ mrb_time_to_i(mrb_state *mrb, mrb_value self)
{
struct mrb_time *tm;
- tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
+ tm = time_get_ptr(mrb, self);
if (tm->sec > MRB_INT_MAX || tm->sec < MRB_INT_MIN) {
return mrb_float_value(mrb, (mrb_float)tm->sec);
}
@@ -714,7 +743,7 @@ mrb_time_usec(mrb_state *mrb, mrb_value self)
{
struct mrb_time *tm;
- tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
+ tm = time_get_ptr(mrb, self);
if (tm->usec > MRB_INT_MAX || tm->usec < MRB_INT_MIN) {
return mrb_float_value(mrb, (mrb_float)tm->usec);
}
@@ -728,9 +757,9 @@ mrb_time_utc(mrb_state *mrb, mrb_value self)
{
struct mrb_time *tm;
- tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
+ tm = time_get_ptr(mrb, self);
tm->timezone = MRB_TIMEZONE_UTC;
- mrb_time_update_datetime(tm);
+ time_update_datetime(mrb, tm);
return self;
}
@@ -741,7 +770,7 @@ mrb_time_utc_p(mrb_state *mrb, mrb_value self)
{
struct mrb_time *tm;
- tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
+ tm = time_get_ptr(mrb, self);
return mrb_bool_value(tm->timezone == MRB_TIMEZONE_UTC);
}