cprintf_formats.hh revision 502
112855Sgabeblack@google.com/* 212855Sgabeblack@google.com * Copyright (c) 2003 The Regents of The University of Michigan 312855Sgabeblack@google.com * All rights reserved. 412855Sgabeblack@google.com * 512855Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without 612855Sgabeblack@google.com * modification, are permitted provided that the following conditions are 712855Sgabeblack@google.com * met: redistributions of source code must retain the above copyright 812855Sgabeblack@google.com * notice, this list of conditions and the following disclaimer; 912855Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright 1012855Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the 1112855Sgabeblack@google.com * documentation and/or other materials provided with the distribution; 1212855Sgabeblack@google.com * neither the name of the copyright holders nor the names of its 1312855Sgabeblack@google.com * contributors may be used to endorse or promote products derived from 1412855Sgabeblack@google.com * this software without specific prior written permission. 1512855Sgabeblack@google.com * 1612855Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1712855Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1812855Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1912855Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2012855Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2112855Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2212855Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2312855Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2412855Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2512855Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2612855Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2712855Sgabeblack@google.com */ 2812855Sgabeblack@google.com 2912855Sgabeblack@google.com#ifndef __CPRINTF_FORMATS_HH__ 3012855Sgabeblack@google.com#define __CPRINTF_FORMATS_HH__ 3112855Sgabeblack@google.com 3212855Sgabeblack@google.comstruct Format 3312855Sgabeblack@google.com{ 3412855Sgabeblack@google.com bool alternate_form; 3512855Sgabeblack@google.com bool flush_left; 3612855Sgabeblack@google.com bool print_sign; 3712855Sgabeblack@google.com bool blank_space; 3812855Sgabeblack@google.com bool fill_zero; 3912855Sgabeblack@google.com bool uppercase; 4012855Sgabeblack@google.com enum { dec, hex, oct } base; 4112855Sgabeblack@google.com enum { none, string, integer, character, floating } format; 4212855Sgabeblack@google.com enum { best, fixed, scientific } float_format; 4312855Sgabeblack@google.com int precision; 4412855Sgabeblack@google.com int width; 4512855Sgabeblack@google.com 4612855Sgabeblack@google.com Format() { clear(); } 4712855Sgabeblack@google.com 4812855Sgabeblack@google.com void clear() 4912855Sgabeblack@google.com { 5012855Sgabeblack@google.com alternate_form = false; 5112855Sgabeblack@google.com flush_left = false; 5212855Sgabeblack@google.com print_sign = false; 5312855Sgabeblack@google.com blank_space = false; 5412855Sgabeblack@google.com fill_zero = false; 5512855Sgabeblack@google.com uppercase = false; 5612855Sgabeblack@google.com base = dec; 5712855Sgabeblack@google.com format = none; 5812855Sgabeblack@google.com precision = -1; 5912855Sgabeblack@google.com width = 0; 6012855Sgabeblack@google.com } 6112855Sgabeblack@google.com}; 6212855Sgabeblack@google.com 6312855Sgabeblack@google.comtemplate <typename T> 6412855Sgabeblack@google.cominline void 6512855Sgabeblack@google.com_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