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