back to topotato report
topotato coverage report
Current view: top level - lib/printf - printfcommon.h (source / functions) Hit Total Coverage
Test: aggregated run ( view descriptions ) Lines: 40 51 78.4 %
Date: 2023-02-24 19:38:44 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /*-
       2             :  * SPDX-License-Identifier: BSD-3-Clause
       3             :  *
       4             :  * Copyright (c) 1990, 1993
       5             :  *      The Regents of the University of California.  All rights reserved.
       6             :  *
       7             :  * This code is derived from software contributed to Berkeley by
       8             :  * Chris Torek.
       9             :  *
      10             :  * Copyright (c) 2011 The FreeBSD Foundation
      11             :  * All rights reserved.
      12             :  * Portions of this software were developed by David Chisnall
      13             :  * under sponsorship from the FreeBSD Foundation.
      14             :  *
      15             :  * Redistribution and use in source and binary forms, with or without
      16             :  * modification, are permitted provided that the following conditions
      17             :  * are met:
      18             :  * 1. Redistributions of source code must retain the above copyright
      19             :  *    notice, this list of conditions and the following disclaimer.
      20             :  * 2. Redistributions in binary form must reproduce the above copyright
      21             :  *    notice, this list of conditions and the following disclaimer in the
      22             :  *    documentation and/or other materials provided with the distribution.
      23             :  * 3. Neither the name of the University nor the names of its contributors
      24             :  *    may be used to endorse or promote products derived from this software
      25             :  *    without specific prior written permission.
      26             :  *
      27             :  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
      28             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      29             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      30             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
      31             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      32             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      33             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      34             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      35             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      36             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      37             :  * SUCH DAMAGE.
      38             :  *
      39             :  * $FreeBSD$
      40             :  */
      41             : 
      42             : /*
      43             :  * This file defines common routines used by both printf and wprintf.
      44             :  * You must define CHAR to either char or wchar_t prior to including this.
      45             :  */
      46             : 
      47             : 
      48             : static CHAR     *__ujtoa(uintmax_t, CHAR *, int, int, const char *);
      49             : static CHAR     *__ultoa(u_long, CHAR *, int, int, const char *);
      50             : 
      51             : #define NIOV 8
      52             : struct io_state {
      53             :         struct fbuf *cb;
      54             :         size_t avail;
      55             : };
      56             : 
      57             : static inline void
      58       77311 : io_init(struct io_state *iop, struct fbuf *cb)
      59             : {
      60       77311 :         iop->cb = cb;
      61       77311 :         iop->avail = cb ? cb->len - (cb->pos - cb->buf) : 0;
      62             : }
      63             : 
      64             : /*
      65             :  * WARNING: The buffer passed to io_print() is not copied immediately; it must
      66             :  * remain valid until io_flush() is called.
      67             :  */
      68             : static inline int
      69      339029 : io_print(struct io_state *iop, const CHAR * __restrict ptr, size_t len)
      70             : {
      71      339029 :         size_t copylen = len;
      72             : 
      73      339029 :         if (!iop->cb)
      74             :                 return 0;
      75      339029 :         if (iop->avail < copylen)
      76             :                 copylen = iop->avail;
      77             : 
      78      339029 :         memcpy(iop->cb->pos, ptr, copylen);
      79      339029 :         iop->avail -= copylen;
      80      339029 :         iop->cb->pos += copylen;
      81      339029 :         return 0;
      82             : }
      83             : 
      84             : /*
      85             :  * Choose PADSIZE to trade efficiency vs. size.  If larger printf
      86             :  * fields occur frequently, increase PADSIZE and make the initialisers
      87             :  * below longer.
      88             :  */
      89             : #define PADSIZE 16              /* pad chunk size */
      90             : static const CHAR blanks[PADSIZE] =
      91             : {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
      92             : static const CHAR zeroes[PADSIZE] =
      93             : {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
      94             : 
      95             : /*
      96             :  * Pad with blanks or zeroes. 'with' should point to either the blanks array
      97             :  * or the zeroes array.
      98             :  */
      99             : static inline int
     100      283737 : io_pad(struct io_state *iop, int howmany, const CHAR * __restrict with)
     101             : {
     102      283737 :         int n;
     103             : 
     104      334114 :         while (howmany > 0) {
     105       50391 :                 n = (howmany >= PADSIZE) ? PADSIZE : howmany;
     106       50391 :                 if (io_print(iop, with, n))
     107             :                         return (-1);
     108       50377 :                 howmany -= n;
     109             :         }
     110             :         return (0);
     111             : }
     112             : 
     113             : /*
     114             :  * Print exactly len characters of the string spanning p to ep, truncating
     115             :  * or padding with 'with' as necessary.
     116             :  */
     117             : static inline int
     118             : io_printandpad(struct io_state *iop, const CHAR *p, const CHAR *ep,
     119             :                int len, const CHAR * __restrict with)
     120             : {
     121             :         int p_len;
     122             : 
     123             :         p_len = ep - p;
     124             :         if (p_len > len)
     125             :                 p_len = len;
     126             :         if (p_len > 0) {
     127             :                 if (io_print(iop, p, p_len))
     128             :                         return (-1);
     129             :         } else {
     130             :                 p_len = 0;
     131             :         }
     132             :         return (io_pad(iop, len - p_len, with));
     133             : }
     134             : 
     135             : /*
     136             :  * Convert an unsigned long to ASCII for printf purposes, returning
     137             :  * a pointer to the first character of the string representation.
     138             :  * Octal numbers can be forced to have a leading zero; hex numbers
     139             :  * use the given digits.
     140             :  */
     141             : static CHAR *
     142       91969 : __ultoa(u_long val, CHAR *endp, int base, int octzero, const char *xdigs)
     143             : {
     144       91969 :         CHAR *cp = endp;
     145       91969 :         long sval;
     146             : 
     147             :         /*
     148             :          * Handle the three cases separately, in the hope of getting
     149             :          * better/faster code.
     150             :          */
     151       91969 :         switch (base) {
     152       86908 :         case 10:
     153       86908 :                 if (val < 10) {      /* many numbers are 1 digit */
     154       57146 :                         *--cp = to_char(val);
     155       57146 :                         return (cp);
     156             :                 }
     157             :                 /*
     158             :                  * On many machines, unsigned arithmetic is harder than
     159             :                  * signed arithmetic, so we do at most one unsigned mod and
     160             :                  * divide; this is sufficient to reduce the range of
     161             :                  * the incoming value to where signed arithmetic works.
     162             :                  */
     163       29762 :                 if (val > LONG_MAX) {
     164           0 :                         *--cp = to_char(val % 10);
     165           0 :                         sval = val / 10;
     166             :                 } else
     167             :                         sval = val;
     168      214707 :                 do {
     169      214707 :                         *--cp = to_char(sval % 10);
     170      214707 :                         sval /= 10;
     171      214707 :                 } while (sval != 0);
     172             :                 break;
     173             : 
     174           0 :         case 8:
     175           0 :                 do {
     176           0 :                         *--cp = to_char(val & 7);
     177           0 :                         val >>= 3;
     178           0 :                 } while (val);
     179           0 :                 if (octzero && *cp != '0')
     180           0 :                         *--cp = '0';
     181             :                 break;
     182             : 
     183       44060 :         case 16:
     184       49121 :                 do {
     185       49121 :                         *--cp = xdigs[val & 15];
     186       49121 :                         val >>= 4;
     187       49121 :                 } while (val);
     188             :                 break;
     189             : 
     190           0 :         default:                        /* oops */
     191           0 :                 abort();
     192             :         }
     193             :         return (cp);
     194             : }
     195             : 
     196             : /* Identical to __ultoa, but for intmax_t. */
     197             : static CHAR *
     198        9555 : __ujtoa(uintmax_t val, CHAR *endp, int base, int octzero, const char *xdigs)
     199             : {
     200        9555 :         CHAR *cp = endp;
     201        9555 :         intmax_t sval;
     202             : 
     203             :         /* quick test for small values; __ultoa is typically much faster */
     204             :         /* (perhaps instead we should run until small, then call __ultoa?) */
     205        9555 :         if (val <= ULONG_MAX)
     206        9555 :                 return (__ultoa((u_long)val, endp, base, octzero, xdigs));
     207             :         switch (base) {
     208             :         case 10:
     209             :                 if (val < 10) {
     210             :                         *--cp = to_char(val % 10);
     211             :                         return (cp);
     212             :                 }
     213             :                 if (val > INTMAX_MAX) {
     214             :                         *--cp = to_char(val % 10);
     215             :                         sval = val / 10;
     216             :                 } else
     217             :                         sval = val;
     218             :                 do {
     219             :                         *--cp = to_char(sval % 10);
     220             :                         sval /= 10;
     221             :                 } while (sval != 0);
     222             :                 break;
     223             : 
     224             :         case 8:
     225             :                 do {
     226             :                         *--cp = to_char(val & 7);
     227             :                         val >>= 3;
     228             :                 } while (val);
     229             :                 if (octzero && *cp != '0')
     230             :                         *--cp = '0';
     231             :                 break;
     232             : 
     233             :         case 16:
     234             :                 do {
     235             :                         *--cp = xdigs[val & 15];
     236             :                         val >>= 4;
     237             :                 } while (val);
     238             :                 break;
     239             : 
     240             :         default:
     241             :                 abort();
     242             :         }
     243             :         return (cp);
     244             : }

Generated by: LCOV version v1.16-topotato