File Coverage

src/ldns/duration.c
Criterion Covered Total %
statement 0 181 0.0
branch 0 102 0.0
condition n/a
subroutine n/a
pod n/a
total 0 283 0.0


line stmt bran cond sub pod time code
1             /*
2             * $Id: duration.c 4518 2011-02-24 15:39:09Z matthijs $
3             *
4             * Copyright (c) 2009 NLNet Labs. All rights reserved.
5             *
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.
14             *
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.
26             *
27             */
28              
29             /**
30             *
31             * This file is copied from the OpenDNSSEC source repository
32             * and only slightly adapted to make it fit.
33             */
34              
35             /**
36             *
37             * Durations.
38             */
39              
40             #include
41             #include
42              
43             #include
44             #include
45             #include
46             #include
47              
48              
49             /**
50             * Create a new 'instant' duration.
51             *
52             */
53             ldns_duration_type*
54 0           ldns_duration_create(void)
55             {
56             ldns_duration_type* duration;
57              
58 0           duration = malloc(sizeof(ldns_duration_type));
59 0 0         if (!duration) {
60 0           return NULL;
61             }
62 0           duration->years = 0;
63 0           duration->months = 0;
64 0           duration->weeks = 0;
65 0           duration->days = 0;
66 0           duration->hours = 0;
67 0           duration->minutes = 0;
68 0           duration->seconds = 0;
69 0           return duration;
70             }
71              
72              
73             /**
74             * Compare durations.
75             *
76             */
77             int
78 0           ldns_duration_compare(ldns_duration_type* d1, ldns_duration_type* d2)
79             {
80 0 0         if (!d1 && !d2) {
    0          
81 0           return 0;
82             }
83 0 0         if (!d1 || !d2) {
    0          
84 0 0         return d1?-1:1;
85             }
86              
87 0 0         if (d1->years != d2->years) {
88 0           return (int) (d1->years - d2->years);
89             }
90 0 0         if (d1->months != d2->months) {
91 0           return (int) (d1->months - d2->months);
92             }
93 0 0         if (d1->weeks != d2->weeks) {
94 0           return (int) (d1->weeks - d2->weeks);
95             }
96 0 0         if (d1->days != d2->days) {
97 0           return (int) (d1->days - d2->days);
98             }
99 0 0         if (d1->hours != d2->hours) {
100 0           return (int) (d1->hours - d2->hours);
101             }
102 0 0         if (d1->minutes != d2->minutes) {
103 0           return (int) (d1->minutes - d2->minutes);
104             }
105 0 0         if (d1->seconds != d2->seconds) {
106 0           return (int) (d1->seconds - d2->seconds);
107             }
108              
109 0           return 0;
110             }
111              
112              
113             /**
114             * Create a duration from string.
115             *
116             */
117             ldns_duration_type*
118 0           ldns_duration_create_from_string(const char* str)
119             {
120 0           ldns_duration_type* duration = ldns_duration_create();
121             char* P, *X, *T, *W;
122 0           int not_weeks = 0;
123              
124 0 0         if (!duration) {
125 0           return NULL;
126             }
127 0 0         if (!str) {
128 0           return duration;
129             }
130              
131 0           P = strchr(str, 'P');
132 0 0         if (!P) {
133 0           ldns_duration_cleanup(duration);
134 0           return NULL;
135             }
136              
137 0           T = strchr(str, 'T');
138 0           X = strchr(str, 'Y');
139 0 0         if (X) {
140 0           duration->years = (time_t) atoi(str+1);
141 0           str = X;
142 0           not_weeks = 1;
143             }
144 0           X = strchr(str, 'M');
145 0 0         if (X && (!T || (size_t) (X-P) < (size_t) (T-P))) {
    0          
    0          
146 0           duration->months = (time_t) atoi(str+1);
147 0           str = X;
148 0           not_weeks = 1;
149             }
150 0           X = strchr(str, 'D');
151 0 0         if (X) {
152 0           duration->days = (time_t) atoi(str+1);
153 0           str = X;
154 0           not_weeks = 1;
155             }
156 0 0         if (T) {
157 0           str = T;
158 0           not_weeks = 1;
159             }
160 0           X = strchr(str, 'H');
161 0 0         if (X && T) {
    0          
162 0           duration->hours = (time_t) atoi(str+1);
163 0           str = X;
164 0           not_weeks = 1;
165             }
166 0           X = strrchr(str, 'M');
167 0 0         if (X && T && (size_t) (X-P) > (size_t) (T-P)) {
    0          
    0          
168 0           duration->minutes = (time_t) atoi(str+1);
169 0           str = X;
170 0           not_weeks = 1;
171             }
172 0           X = strchr(str, 'S');
173 0 0         if (X && T) {
    0          
174 0           duration->seconds = (time_t) atoi(str+1);
175 0           str = X;
176 0           not_weeks = 1;
177             }
178              
179 0           W = strchr(str, 'W');
180 0 0         if (W) {
181 0 0         if (not_weeks) {
182 0           ldns_duration_cleanup(duration);
183 0           return NULL;
184             } else {
185 0           duration->weeks = (time_t) atoi(str+1);
186 0           str = W;
187             }
188             }
189 0           return duration;
190             }
191              
192              
193             /**
194             * Get the number of digits in a number.
195             *
196             */
197             static size_t
198 0           digits_in_number(time_t duration)
199             {
200 0           uint32_t period = (uint32_t) duration;
201 0           size_t count = 0;
202              
203 0 0         while (period > 0) {
204 0           count++;
205 0           period /= 10;
206             }
207 0           return count;
208             }
209              
210              
211             /**
212             * Convert a duration to a string.
213             *
214             */
215             char*
216 0           ldns_duration2string(ldns_duration_type* duration)
217             {
218 0           char* str = NULL, *num = NULL;
219 0           size_t count = 2;
220 0           int T = 0;
221              
222 0 0         if (!duration) {
223 0           return NULL;
224             }
225              
226 0 0         if (duration->years > 0) {
227 0           count = count + 1 + digits_in_number(duration->years);
228             }
229 0 0         if (duration->months > 0) {
230 0           count = count + 1 + digits_in_number(duration->months);
231             }
232 0 0         if (duration->weeks > 0) {
233 0           count = count + 1 + digits_in_number(duration->weeks);
234             }
235 0 0         if (duration->days > 0) {
236 0           count = count + 1 + digits_in_number(duration->days);
237             }
238 0 0         if (duration->hours > 0) {
239 0           count = count + 1 + digits_in_number(duration->hours);
240 0           T = 1;
241             }
242 0 0         if (duration->minutes > 0) {
243 0           count = count + 1 + digits_in_number(duration->minutes);
244 0           T = 1;
245             }
246 0 0         if (duration->seconds > 0) {
247 0           count = count + 1 + digits_in_number(duration->seconds);
248 0           T = 1;
249             }
250 0 0         if (T) {
251 0           count++;
252             }
253              
254 0           str = (char*) calloc(count, sizeof(char));
255 0           str[0] = 'P';
256 0           str[1] = '\0';
257              
258 0 0         if (duration->years > 0) {
259 0           count = digits_in_number(duration->years);
260 0           num = (char*) calloc(count+2, sizeof(char));
261 0           snprintf(num, count+2, "%uY", (unsigned int) duration->years);
262 0           str = strncat(str, num, count+2);
263 0           free((void*) num);
264             }
265 0 0         if (duration->months > 0) {
266 0           count = digits_in_number(duration->months);
267 0           num = (char*) calloc(count+2, sizeof(char));
268 0           snprintf(num, count+2, "%uM", (unsigned int) duration->months);
269 0           str = strncat(str, num, count+2);
270 0           free((void*) num);
271             }
272 0 0         if (duration->weeks > 0) {
273 0           count = digits_in_number(duration->weeks);
274 0           num = (char*) calloc(count+2, sizeof(char));
275 0           snprintf(num, count+2, "%uW", (unsigned int) duration->weeks);
276 0           str = strncat(str, num, count+2);
277 0           free((void*) num);
278             }
279 0 0         if (duration->days > 0) {
280 0           count = digits_in_number(duration->days);
281 0           num = (char*) calloc(count+2, sizeof(char));
282 0           snprintf(num, count+2, "%uD", (unsigned int) duration->days);
283 0           str = strncat(str, num, count+2);
284 0           free((void*) num);
285             }
286 0 0         if (T) {
287 0           str = strncat(str, "T", 1);
288             }
289 0 0         if (duration->hours > 0) {
290 0           count = digits_in_number(duration->hours);
291 0           num = (char*) calloc(count+2, sizeof(char));
292 0           snprintf(num, count+2, "%uH", (unsigned int) duration->hours);
293 0           str = strncat(str, num, count+2);
294 0           free((void*) num);
295             }
296 0 0         if (duration->minutes > 0) {
297 0           count = digits_in_number(duration->minutes);
298 0           num = (char*) calloc(count+2, sizeof(char));
299 0           snprintf(num, count+2, "%uM", (unsigned int) duration->minutes);
300 0           str = strncat(str, num, count+2);
301 0           free((void*) num);
302             }
303 0 0         if (duration->seconds > 0) {
304 0           count = digits_in_number(duration->seconds);
305 0           num = (char*) calloc(count+2, sizeof(char));
306 0           snprintf(num, count+2, "%uS", (unsigned int) duration->seconds);
307 0           str = strncat(str, num, count+2);
308 0           free((void*) num);
309             }
310 0           return str;
311             }
312              
313              
314             /**
315             * Convert a duration to a time.
316             *
317             */
318             time_t
319 0           ldns_duration2time(ldns_duration_type* duration)
320             {
321 0           time_t period = 0;
322              
323 0 0         if (duration) {
324 0           period += (duration->seconds);
325 0           period += (duration->minutes)*60;
326 0           period += (duration->hours)*3600;
327 0           period += (duration->days)*86400;
328 0           period += (duration->weeks)*86400*7;
329 0           period += (duration->months)*86400*31;
330 0           period += (duration->years)*86400*365;
331              
332             /* [TODO] calculate correct number of days in this month/year */
333             /*
334             if (duration->months || duration->years) {
335             }
336             */
337             }
338 0           return period;
339             }
340              
341              
342             /**
343             * Clean up duration.
344             *
345             */
346             void
347 0           ldns_duration_cleanup(ldns_duration_type* duration)
348             {
349 0 0         if (!duration) {
350 0           return;
351             }
352 0           free(duration);
353 0           return;
354             }