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 37 namespace llvm { 38 39 /// format_object_base - This is a helper class used for handling formatted 40 /// output. It is the abstract base class of a templated derived class. 41 class format_object_base { 42 protected: 43 const char *Fmt; 44 virtual void home(); // Out of line virtual method. 45 46 /// snprint - Call snprintf() for this object, on the given buffer and size. 47 virtual int snprint(char *Buffer, unsigned BufferSize) const = 0; 48 49 public: 50 format_object_base(const char *fmt) : Fmt(fmt) {} 51 virtual ~format_object_base() {} 52 53 /// print - Format the object into the specified buffer. On success, this 54 /// returns the length of the formatted string. If the buffer is too small, 55 /// this 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 impls yield number of bytes needed, not including the final '\0'. 67 if (unsigned(N) >= BufferSize) 68 return N+1; 69 70 // Otherwise N is the length of output (not including the final '\0'). 71 return N; 72 } 73 }; 74 75 /// format_object1 - This is a templated helper class used by the format 76 /// function that captures the object to be formated and the format string. When 77 /// actually printed, this synthesizes the string into a temporary buffer 78 /// provided and returns whether or not it is big enough. 79 template <typename T> 80 class format_object1 : public format_object_base { 81 T Val; 82 public: 83 format_object1(const char *fmt, const T &val) 84 : format_object_base(fmt), Val(val) { 85 } 86 87 virtual int snprint(char *Buffer, unsigned BufferSize) const { 88 return snprintf(Buffer, BufferSize, Fmt, Val); 89 } 90 }; 91 92 /// format_object2 - This is a templated helper class used by the format 93 /// function that captures the object to be formated and the format string. When 94 /// actually printed, this synthesizes the string into a temporary buffer 95 /// provided and returns whether or not it is big enough. 96 template <typename T1, typename T2> 97 class format_object2 : public format_object_base { 98 T1 Val1; 99 T2 Val2; 100 public: 101 format_object2(const char *fmt, const T1 &val1, const T2 &val2) 102 : format_object_base(fmt), Val1(val1), Val2(val2) { 103 } 104 105 virtual int snprint(char *Buffer, unsigned BufferSize) const { 106 return snprintf(Buffer, BufferSize, Fmt, Val1, Val2); 107 } 108 }; 109 110 /// format_object3 - This is a templated helper class used by the format 111 /// function that captures the object to be formated and the format string. When 112 /// actually printed, this synthesizes the string into a temporary buffer 113 /// provided and returns whether or not it is big enough. 114 template <typename T1, typename T2, typename T3> 115 class format_object3 : public format_object_base { 116 T1 Val1; 117 T2 Val2; 118 T3 Val3; 119 public: 120 format_object3(const char *fmt, const T1 &val1, const T2 &val2,const T3 &val3) 121 : format_object_base(fmt), Val1(val1), Val2(val2), Val3(val3) { 122 } 123 124 virtual int snprint(char *Buffer, unsigned BufferSize) const { 125 return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3); 126 } 127 }; 128 129 /// format_object4 - This is a templated helper class used by the format 130 /// function that captures the object to be formated and the format string. When 131 /// actually printed, this synthesizes the string into a temporary buffer 132 /// provided and returns whether or not it is big enough. 133 template <typename T1, typename T2, typename T3, typename T4> 134 class format_object4 : public format_object_base { 135 T1 Val1; 136 T2 Val2; 137 T3 Val3; 138 T4 Val4; 139 public: 140 format_object4(const char *fmt, const T1 &val1, const T2 &val2, 141 const T3 &val3, const T4 &val4) 142 : format_object_base(fmt), Val1(val1), Val2(val2), Val3(val3), Val4(val4) { 143 } 144 145 virtual int snprint(char *Buffer, unsigned BufferSize) const { 146 return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3, Val4); 147 } 148 }; 149 150 /// format_object5 - This is a templated helper class used by the format 151 /// function that captures the object to be formated and the format string. When 152 /// actually printed, this synthesizes the string into a temporary buffer 153 /// provided and returns whether or not it is big enough. 154 template <typename T1, typename T2, typename T3, typename T4, typename T5> 155 class format_object5 : public format_object_base { 156 T1 Val1; 157 T2 Val2; 158 T3 Val3; 159 T4 Val4; 160 T5 Val5; 161 public: 162 format_object5(const char *fmt, const T1 &val1, const T2 &val2, 163 const T3 &val3, const T4 &val4, const T5 &val5) 164 : format_object_base(fmt), Val1(val1), Val2(val2), Val3(val3), Val4(val4), 165 Val5(val5) { 166 } 167 168 virtual int snprint(char *Buffer, unsigned BufferSize) const { 169 return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3, Val4, Val5); 170 } 171 }; 172 173 /// format - This is a helper function that is used to produce formatted output. 174 /// This is typically used like: OS << format("%0.4f", myfloat) << '\n'; 175 template <typename T> 176 inline format_object1<T> format(const char *Fmt, const T &Val) { 177 return format_object1<T>(Fmt, Val); 178 } 179 180 /// format - This is a helper function that is used to produce formatted output. 181 /// This is typically used like: OS << format("%0.4f", myfloat) << '\n'; 182 template <typename T1, typename T2> 183 inline format_object2<T1, T2> format(const char *Fmt, const T1 &Val1, 184 const T2 &Val2) { 185 return format_object2<T1, T2>(Fmt, Val1, Val2); 186 } 187 188 /// format - This is a helper function that is used to produce formatted output. 189 /// This is typically used like: OS << format("%0.4f", myfloat) << '\n'; 190 template <typename T1, typename T2, typename T3> 191 inline format_object3<T1, T2, T3> format(const char *Fmt, const T1 &Val1, 192 const T2 &Val2, const T3 &Val3) { 193 return format_object3<T1, T2, T3>(Fmt, Val1, Val2, Val3); 194 } 195 196 /// format - This is a helper function that is used to produce formatted output. 197 /// This is typically used like: OS << format("%0.4f", myfloat) << '\n'; 198 template <typename T1, typename T2, typename T3, typename T4> 199 inline format_object4<T1, T2, T3, T4> format(const char *Fmt, const T1 &Val1, 200 const T2 &Val2, const T3 &Val3, 201 const T4 &Val4) { 202 return format_object4<T1, T2, T3, T4>(Fmt, Val1, Val2, Val3, Val4); 203 } 204 205 /// format - This is a helper function that is used to produce formatted output. 206 /// This is typically used like: OS << format("%0.4f", myfloat) << '\n'; 207 template <typename T1, typename T2, typename T3, typename T4, typename T5> 208 inline format_object5<T1, T2, T3, T4, T5> format(const char *Fmt,const T1 &Val1, 209 const T2 &Val2, const T3 &Val3, 210 const T4 &Val4, const T5 &Val5) { 211 return format_object5<T1, T2, T3, T4, T5>(Fmt, Val1, Val2, Val3, Val4, Val5); 212 } 213 214 } // end namespace llvm 215 216 #endif 217