cprintf.hh revision 2632:1bb2f91485ea
1/*
2 * Copyright (c) 2002-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_HH__
30#define __CPRINTF_HH__
31
32#include <iostream>
33#include <list>
34#include <string>
35
36#include "base/cprintf_formats.hh"
37
38namespace cp {
39
40class ArgList
41{
42  private:
43    class Base
44    {
45      public:
46        virtual ~Base() {}
47        virtual void process(std::ostream &out, Format &fmt) = 0;
48    };
49
50    template <typename T>
51    class Node : public Base
52    {
53      public:
54        const T &data;
55
56      public:
57        Node(const T &d) : data(d) {}
58        virtual void process(std::ostream &out, Format &fmt) {
59            switch (fmt.format) {
60              case Format::character:
61                format_char(out, data, fmt);
62                break;
63
64              case Format::integer:
65                format_integer(out, data, fmt);
66                break;
67
68              case Format::floating:
69                format_float(out, data, fmt);
70                break;
71
72              case Format::string:
73                format_string(out, data, fmt);
74                break;
75
76              default:
77                out << "<bad format>";
78                break;
79            }
80        }
81    };
82
83    typedef std::list<Base *> list_t;
84
85  protected:
86    list_t objects;
87    std::ostream *stream;
88
89  public:
90    ArgList() : stream(&std::cout) {}
91    ~ArgList();
92
93    template<class T>
94    void append(const T &data) {
95        Base *obj = new ArgList::Node<T>(data);
96        objects.push_back(obj);
97    }
98
99    template<class T>
100    void prepend(const T &data) {
101        Base *obj = new ArgList::Node<T>(data);
102        objects.push_front(obj);
103    }
104
105    void dump(const std::string &format);
106    void dump(std::ostream &strm, const std::string &fmt)
107        { stream = &strm; dump(fmt); }
108
109    std::string dumpToString(const std::string &format);
110
111    friend ArgList &operator<<(std::ostream &str, ArgList &list);
112};
113
114template<class T>
115inline ArgList &
116operator,(ArgList &alist, const T &data)
117{
118    alist.append(data);
119    return alist;
120}
121
122class ArgListNull {
123};
124
125inline ArgList &
126operator,(ArgList &alist, ArgListNull)
127{ return alist; }
128
129//
130// cprintf(format, args, ...) prints to cout
131// (analogous to printf())
132//
133inline void
134__cprintf(const std::string &format, ArgList &args)
135{ args.dump(format); delete &args; }
136#define __cprintf__(format, args...) \
137    cp::__cprintf(format, (*(new cp::ArgList), args))
138#define cprintf(args...) \
139    __cprintf__(args, cp::ArgListNull())
140
141//
142// ccprintf(stream, format, args, ...) prints to the specified stream
143// (analogous to fprintf())
144//
145inline void
146__ccprintf(std::ostream &stream, const std::string &format, ArgList &args)
147{ args.dump(stream, format); delete &args; }
148#define __ccprintf__(stream, format, args...) \
149    cp::__ccprintf(stream, format, (*(new cp::ArgList), args))
150#define ccprintf(stream, args...) \
151    __ccprintf__(stream, args, cp::ArgListNull())
152
153//
154// csprintf(format, args, ...) returns a string
155// (roughly analogous to sprintf())
156//
157inline std::string
158__csprintf(const std::string &format, ArgList &args)
159{ std::string s = args.dumpToString(format); delete &args; return s; }
160#define __csprintf__(format, args...) \
161    cp::__csprintf(format, (*(new cp::ArgList), args))
162#define csprintf(args...) \
163    __csprintf__(args, cp::ArgListNull())
164
165template<class T>
166inline ArgList &
167operator<<(ArgList &list, const T &data)
168{
169    list.append(data);
170    return list;
171}
172
173inline ArgList &
174operator<<(std::ostream &str, ArgList &list)
175{
176    list.stream = &str;
177    return list;
178}
179
180class ArgListTemp
181{
182  private:
183    std::string format;
184    ArgList *args;
185
186  public:
187    ArgListTemp(const std::string &f) : format(f) { args = new ArgList; }
188    ~ArgListTemp() { args->dump(format); delete args; }
189
190    operator ArgList *() { return args; }
191};
192
193#define cformat(format) \
194    (*((cp::ArgList *)cp::ArgListTemp(format)))
195}
196
197#endif // __CPRINTF_HH__
198