rsys

Basic data structures and low-level features
git clone git://git.meso-star.fr/rsys.git
Log | Files | Refs | README | LICENSE

clock_time.c (6272B)


      1 /* Copyright (C) 2013-2023, 2025 Vincent Forest (vaplv@free.fr)
      2  *
      3  * The RSys library is free software: you can redistribute it and/or modify
      4  * it under the terms of the GNU General Public License as published
      5  * by the Free Software Foundation, either version 3 of the License, or
      6  * (at your option) any later version.
      7  *
      8  * The RSys library is distributed in the hope that it will be useful,
      9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     11  * GNU General Public License for more details.
     12  *
     13  * You should have received a copy of the GNU General Public License
     14  * along with the RSys library. If not, see <http://www.gnu.org/licenses/>. */
     15 
     16 #define _POSIX_C_SOURCE 200112L /* snprintf support */
     17 #include "rsys.h"
     18 
     19 #include <time.h>
     20 
     21 #include "clock_time.h"
     22 #include <string.h>
     23 
     24 #define TIME_TO_NSEC(Time) ((Time)->nsec + (Time)->sec * 1000000000L)
     25 #define NSEC_PER_USEC__ (int64_t)1000
     26 #define NSEC_PER_MSEC__ ((int64_t)1000 * NSEC_PER_USEC__)
     27 #define NSEC_PER_SEC__ ((int64_t)1000 * NSEC_PER_MSEC__)
     28 #define NSEC_PER_MIN__ ((int64_t)60 * NSEC_PER_SEC__)
     29 #define NSEC_PER_HOUR__ ((int64_t)60 * NSEC_PER_MIN__)
     30 #define NSEC_PER_DAY__ ((int64_t)24 * NSEC_PER_HOUR__)
     31 
     32 struct time*
     33 time_current(struct time* t)
     34 {
     35   struct timespec time;
     36   int err = 0; (void)err;
     37   ASSERT(t);
     38 
     39   err = clock_gettime(CLOCK_REALTIME, &time);
     40   ASSERT(err == 0);
     41   t->sec = (int64_t)time.tv_sec;
     42   t->nsec = (int64_t)time.tv_nsec;
     43   return t;
     44 }
     45 
     46 struct time*
     47 time_sub(struct time* res, const struct time* a, const struct time* b)
     48 {
     49   ASSERT(res && a && b);
     50   res->sec = a->sec - b->sec;
     51   res->nsec = a->nsec - b->nsec;
     52   if(res->nsec < 0) {
     53     --res->sec;
     54     res->nsec += 1000000000L;
     55   }
     56   return res;
     57 }
     58 
     59 struct time*
     60 time_add(struct time* res, const struct time* a, const struct time* b)
     61 {
     62   ASSERT(res && a && b);
     63 
     64   res->sec = a->sec + b->sec;
     65   res->nsec = a->nsec + b->nsec;
     66   if(res->nsec >= 1000000000L) {
     67 	  ++res->sec;
     68     res->nsec -= 1000000000L;
     69   }
     70   return res;
     71 }
     72 
     73 int64_t
     74 time_val(const struct time* time, enum time_unit unit)
     75 {
     76   int64_t val = TIME_TO_NSEC(time);
     77   switch(unit) {
     78     case TIME_NSEC:
     79       /* Do nothing. */
     80       break;
     81     case TIME_USEC:
     82       val /= NSEC_PER_USEC__;
     83       break;
     84     case TIME_MSEC:
     85       val /= NSEC_PER_MSEC__;
     86       break;
     87     case TIME_SEC:
     88       val /= NSEC_PER_SEC__;
     89       break;
     90     case TIME_MIN:
     91       val /= NSEC_PER_MIN__;
     92       break;
     93     case TIME_HOUR:
     94       val /= NSEC_PER_HOUR__;
     95       break;
     96     case TIME_DAY:
     97       val /= NSEC_PER_DAY__;
     98       break;
     99     default: ASSERT(0); break;
    100   }
    101   return val;
    102 }
    103 
    104 void
    105 time_dump
    106   (const struct time* time,
    107    int flag,
    108    size_t* real_dump_len,
    109    char* dump,
    110    size_t max_dump_len)
    111 {
    112   size_t available_dump_space = max_dump_len;
    113   int64_t time_nsec = 0;
    114   char* dst = dump;
    115 
    116   ASSERT(time && (!max_dump_len || dump));
    117   if(real_dump_len) *real_dump_len = 0;
    118   if(max_dump_len > 0) dump[0] = '\0';
    119   if(!flag) return;
    120 
    121   #define DUMP(Time, Suffix)                                                   \
    122     {                                                                          \
    123       const int len = snprintf                                                 \
    124         (dst, available_dump_space,                                            \
    125          "%li %s", (long)Time, Time > 1 ? Suffix "s ": Suffix " ");            \
    126       ASSERT(len >= 0);                                                        \
    127       if(real_dump_len) {                                                      \
    128         *real_dump_len += (size_t)len;                                         \
    129       }                                                                        \
    130       if((size_t)len < available_dump_space) {                                 \
    131         dst += len;                                                            \
    132         available_dump_space -= (size_t)len;                                   \
    133       } else if(dst) {                                                         \
    134         available_dump_space = 0;                                              \
    135         dst = NULL;                                                            \
    136       }                                                                        \
    137     } (void) 0
    138 
    139   time_nsec = TIME_TO_NSEC(time);
    140   if(flag & TIME_DAY) {
    141     const int64_t nb_days = time_nsec / NSEC_PER_DAY__;
    142     if(nb_days) DUMP(nb_days, "day");
    143     time_nsec -= nb_days * NSEC_PER_DAY__;
    144   }
    145   if(flag & TIME_HOUR) {
    146     const int64_t nb_hours = time_nsec / NSEC_PER_HOUR__;
    147     if(nb_hours) DUMP(nb_hours, "hour");
    148     time_nsec -= nb_hours * NSEC_PER_HOUR__;
    149   }
    150   if(flag & TIME_MIN) {
    151     const int64_t nb_mins = time_nsec / NSEC_PER_MIN__;
    152     if(nb_mins) DUMP(nb_mins, "min");
    153     time_nsec -= nb_mins * NSEC_PER_MIN__;
    154   }
    155   if(flag & TIME_SEC) {
    156     const int64_t nb_secs = time_nsec / NSEC_PER_SEC__;
    157     if(nb_secs) DUMP(nb_secs, "sec");
    158     time_nsec -= nb_secs * NSEC_PER_SEC__;
    159   }
    160   if(flag & TIME_MSEC) {
    161     const int64_t nb_msecs = time_nsec / NSEC_PER_MSEC__;
    162     if(nb_msecs) DUMP(nb_msecs, "msec");
    163     time_nsec -= nb_msecs * NSEC_PER_MSEC__;
    164   }
    165   if(flag & TIME_USEC) {
    166     const int64_t nb_usecs = time_nsec / NSEC_PER_USEC__;
    167     if(nb_usecs) DUMP(nb_usecs, "usec");
    168     time_nsec -= nb_usecs * NSEC_PER_USEC__;
    169   }
    170   if(flag & TIME_NSEC) {
    171     if(time_nsec) DUMP(time_nsec, "nsec");
    172   }
    173 
    174   /* Remove last space */
    175   if(real_dump_len) *real_dump_len -= 1;
    176 
    177   if(max_dump_len > 0) {
    178     size_t dump_len = strlen(dump);
    179     if(!dump_len && flag) {
    180       if(flag & TIME_NSEC) { DUMP(0, "nsec");
    181       } else if(flag & TIME_USEC) { DUMP(0, "usec");
    182       } else if(flag & TIME_MSEC) { DUMP(0, "msec");
    183       } else if(flag & TIME_SEC) { DUMP(0, "sec");
    184       } else if(flag & TIME_MIN) { DUMP(0, "min");
    185       } else if(flag & TIME_HOUR) { DUMP(0, "hour");
    186       } else if(flag & TIME_DAY) { DUMP(0, "day");
    187       }
    188       dump_len = strlen(dump);
    189     }
    190     /* Remove last space */
    191     if(dump[dump_len-1] == ' ') {
    192       dump[dump_len-1] = '\0';
    193     }
    194   }
    195   #undef DUMP
    196 }
    197 
    198 #undef TIME_TO_NSEC
    199 #undef NSEC_PER_USEC__
    200 #undef NSEC_PER_MSEC__
    201 #undef NSEC_PER_SEC__
    202 #undef NSEC_PER_MIN__
    203 #undef NSEC_PER_HOUR__
    204 #undef NSEC_PER_DAY__