
#include <sys/time.h>
#include <unistd.h>
#include <time.h>

#include "ixtime.h"

void
timeval_add (struct timeval *res, struct timeval *t1, struct timeval *t2)
{
   res->tv_sec = t1->tv_sec + t2->tv_sec;
   res->tv_usec = t1->tv_usec + t2->tv_usec;

   res->tv_sec += res->tv_usec / 1000000L;

   res->tv_usec %= 1000000L;
}

void
timespec_add (struct timespec *res, struct timespec *t1, struct timespec *t2)
{
   res->tv_sec = t1->tv_sec + t2->tv_sec;
   res->tv_nsec = t1->tv_nsec + t2->tv_nsec;

   res->tv_sec += res->tv_nsec / 1000000000L;

   res->tv_nsec %= 1000000000L;
}

/* Subtract the `struct timeval' values X and Y,
 *    storing the result in RESULT.
 *       Return 1 if the difference is negative, otherwise 0.  */

/* ripped from some GNU webpage
 * http://www.gnu.org/manual/glibc-2.2.3/html_node/libc_418.html
 */

int
timeval_subtract (result, x, y)
        struct timeval *result, *x, *y;
{
   /* Perform the carry for the later subtraction by updating y. */
   if (x->tv_usec < y->tv_usec) {
      int nsec = (y->tv_usec - x->tv_usec) / 1000000L + 1;
      y->tv_usec -= 1000000L * nsec;
      y->tv_sec += nsec;
   }
   if (x->tv_usec - y->tv_usec > 1000000L) {
      int nsec = (x->tv_usec - y->tv_usec) / 1000000L;
      y->tv_usec += 1000000L * nsec;
      y->tv_sec -= nsec;
   }

   /* Compute the time remaining to wait.
    *      tv_usec is certainly positive. */
   result->tv_sec = x->tv_sec - y->tv_sec;
   result->tv_usec = x->tv_usec - y->tv_usec;

   /* Return 1 if result is negative. */
   return x->tv_sec < y->tv_sec;
}

int
timespec_subtract (struct timespec *result, struct timespec *x, struct timespec *y)
{
   /* Perform the carry for the later subtraction by updating y. */
   if (x->tv_nsec < y->tv_nsec) {
      int nsec = (y->tv_nsec - x->tv_nsec) / 1000000000L + 1;
      y->tv_nsec -= 1000000000L * nsec;
      y->tv_sec += nsec;
   }
   if (x->tv_nsec - y->tv_nsec > 1000000000L) {
      int nsec = (x->tv_nsec - y->tv_nsec) / 1000000000L;
      y->tv_nsec += 1000000 * nsec;
      y->tv_sec -= nsec;
   }

   /* Compute the time remaining to wait.
    *      tv_nsec is certainly positive. */
   result->tv_sec = x->tv_sec - y->tv_sec;
   result->tv_nsec = x->tv_nsec - y->tv_nsec;

   /* Return 1 if result is negative. */
   return x->tv_sec < y->tv_sec;
}

long
timeval_to_ms (struct timeval *tv)
{
   return (tv->tv_sec * 1000 + tv->tv_usec / 1000);
}
