/* * 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 #include #include 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 inline void _format_char(std::ostream &out, const T &data, Format &fmt) { using namespace std; out << data; } template 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 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 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 inline void format_char(std::ostream &out, const T &data, Format &fmt) { out << ""; } 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 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 inline void format_float(std::ostream &out, const T &data, Format &fmt) { out << ""; } 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 inline void format_string(std::ostream &out, const T &data, Format &fmt) { _format_string(out, data, fmt); } } // namespace cp #endif // __CPRINTF_FORMATS_HH__