Changeset View
Changeset View
Standalone View
Standalone View
contrib/ldns/duration.c
Show First 20 Lines • Show All 177 Lines • ▼ Show 20 Lines | ldns_duration_cleanup(duration); | ||||
W = strchr(str, 'W'); | W = strchr(str, 'W'); | ||||
if (W) { | if (W) { | ||||
if (not_weeks) { | if (not_weeks) { | ||||
ldns_duration_cleanup(duration); | ldns_duration_cleanup(duration); | ||||
return NULL; | return NULL; | ||||
} else { | } else { | ||||
duration->weeks = (time_t) atoi(str+1); | duration->weeks = (time_t) atoi(str+1); | ||||
str = W; | |||||
} | } | ||||
} | } | ||||
return duration; | return duration; | ||||
} | } | ||||
/** | /** | ||||
* Get the number of digits in a number. | * Helper func for ldns_duration2string below. If t > 0, | ||||
* | * scan print t and c on buf, forwarding buf. Return 0 on success. | ||||
*/ | */ | ||||
static size_t | static inline int dur_scan_print(char **buf, char *eob, char c, time_t t) | ||||
digits_in_number(time_t duration) | |||||
{ | { | ||||
uint32_t period = (uint32_t) duration; | if (t > 0) { | ||||
size_t count = 0; | int r = snprintf(*buf, eob - *buf, "%u%c", (unsigned)t, c); | ||||
if (r < 0 || (*buf += r) >= eob) | |||||
while (period > 0) { | return -1; | ||||
count++; | |||||
period /= 10; | |||||
} | } | ||||
return count; | return 0; | ||||
} | } | ||||
/** | /** | ||||
* Convert a duration to a string. | * Convert a duration to a string. | ||||
* | * | ||||
*/ | */ | ||||
char* | char* | ||||
ldns_duration2string(const ldns_duration_type* duration) | ldns_duration2string(const ldns_duration_type* d) | ||||
{ | { | ||||
char* str = NULL, *num = NULL; | /* Max string size should be 7 * 40 + 3 on a 127 bits machine | ||||
size_t count = 2; | * So 300 (< 273) is more than enough. | ||||
int T = 0; | */ | ||||
char buf[300] = "P0D", *eob = buf + sizeof(buf), *p = buf + 1; | |||||
if (!duration) { | if (!d) | ||||
return NULL; | return NULL; | ||||
} | |||||
if (duration->years > 0) { | if (dur_scan_print(&p, eob, 'Y', d->years) | ||||
count = count + 1 + digits_in_number(duration->years); | || dur_scan_print(&p, eob, 'M', d->months) | ||||
} | || dur_scan_print(&p, eob, 'W', d->weeks) | ||||
if (duration->months > 0) { | || dur_scan_print(&p, eob, 'D', d->days)) | ||||
count = count + 1 + digits_in_number(duration->months); | return NULL; | ||||
} | |||||
if (duration->weeks > 0) { | |||||
count = count + 1 + digits_in_number(duration->weeks); | |||||
} | |||||
if (duration->days > 0) { | |||||
count = count + 1 + digits_in_number(duration->days); | |||||
} | |||||
if (duration->hours > 0) { | |||||
count = count + 1 + digits_in_number(duration->hours); | |||||
T = 1; | |||||
} | |||||
if (duration->minutes > 0) { | |||||
count = count + 1 + digits_in_number(duration->minutes); | |||||
T = 1; | |||||
} | |||||
if (duration->seconds > 0) { | |||||
count = count + 1 + digits_in_number(duration->seconds); | |||||
T = 1; | |||||
} | |||||
if (T) { | |||||
count++; | |||||
} | |||||
str = (char*) calloc(count, sizeof(char)); | if (d->hours || d->minutes || d->seconds) { | ||||
str[0] = 'P'; | if (p > (eob - 2)) | ||||
str[1] = '\0'; | return NULL; /* Error; no space left on buf for 'T' */ | ||||
if (duration->years > 0) { | *p++ = 'T'; *p = 0; | ||||
count = digits_in_number(duration->years); | if (dur_scan_print(&p, eob, 'H', d->hours) | ||||
num = (char*) calloc(count+2, sizeof(char)); | || dur_scan_print(&p, eob, 'M', d->minutes) | ||||
snprintf(num, count+2, "%uY", (unsigned int) duration->years); | || dur_scan_print(&p, eob, 'S', d->seconds)) | ||||
str = strncat(str, num, count+2); | return NULL; | ||||
free((void*) num); | |||||
} | } | ||||
if (duration->months > 0) { | return strdup(buf); | ||||
count = digits_in_number(duration->months); | |||||
num = (char*) calloc(count+2, sizeof(char)); | |||||
snprintf(num, count+2, "%uM", (unsigned int) duration->months); | |||||
str = strncat(str, num, count+2); | |||||
free((void*) num); | |||||
} | |||||
if (duration->weeks > 0) { | |||||
count = digits_in_number(duration->weeks); | |||||
num = (char*) calloc(count+2, sizeof(char)); | |||||
snprintf(num, count+2, "%uW", (unsigned int) duration->weeks); | |||||
str = strncat(str, num, count+2); | |||||
free((void*) num); | |||||
} | |||||
if (duration->days > 0) { | |||||
count = digits_in_number(duration->days); | |||||
num = (char*) calloc(count+2, sizeof(char)); | |||||
snprintf(num, count+2, "%uD", (unsigned int) duration->days); | |||||
str = strncat(str, num, count+2); | |||||
free((void*) num); | |||||
} | |||||
if (T) { | |||||
str = strncat(str, "T", 1); | |||||
} | |||||
if (duration->hours > 0) { | |||||
count = digits_in_number(duration->hours); | |||||
num = (char*) calloc(count+2, sizeof(char)); | |||||
snprintf(num, count+2, "%uH", (unsigned int) duration->hours); | |||||
str = strncat(str, num, count+2); | |||||
free((void*) num); | |||||
} | |||||
if (duration->minutes > 0) { | |||||
count = digits_in_number(duration->minutes); | |||||
num = (char*) calloc(count+2, sizeof(char)); | |||||
snprintf(num, count+2, "%uM", (unsigned int) duration->minutes); | |||||
str = strncat(str, num, count+2); | |||||
free((void*) num); | |||||
} | |||||
if (duration->seconds > 0) { | |||||
count = digits_in_number(duration->seconds); | |||||
num = (char*) calloc(count+2, sizeof(char)); | |||||
snprintf(num, count+2, "%uS", (unsigned int) duration->seconds); | |||||
str = strncat(str, num, count+2); | |||||
free((void*) num); | |||||
} | |||||
return str; | |||||
} | } | ||||
/** | /** | ||||
* Convert a duration to a time. | * Convert a duration to a time. | ||||
* | * | ||||
*/ | */ | ||||
time_t | time_t | ||||
Show All 36 Lines |