cprintf_formats.hh revision 448
16899SN/A/*
26899SN/A * Copyright (c) 2003 The Regents of The University of Michigan
36899SN/A * All rights reserved.
46899SN/A *
56899SN/A * Redistribution and use in source and binary forms, with or without
66899SN/A * modification, are permitted provided that the following conditions are
76899SN/A * met: redistributions of source code must retain the above copyright
86899SN/A * notice, this list of conditions and the following disclaimer;
96899SN/A * redistributions in binary form must reproduce the above copyright
106899SN/A * notice, this list of conditions and the following disclaimer in the
116899SN/A * documentation and/or other materials provided with the distribution;
126899SN/A * neither the name of the copyright holders nor the names of its
136899SN/A * contributors may be used to endorse or promote products derived from
146899SN/A * this software without specific prior written permission.
156899SN/A *
166899SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
176899SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
186899SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
196899SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
206899SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
216899SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
226899SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
236899SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
246899SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
256899SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
266899SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
276899SN/A */
286899SN/A
296899SN/A#ifndef __CPRINTF_FORMATS_HH__
307053SN/A#define __CPRINTF_FORMATS_HH__
317053SN/A
326899SN/Astruct Format
337055SN/A{
347055SN/A    bool alternate_form;
357632SBrad.Beckmann@amd.com    bool flush_left;
367053SN/A    bool print_sign;
3714184Sgabeblack@google.com    bool blank_space;
3814184Sgabeblack@google.com    bool fill_zero;
397053SN/A    bool uppercase;
406899SN/A    enum { dec, hex, oct } base;
416899SN/A    enum { none, string, integer, character, floating } format;
426899SN/A    enum { best, fixed, scientific } float_format;
437053SN/A    int precision;
446899SN/A    int width;
457053SN/A
467053SN/A    Format() { clear(); }
477053SN/A
4811025Snilay@cs.wisc.edu    void clear()
498932SBrad.Beckmann@amd.com    {
506899SN/A        alternate_form = false;
517053SN/A        flush_left = false;
5210302Snilay@cs.wisc.edu        print_sign = false;
5311025Snilay@cs.wisc.edu        blank_space = false;
5411025Snilay@cs.wisc.edu        fill_zero = false;
556899SN/A        uppercase = false;
567055SN/A        base = dec;
576899SN/A        format = none;
587053SN/A        precision = -1;
598184Ssomayeh@cs.wisc.edu        width = 0;
607053SN/A    }
617053SN/A};
627053SN/A
636899SN/Atemplate <typename T>
647053SN/Ainline void
657053SN/A_format_char(std::ostream &out, const T& data, Format &fmt)
666899SN/A{
677053SN/A    using namespace std;
686899SN/A
697053SN/A    out << data;
709208Snilay@cs.wisc.edu}
717053SN/A
727053SN/Atemplate <typename T>
7311025Snilay@cs.wisc.eduinline void
7411025Snilay@cs.wisc.edu_format_integer(std::ostream &out, const T& data, Format &fmt)
758164Snilay@cs.wisc.edu{
768932SBrad.Beckmann@amd.com    using namespace std;
778932SBrad.Beckmann@amd.com
787053SN/A    switch (fmt.base) {
796899SN/A      case Format::hex:
806899SN/A        out.setf(ios::hex, ios::basefield);
817055SN/A        break;
827055SN/A
836899SN/A      case Format::oct:
847053SN/A        out.setf(ios::oct, ios::basefield);
857055SN/A        break;
867053SN/A
876899SN/A      case Format::dec:
886899SN/A        out.setf(ios::dec, ios::basefield);
897053SN/A        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