From e8ac460f599e13a6dd2f267dd4abd27e14fe7843 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Thu, 3 Sep 2020 06:21:01 +0000 Subject: [PATCH] added hcl_add_ntime()/hcl_sub_ntime() --- lib/hcl-cmn.h | 11 ++++- lib/hcl-utl.h | 28 +++++++++++++ lib/utl.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 147 insertions(+), 2 deletions(-) diff --git a/lib/hcl-cmn.h b/lib/hcl-cmn.h index 30bbd12..caf127b 100644 --- a/lib/hcl-cmn.h +++ b/lib/hcl-cmn.h @@ -564,11 +564,18 @@ typedef struct hcl_obj_t* hcl_oop_t; #define HCL_SEC_TO_USEC(sec) ((sec) * HCL_USECS_PER_SEC) #define HCL_USEC_TO_SEC(usec) ((usec) / HCL_USECS_PER_SEC) +#if defined(HCL_SIZEOF_INT64_T) && (HCL_SIZEOF_INT64_T > 0) +typedef hcl_int64_t hcl_ntime_sec_t; +#else +typedef hcl_int32_t hcl_ntime_sec_t; +#endif +typedef hcl_int32_t hcl_ntime_nsec_t; + typedef struct hcl_ntime_t hcl_ntime_t; struct hcl_ntime_t { - hcl_intptr_t sec; - hcl_int32_t nsec; /* nanoseconds */ + hcl_ntime_sec_t sec; + hcl_ntime_nsec_t nsec; /* nanoseconds */ }; #define HCL_INIT_NTIME(c,s,ns) (((c)->sec = (s)), ((c)->nsec = (ns))) diff --git a/lib/hcl-utl.h b/lib/hcl-utl.h index d1291b6..112225c 100644 --- a/lib/hcl-utl.h +++ b/lib/hcl-utl.h @@ -758,6 +758,34 @@ HCL_EXPORT int hcl_ufmt_out ( ... ); +/* ========================================================================= + * TIME CALCULATION WITH OVERFLOW/UNDERFLOW DETECTION + * ========================================================================= */ + +/** + * The hcl_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 HCL_ADD_NTIME() macro if overflow/underflow check isn't needed. + */ +HCL_EXPORT void hcl_add_ntime ( + hcl_ntime_t* z, + const hcl_ntime_t* x, + const hcl_ntime_t* y +); + +/** + * The hcl_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 HCL_SUB_NTIME() macro if overflow/underflow check isn't needed. + */ +HCL_EXPORT void hcl_sub_ntime ( + hcl_ntime_t* z, + const hcl_ntime_t* x, + const hcl_ntime_t* y +); + /* ========================================================================= * BIT SWAP * ========================================================================= */ diff --git a/lib/utl.c b/lib/utl.c index 6222ecc..b0c816c 100644 --- a/lib/utl.c +++ b/lib/utl.c @@ -925,3 +925,113 @@ hcl_bch_t* hcl_dupbchars (hcl_t* hcl, const hcl_bch_t* bcs, hcl_oow_t bcslen) return ptr; } +/* ----------------------------------------------------------------------- */ + +void hcl_add_ntime (hcl_ntime_t* z, const hcl_ntime_t* x, const hcl_ntime_t* y) +{ + hcl_ntime_sec_t xs, ys; + hcl_ntime_nsec_t ns; + + /*HCL_ASSERT (x->nsec >= 0 && x->nsec < HCL_NSECS_PER_SEC); + HCL_ASSERT (y->nsec >= 0 && y->nsec < HCL_NSECS_PER_SEC);*/ + + ns = x->nsec + y->nsec; + if (ns >= HCL_NSECS_PER_SEC) + { + ns = ns - HCL_NSECS_PER_SEC; + if (x->sec == HCL_TYPE_MAX(hcl_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 > HCL_TYPE_MAX(hcl_ntime_sec_t) - ys) || + (ys <= -1 && xs < HCL_TYPE_MIN(hcl_ntime_sec_t) - ys)) + { + if (xs >= 0) + { + overflow: + xs = HCL_TYPE_MAX(hcl_ntime_sec_t); + ns = HCL_NSECS_PER_SEC - 1; + } + else + { + xs = HCL_TYPE_MIN(hcl_ntime_sec_t); + ns = 0; + } + } + else + { + xs = xs + ys; + } + + z->sec = xs; + z->nsec = ns; +} + +void hcl_sub_ntime (hcl_ntime_t* z, const hcl_ntime_t* x, const hcl_ntime_t* y) +{ + hcl_ntime_sec_t xs, ys; + hcl_ntime_nsec_t ns; + + /*HCL_ASSERT (x->nsec >= 0 && x->nsec < HCL_NSECS_PER_SEC); + HCL_ASSERT (y->nsec >= 0 && y->nsec < HCL_NSECS_PER_SEC);*/ + + ns = x->nsec - y->nsec; + if (ns < 0) + { + ns = ns + HCL_NSECS_PER_SEC; + if (x->sec == HCL_TYPE_MIN(hcl_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 < HCL_TYPE_MIN(hcl_ntime_sec_t) + ys) || + (ys <= -1 && xs > HCL_TYPE_MAX(hcl_ntime_sec_t) + ys)) + { + if (xs >= 0) + { + xs = HCL_TYPE_MAX(hcl_ntime_sec_t); + ns = HCL_NSECS_PER_SEC - 1; + } + else + { + underflow: + xs = HCL_TYPE_MIN(hcl_ntime_sec_t); + ns = 0; + } + } + else + { + xs = xs - ys; + } + + z->sec = xs; + z->nsec = ns; +} +