/*
 * Copyright (c) 2002-2005 Sendmail, Inc. and its suppliers.
 *      All rights reserved.
 *
 * By using this file, you agree to the terms and conditions set
 * forth in the LICENSE file which can be found at the top level of
 * the sendmail distribution.
 *
 *	$Id: time.h,v 1.23 2006/12/10 20:55:59 ca Exp $
 */

#ifndef SM_TIME_H
#define SM_TIME_H 1

#include "sm/generic.h"

#if TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else /* TIME_WITH_SYS_TIME */
# if HAVE_SYS_TIME_H
#  include <sys/time.h>
# else
#  include <time.h>
# endif
#endif /* TIME_WITH_SYS_TIME */

/* required by arpadate() prototype */
#include "sm/str.h"

/* should be defined in sys/time.h */
#ifndef timersub
# define timersub(tvp, uvp, res)					\
	do								\
	{								\
		(res)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec;		\
		(res)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec;	\
		if ((res)->tv_usec < 0)					\
		{							\
			(res)->tv_sec--;				\
			(res)->tv_usec += 1000000;			\
		}							\
	} while (0)
#endif /* ! timersub */

#ifndef timeradd
# define timeradd(tvp, uvp, res)					\
	do								\
	{								\
		(res)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec;		\
		(res)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec;	\
		if ((res)->tv_usec >= 1000000)				\
		{							\
			(res)->tv_sec++;				\
			(res)->tv_usec -= 1000000;			\
		}							\
	} while (0)
#endif /* ! timeradd */

#ifndef timercmp
# define timercmp(tvp, uvp, cmp)					\
	(((tvp)->tv_sec == (uvp)->tv_sec) ?				\
	    ((tvp)->tv_usec cmp (uvp)->tv_usec) :			\
	    ((tvp)->tv_sec cmp (uvp)->tv_sec))
#endif /* ! timercmp */

/* some people are clueless and define this without do { } while (0) */
#define SM_TIMEVAL_TO_TIMESPEC(tv, ts)					\
	do {								\
		(ts)->tv_sec = (tv)->tv_sec;				\
		(ts)->tv_nsec = (tv)->tv_usec * 1000;			\
	} while (0)

#define SM_TIMESPEC_TO_TIMEVAL(tv, ts)					\
	do {								\
		(tv)->tv_sec = (ts)->tv_sec;				\
		(tv)->tv_usec = (ts)->tv_nsec / 1000;			\
	} while (0)

#ifndef timespecclear
# define timespecclear(tsp)	(tsp)->tv_sec = (tsp)->tv_nsec = 0
#endif

#ifndef timespeccmp
# define timespeccmp(tvp, uvp, cmp)				\
	(((tvp)->tv_sec == (uvp)->tv_sec) ?				\
	    ((tvp)->tv_nsec cmp (uvp)->tv_nsec) :			\
	    ((tvp)->tv_sec cmp (uvp)->tv_sec))
#endif

/* FreeBSD and OpenBSD don't agree on number of arguments... */
#define sm_timespecadd(tsp, usp, res)					\
	do {								\
		(res)->tv_sec = (tsp)->tv_sec + (usp)->tv_sec;		\
		(res)->tv_nsec = (tsp)->tv_nsec + (usp)->tv_nsec;	\
		if ((res)->tv_nsec >= 1000000000L) {			\
			(res)->tv_sec++;				\
			(res)->tv_nsec -= 1000000000L;			\
		}							\
	} while (0)

#define sm_timespecsub(tsp, usp, res)					\
	do {								\
		(res)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec;		\
		(res)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec;	\
		if ((res)->tv_nsec < 0) {				\
			(res)->tv_sec--;				\
			(res)->tv_nsec += 1000000000L;			\
		}							\
	} while (0)

typedef struct timeval	timeval_T, *timeval_P;
typedef time_t time_T;
typedef struct timespec	timespec_T, *timespec_P;

/* fixme: rename this to something more intuitive! */
#define NULLT	((time_T *)0)

#if SIZEOF_TIME_T == 4
# define TIME_T_MAX	((time_T)INT_MAX)
#elif SIZEOF_TIME_T == 8
# define TIME_T_MAX	((time_T)LONG_MAX)
#else
oops _SIZEOF_TIME_T is neither 4 nor 8
#endif /* SIZEOF_TIME_T == 4 */

#define sm_usleep(s, us, tv)	(			\
		tv.tv_sec = (s),			\
		tv.tv_usec = (us),			\
		select(0, NULL, NULL, NULL, &tv)	\
	)

#define SEC2USEC(s) ((s)*1000000LL)
#define SEC2NSEC(s) ((s)*1000000000LL)

#if HAVE_GETHRTIME
#  define MTA_NS_TIME(ns) ns = gethrtime()
#elif HAVE_CLOCK_GETTIME
# ifndef CLOCK_MONOTONIC
#  define CLOCK_MONOTONIC CLOCK_REALTIME
#endif
# define MTA_NS_TIME(ns) do { \
		struct timespec tsr; \
		(void) clock_gettime(CLOCK_MONOTONIC, &tsr); \
		ns = SEC2NSEC((uint64_t)tsr.tv_sec) + (uint64_t)tsr.tv_nsec; \
	} while (0)
#endif

sm_ret_T arpadate(time_t *_when, sm_str_P _udate);

#if HAVE_STRPTIME && NEED_STRPTIME_PROTO
char *strptime(const char *_s, const char *_format, struct tm *_tm);
#endif

#endif /* SM_TIME_H */


syntax highlighted by Code2HTML, v. 0.9.1