back to topotato report
topotato coverage report
Current view: top level - lib - strformat.c (source / functions) Hit Total Coverage
Test: test_ospf_topo1.py::OSPFTopo1Test Lines: 7 339 2.1 %
Date: 2023-02-24 18:38:32 Functions: 7 19 36.8 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2019  David Lamparter, for NetDEF, Inc.
       3             :  *
       4             :  * Permission to use, copy, modify, and distribute this software for any
       5             :  * purpose with or without fee is hereby granted, provided that the above
       6             :  * copyright notice and this permission notice appear in all copies.
       7             :  *
       8             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
       9             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      10             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      11             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      12             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      13             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      14             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      15             :  */
      16             : 
      17             : #ifdef HAVE_CONFIG_H
      18             : #include "config.h"
      19             : #endif
      20             : 
      21             : #include "compiler.h"
      22             : 
      23             : #include <string.h>
      24             : #include <ctype.h>
      25             : #include <time.h>
      26             : 
      27             : #include "printfrr.h"
      28             : #include "monotime.h"
      29             : 
      30          12 : printfrr_ext_autoreg_p("HX", printfrr_hexdump);
      31           0 : static ssize_t printfrr_hexdump(struct fbuf *buf, struct printfrr_eargs *ea,
      32             :                                 const void *ptr)
      33             : {
      34           0 :         ssize_t ret = 0;
      35           0 :         ssize_t input_len = printfrr_ext_len(ea);
      36           0 :         char sep = ' ';
      37           0 :         const uint8_t *pos, *end;
      38             : 
      39           0 :         if (ea->fmt[0] == 'c') {
      40           0 :                 ea->fmt++;
      41           0 :                 sep = ':';
      42           0 :         } else if (ea->fmt[0] == 'n') {
      43           0 :                 ea->fmt++;
      44           0 :                 sep = '\0';
      45             :         }
      46             : 
      47           0 :         if (input_len < 0)
      48             :                 return 0;
      49             : 
      50           0 :         for (pos = ptr, end = pos + input_len; pos < end; pos++) {
      51           0 :                 if (sep && pos != ptr)
      52           0 :                         ret += bputch(buf, sep);
      53           0 :                 ret += bputhex(buf, *pos);
      54             :         }
      55             : 
      56             :         return ret;
      57             : }
      58             : 
      59             : /* string analog for hexdumps / the "this." in ("74 68 69 73 0a  |this.|") */
      60             : 
      61          12 : printfrr_ext_autoreg_p("HS", printfrr_hexdstr);
      62           0 : static ssize_t printfrr_hexdstr(struct fbuf *buf, struct printfrr_eargs *ea,
      63             :                                 const void *ptr)
      64             : {
      65           0 :         ssize_t ret = 0;
      66           0 :         ssize_t input_len = printfrr_ext_len(ea);
      67           0 :         const uint8_t *pos, *end;
      68             : 
      69           0 :         if (input_len < 0)
      70             :                 return 0;
      71             : 
      72           0 :         for (pos = ptr, end = pos + input_len; pos < end; pos++) {
      73           0 :                 if (*pos >= 0x20 && *pos < 0x7f)
      74           0 :                         ret += bputch(buf, *pos);
      75             :                 else
      76           0 :                         ret += bputch(buf, '.');
      77             :         }
      78             : 
      79             :         return ret;
      80             : }
      81             : 
      82             : enum escape_flags {
      83             :         ESC_N_R_T       = (1 << 0),       /* use \n \r \t instead of \x0a ...*/
      84             :         ESC_SPACE       = (1 << 1),       /* \  */
      85             :         ESC_BACKSLASH   = (1 << 2),       /* \\ */
      86             :         ESC_DBLQUOTE    = (1 << 3),       /* \" */
      87             :         ESC_SGLQUOTE    = (1 << 4),       /* \' */
      88             :         ESC_BACKTICK    = (1 << 5),       /* \` */
      89             :         ESC_DOLLAR      = (1 << 6),       /* \$ */
      90             :         ESC_CLBRACKET   = (1 << 7),       /* \] for RFC5424 syslog */
      91             :         ESC_OTHER       = (1 << 8),       /* remaining non-alpha */
      92             : 
      93             :         ESC_ALL = ESC_N_R_T | ESC_SPACE | ESC_BACKSLASH | ESC_DBLQUOTE
      94             :                 | ESC_SGLQUOTE | ESC_DOLLAR | ESC_OTHER,
      95             :         ESC_QUOTSTRING = ESC_N_R_T | ESC_BACKSLASH | ESC_DBLQUOTE,
      96             :         /* if needed: ESC_SHELL = ... */
      97             : };
      98             : 
      99           0 : static ssize_t bquote(struct fbuf *buf, const uint8_t *pos, size_t len,
     100             :                       unsigned int flags)
     101             : {
     102           0 :         ssize_t ret = 0;
     103           0 :         const uint8_t *end = pos + len;
     104             : 
     105           0 :         for (; pos < end; pos++) {
     106             :                 /* here's to hoping this might be a bit faster... */
     107           0 :                 if (__builtin_expect(!!isalnum(*pos), 1)) {
     108           0 :                         ret += bputch(buf, *pos);
     109           0 :                         continue;
     110             :                 }
     111             : 
     112           0 :                 switch (*pos) {
     113           0 :                 case '%':
     114             :                 case '+':
     115             :                 case ',':
     116             :                 case '-':
     117             :                 case '.':
     118             :                 case '/':
     119             :                 case ':':
     120             :                 case '@':
     121             :                 case '_':
     122           0 :                         ret += bputch(buf, *pos);
     123           0 :                         continue;
     124             : 
     125           0 :                 case '\r':
     126           0 :                         if (!(flags & ESC_N_R_T))
     127             :                                 break;
     128           0 :                         ret += bputch(buf, '\\');
     129           0 :                         ret += bputch(buf, 'r');
     130           0 :                         continue;
     131           0 :                 case '\n':
     132           0 :                         if (!(flags & ESC_N_R_T))
     133             :                                 break;
     134           0 :                         ret += bputch(buf, '\\');
     135           0 :                         ret += bputch(buf, 'n');
     136           0 :                         continue;
     137           0 :                 case '\t':
     138           0 :                         if (!(flags & ESC_N_R_T))
     139             :                                 break;
     140           0 :                         ret += bputch(buf, '\\');
     141           0 :                         ret += bputch(buf, 't');
     142           0 :                         continue;
     143             : 
     144           0 :                 case ' ':
     145           0 :                         if (flags & ESC_SPACE)
     146           0 :                                 ret += bputch(buf, '\\');
     147           0 :                         ret += bputch(buf, *pos);
     148           0 :                         continue;
     149             : 
     150           0 :                 case '\\':
     151           0 :                         if (flags & ESC_BACKSLASH)
     152           0 :                                 ret += bputch(buf, '\\');
     153           0 :                         ret += bputch(buf, *pos);
     154           0 :                         continue;
     155             : 
     156           0 :                 case '"':
     157           0 :                         if (flags & ESC_DBLQUOTE)
     158           0 :                                 ret += bputch(buf, '\\');
     159           0 :                         ret += bputch(buf, *pos);
     160           0 :                         continue;
     161             : 
     162           0 :                 case '\'':
     163           0 :                         if (flags & ESC_SGLQUOTE)
     164           0 :                                 ret += bputch(buf, '\\');
     165           0 :                         ret += bputch(buf, *pos);
     166           0 :                         continue;
     167             : 
     168           0 :                 case '`':
     169           0 :                         if (flags & ESC_BACKTICK)
     170           0 :                                 ret += bputch(buf, '\\');
     171           0 :                         ret += bputch(buf, *pos);
     172           0 :                         continue;
     173             : 
     174           0 :                 case '$':
     175           0 :                         if (flags & ESC_DOLLAR)
     176           0 :                                 ret += bputch(buf, '\\');
     177           0 :                         ret += bputch(buf, *pos);
     178           0 :                         continue;
     179             : 
     180           0 :                 case ']':
     181           0 :                         if (flags & ESC_CLBRACKET)
     182           0 :                                 ret += bputch(buf, '\\');
     183           0 :                         ret += bputch(buf, *pos);
     184           0 :                         continue;
     185             : 
     186             :                 /* remaining: !#&'()*;<=>?[^{|}~ */
     187             : 
     188           0 :                 default:
     189           0 :                         if (*pos >= 0x20 && *pos < 0x7f) {
     190           0 :                                 if (flags & ESC_OTHER)
     191           0 :                                         ret += bputch(buf, '\\');
     192           0 :                                 ret += bputch(buf, *pos);
     193           0 :                                 continue;
     194             :                         }
     195             :                 }
     196           0 :                 ret += bputch(buf, '\\');
     197           0 :                 ret += bputch(buf, 'x');
     198           0 :                 ret += bputhex(buf, *pos);
     199             :         }
     200             : 
     201           0 :         return ret;
     202             : }
     203             : 
     204          12 : printfrr_ext_autoreg_p("SE", printfrr_escape);
     205           0 : static ssize_t printfrr_escape(struct fbuf *buf, struct printfrr_eargs *ea,
     206             :                                const void *vptr)
     207             : {
     208           0 :         ssize_t len = printfrr_ext_len(ea);
     209           0 :         const uint8_t *ptr = vptr;
     210           0 :         bool null_is_empty = false;
     211             : 
     212           0 :         if (ea->fmt[0] == 'n') {
     213           0 :                 null_is_empty = true;
     214           0 :                 ea->fmt++;
     215             :         }
     216             : 
     217           0 :         if (!ptr) {
     218           0 :                 if (null_is_empty)
     219             :                         return 0;
     220           0 :                 return bputs(buf, "(null)");
     221             :         }
     222             : 
     223           0 :         if (len < 0)
     224           0 :                 len = strlen((const char *)ptr);
     225             : 
     226           0 :         return bquote(buf, ptr, len, ESC_ALL);
     227             : }
     228             : 
     229          12 : printfrr_ext_autoreg_p("SQ", printfrr_quote);
     230           0 : static ssize_t printfrr_quote(struct fbuf *buf, struct printfrr_eargs *ea,
     231             :                               const void *vptr)
     232             : {
     233           0 :         ssize_t len = printfrr_ext_len(ea);
     234           0 :         const uint8_t *ptr = vptr;
     235           0 :         ssize_t ret = 0;
     236           0 :         bool null_is_empty = false;
     237           0 :         bool do_quotes = false;
     238           0 :         unsigned int flags = ESC_QUOTSTRING;
     239             : 
     240           0 :         while (ea->fmt[0]) {
     241           0 :                 switch (ea->fmt[0]) {
     242           0 :                 case 'n':
     243           0 :                         null_is_empty = true;
     244           0 :                         ea->fmt++;
     245           0 :                         continue;
     246           0 :                 case 'q':
     247           0 :                         do_quotes = true;
     248           0 :                         ea->fmt++;
     249           0 :                         continue;
     250           0 :                 case 's':
     251           0 :                         flags |= ESC_CLBRACKET;
     252           0 :                         flags &= ~ESC_N_R_T;
     253           0 :                         ea->fmt++;
     254           0 :                         continue;
     255             :                 }
     256             :                 break;
     257             :         }
     258             : 
     259           0 :         if (!ptr) {
     260           0 :                 if (null_is_empty)
     261           0 :                         return bputs(buf, do_quotes ? "\"\"" : "");
     262           0 :                 return bputs(buf, "(null)");
     263             :         }
     264             : 
     265           0 :         if (len < 0)
     266           0 :                 len = strlen((const char *)ptr);
     267             : 
     268           0 :         if (do_quotes)
     269           0 :                 ret += bputch(buf, '"');
     270           0 :         ret += bquote(buf, ptr, len, flags);
     271           0 :         if (do_quotes)
     272           0 :                 ret += bputch(buf, '"');
     273             :         return ret;
     274             : }
     275             : 
     276             : static ssize_t printfrr_abstime(struct fbuf *buf, struct printfrr_eargs *ea,
     277             :                                 const struct timespec *ts, unsigned int flags);
     278             : static ssize_t printfrr_reltime(struct fbuf *buf, struct printfrr_eargs *ea,
     279             :                                 const struct timespec *ts, unsigned int flags);
     280             : 
     281           0 : ssize_t printfrr_time(struct fbuf *buf, struct printfrr_eargs *ea,
     282             :                       const struct timespec *ts, unsigned int flags)
     283             : {
     284           0 :         bool have_abs, have_anchor;
     285             : 
     286           0 :         if (!(flags & TIMEFMT_PRESELECT)) {
     287           0 :                 switch (ea->fmt[0]) {
     288             :                 case 'I':
     289             :                         /* no bit set */
     290             :                         break;
     291           0 :                 case 'M':
     292           0 :                         flags |= TIMEFMT_MONOTONIC;
     293           0 :                         break;
     294           0 :                 case 'R':
     295           0 :                         flags |= TIMEFMT_REALTIME;
     296           0 :                         break;
     297           0 :                 default:
     298           0 :                         return bputs(buf,
     299             :                                      "{invalid time format input specifier}");
     300             :                 }
     301           0 :                 ea->fmt++;
     302             : 
     303           0 :                 if (ea->fmt[0] == 's') {
     304           0 :                         flags |= TIMEFMT_SINCE;
     305           0 :                         ea->fmt++;
     306           0 :                 } else if (ea->fmt[0] == 'u') {
     307           0 :                         flags |= TIMEFMT_UNTIL;
     308           0 :                         ea->fmt++;
     309             :                 }
     310             :         }
     311             : 
     312           0 :         have_abs = !!(flags & TIMEFMT_ABSOLUTE);
     313           0 :         have_anchor = !!(flags & TIMEFMT_ANCHORS);
     314             : 
     315           0 :         if (have_abs ^ have_anchor)
     316           0 :                 return printfrr_abstime(buf, ea, ts, flags);
     317             :         else
     318           0 :                 return printfrr_reltime(buf, ea, ts, flags);
     319             : }
     320             : 
     321           0 : static ssize_t do_subsec(struct fbuf *buf, const struct timespec *ts,
     322             :                          int precision, unsigned int flags)
     323             : {
     324           0 :         unsigned long long frac;
     325             : 
     326           0 :         if (precision <= 0 || (flags & TIMEFMT_SECONDS))
     327             :                 return 0;
     328             : 
     329           0 :         frac = ts->tv_nsec;
     330           0 :         if (precision > 9)
     331             :                 precision = 9;
     332           0 :         for (int i = precision; i < 9; i++)
     333           0 :                 frac /= 10;
     334           0 :         return bprintfrr(buf, ".%0*llu", precision, frac);
     335             : }
     336             : 
     337           0 : static ssize_t printfrr_abstime(struct fbuf *buf, struct printfrr_eargs *ea,
     338             :                                 const struct timespec *ts, unsigned int flags)
     339             : {
     340           0 :         struct timespec real_ts[1];
     341           0 :         struct tm tm;
     342           0 :         char cbuf[32] = ""; /* manpage says 26 for ctime_r */
     343           0 :         ssize_t ret = 0;
     344           0 :         int precision = ea->precision;
     345             : 
     346           0 :         while (ea->fmt[0]) {
     347           0 :                 char ch = *ea->fmt++;
     348             : 
     349           0 :                 switch (ch) {
     350           0 :                 case 'p':
     351           0 :                         flags |= TIMEFMT_SPACE;
     352           0 :                         continue;
     353           0 :                 case 'i':
     354           0 :                         flags |= TIMEFMT_ISO8601;
     355           0 :                         continue;
     356             :                 }
     357             : 
     358           0 :                 ea->fmt--;
     359           0 :                 break;
     360             :         }
     361             : 
     362           0 :         if (flags & TIMEFMT_SKIP)
     363             :                 return 0;
     364           0 :         if (!ts)
     365           0 :                 return bputch(buf, '-');
     366             : 
     367           0 :         if (flags & TIMEFMT_REALTIME)
     368           0 :                 *real_ts = *ts;
     369           0 :         else if (flags & TIMEFMT_MONOTONIC) {
     370           0 :                 struct timespec mono_now[1];
     371             : 
     372           0 :                 clock_gettime(CLOCK_REALTIME, real_ts);
     373           0 :                 clock_gettime(CLOCK_MONOTONIC, mono_now);
     374             : 
     375           0 :                 timespecsub(real_ts, mono_now, real_ts);
     376           0 :                 timespecadd(real_ts, ts, real_ts);
     377             :         } else {
     378           0 :                 clock_gettime(CLOCK_REALTIME, real_ts);
     379             : 
     380           0 :                 if (flags & TIMEFMT_SINCE)
     381           0 :                         timespecsub(real_ts, ts, real_ts);
     382             :                 else /* flags & TIMEFMT_UNTIL */
     383           0 :                         timespecadd(real_ts, ts, real_ts);
     384             :         }
     385             : 
     386           0 :         localtime_r(&real_ts->tv_sec, &tm);
     387             : 
     388           0 :         if (flags & TIMEFMT_ISO8601) {
     389           0 :                 if (flags & TIMEFMT_SPACE)
     390           0 :                         strftime(cbuf, sizeof(cbuf), "%Y-%m-%d %H:%M:%S", &tm);
     391             :                 else
     392           0 :                         strftime(cbuf, sizeof(cbuf), "%Y-%m-%dT%H:%M:%S", &tm);
     393           0 :                 ret += bputs(buf, cbuf);
     394             : 
     395           0 :                 if (precision == -1)
     396           0 :                         precision = 3;
     397           0 :                 ret += do_subsec(buf, real_ts, precision, flags);
     398             :         } else {
     399           0 :                 size_t len;
     400             : 
     401           0 :                 asctime_r(&tm, cbuf);
     402             : 
     403           0 :                 len = strlen(cbuf);
     404           0 :                 if (!len)
     405             :                         /* WTF. */
     406             :                         return 0;
     407           0 :                 if (cbuf[len - 1] == '\n')
     408           0 :                         cbuf[len - 1] = '\0';
     409             : 
     410           0 :                 ret += bputs(buf, cbuf);
     411             :         }
     412             :         return ret;
     413             : }
     414             : 
     415           0 : static ssize_t printfrr_reltime(struct fbuf *buf, struct printfrr_eargs *ea,
     416             :                                 const struct timespec *ts, unsigned int flags)
     417             : {
     418           0 :         struct timespec real_ts[1];
     419           0 :         ssize_t ret = 0;
     420           0 :         const char *space = "";
     421           0 :         const char *dashes = "-";
     422           0 :         int precision = ea->precision;
     423             : 
     424           0 :         while (ea->fmt[0]) {
     425           0 :                 char ch = *ea->fmt++;
     426             : 
     427           0 :                 switch (ch) {
     428           0 :                 case 'p':
     429           0 :                         flags |= TIMEFMT_SPACE;
     430           0 :                         space = " ";
     431           0 :                         continue;
     432           0 :                 case 't':
     433           0 :                         flags |= TIMEFMT_BASIC;
     434           0 :                         continue;
     435           0 :                 case 'd':
     436           0 :                         flags |= TIMEFMT_DECIMAL;
     437           0 :                         continue;
     438           0 :                 case 'm':
     439           0 :                         flags |= TIMEFMT_MMSS;
     440           0 :                         dashes = "--:--";
     441           0 :                         continue;
     442           0 :                 case 'h':
     443           0 :                         flags |= TIMEFMT_HHMMSS;
     444           0 :                         dashes = "--:--:--";
     445           0 :                         continue;
     446           0 :                 case 'x':
     447           0 :                         flags |= TIMEFMT_DASHES;
     448           0 :                         continue;
     449             :                 }
     450             : 
     451           0 :                 ea->fmt--;
     452           0 :                 break;
     453             :         }
     454             : 
     455           0 :         if (flags & TIMEFMT_SKIP)
     456             :                 return 0;
     457           0 :         if (!ts)
     458           0 :                 return bputch(buf, '-');
     459             : 
     460           0 :         if (flags & TIMEFMT_ABSOLUTE) {
     461           0 :                 struct timespec anchor[1];
     462             : 
     463           0 :                 if (flags & TIMEFMT_REALTIME)
     464           0 :                         clock_gettime(CLOCK_REALTIME, anchor);
     465             :                 else
     466           0 :                         clock_gettime(CLOCK_MONOTONIC, anchor);
     467           0 :                 if (flags & TIMEFMT_UNTIL)
     468           0 :                         timespecsub(ts, anchor, real_ts);
     469             :                 else /* flags & TIMEFMT_SINCE */
     470           0 :                         timespecsub(anchor, ts, real_ts);
     471             :         } else
     472           0 :                 *real_ts = *ts;
     473             : 
     474           0 :         if (real_ts->tv_sec == 0 && real_ts->tv_nsec == 0 &&
     475             :             (flags & TIMEFMT_DASHES))
     476           0 :                 return bputs(buf, dashes);
     477             : 
     478           0 :         if (real_ts->tv_sec < 0) {
     479           0 :                 if (flags & TIMEFMT_DASHES)
     480           0 :                         return bputs(buf, dashes);
     481             : 
     482             :                 /* -0.3s is { -1s + 700ms } */
     483           0 :                 real_ts->tv_sec = -real_ts->tv_sec - 1;
     484           0 :                 real_ts->tv_nsec = 1000000000L - real_ts->tv_nsec;
     485           0 :                 if (real_ts->tv_nsec >= 1000000000L) {
     486           0 :                         real_ts->tv_sec++;
     487           0 :                         real_ts->tv_nsec -= 1000000000L;
     488             :                 }
     489             : 
     490             :                 /* all formats have a - make sense in front */
     491           0 :                 ret += bputch(buf, '-');
     492             :         }
     493             : 
     494           0 :         if (flags & TIMEFMT_DECIMAL) {
     495           0 :                 ret += bprintfrr(buf, "%lld", (long long)real_ts->tv_sec);
     496           0 :                 if (precision == -1)
     497           0 :                         precision = 3;
     498           0 :                 ret += do_subsec(buf, real_ts, precision, flags);
     499           0 :                 return ret;
     500             :         }
     501             : 
     502             :         /* these divisions may be slow on embedded boxes, hence only do the
     503             :          * ones we need, plus the ?: zero check to hopefully skip zeros fast
     504             :          */
     505           0 :         lldiv_t min_sec = lldiv(real_ts->tv_sec, 60);
     506             : 
     507           0 :         if (flags & TIMEFMT_MMSS) {
     508           0 :                 ret += bprintfrr(buf, "%02lld:%02lld", min_sec.quot,
     509             :                                  min_sec.rem);
     510           0 :                 ret += do_subsec(buf, real_ts, precision, flags);
     511           0 :                 return ret;
     512             :         }
     513             : 
     514           0 :         lldiv_t hour_min = min_sec.quot ? lldiv(min_sec.quot, 60) : (lldiv_t){};
     515             : 
     516           0 :         if (flags & TIMEFMT_HHMMSS) {
     517           0 :                 ret += bprintfrr(buf, "%02lld:%02lld:%02lld", hour_min.quot,
     518             :                                  hour_min.rem, min_sec.rem);
     519           0 :                 ret += do_subsec(buf, real_ts, precision, flags);
     520           0 :                 return ret;
     521             :         }
     522             : 
     523           0 :         lldiv_t day_hour =
     524           0 :                 hour_min.quot ? lldiv(hour_min.quot, 24) : (lldiv_t){};
     525           0 :         lldiv_t week_day =
     526           0 :                 day_hour.quot ? lldiv(day_hour.quot, 7) : (lldiv_t){};
     527             : 
     528             :         /* if sub-second precision is not supported, return */
     529           0 :         if (flags & TIMEFMT_BASIC) {
     530             :                 /* match frrtime_to_interval (without space flag) */
     531           0 :                 if (week_day.quot)
     532           0 :                         ret += bprintfrr(buf, "%lldw%s%lldd%s%02lldh",
     533             :                                          week_day.quot, space, week_day.rem,
     534             :                                          space, day_hour.rem);
     535           0 :                 else if (day_hour.quot)
     536           0 :                         ret += bprintfrr(buf, "%lldd%s%02lldh%s%02lldm",
     537             :                                          day_hour.quot, space, day_hour.rem,
     538             :                                          space, hour_min.rem);
     539             :                 else
     540           0 :                         ret += bprintfrr(buf, "%02lld:%02lld:%02lld",
     541             :                                          hour_min.quot, hour_min.rem,
     542             :                                          min_sec.rem);
     543             :                 /* no sub-seconds here */
     544           0 :                 return ret;
     545             :         }
     546             : 
     547             :         /* default format */
     548           0 :         if (week_day.quot)
     549           0 :                 ret += bprintfrr(buf, "%lldw%s", week_day.quot, space);
     550           0 :         if (week_day.rem || week_day.quot)
     551           0 :                 ret += bprintfrr(buf, "%lldd%s", week_day.rem, space);
     552             : 
     553           0 :         ret += bprintfrr(buf, "%02lld:%02lld:%02lld", day_hour.rem,
     554             :                          hour_min.rem, min_sec.rem);
     555             : 
     556           0 :         if (precision == -1)
     557           0 :                 precision = 3;
     558           0 :         ret += do_subsec(buf, real_ts, precision, flags);
     559           0 :         return ret;
     560             : }
     561             : 
     562          12 : printfrr_ext_autoreg_p("TS", printfrr_ts);
     563           0 : static ssize_t printfrr_ts(struct fbuf *buf, struct printfrr_eargs *ea,
     564             :                            const void *vptr)
     565             : {
     566           0 :         const struct timespec *ts = vptr;
     567             : 
     568           0 :         return printfrr_time(buf, ea, ts, 0);
     569             : }
     570             : 
     571          12 : printfrr_ext_autoreg_p("TV", printfrr_tv);
     572           0 : static ssize_t printfrr_tv(struct fbuf *buf, struct printfrr_eargs *ea,
     573             :                            const void *vptr)
     574             : {
     575           0 :         const struct timeval *tv = vptr;
     576           0 :         struct timespec ts;
     577             : 
     578           0 :         if (!tv)
     579           0 :                 return printfrr_time(buf, ea, NULL, 0);
     580             : 
     581           0 :         ts.tv_sec = tv->tv_sec;
     582           0 :         ts.tv_nsec = tv->tv_usec * 1000;
     583           0 :         return printfrr_time(buf, ea, &ts, 0);
     584             : }
     585             : 
     586          12 : printfrr_ext_autoreg_p("TT", printfrr_tt);
     587           0 : static ssize_t printfrr_tt(struct fbuf *buf, struct printfrr_eargs *ea,
     588             :                            const void *vptr)
     589             : {
     590           0 :         const time_t *tt = vptr;
     591           0 :         struct timespec ts;
     592             : 
     593           0 :         if (!tt)
     594           0 :                 return printfrr_time(buf, ea, NULL, TIMEFMT_SECONDS);
     595             : 
     596           0 :         ts.tv_sec = *tt;
     597           0 :         ts.tv_nsec = 0;
     598           0 :         return printfrr_time(buf, ea, &ts, TIMEFMT_SECONDS);
     599             : }

Generated by: LCOV version v1.16-topotato