duration.c

Go to the documentation of this file.
00001 /*
00002  * $Id: duration.c 4518 2011-02-24 15:39:09Z matthijs $
00003  *
00004  * Copyright (c) 2009 NLNet Labs. All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  *
00015  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00016  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00017  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00018  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
00019  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00020  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00021  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00022  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
00023  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
00024  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
00025  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026  *
00027  */
00028 
00040 #include <ldns/config.h>
00041 #include <ldns/duration.h>
00042 
00043 #include <stdio.h>
00044 #include <stdlib.h>
00045 #include <string.h>
00046 #include <time.h>
00047 
00048 
00053 ldns_duration_type*
00054 ldns_duration_create(void)
00055 {
00056     ldns_duration_type* duration;
00057 
00058     duration = malloc(sizeof(ldns_duration_type));
00059     if (!duration) {
00060         return NULL;
00061     }
00062     duration->years = 0;
00063     duration->months = 0;
00064     duration->weeks = 0;
00065     duration->days = 0;
00066     duration->hours = 0;
00067     duration->minutes = 0;
00068     duration->seconds = 0;
00069     return duration;
00070 }
00071 
00072 
00077 int
00078 ldns_duration_compare(ldns_duration_type* d1, ldns_duration_type* d2)
00079 {
00080     if (!d1 && !d2) {
00081         return 0;
00082     }
00083     if (!d1 || !d2) {
00084         return d1?-1:1;
00085     }
00086 
00087     if (d1->years != d2->years) {
00088         return (int) (d1->years - d2->years);
00089     }
00090     if (d1->months != d2->months) {
00091         return (int) (d1->months - d2->months);
00092     }
00093     if (d1->weeks != d2->weeks) {
00094         return (int) (d1->weeks - d2->weeks);
00095     }
00096     if (d1->days != d2->days) {
00097         return (int) (d1->days - d2->days);
00098     }
00099     if (d1->hours != d2->hours) {
00100         return (int) (d1->hours - d2->hours);
00101     }
00102     if (d1->minutes != d2->minutes) {
00103         return (int) (d1->minutes - d2->minutes);
00104     }
00105     if (d1->seconds != d2->seconds) {
00106         return (int) (d1->seconds - d2->seconds);
00107     }
00108 
00109     return 0;
00110 }
00111 
00112 
00117 ldns_duration_type*
00118 ldns_duration_create_from_string(const char* str)
00119 {
00120     ldns_duration_type* duration = ldns_duration_create();
00121     char* P, *X, *T, *W;
00122     int not_weeks = 0;
00123 
00124     if (!duration) {
00125         return NULL;
00126     }
00127     if (!str) {
00128         return duration;
00129     }
00130 
00131     P = strchr(str, 'P');
00132     if (!P) {
00133         ldns_duration_cleanup(duration);
00134         return NULL;
00135     }
00136 
00137     T = strchr(str, 'T');
00138     X = strchr(str, 'Y');
00139     if (X) {
00140         duration->years = (time_t) atoi(str+1);
00141         str = X;
00142         not_weeks = 1;
00143     }
00144     X = strchr(str, 'M');
00145     if (X && (!T || (size_t) (X-P) < (size_t) (T-P))) {
00146         duration->months = (time_t) atoi(str+1);
00147         str = X;
00148         not_weeks = 1;
00149     }
00150     X = strchr(str, 'D');
00151     if (X) {
00152         duration->days = (time_t) atoi(str+1);
00153         str = X;
00154         not_weeks = 1;
00155     }
00156     if (T) {
00157         str = T;
00158         not_weeks = 1;
00159     }
00160     X = strchr(str, 'H');
00161     if (X && T) {
00162         duration->hours = (time_t) atoi(str+1);
00163         str = X;
00164         not_weeks = 1;
00165     }
00166     X = strrchr(str, 'M');
00167     if (X && T && (size_t) (X-P) > (size_t) (T-P)) {
00168         duration->minutes = (time_t) atoi(str+1);
00169         str = X;
00170         not_weeks = 1;
00171     }
00172     X = strchr(str, 'S');
00173     if (X && T) {
00174         duration->seconds = (time_t) atoi(str+1);
00175         str = X;
00176         not_weeks = 1;
00177     }
00178 
00179     W = strchr(str, 'W');
00180     if (W) {
00181         if (not_weeks) {
00182             ldns_duration_cleanup(duration);
00183             return NULL;
00184         } else {
00185             duration->weeks = (time_t) atoi(str+1);
00186             str = W;
00187         }
00188     }
00189     return duration;
00190 }
00191 
00192 
00197 static size_t
00198 digits_in_number(time_t duration)
00199 {
00200     uint32_t period = (uint32_t) duration;
00201     size_t count = 0;
00202 
00203     while (period > 0) {
00204         count++;
00205         period /= 10;
00206     }
00207     return count;
00208 }
00209 
00210 
00215 char*
00216 ldns_duration2string(ldns_duration_type* duration)
00217 {
00218     char* str = NULL, *num = NULL;
00219     size_t count = 2;
00220     int T = 0;
00221 
00222     if (!duration) {
00223         return NULL;
00224     }
00225 
00226     if (duration->years > 0) {
00227         count = count + 1 + digits_in_number(duration->years);
00228     }
00229     if (duration->months > 0) {
00230         count = count + 1 + digits_in_number(duration->months);
00231     }
00232     if (duration->weeks > 0) {
00233         count = count + 1 + digits_in_number(duration->weeks);
00234     }
00235     if (duration->days > 0) {
00236         count = count + 1 + digits_in_number(duration->days);
00237     }
00238     if (duration->hours > 0) {
00239         count = count + 1 + digits_in_number(duration->hours);
00240         T = 1;
00241     }
00242     if (duration->minutes > 0) {
00243         count = count + 1 + digits_in_number(duration->minutes);
00244         T = 1;
00245     }
00246     if (duration->seconds > 0) {
00247         count = count + 1 + digits_in_number(duration->seconds);
00248         T = 1;
00249     }
00250     if (T) {
00251         count++;
00252     }
00253 
00254     str = (char*) calloc(count, sizeof(char));
00255     str[0] = 'P';
00256     str[1] = '\0';
00257 
00258     if (duration->years > 0) {
00259         count = digits_in_number(duration->years);
00260         num = (char*) calloc(count+2, sizeof(char));
00261         snprintf(num, count+2, "%uY", (unsigned int) duration->years);
00262         str = strncat(str, num, count+2);
00263         free((void*) num);
00264     }
00265     if (duration->months > 0) {
00266         count = digits_in_number(duration->months);
00267         num = (char*) calloc(count+2, sizeof(char));
00268         snprintf(num, count+2, "%uM", (unsigned int) duration->months);
00269         str = strncat(str, num, count+2);
00270         free((void*) num);
00271     }
00272     if (duration->weeks > 0) {
00273         count = digits_in_number(duration->weeks);
00274         num = (char*) calloc(count+2, sizeof(char));
00275         snprintf(num, count+2, "%uW", (unsigned int) duration->weeks);
00276         str = strncat(str, num, count+2);
00277         free((void*) num);
00278     }
00279     if (duration->days > 0) {
00280         count = digits_in_number(duration->days);
00281         num = (char*) calloc(count+2, sizeof(char));
00282         snprintf(num, count+2, "%uD", (unsigned int) duration->days);
00283         str = strncat(str, num, count+2);
00284         free((void*) num);
00285     }
00286     if (T) {
00287         str = strncat(str, "T", 1);
00288     }
00289     if (duration->hours > 0) {
00290         count = digits_in_number(duration->hours);
00291         num = (char*) calloc(count+2, sizeof(char));
00292         snprintf(num, count+2, "%uH", (unsigned int) duration->hours);
00293         str = strncat(str, num, count+2);
00294         free((void*) num);
00295     }
00296     if (duration->minutes > 0) {
00297         count = digits_in_number(duration->minutes);
00298         num = (char*) calloc(count+2, sizeof(char));
00299         snprintf(num, count+2, "%uM", (unsigned int) duration->minutes);
00300         str = strncat(str, num, count+2);
00301         free((void*) num);
00302     }
00303     if (duration->seconds > 0) {
00304         count = digits_in_number(duration->seconds);
00305         num = (char*) calloc(count+2, sizeof(char));
00306         snprintf(num, count+2, "%uS", (unsigned int) duration->seconds);
00307         str = strncat(str, num, count+2);
00308         free((void*) num);
00309     }
00310     return str;
00311 }
00312 
00313 
00318 time_t
00319 ldns_duration2time(ldns_duration_type* duration)
00320 {
00321     time_t period = 0;
00322 
00323     if (duration) {
00324         period += (duration->seconds);
00325         period += (duration->minutes)*60;
00326         period += (duration->hours)*3600;
00327         period += (duration->days)*86400;
00328         period += (duration->weeks)*86400*7;
00329         period += (duration->months)*86400*31;
00330         period += (duration->years)*86400*365;
00331 
00332         /* [TODO] calculate correct number of days in this month/year */
00333         /*
00334         if (duration->months || duration->years) {
00335         }
00336         */
00337     }
00338     return period;
00339 }
00340 
00341 
00346 void
00347 ldns_duration_cleanup(ldns_duration_type* duration)
00348 {
00349     if (!duration) {
00350         return;
00351     }
00352     free(duration);
00353     return;
00354 }

Generated on Wed Dec 19 16:56:42 2012 for ldns by  doxygen 1.4.7