1/*
2 * Copyright (C) 2012 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. 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 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#ifndef PrintStream_h
27#define PrintStream_h
28
29#include <stdarg.h>
30#include "wtf/FastAllocBase.h"
31#include "wtf/Noncopyable.h"
32#include "wtf/StdLibExtras.h"
33
34namespace WTF {
35
36class CString;
37class String;
38
39class PrintStream {
40    WTF_MAKE_FAST_ALLOCATED; WTF_MAKE_NONCOPYABLE(PrintStream);
41public:
42    PrintStream();
43    virtual ~PrintStream();
44
45    void printf(const char* format, ...) WTF_ATTRIBUTE_PRINTF(2, 3);
46    virtual void vprintf(const char* format, va_list) WTF_ATTRIBUTE_PRINTF(2, 0) = 0;
47
48    // Typically a no-op for many subclasses of PrintStream, this is a hint that
49    // the implementation should flush its buffers if it had not done so already.
50    virtual void flush();
51
52    template<typename T>
53    void print(const T& value)
54    {
55        printInternal(*this, value);
56    }
57
58    template<typename T1, typename T2>
59    void print(const T1& value1, const T2& value2)
60    {
61        print(value1);
62        print(value2);
63    }
64
65    template<typename T1, typename T2, typename T3>
66    void print(const T1& value1, const T2& value2, const T3& value3)
67    {
68        print(value1);
69        print(value2);
70        print(value3);
71    }
72
73    template<typename T1, typename T2, typename T3, typename T4>
74    void print(const T1& value1, const T2& value2, const T3& value3, const T4& value4)
75    {
76        print(value1);
77        print(value2);
78        print(value3);
79        print(value4);
80    }
81
82    template<typename T1, typename T2, typename T3, typename T4, typename T5>
83    void print(const T1& value1, const T2& value2, const T3& value3, const T4& value4, const T5& value5)
84    {
85        print(value1);
86        print(value2);
87        print(value3);
88        print(value4);
89        print(value5);
90    }
91
92    template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
93    void print(const T1& value1, const T2& value2, const T3& value3, const T4& value4, const T5& value5, const T6& value6)
94    {
95        print(value1);
96        print(value2);
97        print(value3);
98        print(value4);
99        print(value5);
100        print(value6);
101    }
102
103    template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
104    void print(const T1& value1, const T2& value2, const T3& value3, const T4& value4, const T5& value5, const T6& value6, const T7& value7)
105    {
106        print(value1);
107        print(value2);
108        print(value3);
109        print(value4);
110        print(value5);
111        print(value6);
112        print(value7);
113    }
114
115    template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
116    void print(const T1& value1, const T2& value2, const T3& value3, const T4& value4, const T5& value5, const T6& value6, const T7& value7, const T8& value8)
117    {
118        print(value1);
119        print(value2);
120        print(value3);
121        print(value4);
122        print(value5);
123        print(value6);
124        print(value7);
125        print(value8);
126    }
127
128    template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
129    void print(const T1& value1, const T2& value2, const T3& value3, const T4& value4, const T5& value5, const T6& value6, const T7& value7, const T8& value8, const T9& value9)
130    {
131        print(value1);
132        print(value2);
133        print(value3);
134        print(value4);
135        print(value5);
136        print(value6);
137        print(value7);
138        print(value8);
139        print(value9);
140    }
141
142    template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10>
143    void print(const T1& value1, const T2& value2, const T3& value3, const T4& value4, const T5& value5, const T6& value6, const T7& value7, const T8& value8, const T9& value9, const T10& value10)
144    {
145        print(value1);
146        print(value2);
147        print(value3);
148        print(value4);
149        print(value5);
150        print(value6);
151        print(value7);
152        print(value8);
153        print(value9);
154        print(value10);
155    }
156
157    template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11>
158    void print(const T1& value1, const T2& value2, const T3& value3, const T4& value4, const T5& value5, const T6& value6, const T7& value7, const T8& value8, const T9& value9, const T10& value10, const T11& value11)
159    {
160        print(value1);
161        print(value2);
162        print(value3);
163        print(value4);
164        print(value5);
165        print(value6);
166        print(value7);
167        print(value8);
168        print(value9);
169        print(value10);
170        print(value11);
171    }
172
173    template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12>
174    void print(const T1& value1, const T2& value2, const T3& value3, const T4& value4, const T5& value5, const T6& value6, const T7& value7, const T8& value8, const T9& value9, const T10& value10, const T11& value11, const T12& value12)
175    {
176        print(value1);
177        print(value2);
178        print(value3);
179        print(value4);
180        print(value5);
181        print(value6);
182        print(value7);
183        print(value8);
184        print(value9);
185        print(value10);
186        print(value11);
187        print(value12);
188    }
189
190    template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13>
191    void print(const T1& value1, const T2& value2, const T3& value3, const T4& value4, const T5& value5, const T6& value6, const T7& value7, const T8& value8, const T9& value9, const T10& value10, const T11& value11, const T12& value12, const T13& value13)
192    {
193        print(value1);
194        print(value2);
195        print(value3);
196        print(value4);
197        print(value5);
198        print(value6);
199        print(value7);
200        print(value8);
201        print(value9);
202        print(value10);
203        print(value11);
204        print(value12);
205        print(value13);
206    }
207};
208
209void printInternal(PrintStream&, const char*);
210void printInternal(PrintStream&, const CString&);
211void printInternal(PrintStream&, const String&);
212inline void printInternal(PrintStream& out, char* value) { printInternal(out, static_cast<const char*>(value)); }
213inline void printInternal(PrintStream& out, CString& value) { printInternal(out, static_cast<const CString&>(value)); }
214inline void printInternal(PrintStream& out, String& value) { printInternal(out, static_cast<const String&>(value)); }
215void printInternal(PrintStream&, bool);
216void printInternal(PrintStream&, int);
217void printInternal(PrintStream&, unsigned);
218void printInternal(PrintStream&, long);
219void printInternal(PrintStream&, unsigned long);
220void printInternal(PrintStream&, long long);
221void printInternal(PrintStream&, unsigned long long);
222void printInternal(PrintStream&, float);
223void printInternal(PrintStream&, double);
224
225template<typename T>
226void printInternal(PrintStream& out, const T& value)
227{
228    value.dump(out);
229}
230
231#define MAKE_PRINT_ADAPTOR(Name, Type, function) \
232    class Name {                                 \
233    public:                                      \
234        Name(const Type& value)                  \
235            : m_value(value)                     \
236        {                                        \
237        }                                        \
238        void dump(PrintStream& out) const        \
239        {                                        \
240            function(out, m_value);              \
241        }                                        \
242    private:                                     \
243        Type m_value;                            \
244    }
245
246#define MAKE_PRINT_METHOD_ADAPTOR(Name, Type, method) \
247    class Name {                                 \
248    public:                                      \
249        Name(const Type& value)                  \
250            : m_value(value)                     \
251        {                                        \
252        }                                        \
253        void dump(PrintStream& out) const        \
254        {                                        \
255            m_value.method(out);                 \
256        }                                        \
257    private:                                     \
258        const Type& m_value;                     \
259    }
260
261#define MAKE_PRINT_METHOD(Type, dumpMethod, method) \
262    MAKE_PRINT_METHOD_ADAPTOR(DumperFor_##method, Type, dumpMethod);    \
263    DumperFor_##method method() const { return DumperFor_##method(*this); }
264
265// Use an adaptor-based dumper for characters to avoid situations where
266// you've "compressed" an integer to a character and it ends up printing
267// as ASCII when you wanted it to print as a number.
268void dumpCharacter(PrintStream&, char);
269MAKE_PRINT_ADAPTOR(CharacterDump, char, dumpCharacter);
270
271template<typename T>
272class PointerDump {
273public:
274    PointerDump(const T* ptr)
275        : m_ptr(ptr)
276    {
277    }
278
279    void dump(PrintStream& out) const
280    {
281        if (m_ptr)
282            printInternal(out, *m_ptr);
283        else
284            out.print("(null)");
285    }
286private:
287    const T* m_ptr;
288};
289
290template<typename T>
291PointerDump<T> pointerDump(const T* ptr) { return PointerDump<T>(ptr); }
292
293} // namespace WTF
294
295using WTF::CharacterDump;
296using WTF::PointerDump;
297using WTF::PrintStream;
298using WTF::pointerDump;
299
300#endif // PrintStream_h
301
302