comparison include/llvm/Support/FormatVariadic.h @ 121:803732b1fca8

LLVM 5.0
author kono
date Fri, 27 Oct 2017 17:07:41 +0900
parents 1172e4bd9c6f
children
comparison
equal deleted inserted replaced
120:1172e4bd9c6f 121:803732b1fca8
24 //===----------------------------------------------------------------------===// 24 //===----------------------------------------------------------------------===//
25 25
26 #ifndef LLVM_SUPPORT_FORMATVARIADIC_H 26 #ifndef LLVM_SUPPORT_FORMATVARIADIC_H
27 #define LLVM_SUPPORT_FORMATVARIADIC_H 27 #define LLVM_SUPPORT_FORMATVARIADIC_H
28 28
29 #include "llvm/ADT/Optional.h"
29 #include "llvm/ADT/STLExtras.h" 30 #include "llvm/ADT/STLExtras.h"
30 #include "llvm/ADT/SmallString.h" 31 #include "llvm/ADT/SmallString.h"
31 #include "llvm/ADT/StringRef.h" 32 #include "llvm/ADT/StringRef.h"
32 #include "llvm/Support/DataTypes.h"
33 #include "llvm/Support/FormatCommon.h" 33 #include "llvm/Support/FormatCommon.h"
34 #include "llvm/Support/FormatProviders.h" 34 #include "llvm/Support/FormatProviders.h"
35 #include "llvm/Support/FormatVariadicDetails.h" 35 #include "llvm/Support/FormatVariadicDetails.h"
36 #include "llvm/Support/raw_ostream.h" 36 #include "llvm/Support/raw_ostream.h"
37 37 #include <cstddef>
38 #include <string> 38 #include <string>
39 #include <tuple> 39 #include <tuple>
40 #include <utility>
40 #include <vector> 41 #include <vector>
41 42
42 namespace llvm { 43 namespace llvm {
43 44
44 enum class ReplacementType { Empty, Format, Literal }; 45 enum class ReplacementType { Empty, Format, Literal };
45 46
46 struct ReplacementItem { 47 struct ReplacementItem {
47 ReplacementItem() {} 48 ReplacementItem() = default;
48 explicit ReplacementItem(StringRef Literal) 49 explicit ReplacementItem(StringRef Literal)
49 : Type(ReplacementType::Literal), Spec(Literal) {} 50 : Type(ReplacementType::Literal), Spec(Literal) {}
50 ReplacementItem(StringRef Spec, size_t Index, size_t Align, AlignStyle Where, 51 ReplacementItem(StringRef Spec, size_t Index, size_t Align, AlignStyle Where,
51 char Pad, StringRef Options) 52 char Pad, StringRef Options)
52 : Type(ReplacementType::Format), Spec(Spec), Index(Index), Align(Align), 53 : Type(ReplacementType::Format), Spec(Spec), Index(Index), Align(Align),
53 Where(Where), Pad(Pad), Options(Options) {} 54 Where(Where), Pad(Pad), Options(Options) {}
55
54 ReplacementType Type = ReplacementType::Empty; 56 ReplacementType Type = ReplacementType::Empty;
55 StringRef Spec; 57 StringRef Spec;
56 size_t Index = 0; 58 size_t Index = 0;
57 size_t Align = 0; 59 size_t Align = 0;
58 AlignStyle Where = AlignStyle::Right; 60 AlignStyle Where = AlignStyle::Right;
67 // structure to put the parameters into a std::vector. Since the parameters 69 // structure to put the parameters into a std::vector. Since the parameters
68 // are not all the same type, we use some type-erasure by wrapping the 70 // are not all the same type, we use some type-erasure by wrapping the
69 // parameters in a template class that derives from a non-template superclass. 71 // parameters in a template class that derives from a non-template superclass.
70 // Essentially, we are converting a std::tuple<Derived<Ts...>> to a 72 // Essentially, we are converting a std::tuple<Derived<Ts...>> to a
71 // std::vector<Base*>. 73 // std::vector<Base*>.
72 struct create_wrappers { 74 struct create_adapters {
73 template <typename... Ts> 75 template <typename... Ts>
74 std::vector<detail::format_wrapper *> operator()(Ts &... Items) { 76 std::vector<detail::format_adapter *> operator()(Ts &... Items) {
75 return std::vector<detail::format_wrapper *>{&Items...}; 77 return std::vector<detail::format_adapter *>{&Items...};
76 } 78 }
77 }; 79 };
78 80
79 StringRef Fmt; 81 StringRef Fmt;
80 std::vector<detail::format_wrapper *> Wrappers; 82 std::vector<detail::format_adapter *> Adapters;
81 std::vector<ReplacementItem> Replacements; 83 std::vector<ReplacementItem> Replacements;
82 84
83 static bool consumeFieldLayout(StringRef &Spec, AlignStyle &Where, 85 static bool consumeFieldLayout(StringRef &Spec, AlignStyle &Where,
84 size_t &Align, char &Pad); 86 size_t &Align, char &Pad);
85 87
87 splitLiteralAndReplacement(StringRef Fmt); 89 splitLiteralAndReplacement(StringRef Fmt);
88 90
89 public: 91 public:
90 formatv_object_base(StringRef Fmt, std::size_t ParamCount) 92 formatv_object_base(StringRef Fmt, std::size_t ParamCount)
91 : Fmt(Fmt), Replacements(parseFormatString(Fmt)) { 93 : Fmt(Fmt), Replacements(parseFormatString(Fmt)) {
92 Wrappers.reserve(ParamCount); 94 Adapters.reserve(ParamCount);
93 return; 95 }
94 } 96
97 formatv_object_base(formatv_object_base const &rhs) = delete;
98
99 formatv_object_base(formatv_object_base &&rhs)
100 : Fmt(std::move(rhs.Fmt)),
101 Adapters(), // Adapters are initialized by formatv_object
102 Replacements(std::move(rhs.Replacements)) {
103 Adapters.reserve(rhs.Adapters.size());
104 };
95 105
96 void format(raw_ostream &S) const { 106 void format(raw_ostream &S) const {
97 for (auto &R : Replacements) { 107 for (auto &R : Replacements) {
98 if (R.Type == ReplacementType::Empty) 108 if (R.Type == ReplacementType::Empty)
99 continue; 109 continue;
100 if (R.Type == ReplacementType::Literal) { 110 if (R.Type == ReplacementType::Literal) {
101 S << R.Spec; 111 S << R.Spec;
102 continue; 112 continue;
103 } 113 }
104 if (R.Index >= Wrappers.size()) { 114 if (R.Index >= Adapters.size()) {
105 S << R.Spec; 115 S << R.Spec;
106 continue; 116 continue;
107 } 117 }
108 118
109 auto W = Wrappers[R.Index]; 119 auto W = Adapters[R.Index];
110 120
111 FmtAlign Align(*W, R.Where, R.Align); 121 FmtAlign Align(*W, R.Where, R.Align);
112 Align.format(S, R.Options); 122 Align.format(S, R.Options);
113 } 123 }
114 } 124 }
122 Stream << *this; 132 Stream << *this;
123 Stream.flush(); 133 Stream.flush();
124 return Result; 134 return Result;
125 } 135 }
126 136
127 template <unsigned N> llvm::SmallString<N> sstr() const { 137 template <unsigned N> SmallString<N> sstr() const {
128 SmallString<N> Result; 138 SmallString<N> Result;
129 raw_svector_ostream Stream(Result); 139 raw_svector_ostream Stream(Result);
130 Stream << *this; 140 Stream << *this;
131 return Result; 141 return Result;
132 } 142 }
135 145
136 operator std::string() const { return str(); } 146 operator std::string() const { return str(); }
137 }; 147 };
138 148
139 template <typename Tuple> class formatv_object : public formatv_object_base { 149 template <typename Tuple> class formatv_object : public formatv_object_base {
140 // Storage for the parameter wrappers. Since the base class erases the type 150 // Storage for the parameter adapters. Since the base class erases the type
141 // of the parameters, we have to own the storage for the parameters here, and 151 // of the parameters, we have to own the storage for the parameters here, and
142 // have the base class store type-erased pointers into this tuple. 152 // have the base class store type-erased pointers into this tuple.
143 Tuple Parameters; 153 Tuple Parameters;
144 154
145 public: 155 public:
146 formatv_object(StringRef Fmt, Tuple &&Params) 156 formatv_object(StringRef Fmt, Tuple &&Params)
147 : formatv_object_base(Fmt, std::tuple_size<Tuple>::value), 157 : formatv_object_base(Fmt, std::tuple_size<Tuple>::value),
148 Parameters(std::move(Params)) { 158 Parameters(std::move(Params)) {
149 Wrappers = apply_tuple(create_wrappers(), Parameters); 159 Adapters = apply_tuple(create_adapters(), Parameters);
160 }
161
162 formatv_object(formatv_object const &rhs) = delete;
163
164 formatv_object(formatv_object &&rhs)
165 : formatv_object_base(std::move(rhs)),
166 Parameters(std::move(rhs.Parameters)) {
167 Adapters = apply_tuple(create_adapters(), Parameters);
150 } 168 }
151 }; 169 };
152 170
153 // \brief Format text given a format string and replacement parameters. 171 // \brief Format text given a format string and replacement parameters.
154 // 172 //
193 // replacement sequence. Outside of a replacement sequence, in order to print 211 // replacement sequence. Outside of a replacement sequence, in order to print
194 // a literal '{' or '}' it must be doubled -- "{{" to print a literal '{' and 212 // a literal '{' or '}' it must be doubled -- "{{" to print a literal '{' and
195 // "}}" to print a literal '}'. 213 // "}}" to print a literal '}'.
196 // 214 //
197 // ===Parameter Indexing=== 215 // ===Parameter Indexing===
198 // `index` specifies the index of the paramter in the parameter pack to format 216 // `index` specifies the index of the parameter in the parameter pack to format
199 // into the output. Note that it is possible to refer to the same parameter 217 // into the output. Note that it is possible to refer to the same parameter
200 // index multiple times in a given format string. This makes it possible to 218 // index multiple times in a given format string. This makes it possible to
201 // output the same value multiple times without passing it multiple times to the 219 // output the same value multiple times without passing it multiple times to the
202 // function. For example: 220 // function. For example:
203 // 221 //
210 // ===Formatter Search=== 228 // ===Formatter Search===
211 // 229 //
212 // For a given parameter of type T, the following steps are executed in order 230 // For a given parameter of type T, the following steps are executed in order
213 // until a match is found: 231 // until a match is found:
214 // 232 //
215 // 1. If the parameter is of class type, and contains a method 233 // 1. If the parameter is of class type, and inherits from format_adapter,
216 // void format(raw_ostream &Stream, StringRef Options) 234 // Then format() is invoked on it to produce the formatted output. The
217 // Then this method is invoked to produce the formatted output. The
218 // implementation should write the formatted text into `Stream`. 235 // implementation should write the formatted text into `Stream`.
219 // 2. If there is a suitable template specialization of format_provider<> 236 // 2. If there is a suitable template specialization of format_provider<>
220 // for type T containing a method whose signature is: 237 // for type T containing a method whose signature is:
221 // void format(const T &Obj, raw_ostream &Stream, StringRef Options) 238 // void format(const T &Obj, raw_ostream &Stream, StringRef Options)
222 // Then this method is invoked as described in Step 1. 239 // Then this method is invoked as described in Step 1.
231 // assertion. Otherwise, it will try to do something reasonable, but in general 248 // assertion. Otherwise, it will try to do something reasonable, but in general
232 // the details of what that is are undefined. 249 // the details of what that is are undefined.
233 // 250 //
234 template <typename... Ts> 251 template <typename... Ts>
235 inline auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object<decltype( 252 inline auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object<decltype(
236 std::make_tuple(detail::build_format_wrapper(std::forward<Ts>(Vals))...))> { 253 std::make_tuple(detail::build_format_adapter(std::forward<Ts>(Vals))...))> {
237 using ParamTuple = decltype( 254 using ParamTuple = decltype(
238 std::make_tuple(detail::build_format_wrapper(std::forward<Ts>(Vals))...)); 255 std::make_tuple(detail::build_format_adapter(std::forward<Ts>(Vals))...));
239 return formatv_object<ParamTuple>( 256 return formatv_object<ParamTuple>(
240 Fmt, 257 Fmt,
241 std::make_tuple(detail::build_format_wrapper(std::forward<Ts>(Vals))...)); 258 std::make_tuple(detail::build_format_adapter(std::forward<Ts>(Vals))...));
242 } 259 }
243 260
261 // Allow a formatv_object to be formatted (no options supported).
262 template <typename T> struct format_provider<formatv_object<T>> {
263 static void format(const formatv_object<T> &V, raw_ostream &OS, StringRef) {
264 OS << V;
265 }
266 };
267
244 } // end namespace llvm 268 } // end namespace llvm
245 269
246 #endif 270 #endif // LLVM_SUPPORT_FORMATVARIADIC_H