diff --git a/moo/lib/moo-cmn.h b/moo/lib/moo-cmn.h index dda7a4a..fd7c905 100644 --- a/moo/lib/moo-cmn.h +++ b/moo/lib/moo-cmn.h @@ -614,11 +614,18 @@ typedef struct moo_obj_t* moo_oop_t; #define MOO_SEC_TO_USEC(sec) ((sec) * MOO_USECS_PER_SEC) #define MOO_USEC_TO_SEC(usec) ((usec) / MOO_USECS_PER_SEC) +#if defined(MOO_SIZEOF_INT64_T) && (MOO_SIZEOF_INT64_T > 0) +typedef moo_int64_t moo_ntime_sec_t; +#else +typedef moo_int32_t moo_ntime_sec_t; +#endif +typedef moo_int32_t moo_ntime_nsec_t; + typedef struct moo_ntime_t moo_ntime_t; struct moo_ntime_t { - moo_intptr_t sec; - moo_int32_t nsec; /* nanoseconds */ + moo_ntime_sec_t sec; + moo_ntime_nsec_t nsec; /* nanoseconds */ }; #define MOO_INIT_NTIME(c,s,ns) (((c)->sec = (s)), ((c)->nsec = (ns))) diff --git a/moo/lib/moo-utl.h b/moo/lib/moo-utl.h index 4297cca..92ecf71 100644 --- a/moo/lib/moo-utl.h +++ b/moo/lib/moo-utl.h @@ -875,6 +875,34 @@ MOO_EXPORT int moo_conv_mb8_to_ucstr ( moo_oow_t* ucslen ); +/* ========================================================================= + * TIME CALCULATION WITH OVERFLOW/UNDERFLOW DETECTION + * ========================================================================= */ + +/** + * The moo_add_ntime() function adds two time structures pointed to by \a x and \a y + * and stores the result in the structure pointed to by \a z. If it detects overflow/ + * underflow, it stores the largest/least possible value respectively. + * You may use the MOO_ADD_NTIME() macro if overflow/underflow check isn't needed. + */ +MOO_EXPORT void moo_add_ntime ( + moo_ntime_t* z, + const moo_ntime_t* x, + const moo_ntime_t* y +); + +/** + * The moo_sub_ntime() function subtracts the time value \a y from the time value \a x + * and stores the result in the structure pointed to by \a z. If it detects overflow/ + * underflow, it stores the largest/least possible value respectively. + * You may use the MOO_SUB_NTIME() macro if overflow/underflow check isn't needed. + */ +MOO_EXPORT void moo_sub_ntime ( + moo_ntime_t* z, + const moo_ntime_t* x, + const moo_ntime_t* y +); + /* ========================================================================= * BIT SWAP * ========================================================================= */ diff --git a/moo/lib/utl.c b/moo/lib/utl.c index ddcfacd..1ab6619 100644 --- a/moo/lib/utl.c +++ b/moo/lib/utl.c @@ -1314,3 +1314,115 @@ int moo_copyoocharstosbuf (moo_t* moo, const moo_ooch_t* ptr, moo_oow_t len, moo moo->sbuf[id].len = 0; return moo_concatoocharstosbuf(moo, ptr, len, id); } + + +/* ----------------------------------------------------------------------- */ + +void moo_add_ntime (moo_ntime_t* z, const moo_ntime_t* x, const moo_ntime_t* y) +{ + moo_ntime_sec_t xs, ys; + moo_ntime_nsec_t ns; + + /*MOO_ASSERT (x->nsec >= 0 && x->nsec < MOO_NSECS_PER_SEC); + MOO_ASSERT (y->nsec >= 0 && y->nsec < MOO_NSECS_PER_SEC);*/ + + ns = x->nsec + y->nsec; + if (ns >= MOO_NSECS_PER_SEC) + { + ns = ns - MOO_NSECS_PER_SEC; + if (x->sec == MOO_TYPE_MAX(moo_ntime_sec_t)) + { + if (y->sec >= 0) goto overflow; + xs = x->sec; + ys = y->sec + 1; /* this won't overflow */ + } + else + { + xs = x->sec + 1; /* this won't overflow */ + ys = y->sec; + } + } + else + { + xs = x->sec; + ys = y->sec; + } + + if ((ys >= 1 && xs > MOO_TYPE_MAX(moo_ntime_sec_t) - ys) || + (ys <= -1 && xs < MOO_TYPE_MIN(moo_ntime_sec_t) - ys)) + { + if (xs >= 0) + { + overflow: + xs = MOO_TYPE_MAX(moo_ntime_sec_t); + ns = MOO_NSECS_PER_SEC - 1; + } + else + { + xs = MOO_TYPE_MIN(moo_ntime_sec_t); + ns = 0; + } + } + else + { + xs = xs + ys; + } + + z->sec = xs; + z->nsec = ns; +} + +void moo_sub_ntime (moo_ntime_t* z, const moo_ntime_t* x, const moo_ntime_t* y) +{ + moo_ntime_sec_t xs, ys; + moo_ntime_nsec_t ns; + + /*MOO_ASSERT (x->nsec >= 0 && x->nsec < MOO_NSECS_PER_SEC); + MOO_ASSERT (y->nsec >= 0 && y->nsec < MOO_NSECS_PER_SEC);*/ + + ns = x->nsec - y->nsec; + if (ns < 0) + { + ns = ns + MOO_NSECS_PER_SEC; + if (x->sec == MOO_TYPE_MIN(moo_ntime_sec_t)) + { + if (y->sec <= 0) goto underflow; + xs = x->sec; + ys = y->sec - 1; /* this won't underflow */ + } + else + { + xs = x->sec - 1; /* this won't underflow */ + ys = y->sec; + } + } + else + { + xs = x->sec; + ys = y->sec; + } + + if ((ys >= 1 && xs < MOO_TYPE_MIN(moo_ntime_sec_t) + ys) || + (ys <= -1 && xs > MOO_TYPE_MAX(moo_ntime_sec_t) + ys)) + { + if (xs >= 0) + { + xs = MOO_TYPE_MAX(moo_ntime_sec_t); + ns = MOO_NSECS_PER_SEC - 1; + } + else + { + underflow: + xs = MOO_TYPE_MIN(moo_ntime_sec_t); + ns = 0; + } + } + else + { + xs = xs - ys; + } + + z->sec = xs; + z->nsec = ns; +} +