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