Mercurial > hg > Members > tobaru > cbc > CbC_llvm
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 |