LCOV - code coverage report
Current view: top level - snapdev - timespec_operations.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 210 210 100.0 %
Date: 2021-08-22 18:14:51 Functions: 45 45 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2021  Made to Order Software Corp.  All Rights Reserved
       2             : //
       3             : // https://snapwebsites.org/project/snapdev
       4             : // contact@m2osw.com
       5             : //
       6             : // This program is free software; you can redistribute it and/or modify
       7             : // it under the terms of the GNU General Public License as published by
       8             : // the Free Software Foundation; either version 2 of the License, or
       9             : // (at your option) any later version.
      10             : //
      11             : // This program is distributed in the hope that it will be useful,
      12             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             : // GNU General Public License for more details.
      15             : //
      16             : // You should have received a copy of the GNU General Public License along
      17             : // with this program; if not, write to the Free Software Foundation, Inc.,
      18             : // 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
      19             : #pragma once
      20             : 
      21             : // C++ lib
      22             : //
      23             : #include    <cmath>
      24             : #include    <cstdint>
      25             : #include    <iomanip>
      26             : #include    <iostream>
      27             : #include    <sstream>
      28             : 
      29             : 
      30             : // C lib
      31             : //
      32             : #include    <stdlib.h>
      33             : #include    <sys/time.h>
      34             : 
      35             : 
      36             : 
      37             : 
      38           7 : inline bool valid_timespec(timespec const & t)
      39             : {
      40           7 :     return t.tv_nsec < 1'000'000'000LL;
      41             : }
      42             : 
      43             : 
      44          64 : inline bool negative_timespec(timespec const & t)
      45             : {
      46          64 :     return t.tv_sec < 0LL;
      47             : }
      48             : 
      49             : 
      50          44 : inline timespec operator - (timespec const & t)
      51             : {
      52             :     // equivalen to `0 - t`
      53             :     //
      54          44 :     timespec result{ -t.tv_sec, -t.tv_nsec };
      55          44 :     if(result.tv_nsec < 0)
      56             :     {
      57          43 :         --result.tv_sec;
      58          43 :         result.tv_nsec += 1'000'000'000L;
      59             :     }
      60          44 :     return result;
      61             : }
      62             : 
      63             : 
      64          29 : inline timespec add_timespec(timespec const & lhs, timespec const & rhs)
      65             : {
      66          29 :     bool const lneg(negative_timespec(lhs));
      67          29 :     bool const rneg(negative_timespec(rhs));
      68             : 
      69          29 :     timespec lp(lneg ? -lhs : lhs);
      70          29 :     timespec rp(rneg ? -rhs : rhs);
      71             : 
      72          29 :     timespec result = {};
      73             : 
      74          29 :     switch((lneg ? 1 : 0) + (rneg ? 2 : 0))
      75             :     {
      76          12 :     case 0:     // positive + positive
      77          12 :         result.tv_sec = lp.tv_sec + rp.tv_sec;
      78          12 :         result.tv_nsec = lp.tv_nsec + rp.tv_nsec;
      79          12 :         break;
      80             : 
      81           5 :     case 1:     // negative + positive
      82           5 :         result.tv_sec = rp.tv_sec - lp.tv_sec;
      83           5 :         result.tv_nsec = rp.tv_nsec - lp.tv_nsec;
      84           5 :         break;
      85             : 
      86          10 :     case 2:     // positive + negative
      87          10 :         result.tv_sec = lp.tv_sec - rp.tv_sec;
      88          10 :         result.tv_nsec = lp.tv_nsec - rp.tv_nsec;
      89          10 :         break;
      90             : 
      91           2 :     case 3:     // negative + negative
      92           2 :         result.tv_sec = lp.tv_sec + rp.tv_sec;
      93           2 :         result.tv_nsec = lp.tv_nsec + rp.tv_nsec;
      94           2 :         break;
      95             : 
      96             :     }
      97             : 
      98          29 :     if(result.tv_nsec < 0)
      99             :     {
     100           3 :         --result.tv_sec;
     101           3 :         result.tv_nsec += 1'000'000'000L;
     102             :     }
     103          26 :     else if(result.tv_nsec >= 1'000'000'000)
     104             :     {
     105           5 :         ++result.tv_sec;
     106           5 :         result.tv_nsec -= 1'000'000'000;
     107             :     }
     108             : 
     109          29 :     if(lneg && rneg)
     110             :     {
     111           2 :         result = -result;
     112             :     }
     113             : 
     114          29 :     return result;
     115             : }
     116             : 
     117             : 
     118             : // This one is not possible as a static function
     119             : //inline operator bool (timespec const & t)
     120             : //{
     121             : //    return t.tv_sec != 0 || tv.tv_nsec != 0;
     122             : //}
     123             : 
     124             : 
     125          11 : inline bool operator ! (timespec const & t)
     126             : {
     127          11 :     return t.tv_sec == 0 && t.tv_nsec == 0;
     128             : }
     129             : 
     130             : 
     131          26 : inline timespec & operator <<= (timespec & lhs, std::int64_t nsec)
     132             : {
     133          26 :     bool const neg(nsec < 0);
     134          26 :     if(neg)
     135             :     {
     136           9 :         nsec = -nsec;
     137             :     }
     138          26 :     lhs.tv_sec = static_cast<time_t>(nsec / 1'000'000'000LL);
     139          26 :     lhs.tv_nsec = static_cast<long>(llabs(nsec) % 1'000'000'000LL);
     140          26 :     if(neg)
     141             :     {
     142           9 :         lhs = -lhs;
     143             :     }
     144          26 :     return lhs;
     145             : }
     146             : 
     147             : 
     148           1 : inline std::int64_t operator >>= (timespec & t, std::int64_t & nsec)
     149             : {
     150           1 :     nsec = t.tv_sec * 1'000'000'000LL + t.tv_nsec;
     151           1 :     return nsec;
     152             : }
     153             : 
     154             : 
     155          16 : inline timespec & operator <<= (timespec & lhs, double sec)
     156             : {
     157          16 :     bool const neg(sec < 0.0);
     158          16 :     if(neg)
     159             :     {
     160           1 :         sec = -sec;
     161             :     }
     162          16 :     lhs.tv_sec = static_cast<time_t>(floor(sec));
     163          16 :     lhs.tv_nsec = static_cast<long>((sec - floor(sec)) * 1.0e9);
     164          16 :     if(neg)
     165             :     {
     166           1 :         lhs = -lhs;
     167             :     }
     168          16 :     return lhs;
     169             : }
     170             : 
     171             : 
     172           6 : inline std::int64_t operator >>= (timespec & t, double & nsec)
     173             : {
     174           6 :     nsec = t.tv_sec + t.tv_nsec / 1'000'000'000.0;
     175           6 :     return nsec;
     176             : }
     177             : 
     178             : 
     179          19 : inline timespec & operator += (timespec & lhs, timespec const & rhs)
     180             : {
     181          19 :     lhs = add_timespec(lhs, rhs);
     182          19 :     return lhs;
     183             : }
     184             : 
     185             : 
     186           6 : inline timespec & operator += (timespec & lhs, std::int64_t rhs)
     187             : {
     188           6 :     timespec t;
     189           6 :     t <<= rhs;
     190           6 :     lhs += t;
     191           6 :     return lhs;
     192             : }
     193             : 
     194             : 
     195           1 : inline timespec & operator += (timespec & lhs, double rhs)
     196             : {
     197           1 :     timespec t;
     198           1 :     t <<= rhs;
     199           1 :     lhs += t;
     200           1 :     return lhs;
     201             : }
     202             : 
     203             : 
     204           3 : inline timespec & operator ++ (timespec & lhs)
     205             : {
     206           3 :     lhs += 1L;
     207           3 :     return lhs;
     208             : }
     209             : 
     210             : 
     211           1 : inline timespec operator ++ (timespec & lhs, int)
     212             : {
     213           1 :     timespec result(lhs);
     214           1 :     lhs += 1L;
     215           1 :     return result;
     216             : }
     217             : 
     218             : 
     219           4 : inline timespec operator + (timespec const & lhs, timespec const & rhs)
     220             : {
     221           4 :     timespec result(lhs);
     222           4 :     result += rhs;
     223           4 :     return result;
     224             : }
     225             : 
     226             : 
     227           2 : inline timespec operator + (timespec const & lhs, std::int64_t rhs)
     228             : {
     229           2 :     timespec result;
     230           2 :     result <<= rhs;
     231           2 :     result += lhs;
     232           2 :     return result;
     233             : }
     234             : 
     235             : 
     236           1 : inline timespec operator + (timespec const & lhs, double rhs)
     237             : {
     238           1 :     timespec result;
     239           1 :     result <<= rhs;
     240           1 :     result += lhs;
     241           1 :     return result;
     242             : }
     243             : 
     244             : 
     245          10 : inline timespec & operator -= (timespec & lhs, timespec const & rhs)
     246             : {
     247          10 :     timespec const neg(-rhs);
     248          10 :     lhs = add_timespec(lhs, neg);
     249          10 :     return lhs;
     250             : }
     251             : 
     252             : 
     253           4 : inline timespec & operator -= (timespec & lhs, std::int64_t rhs)
     254             : {
     255           4 :     timespec result;
     256           4 :     result <<= rhs;
     257           4 :     lhs -= result;
     258           4 :     return lhs;
     259             : }
     260             : 
     261             : 
     262           1 : inline timespec & operator -= (timespec & lhs, double rhs)
     263             : {
     264           1 :     timespec result;
     265           1 :     result <<= rhs;
     266           1 :     lhs -= result;
     267           1 :     return lhs;
     268             : }
     269             : 
     270             : 
     271           3 : inline timespec & operator -- (timespec & lhs)
     272             : {
     273           3 :     lhs -= 1L;
     274           3 :     return lhs;
     275             : }
     276             : 
     277             : 
     278           1 : inline timespec operator -- (timespec & lhs, int)
     279             : {
     280           1 :     timespec result(lhs);
     281           1 :     lhs -= 1L;
     282           1 :     return result;
     283             : }
     284             : 
     285             : 
     286           3 : inline timespec operator - (timespec const & lhs, timespec const & rhs)
     287             : {
     288           3 :     timespec result(lhs);
     289           3 :     result -= rhs;
     290           3 :     return result;
     291             : }
     292             : 
     293             : 
     294           1 : inline timespec operator - (timespec const & lhs, std::int64_t rhs)
     295             : {
     296           1 :     timespec result;
     297           1 :     result <<= -rhs;
     298           1 :     result += lhs;
     299           1 :     return result;
     300             : }
     301             : 
     302             : 
     303           1 : inline timespec operator - (timespec const & lhs, double rhs)
     304             : {
     305           1 :     timespec result;
     306           1 :     result <<= -rhs;
     307           1 :     result += lhs;
     308           1 :     return result;
     309             : }
     310             : 
     311             : 
     312          96 : int compare_timespec(timespec const & lhs, timespec const & rhs)
     313             : {
     314          96 :     if(lhs.tv_sec == rhs.tv_sec)
     315             :     {
     316          85 :         return lhs.tv_nsec == rhs.tv_nsec
     317         112 :                 ? 0
     318         112 :                 : (lhs.tv_nsec < rhs.tv_nsec ? -1 : 1);
     319             :     }
     320             : 
     321          11 :     return lhs.tv_sec < rhs.tv_sec ? -1 : 1;
     322             : }
     323             : 
     324             : 
     325          19 : inline bool operator == (timespec const & lhs, timespec const & rhs)
     326             : {
     327          19 :     return compare_timespec(lhs, rhs) == 0;
     328             : }
     329             : 
     330             : 
     331           2 : inline bool operator == (timespec const & lhs, std::int64_t rhs)
     332             : {
     333           2 :     timespec t;
     334           2 :     t <<= rhs;
     335           2 :     return compare_timespec(lhs, t) == 0;
     336             : }
     337             : 
     338             : 
     339           2 : inline bool operator == (timespec const & lhs, double rhs)
     340             : {
     341           2 :     timespec t;
     342           2 :     t <<= rhs;
     343           2 :     return compare_timespec(lhs, t) == 0;
     344             : }
     345             : 
     346             : 
     347          11 : inline bool operator != (timespec const & lhs, timespec const & rhs)
     348             : {
     349          11 :     return compare_timespec(lhs, rhs) != 0;
     350             : }
     351             : 
     352             : 
     353           2 : inline bool operator != (timespec const & lhs, std::int64_t rhs)
     354             : {
     355           2 :     timespec t;
     356           2 :     t <<= rhs;
     357           2 :     return compare_timespec(lhs, t) != 0;
     358             : }
     359             : 
     360             : 
     361           2 : inline bool operator != (timespec const & lhs, double rhs)
     362             : {
     363           2 :     timespec t;
     364           2 :     t <<= rhs;
     365           2 :     return compare_timespec(lhs, t) != 0;
     366             : }
     367             : 
     368             : 
     369          11 : inline bool operator < (timespec const & lhs, timespec const & rhs)
     370             : {
     371          11 :     return compare_timespec(lhs, rhs) == -1;
     372             : }
     373             : 
     374             : 
     375           2 : inline bool operator < (timespec const & lhs, std::int64_t rhs)
     376             : {
     377           2 :     timespec t;
     378           2 :     t <<= rhs;
     379           2 :     return compare_timespec(lhs, t) == -1;
     380             : }
     381             : 
     382             : 
     383           1 : inline bool operator < (timespec const & lhs, double rhs)
     384             : {
     385           1 :     timespec t;
     386           1 :     t <<= rhs;
     387           1 :     return compare_timespec(lhs, t) == -1;
     388             : }
     389             : 
     390             : 
     391          11 : inline bool operator <= (timespec const & lhs, timespec const & rhs)
     392             : {
     393          11 :     return compare_timespec(lhs, rhs) <= 0;
     394             : }
     395             : 
     396             : 
     397           2 : inline bool operator <= (timespec const & lhs, std::int64_t rhs)
     398             : {
     399           2 :     timespec t;
     400           2 :     t <<= rhs;
     401           2 :     return compare_timespec(lhs, t) <= 0;
     402             : }
     403             : 
     404             : 
     405           2 : inline bool operator <= (timespec const & lhs, double rhs)
     406             : {
     407           2 :     timespec t;
     408           2 :     t <<= rhs;
     409           2 :     return compare_timespec(lhs, t) <= 0;
     410             : }
     411             : 
     412             : 
     413          11 : inline bool operator > (timespec const & lhs, timespec const & rhs)
     414             : {
     415          11 :     return compare_timespec(lhs, rhs) == 1;
     416             : }
     417             : 
     418             : 
     419           2 : inline bool operator > (timespec const & lhs, std::int64_t rhs)
     420             : {
     421           2 :     timespec t;
     422           2 :     t <<= rhs;
     423           2 :     return compare_timespec(lhs, t) == 1;
     424             : }
     425             : 
     426             : 
     427           1 : inline bool operator > (timespec const & lhs, double rhs)
     428             : {
     429           1 :     timespec t;
     430           1 :     t <<= rhs;
     431           1 :     return compare_timespec(lhs, t) == 1;
     432             : }
     433             : 
     434             : 
     435          11 : inline bool operator >= (timespec const & lhs, timespec const & rhs)
     436             : {
     437          11 :     return compare_timespec(lhs, rhs) >= 0;
     438             : }
     439             : 
     440             : 
     441           2 : inline bool operator >= (timespec const & lhs, std::int64_t rhs)
     442             : {
     443           2 :     timespec t;
     444           2 :     t <<= rhs;
     445           2 :     return compare_timespec(lhs, t) >= 0;
     446             : }
     447             : 
     448             : 
     449           2 : inline bool operator >= (timespec const & lhs, double rhs)
     450             : {
     451           2 :     timespec t;
     452           2 :     t <<= rhs;
     453           2 :     return compare_timespec(lhs, t) >= 0;
     454             : }
     455             : 
     456             : 
     457             : /** \brief Output a timespec to a basic_ostream.
     458             :  *
     459             :  * This function allows one to print out a timespec. By default the function
     460             :  * prints the timespec as a floating point.
     461             :  *
     462             :  * \todo
     463             :  * Look into the possibility to write the data as Y/M/D H:M:S.nanosecs
     464             :  *
     465             :  * \param[in] out  The output stream where the timespec gets written.
     466             :  * \param[in] t  The actual timespec that is to be printed.
     467             :  *
     468             :  * \return A reference to the basic_ostream object.
     469             :  */
     470             : template<class E, class S>
     471           3 : std::basic_ostream<E, S> & operator << (std::basic_ostream<E, S> & out, timespec const & t)
     472             : {
     473             :     // write to a string buffer first
     474             :     //
     475           6 :     std::basic_ostringstream<E, S, std::allocator<E> > s;
     476             : 
     477             :     // setup the string output like the out stream
     478             :     //
     479           3 :     s.flags(out.flags());
     480           3 :     s.imbue(out.getloc());
     481           3 :     s.precision(out.precision());
     482           3 :     s << t.tv_sec << "." << std::setw(9) << std::setfill('0') << t.tv_nsec;
     483             : 
     484             :     // buffer is ready, display in output in one go
     485             :     //
     486           6 :     return out << s.str();
     487             : }
     488             : 
     489             : 
     490             : 
     491             : 
     492             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.13