cprintf_formats.hh revision 5756
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 __BASE_CPRINTF_FORMATS_HH__ 32#define __BASE_CPRINTF_FORMATS_HH__ 33 34#include <cstring> 35#include <ostream> 36#include <sstream> 37 38namespace cp { 39 40struct Format 41{ 42 bool alternate_form; 43 bool flush_left; 44 bool print_sign; 45 bool blank_space; 46 bool fill_zero; 47 bool uppercase; 48 enum { dec, hex, oct } base; 49 enum { none, string, integer, character, floating } format; 50 enum { best, fixed, scientific } float_format; 51 int precision; 52 int width; 53 bool get_precision; 54 bool get_width; 55 56 Format() { clear(); } 57 58 void clear() 59 { 60 alternate_form = false; 61 flush_left = false; 62 print_sign = false; 63 blank_space = false; 64 fill_zero = false; 65 uppercase = false; 66 base = dec; 67 format = none; 68 precision = -1; 69 width = 0; 70 get_precision = false; 71 get_width = false; 72 } 73}; 74 75template <typename T> 76inline void 77_format_char(std::ostream &out, const T &data, Format &fmt) 78{ 79 using namespace std; 80 81 out << data; 82} 83 84template <typename T> 85inline void 86_format_integer(std::ostream &out, const T &data, Format &fmt) 87{ 88 using namespace std; 89 90 switch (fmt.base) { 91 case Format::hex: 92 out.setf(std::ios::hex, std::ios::basefield); 93 break; 94 95 case Format::oct: 96 out.setf(std::ios::oct, std::ios::basefield); 97 break; 98 99 case Format::dec: 100 out.setf(std::ios::dec, std::ios::basefield); 101 break; 102 } 103 104 if (fmt.alternate_form) { 105 if (!fmt.fill_zero) 106 out.setf(std::ios::showbase); 107 else { 108 switch (fmt.base) { 109 case Format::hex: 110 out << "0x"; 111 fmt.width -= 2; 112 break; 113 case Format::oct: 114 out << "0"; 115 fmt.width -= 1; 116 break; 117 case Format::dec: 118 break; 119 } 120 } 121 } 122 123 if (fmt.fill_zero) 124 out.fill('0'); 125 126 if (fmt.width > 0) 127 out.width(fmt.width); 128 129 if (fmt.flush_left && !fmt.fill_zero) 130 out.setf(std::ios::left); 131 132 if (fmt.print_sign) 133 out.setf(std::ios::showpos); 134 135 if (fmt.uppercase) 136 out.setf(std::ios::uppercase); 137 138 out << data; 139} 140 141template <typename T> 142inline void 143_format_float(std::ostream &out, const T &data, Format &fmt) 144{ 145 using namespace std; 146 147 switch (fmt.float_format) { 148 case Format::scientific: 149 if (fmt.precision != -1) { 150 if (fmt.width > 0) 151 out.width(fmt.width); 152 153 if (fmt.precision == 0) 154 fmt.precision = 1; 155 else 156 out.setf(std::ios::scientific); 157 158 out.precision(fmt.precision); 159 } else 160 if (fmt.width > 0) 161 out.width(fmt.width); 162 163 if (fmt.uppercase) 164 out.setf(std::ios::uppercase); 165 break; 166 167 case Format::fixed: 168 if (fmt.precision != -1) { 169 if (fmt.width > 0) 170 out.width(fmt.width); 171 172 out.setf(std::ios::fixed); 173 out.precision(fmt.precision); 174 } else 175 if (fmt.width > 0) 176 out.width(fmt.width); 177 178 break; 179 180 default: 181 if (fmt.precision != -1) 182 out.precision(fmt.precision); 183 184 if (fmt.width > 0) 185 out.width(fmt.width); 186 187 break; 188 } 189 190 out << data; 191} 192 193template <typename T> 194inline void 195_format_string(std::ostream &out, const T &data, Format &fmt) 196{ 197 using namespace std; 198 199#if defined(__GNUC__) && (__GNUC__ < 3) || 1 200 if (fmt.width > 0) { 201 std::stringstream foo; 202 foo << data; 203 int flen = foo.str().size(); 204 205 if (fmt.width > flen) { 206 char *spaces = new char[fmt.width - flen + 1]; 207 memset(spaces, ' ', fmt.width - flen); 208 spaces[fmt.width - flen] = 0; 209 210 if (fmt.flush_left) 211 out << foo.str() << spaces; 212 else 213 out << spaces << foo.str(); 214 215 delete [] spaces; 216 } else 217 out << data; 218 } else 219 out << data; 220#else 221 if (fmt.width > 0) 222 out.width(fmt.width); 223 if (fmt.flush_left) 224 out.setf(std::ios::left); 225 226 out << data; 227#endif 228} 229 230///////////////////////////////////////////////////////////////////////////// 231// 232// The code below controls the actual usage of formats for various types 233// 234 235// 236// character formats 237// 238template <typename T> 239inline void 240format_char(std::ostream &out, const T &data, Format &fmt) 241{ out << "<bad arg type for char format>"; } 242 243inline void 244format_char(std::ostream &out, char data, Format &fmt) 245{ _format_char(out, data, fmt); } 246 247inline void 248format_char(std::ostream &out, unsigned char data, Format &fmt) 249{ _format_char(out, data, fmt); } 250 251inline void 252format_char(std::ostream &out, signed char data, Format &fmt) 253{ _format_char(out, data, fmt); } 254 255inline void 256format_char(std::ostream &out, short data, Format &fmt) 257{ _format_char(out, (char)data, fmt); } 258 259inline void 260format_char(std::ostream &out, unsigned short data, Format &fmt) 261{ _format_char(out, (char)data, fmt); } 262 263inline void 264format_char(std::ostream &out, int data, Format &fmt) 265{ _format_char(out, (char)data, fmt); } 266 267inline void 268format_char(std::ostream &out, unsigned int data, Format &fmt) 269{ _format_char(out, (char)data, fmt); } 270 271inline void 272format_char(std::ostream &out, long data, Format &fmt) 273{ _format_char(out, (char)data, fmt); } 274 275inline void 276format_char(std::ostream &out, unsigned long data, Format &fmt) 277{ _format_char(out, (char)data, fmt); } 278 279inline void 280format_char(std::ostream &out, long long data, Format &fmt) 281{ _format_char(out, (char)data, fmt); } 282 283inline void 284format_char(std::ostream &out, unsigned long long data, Format &fmt) 285{ _format_char(out, (char)data, fmt); } 286 287// 288// integer formats 289// 290template <typename T> 291inline void 292format_integer(std::ostream &out, const T &data, Format &fmt) 293{ _format_integer(out, data, fmt); } 294inline void 295format_integer(std::ostream &out, char data, Format &fmt) 296{ _format_integer(out, (int)data, fmt); } 297inline void 298format_integer(std::ostream &out, unsigned char data, Format &fmt) 299{ _format_integer(out, (int)data, fmt); } 300inline void 301format_integer(std::ostream &out, signed char data, Format &fmt) 302{ _format_integer(out, (int)data, fmt); } 303#if 0 304inline void 305format_integer(std::ostream &out, short data, Format &fmt) 306{ _format_integer(out, data, fmt); } 307inline void 308format_integer(std::ostream &out, unsigned short data, Format &fmt) 309{ _format_integer(out, data, fmt); } 310inline void 311format_integer(std::ostream &out, int data, Format &fmt) 312{ _format_integer(out, data, fmt); } 313inline void 314format_integer(std::ostream &out, unsigned int data, Format &fmt) 315{ _format_integer(out, data, fmt); } 316inline void 317format_integer(std::ostream &out, long data, Format &fmt) 318{ _format_integer(out, data, fmt); } 319inline void 320format_integer(std::ostream &out, unsigned long data, Format &fmt) 321{ _format_integer(out, data, fmt); } 322inline void 323format_integer(std::ostream &out, long long data, Format &fmt) 324{ _format_integer(out, data, fmt); } 325inline void 326format_integer(std::ostream &out, unsigned long long data, Format &fmt) 327{ _format_integer(out, data, fmt); } 328#endif 329 330// 331// floating point formats 332// 333template <typename T> 334inline void 335format_float(std::ostream &out, const T &data, Format &fmt) 336{ out << "<bad arg type for float format>"; } 337 338inline void 339format_float(std::ostream &out, float data, Format &fmt) 340{ _format_float(out, data, fmt); } 341 342inline void 343format_float(std::ostream &out, double data, Format &fmt) 344{ _format_float(out, data, fmt); } 345 346// 347// string formats 348// 349template <typename T> 350inline void 351format_string(std::ostream &out, const T &data, Format &fmt) 352{ _format_string(out, data, fmt); } 353 354inline void 355format_string(std::ostream &out, const std::stringstream &data, Format &fmt) 356{ _format_string(out, data.str(), fmt); } 357 358} // namespace cp 359 360#endif // __CPRINTF_FORMATS_HH__ 361