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