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