summaryrefslogtreecommitdiff
path: root/lib/printf.c
diff options
context:
space:
mode:
authorOndrej Zajicek (work) <santiago@crfreenet.org>2017-06-13 15:41:49 +0200
committerOndrej Zajicek (work) <santiago@crfreenet.org>2017-12-07 13:49:27 +0100
commit49fc021337eba2e9cea228e80e1f95ef21b30cd2 (patch)
tree0b6a15d8395baeac54e40f42eca9d5deb6b1b9db /lib/printf.c
parentf047271cb963c62663687d63b2f7cf8dd5edfbb7 (diff)
Printf: Add support for microsecond times
Use '%t' in bsnprintf() for microsecond times (in btime) with variable sub-second precision.
Diffstat (limited to 'lib/printf.c')
-rw-r--r--lib/printf.c55
1 files changed, 51 insertions, 4 deletions
diff --git a/lib/printf.c b/lib/printf.c
index 8e3cbbcf..533a1300 100644
--- a/lib/printf.c
+++ b/lib/printf.c
@@ -125,9 +125,10 @@ static char * number(char * str, long num, int base, int size, int precision,
* or |%I6| can be used for explicit ip4_addr / ip6_addr arguments, |%N| for
* generic network addresses (net_addr *), |%R| for Router / Network ID (u32
* value printed as IPv4 address), |%lR| for 64bit Router / Network ID (u64
- * value printed as eight :-separated octets) and |%m| resp. |%M| for error
- * messages (uses strerror() to translate @errno code to message text). On the
- * other hand, it doesn't support floating point numbers.
+ * value printed as eight :-separated octets), |%t| for time values (btime) with
+ * specified subsecond precision, and |%m| resp. |%M| for error messages (uses
+ * strerror() to translate @errno code to message text). On the other hand, it
+ * doesn't support floating point numbers.
*
* Result: number of characters of the output string or -1 if
* the buffer space was insufficient.
@@ -139,6 +140,8 @@ int bvsnprintf(char *buf, int size, const char *fmt, va_list args)
int i, base;
u32 x;
u64 X;
+ btime t;
+ s64 t1, t2;
char *str, *start;
const char *s;
char ipbuf[NET_MAX_TEXT_LENGTH+1];
@@ -279,7 +282,6 @@ int bvsnprintf(char *buf, int size, const char *fmt, va_list args)
return -1;
continue;
-
case 'n':
if (qualifier == 'l') {
long * ip = va_arg(args, long *);
@@ -360,6 +362,50 @@ int bvsnprintf(char *buf, int size, const char *fmt, va_list args)
s = ipbuf;
goto str;
+ case 't':
+ t = va_arg(args, btime);
+ t1 = t TO_S;
+ t2 = t - t1 S;
+
+ if (precision < 0)
+ precision = 3;
+
+ if (precision > 6)
+ precision = 6;
+
+ /* Compute field_width for second part */
+ if ((precision > 0) && (field_width > 0))
+ field_width -= (1 + precision);
+
+ if (field_width < 0)
+ field_width = 0;
+
+ /* Print seconds */
+ flags |= SIGN;
+ str = number(str, t1, 10, field_width, 0, flags, size);
+ if (!str)
+ return -1;
+
+ if (precision > 0)
+ {
+ size -= (str-start);
+ start = str;
+
+ if ((1 + precision) > size)
+ return -1;
+
+ /* Convert microseconds to requested precision */
+ for (i = precision; i < 6; i++)
+ t2 /= 10;
+
+ /* Print sub-seconds */
+ *str++ = '.';
+ str = number(str, t2, 10, precision, 0, ZEROPAD, size - 1);
+ if (!str)
+ return -1;
+ }
+ goto done;
+
/* integer number formats - set up the flags and "break" */
case 'o':
base = 8;
@@ -401,6 +447,7 @@ int bvsnprintf(char *buf, int size, const char *fmt, va_list args)
str = number(str, num, base, field_width, precision, flags, size);
if (!str)
return -1;
+ done: ;
}
if (!size)
return -1;