Skip to content

Commit

Permalink
Issue #73 replace ldns_duration2string...
Browse files Browse the repository at this point in the history
with something more straight forward and comprehensible
  • Loading branch information
wtoorop committed Mar 17, 2020
1 parent a30cde9 commit af27a2b
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 105 deletions.
2 changes: 1 addition & 1 deletion Changelog
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
1.7.2 2019-??-??
1.7.2 2020-??-??
* bugfix #38: Print "line" before line number when printing
zone parse errors. Thanks Petr Špaček.
* bugfix: Revert unused variables in ldns-config removal patch.
Expand Down
138 changes: 34 additions & 104 deletions duration.c
Original file line number Diff line number Diff line change
Expand Up @@ -190,121 +190,51 @@ ldns_duration_create_from_string(const char* str)


/**
* 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
digits_in_number(time_t duration)
static inline int dur_scan_print(char **buf, char *eob, char c, time_t t)
{
unsigned int i = (unsigned int) duration;
size_t n = 1;

while (i >= 100000000) {
n += 8;
i /= 100000000;
if (t > 0) {
int r = snprintf(*buf, eob - *buf, "%u%c", (unsigned)t, c);
if (r < 0 || (*buf += r) >= eob)
return -1;
}
if (i >= 10000) { n += 4; i /= 10000; }
if (i >= 100 ) { n += 2; i /= 100; }
if (i >= 10 ) { n += 1; }
return n;
return 0;
}


/**
* Convert a duration to a string.
*
*/
char*
ldns_duration2string(const ldns_duration_type* duration)
ldns_duration2string(const ldns_duration_type* d)
{
char* str = NULL;
size_t count = 2;
int T = 0;
char num[sizeof(unsigned int) + 2];

if (!duration) {
return NULL;
}

if (duration->years > 0) {
count = count + 1 + digits_in_number(duration->years);
}
if (duration->months > 0) {
count = count + 1 + digits_in_number(duration->months);
}
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++;
}

if (!(str = (char*) calloc(count, sizeof(char))))
return NULL;
str[0] = 'P';
str[1] = '\0';

if (duration->years > 0) {
count = digits_in_number(duration->years);
assert(count <= sizeof(num) - 2);
snprintf(num, count+2, "%uY", (unsigned int) duration->years);
str = strncat(str, num, count+2);
}
if (duration->months > 0) {
count = digits_in_number(duration->months);
assert(count <= sizeof(num) - 2);
snprintf(num, count+2, "%uM", (unsigned int) duration->months);
str = strncat(str, num, count+2);
}
if (duration->weeks > 0) {
count = digits_in_number(duration->weeks);
assert(count <= sizeof(num) - 2);
snprintf(num, count+2, "%uW", (unsigned int) duration->weeks);
str = strncat(str, num, count+2);
}
if (duration->days > 0) {
count = digits_in_number(duration->days);
assert(count <= sizeof(num) - 2);
snprintf(num, count+2, "%uD", (unsigned int) duration->days);
str = strncat(str, num, count+2);
}
if (T) {
str = strcat(str, "T");
}
if (duration->hours > 0) {
count = digits_in_number(duration->hours);
assert(count <= sizeof(num) - 2);
snprintf(num, count+2, "%uH", (unsigned int) duration->hours);
str = strncat(str, num, count+2);
}
if (duration->minutes > 0) {
count = digits_in_number(duration->minutes);
assert(count <= sizeof(num) - 2);
snprintf(num, count+2, "%uM", (unsigned int) duration->minutes);
str = strncat(str, num, count+2);
}
if (duration->seconds > 0) {
count = digits_in_number(duration->seconds);
assert(count <= sizeof(num) - 2);
snprintf(num, count+2, "%uS", (unsigned int) duration->seconds);
str = strncat(str, num, count+2);
}
return str;
/* Max string size should be 7 * 40 + 3 on a 127 bits machine
* So 300 (< 273) is more than enough.
*/
char buf[300] = "P0D", *eob = buf + sizeof(buf), *p = buf + 1;

if (!d)
return NULL;

if (dur_scan_print(&p, eob, 'Y', d->years)
|| dur_scan_print(&p, eob, 'M', d->months)
|| dur_scan_print(&p, eob, 'W', d->weeks)
|| dur_scan_print(&p, eob, 'D', d->days))
return NULL;

if (d->hours || d->minutes || d->seconds) {
if (p > (eob - 2))
return NULL; /* Error; no space left on buf for 'T' */

*p++ = 'T'; *p = 0;
if (dur_scan_print(&p, eob, 'H', d->hours)
|| dur_scan_print(&p, eob, 'M', d->minutes)
|| dur_scan_print(&p, eob, 'S', d->seconds))
return NULL;
}
return strdup(buf);
}


Expand Down
54 changes: 54 additions & 0 deletions test/13-unit-tests-base.tpkg/13-unit-tests-base.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,57 @@

#include <ldns/ldns.h>

int test_duration(void)
{
ldns_duration_type *d1 = NULL, *d2 = NULL;
char *s1 = NULL, *s2 = NULL, *s3 = NULL;
int r = -1;

if (!(d1 = ldns_duration_create()))
fprintf(stderr, "ldns_duration_create() returned NULL\n");

else if (!(s1 = ldns_duration2string(d1)))
fprintf(stderr, "ldns_duration2string() returned NULL\n");

else if (!(d2 = ldns_duration_create_from_string("PT0S")))
fprintf( stderr
, "ldns_duration_create_from_string(\"P0D\") returned NULL\n");

else if (ldns_duration_compare(d1, d2))
fprintf(stderr, "0 durations not equal\n");

else if ((d1->years = 1), (d1->months = 3), 0)
; /* pass */

else if (!(s2 = ldns_duration2string(d1)))
fprintf(stderr, "ldns_duration2string() returned NULL\n");

else if (strcmp(s2, "P1Y3M"))
fprintf(stderr, "\"%s\" should have been \"P1Y3M\"\n", s2);

else if ((d1->minutes = 3), 0)
; /* pass */

else if (!(s3 = ldns_duration2string(d1)))
fprintf(stderr, "ldns_duration2string() returned NULL\n");

else if (strcmp(s3, "P1Y3MT3M"))
fprintf(stderr, "\"%s\" should have been \"P1Y3MT3M\"\n", s3);

else if (ldns_duration_compare(d1, d2) <= 0)
fprintf(stderr, "ldns_duration_compare() error\n");
else
r = 0;

if (d1) ldns_duration_cleanup(d1);
if (d2) ldns_duration_cleanup(d2);
if (s1) free(s1);
if (s2) free(s2);
if (s3) free(s3);
return r;
}


void print_data_ar(const uint8_t *data, const size_t len) {
size_t i;

Expand Down Expand Up @@ -823,6 +874,9 @@ main(void)
}
free(data);

if (test_duration())
result = EXIT_FAILURE;

printf("unit test is %s\n", result==EXIT_SUCCESS?"ok":"fail");
exit(result);
}

0 comments on commit af27a2b

Please sign in to comment.