cprintf_formats.hh revision 3940
1/* 2 * Copyright (c) 2003-2005 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Nathan Binkert 29 */ 30 31#ifndef __CPRINTF_FORMATS_HH__ 32#define __CPRINTF_FORMATS_HH__ 33 34#include <sstream> 35#include <ostream> 36 37namespace cp { 38 39struct Format 40{ 41 bool alternate_form; 42 bool flush_left; 43 bool print_sign; 44 bool blank_space; 45 bool fill_zero; 46 bool uppercase; 47 enum { dec, hex, oct } base; 48 enum { none, string, integer, character, floating } format; 49 enum { best, fixed, scientific } float_format; 50 int precision; 51 int width; 52 53 Format() { clear(); } 54 55 void clear() 56 { 57 alternate_form = false; 58 flush_left = false; 59 print_sign = false; 60 blank_space = false; 61 fill_zero = false; 62 uppercase = false; 63 base = dec; 64 format = none; 65 precision = -1; 66 width = 0; 67 } 68}; 69 70template <typename T> 71inline void 72_format_char(std::ostream &out, const T &data, Format &fmt) 73{ 74 using namespace std; 75 76 out << data; 77} 78 79template <typename T> 80inline void 81_format_integer(std::ostream &out, const T &data, Format &fmt) 82{ 83 using namespace std; 84 85 switch (fmt.base) { 86 case Format::hex: 87 out.setf(std::ios::hex, std::ios::basefield); 88 break; 89 90 case Format::oct: 91 out.setf(std::ios::oct, std::ios::basefield); 92 break; 93 94 case Format::dec: 95 out.setf(std::ios::dec, std::ios::basefield); 96 break; 97 } 98 99 if (fmt.alternate_form) { 100 if (!fmt.fill_zero) 101 out.setf(std::ios::showbase); 102 else { 103 switch (fmt.base) { 104 case Format::hex: 105 out << "0x"; 106 fmt.width -= 2; 107 break; 108 case Format::oct: 109 out << "0"; 110 fmt.width -= 1; 111 break; 112 case Format::dec: 113 break; 114 } 115 } 116 } 117 118 if (fmt.fill_zero) 119 out.fill('0'); 120 121 if (fmt.width > 0) 122 out.width(fmt.width); 123 124 if (fmt.flush_left && !fmt.fill_zero) 125 out.setf(std::ios::left); 126 127 if (fmt.print_sign) 128 out.setf(std::ios::showpos); 129 130 if (fmt.uppercase) 131 out.setf(std::ios::uppercase); 132 133 out << data; 134} 135 136template <typename T> 137inline void 138_format_float(std::ostream &out, const T &data, Format &fmt) 139{ 140 using namespace std; 141 142 switch (fmt.float_format) { 143 case Format::scientific: 144 if (fmt.precision != -1) { 145 if (fmt.width > 0) 146 out.width(fmt.width); 147 148 if (fmt.precision == 0) 149 fmt.precision = 1; 150 else 151 out.setf(std::ios::scientific); 152 153 out.precision(fmt.precision); 154 } else 155 if (fmt.width > 0) 156 out.width(fmt.width); 157 158 if (fmt.uppercase) 159 out.setf(std::ios::uppercase); 160 break; 161 162 case Format::fixed: 163 if (fmt.precision != -1) { 164 if (fmt.width > 0) 165 out.width(fmt.width); 166 167 out.setf(std::ios::fixed); 168 out.precision(fmt.precision); 169 } else 170 if (fmt.width > 0) 171 out.width(fmt.width); 172 173 break; 174 175 default: 176 if (fmt.precision != -1) 177 out.precision(fmt.precision); 178 179 if (fmt.width > 0) 180 out.width(fmt.width); 181 182 break; 183 } 184 185 out << data; 186} 187 188template <typename T> 189inline void 190_format_string(std::ostream &out, const T &data, Format &fmt) 191{ 192 using namespace std; 193 194#if defined(__GNUC__) && (__GNUC__ < 3) || 1 195 if (fmt.width > 0) { 196 std::stringstream foo; 197 foo << data; 198 int flen = foo.str().size(); 199 200 if (fmt.width > flen) { 201 char *spaces = new char[fmt.width - flen + 1]; 202 memset(spaces, ' ', fmt.width - flen); 203 spaces[fmt.width - flen] = 0; 204 205 if (fmt.flush_left) 206 out << foo.str() << spaces; 207 else 208 out << spaces << foo.str(); 209 210 delete [] spaces; 211 } else 212 out << data; 213 } else 214 out << data; 215#else 216 if (fmt.width > 0) 217 out.width(fmt.width); 218 if (fmt.flush_left) 219 out.setf(std::ios::left); 220 221 out << data; 222#endif 223} 224 225///////////////////////////////////////////////////////////////////////////// 226// 227// The code below controls the actual usage of formats for various types 228// 229 230// 231// character formats 232// 233template <typename T> 234inline void 235format_char(std::ostream &out, const T &data, Format &fmt) 236{ out << "<bad arg type for char format>"; } 237 238inline void 239format_char(std::ostream &out, char data, Format &fmt) 240{ _format_char(out, data, fmt); } 241 242inline void 243format_char(std::ostream &out, unsigned char data, Format &fmt) 244{ _format_char(out, data, fmt); } 245 246inline void 247format_char(std::ostream &out, signed char data, Format &fmt) 248{ _format_char(out, data, fmt); } 249 250inline void 251format_char(std::ostream &out, short data, Format &fmt) 252{ _format_char(out, (char)data, fmt); } 253 254inline void 255format_char(std::ostream &out, unsigned short data, Format &fmt) 256{ _format_char(out, (char)data, fmt); } 257 258inline void 259format_char(std::ostream &out, int data, Format &fmt) 260{ _format_char(out, (char)data, fmt); } 261 262inline void 263format_char(std::ostream &out, unsigned int data, Format &fmt) 264{ _format_char(out, (char)data, fmt); } 265 266inline void 267format_char(std::ostream &out, long data, Format &fmt) 268{ _format_char(out, (char)data, fmt); } 269 270inline void 271format_char(std::ostream &out, unsigned long data, Format &fmt) 272{ _format_char(out, (char)data, fmt); } 273 274inline void 275format_char(std::ostream &out, long long data, Format &fmt) 276{ _format_char(out, (char)data, fmt); } 277 278inline void 279format_char(std::ostream &out, unsigned long long data, Format &fmt) 280{ _format_char(out, (char)data, fmt); } 281 282// 283// integer formats 284// 285template <typename T> 286inline void 287format_integer(std::ostream &out, const T &data, Format &fmt) 288{ _format_integer(out, data, fmt); } 289inline void 290format_integer(std::ostream &out, char data, Format &fmt) 291{ _format_integer(out, (int)data, fmt); } 292inline void 293format_integer(std::ostream &out, unsigned char data, Format &fmt) 294{ _format_integer(out, (int)data, fmt); } 295inline void 296format_integer(std::ostream &out, signed char data, Format &fmt) 297{ _format_integer(out, (int)data, fmt); } 298#if 0 299inline void 300format_integer(std::ostream &out, short data, Format &fmt) 301{ _format_integer(out, data, fmt); } 302inline void 303format_integer(std::ostream &out, unsigned short data, Format &fmt) 304{ _format_integer(out, data, fmt); } 305inline void 306format_integer(std::ostream &out, int data, Format &fmt) 307{ _format_integer(out, data, fmt); } 308inline void 309format_integer(std::ostream &out, unsigned int data, Format &fmt) 310{ _format_integer(out, data, fmt); } 311inline void 312format_integer(std::ostream &out, long data, Format &fmt) 313{ _format_integer(out, data, fmt); } 314inline void 315format_integer(std::ostream &out, unsigned long data, Format &fmt) 316{ _format_integer(out, data, fmt); } 317inline void 318format_integer(std::ostream &out, long long data, Format &fmt) 319{ _format_integer(out, data, fmt); } 320inline void 321format_integer(std::ostream &out, unsigned long long data, Format &fmt) 322{ _format_integer(out, data, fmt); } 323#endif 324 325// 326// floating point formats 327// 328template <typename T> 329inline void 330format_float(std::ostream &out, const T &data, Format &fmt) 331{ out << "<bad arg type for float format>"; } 332 333inline void 334format_float(std::ostream &out, float data, Format &fmt) 335{ _format_float(out, data, fmt); } 336 337inline void 338format_float(std::ostream &out, double data, Format &fmt) 339{ _format_float(out, data, fmt); } 340 341// 342// string formats 343// 344template <typename T> 345inline void 346format_string(std::ostream &out, const T &data, Format &fmt) 347{ _format_string(out, data, fmt); } 348 349inline void 350format_string(std::ostream &out, const std::stringstream &data, Format &fmt) 351{ _format_string(out, data.str(), fmt); } 352 353} // namespace cp 354 355#endif // __CPRINTF_FORMATS_HH__ 356