dhcpcd: Update README.DRAGONFLY for 10.0.2
[dragonfly.git] / contrib / ldns / duration.c
blobabff9a074fc34b4c9b26b826e0b76c0f5291b372
1 /*
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
8 * are met:
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.
29 /**
31 * This file is copied from the OpenDNSSEC source repository
32 * and only slightly adapted to make it fit.
35 /**
37 * Durations.
40 #include <ldns/config.h>
41 #include <ldns/duration.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <time.h>
49 /**
50 * Create a new 'instant' duration.
53 ldns_duration_type*
54 ldns_duration_create(void)
56 ldns_duration_type* duration;
58 duration = malloc(sizeof(ldns_duration_type));
59 if (!duration) {
60 return NULL;
62 duration->years = 0;
63 duration->months = 0;
64 duration->weeks = 0;
65 duration->days = 0;
66 duration->hours = 0;
67 duration->minutes = 0;
68 duration->seconds = 0;
69 return duration;
73 /**
74 * Compare durations.
77 int
78 ldns_duration_compare(const ldns_duration_type* d1, const ldns_duration_type* d2)
80 if (!d1 && !d2) {
81 return 0;
83 if (!d1 || !d2) {
84 return d1?-1:1;
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);
109 return 0;
114 * Create a duration from string.
117 ldns_duration_type*
118 ldns_duration_create_from_string(const char* str)
120 ldns_duration_type* duration = ldns_duration_create();
121 char* P, *X, *T, *W;
122 int not_weeks = 0;
124 if (!duration) {
125 return NULL;
127 if (!str) {
128 return duration;
131 P = strchr(str, 'P');
132 if (!P) {
133 ldns_duration_cleanup(duration);
134 return NULL;
137 T = strchr(str, 'T');
138 X = strchr(str, 'Y');
139 if (X) {
140 duration->years = (time_t) atoi(str+1);
141 str = X;
142 not_weeks = 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);
147 str = X;
148 not_weeks = 1;
150 X = strchr(str, 'D');
151 if (X) {
152 duration->days = (time_t) atoi(str+1);
153 str = X;
154 not_weeks = 1;
156 if (T) {
157 str = T;
158 not_weeks = 1;
160 X = strchr(str, 'H');
161 if (X && T) {
162 duration->hours = (time_t) atoi(str+1);
163 str = X;
164 not_weeks = 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);
169 str = X;
170 not_weeks = 1;
172 X = strchr(str, 'S');
173 if (X && T) {
174 duration->seconds = (time_t) atoi(str+1);
175 str = X;
176 not_weeks = 1;
179 W = strchr(str, 'W');
180 if (W) {
181 if (not_weeks) {
182 ldns_duration_cleanup(duration);
183 return NULL;
184 } else {
185 duration->weeks = (time_t) atoi(str+1);
188 return duration;
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)
198 if (t > 0) {
199 int r = snprintf(*buf, eob - *buf, "%u%c", (unsigned)t, c);
200 if (r < 0 || (*buf += r) >= eob)
201 return -1;
203 return 0;
207 * Convert a duration to a string.
210 char*
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;
218 if (!d)
219 return NULL;
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))
225 return NULL;
227 if (d->hours || d->minutes || d->seconds) {
228 if (p > (eob - 2))
229 return NULL; /* Error; no space left on buf for 'T' */
231 *p++ = 'T'; *p = 0;
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))
235 return NULL;
237 return strdup(buf);
242 * Convert a duration to a time.
245 time_t
246 ldns_duration2time(const ldns_duration_type* duration)
248 time_t period = 0;
250 if (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) {
265 return period;
270 * Clean up duration.
273 void
274 ldns_duration_cleanup(ldns_duration_type* duration)
276 if (!duration) {
277 return;
279 free(duration);
280 return;