LCOV - code coverage report
Current view: top level - snapdev - timespec_operations.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 171 171 100.0 %
Date: 2022-07-09 19:51:09 Functions: 39 39 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2021-2022  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             : // libexcept
      22             : //
      23             : #include    <libexcept/exception.h>
      24             : 
      25             : 
      26             : // C++
      27             : //
      28             : #include    <cmath>
      29             : #include    <cstdint>
      30             : #include    <iomanip>
      31             : #include    <iostream>
      32             : #include    <sstream>
      33             : 
      34             : 
      35             : // C
      36             : //
      37             : #include    <stdlib.h>
      38             : #include    <sys/time.h>
      39             : #include    <time.h>
      40             : 
      41             : 
      42             : 
      43             : 
      44             : namespace snapdev
      45             : {
      46             : 
      47             : DECLARE_MAIN_EXCEPTION(timespec_ex_exception);
      48             : 
      49             : DECLARE_EXCEPTION(timespec_ex_exception, overflow);
      50             : 
      51             : 
      52             : class timespec_ex
      53             :     : public timespec
      54             : {
      55             : public:
      56             :     /** \brief Initialize a timespec_ex to zero.
      57             :      *
      58             :      * This constructor is used to initialize a new timespec_ex to the
      59             :      * default value, which is 0.
      60             :      */
      61          38 :     timespec_ex()
      62          38 :     {
      63          38 :         set(0L);
      64          38 :     }
      65             : 
      66             : 
      67             :     /** \brief Initialize a timespec_ex from another.
      68             :      *
      69             :      * This constructors allows you to directly copy a timespec_ex
      70             :      * in another new timespec_ex object.
      71             :      *
      72             :      * \param[in] t  The timespec_ex to directly copy.
      73             :      */
      74          62 :     timespec_ex(timespec_ex const & t)
      75          62 :     {
      76          62 :         set(t);
      77          62 :     }
      78             : 
      79             : 
      80             :     /** \brief Initialize a timespec_ex from a timespec structure.
      81             :      *
      82             :      * This constructors allows you to directly set a timespec_ex
      83             :      * to the specified timespec values.
      84             :      *
      85             :      * \param[in] t  The timespec to directly copy.
      86             :      */
      87          59 :     timespec_ex(timespec const & t)
      88          59 :     {
      89          59 :         set(t);
      90          59 :     }
      91             : 
      92             : 
      93             :     /** \brief Initialize a timespec_ex from seconds and nanoseconds.
      94             :      *
      95             :      * This constructors allows you to directly initialize a timespec_ex
      96             :      * from seconds and nanoseconds.
      97             :      *
      98             :      * To create a valid timespec_ex object, you must pass a number
      99             :      * between 0 and 999'999'999 for the \p nsec parameter.
     100             :      *
     101             :      * \param[in] sec  The number of seconds.
     102             :      * \param[in] nsec  The number of nano-seconds.
     103             :      */
     104           6 :     timespec_ex(time_t sec, long nsec)
     105           6 :     {
     106           6 :         set(sec, nsec);
     107           6 :     }
     108             : 
     109             : 
     110             :     /** \brief Initialize a timespec_ex from an int64_t in nanoseconds.
     111             :      *
     112             :      * This constructors allows you to directly set a timespec_ex
     113             :      * to the specified \p nsec value.
     114             :      *
     115             :      * \param[in] nsec  The nano-seconds to copy to timespec_ex.
     116             :      */
     117          28 :     timespec_ex(std::int64_t nsec)
     118          28 :     {
     119          28 :         set(nsec);
     120          28 :     }
     121             : 
     122             : 
     123             :     /** \brief Initialize a timespec_ex from an double in seconds.
     124             :      *
     125             :      * This constructors allows you to directly set a timespec_ex
     126             :      * to the specified \p sec value.
     127             :      *
     128             :      * \param[in] sec  The seconds to copy to timespec_ex.
     129             :      */
     130          14 :     timespec_ex(double sec)
     131          14 :     {
     132          14 :         set(sec);
     133          14 :     }
     134             : 
     135             : 
     136             :     /** \brief Set the timespec_ex to the specified timespec_ex.
     137             :      *
     138             :      * This function copies the specified timespec_ex (\p t) to this
     139             :      * timespec_ex object.
     140             :      *
     141             :      * \param[in] t  The timespec to copy in this timespec_ex.
     142             :      *
     143             :      * \return A reference to this object.
     144             :      */
     145          47 :     timespec_ex & operator = (timespec_ex t)
     146             :     {
     147          47 :         tv_sec = t.tv_sec;
     148          47 :         tv_nsec = t.tv_nsec;
     149          47 :         return *this;
     150             :     }
     151             : 
     152             : 
     153             :     /** \brief Set the timespec_ex to the specified timespec.
     154             :      *
     155             :      * This function copies the specified timespec to this timespec_ex
     156             :      * object.
     157             :      *
     158             :      * \param[in] t  The timespec to copy in this timespec_ex.
     159             :      *
     160             :      * \return A reference to this object.
     161             :      */
     162           1 :     timespec_ex & operator = (timespec const & t)
     163             :     {
     164           1 :         tv_sec = t.tv_sec;
     165           1 :         tv_nsec = t.tv_nsec;
     166           1 :         return *this;
     167             :     }
     168             : 
     169             : 
     170             :     /** \brief Set the timespec_ex to the number of nanoseconds.
     171             :      *
     172             :      * This function saves the number of nanoseconds in \p nsec as a
     173             :      * tv_sec and tv_nsec representation.
     174             :      *
     175             :      * \param[in] nsec  The nano-seconds to save in this timespec_ex.
     176             :      *
     177             :      * \return A reference to this object.
     178             :      */
     179           1 :     timespec_ex & operator = (std::int64_t nsec)
     180             :     {
     181           1 :         set(nsec);
     182           1 :         return *this;
     183             :     }
     184             : 
     185             : 
     186             :     /** \brief Set this timespec_ex to the number of seconds in \p sec.
     187             :      *
     188             :      * This function transforms the specified double \p sec in a timespec_ex.
     189             :      *
     190             :      * \note
     191             :      * At this time, the number of nanoseconds is floored.
     192             :      *
     193             :      * \param[in] sec  The number of seconds defined in a double.
     194             :      *
     195             :      * \return A reference to this object.
     196             :      */
     197           3 :     timespec_ex & operator = (double sec)
     198             :     {
     199           3 :         set(sec);
     200           3 :         return *this;
     201             :     }
     202             : 
     203             : 
     204             :     /** \brief Set the timespec_ex to the number of nanoseconds.
     205             :      *
     206             :      * This function saves the number of nanoseconds in \p nsec as a
     207             :      * tv_sec and tv_nsec representation.
     208             :      *
     209             :      * \param[in] t  The nano-seconds to save in this timespec_ex.
     210             :      *
     211             :      * \return A reference to this object.
     212             :      */
     213          62 :     void set(timespec_ex const & t)
     214             :     {
     215          62 :         tv_sec = t.tv_sec;
     216          62 :         tv_nsec = t.tv_nsec;
     217          62 :     }
     218             : 
     219             : 
     220             :     /** \brief Set the timespec_ex to the specified timespec.
     221             :      *
     222             :      * This function copies the timespec in \p t in this timespec_ex object.
     223             :      *
     224             :      * \param[in] t  The timespec to save in this timespec_ex.
     225             :      *
     226             :      * \return A reference to this object.
     227             :      */
     228          59 :     void set(timespec const & t)
     229             :     {
     230          59 :         tv_sec = t.tv_sec;
     231          59 :         tv_nsec = t.tv_nsec;
     232          59 :     }
     233             : 
     234             : 
     235             :     /** \brief Set the timespec_ex to the specified values.
     236             :      *
     237             :      * This function allows you to set the timespec_ex to the specified
     238             :      * number of seconds (\p sec) and nano-seconds (\p nsec).
     239             :      *
     240             :      * \param[in] sec  The new number of seconds.
     241             :      * \param[in] nsec  The new number of nano-seconds.
     242             :      */
     243           6 :     void set(time_t sec, long nsec)
     244             :     {
     245           6 :         tv_sec = sec;
     246           6 :         tv_nsec = nsec;
     247           6 :     }
     248             : 
     249             : 
     250             :     /** \brief Set the timespec_ex to the number of nanoseconds.
     251             :      *
     252             :      * This function saves the number of nanoseconds in \p nsec as a
     253             :      * tv_sec and tv_nsec representation.
     254             :      *
     255             :      * \param[in] nsec  The nano-seconds to save in this timespec_ex.
     256             :      *
     257             :      * \return A reference to this object.
     258             :      */
     259          67 :     void set(std::int64_t nsec)
     260             :     {
     261          67 :         bool const neg(nsec < 0);
     262          67 :         if(neg)
     263             :         {
     264           8 :             nsec = -nsec;
     265             :         }
     266          67 :         tv_sec = static_cast<time_t>(nsec / 1'000'000'000LL);
     267          67 :         tv_nsec = static_cast<long>(nsec % 1'000'000'000LL);
     268          67 :         if(neg)
     269             :         {
     270           8 :             *this = -*this;
     271             :         }
     272          67 :     }
     273             : 
     274             : 
     275             :     /** \brief Set this timespec_ex to the number of seconds in \p sec.
     276             :      *
     277             :      * This function transforms the specified double \p sec in a timespec_ex.
     278             :      *
     279             :      * \note
     280             :      * At this time, the number of nanoseconds is floored.
     281             :      *
     282             :      * \param[in] sec  The number of seconds defined in a double.
     283             :      *
     284             :      * \return A reference to this object.
     285             :      */
     286          17 :     void set(double sec)
     287             :     {
     288          17 :         bool const neg(sec < 0.0);
     289          17 :         if(neg)
     290             :         {
     291           1 :             sec = -sec;
     292             :         }
     293          17 :         tv_sec = static_cast<time_t>(floor(sec));
     294          17 :         tv_nsec = static_cast<long>((sec - floor(sec)) * 1.0e9);
     295          17 :         if(neg)
     296             :         {
     297           1 :             *this = -*this;
     298             :         }
     299          17 :     }
     300             : 
     301             :     /** \brief Get system time.
     302             :      *
     303             :      * This function reads the system time and saves it into this
     304             :      * timespec_ex object.
     305             :      *
     306             :      * \todo
     307             :      * Look into whether we want to return an error if clock_gettime()
     308             :      * fails.
     309             :      *
     310             :      * \param[in] clk_id  The type of clock you want to query.
     311             :      *
     312             :      * \return A timespec_ex representing the specified \p clk_id.
     313             :      */
     314           1 :     static timespec_ex gettime(clockid_t clk_id = CLOCK_REALTIME)
     315             :     {
     316           1 :         timespec_ex result;
     317           1 :         clock_gettime(clk_id, &result);
     318           1 :         return result;
     319             :     }
     320             : 
     321             : 
     322             :     /** \brief Extract the timespec_ex as an int64_t value.
     323             :      *
     324             :      * This function transforms a timespec_ex structure in an int64_t
     325             :      * in nanoseconds.
     326             :      *
     327             :      * \return This timespec_ex converted to nanoseconds.
     328             :      */
     329           1 :     std::int64_t to_nsec() const
     330             :     {
     331           1 :         return tv_nsec
     332           1 :              + tv_sec * 1'000'000'000LL;
     333             :     }
     334             : 
     335             : 
     336             :     /** \brief Extract the timespec_ex as a double value.
     337             :      *
     338             :      * This function transforms a timespec_ex structure into a double
     339             :      * in seconds. The nanoseconds are added as one billionth of a
     340             :      * second.
     341             :      *
     342             :      * \return The timespec_ex converted the seconds.
     343             :      */
     344           6 :     double to_sec() const
     345             :     {
     346           6 :         return static_cast<double>(tv_sec)
     347           6 :              + static_cast<double>(tv_nsec) / 1.0e9;
     348             :     }
     349             : 
     350             : 
     351             :     /** \brief Format the date to the specified format.
     352             :      *
     353             :      * This function transforms the time in a string and returns that string.
     354             :      * The function uses the strftime(). See that manual page to define
     355             :      * the format properly.
     356             :      *
     357             :      * Unless you use the `%N` extension, the output will not include the
     358             :      * precision available in the timespec (i.e. without the %N, the output
     359             :      * is to the second, the timespec has nanoseconds available).
     360             :      *
     361             :      * \param[in] format  The format used to transform the date and time in
     362             :      * a string.
     363             :      * \param[in] local  Whether to generate a local time or use UTC.
     364             :      *
     365             :      * \return The formatted date and time.
     366             :      */
     367             :     std::string to_string(std::string const & format = std::string(), bool local = false) const
     368             :     {
     369             :         struct tm date_and_time = {};
     370             :         struct tm * ptr(nullptr);
     371             :         if(local)
     372             :         {
     373             :             ptr = localtime_r(&tv_sec, &date_and_time);
     374             :         }
     375             :         else
     376             :         {
     377             :             ptr = gmtime_r(&tv_sec, &date_and_time);
     378             :         }
     379             :         if(ptr == nullptr)
     380             :         {
     381             :             throw overflow("the specified number of seconds could not be transformed in a 'struct tm'.");
     382             :         }
     383             :         std::string f(format);
     384             :         if(f.empty())
     385             :         {
     386             :             // TODO: actually retrieve the locale() format and
     387             :             //       search for "%T" or "%S" and insert ".%N"
     388             :             //       right after either
     389             :             //
     390             :             f = "%c.%N";
     391             :         }
     392             :         std::string::size_type pos(f.find("%N"));
     393             :         if(pos != std::string::npos)
     394             :         {
     395             :             std::string n(std::to_string(tv_nsec));
     396             :             if(n.length() > 9)
     397             :             {
     398             :                 throw overflow("tv_nsec is 1 billion or more, which is invalid.");
     399             :             }
     400             :             std::string const indent(9 - n.length(), '0');
     401             :             n = indent + n;
     402             :             f = f.substr(0, pos) + n + f.substr(pos + 2);
     403             :         }
     404             :         char buf[256];
     405             :         size_t const sz(strftime(buf, sizeof(buf), f.c_str(), &date_and_time));
     406             :         if(sz == 0)
     407             :         {
     408             :             // this happens with just a "%p" and "wrong locale"
     409             :             // or when the buffer is too small, which should not
     410             :             // be the case unless you add much more than the format
     411             :             // in that string
     412             :             //
     413             :             throw overflow(
     414             :                   "the specified strftime() format \""
     415             :                 + format
     416             :                 + "\" failed.");
     417             :         }
     418             : 
     419             :         return std::string(buf, sz);
     420             :     }
     421             : 
     422             : 
     423             :     /** \brief Validate this timespec_ex structure.
     424             :      *
     425             :      * This function returns true if this timespec_ex structure is considered
     426             :      * valid.
     427             :      *
     428             :      * At this time, the validation consists of verifying that the
     429             :      * nanoseconds is a number between 0 and 1 billion (maximum excluded).
     430             :      *
     431             :      * \note
     432             :      * Negative timespec_ex are represented by a negative tv_sec. The
     433             :      * tv_nsec can never be negative after a valid operation.
     434             :      *
     435             :      * \return true if the timespec_ex is considered valid.
     436             :      */
     437           7 :     bool valid() const
     438             :     {
     439           7 :         return tv_nsec < 1'000'000'000LL;
     440             :     }
     441             : 
     442             : 
     443             :     /** \brief Check whether this timespec_ex is negative.
     444             :      *
     445             :      * This function checks whether the number represents a negative
     446             :      * timespec_ex. This is true if the number of seconds is negative.
     447             :      *
     448             :      * \note
     449             :      * The first negative timespec_ex is { -1, 999,999,999 }.
     450             :      *
     451             :      * \return true if the timespec_ex is considered negative.
     452             :      */
     453          72 :     bool negative() const
     454             :     {
     455          72 :         return tv_sec < 0LL;
     456             :     }
     457             : 
     458             : 
     459             :     /** \brief Add two timespec_ex together.
     460             :      *
     461             :      * This function adds \p rhs to this timespec_ex value and returns a
     462             :      * new timespec_ex with the result. This timespec_ex is not modified.
     463             :      *
     464             :      * \param[in] rhs  The right handside to add to this number.
     465             :      *
     466             :      * \return A new timespec_ex representing the sum of 'this' and rhs.
     467             :      */
     468          33 :     timespec_ex add(timespec_ex const & rhs) const
     469             :     {
     470          33 :         bool const lneg(negative());
     471          33 :         bool const rneg(rhs.negative());
     472             : 
     473          33 :         timespec_ex lp(lneg ? -*this : *this);
     474          33 :         timespec_ex rp(rneg ? -rhs : rhs);
     475             : 
     476          33 :         timespec_ex result;
     477             : 
     478          33 :         switch((lneg ? 1 : 0) + (rneg ? 2 : 0))
     479             :         {
     480          16 :         case 0:     // positive + positive
     481             :         case 3:     // negative + negative
     482          16 :             result.tv_sec = lp.tv_sec + rp.tv_sec;
     483          16 :             result.tv_nsec = lp.tv_nsec + rp.tv_nsec;
     484          16 :             break;
     485             : 
     486           3 :         case 1:     // negative + positive
     487           3 :             result.tv_sec = rp.tv_sec - lp.tv_sec;
     488           3 :             result.tv_nsec = rp.tv_nsec - lp.tv_nsec;
     489           3 :             break;
     490             : 
     491          14 :         case 2:     // positive + negative
     492          14 :             result.tv_sec = lp.tv_sec - rp.tv_sec;
     493          14 :             result.tv_nsec = lp.tv_nsec - rp.tv_nsec;
     494          14 :             break;
     495             : 
     496             :         }
     497             : 
     498          33 :         if(result.tv_nsec < 0)
     499             :         {
     500           4 :             --result.tv_sec;
     501           4 :             result.tv_nsec += 1'000'000'000L;
     502             :         }
     503          29 :         else if(result.tv_nsec >= 1'000'000'000)
     504             :         {
     505           5 :             ++result.tv_sec;
     506           5 :             result.tv_nsec -= 1'000'000'000;
     507             :         }
     508             : 
     509          33 :         if(lneg && rneg)
     510             :         {
     511           2 :             result = -result;
     512             :         }
     513             : 
     514          33 :         return result;
     515             :     }
     516             : 
     517             : 
     518             :     /** \brief Compare two timespec_ex together.
     519             :      *
     520             :      * This function compares two timespecs and determine whether they
     521             :      * are equal (0), 'this' is smaller (-1) or \p rhs is smaller (1).
     522             :      *
     523             :      * \param[in] rhs  The right handside to compare.
     524             :      *
     525             :      * \return -1, 0, or 1 depending on the order between \p lhs and \p rhs.
     526             :      */
     527          97 :     int compare(timespec_ex const & rhs) const
     528             :     {
     529          97 :         if(tv_sec == rhs.tv_sec)
     530             :         {
     531          85 :             return tv_nsec == rhs.tv_nsec
     532         112 :                     ? 0
     533         112 :                     : (tv_nsec < rhs.tv_nsec ? -1 : 1);
     534             :         }
     535             : 
     536          12 :         return tv_sec < rhs.tv_sec ? -1 : 1;
     537             :     }
     538             : 
     539             : 
     540             :     /** \brief Check whether the timespec_ex is zero.
     541             :      *
     542             :      * This function returns true if the timespec_ex represents zero
     543             :      * (i.e. zero seconds and zero nano-seconds).
     544             :      *
     545             :      * \return true if the timespec_ex is zero, false if not zero.
     546             :      */
     547          11 :     bool operator ! ()
     548             :     {
     549          11 :         return tv_sec == 0 && tv_nsec == 0;
     550             :     }
     551             : 
     552             : 
     553             :     /** \brief Add the right handside to this timespec_ex.
     554             :      *
     555             :      * This operator adds the right handside to this object.
     556             :      *
     557             :      * \param[in] rhs  Another timespec_ex to add to this one.
     558             :      *
     559             :      * \return A reference to this timespec_ex object.
     560             :      */
     561          19 :     timespec_ex & operator += (timespec_ex const & rhs)
     562             :     {
     563          19 :         *this = add(rhs);
     564          19 :         return *this;
     565             :     }
     566             : 
     567             : 
     568             :     /** \brief Add 1 nanosecond to this timespec_ex object.
     569             :      *
     570             :      * This function adds exactly one nanonsecond to this timespec_ex
     571             :      * object.
     572             :      *
     573             :      * \return A reference to this timespec_ex object.
     574             :      */
     575           3 :     timespec_ex & operator ++ ()
     576             :     {
     577           3 :         *this += 1L;
     578           3 :         return *this;
     579             :     }
     580             : 
     581             : 
     582             :     /** \brief Add 1 nanosecond to this timespec_ex object.
     583             :      *
     584             :      * This function adds exactly one nanonsecond to this timespec_ex
     585             :      * object and returns the original value.
     586             :      *
     587             :      * \return A copy of this timespec_ex object before the add() occurs.
     588             :      */
     589           1 :     timespec_ex operator ++ (int)
     590             :     {
     591           1 :         timespec_ex result(*this);
     592           1 :         *this += 1L;
     593           1 :         return result;
     594             :     }
     595             : 
     596             : 
     597             :     /** \brief Add two timespec_ex objects and return the result.
     598             :      *
     599             :      * This function computes the addition of this timespec_ex object
     600             :      * and the \p t timespec_ex and returns the result. The inputs
     601             :      * are not modified.
     602             :      *
     603             :      * \param[in] t  The right handside to add to this timespex_ex object.
     604             :      *
     605             :      * \return The sum of the inputs in a new timespec_ex object.
     606             :      */
     607           7 :     timespec_ex operator + (timespec_ex const & t) const
     608             :     {
     609           7 :         timespec_ex result(*this);
     610           7 :         result += t;
     611           7 :         return result;
     612             :     }
     613             : 
     614             : 
     615             :     /** \brief Subtract the right handside from this timespec_ex.
     616             :      *
     617             :      * This operator subtracts the right handside from this object.
     618             :      *
     619             :      * \param[in] rhs  Another timespec_ex to subtract from this one.
     620             :      *
     621             :      * \return A reference to this timespec_ex object.
     622             :      */
     623          14 :     timespec_ex & operator -= (timespec_ex const & rhs)
     624             :     {
     625          14 :         *this = add(-rhs);
     626          14 :         return *this;
     627             :     }
     628             : 
     629             : 
     630             :     /** \brief Subtract 1 nanosecond from timespec_ex object.
     631             :      *
     632             :      * This function subtracts exactly one nanonsecond from this
     633             :      * timespec_ex object.
     634             :      *
     635             :      * \return A reference to this timespec_ex object.
     636             :      */
     637           3 :     timespec_ex & operator -- ()
     638             :     {
     639           3 :         *this -= 1L;
     640           3 :         return *this;
     641             :     }
     642             : 
     643             : 
     644             :     /** \brief Subtract 1 nanosecond from timespec_ex object.
     645             :      *
     646             :      * This function subtracts exactly one nanonsecond from this
     647             :      * timespec_ex object and returns the original value.
     648             :      *
     649             :      * \return A copy of this timespec_ex object before the subtract occurs.
     650             :      */
     651           1 :     timespec_ex operator -- (int)
     652             :     {
     653           1 :         timespec_ex result(*this);
     654           1 :         *this -= 1L;
     655           1 :         return result;
     656             :     }
     657             : 
     658             : 
     659             :     /** \brief Compute the additive opposite of the right handside timespec_ex.
     660             :      *
     661             :      * This function computers the opposite of the right handside timespec_ex
     662             :      * and returns a copy with the result.
     663             :      *
     664             :      * This is equivalent to computing `0 - t`.
     665             :      *
     666             :      * \param[in] t  The right handside time to negate.
     667             :      *
     668             :      * \return A timespec_ex representing the additive opposite of the input.
     669             :      */
     670          49 :     timespec_ex operator - () const
     671             :     {
     672          49 :         timespec_ex result(timespec{ -tv_sec, -tv_nsec });
     673          49 :         if(result.tv_nsec < 0)
     674             :         {
     675          48 :             --result.tv_sec;
     676          48 :             result.tv_nsec += 1'000'000'000L;
     677             :         }
     678          49 :         return result;
     679             :     }
     680             : 
     681             : 
     682             :     /** \brief Subtract \p t from this timespec_ex object.
     683             :      *
     684             :      * This function computes the difference of this timespec_ex object
     685             :      * and the \p t timespec_ex object and returns the result. The inputs
     686             :      * are not modified.
     687             :      *
     688             :      * \param[in] rhs  The right handside to subtract from this timespex_ex
     689             :      * object.
     690             :      *
     691             :      * \return The different of the inputs in a new timespec_ex object.
     692             :      */
     693           6 :     timespec_ex operator - (timespec_ex const & rhs) const
     694             :     {
     695           6 :         timespec_ex result(*this);
     696           6 :         result -= rhs;
     697           6 :         return result;
     698             :     }
     699             : 
     700             : 
     701             :     /** \brief Compare whether the two timespec_ex are equal.
     702             :      *
     703             :      * \param[in] t  The time to compare against.
     704             :      *
     705             :      * \return true if both timespec_ex objects are equal.
     706             :      */
     707          23 :     bool operator == (timespec_ex const & t) const
     708             :     {
     709          23 :         return compare(t) == 0;
     710             :     }
     711             : 
     712             : 
     713             :     /** \brief Compare whether the two timespec_ex are not equal.
     714             :      *
     715             :      * \param[in] t  The time to compare against.
     716             :      *
     717             :      * \return true if both timespec_ex objects are not equal.
     718             :      */
     719          15 :     bool operator != (timespec_ex const & t) const
     720             :     {
     721          15 :         return compare(t) != 0;
     722             :     }
     723             : 
     724             : 
     725             :     /** \brief Compare whether the left handside is smaller.
     726             :      *
     727             :      * \param[in] t  The time to compare against.
     728             :      *
     729             :      * \return true if the left handside timespec_ex object is smaller.
     730             :      */
     731          15 :     bool operator < (timespec_ex const & t) const
     732             :     {
     733          15 :         return compare(t) == -1;
     734             :     }
     735             : 
     736             : 
     737             :     /** \brief Compare whether the left handside is smaller or equal.
     738             :      *
     739             :      * \param[in] t  The time to compare against.
     740             :      *
     741             :      * \return true if the left handside timespec_ex object is smaller
     742             :      * or equal.
     743             :      */
     744          15 :     bool operator <= (timespec_ex const & t) const
     745             :     {
     746          15 :         return compare(t) <= 0;
     747             :     }
     748             : 
     749             : 
     750             :     /** \brief Compare whether the left handside is larger.
     751             :      *
     752             :      * \param[in] t  The time to compare against.
     753             :      *
     754             :      * \return true if the left handside timespec_ex object is larger.
     755             :      */
     756          14 :     bool operator > (timespec_ex const & t) const
     757             :     {
     758          14 :         return compare(t) == 1;
     759             :     }
     760             : 
     761             : 
     762             :     /** \brief Compare whether the left handside is larger or equal.
     763             :      *
     764             :      * \param[in] t  The time to compare against.
     765             :      *
     766             :      * \return true if the left handside timespec_ex object is larger
     767             :      * or equal.
     768             :      */
     769          15 :     bool operator >= (timespec_ex const & t) const
     770             :     {
     771          15 :         return compare(t) >= 0;
     772             :     }
     773             : };
     774             : 
     775             : 
     776             : 
     777             : 
     778             : 
     779             : 
     780             : 
     781             : /** \brief Output a timespec to a basic_ostream.
     782             :  *
     783             :  * This function allows one to print out a timespec. By default the function
     784             :  * prints the timespec as a floating point.
     785             :  *
     786             :  * \todo
     787             :  * Look into the possibility to write the data as Y/M/D H:M:S.nanosecs
     788             :  *
     789             :  * \param[in] out  The output stream where the timespec gets written.
     790             :  * \param[in] t  The actual timespec that is to be printed.
     791             :  *
     792             :  * \return A reference to the basic_ostream object.
     793             :  */
     794             : template<typename CharT, typename Traits>
     795           3 : std::basic_ostream<CharT, Traits> & operator << (std::basic_ostream<CharT, Traits> & out, timespec const & t)
     796             : {
     797             :     // write to a string buffer first
     798             :     //
     799           6 :     std::basic_ostringstream<CharT, Traits, std::allocator<CharT> > s;
     800             : 
     801             :     // setup the string output like the out stream
     802             :     //
     803           3 :     s.flags(out.flags());
     804           3 :     s.imbue(out.getloc());
     805           3 :     s.precision(out.precision());
     806           3 :     s << t.tv_sec << "." << std::setw(9) << std::setfill('0') << t.tv_nsec;
     807             : 
     808             :     // buffer is ready, display in output in one go
     809             :     //
     810           6 :     return out << s.str();
     811             : }
     812             : 
     813             : 
     814             : } // namespace snapdev
     815             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.13