cprintf.cc revision 56
19537Satgutier@umich.edu/* 29537Satgutier@umich.edu * Copyright (c) 2003 The Regents of The University of Michigan 39537Satgutier@umich.edu * All rights reserved. 49537Satgutier@umich.edu * 59537Satgutier@umich.edu * Redistribution and use in source and binary forms, with or without 69537Satgutier@umich.edu * modification, are permitted provided that the following conditions are 79537Satgutier@umich.edu * met: redistributions of source code must retain the above copyright 89537Satgutier@umich.edu * notice, this list of conditions and the following disclaimer; 99537Satgutier@umich.edu * redistributions in binary form must reproduce the above copyright 109537Satgutier@umich.edu * notice, this list of conditions and the following disclaimer in the 119537Satgutier@umich.edu * documentation and/or other materials provided with the distribution; 129537Satgutier@umich.edu * neither the name of the copyright holders nor the names of its 139537Satgutier@umich.edu * contributors may be used to endorse or promote products derived from 149537Satgutier@umich.edu * this software without specific prior written permission. 159537Satgutier@umich.edu * 169537Satgutier@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 179537Satgutier@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 189537Satgutier@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 199537Satgutier@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 209537Satgutier@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 219537Satgutier@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 229537Satgutier@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 239537Satgutier@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 249537Satgutier@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 259537Satgutier@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 269537Satgutier@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 279537Satgutier@umich.edu */ 289537Satgutier@umich.edu 299537Satgutier@umich.edu#include <cassert> 309537Satgutier@umich.edu#include <iomanip> 319537Satgutier@umich.edu#include <iostream> 329537Satgutier@umich.edu#include <sstream> 339537Satgutier@umich.edu 349537Satgutier@umich.edu#include "base/cprintf.hh" 359537Satgutier@umich.edu 369537Satgutier@umich.eduusing namespace std; 379537Satgutier@umich.edu 389537Satgutier@umich.edunamespace cp { 399537Satgutier@umich.edu 409537Satgutier@umich.eduvoid 419537Satgutier@umich.eduArgList::dump(const string &format) 429537Satgutier@umich.edu{ 439537Satgutier@umich.edu const char *p = format.c_str(); 449537Satgutier@umich.edu 459537Satgutier@umich.edu stream->fill(' '); 469537Satgutier@umich.edu stream->flags((ios::fmtflags)0); 479537Satgutier@umich.edu 489537Satgutier@umich.edu Format fmt; 499537Satgutier@umich.edu 509537Satgutier@umich.edu while (*p) { 519537Satgutier@umich.edu switch (*p) { 529537Satgutier@umich.edu case '%': { 539537Satgutier@umich.edu if (p[1] == '%') { 549537Satgutier@umich.edu *stream << '%'; 559537Satgutier@umich.edu p += 2; 569537Satgutier@umich.edu continue; 579537Satgutier@umich.edu } 589537Satgutier@umich.edu 599537Satgutier@umich.edu if (objects.empty()) 609537Satgutier@umich.edu format_invalid(*stream); 619537Satgutier@umich.edu 629537Satgutier@umich.edu Base *data = objects.front(); 639537Satgutier@umich.edu 649537Satgutier@umich.edu fmt.clear(); 659537Satgutier@umich.edu bool done = false; 669537Satgutier@umich.edu bool end_number = false; 679537Satgutier@umich.edu bool have_precision = false; 689537Satgutier@umich.edu int number = 0; 699537Satgutier@umich.edu 709537Satgutier@umich.edu while (!done) { 719537Satgutier@umich.edu ++p; 729537Satgutier@umich.edu if (*p >= '0' && *p <= '9') { 739537Satgutier@umich.edu if (end_number) 749537Satgutier@umich.edu continue; 759537Satgutier@umich.edu } else if (number > 0) 769537Satgutier@umich.edu end_number = true; 779537Satgutier@umich.edu 789537Satgutier@umich.edu switch (*p) { 799537Satgutier@umich.edu case 's': 809537Satgutier@umich.edu fmt.format = Format::string; 819537Satgutier@umich.edu done = true; 829537Satgutier@umich.edu break; 839537Satgutier@umich.edu 849537Satgutier@umich.edu case 'c': 859537Satgutier@umich.edu fmt.format = Format::character; 869537Satgutier@umich.edu done = true; 879537Satgutier@umich.edu break; 889537Satgutier@umich.edu 899537Satgutier@umich.edu case 'l': 909537Satgutier@umich.edu continue; 919537Satgutier@umich.edu 929537Satgutier@umich.edu case 'p': 939537Satgutier@umich.edu fmt.format = Format::integer; 949537Satgutier@umich.edu fmt.base = Format::hex; 959537Satgutier@umich.edu fmt.alternate_form = true; 969537Satgutier@umich.edu done = true; 979537Satgutier@umich.edu break; 989537Satgutier@umich.edu 999537Satgutier@umich.edu case 'X': 1009537Satgutier@umich.edu fmt.uppercase = true; 1019537Satgutier@umich.edu case 'x': 1029537Satgutier@umich.edu fmt.base = Format::hex; 1039537Satgutier@umich.edu fmt.format = Format::integer; 1049537Satgutier@umich.edu done = true; 1059537Satgutier@umich.edu break; 1069537Satgutier@umich.edu 1079537Satgutier@umich.edu case 'o': 1089537Satgutier@umich.edu fmt.base = Format::oct; 1099537Satgutier@umich.edu fmt.format = Format::integer; 1109537Satgutier@umich.edu done = true; 1119537Satgutier@umich.edu break; 1129537Satgutier@umich.edu 1139537Satgutier@umich.edu case 'd': 1149537Satgutier@umich.edu case 'i': 1159537Satgutier@umich.edu case 'u': 1169537Satgutier@umich.edu fmt.format = Format::integer; 1179537Satgutier@umich.edu done = true; 1189537Satgutier@umich.edu break; 1199537Satgutier@umich.edu 1209537Satgutier@umich.edu case 'G': 1219537Satgutier@umich.edu fmt.uppercase = true; 1229537Satgutier@umich.edu case 'g': 1239537Satgutier@umich.edu fmt.format = Format::floating; 1249537Satgutier@umich.edu fmt.float_format = Format::best; 1259537Satgutier@umich.edu done = true; 1269537Satgutier@umich.edu break; 1279537Satgutier@umich.edu 1289537Satgutier@umich.edu case 'E': 1299537Satgutier@umich.edu fmt.uppercase = true; 1309537Satgutier@umich.edu case 'e': 1319537Satgutier@umich.edu fmt.format = Format::floating; 1329537Satgutier@umich.edu fmt.float_format = Format::scientific; 1339537Satgutier@umich.edu done = true; 1349537Satgutier@umich.edu break; 1359537Satgutier@umich.edu 1369537Satgutier@umich.edu case 'f': 1379537Satgutier@umich.edu fmt.format = Format::floating; 1389537Satgutier@umich.edu fmt.float_format = Format::fixed; 1399537Satgutier@umich.edu done = true; 1409537Satgutier@umich.edu break; 1419537Satgutier@umich.edu 1429537Satgutier@umich.edu case 'n': 1439537Satgutier@umich.edu *stream << "we don't do %n!!!\n"; 1449537Satgutier@umich.edu done = true; 1459537Satgutier@umich.edu break; 1469537Satgutier@umich.edu 1479537Satgutier@umich.edu case '#': 1489537Satgutier@umich.edu fmt.alternate_form = true; 1499537Satgutier@umich.edu break; 1509537Satgutier@umich.edu 1519537Satgutier@umich.edu case '-': 1529537Satgutier@umich.edu fmt.flush_left = true; 1539537Satgutier@umich.edu break; 1549537Satgutier@umich.edu 1559537Satgutier@umich.edu case '+': 1569537Satgutier@umich.edu fmt.print_sign = true; 1579537Satgutier@umich.edu break; 1589537Satgutier@umich.edu 1599537Satgutier@umich.edu case ' ': 1609537Satgutier@umich.edu fmt.blank_space = true; 1619537Satgutier@umich.edu break; 1629537Satgutier@umich.edu 1639537Satgutier@umich.edu case '.': 1649537Satgutier@umich.edu fmt.width = number; 1659537Satgutier@umich.edu fmt.precision = 0; 1669537Satgutier@umich.edu have_precision = true; 1679537Satgutier@umich.edu number = 0; 1689537Satgutier@umich.edu end_number = false; 1699537Satgutier@umich.edu break; 1709537Satgutier@umich.edu 1719537Satgutier@umich.edu case '0': 1729537Satgutier@umich.edu if (number == 0) { 1739537Satgutier@umich.edu fmt.fill_zero = true; 1749537Satgutier@umich.edu break; 1759537Satgutier@umich.edu } 1769537Satgutier@umich.edu case '1': 1779537Satgutier@umich.edu case '2': 1789537Satgutier@umich.edu case '3': 1799537Satgutier@umich.edu case '4': 1809537Satgutier@umich.edu case '5': 1819537Satgutier@umich.edu case '6': 1829537Satgutier@umich.edu case '7': 1839537Satgutier@umich.edu case '8': 1849537Satgutier@umich.edu case '9': 1859537Satgutier@umich.edu number = number * 10 + (*p - '0'); 1869537Satgutier@umich.edu break; 1879537Satgutier@umich.edu 1889537Satgutier@umich.edu case '%': 1899537Satgutier@umich.edu assert("we shouldn't get here"); 1909537Satgutier@umich.edu break; 1919537Satgutier@umich.edu 1929537Satgutier@umich.edu default: 1939537Satgutier@umich.edu done = true; 1949537Satgutier@umich.edu break; 1959537Satgutier@umich.edu } 1969537Satgutier@umich.edu 1979537Satgutier@umich.edu if (end_number) { 1989537Satgutier@umich.edu if (have_precision) 1999537Satgutier@umich.edu fmt.precision = number; 2009537Satgutier@umich.edu else 2019537Satgutier@umich.edu fmt.width = number; 2029537Satgutier@umich.edu 2039537Satgutier@umich.edu end_number = false; 2049537Satgutier@umich.edu number = 0; 2059537Satgutier@umich.edu } 2069537Satgutier@umich.edu } 2079537Satgutier@umich.edu 2089537Satgutier@umich.edu ios::fmtflags saved_flags = stream->flags(); 2099537Satgutier@umich.edu char old_fill = stream->fill(); 2109537Satgutier@umich.edu int old_precision = stream->precision(); 2119537Satgutier@umich.edu 2129537Satgutier@umich.edu data->process(*stream, fmt); 2139537Satgutier@umich.edu 2149537Satgutier@umich.edu stream->flags(saved_flags); 2159537Satgutier@umich.edu stream->fill(old_fill); 2169537Satgutier@umich.edu stream->precision(old_precision); 2179537Satgutier@umich.edu 2189537Satgutier@umich.edu delete data; 2199537Satgutier@umich.edu objects.pop_front(); 2209537Satgutier@umich.edu ++p; 2219537Satgutier@umich.edu } 2229537Satgutier@umich.edu break; 2239537Satgutier@umich.edu 2249537Satgutier@umich.edu case '\n': 2259537Satgutier@umich.edu *stream << endl; 2269537Satgutier@umich.edu ++p; 2279537Satgutier@umich.edu break; 2289537Satgutier@umich.edu case '\r': 2299537Satgutier@umich.edu ++p; 2309537Satgutier@umich.edu if (*p != '\n') 2319537Satgutier@umich.edu *stream << endl; 2329537Satgutier@umich.edu break; 2339537Satgutier@umich.edu 2349537Satgutier@umich.edu default: { 2359537Satgutier@umich.edu size_t len = strcspn(p, "%\n\r\0"); 2369537Satgutier@umich.edu stream->write(p, len); 2379537Satgutier@umich.edu p += len; 2389537Satgutier@umich.edu } 2399537Satgutier@umich.edu break; 2409537Satgutier@umich.edu } 2419537Satgutier@umich.edu 2429537Satgutier@umich.edu ios::iostate state = stream->rdstate(); 2439537Satgutier@umich.edu if (state) { 2449537Satgutier@umich.edu#if 0 2459537Satgutier@umich.edu cout << "stream->rdstate() == " << state << endl; 2469537Satgutier@umich.edu if (state & ios::badbit) 2479537Satgutier@umich.edu cout << "stream is bad!\n"; 2489537Satgutier@umich.edu if (state & ios::eofbit) 2499537Satgutier@umich.edu cout << "stream at eof!\n"; 2509537Satgutier@umich.edu if (state & ios::failbit) 2519537Satgutier@umich.edu cout << "stream failed!\n"; 2529537Satgutier@umich.edu if (state & ios::goodbit) 2539537Satgutier@umich.edu cout << "stream is good!!\n"; 2549537Satgutier@umich.edu#endif 2559537Satgutier@umich.edu stream->clear(); 2569537Satgutier@umich.edu } 2579537Satgutier@umich.edu } 2589537Satgutier@umich.edu 2599537Satgutier@umich.edu while (!objects.empty()) { 2609537Satgutier@umich.edu Base *data = objects.front(); 2619537Satgutier@umich.edu data->process(*stream, fmt); 2629537Satgutier@umich.edu delete data; 2639537Satgutier@umich.edu objects.pop_front(); 2649537Satgutier@umich.edu } 2659537Satgutier@umich.edu} 2669537Satgutier@umich.edu 2679537Satgutier@umich.edustring 2689537Satgutier@umich.eduArgList::dumpToString(const string &format) 2699537Satgutier@umich.edu{ 2709537Satgutier@umich.edu stringstream ss; 2719537Satgutier@umich.edu 2729537Satgutier@umich.edu dump(ss, format); 2739537Satgutier@umich.edu 2749537Satgutier@umich.edu return ss.str(); 2759537Satgutier@umich.edu} 2769537Satgutier@umich.edu 2779537Satgutier@umich.edu} 2789537Satgutier@umich.edu