xref: /netbsd-src/external/ibm-public/postfix/dist/src/util/timecmp.c (revision e89934bbf778a6d6d6894877c4da59d0c7835b0f)
1 /*	$NetBSD: timecmp.c,v 1.2 2017/02/14 01:16:49 christos Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	timecmp 3
6 /* SUMMARY
7 /*	compare two time_t values
8 /* SYNOPSIS
9 /*	#include <timecmp.h>
10 /*
11 /*	int	timecmp(t1, t2)
12 /*	time_t	t1;
13 /*	time_t	t2;
14 /* DESCRIPTION
15 /*	The timecmp() function return an integer greater than, equal to, or
16 /*	less than 0, according as the time t1 is greater than, equal to, or
17 /*	less than the time t2.  The comparison is made in a manner that is
18 /*	insensitive to clock wrap-around, provided the underlying times are
19 /*	within half of the time interval between the smallest and largest
20 /*	representable time values.
21 /* LICENSE
22 /* .ad
23 /* .fi
24 /*	The Secure Mailer license must be distributed with this software.
25 /* AUTHOR(S)
26 /*	Wietse Venema
27 /*	IBM T.J. Watson Research
28 /*	P.O. Box 704
29 /*	Yorktown Heights, NY 10598, USA
30 /*
31 /*	Viktor Dukhovni
32 /*--*/
33 
34 #include "timecmp.h"
35 
36 /* timecmp - wrap-safe time_t comparison */
37 
timecmp(time_t t1,time_t t2)38 int     timecmp(time_t t1, time_t t2)
39 {
40     time_t  delta = t1 - t2;
41 
42     if (delta == 0)
43 	return 0;
44 
45 #define UNSIGNED(type) ( ((type)-1) > ((type)0) )
46 
47     /*
48      * With a constant switch value, the compiler will emit only the code for
49      * the correct case, so the signed/unsigned test happens at compile time.
50      */
51     switch (UNSIGNED(time_t) ? 0 : 1) {
52     case 0:
53 	return ((2 * delta > delta) ? 1 : -1);
54     case 1:
55 	return ((delta > (time_t) 0) ? 1 : -1);
56     }
57 }
58 
59 #ifdef TEST
60 #include <assert.h>
61 
62  /*
63   * Bit banging!! There is no official constant that defines the INT_MAX
64   * equivalent of the off_t type. Wietse came up with the following macro
65   * that works as long as off_t is some two's complement number.
66   *
67   * Note, however, that C99 permits signed integer representations other than
68   * two's complement.
69   */
70 #include <limits.h>
71 #define __MAXINT__(T) ((T) (((((T) 1) << ((sizeof(T) * CHAR_BIT) - 1)) ^ ((T) -1))))
72 
main(void)73 int     main(void)
74 {
75     time_t  now = time((time_t *) 0);
76 
77     /* Test that it works for normal times */
78     assert(timecmp(now + 10, now) > 0);
79     assert(timecmp(now, now) == 0);
80     assert(timecmp(now - 10, now) < 0);
81 
82     /* Test that it works at a boundary time */
83     if (UNSIGNED(time_t))
84 	now = (time_t) -1;
85     else
86 	now = __MAXINT__(time_t);
87 
88     assert(timecmp(now + 10, now) > 0);
89     assert(timecmp(now, now) == 0);
90     assert(timecmp(now - 10, now) < 0);
91 
92     return (0);
93 }
94 
95 #endif
96