]>
Commit | Line | Data |
---|---|---|
223e47cc LB |
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 | ||
1a4d82fc JJ |
26 | #include "llvm/ADT/StringRef.h" |
27 | #include "llvm/Support/DataTypes.h" | |
223e47cc LB |
28 | #include <cassert> |
29 | #include <cstdio> | |
30 | #ifdef _MSC_VER | |
31 | // FIXME: This define is wrong: | |
32 | // - _snprintf does not guarantee that trailing null is always added - if | |
33 | // there is no space for null, it does not report any error. | |
34 | // - According to C++ standard, snprintf should be visible in the 'std' | |
35 | // namespace - this define makes this impossible. | |
36 | #define snprintf _snprintf | |
37 | #endif | |
38 | ||
39 | namespace llvm { | |
40 | ||
1a4d82fc JJ |
41 | /// This is a helper class used for handling formatted output. It is the |
42 | /// abstract base class of a templated derived class. | |
223e47cc LB |
43 | class format_object_base { |
44 | protected: | |
45 | const char *Fmt; | |
1a4d82fc | 46 | ~format_object_base() {} // Disallow polymorphic deletion. |
223e47cc LB |
47 | virtual void home(); // Out of line virtual method. |
48 | ||
1a4d82fc | 49 | /// Call snprintf() for this object, on the given buffer and size. |
223e47cc LB |
50 | virtual int snprint(char *Buffer, unsigned BufferSize) const = 0; |
51 | ||
52 | public: | |
53 | format_object_base(const char *fmt) : Fmt(fmt) {} | |
223e47cc | 54 | |
1a4d82fc JJ |
55 | /// Format the object into the specified buffer. On success, this returns |
56 | /// the length of the formatted string. If the buffer is too small, this | |
57 | /// returns a length to retry with, which will be larger than BufferSize. | |
223e47cc LB |
58 | unsigned print(char *Buffer, unsigned BufferSize) const { |
59 | assert(BufferSize && "Invalid buffer size!"); | |
60 | ||
61 | // Print the string, leaving room for the terminating null. | |
62 | int N = snprint(Buffer, BufferSize); | |
63 | ||
64 | // VC++ and old GlibC return negative on overflow, just double the size. | |
65 | if (N < 0) | |
1a4d82fc | 66 | return BufferSize * 2; |
223e47cc | 67 | |
1a4d82fc JJ |
68 | // Other implementations yield number of bytes needed, not including the |
69 | // final '\0'. | |
223e47cc | 70 | if (unsigned(N) >= BufferSize) |
1a4d82fc | 71 | return N + 1; |
223e47cc LB |
72 | |
73 | // Otherwise N is the length of output (not including the final '\0'). | |
74 | return N; | |
75 | } | |
76 | }; | |
77 | ||
1a4d82fc JJ |
78 | /// These are templated helper classes used by the format function that |
79 | /// capture the object to be formated and the format string. When actually | |
80 | /// printed, this synthesizes the string into a temporary buffer provided and | |
81 | /// returns whether or not it is big enough. | |
82 | ||
223e47cc | 83 | template <typename T> |
1a4d82fc | 84 | class format_object1 final : public format_object_base { |
223e47cc LB |
85 | T Val; |
86 | public: | |
87 | format_object1(const char *fmt, const T &val) | |
88 | : format_object_base(fmt), Val(val) { | |
89 | } | |
90 | ||
1a4d82fc | 91 | int snprint(char *Buffer, unsigned BufferSize) const override { |
223e47cc LB |
92 | return snprintf(Buffer, BufferSize, Fmt, Val); |
93 | } | |
94 | }; | |
95 | ||
223e47cc | 96 | template <typename T1, typename T2> |
1a4d82fc | 97 | class format_object2 final : public format_object_base { |
223e47cc LB |
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 | ||
1a4d82fc | 105 | int snprint(char *Buffer, unsigned BufferSize) const override { |
223e47cc LB |
106 | return snprintf(Buffer, BufferSize, Fmt, Val1, Val2); |
107 | } | |
108 | }; | |
109 | ||
223e47cc | 110 | template <typename T1, typename T2, typename T3> |
1a4d82fc | 111 | class format_object3 final : public format_object_base { |
223e47cc LB |
112 | T1 Val1; |
113 | T2 Val2; | |
114 | T3 Val3; | |
115 | public: | |
116 | format_object3(const char *fmt, const T1 &val1, const T2 &val2,const T3 &val3) | |
117 | : format_object_base(fmt), Val1(val1), Val2(val2), Val3(val3) { | |
118 | } | |
119 | ||
1a4d82fc | 120 | int snprint(char *Buffer, unsigned BufferSize) const override { |
223e47cc LB |
121 | return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3); |
122 | } | |
123 | }; | |
124 | ||
223e47cc | 125 | template <typename T1, typename T2, typename T3, typename T4> |
1a4d82fc | 126 | class format_object4 final : public format_object_base { |
223e47cc LB |
127 | T1 Val1; |
128 | T2 Val2; | |
129 | T3 Val3; | |
130 | T4 Val4; | |
131 | public: | |
132 | format_object4(const char *fmt, const T1 &val1, const T2 &val2, | |
133 | const T3 &val3, const T4 &val4) | |
134 | : format_object_base(fmt), Val1(val1), Val2(val2), Val3(val3), Val4(val4) { | |
135 | } | |
136 | ||
1a4d82fc | 137 | int snprint(char *Buffer, unsigned BufferSize) const override { |
223e47cc LB |
138 | return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3, Val4); |
139 | } | |
140 | }; | |
141 | ||
223e47cc | 142 | template <typename T1, typename T2, typename T3, typename T4, typename T5> |
1a4d82fc | 143 | class format_object5 final : public format_object_base { |
223e47cc LB |
144 | T1 Val1; |
145 | T2 Val2; | |
146 | T3 Val3; | |
147 | T4 Val4; | |
148 | T5 Val5; | |
149 | public: | |
150 | format_object5(const char *fmt, const T1 &val1, const T2 &val2, | |
151 | const T3 &val3, const T4 &val4, const T5 &val5) | |
152 | : format_object_base(fmt), Val1(val1), Val2(val2), Val3(val3), Val4(val4), | |
153 | Val5(val5) { | |
154 | } | |
155 | ||
1a4d82fc | 156 | int snprint(char *Buffer, unsigned BufferSize) const override { |
223e47cc LB |
157 | return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3, Val4, Val5); |
158 | } | |
159 | }; | |
160 | ||
1a4d82fc JJ |
161 | template <typename T1, typename T2, typename T3, typename T4, typename T5, |
162 | typename T6> | |
163 | class format_object6 final : public format_object_base { | |
164 | T1 Val1; | |
165 | T2 Val2; | |
166 | T3 Val3; | |
167 | T4 Val4; | |
168 | T5 Val5; | |
169 | T6 Val6; | |
170 | public: | |
171 | format_object6(const char *Fmt, const T1 &Val1, const T2 &Val2, | |
172 | const T3 &Val3, const T4 &Val4, const T5 &Val5, const T6 &Val6) | |
173 | : format_object_base(Fmt), Val1(Val1), Val2(Val2), Val3(Val3), Val4(Val4), | |
174 | Val5(Val5), Val6(Val6) { } | |
175 | ||
176 | int snprint(char *Buffer, unsigned BufferSize) const override { | |
177 | return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3, Val4, Val5, Val6); | |
178 | } | |
179 | }; | |
180 | ||
181 | /// These are helper functions used to produce formatted output. They use | |
182 | /// template type deduction to construct the appropriate instance of the | |
183 | /// format_object class to simplify their construction. | |
223e47cc LB |
184 | /// |
185 | /// This is typically used like: | |
186 | /// \code | |
187 | /// OS << format("%0.4f", myfloat) << '\n'; | |
188 | /// \endcode | |
1a4d82fc | 189 | |
223e47cc LB |
190 | template <typename T> |
191 | inline format_object1<T> format(const char *Fmt, const T &Val) { | |
192 | return format_object1<T>(Fmt, Val); | |
193 | } | |
194 | ||
223e47cc LB |
195 | template <typename T1, typename T2> |
196 | inline format_object2<T1, T2> format(const char *Fmt, const T1 &Val1, | |
197 | const T2 &Val2) { | |
198 | return format_object2<T1, T2>(Fmt, Val1, Val2); | |
199 | } | |
200 | ||
223e47cc LB |
201 | template <typename T1, typename T2, typename T3> |
202 | inline format_object3<T1, T2, T3> format(const char *Fmt, const T1 &Val1, | |
203 | const T2 &Val2, const T3 &Val3) { | |
204 | return format_object3<T1, T2, T3>(Fmt, Val1, Val2, Val3); | |
205 | } | |
206 | ||
223e47cc LB |
207 | template <typename T1, typename T2, typename T3, typename T4> |
208 | inline format_object4<T1, T2, T3, T4> format(const char *Fmt, const T1 &Val1, | |
209 | const T2 &Val2, const T3 &Val3, | |
210 | const T4 &Val4) { | |
211 | return format_object4<T1, T2, T3, T4>(Fmt, Val1, Val2, Val3, Val4); | |
212 | } | |
213 | ||
223e47cc LB |
214 | template <typename T1, typename T2, typename T3, typename T4, typename T5> |
215 | inline format_object5<T1, T2, T3, T4, T5> format(const char *Fmt,const T1 &Val1, | |
216 | const T2 &Val2, const T3 &Val3, | |
217 | const T4 &Val4, const T5 &Val5) { | |
218 | return format_object5<T1, T2, T3, T4, T5>(Fmt, Val1, Val2, Val3, Val4, Val5); | |
219 | } | |
220 | ||
1a4d82fc JJ |
221 | template <typename T1, typename T2, typename T3, typename T4, typename T5, |
222 | typename T6> | |
223 | inline format_object6<T1, T2, T3, T4, T5, T6> | |
224 | format(const char *Fmt, const T1 &Val1, const T2 &Val2, const T3 &Val3, | |
225 | const T4 &Val4, const T5 &Val5, const T6 &Val6) { | |
226 | return format_object6<T1, T2, T3, T4, T5, T6>(Fmt, Val1, Val2, Val3, Val4, | |
227 | Val5, Val6); | |
228 | } | |
229 | ||
230 | /// This is a helper class used for left_justify() and right_justify(). | |
231 | class FormattedString { | |
232 | StringRef Str; | |
233 | unsigned Width; | |
234 | bool RightJustify; | |
235 | friend class raw_ostream; | |
236 | public: | |
237 | FormattedString(StringRef S, unsigned W, bool R) | |
238 | : Str(S), Width(W), RightJustify(R) { } | |
239 | }; | |
240 | ||
241 | /// left_justify - append spaces after string so total output is | |
242 | /// \p Width characters. If \p Str is larger that \p Width, full string | |
243 | /// is written with no padding. | |
244 | inline FormattedString left_justify(StringRef Str, unsigned Width) { | |
245 | return FormattedString(Str, Width, false); | |
246 | } | |
247 | ||
248 | /// right_justify - add spaces before string so total output is | |
249 | /// \p Width characters. If \p Str is larger that \p Width, full string | |
250 | /// is written with no padding. | |
251 | inline FormattedString right_justify(StringRef Str, unsigned Width) { | |
252 | return FormattedString(Str, Width, true); | |
253 | } | |
254 | ||
255 | /// This is a helper class used for format_hex() and format_decimal(). | |
256 | class FormattedNumber { | |
257 | uint64_t HexValue; | |
258 | int64_t DecValue; | |
259 | unsigned Width; | |
260 | bool Hex; | |
261 | bool Upper; | |
262 | friend class raw_ostream; | |
263 | public: | |
264 | FormattedNumber(uint64_t HV, int64_t DV, unsigned W, bool H, bool U) | |
265 | : HexValue(HV), DecValue(DV), Width(W), Hex(H), Upper(U) { } | |
266 | }; | |
267 | ||
268 | /// format_hex - Output \p N as a fixed width hexadecimal. If number will not | |
269 | /// fit in width, full number is still printed. Examples: | |
270 | /// OS << format_hex(255, 4) => 0xff | |
271 | /// OS << format_hex(255, 4, true) => 0xFF | |
272 | /// OS << format_hex(255, 6) => 0x00ff | |
273 | /// OS << format_hex(255, 2) => 0xff | |
274 | inline FormattedNumber format_hex(uint64_t N, unsigned Width, bool Upper=false) { | |
275 | assert(Width <= 18 && "hex width must be <= 18"); | |
276 | return FormattedNumber(N, 0, Width, true, Upper); | |
277 | } | |
278 | ||
279 | /// format_decimal - Output \p N as a right justified, fixed-width decimal. If | |
280 | /// number will not fit in width, full number is still printed. Examples: | |
281 | /// OS << format_decimal(0, 5) => " 0" | |
282 | /// OS << format_decimal(255, 5) => " 255" | |
283 | /// OS << format_decimal(-1, 3) => " -1" | |
284 | /// OS << format_decimal(12345, 3) => "12345" | |
285 | inline FormattedNumber format_decimal(int64_t N, unsigned Width) { | |
286 | return FormattedNumber(0, N, Width, false, false); | |
287 | } | |
288 | ||
289 | ||
223e47cc LB |
290 | } // end namespace llvm |
291 | ||
292 | #endif |