xref: /netbsd-src/external/ibm-public/postfix/dist/src/util/timecmp.c (revision e89934bbf778a6d6d6894877c4da59d0c7835b0f)
1*e89934bbSchristos /*	$NetBSD: timecmp.c,v 1.2 2017/02/14 01:16:49 christos Exp $	*/
216d67a18Stron 
316d67a18Stron /*++
416d67a18Stron /* NAME
516d67a18Stron /*	timecmp 3
616d67a18Stron /* SUMMARY
716d67a18Stron /*	compare two time_t values
816d67a18Stron /* SYNOPSIS
916d67a18Stron /*	#include <timecmp.h>
1016d67a18Stron /*
1116d67a18Stron /*	int	timecmp(t1, t2)
1216d67a18Stron /*	time_t	t1;
1316d67a18Stron /*	time_t	t2;
1416d67a18Stron /* DESCRIPTION
1516d67a18Stron /*	The timecmp() function return an integer greater than, equal to, or
1616d67a18Stron /*	less than 0, according as the time t1 is greater than, equal to, or
1716d67a18Stron /*	less than the time t2.  The comparison is made in a manner that is
1816d67a18Stron /*	insensitive to clock wrap-around, provided the underlying times are
1916d67a18Stron /*	within half of the time interval between the smallest and largest
2016d67a18Stron /*	representable time values.
2116d67a18Stron /* LICENSE
2216d67a18Stron /* .ad
2316d67a18Stron /* .fi
2416d67a18Stron /*	The Secure Mailer license must be distributed with this software.
2516d67a18Stron /* AUTHOR(S)
2616d67a18Stron /*	Wietse Venema
2716d67a18Stron /*	IBM T.J. Watson Research
2816d67a18Stron /*	P.O. Box 704
2916d67a18Stron /*	Yorktown Heights, NY 10598, USA
3016d67a18Stron /*
3116d67a18Stron /*	Viktor Dukhovni
3216d67a18Stron /*--*/
3316d67a18Stron 
3416d67a18Stron #include "timecmp.h"
3516d67a18Stron 
3616d67a18Stron /* timecmp - wrap-safe time_t comparison */
3716d67a18Stron 
timecmp(time_t t1,time_t t2)3816d67a18Stron int     timecmp(time_t t1, time_t t2)
3916d67a18Stron {
4016d67a18Stron     time_t  delta = t1 - t2;
4116d67a18Stron 
4216d67a18Stron     if (delta == 0)
4316d67a18Stron 	return 0;
4416d67a18Stron 
4516d67a18Stron #define UNSIGNED(type) ( ((type)-1) > ((type)0) )
4616d67a18Stron 
4716d67a18Stron     /*
4816d67a18Stron      * With a constant switch value, the compiler will emit only the code for
4916d67a18Stron      * the correct case, so the signed/unsigned test happens at compile time.
5016d67a18Stron      */
5116d67a18Stron     switch (UNSIGNED(time_t) ? 0 : 1) {
5216d67a18Stron     case 0:
5316d67a18Stron 	return ((2 * delta > delta) ? 1 : -1);
5416d67a18Stron     case 1:
5516d67a18Stron 	return ((delta > (time_t) 0) ? 1 : -1);
5616d67a18Stron     }
5716d67a18Stron }
5816d67a18Stron 
5916d67a18Stron #ifdef TEST
6016d67a18Stron #include <assert.h>
6116d67a18Stron 
6216d67a18Stron  /*
6316d67a18Stron   * Bit banging!! There is no official constant that defines the INT_MAX
6416d67a18Stron   * equivalent of the off_t type. Wietse came up with the following macro
6516d67a18Stron   * that works as long as off_t is some two's complement number.
6616d67a18Stron   *
6716d67a18Stron   * Note, however, that C99 permits signed integer representations other than
6816d67a18Stron   * two's complement.
6916d67a18Stron   */
7016d67a18Stron #include <limits.h>
7116d67a18Stron #define __MAXINT__(T) ((T) (((((T) 1) << ((sizeof(T) * CHAR_BIT) - 1)) ^ ((T) -1))))
7216d67a18Stron 
main(void)73e262b48eSchristos int     main(void)
7416d67a18Stron {
7516d67a18Stron     time_t  now = time((time_t *) 0);
7616d67a18Stron 
7716d67a18Stron     /* Test that it works for normal times */
7816d67a18Stron     assert(timecmp(now + 10, now) > 0);
7916d67a18Stron     assert(timecmp(now, now) == 0);
8016d67a18Stron     assert(timecmp(now - 10, now) < 0);
8116d67a18Stron 
8216d67a18Stron     /* Test that it works at a boundary time */
8316d67a18Stron     if (UNSIGNED(time_t))
8416d67a18Stron 	now = (time_t) -1;
8516d67a18Stron     else
8616d67a18Stron 	now = __MAXINT__(time_t);
8716d67a18Stron 
8816d67a18Stron     assert(timecmp(now + 10, now) > 0);
8916d67a18Stron     assert(timecmp(now, now) == 0);
9016d67a18Stron     assert(timecmp(now - 10, now) < 0);
9116d67a18Stron 
9216d67a18Stron     return (0);
9316d67a18Stron }
9416d67a18Stron 
9516d67a18Stron #endif
96