1//===- Format.h - Efficient printf-style formatting for streams -*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file implements the format() function, which can be used with other 11// LLVM subsystems to provide printf-style formatting. This gives all the power 12// and risk of printf. This can be used like this (with raw_ostreams as an 13// example): 14// 15// OS << "mynumber: " << format("%4.5f", 1234.412) << '\n'; 16// 17// Or if you prefer: 18// 19// OS << format("mynumber: %4.5f\n", 1234.412); 20// 21//===----------------------------------------------------------------------===// 22 23#ifndef LLVM_SUPPORT_FORMAT_H 24#define LLVM_SUPPORT_FORMAT_H 25 26#include <cassert> 27#include <cstdio> 28#ifdef _MSC_VER 29// FIXME: This define is wrong: 30// - _snprintf does not guarantee that trailing null is always added - if 31// there is no space for null, it does not report any error. 32// - According to C++ standard, snprintf should be visible in the 'std' 33// namespace - this define makes this impossible. 34#define snprintf _snprintf 35#endif 36 37namespace llvm { 38 39/// This is a helper class used for handling formatted output. It is the 40/// abstract base class of a templated derived class. 41class format_object_base { 42protected: 43 const char *Fmt; 44 virtual void home(); // Out of line virtual method. 45 46 /// Call snprintf() for this object, on the given buffer and size. 47 virtual int snprint(char *Buffer, unsigned BufferSize) const = 0; 48 49public: 50 format_object_base(const char *fmt) : Fmt(fmt) {} 51 virtual ~format_object_base() {} 52 53 /// Format the object into the specified buffer. On success, this returns 54 /// the length of the formatted string. If the buffer is too small, this 55 /// returns a length to retry with, which will be larger than BufferSize. 56 unsigned print(char *Buffer, unsigned BufferSize) const { 57 assert(BufferSize && "Invalid buffer size!"); 58 59 // Print the string, leaving room for the terminating null. 60 int N = snprint(Buffer, BufferSize); 61 62 // VC++ and old GlibC return negative on overflow, just double the size. 63 if (N < 0) 64 return BufferSize * 2; 65 66 // Other implementations yield number of bytes needed, not including the 67 // final '\0'. 68 if (unsigned(N) >= BufferSize) 69 return N + 1; 70 71 // Otherwise N is the length of output (not including the final '\0'). 72 return N; 73 } 74}; 75 76/// These are templated helper classes used by the format function that 77/// capture the object to be formated and the format string. When actually 78/// printed, this synthesizes the string into a temporary buffer provided and 79/// returns whether or not it is big enough. 80 81template <typename T> 82class format_object1 : public format_object_base { 83 T Val; 84public: 85 format_object1(const char *fmt, const T &val) 86 : format_object_base(fmt), Val(val) { 87 } 88 89 int snprint(char *Buffer, unsigned BufferSize) const override { 90 return snprintf(Buffer, BufferSize, Fmt, Val); 91 } 92}; 93 94template <typename T1, typename T2> 95class format_object2 : public format_object_base { 96 T1 Val1; 97 T2 Val2; 98public: 99 format_object2(const char *fmt, const T1 &val1, const T2 &val2) 100 : format_object_base(fmt), Val1(val1), Val2(val2) { 101 } 102 103 int snprint(char *Buffer, unsigned BufferSize) const override { 104 return snprintf(Buffer, BufferSize, Fmt, Val1, Val2); 105 } 106}; 107 108template <typename T1, typename T2, typename T3> 109class format_object3 : public format_object_base { 110 T1 Val1; 111 T2 Val2; 112 T3 Val3; 113public: 114 format_object3(const char *fmt, const T1 &val1, const T2 &val2,const T3 &val3) 115 : format_object_base(fmt), Val1(val1), Val2(val2), Val3(val3) { 116 } 117 118 int snprint(char *Buffer, unsigned BufferSize) const override { 119 return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3); 120 } 121}; 122 123template <typename T1, typename T2, typename T3, typename T4> 124class format_object4 : public format_object_base { 125 T1 Val1; 126 T2 Val2; 127 T3 Val3; 128 T4 Val4; 129public: 130 format_object4(const char *fmt, const T1 &val1, const T2 &val2, 131 const T3 &val3, const T4 &val4) 132 : format_object_base(fmt), Val1(val1), Val2(val2), Val3(val3), Val4(val4) { 133 } 134 135 int snprint(char *Buffer, unsigned BufferSize) const override { 136 return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3, Val4); 137 } 138}; 139 140template <typename T1, typename T2, typename T3, typename T4, typename T5> 141class format_object5 : public format_object_base { 142 T1 Val1; 143 T2 Val2; 144 T3 Val3; 145 T4 Val4; 146 T5 Val5; 147public: 148 format_object5(const char *fmt, const T1 &val1, const T2 &val2, 149 const T3 &val3, const T4 &val4, const T5 &val5) 150 : format_object_base(fmt), Val1(val1), Val2(val2), Val3(val3), Val4(val4), 151 Val5(val5) { 152 } 153 154 int snprint(char *Buffer, unsigned BufferSize) const override { 155 return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3, Val4, Val5); 156 } 157}; 158 159template <typename T1, typename T2, typename T3, typename T4, typename T5, 160 typename T6> 161class format_object6 : public format_object_base { 162 T1 Val1; 163 T2 Val2; 164 T3 Val3; 165 T4 Val4; 166 T5 Val5; 167 T6 Val6; 168public: 169 format_object6(const char *Fmt, const T1 &Val1, const T2 &Val2, 170 const T3 &Val3, const T4 &Val4, const T5 &Val5, const T6 &Val6) 171 : format_object_base(Fmt), Val1(Val1), Val2(Val2), Val3(Val3), Val4(Val4), 172 Val5(Val5), Val6(Val6) { } 173 174 int snprint(char *Buffer, unsigned BufferSize) const override { 175 return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3, Val4, Val5, Val6); 176 } 177}; 178 179/// These are helper functions used to produce formatted output. They use 180/// template type deduction to construct the appropriate instance of the 181/// format_object class to simplify their construction. 182/// 183/// This is typically used like: 184/// \code 185/// OS << format("%0.4f", myfloat) << '\n'; 186/// \endcode 187 188template <typename T> 189inline format_object1<T> format(const char *Fmt, const T &Val) { 190 return format_object1<T>(Fmt, Val); 191} 192 193template <typename T1, typename T2> 194inline format_object2<T1, T2> format(const char *Fmt, const T1 &Val1, 195 const T2 &Val2) { 196 return format_object2<T1, T2>(Fmt, Val1, Val2); 197} 198 199template <typename T1, typename T2, typename T3> 200 inline format_object3<T1, T2, T3> format(const char *Fmt, const T1 &Val1, 201 const T2 &Val2, const T3 &Val3) { 202 return format_object3<T1, T2, T3>(Fmt, Val1, Val2, Val3); 203} 204 205template <typename T1, typename T2, typename T3, typename T4> 206inline format_object4<T1, T2, T3, T4> format(const char *Fmt, const T1 &Val1, 207 const T2 &Val2, const T3 &Val3, 208 const T4 &Val4) { 209 return format_object4<T1, T2, T3, T4>(Fmt, Val1, Val2, Val3, Val4); 210} 211 212template <typename T1, typename T2, typename T3, typename T4, typename T5> 213inline format_object5<T1, T2, T3, T4, T5> format(const char *Fmt,const T1 &Val1, 214 const T2 &Val2, const T3 &Val3, 215 const T4 &Val4, const T5 &Val5) { 216 return format_object5<T1, T2, T3, T4, T5>(Fmt, Val1, Val2, Val3, Val4, Val5); 217} 218 219template <typename T1, typename T2, typename T3, typename T4, typename T5, 220 typename T6> 221inline format_object6<T1, T2, T3, T4, T5, T6> 222format(const char *Fmt, const T1 &Val1, const T2 &Val2, const T3 &Val3, 223 const T4 &Val4, const T5 &Val5, const T6 &Val6) { 224 return format_object6<T1, T2, T3, T4, T5, T6>(Fmt, Val1, Val2, Val3, Val4, 225 Val5, Val6); 226} 227 228} // end namespace llvm 229 230#endif 231