2 * $Id: duration.c 4518 2011-02-24 15:39:09Z matthijs $
4 * Copyright (c) 2009 NLNet Labs. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
21 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
23 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
25 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 * This file is copied from the OpenDNSSEC source repository
32 * and only slightly adapted to make it fit.
40 #include <ldns/config.h>
41 #include <ldns/duration.h>
50 * Create a new 'instant' duration.
54 ldns_duration_create(void)
56 ldns_duration_type
* duration
;
58 duration
= malloc(sizeof(ldns_duration_type
));
67 duration
->minutes
= 0;
68 duration
->seconds
= 0;
78 ldns_duration_compare(const ldns_duration_type
* d1
, const ldns_duration_type
* d2
)
87 if (d1
->years
!= d2
->years
) {
88 return (int) (d1
->years
- d2
->years
);
90 if (d1
->months
!= d2
->months
) {
91 return (int) (d1
->months
- d2
->months
);
93 if (d1
->weeks
!= d2
->weeks
) {
94 return (int) (d1
->weeks
- d2
->weeks
);
96 if (d1
->days
!= d2
->days
) {
97 return (int) (d1
->days
- d2
->days
);
99 if (d1
->hours
!= d2
->hours
) {
100 return (int) (d1
->hours
- d2
->hours
);
102 if (d1
->minutes
!= d2
->minutes
) {
103 return (int) (d1
->minutes
- d2
->minutes
);
105 if (d1
->seconds
!= d2
->seconds
) {
106 return (int) (d1
->seconds
- d2
->seconds
);
114 * Create a duration from string.
118 ldns_duration_create_from_string(const char* str
)
120 ldns_duration_type
* duration
= ldns_duration_create();
131 P
= strchr(str
, 'P');
133 ldns_duration_cleanup(duration
);
137 T
= strchr(str
, 'T');
138 X
= strchr(str
, 'Y');
140 duration
->years
= (time_t) atoi(str
+1);
144 X
= strchr(str
, 'M');
145 if (X
&& (!T
|| (size_t) (X
-P
) < (size_t) (T
-P
))) {
146 duration
->months
= (time_t) atoi(str
+1);
150 X
= strchr(str
, 'D');
152 duration
->days
= (time_t) atoi(str
+1);
160 X
= strchr(str
, 'H');
162 duration
->hours
= (time_t) atoi(str
+1);
166 X
= strrchr(str
, 'M');
167 if (X
&& T
&& (size_t) (X
-P
) > (size_t) (T
-P
)) {
168 duration
->minutes
= (time_t) atoi(str
+1);
172 X
= strchr(str
, 'S');
174 duration
->seconds
= (time_t) atoi(str
+1);
179 W
= strchr(str
, 'W');
182 ldns_duration_cleanup(duration
);
185 duration
->weeks
= (time_t) atoi(str
+1);
193 * Helper func for ldns_duration2string below. If t > 0,
194 * scan print t and c on buf, forwarding buf. Return 0 on success.
196 static inline int dur_scan_print(char **buf
, char *eob
, char c
, time_t t
)
199 int r
= snprintf(*buf
, eob
- *buf
, "%u%c", (unsigned)t
, c
);
200 if (r
< 0 || (*buf
+= r
) >= eob
)
207 * Convert a duration to a string.
211 ldns_duration2string(const ldns_duration_type
* d
)
213 /* Max string size should be 7 * 40 + 3 on a 127 bits machine
214 * So 300 (< 273) is more than enough.
216 char buf
[300] = "P0D", *eob
= buf
+ sizeof(buf
), *p
= buf
+ 1;
221 if (dur_scan_print(&p
, eob
, 'Y', d
->years
)
222 || dur_scan_print(&p
, eob
, 'M', d
->months
)
223 || dur_scan_print(&p
, eob
, 'W', d
->weeks
)
224 || dur_scan_print(&p
, eob
, 'D', d
->days
))
227 if (d
->hours
|| d
->minutes
|| d
->seconds
) {
229 return NULL
; /* Error; no space left on buf for 'T' */
232 if (dur_scan_print(&p
, eob
, 'H', d
->hours
)
233 || dur_scan_print(&p
, eob
, 'M', d
->minutes
)
234 || dur_scan_print(&p
, eob
, 'S', d
->seconds
))
242 * Convert a duration to a time.
246 ldns_duration2time(const ldns_duration_type
* duration
)
251 period
+= (duration
->seconds
);
252 period
+= (duration
->minutes
)*60;
253 period
+= (duration
->hours
)*3600;
254 period
+= (duration
->days
)*86400;
255 period
+= (duration
->weeks
)*86400*7;
256 period
+= (duration
->months
)*86400*31;
257 period
+= (duration
->years
)*86400*365;
259 /* [TODO] calculate correct number of days in this month/year */
261 if (duration->months || duration->years) {
274 ldns_duration_cleanup(ldns_duration_type
* duration
)