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