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