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