| /* | |
| * Copyright (c) 2003-2005 The Regents of The University of Michigan | |
| * All rights reserved. | |
| * | |
| * Redistribution and use in source and binary forms, with or without | |
| * modification, are permitted provided that the following conditions are | |
| * met: redistributions of source code must retain the above copyright | |
| * notice, this list of conditions and the following disclaimer; | |
| * redistributions in binary form must reproduce the above copyright | |
| * notice, this list of conditions and the following disclaimer in the | |
| * documentation and/or other materials provided with the distribution; | |
| * neither the name of the copyright holders nor the names of its | |
| * contributors may be used to endorse or promote products derived from | |
| * this software without specific prior written permission. | |
| * | |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| * | |
| * Authors: Nathan Binkert | |
| */ | |
| #ifndef __BASE_CPRINTF_FORMATS_HH__ | |
| #define __BASE_CPRINTF_FORMATS_HH__ | |
| #include <cstring> | |
| #include <ostream> | |
| #include <sstream> | |
| namespace cp { | |
| struct Format | |
| { | |
| bool alternate_form; | |
| bool flush_left; | |
| bool print_sign; | |
| bool blank_space; | |
| bool fill_zero; | |
| bool uppercase; | |
| enum { dec, hex, oct } base; | |
| enum { none, string, integer, character, floating } format; | |
| enum { best, fixed, scientific } float_format; | |
| int precision; | |
| int width; | |
| bool get_precision; | |
| bool get_width; | |
| Format() { clear(); } | |
| void clear() | |
| { | |
| alternate_form = false; | |
| flush_left = false; | |
| print_sign = false; | |
| blank_space = false; | |
| fill_zero = false; | |
| uppercase = false; | |
| base = dec; | |
| format = none; | |
| float_format = best; | |
| precision = -1; | |
| width = 0; | |
| get_precision = false; | |
| get_width = false; | |
| } | |
| }; | |
| template <typename T> | |
| inline void | |
| _format_char(std::ostream &out, const T &data, Format &fmt) | |
| { | |
| using namespace std; | |
| out << data; | |
| } | |
| template <typename T> | |
| inline void | |
| _format_integer(std::ostream &out, const T &data, Format &fmt) | |
| { | |
| using namespace std; | |
| ios::fmtflags flags(out.flags()); | |
| switch (fmt.base) { | |
| case Format::hex: | |
| out.setf(std::ios::hex, std::ios::basefield); | |
| break; | |
| case Format::oct: | |
| out.setf(std::ios::oct, std::ios::basefield); | |
| break; | |
| case Format::dec: | |
| out.setf(std::ios::dec, std::ios::basefield); | |
| break; | |
| } | |
| if (fmt.alternate_form) { | |
| if (!fmt.fill_zero) | |
| out.setf(std::ios::showbase); | |
| else { | |
| switch (fmt.base) { | |
| case Format::hex: | |
| out << "0x"; | |
| fmt.width -= 2; | |
| break; | |
| case Format::oct: | |
| out << "0"; | |
| fmt.width -= 1; | |
| break; | |
| case Format::dec: | |
| break; | |
| } | |
| } | |
| } | |
| if (fmt.fill_zero) | |
| out.fill('0'); | |
| if (fmt.width > 0) | |
| out.width(fmt.width); | |
| if (fmt.flush_left && !fmt.fill_zero) | |
| out.setf(std::ios::left); | |
| if (fmt.print_sign) | |
| out.setf(std::ios::showpos); | |
| if (fmt.uppercase) | |
| out.setf(std::ios::uppercase); | |
| out << data; | |
| out.flags(flags); | |
| } | |
| template <typename T> | |
| inline void | |
| _format_float(std::ostream &out, const T &data, Format &fmt) | |
| { | |
| using namespace std; | |
| ios::fmtflags flags(out.flags()); | |
| if (fmt.fill_zero) | |
| out.fill('0'); | |
| switch (fmt.float_format) { | |
| case Format::scientific: | |
| if (fmt.precision != -1) { | |
| if (fmt.width > 0) | |
| out.width(fmt.width); | |
| if (fmt.precision == 0) | |
| fmt.precision = 1; | |
| else | |
| out.setf(std::ios::scientific); | |
| out.precision(fmt.precision); | |
| } else | |
| if (fmt.width > 0) | |
| out.width(fmt.width); | |
| if (fmt.uppercase) | |
| out.setf(std::ios::uppercase); | |
| break; | |
| case Format::fixed: | |
| if (fmt.precision != -1) { | |
| if (fmt.width > 0) | |
| out.width(fmt.width); | |
| out.setf(std::ios::fixed); | |
| out.precision(fmt.precision); | |
| } else | |
| if (fmt.width > 0) | |
| out.width(fmt.width); | |
| break; | |
| default: | |
| if (fmt.precision != -1) | |
| out.precision(fmt.precision); | |
| if (fmt.width > 0) | |
| out.width(fmt.width); | |
| break; | |
| } | |
| out << data; | |
| out.flags(flags); | |
| } | |
| template <typename T> | |
| inline void | |
| _format_string(std::ostream &out, const T &data, Format &fmt) | |
| { | |
| using namespace std; | |
| #if defined(__GNUC__) && (__GNUC__ < 3) || 1 | |
| if (fmt.width > 0) { | |
| std::stringstream foo; | |
| foo << data; | |
| int flen = foo.str().size(); | |
| if (fmt.width > flen) { | |
| char *spaces = new char[fmt.width - flen + 1]; | |
| memset(spaces, ' ', fmt.width - flen); | |
| spaces[fmt.width - flen] = 0; | |
| if (fmt.flush_left) | |
| out << foo.str() << spaces; | |
| else | |
| out << spaces << foo.str(); | |
| delete [] spaces; | |
| } else | |
| out << data; | |
| } else | |
| out << data; | |
| #else | |
| if (fmt.width > 0) | |
| out.width(fmt.width); | |
| if (fmt.flush_left) | |
| out.setf(std::ios::left); | |
| out << data; | |
| #endif | |
| } | |
| ///////////////////////////////////////////////////////////////////////////// | |
| // | |
| // The code below controls the actual usage of formats for various types | |
| // | |
| // | |
| // character formats | |
| // | |
| template <typename T> | |
| inline void | |
| format_char(std::ostream &out, const T &data, Format &fmt) | |
| { out << "<bad arg type for char format>"; } | |
| inline void | |
| format_char(std::ostream &out, char data, Format &fmt) | |
| { _format_char(out, data, fmt); } | |
| inline void | |
| format_char(std::ostream &out, unsigned char data, Format &fmt) | |
| { _format_char(out, data, fmt); } | |
| inline void | |
| format_char(std::ostream &out, signed char data, Format &fmt) | |
| { _format_char(out, data, fmt); } | |
| inline void | |
| format_char(std::ostream &out, short data, Format &fmt) | |
| { _format_char(out, (char)data, fmt); } | |
| inline void | |
| format_char(std::ostream &out, unsigned short data, Format &fmt) | |
| { _format_char(out, (char)data, fmt); } | |
| inline void | |
| format_char(std::ostream &out, int data, Format &fmt) | |
| { _format_char(out, (char)data, fmt); } | |
| inline void | |
| format_char(std::ostream &out, unsigned int data, Format &fmt) | |
| { _format_char(out, (char)data, fmt); } | |
| inline void | |
| format_char(std::ostream &out, long data, Format &fmt) | |
| { _format_char(out, (char)data, fmt); } | |
| inline void | |
| format_char(std::ostream &out, unsigned long data, Format &fmt) | |
| { _format_char(out, (char)data, fmt); } | |
| inline void | |
| format_char(std::ostream &out, long long data, Format &fmt) | |
| { _format_char(out, (char)data, fmt); } | |
| inline void | |
| format_char(std::ostream &out, unsigned long long data, Format &fmt) | |
| { _format_char(out, (char)data, fmt); } | |
| // | |
| // integer formats | |
| // | |
| template <typename T> | |
| inline void | |
| format_integer(std::ostream &out, const T &data, Format &fmt) | |
| { _format_integer(out, data, fmt); } | |
| inline void | |
| format_integer(std::ostream &out, char data, Format &fmt) | |
| { _format_integer(out, (int)data, fmt); } | |
| inline void | |
| format_integer(std::ostream &out, unsigned char data, Format &fmt) | |
| { _format_integer(out, (int)data, fmt); } | |
| inline void | |
| format_integer(std::ostream &out, signed char data, Format &fmt) | |
| { _format_integer(out, (int)data, fmt); } | |
| // | |
| // floating point formats | |
| // | |
| template <typename T> | |
| inline void | |
| format_float(std::ostream &out, const T &data, Format &fmt) | |
| { out << "<bad arg type for float format>"; } | |
| inline void | |
| format_float(std::ostream &out, float data, Format &fmt) | |
| { _format_float(out, data, fmt); } | |
| inline void | |
| format_float(std::ostream &out, double data, Format &fmt) | |
| { _format_float(out, data, fmt); } | |
| // | |
| // string formats | |
| // | |
| template <typename T> | |
| inline void | |
| format_string(std::ostream &out, const T &data, Format &fmt) | |
| { _format_string(out, data, fmt); } | |
| } // namespace cp | |
| #endif // __CPRINTF_FORMATS_HH__ |