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/FastMalloc.h> 31#include <wtf/Noncopyable.h> 32#include <wtf/RawPointer.h> 33#include <wtf/StdLibExtras.h> 34 35namespace WTF { 36 37class CString; 38class String; 39class StringImpl; 40 41class PrintStream { 42 WTF_MAKE_FAST_ALLOCATED; WTF_MAKE_NONCOPYABLE(PrintStream); 43public: 44 PrintStream(); 45 virtual ~PrintStream(); 46 47 WTF_EXPORT_PRIVATE void printf(const char* format, ...) WTF_ATTRIBUTE_PRINTF(2, 3); 48 virtual void vprintf(const char* format, va_list) WTF_ATTRIBUTE_PRINTF(2, 0) = 0; 49 50 // Typically a no-op for many subclasses of PrintStream, this is a hint that 51 // the implementation should flush its buffers if it had not done so already. 52 virtual void flush(); 53 54 template<typename T> 55 void print(const T& value) 56 { 57 printInternal(*this, value); 58 } 59 60 template<typename T, typename... Types> 61 void print(const T& value, const Types&... remainingValues) 62 { 63 printInternal(*this, value); 64 print(remainingValues...); 65 } 66}; 67 68WTF_EXPORT_PRIVATE void printInternal(PrintStream&, const char*); 69WTF_EXPORT_PRIVATE void printInternal(PrintStream&, const CString&); 70WTF_EXPORT_PRIVATE void printInternal(PrintStream&, const String&); 71WTF_EXPORT_PRIVATE void printInternal(PrintStream&, const StringImpl*); 72inline void printInternal(PrintStream& out, char* value) { printInternal(out, static_cast<const char*>(value)); } 73inline void printInternal(PrintStream& out, CString& value) { printInternal(out, static_cast<const CString&>(value)); } 74inline void printInternal(PrintStream& out, String& value) { printInternal(out, static_cast<const String&>(value)); } 75inline void printInternal(PrintStream& out, StringImpl* value) { printInternal(out, static_cast<const StringImpl*>(value)); } 76WTF_EXPORT_PRIVATE void printInternal(PrintStream&, bool); 77WTF_EXPORT_PRIVATE void printInternal(PrintStream&, signed char); // NOTE: this prints as a number, not as a character; use CharacterDump if you want the character 78WTF_EXPORT_PRIVATE void printInternal(PrintStream&, unsigned char); // NOTE: see above. 79WTF_EXPORT_PRIVATE void printInternal(PrintStream&, short); 80WTF_EXPORT_PRIVATE void printInternal(PrintStream&, unsigned short); 81WTF_EXPORT_PRIVATE void printInternal(PrintStream&, int); 82WTF_EXPORT_PRIVATE void printInternal(PrintStream&, unsigned); 83WTF_EXPORT_PRIVATE void printInternal(PrintStream&, long); 84WTF_EXPORT_PRIVATE void printInternal(PrintStream&, unsigned long); 85WTF_EXPORT_PRIVATE void printInternal(PrintStream&, long long); 86WTF_EXPORT_PRIVATE void printInternal(PrintStream&, unsigned long long); 87WTF_EXPORT_PRIVATE void printInternal(PrintStream&, float); 88WTF_EXPORT_PRIVATE void printInternal(PrintStream&, double); 89WTF_EXPORT_PRIVATE void printInternal(PrintStream&, RawPointer); 90 91template<typename T> 92void printInternal(PrintStream& out, const T& value) 93{ 94 value.dump(out); 95} 96 97#define MAKE_PRINT_ADAPTOR(Name, Type, function) \ 98 class Name { \ 99 public: \ 100 Name(const Type& value) \ 101 : m_value(value) \ 102 { \ 103 } \ 104 void dump(PrintStream& out) const \ 105 { \ 106 function(out, m_value); \ 107 } \ 108 private: \ 109 Type m_value; \ 110 } 111 112#define MAKE_PRINT_METHOD_ADAPTOR(Name, Type, method) \ 113 class Name { \ 114 public: \ 115 Name(const Type& value) \ 116 : m_value(value) \ 117 { \ 118 } \ 119 void dump(PrintStream& out) const \ 120 { \ 121 m_value.method(out); \ 122 } \ 123 private: \ 124 const Type& m_value; \ 125 } 126 127#define MAKE_PRINT_METHOD(Type, dumpMethod, method) \ 128 MAKE_PRINT_METHOD_ADAPTOR(DumperFor_##method, Type, dumpMethod); \ 129 DumperFor_##method method() const { return DumperFor_##method(*this); } 130 131// Use an adaptor-based dumper for characters to avoid situations where 132// you've "compressed" an integer to a character and it ends up printing 133// as ASCII when you wanted it to print as a number. 134WTF_EXPORT_PRIVATE void dumpCharacter(PrintStream&, char); 135MAKE_PRINT_ADAPTOR(CharacterDump, char, dumpCharacter); 136 137template<typename T> 138class PointerDump { 139public: 140 PointerDump(const T* ptr) 141 : m_ptr(ptr) 142 { 143 } 144 145 void dump(PrintStream& out) const 146 { 147 if (m_ptr) 148 printInternal(out, *m_ptr); 149 else 150 out.print("(null)"); 151 } 152private: 153 const T* m_ptr; 154}; 155 156template<typename T> 157PointerDump<T> pointerDump(const T* ptr) { return PointerDump<T>(ptr); } 158 159template<typename T, typename U> 160class ValueInContext { 161public: 162 ValueInContext(const T& value, U* context) 163 : m_value(&value) 164 , m_context(context) 165 { 166 } 167 168 void dump(PrintStream& out) const 169 { 170 m_value->dumpInContext(out, m_context); 171 } 172 173private: 174 const T* m_value; 175 U* m_context; 176}; 177 178template<typename T, typename U> 179ValueInContext<T, U> inContext(const T& value, U* context) 180{ 181 return ValueInContext<T, U>(value, context); 182} 183 184template<typename T, typename U> 185class PointerDumpInContext { 186public: 187 PointerDumpInContext(const T* ptr, U* context) 188 : m_ptr(ptr) 189 , m_context(context) 190 { 191 } 192 193 void dump(PrintStream& out) const 194 { 195 if (m_ptr) 196 m_ptr->dumpInContext(out, m_context); 197 else 198 out.print("(null)"); 199 } 200 201private: 202 const T* m_ptr; 203 U* m_context; 204}; 205 206template<typename T, typename U> 207PointerDumpInContext<T, U> pointerDumpInContext(const T* ptr, U* context) 208{ 209 return PointerDumpInContext<T, U>(ptr, context); 210} 211 212template<typename T, typename U> 213class ValueIgnoringContext { 214public: 215 ValueIgnoringContext(const U& value) 216 : m_value(&value) 217 { 218 } 219 220 void dump(PrintStream& out) const 221 { 222 T context; 223 m_value->dumpInContext(out, &context); 224 } 225 226private: 227 const U* m_value; 228}; 229 230template<typename T, typename U> 231ValueIgnoringContext<T, U> ignoringContext(const U& value) 232{ 233 return ValueIgnoringContext<T, U>(value); 234} 235 236} // namespace WTF 237 238using WTF::CharacterDump; 239using WTF::PointerDump; 240using WTF::PrintStream; 241using WTF::ignoringContext; 242using WTF::inContext; 243using WTF::pointerDump; 244using WTF::pointerDumpInContext; 245 246#endif // PrintStream_h 247 248