cprintf_formats.hh revision 502
112855Sgabeblack@google.com/*
212855Sgabeblack@google.com * Copyright (c) 2003 The Regents of The University of Michigan
312855Sgabeblack@google.com * All rights reserved.
412855Sgabeblack@google.com *
512855Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without
612855Sgabeblack@google.com * modification, are permitted provided that the following conditions are
712855Sgabeblack@google.com * met: redistributions of source code must retain the above copyright
812855Sgabeblack@google.com * notice, this list of conditions and the following disclaimer;
912855Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright
1012855Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the
1112855Sgabeblack@google.com * documentation and/or other materials provided with the distribution;
1212855Sgabeblack@google.com * neither the name of the copyright holders nor the names of its
1312855Sgabeblack@google.com * contributors may be used to endorse or promote products derived from
1412855Sgabeblack@google.com * this software without specific prior written permission.
1512855Sgabeblack@google.com *
1612855Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1712855Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1812855Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1912855Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2012855Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2112855Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2212855Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2312855Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2412855Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2512855Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2612855Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2712855Sgabeblack@google.com */
2812855Sgabeblack@google.com
2912855Sgabeblack@google.com#ifndef __CPRINTF_FORMATS_HH__
3012855Sgabeblack@google.com#define __CPRINTF_FORMATS_HH__
3112855Sgabeblack@google.com
3212855Sgabeblack@google.comstruct Format
3312855Sgabeblack@google.com{
3412855Sgabeblack@google.com    bool alternate_form;
3512855Sgabeblack@google.com    bool flush_left;
3612855Sgabeblack@google.com    bool print_sign;
3712855Sgabeblack@google.com    bool blank_space;
3812855Sgabeblack@google.com    bool fill_zero;
3912855Sgabeblack@google.com    bool uppercase;
4012855Sgabeblack@google.com    enum { dec, hex, oct } base;
4112855Sgabeblack@google.com    enum { none, string, integer, character, floating } format;
4212855Sgabeblack@google.com    enum { best, fixed, scientific } float_format;
4312855Sgabeblack@google.com    int precision;
4412855Sgabeblack@google.com    int width;
4512855Sgabeblack@google.com
4612855Sgabeblack@google.com    Format() { clear(); }
4712855Sgabeblack@google.com
4812855Sgabeblack@google.com    void clear()
4912855Sgabeblack@google.com    {
5012855Sgabeblack@google.com        alternate_form = false;
5112855Sgabeblack@google.com        flush_left = false;
5212855Sgabeblack@google.com        print_sign = false;
5312855Sgabeblack@google.com        blank_space = false;
5412855Sgabeblack@google.com        fill_zero = false;
5512855Sgabeblack@google.com        uppercase = false;
5612855Sgabeblack@google.com        base = dec;
5712855Sgabeblack@google.com        format = none;
5812855Sgabeblack@google.com        precision = -1;
5912855Sgabeblack@google.com        width = 0;
6012855Sgabeblack@google.com    }
6112855Sgabeblack@google.com};
6212855Sgabeblack@google.com
6312855Sgabeblack@google.comtemplate <typename T>
6412855Sgabeblack@google.cominline void
6512855Sgabeblack@google.com_format_char(std::ostream &out, const T &data, Format &fmt)
66{
67    using namespace std;
68
69    out << data;
70}
71
72template <typename T>
73inline void
74_format_integer(std::ostream &out, const T &data, Format &fmt)
75{
76    using namespace std;
77
78    switch (fmt.base) {
79      case Format::hex:
80        out.setf(ios::hex, ios::basefield);
81        break;
82
83      case Format::oct:
84        out.setf(ios::oct, ios::basefield);
85        break;
86
87      case Format::dec:
88        out.setf(ios::dec, ios::basefield);
89        break;
90    }
91
92    if (fmt.alternate_form) {
93        if (!fmt.fill_zero)
94            out.setf(ios::showbase);
95        else {
96            switch (fmt.base) {
97              case Format::hex:
98                out << "0x";
99                fmt.width -= 2;
100                break;
101              case Format::oct:
102                out << "0";
103                fmt.width -= 1;
104                break;
105              case Format::dec:
106                break;
107            }
108        }
109    }
110
111    if (fmt.fill_zero)
112        out.fill('0');
113
114    if (fmt.width > 0)
115        out.width(fmt.width);
116
117    if (fmt.flush_left && !fmt.fill_zero)
118        out.setf(ios::left);
119
120    if (fmt.print_sign)
121        out.setf(ios::showpos);
122
123    if (fmt.uppercase)
124        out.setf(ios::uppercase);
125
126    out << data;
127}
128
129template <typename T>
130inline void
131_format_float(std::ostream &out, const T &data, Format &fmt)
132{
133    using namespace std;
134
135    switch (fmt.float_format) {
136      case Format::scientific:
137        if (fmt.precision != -1) {
138            if (fmt.width > 0)
139                out.width(fmt.width);
140
141            if (fmt.precision == 0)
142                fmt.precision = 1;
143            else
144                out.setf(ios::scientific);
145
146            out.precision(fmt.precision);
147        } else
148            if (fmt.width > 0)
149                out.width(fmt.width);
150
151        if (fmt.uppercase)
152            out.setf(ios::uppercase);
153        break;
154
155      case Format::fixed:
156        if (fmt.precision != -1) {
157            if (fmt.width > 0)
158                out.width(fmt.width);
159
160            out.setf(ios::fixed);
161            out.precision(fmt.precision);
162        } else
163            if (fmt.width > 0)
164                out.width(fmt.width);
165
166        break;
167
168      default:
169        if (fmt.precision != -1)
170            out.precision(fmt.precision);
171
172        if (fmt.width > 0)
173            out.width(fmt.width);
174
175        break;
176    }
177
178    out << data;
179}
180
181template <typename T>
182inline void
183_format_string(std::ostream &out, const T &data, Format &fmt)
184{
185    using namespace std;
186
187#if defined(__GNUC__) && (__GNUC__ < 3) || 1
188    if (fmt.width > 0) {
189        std::stringstream foo;
190        foo << data;
191        int flen = foo.str().size();
192
193        if (fmt.width > flen) {
194            char *spaces = new char[fmt.width - flen + 1];
195            memset(spaces, ' ', fmt.width - flen);
196            spaces[fmt.width - flen] = 0;
197
198            if (fmt.flush_left)
199                out << foo.str() << spaces;
200            else
201                out << spaces << foo.str();
202
203            delete [] spaces;
204        } else
205            out << data;
206    } else
207        out << data;
208#else
209    if (fmt.width > 0)
210        out.width(fmt.width);
211    if (fmt.flush_left)
212        out.setf(ios::left);
213
214    out << data;
215#endif
216}
217
218/////////////////////////////////////////////////////////////////////////////
219//
220//  The code below controls the actual usage of formats for various types
221//
222
223//
224// character formats
225//
226template <typename T>
227inline void
228format_char(std::ostream &out, const T &data, Format &fmt)
229{ out << "<bad arg type for char format>"; }
230
231inline void
232format_char(std::ostream &out, char data, Format &fmt)
233{ _format_char(out, data, fmt); }
234
235inline void
236format_char(std::ostream &out, unsigned char data, Format &fmt)
237{ _format_char(out, data, fmt); }
238
239inline void
240format_char(std::ostream &out, signed char data, Format &fmt)
241{ _format_char(out, data, fmt); }
242
243inline void
244format_char(std::ostream &out, short data, Format &fmt)
245{ _format_char(out, (char)data, fmt); }
246
247inline void
248format_char(std::ostream &out, unsigned short data, Format &fmt)
249{ _format_char(out, (char)data, fmt); }
250
251inline void
252format_char(std::ostream &out, int data, Format &fmt)
253{ _format_char(out, (char)data, fmt); }
254
255inline void
256format_char(std::ostream &out, unsigned int data, Format &fmt)
257{ _format_char(out, (char)data, fmt); }
258
259inline void
260format_char(std::ostream &out, long data, Format &fmt)
261{ _format_char(out, (char)data, fmt); }
262
263inline void
264format_char(std::ostream &out, unsigned long data, Format &fmt)
265{ _format_char(out, (char)data, fmt); }
266
267inline void
268format_char(std::ostream &out, long long data, Format &fmt)
269{ _format_char(out, (char)data, fmt); }
270
271inline void
272format_char(std::ostream &out, unsigned long long data, Format &fmt)
273{ _format_char(out, (char)data, fmt); }
274
275//
276// integer formats
277//
278template <typename T>
279inline void
280format_integer(std::ostream &out, const T &data, Format &fmt)
281{ _format_integer(out, data, fmt); }
282
283#if 0
284inline void
285format_integer(std::ostream &out, char data, Format &fmt)
286{ _format_integer(out, data, fmt); }
287inline void
288format_integer(std::ostream &out, unsigned char data, Format &fmt)
289{ _format_integer(out, data, fmt); }
290inline void
291format_integer(std::ostream &out, signed char data, Format &fmt)
292{ _format_integer(out, data, fmt); }
293inline void
294format_integer(std::ostream &out, short data, Format &fmt)
295{ _format_integer(out, data, fmt); }
296inline void
297format_integer(std::ostream &out, unsigned short data, Format &fmt)
298{ _format_integer(out, data, fmt); }
299inline void
300format_integer(std::ostream &out, int data, Format &fmt)
301{ _format_integer(out, data, fmt); }
302inline void
303format_integer(std::ostream &out, unsigned int data, Format &fmt)
304{ _format_integer(out, data, fmt); }
305inline void
306format_integer(std::ostream &out, long data, Format &fmt)
307{ _format_integer(out, data, fmt); }
308inline void
309format_integer(std::ostream &out, unsigned long data, Format &fmt)
310{ _format_integer(out, data, fmt); }
311inline void
312format_integer(std::ostream &out, long long data, Format &fmt)
313{ _format_integer(out, data, fmt); }
314inline void
315format_integer(std::ostream &out, unsigned long long data, Format &fmt)
316{ _format_integer(out, data, fmt); }
317#endif
318
319//
320// floating point formats
321//
322template <typename T>
323inline void
324format_float(std::ostream &out, const T &data, Format &fmt)
325{ out << "<bad arg type for float format>"; }
326
327inline void
328format_float(std::ostream &out, float data, Format &fmt)
329{ _format_float(out, data, fmt); }
330
331inline void
332format_float(std::ostream &out, double data, Format &fmt)
333{ _format_float(out, data, fmt); }
334
335//
336// string formats
337//
338template <typename T>
339inline void
340format_string(std::ostream &out, const T &data, Format &fmt)
341{ _format_string(out, data, fmt); }
342
343inline void
344format_string(std::ostream &out, const std::stringstream& data, Format &fmt)
345{ _format_string(out, data.str(), fmt); }
346
347#endif // __CPRINTF_FORMATS_HH__
348