printfcommon.h revision 187277
1187277Sdas/*- 2187277Sdas * Copyright (c) 1990, 1993 3187277Sdas * The Regents of the University of California. All rights reserved. 4187277Sdas * 5187277Sdas * This code is derived from software contributed to Berkeley by 6187277Sdas * Chris Torek. 7187277Sdas * 8187277Sdas * Redistribution and use in source and binary forms, with or without 9187277Sdas * modification, are permitted provided that the following conditions 10187277Sdas * are met: 11187277Sdas * 1. Redistributions of source code must retain the above copyright 12187277Sdas * notice, this list of conditions and the following disclaimer. 13187277Sdas * 2. Redistributions in binary form must reproduce the above copyright 14187277Sdas * notice, this list of conditions and the following disclaimer in the 15187277Sdas * documentation and/or other materials provided with the distribution. 16187277Sdas * 4. Neither the name of the University nor the names of its contributors 17187277Sdas * may be used to endorse or promote products derived from this software 18187277Sdas * without specific prior written permission. 19187277Sdas * 20187277Sdas * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21187277Sdas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22187277Sdas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23187277Sdas * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24187277Sdas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25187277Sdas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26187277Sdas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27187277Sdas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28187277Sdas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29187277Sdas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30187277Sdas * SUCH DAMAGE. 31187277Sdas * 32187277Sdas * $FreeBSD: head/lib/libc/stdio/printfcommon.h 187277 2009-01-15 04:29:02Z das $ 33187277Sdas */ 34187277Sdas 35187277Sdas/* 36187277Sdas * This file defines common routines used by both printf and wprintf. 37187277Sdas * You must define CHAR to either char or wchar_t prior to including this. 38187277Sdas */ 39187277Sdas 40187277Sdas#define NIOV 8 41187277Sdasstruct io_state { 42187277Sdas FILE *fp; 43187277Sdas struct __suio uio; /* output information: summary */ 44187277Sdas struct __siov iov[NIOV];/* ... and individual io vectors */ 45187277Sdas struct __siov *iovp; /* pointer to next free slot in iov */ 46187277Sdas}; 47187277Sdas 48187277Sdasstatic inline void 49187277Sdasio_init(struct io_state *iop, FILE *fp) 50187277Sdas{ 51187277Sdas 52187277Sdas iop->uio.uio_iov = iop->iovp = iop->iov; 53187277Sdas iop->uio.uio_resid = 0; 54187277Sdas iop->uio.uio_iovcnt = 0; 55187277Sdas iop->fp = fp; 56187277Sdas} 57187277Sdas 58187277Sdas/* 59187277Sdas * WARNING: The buffer passed to io_print() is not copied immediately; it must 60187277Sdas * remain valid until io_flush() is called. 61187277Sdas */ 62187277Sdasstatic inline int 63187277Sdasio_print(struct io_state *iop, const CHAR * __restrict ptr, int len) 64187277Sdas{ 65187277Sdas 66187277Sdas iop->iovp->iov_base = (char *)ptr; 67187277Sdas iop->iovp->iov_len = len; 68187277Sdas iop->uio.uio_resid += len; 69187277Sdas iop->iovp++; 70187277Sdas if (++iop->uio.uio_iovcnt >= NIOV) { 71187277Sdas iop->iovp = iop->iov; 72187277Sdas return (__sprint(iop->fp, &iop->uio)); 73187277Sdas } 74187277Sdas return (0); 75187277Sdas} 76187277Sdas 77187277Sdas/* 78187277Sdas * Choose PADSIZE to trade efficiency vs. size. If larger printf 79187277Sdas * fields occur frequently, increase PADSIZE and make the initialisers 80187277Sdas * below longer. 81187277Sdas */ 82187277Sdas#define PADSIZE 16 /* pad chunk size */ 83187277Sdasstatic const CHAR blanks[PADSIZE] = 84187277Sdas{' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}; 85187277Sdasstatic const CHAR zeroes[PADSIZE] = 86187277Sdas{'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'}; 87187277Sdas 88187277Sdas/* 89187277Sdas * Pad with blanks or zeroes. 'with' should point to either the blanks array 90187277Sdas * or the zeroes array. 91187277Sdas */ 92187277Sdasstatic inline int 93187277Sdasio_pad(struct io_state *iop, int howmany, const CHAR * __restrict with) 94187277Sdas{ 95187277Sdas 96187277Sdas while (howmany > PADSIZE) { 97187277Sdas if (io_print(iop, with, PADSIZE)) 98187277Sdas return (-1); 99187277Sdas howmany -= PADSIZE; 100187277Sdas } 101187277Sdas if (howmany > 0 && io_print(iop, with, howmany)) 102187277Sdas return (-1); 103187277Sdas return (0); 104187277Sdas} 105187277Sdas 106187277Sdas/* 107187277Sdas * Print exactly len characters of the string spanning p to ep, truncating 108187277Sdas * or padding with 'with' as necessary. 109187277Sdas */ 110187277Sdasstatic inline int 111187277Sdasio_printandpad(struct io_state *iop, const CHAR *p, const CHAR *ep, 112187277Sdas int len, const CHAR * __restrict with) 113187277Sdas{ 114187277Sdas int p_len; 115187277Sdas 116187277Sdas p_len = ep - p; 117187277Sdas if (p_len > len) 118187277Sdas p_len = len; 119187277Sdas if (p_len > 0 && io_print(iop, p, p_len)) 120187277Sdas return (-1); 121187277Sdas return (io_pad(iop, len - (p_len > 0 ? p_len : 0), with)); 122187277Sdas} 123187277Sdas 124187277Sdasstatic inline int 125187277Sdasio_flush(struct io_state *iop) 126187277Sdas{ 127187277Sdas 128187277Sdas iop->iovp = iop->iov; 129187277Sdas return (__sprint(iop->fp, &iop->uio)); 130187277Sdas} 131