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