a69d1d0d7fc000ba0e9788f2fcb5e1e45b0f60a0
[WebKit-https.git] / Source / WTF / wtf / PrintStream.h
1 /*
2  * Copyright (C) 2012, 2014-2016 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 <memory>
30 #include <stdarg.h>
31 #include <tuple>
32 #include <wtf/FastMalloc.h>
33 #include <wtf/Noncopyable.h>
34 #include <wtf/Optional.h>
35 #include <wtf/RawPointer.h>
36 #include <wtf/RefPtr.h>
37 #include <wtf/StdLibExtras.h>
38
39 namespace WTF {
40
41 class AtomicStringImpl;
42 class CString;
43 class String;
44 class StringImpl;
45 class StringView;
46 class UniquedStringImpl;
47
48 inline const char* boolForPrinting(bool value)
49 {
50     return value ? "true" : "false";
51 }
52
53 class PrintStream {
54     WTF_MAKE_FAST_ALLOCATED; WTF_MAKE_NONCOPYABLE(PrintStream);
55 public:
56     PrintStream();
57     virtual ~PrintStream();
58
59     WTF_EXPORT_PRIVATE void printf(const char* format, ...) WTF_ATTRIBUTE_PRINTF(2, 3);
60     WTF_EXPORT_PRIVATE void printfVariableFormat(const char* format, ...);
61     virtual void vprintf(const char* format, va_list) WTF_ATTRIBUTE_PRINTF(2, 0) = 0;
62
63     // Typically a no-op for many subclasses of PrintStream, this is a hint that
64     // the implementation should flush its buffers if it had not done so already.
65     virtual void flush();
66     
67     template<typename Func>
68     void atomically(const Func& func)
69     {
70         func(begin());
71         end();
72     }
73     
74     template<typename... Types>
75     void print(const Types&... values)
76     {
77         atomically(
78             [&] (PrintStream& out) {
79                 out.printImpl(values...);
80             });
81     }
82     
83     template<typename... Types>
84     void println(const Types&... values)
85     {
86         print(values..., "\n");
87     }
88
89 protected:
90     void printImpl() { }
91
92     template<typename T, typename... Types>
93     void printImpl(const T& value, const Types&... remainingValues)
94     {
95         printInternal(*this, value);
96         printImpl(remainingValues...);
97     }
98     
99     virtual PrintStream& begin();
100     virtual void end();
101 };
102
103 WTF_EXPORT_PRIVATE void printInternal(PrintStream&, const char*);
104 WTF_EXPORT_PRIVATE void printInternal(PrintStream&, const StringView&);
105 WTF_EXPORT_PRIVATE void printInternal(PrintStream&, const CString&);
106 WTF_EXPORT_PRIVATE void printInternal(PrintStream&, const String&);
107 WTF_EXPORT_PRIVATE void printInternal(PrintStream&, const StringImpl*);
108 inline void printInternal(PrintStream& out, const AtomicStringImpl* value) { printInternal(out, bitwise_cast<const StringImpl*>(value)); }
109 inline void printInternal(PrintStream& out, const UniquedStringImpl* value) { printInternal(out, bitwise_cast<const StringImpl*>(value)); }
110 inline void printInternal(PrintStream& out, const UniquedStringImpl& value) { printInternal(out, &value); }
111 inline void printInternal(PrintStream& out, char* value) { printInternal(out, static_cast<const char*>(value)); }
112 inline void printInternal(PrintStream& out, CString& value) { printInternal(out, static_cast<const CString&>(value)); }
113 inline void printInternal(PrintStream& out, String& value) { printInternal(out, static_cast<const String&>(value)); }
114 inline void printInternal(PrintStream& out, StringImpl* value) { printInternal(out, static_cast<const StringImpl*>(value)); }
115 inline void printInternal(PrintStream& out, AtomicStringImpl* value) { printInternal(out, static_cast<const AtomicStringImpl*>(value)); }
116 inline void printInternal(PrintStream& out, UniquedStringImpl* value) { printInternal(out, static_cast<const UniquedStringImpl*>(value)); }
117 inline void printInternal(PrintStream& out, UniquedStringImpl& value) { printInternal(out, &value); }
118 WTF_EXPORT_PRIVATE void printInternal(PrintStream&, bool);
119 WTF_EXPORT_PRIVATE void printInternal(PrintStream&, signed char); // NOTE: this prints as a number, not as a character; use CharacterDump if you want the character
120 WTF_EXPORT_PRIVATE void printInternal(PrintStream&, unsigned char); // NOTE: see above.
121 WTF_EXPORT_PRIVATE void printInternal(PrintStream&, short);
122 WTF_EXPORT_PRIVATE void printInternal(PrintStream&, unsigned short);
123 WTF_EXPORT_PRIVATE void printInternal(PrintStream&, int);
124 WTF_EXPORT_PRIVATE void printInternal(PrintStream&, unsigned);
125 WTF_EXPORT_PRIVATE void printInternal(PrintStream&, long);
126 WTF_EXPORT_PRIVATE void printInternal(PrintStream&, unsigned long);
127 WTF_EXPORT_PRIVATE void printInternal(PrintStream&, long long);
128 WTF_EXPORT_PRIVATE void printInternal(PrintStream&, unsigned long long);
129 WTF_EXPORT_PRIVATE void printInternal(PrintStream&, float);
130 WTF_EXPORT_PRIVATE void printInternal(PrintStream&, double);
131 WTF_EXPORT_PRIVATE void printInternal(PrintStream&, RawPointer);
132
133 template<typename T>
134 void printInternal(PrintStream& out, const T& value)
135 {
136     value.dump(out);
137 }
138
139 #define MAKE_PRINT_ADAPTOR(Name, Type, function) \
140     class Name {                                 \
141     public:                                      \
142         Name(const Type& value)                  \
143             : m_value(value)                     \
144         {                                        \
145         }                                        \
146         void dump(PrintStream& out) const        \
147         {                                        \
148             function(out, m_value);              \
149         }                                        \
150     private:                                     \
151         Type m_value;                            \
152     }
153
154 #define MAKE_PRINT_METHOD_ADAPTOR(Name, Type, method) \
155     class Name {                                 \
156     public:                                      \
157         Name(const Type& value)                  \
158             : m_value(value)                     \
159         {                                        \
160         }                                        \
161         void dump(PrintStream& out) const        \
162         {                                        \
163             m_value.method(out);                 \
164         }                                        \
165     private:                                     \
166         const Type& m_value;                     \
167     }
168
169 #define MAKE_PRINT_METHOD(Type, dumpMethod, method) \
170     MAKE_PRINT_METHOD_ADAPTOR(DumperFor_##method, Type, dumpMethod);    \
171     DumperFor_##method method() const { return DumperFor_##method(*this); }
172
173 // Use an adaptor-based dumper for characters to avoid situations where
174 // you've "compressed" an integer to a character and it ends up printing
175 // as ASCII when you wanted it to print as a number.
176 WTF_EXPORT_PRIVATE void dumpCharacter(PrintStream&, char);
177 MAKE_PRINT_ADAPTOR(CharacterDump, char, dumpCharacter);
178
179 template<typename T>
180 class PointerDump {
181 public:
182     PointerDump(const T* ptr)
183         : m_ptr(ptr)
184     {
185     }
186     
187     void dump(PrintStream& out) const
188     {
189         if (m_ptr)
190             printInternal(out, *m_ptr);
191         else
192             out.print("(null)");
193     }
194 private:
195     const T* m_ptr;
196 };
197
198 template<typename T>
199 PointerDump<T> pointerDump(const T* ptr) { return PointerDump<T>(ptr); }
200
201 template<typename T>
202 void printInternal(PrintStream& out, const std::unique_ptr<T>& value)
203 {
204     out.print(pointerDump(value.get()));
205 }
206
207 template<typename T>
208 void printInternal(PrintStream& out, const RefPtr<T>& value)
209 {
210     out.print(pointerDump(value.get()));
211 }
212
213 template<typename T, typename U>
214 class ValueInContext {
215 public:
216     ValueInContext(const T& value, U* context)
217         : m_value(&value)
218         , m_context(context)
219     {
220     }
221     
222     void dump(PrintStream& out) const
223     {
224         m_value->dumpInContext(out, m_context);
225     }
226
227 private:
228     const T* m_value;
229     U* m_context;
230 };
231
232 template<typename T, typename U>
233 ValueInContext<T, U> inContext(const T& value, U* context)
234 {
235     return ValueInContext<T, U>(value, context);
236 }
237
238 template<typename T, typename U>
239 class PointerDumpInContext {
240 public:
241     PointerDumpInContext(const T* ptr, U* context)
242         : m_ptr(ptr)
243         , m_context(context)
244     {
245     }
246     
247     void dump(PrintStream& out) const
248     {
249         if (m_ptr)
250             m_ptr->dumpInContext(out, m_context);
251         else
252             out.print("(null)");
253     }
254
255 private:
256     const T* m_ptr;
257     U* m_context;
258 };
259
260 template<typename T, typename U>
261 PointerDumpInContext<T, U> pointerDumpInContext(const T* ptr, U* context)
262 {
263     return PointerDumpInContext<T, U>(ptr, context);
264 }
265
266 template<typename T, typename U>
267 class ValueIgnoringContext {
268 public:
269     ValueIgnoringContext(const U& value)
270         : m_value(&value)
271     {
272     }
273     
274     void dump(PrintStream& out) const
275     {
276         T context;
277         m_value->dumpInContext(out, &context);
278     }
279
280 private:
281     const U* m_value;
282 };
283
284 template<typename T, typename U>
285 ValueIgnoringContext<T, U> ignoringContext(const U& value)
286 {
287     return ValueIgnoringContext<T, U>(value);
288 }
289
290 template<unsigned index, typename... Types>
291 struct FormatImplUnpacker {
292     template<typename... Args>
293     static void unpack(PrintStream& out, const std::tuple<Types...>& tuple, const Args&... values);
294 };
295     
296 template<typename... Types>
297 struct FormatImplUnpacker<0, Types...> {
298     template<typename... Args>
299     static void unpack(PrintStream& out, const std::tuple<Types...>& tuple, const Args&... values)
300     {
301         out.printfVariableFormat(std::get<0>(tuple), values...);
302     }
303 };
304     
305 template<unsigned index, typename... Types>
306 template<typename... Args>
307 void FormatImplUnpacker<index, Types...>::unpack(PrintStream& out, const std::tuple<Types...>& tuple, const Args&... values)
308 {
309     FormatImplUnpacker<index - 1, Types...>::unpack(out, tuple, std::get<index>(tuple), values...);
310 }
311
312 template<typename... Types>
313 class FormatImpl {
314 public:
315     FormatImpl(Types... values)
316         : m_values(values...)
317     {
318     }
319     
320     void dump(PrintStream& out) const
321     {
322         FormatImplUnpacker<sizeof...(Types) - 1, Types...>::unpack(out, m_values);
323     }
324
325 private:
326     std::tuple<Types...> m_values;
327 };
328
329 template<typename... Types>
330 FormatImpl<Types...> format(Types... values)
331 {
332     return FormatImpl<Types...>(values...);
333 }
334
335 template<typename T>
336 void printInternal(PrintStream& out, const std::optional<T>& value)
337 {
338     if (value)
339         out.print(*value);
340     else
341         out.print("<nullopt>");
342 }
343
344 } // namespace WTF
345
346 using WTF::boolForPrinting;
347 using WTF::CharacterDump;
348 using WTF::PointerDump;
349 using WTF::PrintStream;
350 using WTF::format;
351 using WTF::ignoringContext;
352 using WTF::inContext;
353 using WTF::pointerDump;
354 using WTF::pointerDumpInContext;
355
356 #endif // PrintStream_h
357