]> git.ipfire.org Git - thirdparty/ldns.git/commitdiff
Issue #73 replace ldns_duration2string...
authorWillem Toorop <willem@nlnetlabs.nl>
Tue, 17 Mar 2020 14:32:36 +0000 (15:32 +0100)
committerWillem Toorop <willem@nlnetlabs.nl>
Tue, 17 Mar 2020 14:32:36 +0000 (15:32 +0100)
with something more straight forward and comprehensible

Changelog
duration.c
test/13-unit-tests-base.tpkg/13-unit-tests-base.c

index fd0b12f187c70e58e4d2ab7cb2c075d4f1c7d91b..3fdf8d7141134ba430e4e738e379af27b75507b6 100644 (file)
--- a/Changelog
+++ b/Changelog
@@ -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.
index 0a8d79b519bc722c16046eae01b7b5ac3e818637..abff9a074fc34b4c9b26b826e0b76c0f5291b372 100644 (file)
@@ -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);
 }
 
 
index 0fd4b5d9421e8c4548a977629fef054a7bb675e2..74108a409009d4a71e30c1ce0144476aa7e5ae3d 100644 (file)
@@ -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;
        
@@ -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);
 }