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 if (fmt.fill_zero) 155 out.fill('0'); 156 157 switch (fmt.float_format) { 158 case Format::scientific: 159 if (fmt.precision != -1) { 160 if (fmt.width > 0) 161 out.width(fmt.width); 162 163 if (fmt.precision == 0) 164 fmt.precision = 1; 165 else 166 out.setf(std::ios::scientific); 167 168 out.precision(fmt.precision); 169 } else 170 if (fmt.width > 0) 171 out.width(fmt.width); 172 173 if (fmt.uppercase) 174 out.setf(std::ios::uppercase); 175 break; 176 177 case Format::fixed: 178 if (fmt.precision != -1) { 179 if (fmt.width > 0) 180 out.width(fmt.width); 181 182 out.setf(std::ios::fixed); 183 out.precision(fmt.precision); 184 } else 185 if (fmt.width > 0) 186 out.width(fmt.width); 187 188 break; 189 190 default: 191 if (fmt.precision != -1) 192 out.precision(fmt.precision); 193 194 if (fmt.width > 0) 195 out.width(fmt.width); 196 197 break; 198 } 199 200 out << data; 201 202 out.flags(flags); 203} 204 205template <typename T> 206inline void 207_format_string(std::ostream &out, const T &data, Format &fmt) 208{ 209 using namespace std; 210 211#if defined(__GNUC__) && (__GNUC__ < 3) || 1 212 if (fmt.width > 0) { 213 std::stringstream foo; 214 foo << data; 215 int flen = foo.str().size(); 216 217 if (fmt.width > flen) { 218 char *spaces = new char[fmt.width - flen + 1]; 219 memset(spaces, ' ', fmt.width - flen); 220 spaces[fmt.width - flen] = 0; 221 222 if (fmt.flush_left) 223 out << foo.str() << spaces; 224 else 225 out << spaces << foo.str(); 226 227 delete [] spaces; 228 } else 229 out << data; 230 } else 231 out << data; 232#else 233 if (fmt.width > 0) 234 out.width(fmt.width); 235 if (fmt.flush_left) 236 out.setf(std::ios::left); 237 238 out << data; 239#endif 240} 241 242///////////////////////////////////////////////////////////////////////////// 243// 244// The code below controls the actual usage of formats for various types 245// 246 247// 248// character formats 249// 250template <typename T> 251inline void 252format_char(std::ostream &out, const T &data, Format &fmt) 253{ out << "<bad arg type for char format>"; } 254 255inline void 256format_char(std::ostream &out, char data, Format &fmt) 257{ _format_char(out, data, fmt); } 258 259inline void 260format_char(std::ostream &out, unsigned char data, Format &fmt) 261{ _format_char(out, data, fmt); } 262 263inline void 264format_char(std::ostream &out, signed char data, Format &fmt) 265{ _format_char(out, data, fmt); } 266 267inline void 268format_char(std::ostream &out, short data, Format &fmt) 269{ _format_char(out, (char)data, fmt); } 270 271inline void 272format_char(std::ostream &out, unsigned short data, Format &fmt) 273{ _format_char(out, (char)data, fmt); } 274 275inline void 276format_char(std::ostream &out, int data, Format &fmt) 277{ _format_char(out, (char)data, fmt); } 278 279inline void 280format_char(std::ostream &out, unsigned int data, Format &fmt) 281{ _format_char(out, (char)data, fmt); } 282 283inline void 284format_char(std::ostream &out, long data, Format &fmt) 285{ _format_char(out, (char)data, fmt); } 286 287inline void 288format_char(std::ostream &out, unsigned long data, Format &fmt) 289{ _format_char(out, (char)data, fmt); } 290 291inline void 292format_char(std::ostream &out, long long data, Format &fmt) 293{ _format_char(out, (char)data, fmt); } 294 295inline void 296format_char(std::ostream &out, unsigned long long data, Format &fmt) 297{ _format_char(out, (char)data, fmt); } 298 299// 300// integer formats 301// 302template <typename T> 303inline void 304format_integer(std::ostream &out, const T &data, Format &fmt) 305{ _format_integer(out, data, fmt); } 306inline void 307format_integer(std::ostream &out, char data, Format &fmt) 308{ _format_integer(out, (int)data, fmt); } 309inline void 310format_integer(std::ostream &out, unsigned char data, Format &fmt) 311{ _format_integer(out, (int)data, fmt); } 312inline void 313format_integer(std::ostream &out, signed char data, Format &fmt) 314{ _format_integer(out, (int)data, fmt); } 315 316// 317// floating point formats 318// 319template <typename T> 320inline void 321format_float(std::ostream &out, const T &data, Format &fmt) 322{ out << "<bad arg type for float format>"; } 323 324inline void 325format_float(std::ostream &out, float data, Format &fmt) 326{ _format_float(out, data, fmt); } 327 328inline void 329format_float(std::ostream &out, double data, Format &fmt) 330{ _format_float(out, data, fmt); } 331 332// 333// string formats 334// 335template <typename T> 336inline void 337format_string(std::ostream &out, const T &data, Format &fmt) 338{ _format_string(out, data, fmt); } 339 340} // namespace cp 341 342#endif // __CPRINTF_FORMATS_HH__ 343