File: | tools/clang/tools/extra/clangd/index/YAMLSerialization.cpp |
Warning: | line 124, column 5 1st function call argument is an uninitialized value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===--- SymbolYAML.cpp ------------------------------------------*- 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 | // A YAML index file is a sequence of tagged entries. | |||
11 | // Each entry either encodes a Symbol or the list of references to a symbol | |||
12 | // (a "ref bundle"). | |||
13 | // | |||
14 | //===----------------------------------------------------------------------===// | |||
15 | ||||
16 | #include "Index.h" | |||
17 | #include "Serialization.h" | |||
18 | #include "Trace.h" | |||
19 | #include "dex/Dex.h" | |||
20 | #include "llvm/ADT/Optional.h" | |||
21 | #include "llvm/ADT/SmallVector.h" | |||
22 | #include "llvm/ADT/StringRef.h" | |||
23 | #include "llvm/Support/Errc.h" | |||
24 | #include "llvm/Support/MemoryBuffer.h" | |||
25 | #include "llvm/Support/YAMLTraits.h" | |||
26 | #include "llvm/Support/raw_ostream.h" | |||
27 | #include <cstdint> | |||
28 | ||||
29 | using namespace llvm; | |||
30 | ||||
31 | LLVM_YAML_IS_SEQUENCE_VECTOR(clang::clangd::Symbol::IncludeHeaderWithReferences)namespace llvm { namespace yaml { static_assert( !std::is_fundamental <clang::clangd::Symbol::IncludeHeaderWithReferences>::value && !std::is_same<clang::clangd::Symbol::IncludeHeaderWithReferences , std::string>::value && !std::is_same<clang::clangd ::Symbol::IncludeHeaderWithReferences, llvm::StringRef>::value , "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control" ); template <> struct SequenceElementTraits<clang::clangd ::Symbol::IncludeHeaderWithReferences> { static const bool flow = false; }; } } | |||
32 | LLVM_YAML_IS_SEQUENCE_VECTOR(clang::clangd::Ref)namespace llvm { namespace yaml { static_assert( !std::is_fundamental <clang::clangd::Ref>::value && !std::is_same< clang::clangd::Ref, std::string>::value && !std::is_same <clang::clangd::Ref, llvm::StringRef>::value, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control" ); template <> struct SequenceElementTraits<clang::clangd ::Ref> { static const bool flow = false; }; } } | |||
33 | ||||
34 | namespace { | |||
35 | using RefBundle = | |||
36 | std::pair<clang::clangd::SymbolID, std::vector<clang::clangd::Ref>>; | |||
37 | // This is a pale imitation of std::variant<Symbol, RefBundle> | |||
38 | struct VariantEntry { | |||
39 | Optional<clang::clangd::Symbol> Symbol; | |||
40 | Optional<RefBundle> Refs; | |||
41 | }; | |||
42 | // A class helps YAML to serialize the 32-bit encoded position (Line&Column), | |||
43 | // as YAMLIO can't directly map bitfields. | |||
44 | struct YPosition { | |||
45 | uint32_t Line; | |||
46 | uint32_t Column; | |||
47 | }; | |||
48 | ||||
49 | } // namespace | |||
50 | namespace llvm { | |||
51 | namespace yaml { | |||
52 | ||||
53 | using clang::clangd::Ref; | |||
54 | using clang::clangd::RefKind; | |||
55 | using clang::clangd::Symbol; | |||
56 | using clang::clangd::SymbolID; | |||
57 | using clang::clangd::SymbolLocation; | |||
58 | using clang::clangd::SymbolOrigin; | |||
59 | using clang::index::SymbolInfo; | |||
60 | using clang::index::SymbolKind; | |||
61 | using clang::index::SymbolLanguage; | |||
62 | ||||
63 | // Helper to (de)serialize the SymbolID. We serialize it as a hex string. | |||
64 | struct NormalizedSymbolID { | |||
65 | NormalizedSymbolID(IO &) {} | |||
66 | NormalizedSymbolID(IO &, const SymbolID &ID) { | |||
67 | raw_string_ostream OS(HexString); | |||
68 | OS << ID; | |||
69 | } | |||
70 | ||||
71 | SymbolID denormalize(IO &I) { | |||
72 | auto ID = SymbolID::fromStr(HexString); | |||
73 | if (!ID) { | |||
74 | I.setError(toString(ID.takeError())); | |||
75 | return SymbolID(); | |||
76 | } | |||
77 | return *ID; | |||
78 | } | |||
79 | ||||
80 | std::string HexString; | |||
81 | }; | |||
82 | ||||
83 | struct NormalizedSymbolFlag { | |||
84 | NormalizedSymbolFlag(IO &) {} | |||
85 | NormalizedSymbolFlag(IO &, Symbol::SymbolFlag F) { | |||
86 | Flag = static_cast<uint8_t>(F); | |||
87 | } | |||
88 | ||||
89 | Symbol::SymbolFlag denormalize(IO &) { | |||
90 | return static_cast<Symbol::SymbolFlag>(Flag); | |||
91 | } | |||
92 | ||||
93 | uint8_t Flag = 0; | |||
94 | }; | |||
95 | ||||
96 | struct NormalizedSymbolOrigin { | |||
97 | NormalizedSymbolOrigin(IO &) {} | |||
98 | NormalizedSymbolOrigin(IO &, SymbolOrigin O) { | |||
99 | Origin = static_cast<uint8_t>(O); | |||
100 | } | |||
101 | ||||
102 | SymbolOrigin denormalize(IO &) { return static_cast<SymbolOrigin>(Origin); } | |||
103 | ||||
104 | uint8_t Origin = 0; | |||
105 | }; | |||
106 | ||||
107 | template <> struct MappingTraits<YPosition> { | |||
108 | static void mapping(IO &IO, YPosition &Value) { | |||
109 | IO.mapRequired("Line", Value.Line); | |||
110 | IO.mapRequired("Column", Value.Column); | |||
111 | } | |||
112 | }; | |||
113 | ||||
114 | struct NormalizedPosition { | |||
115 | using Position = clang::clangd::SymbolLocation::Position; | |||
116 | NormalizedPosition(IO &) {} | |||
117 | NormalizedPosition(IO &, const Position &Pos) { | |||
118 | P.Line = Pos.line(); | |||
119 | P.Column = Pos.column(); | |||
120 | } | |||
121 | ||||
122 | Position denormalize(IO &) { | |||
123 | Position Pos; | |||
124 | Pos.setLine(P.Line); | |||
| ||||
125 | Pos.setColumn(P.Column); | |||
126 | return Pos; | |||
127 | } | |||
128 | YPosition P; | |||
129 | }; | |||
130 | ||||
131 | template <> struct MappingTraits<SymbolLocation> { | |||
132 | static void mapping(IO &IO, SymbolLocation &Value) { | |||
133 | IO.mapRequired("FileURI", Value.FileURI); | |||
134 | MappingNormalization<NormalizedPosition, SymbolLocation::Position> NStart( | |||
135 | IO, Value.Start); | |||
136 | IO.mapRequired("Start", NStart->P); | |||
137 | MappingNormalization<NormalizedPosition, SymbolLocation::Position> NEnd( | |||
138 | IO, Value.End); | |||
139 | IO.mapRequired("End", NEnd->P); | |||
140 | } | |||
141 | }; | |||
142 | ||||
143 | template <> struct MappingTraits<SymbolInfo> { | |||
144 | static void mapping(IO &io, SymbolInfo &SymInfo) { | |||
145 | // FIXME: expose other fields? | |||
146 | io.mapRequired("Kind", SymInfo.Kind); | |||
147 | io.mapRequired("Lang", SymInfo.Lang); | |||
148 | } | |||
149 | }; | |||
150 | ||||
151 | template <> | |||
152 | struct MappingTraits<clang::clangd::Symbol::IncludeHeaderWithReferences> { | |||
153 | static void mapping(IO &io, | |||
154 | clang::clangd::Symbol::IncludeHeaderWithReferences &Inc) { | |||
155 | io.mapRequired("Header", Inc.IncludeHeader); | |||
156 | io.mapRequired("References", Inc.References); | |||
157 | } | |||
158 | }; | |||
159 | ||||
160 | template <> struct MappingTraits<Symbol> { | |||
161 | static void mapping(IO &IO, Symbol &Sym) { | |||
162 | MappingNormalization<NormalizedSymbolID, SymbolID> NSymbolID(IO, Sym.ID); | |||
163 | MappingNormalization<NormalizedSymbolFlag, Symbol::SymbolFlag> NSymbolFlag( | |||
164 | IO, Sym.Flags); | |||
165 | MappingNormalization<NormalizedSymbolOrigin, SymbolOrigin> NSymbolOrigin( | |||
166 | IO, Sym.Origin); | |||
167 | IO.mapRequired("ID", NSymbolID->HexString); | |||
168 | IO.mapRequired("Name", Sym.Name); | |||
169 | IO.mapRequired("Scope", Sym.Scope); | |||
170 | IO.mapRequired("SymInfo", Sym.SymInfo); | |||
171 | IO.mapOptional("CanonicalDeclaration", Sym.CanonicalDeclaration, | |||
172 | SymbolLocation()); | |||
173 | IO.mapOptional("Definition", Sym.Definition, SymbolLocation()); | |||
174 | IO.mapOptional("References", Sym.References, 0u); | |||
175 | IO.mapOptional("Origin", NSymbolOrigin->Origin); | |||
176 | IO.mapOptional("Flags", NSymbolFlag->Flag); | |||
177 | IO.mapOptional("Signature", Sym.Signature); | |||
178 | IO.mapOptional("CompletionSnippetSuffix", Sym.CompletionSnippetSuffix); | |||
179 | IO.mapOptional("Documentation", Sym.Documentation); | |||
180 | IO.mapOptional("ReturnType", Sym.ReturnType); | |||
181 | IO.mapOptional("IncludeHeaders", Sym.IncludeHeaders); | |||
182 | } | |||
183 | }; | |||
184 | ||||
185 | template <> struct ScalarEnumerationTraits<SymbolLanguage> { | |||
186 | static void enumeration(IO &IO, SymbolLanguage &Value) { | |||
187 | IO.enumCase(Value, "C", SymbolLanguage::C); | |||
188 | IO.enumCase(Value, "Cpp", SymbolLanguage::CXX); | |||
189 | IO.enumCase(Value, "ObjC", SymbolLanguage::ObjC); | |||
190 | IO.enumCase(Value, "Swift", SymbolLanguage::Swift); | |||
191 | } | |||
192 | }; | |||
193 | ||||
194 | template <> struct ScalarEnumerationTraits<SymbolKind> { | |||
195 | static void enumeration(IO &IO, SymbolKind &Value) { | |||
196 | #define DEFINE_ENUM(name) IO.enumCase(Value, #name, SymbolKind::name) | |||
197 | ||||
198 | DEFINE_ENUM(Unknown); | |||
199 | DEFINE_ENUM(Function); | |||
200 | DEFINE_ENUM(Module); | |||
201 | DEFINE_ENUM(Namespace); | |||
202 | DEFINE_ENUM(NamespaceAlias); | |||
203 | DEFINE_ENUM(Macro); | |||
204 | DEFINE_ENUM(Enum); | |||
205 | DEFINE_ENUM(Struct); | |||
206 | DEFINE_ENUM(Class); | |||
207 | DEFINE_ENUM(Protocol); | |||
208 | DEFINE_ENUM(Extension); | |||
209 | DEFINE_ENUM(Union); | |||
210 | DEFINE_ENUM(TypeAlias); | |||
211 | DEFINE_ENUM(Function); | |||
212 | DEFINE_ENUM(Variable); | |||
213 | DEFINE_ENUM(Field); | |||
214 | DEFINE_ENUM(EnumConstant); | |||
215 | DEFINE_ENUM(InstanceMethod); | |||
216 | DEFINE_ENUM(ClassMethod); | |||
217 | DEFINE_ENUM(StaticMethod); | |||
218 | DEFINE_ENUM(InstanceProperty); | |||
219 | DEFINE_ENUM(ClassProperty); | |||
220 | DEFINE_ENUM(StaticProperty); | |||
221 | DEFINE_ENUM(Constructor); | |||
222 | DEFINE_ENUM(Destructor); | |||
223 | DEFINE_ENUM(ConversionFunction); | |||
224 | DEFINE_ENUM(Parameter); | |||
225 | DEFINE_ENUM(Using); | |||
226 | ||||
227 | #undef DEFINE_ENUM | |||
228 | } | |||
229 | }; | |||
230 | ||||
231 | template <> struct MappingTraits<RefBundle> { | |||
232 | static void mapping(IO &IO, RefBundle &Refs) { | |||
233 | MappingNormalization<NormalizedSymbolID, SymbolID> NSymbolID(IO, | |||
234 | Refs.first); | |||
235 | IO.mapRequired("ID", NSymbolID->HexString); | |||
236 | IO.mapRequired("References", Refs.second); | |||
237 | } | |||
238 | }; | |||
239 | ||||
240 | struct NormalizedRefKind { | |||
241 | NormalizedRefKind(IO &) {} | |||
242 | NormalizedRefKind(IO &, RefKind O) { Kind = static_cast<uint8_t>(O); } | |||
243 | ||||
244 | RefKind denormalize(IO &) { return static_cast<RefKind>(Kind); } | |||
245 | ||||
246 | uint8_t Kind = 0; | |||
247 | }; | |||
248 | ||||
249 | template <> struct MappingTraits<Ref> { | |||
250 | static void mapping(IO &IO, Ref &R) { | |||
251 | MappingNormalization<NormalizedRefKind, RefKind> NKind(IO, R.Kind); | |||
252 | IO.mapRequired("Kind", NKind->Kind); | |||
253 | IO.mapRequired("Location", R.Location); | |||
254 | } | |||
255 | }; | |||
256 | ||||
257 | template <> struct MappingTraits<VariantEntry> { | |||
258 | static void mapping(IO &IO, VariantEntry &Variant) { | |||
259 | if (IO.mapTag("!Symbol", Variant.Symbol.hasValue())) { | |||
260 | if (!IO.outputting()) | |||
261 | Variant.Symbol.emplace(); | |||
262 | MappingTraits<Symbol>::mapping(IO, *Variant.Symbol); | |||
263 | } else if (IO.mapTag("!Refs", Variant.Refs.hasValue())) { | |||
264 | if (!IO.outputting()) | |||
265 | Variant.Refs.emplace(); | |||
266 | MappingTraits<RefBundle>::mapping(IO, *Variant.Refs); | |||
267 | } | |||
268 | } | |||
269 | }; | |||
270 | ||||
271 | } // namespace yaml | |||
272 | } // namespace llvm | |||
273 | ||||
274 | namespace clang { | |||
275 | namespace clangd { | |||
276 | ||||
277 | void writeYAML(const IndexFileOut &O, raw_ostream &OS) { | |||
278 | yaml::Output Yout(OS); | |||
279 | for (const auto &Sym : *O.Symbols) { | |||
280 | VariantEntry Entry; | |||
281 | Entry.Symbol = Sym; | |||
282 | Yout << Entry; | |||
283 | } | |||
284 | if (O.Refs) | |||
285 | for (auto &Sym : *O.Refs) { | |||
286 | VariantEntry Entry; | |||
287 | Entry.Refs = Sym; | |||
288 | Yout << Entry; | |||
289 | } | |||
290 | } | |||
291 | ||||
292 | Expected<IndexFileIn> readYAML(StringRef Data) { | |||
293 | SymbolSlab::Builder Symbols; | |||
294 | RefSlab::Builder Refs; | |||
295 | yaml::Input Yin(Data); | |||
296 | do { | |||
297 | VariantEntry Variant; | |||
298 | Yin >> Variant; | |||
299 | if (Yin.error()) | |||
300 | return errorCodeToError(Yin.error()); | |||
301 | if (Variant.Symbol) | |||
302 | Symbols.insert(*Variant.Symbol); | |||
303 | if (Variant.Refs) | |||
304 | for (const auto &Ref : Variant.Refs->second) | |||
305 | Refs.insert(Variant.Refs->first, Ref); | |||
306 | } while (Yin.nextDocument()); | |||
307 | ||||
308 | IndexFileIn Result; | |||
309 | Result.Symbols.emplace(std::move(Symbols).build()); | |||
310 | Result.Refs.emplace(std::move(Refs).build()); | |||
311 | return std::move(Result); | |||
312 | } | |||
313 | ||||
314 | std::string toYAML(const Symbol &S) { | |||
315 | std::string Buf; | |||
316 | { | |||
317 | raw_string_ostream OS(Buf); | |||
318 | yaml::Output Yout(OS); | |||
319 | Symbol Sym = S; // copy: Yout<< requires mutability. | |||
320 | Yout << Sym; | |||
| ||||
321 | } | |||
322 | return Buf; | |||
323 | } | |||
324 | ||||
325 | std::string toYAML(const std::pair<SymbolID, ArrayRef<Ref>> &Data) { | |||
326 | RefBundle Refs = {Data.first, Data.second}; | |||
327 | std::string Buf; | |||
328 | { | |||
329 | raw_string_ostream OS(Buf); | |||
330 | yaml::Output Yout(OS); | |||
331 | Yout << Refs; | |||
332 | } | |||
333 | return Buf; | |||
334 | } | |||
335 | ||||
336 | } // namespace clangd | |||
337 | } // namespace clang |
1 | //===- llvm/Support/YAMLTraits.h --------------------------------*- C++ -*-===// |
2 | // |
3 | // The LLVM Linker |
4 | // |
5 | // This file is distributed under the University of Illinois Open Source |
6 | // License. See LICENSE.TXT for details. |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | |
10 | #ifndef LLVM_SUPPORT_YAMLTRAITS_H |
11 | #define LLVM_SUPPORT_YAMLTRAITS_H |
12 | |
13 | #include "llvm/ADT/Optional.h" |
14 | #include "llvm/ADT/SmallVector.h" |
15 | #include "llvm/ADT/StringExtras.h" |
16 | #include "llvm/ADT/StringMap.h" |
17 | #include "llvm/ADT/StringRef.h" |
18 | #include "llvm/ADT/Twine.h" |
19 | #include "llvm/Support/AlignOf.h" |
20 | #include "llvm/Support/Allocator.h" |
21 | #include "llvm/Support/Endian.h" |
22 | #include "llvm/Support/Regex.h" |
23 | #include "llvm/Support/SourceMgr.h" |
24 | #include "llvm/Support/YAMLParser.h" |
25 | #include "llvm/Support/raw_ostream.h" |
26 | #include <cassert> |
27 | #include <cctype> |
28 | #include <cstddef> |
29 | #include <cstdint> |
30 | #include <iterator> |
31 | #include <map> |
32 | #include <memory> |
33 | #include <new> |
34 | #include <string> |
35 | #include <system_error> |
36 | #include <type_traits> |
37 | #include <vector> |
38 | |
39 | namespace llvm { |
40 | namespace yaml { |
41 | |
42 | struct EmptyContext {}; |
43 | |
44 | /// This class should be specialized by any type that needs to be converted |
45 | /// to/from a YAML mapping. For example: |
46 | /// |
47 | /// struct MappingTraits<MyStruct> { |
48 | /// static void mapping(IO &io, MyStruct &s) { |
49 | /// io.mapRequired("name", s.name); |
50 | /// io.mapRequired("size", s.size); |
51 | /// io.mapOptional("age", s.age); |
52 | /// } |
53 | /// }; |
54 | template<class T> |
55 | struct MappingTraits { |
56 | // Must provide: |
57 | // static void mapping(IO &io, T &fields); |
58 | // Optionally may provide: |
59 | // static StringRef validate(IO &io, T &fields); |
60 | // |
61 | // The optional flow flag will cause generated YAML to use a flow mapping |
62 | // (e.g. { a: 0, b: 1 }): |
63 | // static const bool flow = true; |
64 | }; |
65 | |
66 | /// This class is similar to MappingTraits<T> but allows you to pass in |
67 | /// additional context for each map operation. For example: |
68 | /// |
69 | /// struct MappingContextTraits<MyStruct, MyContext> { |
70 | /// static void mapping(IO &io, MyStruct &s, MyContext &c) { |
71 | /// io.mapRequired("name", s.name); |
72 | /// io.mapRequired("size", s.size); |
73 | /// io.mapOptional("age", s.age); |
74 | /// ++c.TimesMapped; |
75 | /// } |
76 | /// }; |
77 | template <class T, class Context> struct MappingContextTraits { |
78 | // Must provide: |
79 | // static void mapping(IO &io, T &fields, Context &Ctx); |
80 | // Optionally may provide: |
81 | // static StringRef validate(IO &io, T &fields, Context &Ctx); |
82 | // |
83 | // The optional flow flag will cause generated YAML to use a flow mapping |
84 | // (e.g. { a: 0, b: 1 }): |
85 | // static const bool flow = true; |
86 | }; |
87 | |
88 | /// This class should be specialized by any integral type that converts |
89 | /// to/from a YAML scalar where there is a one-to-one mapping between |
90 | /// in-memory values and a string in YAML. For example: |
91 | /// |
92 | /// struct ScalarEnumerationTraits<Colors> { |
93 | /// static void enumeration(IO &io, Colors &value) { |
94 | /// io.enumCase(value, "red", cRed); |
95 | /// io.enumCase(value, "blue", cBlue); |
96 | /// io.enumCase(value, "green", cGreen); |
97 | /// } |
98 | /// }; |
99 | template<typename T> |
100 | struct ScalarEnumerationTraits { |
101 | // Must provide: |
102 | // static void enumeration(IO &io, T &value); |
103 | }; |
104 | |
105 | /// This class should be specialized by any integer type that is a union |
106 | /// of bit values and the YAML representation is a flow sequence of |
107 | /// strings. For example: |
108 | /// |
109 | /// struct ScalarBitSetTraits<MyFlags> { |
110 | /// static void bitset(IO &io, MyFlags &value) { |
111 | /// io.bitSetCase(value, "big", flagBig); |
112 | /// io.bitSetCase(value, "flat", flagFlat); |
113 | /// io.bitSetCase(value, "round", flagRound); |
114 | /// } |
115 | /// }; |
116 | template<typename T> |
117 | struct ScalarBitSetTraits { |
118 | // Must provide: |
119 | // static void bitset(IO &io, T &value); |
120 | }; |
121 | |
122 | /// Describe which type of quotes should be used when quoting is necessary. |
123 | /// Some non-printable characters need to be double-quoted, while some others |
124 | /// are fine with simple-quoting, and some don't need any quoting. |
125 | enum class QuotingType { None, Single, Double }; |
126 | |
127 | /// This class should be specialized by type that requires custom conversion |
128 | /// to/from a yaml scalar. For example: |
129 | /// |
130 | /// template<> |
131 | /// struct ScalarTraits<MyType> { |
132 | /// static void output(const MyType &val, void*, llvm::raw_ostream &out) { |
133 | /// // stream out custom formatting |
134 | /// out << llvm::format("%x", val); |
135 | /// } |
136 | /// static StringRef input(StringRef scalar, void*, MyType &value) { |
137 | /// // parse scalar and set `value` |
138 | /// // return empty string on success, or error string |
139 | /// return StringRef(); |
140 | /// } |
141 | /// static QuotingType mustQuote(StringRef) { return QuotingType::Single; } |
142 | /// }; |
143 | template<typename T> |
144 | struct ScalarTraits { |
145 | // Must provide: |
146 | // |
147 | // Function to write the value as a string: |
148 | //static void output(const T &value, void *ctxt, llvm::raw_ostream &out); |
149 | // |
150 | // Function to convert a string to a value. Returns the empty |
151 | // StringRef on success or an error string if string is malformed: |
152 | //static StringRef input(StringRef scalar, void *ctxt, T &value); |
153 | // |
154 | // Function to determine if the value should be quoted. |
155 | //static QuotingType mustQuote(StringRef); |
156 | }; |
157 | |
158 | /// This class should be specialized by type that requires custom conversion |
159 | /// to/from a YAML literal block scalar. For example: |
160 | /// |
161 | /// template <> |
162 | /// struct BlockScalarTraits<MyType> { |
163 | /// static void output(const MyType &Value, void*, llvm::raw_ostream &Out) |
164 | /// { |
165 | /// // stream out custom formatting |
166 | /// Out << Val; |
167 | /// } |
168 | /// static StringRef input(StringRef Scalar, void*, MyType &Value) { |
169 | /// // parse scalar and set `value` |
170 | /// // return empty string on success, or error string |
171 | /// return StringRef(); |
172 | /// } |
173 | /// }; |
174 | template <typename T> |
175 | struct BlockScalarTraits { |
176 | // Must provide: |
177 | // |
178 | // Function to write the value as a string: |
179 | // static void output(const T &Value, void *ctx, llvm::raw_ostream &Out); |
180 | // |
181 | // Function to convert a string to a value. Returns the empty |
182 | // StringRef on success or an error string if string is malformed: |
183 | // static StringRef input(StringRef Scalar, void *ctxt, T &Value); |
184 | }; |
185 | |
186 | /// This class should be specialized by any type that needs to be converted |
187 | /// to/from a YAML sequence. For example: |
188 | /// |
189 | /// template<> |
190 | /// struct SequenceTraits<MyContainer> { |
191 | /// static size_t size(IO &io, MyContainer &seq) { |
192 | /// return seq.size(); |
193 | /// } |
194 | /// static MyType& element(IO &, MyContainer &seq, size_t index) { |
195 | /// if ( index >= seq.size() ) |
196 | /// seq.resize(index+1); |
197 | /// return seq[index]; |
198 | /// } |
199 | /// }; |
200 | template<typename T, typename EnableIf = void> |
201 | struct SequenceTraits { |
202 | // Must provide: |
203 | // static size_t size(IO &io, T &seq); |
204 | // static T::value_type& element(IO &io, T &seq, size_t index); |
205 | // |
206 | // The following is option and will cause generated YAML to use |
207 | // a flow sequence (e.g. [a,b,c]). |
208 | // static const bool flow = true; |
209 | }; |
210 | |
211 | /// This class should be specialized by any type for which vectors of that |
212 | /// type need to be converted to/from a YAML sequence. |
213 | template<typename T, typename EnableIf = void> |
214 | struct SequenceElementTraits { |
215 | // Must provide: |
216 | // static const bool flow; |
217 | }; |
218 | |
219 | /// This class should be specialized by any type that needs to be converted |
220 | /// to/from a list of YAML documents. |
221 | template<typename T> |
222 | struct DocumentListTraits { |
223 | // Must provide: |
224 | // static size_t size(IO &io, T &seq); |
225 | // static T::value_type& element(IO &io, T &seq, size_t index); |
226 | }; |
227 | |
228 | /// This class should be specialized by any type that needs to be converted |
229 | /// to/from a YAML mapping in the case where the names of the keys are not known |
230 | /// in advance, e.g. a string map. |
231 | template <typename T> |
232 | struct CustomMappingTraits { |
233 | // static void inputOne(IO &io, StringRef key, T &elem); |
234 | // static void output(IO &io, T &elem); |
235 | }; |
236 | |
237 | // Only used for better diagnostics of missing traits |
238 | template <typename T> |
239 | struct MissingTrait; |
240 | |
241 | // Test if ScalarEnumerationTraits<T> is defined on type T. |
242 | template <class T> |
243 | struct has_ScalarEnumerationTraits |
244 | { |
245 | using Signature_enumeration = void (*)(class IO&, T&); |
246 | |
247 | template <typename U> |
248 | static char test(SameType<Signature_enumeration, &U::enumeration>*); |
249 | |
250 | template <typename U> |
251 | static double test(...); |
252 | |
253 | static bool const value = |
254 | (sizeof(test<ScalarEnumerationTraits<T>>(nullptr)) == 1); |
255 | }; |
256 | |
257 | // Test if ScalarBitSetTraits<T> is defined on type T. |
258 | template <class T> |
259 | struct has_ScalarBitSetTraits |
260 | { |
261 | using Signature_bitset = void (*)(class IO&, T&); |
262 | |
263 | template <typename U> |
264 | static char test(SameType<Signature_bitset, &U::bitset>*); |
265 | |
266 | template <typename U> |
267 | static double test(...); |
268 | |
269 | static bool const value = (sizeof(test<ScalarBitSetTraits<T>>(nullptr)) == 1); |
270 | }; |
271 | |
272 | // Test if ScalarTraits<T> is defined on type T. |
273 | template <class T> |
274 | struct has_ScalarTraits |
275 | { |
276 | using Signature_input = StringRef (*)(StringRef, void*, T&); |
277 | using Signature_output = void (*)(const T&, void*, raw_ostream&); |
278 | using Signature_mustQuote = QuotingType (*)(StringRef); |
279 | |
280 | template <typename U> |
281 | static char test(SameType<Signature_input, &U::input> *, |
282 | SameType<Signature_output, &U::output> *, |
283 | SameType<Signature_mustQuote, &U::mustQuote> *); |
284 | |
285 | template <typename U> |
286 | static double test(...); |
287 | |
288 | static bool const value = |
289 | (sizeof(test<ScalarTraits<T>>(nullptr, nullptr, nullptr)) == 1); |
290 | }; |
291 | |
292 | // Test if BlockScalarTraits<T> is defined on type T. |
293 | template <class T> |
294 | struct has_BlockScalarTraits |
295 | { |
296 | using Signature_input = StringRef (*)(StringRef, void *, T &); |
297 | using Signature_output = void (*)(const T &, void *, raw_ostream &); |
298 | |
299 | template <typename U> |
300 | static char test(SameType<Signature_input, &U::input> *, |
301 | SameType<Signature_output, &U::output> *); |
302 | |
303 | template <typename U> |
304 | static double test(...); |
305 | |
306 | static bool const value = |
307 | (sizeof(test<BlockScalarTraits<T>>(nullptr, nullptr)) == 1); |
308 | }; |
309 | |
310 | // Test if MappingContextTraits<T> is defined on type T. |
311 | template <class T, class Context> struct has_MappingTraits { |
312 | using Signature_mapping = void (*)(class IO &, T &, Context &); |
313 | |
314 | template <typename U> |
315 | static char test(SameType<Signature_mapping, &U::mapping>*); |
316 | |
317 | template <typename U> |
318 | static double test(...); |
319 | |
320 | static bool const value = |
321 | (sizeof(test<MappingContextTraits<T, Context>>(nullptr)) == 1); |
322 | }; |
323 | |
324 | // Test if MappingTraits<T> is defined on type T. |
325 | template <class T> struct has_MappingTraits<T, EmptyContext> { |
326 | using Signature_mapping = void (*)(class IO &, T &); |
327 | |
328 | template <typename U> |
329 | static char test(SameType<Signature_mapping, &U::mapping> *); |
330 | |
331 | template <typename U> static double test(...); |
332 | |
333 | static bool const value = (sizeof(test<MappingTraits<T>>(nullptr)) == 1); |
334 | }; |
335 | |
336 | // Test if MappingContextTraits<T>::validate() is defined on type T. |
337 | template <class T, class Context> struct has_MappingValidateTraits { |
338 | using Signature_validate = StringRef (*)(class IO &, T &, Context &); |
339 | |
340 | template <typename U> |
341 | static char test(SameType<Signature_validate, &U::validate>*); |
342 | |
343 | template <typename U> |
344 | static double test(...); |
345 | |
346 | static bool const value = |
347 | (sizeof(test<MappingContextTraits<T, Context>>(nullptr)) == 1); |
348 | }; |
349 | |
350 | // Test if MappingTraits<T>::validate() is defined on type T. |
351 | template <class T> struct has_MappingValidateTraits<T, EmptyContext> { |
352 | using Signature_validate = StringRef (*)(class IO &, T &); |
353 | |
354 | template <typename U> |
355 | static char test(SameType<Signature_validate, &U::validate> *); |
356 | |
357 | template <typename U> static double test(...); |
358 | |
359 | static bool const value = (sizeof(test<MappingTraits<T>>(nullptr)) == 1); |
360 | }; |
361 | |
362 | // Test if SequenceTraits<T> is defined on type T. |
363 | template <class T> |
364 | struct has_SequenceMethodTraits |
365 | { |
366 | using Signature_size = size_t (*)(class IO&, T&); |
367 | |
368 | template <typename U> |
369 | static char test(SameType<Signature_size, &U::size>*); |
370 | |
371 | template <typename U> |
372 | static double test(...); |
373 | |
374 | static bool const value = (sizeof(test<SequenceTraits<T>>(nullptr)) == 1); |
375 | }; |
376 | |
377 | // Test if CustomMappingTraits<T> is defined on type T. |
378 | template <class T> |
379 | struct has_CustomMappingTraits |
380 | { |
381 | using Signature_input = void (*)(IO &io, StringRef key, T &v); |
382 | |
383 | template <typename U> |
384 | static char test(SameType<Signature_input, &U::inputOne>*); |
385 | |
386 | template <typename U> |
387 | static double test(...); |
388 | |
389 | static bool const value = |
390 | (sizeof(test<CustomMappingTraits<T>>(nullptr)) == 1); |
391 | }; |
392 | |
393 | // has_FlowTraits<int> will cause an error with some compilers because |
394 | // it subclasses int. Using this wrapper only instantiates the |
395 | // real has_FlowTraits only if the template type is a class. |
396 | template <typename T, bool Enabled = std::is_class<T>::value> |
397 | class has_FlowTraits |
398 | { |
399 | public: |
400 | static const bool value = false; |
401 | }; |
402 | |
403 | // Some older gcc compilers don't support straight forward tests |
404 | // for members, so test for ambiguity cause by the base and derived |
405 | // classes both defining the member. |
406 | template <class T> |
407 | struct has_FlowTraits<T, true> |
408 | { |
409 | struct Fallback { bool flow; }; |
410 | struct Derived : T, Fallback { }; |
411 | |
412 | template<typename C> |
413 | static char (&f(SameType<bool Fallback::*, &C::flow>*))[1]; |
414 | |
415 | template<typename C> |
416 | static char (&f(...))[2]; |
417 | |
418 | static bool const value = sizeof(f<Derived>(nullptr)) == 2; |
419 | }; |
420 | |
421 | // Test if SequenceTraits<T> is defined on type T |
422 | template<typename T> |
423 | struct has_SequenceTraits : public std::integral_constant<bool, |
424 | has_SequenceMethodTraits<T>::value > { }; |
425 | |
426 | // Test if DocumentListTraits<T> is defined on type T |
427 | template <class T> |
428 | struct has_DocumentListTraits |
429 | { |
430 | using Signature_size = size_t (*)(class IO &, T &); |
431 | |
432 | template <typename U> |
433 | static char test(SameType<Signature_size, &U::size>*); |
434 | |
435 | template <typename U> |
436 | static double test(...); |
437 | |
438 | static bool const value = (sizeof(test<DocumentListTraits<T>>(nullptr))==1); |
439 | }; |
440 | |
441 | inline bool isNumeric(StringRef S) { |
442 | const static auto skipDigits = [](StringRef Input) { |
443 | return Input.drop_front( |
444 | std::min(Input.find_first_not_of("0123456789"), Input.size())); |
445 | }; |
446 | |
447 | // Make S.front() and S.drop_front().front() (if S.front() is [+-]) calls |
448 | // safe. |
449 | if (S.empty() || S.equals("+") || S.equals("-")) |
450 | return false; |
451 | |
452 | if (S.equals(".nan") || S.equals(".NaN") || S.equals(".NAN")) |
453 | return true; |
454 | |
455 | // Infinity and decimal numbers can be prefixed with sign. |
456 | StringRef Tail = (S.front() == '-' || S.front() == '+') ? S.drop_front() : S; |
457 | |
458 | // Check for infinity first, because checking for hex and oct numbers is more |
459 | // expensive. |
460 | if (Tail.equals(".inf") || Tail.equals(".Inf") || Tail.equals(".INF")) |
461 | return true; |
462 | |
463 | // Section 10.3.2 Tag Resolution |
464 | // YAML 1.2 Specification prohibits Base 8 and Base 16 numbers prefixed with |
465 | // [-+], so S should be used instead of Tail. |
466 | if (S.startswith("0o")) |
467 | return S.size() > 2 && |
468 | S.drop_front(2).find_first_not_of("01234567") == StringRef::npos; |
469 | |
470 | if (S.startswith("0x")) |
471 | return S.size() > 2 && S.drop_front(2).find_first_not_of( |
472 | "0123456789abcdefABCDEF") == StringRef::npos; |
473 | |
474 | // Parse float: [-+]? (\. [0-9]+ | [0-9]+ (\. [0-9]* )?) ([eE] [-+]? [0-9]+)? |
475 | S = Tail; |
476 | |
477 | // Handle cases when the number starts with '.' and hence needs at least one |
478 | // digit after dot (as opposed by number which has digits before the dot), but |
479 | // doesn't have one. |
480 | if (S.startswith(".") && |
481 | (S.equals(".") || |
482 | (S.size() > 1 && std::strchr("0123456789", S[1]) == nullptr))) |
483 | return false; |
484 | |
485 | if (S.startswith("E") || S.startswith("e")) |
486 | return false; |
487 | |
488 | enum ParseState { |
489 | Default, |
490 | FoundDot, |
491 | FoundExponent, |
492 | }; |
493 | ParseState State = Default; |
494 | |
495 | S = skipDigits(S); |
496 | |
497 | // Accept decimal integer. |
498 | if (S.empty()) |
499 | return true; |
500 | |
501 | if (S.front() == '.') { |
502 | State = FoundDot; |
503 | S = S.drop_front(); |
504 | } else if (S.front() == 'e' || S.front() == 'E') { |
505 | State = FoundExponent; |
506 | S = S.drop_front(); |
507 | } else { |
508 | return false; |
509 | } |
510 | |
511 | if (State == FoundDot) { |
512 | S = skipDigits(S); |
513 | if (S.empty()) |
514 | return true; |
515 | |
516 | if (S.front() == 'e' || S.front() == 'E') { |
517 | State = FoundExponent; |
518 | S = S.drop_front(); |
519 | } else { |
520 | return false; |
521 | } |
522 | } |
523 | |
524 | assert(State == FoundExponent && "Should have found exponent at this point.")((State == FoundExponent && "Should have found exponent at this point." ) ? static_cast<void> (0) : __assert_fail ("State == FoundExponent && \"Should have found exponent at this point.\"" , "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Support/YAMLTraits.h" , 524, __PRETTY_FUNCTION__)); |
525 | if (S.empty()) |
526 | return false; |
527 | |
528 | if (S.front() == '+' || S.front() == '-') { |
529 | S = S.drop_front(); |
530 | if (S.empty()) |
531 | return false; |
532 | } |
533 | |
534 | return skipDigits(S).empty(); |
535 | } |
536 | |
537 | inline bool isNull(StringRef S) { |
538 | return S.equals("null") || S.equals("Null") || S.equals("NULL") || |
539 | S.equals("~"); |
540 | } |
541 | |
542 | inline bool isBool(StringRef S) { |
543 | return S.equals("true") || S.equals("True") || S.equals("TRUE") || |
544 | S.equals("false") || S.equals("False") || S.equals("FALSE"); |
545 | } |
546 | |
547 | // 5.1. Character Set |
548 | // The allowed character range explicitly excludes the C0 control block #x0-#x1F |
549 | // (except for TAB #x9, LF #xA, and CR #xD which are allowed), DEL #x7F, the C1 |
550 | // control block #x80-#x9F (except for NEL #x85 which is allowed), the surrogate |
551 | // block #xD800-#xDFFF, #xFFFE, and #xFFFF. |
552 | inline QuotingType needsQuotes(StringRef S) { |
553 | if (S.empty()) |
554 | return QuotingType::Single; |
555 | if (isspace(S.front()) || isspace(S.back())) |
556 | return QuotingType::Single; |
557 | if (isNull(S)) |
558 | return QuotingType::Single; |
559 | if (isBool(S)) |
560 | return QuotingType::Single; |
561 | if (isNumeric(S)) |
562 | return QuotingType::Single; |
563 | |
564 | // 7.3.3 Plain Style |
565 | // Plain scalars must not begin with most indicators, as this would cause |
566 | // ambiguity with other YAML constructs. |
567 | static constexpr char Indicators[] = R"(-?:\,[]{}#&*!|>'"%@`)"; |
568 | if (S.find_first_of(Indicators) == 0) |
569 | return QuotingType::Single; |
570 | |
571 | QuotingType MaxQuotingNeeded = QuotingType::None; |
572 | for (unsigned char C : S) { |
573 | // Alphanum is safe. |
574 | if (isAlnum(C)) |
575 | continue; |
576 | |
577 | switch (C) { |
578 | // Safe scalar characters. |
579 | case '_': |
580 | case '-': |
581 | case '^': |
582 | case '.': |
583 | case ',': |
584 | case ' ': |
585 | // TAB (0x9) is allowed in unquoted strings. |
586 | case 0x9: |
587 | continue; |
588 | // LF(0xA) and CR(0xD) may delimit values and so require at least single |
589 | // quotes. |
590 | case 0xA: |
591 | case 0xD: |
592 | MaxQuotingNeeded = QuotingType::Single; |
593 | continue; |
594 | // DEL (0x7F) are excluded from the allowed character range. |
595 | case 0x7F: |
596 | return QuotingType::Double; |
597 | // Forward slash is allowed to be unquoted, but we quote it anyway. We have |
598 | // many tests that use FileCheck against YAML output, and this output often |
599 | // contains paths. If we quote backslashes but not forward slashes then |
600 | // paths will come out either quoted or unquoted depending on which platform |
601 | // the test is run on, making FileCheck comparisons difficult. |
602 | case '/': |
603 | default: { |
604 | // C0 control block (0x0 - 0x1F) is excluded from the allowed character |
605 | // range. |
606 | if (C <= 0x1F) |
607 | return QuotingType::Double; |
608 | |
609 | // Always double quote UTF-8. |
610 | if ((C & 0x80) != 0) |
611 | return QuotingType::Double; |
612 | |
613 | // The character is not safe, at least simple quoting needed. |
614 | MaxQuotingNeeded = QuotingType::Single; |
615 | } |
616 | } |
617 | } |
618 | |
619 | return MaxQuotingNeeded; |
620 | } |
621 | |
622 | template <typename T, typename Context> |
623 | struct missingTraits |
624 | : public std::integral_constant<bool, |
625 | !has_ScalarEnumerationTraits<T>::value && |
626 | !has_ScalarBitSetTraits<T>::value && |
627 | !has_ScalarTraits<T>::value && |
628 | !has_BlockScalarTraits<T>::value && |
629 | !has_MappingTraits<T, Context>::value && |
630 | !has_SequenceTraits<T>::value && |
631 | !has_CustomMappingTraits<T>::value && |
632 | !has_DocumentListTraits<T>::value> {}; |
633 | |
634 | template <typename T, typename Context> |
635 | struct validatedMappingTraits |
636 | : public std::integral_constant< |
637 | bool, has_MappingTraits<T, Context>::value && |
638 | has_MappingValidateTraits<T, Context>::value> {}; |
639 | |
640 | template <typename T, typename Context> |
641 | struct unvalidatedMappingTraits |
642 | : public std::integral_constant< |
643 | bool, has_MappingTraits<T, Context>::value && |
644 | !has_MappingValidateTraits<T, Context>::value> {}; |
645 | |
646 | // Base class for Input and Output. |
647 | class IO { |
648 | public: |
649 | IO(void *Ctxt = nullptr); |
650 | virtual ~IO(); |
651 | |
652 | virtual bool outputting() = 0; |
653 | |
654 | virtual unsigned beginSequence() = 0; |
655 | virtual bool preflightElement(unsigned, void *&) = 0; |
656 | virtual void postflightElement(void*) = 0; |
657 | virtual void endSequence() = 0; |
658 | virtual bool canElideEmptySequence() = 0; |
659 | |
660 | virtual unsigned beginFlowSequence() = 0; |
661 | virtual bool preflightFlowElement(unsigned, void *&) = 0; |
662 | virtual void postflightFlowElement(void*) = 0; |
663 | virtual void endFlowSequence() = 0; |
664 | |
665 | virtual bool mapTag(StringRef Tag, bool Default=false) = 0; |
666 | virtual void beginMapping() = 0; |
667 | virtual void endMapping() = 0; |
668 | virtual bool preflightKey(const char*, bool, bool, bool &, void *&) = 0; |
669 | virtual void postflightKey(void*) = 0; |
670 | virtual std::vector<StringRef> keys() = 0; |
671 | |
672 | virtual void beginFlowMapping() = 0; |
673 | virtual void endFlowMapping() = 0; |
674 | |
675 | virtual void beginEnumScalar() = 0; |
676 | virtual bool matchEnumScalar(const char*, bool) = 0; |
677 | virtual bool matchEnumFallback() = 0; |
678 | virtual void endEnumScalar() = 0; |
679 | |
680 | virtual bool beginBitSetScalar(bool &) = 0; |
681 | virtual bool bitSetMatch(const char*, bool) = 0; |
682 | virtual void endBitSetScalar() = 0; |
683 | |
684 | virtual void scalarString(StringRef &, QuotingType) = 0; |
685 | virtual void blockScalarString(StringRef &) = 0; |
686 | |
687 | virtual void setError(const Twine &) = 0; |
688 | |
689 | template <typename T> |
690 | void enumCase(T &Val, const char* Str, const T ConstVal) { |
691 | if ( matchEnumScalar(Str, outputting() && Val == ConstVal) ) { |
692 | Val = ConstVal; |
693 | } |
694 | } |
695 | |
696 | // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF |
697 | template <typename T> |
698 | void enumCase(T &Val, const char* Str, const uint32_t ConstVal) { |
699 | if ( matchEnumScalar(Str, outputting() && Val == static_cast<T>(ConstVal)) ) { |
700 | Val = ConstVal; |
701 | } |
702 | } |
703 | |
704 | template <typename FBT, typename T> |
705 | void enumFallback(T &Val) { |
706 | if (matchEnumFallback()) { |
707 | EmptyContext Context; |
708 | // FIXME: Force integral conversion to allow strong typedefs to convert. |
709 | FBT Res = static_cast<typename FBT::BaseType>(Val); |
710 | yamlize(*this, Res, true, Context); |
711 | Val = static_cast<T>(static_cast<typename FBT::BaseType>(Res)); |
712 | } |
713 | } |
714 | |
715 | template <typename T> |
716 | void bitSetCase(T &Val, const char* Str, const T ConstVal) { |
717 | if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) { |
718 | Val = static_cast<T>(Val | ConstVal); |
719 | } |
720 | } |
721 | |
722 | // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF |
723 | template <typename T> |
724 | void bitSetCase(T &Val, const char* Str, const uint32_t ConstVal) { |
725 | if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) { |
726 | Val = static_cast<T>(Val | ConstVal); |
727 | } |
728 | } |
729 | |
730 | template <typename T> |
731 | void maskedBitSetCase(T &Val, const char *Str, T ConstVal, T Mask) { |
732 | if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal)) |
733 | Val = Val | ConstVal; |
734 | } |
735 | |
736 | template <typename T> |
737 | void maskedBitSetCase(T &Val, const char *Str, uint32_t ConstVal, |
738 | uint32_t Mask) { |
739 | if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal)) |
740 | Val = Val | ConstVal; |
741 | } |
742 | |
743 | void *getContext(); |
744 | void setContext(void *); |
745 | |
746 | template <typename T> void mapRequired(const char *Key, T &Val) { |
747 | EmptyContext Ctx; |
748 | this->processKey(Key, Val, true, Ctx); |
749 | } |
750 | |
751 | template <typename T, typename Context> |
752 | void mapRequired(const char *Key, T &Val, Context &Ctx) { |
753 | this->processKey(Key, Val, true, Ctx); |
754 | } |
755 | |
756 | template <typename T> void mapOptional(const char *Key, T &Val) { |
757 | EmptyContext Ctx; |
758 | mapOptionalWithContext(Key, Val, Ctx); |
759 | } |
760 | |
761 | template <typename T> |
762 | void mapOptional(const char *Key, T &Val, const T &Default) { |
763 | EmptyContext Ctx; |
764 | mapOptionalWithContext(Key, Val, Default, Ctx); |
765 | } |
766 | |
767 | template <typename T, typename Context> |
768 | typename std::enable_if<has_SequenceTraits<T>::value, void>::type |
769 | mapOptionalWithContext(const char *Key, T &Val, Context &Ctx) { |
770 | // omit key/value instead of outputting empty sequence |
771 | if (this->canElideEmptySequence() && !(Val.begin() != Val.end())) |
772 | return; |
773 | this->processKey(Key, Val, false, Ctx); |
774 | } |
775 | |
776 | template <typename T, typename Context> |
777 | void mapOptionalWithContext(const char *Key, Optional<T> &Val, Context &Ctx) { |
778 | this->processKeyWithDefault(Key, Val, Optional<T>(), /*Required=*/false, |
779 | Ctx); |
780 | } |
781 | |
782 | template <typename T, typename Context> |
783 | typename std::enable_if<!has_SequenceTraits<T>::value, void>::type |
784 | mapOptionalWithContext(const char *Key, T &Val, Context &Ctx) { |
785 | this->processKey(Key, Val, false, Ctx); |
786 | } |
787 | |
788 | template <typename T, typename Context> |
789 | void mapOptionalWithContext(const char *Key, T &Val, const T &Default, |
790 | Context &Ctx) { |
791 | this->processKeyWithDefault(Key, Val, Default, false, Ctx); |
792 | } |
793 | |
794 | private: |
795 | template <typename T, typename Context> |
796 | void processKeyWithDefault(const char *Key, Optional<T> &Val, |
797 | const Optional<T> &DefaultValue, bool Required, |
798 | Context &Ctx) { |
799 | assert(DefaultValue.hasValue() == false &&((DefaultValue.hasValue() == false && "Optional<T> shouldn't have a value!" ) ? static_cast<void> (0) : __assert_fail ("DefaultValue.hasValue() == false && \"Optional<T> shouldn't have a value!\"" , "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Support/YAMLTraits.h" , 800, __PRETTY_FUNCTION__)) |
800 | "Optional<T> shouldn't have a value!")((DefaultValue.hasValue() == false && "Optional<T> shouldn't have a value!" ) ? static_cast<void> (0) : __assert_fail ("DefaultValue.hasValue() == false && \"Optional<T> shouldn't have a value!\"" , "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Support/YAMLTraits.h" , 800, __PRETTY_FUNCTION__)); |
801 | void *SaveInfo; |
802 | bool UseDefault = true; |
803 | const bool sameAsDefault = outputting() && !Val.hasValue(); |
804 | if (!outputting() && !Val.hasValue()) |
805 | Val = T(); |
806 | if (Val.hasValue() && |
807 | this->preflightKey(Key, Required, sameAsDefault, UseDefault, |
808 | SaveInfo)) { |
809 | yamlize(*this, Val.getValue(), Required, Ctx); |
810 | this->postflightKey(SaveInfo); |
811 | } else { |
812 | if (UseDefault) |
813 | Val = DefaultValue; |
814 | } |
815 | } |
816 | |
817 | template <typename T, typename Context> |
818 | void processKeyWithDefault(const char *Key, T &Val, const T &DefaultValue, |
819 | bool Required, Context &Ctx) { |
820 | void *SaveInfo; |
821 | bool UseDefault; |
822 | const bool sameAsDefault = outputting() && Val == DefaultValue; |
823 | if ( this->preflightKey(Key, Required, sameAsDefault, UseDefault, |
824 | SaveInfo) ) { |
825 | yamlize(*this, Val, Required, Ctx); |
826 | this->postflightKey(SaveInfo); |
827 | } |
828 | else { |
829 | if ( UseDefault ) |
830 | Val = DefaultValue; |
831 | } |
832 | } |
833 | |
834 | template <typename T, typename Context> |
835 | void processKey(const char *Key, T &Val, bool Required, Context &Ctx) { |
836 | void *SaveInfo; |
837 | bool UseDefault; |
838 | if ( this->preflightKey(Key, Required, false, UseDefault, SaveInfo) ) { |
839 | yamlize(*this, Val, Required, Ctx); |
840 | this->postflightKey(SaveInfo); |
841 | } |
842 | } |
843 | |
844 | private: |
845 | void *Ctxt; |
846 | }; |
847 | |
848 | namespace detail { |
849 | |
850 | template <typename T, typename Context> |
851 | void doMapping(IO &io, T &Val, Context &Ctx) { |
852 | MappingContextTraits<T, Context>::mapping(io, Val, Ctx); |
853 | } |
854 | |
855 | template <typename T> void doMapping(IO &io, T &Val, EmptyContext &Ctx) { |
856 | MappingTraits<T>::mapping(io, Val); |
857 | } |
858 | |
859 | } // end namespace detail |
860 | |
861 | template <typename T> |
862 | typename std::enable_if<has_ScalarEnumerationTraits<T>::value, void>::type |
863 | yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) { |
864 | io.beginEnumScalar(); |
865 | ScalarEnumerationTraits<T>::enumeration(io, Val); |
866 | io.endEnumScalar(); |
867 | } |
868 | |
869 | template <typename T> |
870 | typename std::enable_if<has_ScalarBitSetTraits<T>::value, void>::type |
871 | yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) { |
872 | bool DoClear; |
873 | if ( io.beginBitSetScalar(DoClear) ) { |
874 | if ( DoClear ) |
875 | Val = static_cast<T>(0); |
876 | ScalarBitSetTraits<T>::bitset(io, Val); |
877 | io.endBitSetScalar(); |
878 | } |
879 | } |
880 | |
881 | template <typename T> |
882 | typename std::enable_if<has_ScalarTraits<T>::value, void>::type |
883 | yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) { |
884 | if ( io.outputting() ) { |
885 | std::string Storage; |
886 | raw_string_ostream Buffer(Storage); |
887 | ScalarTraits<T>::output(Val, io.getContext(), Buffer); |
888 | StringRef Str = Buffer.str(); |
889 | io.scalarString(Str, ScalarTraits<T>::mustQuote(Str)); |
890 | } |
891 | else { |
892 | StringRef Str; |
893 | io.scalarString(Str, ScalarTraits<T>::mustQuote(Str)); |
894 | StringRef Result = ScalarTraits<T>::input(Str, io.getContext(), Val); |
895 | if ( !Result.empty() ) { |
896 | io.setError(Twine(Result)); |
897 | } |
898 | } |
899 | } |
900 | |
901 | template <typename T> |
902 | typename std::enable_if<has_BlockScalarTraits<T>::value, void>::type |
903 | yamlize(IO &YamlIO, T &Val, bool, EmptyContext &Ctx) { |
904 | if (YamlIO.outputting()) { |
905 | std::string Storage; |
906 | raw_string_ostream Buffer(Storage); |
907 | BlockScalarTraits<T>::output(Val, YamlIO.getContext(), Buffer); |
908 | StringRef Str = Buffer.str(); |
909 | YamlIO.blockScalarString(Str); |
910 | } else { |
911 | StringRef Str; |
912 | YamlIO.blockScalarString(Str); |
913 | StringRef Result = |
914 | BlockScalarTraits<T>::input(Str, YamlIO.getContext(), Val); |
915 | if (!Result.empty()) |
916 | YamlIO.setError(Twine(Result)); |
917 | } |
918 | } |
919 | |
920 | template <typename T, typename Context> |
921 | typename std::enable_if<validatedMappingTraits<T, Context>::value, void>::type |
922 | yamlize(IO &io, T &Val, bool, Context &Ctx) { |
923 | if (has_FlowTraits<MappingTraits<T>>::value) |
924 | io.beginFlowMapping(); |
925 | else |
926 | io.beginMapping(); |
927 | if (io.outputting()) { |
928 | StringRef Err = MappingTraits<T>::validate(io, Val); |
929 | if (!Err.empty()) { |
930 | errs() << Err << "\n"; |
931 | assert(Err.empty() && "invalid struct trying to be written as yaml")((Err.empty() && "invalid struct trying to be written as yaml" ) ? static_cast<void> (0) : __assert_fail ("Err.empty() && \"invalid struct trying to be written as yaml\"" , "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Support/YAMLTraits.h" , 931, __PRETTY_FUNCTION__)); |
932 | } |
933 | } |
934 | detail::doMapping(io, Val, Ctx); |
935 | if (!io.outputting()) { |
936 | StringRef Err = MappingTraits<T>::validate(io, Val); |
937 | if (!Err.empty()) |
938 | io.setError(Err); |
939 | } |
940 | if (has_FlowTraits<MappingTraits<T>>::value) |
941 | io.endFlowMapping(); |
942 | else |
943 | io.endMapping(); |
944 | } |
945 | |
946 | template <typename T, typename Context> |
947 | typename std::enable_if<unvalidatedMappingTraits<T, Context>::value, void>::type |
948 | yamlize(IO &io, T &Val, bool, Context &Ctx) { |
949 | if (has_FlowTraits<MappingTraits<T>>::value) { |
950 | io.beginFlowMapping(); |
951 | detail::doMapping(io, Val, Ctx); |
952 | io.endFlowMapping(); |
953 | } else { |
954 | io.beginMapping(); |
955 | detail::doMapping(io, Val, Ctx); |
956 | io.endMapping(); |
957 | } |
958 | } |
959 | |
960 | template <typename T> |
961 | typename std::enable_if<has_CustomMappingTraits<T>::value, void>::type |
962 | yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) { |
963 | if ( io.outputting() ) { |
964 | io.beginMapping(); |
965 | CustomMappingTraits<T>::output(io, Val); |
966 | io.endMapping(); |
967 | } else { |
968 | io.beginMapping(); |
969 | for (StringRef key : io.keys()) |
970 | CustomMappingTraits<T>::inputOne(io, key, Val); |
971 | io.endMapping(); |
972 | } |
973 | } |
974 | |
975 | template <typename T> |
976 | typename std::enable_if<missingTraits<T, EmptyContext>::value, void>::type |
977 | yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) { |
978 | char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)]; |
979 | } |
980 | |
981 | template <typename T, typename Context> |
982 | typename std::enable_if<has_SequenceTraits<T>::value, void>::type |
983 | yamlize(IO &io, T &Seq, bool, Context &Ctx) { |
984 | if ( has_FlowTraits< SequenceTraits<T>>::value ) { |
985 | unsigned incnt = io.beginFlowSequence(); |
986 | unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt; |
987 | for(unsigned i=0; i < count; ++i) { |
988 | void *SaveInfo; |
989 | if ( io.preflightFlowElement(i, SaveInfo) ) { |
990 | yamlize(io, SequenceTraits<T>::element(io, Seq, i), true, Ctx); |
991 | io.postflightFlowElement(SaveInfo); |
992 | } |
993 | } |
994 | io.endFlowSequence(); |
995 | } |
996 | else { |
997 | unsigned incnt = io.beginSequence(); |
998 | unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt; |
999 | for(unsigned i=0; i < count; ++i) { |
1000 | void *SaveInfo; |
1001 | if ( io.preflightElement(i, SaveInfo) ) { |
1002 | yamlize(io, SequenceTraits<T>::element(io, Seq, i), true, Ctx); |
1003 | io.postflightElement(SaveInfo); |
1004 | } |
1005 | } |
1006 | io.endSequence(); |
1007 | } |
1008 | } |
1009 | |
1010 | template<> |
1011 | struct ScalarTraits<bool> { |
1012 | static void output(const bool &, void* , raw_ostream &); |
1013 | static StringRef input(StringRef, void *, bool &); |
1014 | static QuotingType mustQuote(StringRef) { return QuotingType::None; } |
1015 | }; |
1016 | |
1017 | template<> |
1018 | struct ScalarTraits<StringRef> { |
1019 | static void output(const StringRef &, void *, raw_ostream &); |
1020 | static StringRef input(StringRef, void *, StringRef &); |
1021 | static QuotingType mustQuote(StringRef S) { return needsQuotes(S); } |
1022 | }; |
1023 | |
1024 | template<> |
1025 | struct ScalarTraits<std::string> { |
1026 | static void output(const std::string &, void *, raw_ostream &); |
1027 | static StringRef input(StringRef, void *, std::string &); |
1028 | static QuotingType mustQuote(StringRef S) { return needsQuotes(S); } |
1029 | }; |
1030 | |
1031 | template<> |
1032 | struct ScalarTraits<uint8_t> { |
1033 | static void output(const uint8_t &, void *, raw_ostream &); |
1034 | static StringRef input(StringRef, void *, uint8_t &); |
1035 | static QuotingType mustQuote(StringRef) { return QuotingType::None; } |
1036 | }; |
1037 | |
1038 | template<> |
1039 | struct ScalarTraits<uint16_t> { |
1040 | static void output(const uint16_t &, void *, raw_ostream &); |
1041 | static StringRef input(StringRef, void *, uint16_t &); |
1042 | static QuotingType mustQuote(StringRef) { return QuotingType::None; } |
1043 | }; |
1044 | |
1045 | template<> |
1046 | struct ScalarTraits<uint32_t> { |
1047 | static void output(const uint32_t &, void *, raw_ostream &); |
1048 | static StringRef input(StringRef, void *, uint32_t &); |
1049 | static QuotingType mustQuote(StringRef) { return QuotingType::None; } |
1050 | }; |
1051 | |
1052 | template<> |
1053 | struct ScalarTraits<uint64_t> { |
1054 | static void output(const uint64_t &, void *, raw_ostream &); |
1055 | static StringRef input(StringRef, void *, uint64_t &); |
1056 | static QuotingType mustQuote(StringRef) { return QuotingType::None; } |
1057 | }; |
1058 | |
1059 | template<> |
1060 | struct ScalarTraits<int8_t> { |
1061 | static void output(const int8_t &, void *, raw_ostream &); |
1062 | static StringRef input(StringRef, void *, int8_t &); |
1063 | static QuotingType mustQuote(StringRef) { return QuotingType::None; } |
1064 | }; |
1065 | |
1066 | template<> |
1067 | struct ScalarTraits<int16_t> { |
1068 | static void output(const int16_t &, void *, raw_ostream &); |
1069 | static StringRef input(StringRef, void *, int16_t &); |
1070 | static QuotingType mustQuote(StringRef) { return QuotingType::None; } |
1071 | }; |
1072 | |
1073 | template<> |
1074 | struct ScalarTraits<int32_t> { |
1075 | static void output(const int32_t &, void *, raw_ostream &); |
1076 | static StringRef input(StringRef, void *, int32_t &); |
1077 | static QuotingType mustQuote(StringRef) { return QuotingType::None; } |
1078 | }; |
1079 | |
1080 | template<> |
1081 | struct ScalarTraits<int64_t> { |
1082 | static void output(const int64_t &, void *, raw_ostream &); |
1083 | static StringRef input(StringRef, void *, int64_t &); |
1084 | static QuotingType mustQuote(StringRef) { return QuotingType::None; } |
1085 | }; |
1086 | |
1087 | template<> |
1088 | struct ScalarTraits<float> { |
1089 | static void output(const float &, void *, raw_ostream &); |
1090 | static StringRef input(StringRef, void *, float &); |
1091 | static QuotingType mustQuote(StringRef) { return QuotingType::None; } |
1092 | }; |
1093 | |
1094 | template<> |
1095 | struct ScalarTraits<double> { |
1096 | static void output(const double &, void *, raw_ostream &); |
1097 | static StringRef input(StringRef, void *, double &); |
1098 | static QuotingType mustQuote(StringRef) { return QuotingType::None; } |
1099 | }; |
1100 | |
1101 | // For endian types, we just use the existing ScalarTraits for the underlying |
1102 | // type. This way endian aware types are supported whenever a ScalarTraits |
1103 | // is defined for the underlying type. |
1104 | template <typename value_type, support::endianness endian, size_t alignment> |
1105 | struct ScalarTraits<support::detail::packed_endian_specific_integral< |
1106 | value_type, endian, alignment>> { |
1107 | using endian_type = |
1108 | support::detail::packed_endian_specific_integral<value_type, endian, |
1109 | alignment>; |
1110 | |
1111 | static void output(const endian_type &E, void *Ctx, raw_ostream &Stream) { |
1112 | ScalarTraits<value_type>::output(static_cast<value_type>(E), Ctx, Stream); |
1113 | } |
1114 | |
1115 | static StringRef input(StringRef Str, void *Ctx, endian_type &E) { |
1116 | value_type V; |
1117 | auto R = ScalarTraits<value_type>::input(Str, Ctx, V); |
1118 | E = static_cast<endian_type>(V); |
1119 | return R; |
1120 | } |
1121 | |
1122 | static QuotingType mustQuote(StringRef Str) { |
1123 | return ScalarTraits<value_type>::mustQuote(Str); |
1124 | } |
1125 | }; |
1126 | |
1127 | // Utility for use within MappingTraits<>::mapping() method |
1128 | // to [de]normalize an object for use with YAML conversion. |
1129 | template <typename TNorm, typename TFinal> |
1130 | struct MappingNormalization { |
1131 | MappingNormalization(IO &i_o, TFinal &Obj) |
1132 | : io(i_o), BufPtr(nullptr), Result(Obj) { |
1133 | if ( io.outputting() ) { |
1134 | BufPtr = new (&Buffer) TNorm(io, Obj); |
1135 | } |
1136 | else { |
1137 | BufPtr = new (&Buffer) TNorm(io); |
1138 | } |
1139 | } |
1140 | |
1141 | ~MappingNormalization() { |
1142 | if ( ! io.outputting() ) { |
1143 | Result = BufPtr->denormalize(io); |
1144 | } |
1145 | BufPtr->~TNorm(); |
1146 | } |
1147 | |
1148 | TNorm* operator->() { return BufPtr; } |
1149 | |
1150 | private: |
1151 | using Storage = AlignedCharArrayUnion<TNorm>; |
1152 | |
1153 | Storage Buffer; |
1154 | IO &io; |
1155 | TNorm *BufPtr; |
1156 | TFinal &Result; |
1157 | }; |
1158 | |
1159 | // Utility for use within MappingTraits<>::mapping() method |
1160 | // to [de]normalize an object for use with YAML conversion. |
1161 | template <typename TNorm, typename TFinal> |
1162 | struct MappingNormalizationHeap { |
1163 | MappingNormalizationHeap(IO &i_o, TFinal &Obj, BumpPtrAllocator *allocator) |
1164 | : io(i_o), Result(Obj) { |
1165 | if ( io.outputting() ) { |
1166 | BufPtr = new (&Buffer) TNorm(io, Obj); |
1167 | } |
1168 | else if (allocator) { |
1169 | BufPtr = allocator->Allocate<TNorm>(); |
1170 | new (BufPtr) TNorm(io); |
1171 | } else { |
1172 | BufPtr = new TNorm(io); |
1173 | } |
1174 | } |
1175 | |
1176 | ~MappingNormalizationHeap() { |
1177 | if ( io.outputting() ) { |
1178 | BufPtr->~TNorm(); |
1179 | } |
1180 | else { |
1181 | Result = BufPtr->denormalize(io); |
1182 | } |
1183 | } |
1184 | |
1185 | TNorm* operator->() { return BufPtr; } |
1186 | |
1187 | private: |
1188 | using Storage = AlignedCharArrayUnion<TNorm>; |
1189 | |
1190 | Storage Buffer; |
1191 | IO &io; |
1192 | TNorm *BufPtr = nullptr; |
1193 | TFinal &Result; |
1194 | }; |
1195 | |
1196 | /// |
1197 | /// The Input class is used to parse a yaml document into in-memory structs |
1198 | /// and vectors. |
1199 | /// |
1200 | /// It works by using YAMLParser to do a syntax parse of the entire yaml |
1201 | /// document, then the Input class builds a graph of HNodes which wraps |
1202 | /// each yaml Node. The extra layer is buffering. The low level yaml |
1203 | /// parser only lets you look at each node once. The buffering layer lets |
1204 | /// you search and interate multiple times. This is necessary because |
1205 | /// the mapRequired() method calls may not be in the same order |
1206 | /// as the keys in the document. |
1207 | /// |
1208 | class Input : public IO { |
1209 | public: |
1210 | // Construct a yaml Input object from a StringRef and optional |
1211 | // user-data. The DiagHandler can be specified to provide |
1212 | // alternative error reporting. |
1213 | Input(StringRef InputContent, |
1214 | void *Ctxt = nullptr, |
1215 | SourceMgr::DiagHandlerTy DiagHandler = nullptr, |
1216 | void *DiagHandlerCtxt = nullptr); |
1217 | Input(MemoryBufferRef Input, |
1218 | void *Ctxt = nullptr, |
1219 | SourceMgr::DiagHandlerTy DiagHandler = nullptr, |
1220 | void *DiagHandlerCtxt = nullptr); |
1221 | ~Input() override; |
1222 | |
1223 | // Check if there was an syntax or semantic error during parsing. |
1224 | std::error_code error(); |
1225 | |
1226 | private: |
1227 | bool outputting() override; |
1228 | bool mapTag(StringRef, bool) override; |
1229 | void beginMapping() override; |
1230 | void endMapping() override; |
1231 | bool preflightKey(const char *, bool, bool, bool &, void *&) override; |
1232 | void postflightKey(void *) override; |
1233 | std::vector<StringRef> keys() override; |
1234 | void beginFlowMapping() override; |
1235 | void endFlowMapping() override; |
1236 | unsigned beginSequence() override; |
1237 | void endSequence() override; |
1238 | bool preflightElement(unsigned index, void *&) override; |
1239 | void postflightElement(void *) override; |
1240 | unsigned beginFlowSequence() override; |
1241 | bool preflightFlowElement(unsigned , void *&) override; |
1242 | void postflightFlowElement(void *) override; |
1243 | void endFlowSequence() override; |
1244 | void beginEnumScalar() override; |
1245 | bool matchEnumScalar(const char*, bool) override; |
1246 | bool matchEnumFallback() override; |
1247 | void endEnumScalar() override; |
1248 | bool beginBitSetScalar(bool &) override; |
1249 | bool bitSetMatch(const char *, bool ) override; |
1250 | void endBitSetScalar() override; |
1251 | void scalarString(StringRef &, QuotingType) override; |
1252 | void blockScalarString(StringRef &) override; |
1253 | void setError(const Twine &message) override; |
1254 | bool canElideEmptySequence() override; |
1255 | |
1256 | class HNode { |
1257 | virtual void anchor(); |
1258 | |
1259 | public: |
1260 | HNode(Node *n) : _node(n) { } |
1261 | virtual ~HNode() = default; |
1262 | |
1263 | static bool classof(const HNode *) { return true; } |
1264 | |
1265 | Node *_node; |
1266 | }; |
1267 | |
1268 | class EmptyHNode : public HNode { |
1269 | void anchor() override; |
1270 | |
1271 | public: |
1272 | EmptyHNode(Node *n) : HNode(n) { } |
1273 | |
1274 | static bool classof(const HNode *n) { return NullNode::classof(n->_node); } |
1275 | |
1276 | static bool classof(const EmptyHNode *) { return true; } |
1277 | }; |
1278 | |
1279 | class ScalarHNode : public HNode { |
1280 | void anchor() override; |
1281 | |
1282 | public: |
1283 | ScalarHNode(Node *n, StringRef s) : HNode(n), _value(s) { } |
1284 | |
1285 | StringRef value() const { return _value; } |
1286 | |
1287 | static bool classof(const HNode *n) { |
1288 | return ScalarNode::classof(n->_node) || |
1289 | BlockScalarNode::classof(n->_node); |
1290 | } |
1291 | |
1292 | static bool classof(const ScalarHNode *) { return true; } |
1293 | |
1294 | protected: |
1295 | StringRef _value; |
1296 | }; |
1297 | |
1298 | class MapHNode : public HNode { |
1299 | void anchor() override; |
1300 | |
1301 | public: |
1302 | MapHNode(Node *n) : HNode(n) { } |
1303 | |
1304 | static bool classof(const HNode *n) { |
1305 | return MappingNode::classof(n->_node); |
1306 | } |
1307 | |
1308 | static bool classof(const MapHNode *) { return true; } |
1309 | |
1310 | using NameToNode = StringMap<std::unique_ptr<HNode>>; |
1311 | |
1312 | NameToNode Mapping; |
1313 | SmallVector<std::string, 6> ValidKeys; |
1314 | }; |
1315 | |
1316 | class SequenceHNode : public HNode { |
1317 | void anchor() override; |
1318 | |
1319 | public: |
1320 | SequenceHNode(Node *n) : HNode(n) { } |
1321 | |
1322 | static bool classof(const HNode *n) { |
1323 | return SequenceNode::classof(n->_node); |
1324 | } |
1325 | |
1326 | static bool classof(const SequenceHNode *) { return true; } |
1327 | |
1328 | std::vector<std::unique_ptr<HNode>> Entries; |
1329 | }; |
1330 | |
1331 | std::unique_ptr<Input::HNode> createHNodes(Node *node); |
1332 | void setError(HNode *hnode, const Twine &message); |
1333 | void setError(Node *node, const Twine &message); |
1334 | |
1335 | public: |
1336 | // These are only used by operator>>. They could be private |
1337 | // if those templated things could be made friends. |
1338 | bool setCurrentDocument(); |
1339 | bool nextDocument(); |
1340 | |
1341 | /// Returns the current node that's being parsed by the YAML Parser. |
1342 | const Node *getCurrentNode() const; |
1343 | |
1344 | private: |
1345 | SourceMgr SrcMgr; // must be before Strm |
1346 | std::unique_ptr<llvm::yaml::Stream> Strm; |
1347 | std::unique_ptr<HNode> TopNode; |
1348 | std::error_code EC; |
1349 | BumpPtrAllocator StringAllocator; |
1350 | document_iterator DocIterator; |
1351 | std::vector<bool> BitValuesUsed; |
1352 | HNode *CurrentNode = nullptr; |
1353 | bool ScalarMatchFound; |
1354 | }; |
1355 | |
1356 | /// |
1357 | /// The Output class is used to generate a yaml document from in-memory structs |
1358 | /// and vectors. |
1359 | /// |
1360 | class Output : public IO { |
1361 | public: |
1362 | Output(raw_ostream &, void *Ctxt = nullptr, int WrapColumn = 70); |
1363 | ~Output() override; |
1364 | |
1365 | /// Set whether or not to output optional values which are equal |
1366 | /// to the default value. By default, when outputting if you attempt |
1367 | /// to write a value that is equal to the default, the value gets ignored. |
1368 | /// Sometimes, it is useful to be able to see these in the resulting YAML |
1369 | /// anyway. |
1370 | void setWriteDefaultValues(bool Write) { WriteDefaultValues = Write; } |
1371 | |
1372 | bool outputting() override; |
1373 | bool mapTag(StringRef, bool) override; |
1374 | void beginMapping() override; |
1375 | void endMapping() override; |
1376 | bool preflightKey(const char *key, bool, bool, bool &, void *&) override; |
1377 | void postflightKey(void *) override; |
1378 | std::vector<StringRef> keys() override; |
1379 | void beginFlowMapping() override; |
1380 | void endFlowMapping() override; |
1381 | unsigned beginSequence() override; |
1382 | void endSequence() override; |
1383 | bool preflightElement(unsigned, void *&) override; |
1384 | void postflightElement(void *) override; |
1385 | unsigned beginFlowSequence() override; |
1386 | bool preflightFlowElement(unsigned, void *&) override; |
1387 | void postflightFlowElement(void *) override; |
1388 | void endFlowSequence() override; |
1389 | void beginEnumScalar() override; |
1390 | bool matchEnumScalar(const char*, bool) override; |
1391 | bool matchEnumFallback() override; |
1392 | void endEnumScalar() override; |
1393 | bool beginBitSetScalar(bool &) override; |
1394 | bool bitSetMatch(const char *, bool ) override; |
1395 | void endBitSetScalar() override; |
1396 | void scalarString(StringRef &, QuotingType) override; |
1397 | void blockScalarString(StringRef &) override; |
1398 | void setError(const Twine &message) override; |
1399 | bool canElideEmptySequence() override; |
1400 | |
1401 | // These are only used by operator<<. They could be private |
1402 | // if that templated operator could be made a friend. |
1403 | void beginDocuments(); |
1404 | bool preflightDocument(unsigned); |
1405 | void postflightDocument(); |
1406 | void endDocuments(); |
1407 | |
1408 | private: |
1409 | void output(StringRef s); |
1410 | void outputUpToEndOfLine(StringRef s); |
1411 | void newLineCheck(); |
1412 | void outputNewLine(); |
1413 | void paddedKey(StringRef key); |
1414 | void flowKey(StringRef Key); |
1415 | |
1416 | enum InState { |
1417 | inSeq, |
1418 | inFlowSeq, |
1419 | inMapFirstKey, |
1420 | inMapOtherKey, |
1421 | inFlowMapFirstKey, |
1422 | inFlowMapOtherKey |
1423 | }; |
1424 | |
1425 | raw_ostream &Out; |
1426 | int WrapColumn; |
1427 | SmallVector<InState, 8> StateStack; |
1428 | int Column = 0; |
1429 | int ColumnAtFlowStart = 0; |
1430 | int ColumnAtMapFlowStart = 0; |
1431 | bool NeedBitValueComma = false; |
1432 | bool NeedFlowSequenceComma = false; |
1433 | bool EnumerationMatchFound = false; |
1434 | bool NeedsNewLine = false; |
1435 | bool WriteDefaultValues = false; |
1436 | }; |
1437 | |
1438 | /// YAML I/O does conversion based on types. But often native data types |
1439 | /// are just a typedef of built in intergral types (e.g. int). But the C++ |
1440 | /// type matching system sees through the typedef and all the typedefed types |
1441 | /// look like a built in type. This will cause the generic YAML I/O conversion |
1442 | /// to be used. To provide better control over the YAML conversion, you can |
1443 | /// use this macro instead of typedef. It will create a class with one field |
1444 | /// and automatic conversion operators to and from the base type. |
1445 | /// Based on BOOST_STRONG_TYPEDEF |
1446 | #define LLVM_YAML_STRONG_TYPEDEF(_base, _type)struct _type { _type() = default; _type(const _base v) : value (v) {} _type(const _type &v) = default; _type &operator =(const _type &rhs) = default; _type &operator=(const _base &rhs) { value = rhs; return *this; } operator const _base & () const { return value; } bool operator==(const _type &rhs) const { return value == rhs.value; } bool operator ==(const _base &rhs) const { return value == rhs; } bool operator <(const _type &rhs) const { return value < rhs.value ; } _base value; using BaseType = _base; }; \ |
1447 | struct _type { \ |
1448 | _type() = default; \ |
1449 | _type(const _base v) : value(v) {} \ |
1450 | _type(const _type &v) = default; \ |
1451 | _type &operator=(const _type &rhs) = default; \ |
1452 | _type &operator=(const _base &rhs) { value = rhs; return *this; } \ |
1453 | operator const _base & () const { return value; } \ |
1454 | bool operator==(const _type &rhs) const { return value == rhs.value; } \ |
1455 | bool operator==(const _base &rhs) const { return value == rhs; } \ |
1456 | bool operator<(const _type &rhs) const { return value < rhs.value; } \ |
1457 | _base value; \ |
1458 | using BaseType = _base; \ |
1459 | }; |
1460 | |
1461 | /// |
1462 | /// Use these types instead of uintXX_t in any mapping to have |
1463 | /// its yaml output formatted as hexadecimal. |
1464 | /// |
1465 | LLVM_YAML_STRONG_TYPEDEF(uint8_t, Hex8)struct Hex8 { Hex8() = default; Hex8(const uint8_t v) : value (v) {} Hex8(const Hex8 &v) = default; Hex8 &operator= (const Hex8 &rhs) = default; Hex8 &operator=(const uint8_t &rhs) { value = rhs; return *this; } operator const uint8_t & () const { return value; } bool operator==(const Hex8 & rhs) const { return value == rhs.value; } bool operator==(const uint8_t &rhs) const { return value == rhs; } bool operator <(const Hex8 &rhs) const { return value < rhs.value ; } uint8_t value; using BaseType = uint8_t; }; |
1466 | LLVM_YAML_STRONG_TYPEDEF(uint16_t, Hex16)struct Hex16 { Hex16() = default; Hex16(const uint16_t v) : value (v) {} Hex16(const Hex16 &v) = default; Hex16 &operator =(const Hex16 &rhs) = default; Hex16 &operator=(const uint16_t &rhs) { value = rhs; return *this; } operator const uint16_t & () const { return value; } bool operator==(const Hex16 &rhs) const { return value == rhs.value; } bool operator ==(const uint16_t &rhs) const { return value == rhs; } bool operator<(const Hex16 &rhs) const { return value < rhs.value; } uint16_t value; using BaseType = uint16_t; }; |
1467 | LLVM_YAML_STRONG_TYPEDEF(uint32_t, Hex32)struct Hex32 { Hex32() = default; Hex32(const uint32_t v) : value (v) {} Hex32(const Hex32 &v) = default; Hex32 &operator =(const Hex32 &rhs) = default; Hex32 &operator=(const uint32_t &rhs) { value = rhs; return *this; } operator const uint32_t & () const { return value; } bool operator==(const Hex32 &rhs) const { return value == rhs.value; } bool operator ==(const uint32_t &rhs) const { return value == rhs; } bool operator<(const Hex32 &rhs) const { return value < rhs.value; } uint32_t value; using BaseType = uint32_t; }; |
1468 | LLVM_YAML_STRONG_TYPEDEF(uint64_t, Hex64)struct Hex64 { Hex64() = default; Hex64(const uint64_t v) : value (v) {} Hex64(const Hex64 &v) = default; Hex64 &operator =(const Hex64 &rhs) = default; Hex64 &operator=(const uint64_t &rhs) { value = rhs; return *this; } operator const uint64_t & () const { return value; } bool operator==(const Hex64 &rhs) const { return value == rhs.value; } bool operator ==(const uint64_t &rhs) const { return value == rhs; } bool operator<(const Hex64 &rhs) const { return value < rhs.value; } uint64_t value; using BaseType = uint64_t; }; |
1469 | |
1470 | template<> |
1471 | struct ScalarTraits<Hex8> { |
1472 | static void output(const Hex8 &, void *, raw_ostream &); |
1473 | static StringRef input(StringRef, void *, Hex8 &); |
1474 | static QuotingType mustQuote(StringRef) { return QuotingType::None; } |
1475 | }; |
1476 | |
1477 | template<> |
1478 | struct ScalarTraits<Hex16> { |
1479 | static void output(const Hex16 &, void *, raw_ostream &); |
1480 | static StringRef input(StringRef, void *, Hex16 &); |
1481 | static QuotingType mustQuote(StringRef) { return QuotingType::None; } |
1482 | }; |
1483 | |
1484 | template<> |
1485 | struct ScalarTraits<Hex32> { |
1486 | static void output(const Hex32 &, void *, raw_ostream &); |
1487 | static StringRef input(StringRef, void *, Hex32 &); |
1488 | static QuotingType mustQuote(StringRef) { return QuotingType::None; } |
1489 | }; |
1490 | |
1491 | template<> |
1492 | struct ScalarTraits<Hex64> { |
1493 | static void output(const Hex64 &, void *, raw_ostream &); |
1494 | static StringRef input(StringRef, void *, Hex64 &); |
1495 | static QuotingType mustQuote(StringRef) { return QuotingType::None; } |
1496 | }; |
1497 | |
1498 | // Define non-member operator>> so that Input can stream in a document list. |
1499 | template <typename T> |
1500 | inline |
1501 | typename std::enable_if<has_DocumentListTraits<T>::value, Input &>::type |
1502 | operator>>(Input &yin, T &docList) { |
1503 | int i = 0; |
1504 | EmptyContext Ctx; |
1505 | while ( yin.setCurrentDocument() ) { |
1506 | yamlize(yin, DocumentListTraits<T>::element(yin, docList, i), true, Ctx); |
1507 | if ( yin.error() ) |
1508 | return yin; |
1509 | yin.nextDocument(); |
1510 | ++i; |
1511 | } |
1512 | return yin; |
1513 | } |
1514 | |
1515 | // Define non-member operator>> so that Input can stream in a map as a document. |
1516 | template <typename T> |
1517 | inline typename std::enable_if<has_MappingTraits<T, EmptyContext>::value, |
1518 | Input &>::type |
1519 | operator>>(Input &yin, T &docMap) { |
1520 | EmptyContext Ctx; |
1521 | yin.setCurrentDocument(); |
1522 | yamlize(yin, docMap, true, Ctx); |
1523 | return yin; |
1524 | } |
1525 | |
1526 | // Define non-member operator>> so that Input can stream in a sequence as |
1527 | // a document. |
1528 | template <typename T> |
1529 | inline |
1530 | typename std::enable_if<has_SequenceTraits<T>::value, Input &>::type |
1531 | operator>>(Input &yin, T &docSeq) { |
1532 | EmptyContext Ctx; |
1533 | if (yin.setCurrentDocument()) |
1534 | yamlize(yin, docSeq, true, Ctx); |
1535 | return yin; |
1536 | } |
1537 | |
1538 | // Define non-member operator>> so that Input can stream in a block scalar. |
1539 | template <typename T> |
1540 | inline |
1541 | typename std::enable_if<has_BlockScalarTraits<T>::value, Input &>::type |
1542 | operator>>(Input &In, T &Val) { |
1543 | EmptyContext Ctx; |
1544 | if (In.setCurrentDocument()) |
1545 | yamlize(In, Val, true, Ctx); |
1546 | return In; |
1547 | } |
1548 | |
1549 | // Define non-member operator>> so that Input can stream in a string map. |
1550 | template <typename T> |
1551 | inline |
1552 | typename std::enable_if<has_CustomMappingTraits<T>::value, Input &>::type |
1553 | operator>>(Input &In, T &Val) { |
1554 | EmptyContext Ctx; |
1555 | if (In.setCurrentDocument()) |
1556 | yamlize(In, Val, true, Ctx); |
1557 | return In; |
1558 | } |
1559 | |
1560 | // Provide better error message about types missing a trait specialization |
1561 | template <typename T> |
1562 | inline typename std::enable_if<missingTraits<T, EmptyContext>::value, |
1563 | Input &>::type |
1564 | operator>>(Input &yin, T &docSeq) { |
1565 | char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)]; |
1566 | return yin; |
1567 | } |
1568 | |
1569 | // Define non-member operator<< so that Output can stream out document list. |
1570 | template <typename T> |
1571 | inline |
1572 | typename std::enable_if<has_DocumentListTraits<T>::value, Output &>::type |
1573 | operator<<(Output &yout, T &docList) { |
1574 | EmptyContext Ctx; |
1575 | yout.beginDocuments(); |
1576 | const size_t count = DocumentListTraits<T>::size(yout, docList); |
1577 | for(size_t i=0; i < count; ++i) { |
1578 | if ( yout.preflightDocument(i) ) { |
1579 | yamlize(yout, DocumentListTraits<T>::element(yout, docList, i), true, |
1580 | Ctx); |
1581 | yout.postflightDocument(); |
1582 | } |
1583 | } |
1584 | yout.endDocuments(); |
1585 | return yout; |
1586 | } |
1587 | |
1588 | // Define non-member operator<< so that Output can stream out a map. |
1589 | template <typename T> |
1590 | inline typename std::enable_if<has_MappingTraits<T, EmptyContext>::value, |
1591 | Output &>::type |
1592 | operator<<(Output &yout, T &map) { |
1593 | EmptyContext Ctx; |
1594 | yout.beginDocuments(); |
1595 | if ( yout.preflightDocument(0) ) { |
1596 | yamlize(yout, map, true, Ctx); |
1597 | yout.postflightDocument(); |
1598 | } |
1599 | yout.endDocuments(); |
1600 | return yout; |
1601 | } |
1602 | |
1603 | // Define non-member operator<< so that Output can stream out a sequence. |
1604 | template <typename T> |
1605 | inline |
1606 | typename std::enable_if<has_SequenceTraits<T>::value, Output &>::type |
1607 | operator<<(Output &yout, T &seq) { |
1608 | EmptyContext Ctx; |
1609 | yout.beginDocuments(); |
1610 | if ( yout.preflightDocument(0) ) { |
1611 | yamlize(yout, seq, true, Ctx); |
1612 | yout.postflightDocument(); |
1613 | } |
1614 | yout.endDocuments(); |
1615 | return yout; |
1616 | } |
1617 | |
1618 | // Define non-member operator<< so that Output can stream out a block scalar. |
1619 | template <typename T> |
1620 | inline |
1621 | typename std::enable_if<has_BlockScalarTraits<T>::value, Output &>::type |
1622 | operator<<(Output &Out, T &Val) { |
1623 | EmptyContext Ctx; |
1624 | Out.beginDocuments(); |
1625 | if (Out.preflightDocument(0)) { |
1626 | yamlize(Out, Val, true, Ctx); |
1627 | Out.postflightDocument(); |
1628 | } |
1629 | Out.endDocuments(); |
1630 | return Out; |
1631 | } |
1632 | |
1633 | // Define non-member operator<< so that Output can stream out a string map. |
1634 | template <typename T> |
1635 | inline |
1636 | typename std::enable_if<has_CustomMappingTraits<T>::value, Output &>::type |
1637 | operator<<(Output &Out, T &Val) { |
1638 | EmptyContext Ctx; |
1639 | Out.beginDocuments(); |
1640 | if (Out.preflightDocument(0)) { |
1641 | yamlize(Out, Val, true, Ctx); |
1642 | Out.postflightDocument(); |
1643 | } |
1644 | Out.endDocuments(); |
1645 | return Out; |
1646 | } |
1647 | |
1648 | // Provide better error message about types missing a trait specialization |
1649 | template <typename T> |
1650 | inline typename std::enable_if<missingTraits<T, EmptyContext>::value, |
1651 | Output &>::type |
1652 | operator<<(Output &yout, T &seq) { |
1653 | char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)]; |
1654 | return yout; |
1655 | } |
1656 | |
1657 | template <bool B> struct IsFlowSequenceBase {}; |
1658 | template <> struct IsFlowSequenceBase<true> { static const bool flow = true; }; |
1659 | |
1660 | template <typename T, bool Flow> |
1661 | struct SequenceTraitsImpl : IsFlowSequenceBase<Flow> { |
1662 | private: |
1663 | using type = typename T::value_type; |
1664 | |
1665 | public: |
1666 | static size_t size(IO &io, T &seq) { return seq.size(); } |
1667 | |
1668 | static type &element(IO &io, T &seq, size_t index) { |
1669 | if (index >= seq.size()) |
1670 | seq.resize(index + 1); |
1671 | return seq[index]; |
1672 | } |
1673 | }; |
1674 | |
1675 | // Simple helper to check an expression can be used as a bool-valued template |
1676 | // argument. |
1677 | template <bool> struct CheckIsBool { static const bool value = true; }; |
1678 | |
1679 | // If T has SequenceElementTraits, then vector<T> and SmallVector<T, N> have |
1680 | // SequenceTraits that do the obvious thing. |
1681 | template <typename T> |
1682 | struct SequenceTraits<std::vector<T>, |
1683 | typename std::enable_if<CheckIsBool< |
1684 | SequenceElementTraits<T>::flow>::value>::type> |
1685 | : SequenceTraitsImpl<std::vector<T>, SequenceElementTraits<T>::flow> {}; |
1686 | template <typename T, unsigned N> |
1687 | struct SequenceTraits<SmallVector<T, N>, |
1688 | typename std::enable_if<CheckIsBool< |
1689 | SequenceElementTraits<T>::flow>::value>::type> |
1690 | : SequenceTraitsImpl<SmallVector<T, N>, SequenceElementTraits<T>::flow> {}; |
1691 | |
1692 | // Sequences of fundamental types use flow formatting. |
1693 | template <typename T> |
1694 | struct SequenceElementTraits< |
1695 | T, typename std::enable_if<std::is_fundamental<T>::value>::type> { |
1696 | static const bool flow = true; |
1697 | }; |
1698 | |
1699 | // Sequences of strings use block formatting. |
1700 | template<> struct SequenceElementTraits<std::string> { |
1701 | static const bool flow = false; |
1702 | }; |
1703 | template<> struct SequenceElementTraits<StringRef> { |
1704 | static const bool flow = false; |
1705 | }; |
1706 | template<> struct SequenceElementTraits<std::pair<std::string, std::string>> { |
1707 | static const bool flow = false; |
1708 | }; |
1709 | |
1710 | /// Implementation of CustomMappingTraits for std::map<std::string, T>. |
1711 | template <typename T> struct StdMapStringCustomMappingTraitsImpl { |
1712 | using map_type = std::map<std::string, T>; |
1713 | |
1714 | static void inputOne(IO &io, StringRef key, map_type &v) { |
1715 | io.mapRequired(key.str().c_str(), v[key]); |
1716 | } |
1717 | |
1718 | static void output(IO &io, map_type &v) { |
1719 | for (auto &p : v) |
1720 | io.mapRequired(p.first.c_str(), p.second); |
1721 | } |
1722 | }; |
1723 | |
1724 | } // end namespace yaml |
1725 | } // end namespace llvm |
1726 | |
1727 | #define LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(TYPE, FLOW)namespace llvm { namespace yaml { static_assert( !std::is_fundamental <TYPE>::value && !std::is_same<TYPE, std::string >::value && !std::is_same<TYPE, llvm::StringRef >::value, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control" ); template <> struct SequenceElementTraits<TYPE> { static const bool flow = FLOW; }; } } \ |
1728 | namespace llvm { \ |
1729 | namespace yaml { \ |
1730 | static_assert( \ |
1731 | !std::is_fundamental<TYPE>::value && \ |
1732 | !std::is_same<TYPE, std::string>::value && \ |
1733 | !std::is_same<TYPE, llvm::StringRef>::value, \ |
1734 | "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control"); \ |
1735 | template <> struct SequenceElementTraits<TYPE> { \ |
1736 | static const bool flow = FLOW; \ |
1737 | }; \ |
1738 | } \ |
1739 | } |
1740 | |
1741 | /// Utility for declaring that a std::vector of a particular type |
1742 | /// should be considered a YAML sequence. |
1743 | #define LLVM_YAML_IS_SEQUENCE_VECTOR(type)namespace llvm { namespace yaml { static_assert( !std::is_fundamental <type>::value && !std::is_same<type, std::string >::value && !std::is_same<type, llvm::StringRef >::value, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control" ); template <> struct SequenceElementTraits<type> { static const bool flow = false; }; } } \ |
1744 | LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(type, false)namespace llvm { namespace yaml { static_assert( !std::is_fundamental <type>::value && !std::is_same<type, std::string >::value && !std::is_same<type, llvm::StringRef >::value, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control" ); template <> struct SequenceElementTraits<type> { static const bool flow = false; }; } } |
1745 | |
1746 | /// Utility for declaring that a std::vector of a particular type |
1747 | /// should be considered a YAML flow sequence. |
1748 | #define LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(type)namespace llvm { namespace yaml { static_assert( !std::is_fundamental <type>::value && !std::is_same<type, std::string >::value && !std::is_same<type, llvm::StringRef >::value, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control" ); template <> struct SequenceElementTraits<type> { static const bool flow = true; }; } } \ |
1749 | LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(type, true)namespace llvm { namespace yaml { static_assert( !std::is_fundamental <type>::value && !std::is_same<type, std::string >::value && !std::is_same<type, llvm::StringRef >::value, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control" ); template <> struct SequenceElementTraits<type> { static const bool flow = true; }; } } |
1750 | |
1751 | #define LLVM_YAML_DECLARE_MAPPING_TRAITS(Type)namespace llvm { namespace yaml { template <> struct MappingTraits <Type> { static void mapping(IO &IO, Type &Obj) ; }; } } \ |
1752 | namespace llvm { \ |
1753 | namespace yaml { \ |
1754 | template <> struct MappingTraits<Type> { \ |
1755 | static void mapping(IO &IO, Type &Obj); \ |
1756 | }; \ |
1757 | } \ |
1758 | } |
1759 | |
1760 | #define LLVM_YAML_DECLARE_ENUM_TRAITS(Type)namespace llvm { namespace yaml { template <> struct ScalarEnumerationTraits <Type> { static void enumeration(IO &io, Type & Value); }; } } \ |
1761 | namespace llvm { \ |
1762 | namespace yaml { \ |
1763 | template <> struct ScalarEnumerationTraits<Type> { \ |
1764 | static void enumeration(IO &io, Type &Value); \ |
1765 | }; \ |
1766 | } \ |
1767 | } |
1768 | |
1769 | #define LLVM_YAML_DECLARE_BITSET_TRAITS(Type)namespace llvm { namespace yaml { template <> struct ScalarBitSetTraits <Type> { static void bitset(IO &IO, Type &Options ); }; } } \ |
1770 | namespace llvm { \ |
1771 | namespace yaml { \ |
1772 | template <> struct ScalarBitSetTraits<Type> { \ |
1773 | static void bitset(IO &IO, Type &Options); \ |
1774 | }; \ |
1775 | } \ |
1776 | } |
1777 | |
1778 | #define LLVM_YAML_DECLARE_SCALAR_TRAITS(Type, MustQuote)namespace llvm { namespace yaml { template <> struct ScalarTraits <Type> { static void output(const Type &Value, void *ctx, raw_ostream &Out); static StringRef input(StringRef Scalar, void *ctxt, Type &Value); static QuotingType mustQuote (StringRef) { return MustQuote; } }; } } \ |
1779 | namespace llvm { \ |
1780 | namespace yaml { \ |
1781 | template <> struct ScalarTraits<Type> { \ |
1782 | static void output(const Type &Value, void *ctx, raw_ostream &Out); \ |
1783 | static StringRef input(StringRef Scalar, void *ctxt, Type &Value); \ |
1784 | static QuotingType mustQuote(StringRef) { return MustQuote; } \ |
1785 | }; \ |
1786 | } \ |
1787 | } |
1788 | |
1789 | /// Utility for declaring that a std::vector of a particular type |
1790 | /// should be considered a YAML document list. |
1791 | #define LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(_type)namespace llvm { namespace yaml { template <unsigned N> struct DocumentListTraits<SmallVector<_type, N>> : public SequenceTraitsImpl<SmallVector<_type, N>, false > {}; template <> struct DocumentListTraits<std:: vector<_type>> : public SequenceTraitsImpl<std::vector <_type>, false> {}; } } \ |
1792 | namespace llvm { \ |
1793 | namespace yaml { \ |
1794 | template <unsigned N> \ |
1795 | struct DocumentListTraits<SmallVector<_type, N>> \ |
1796 | : public SequenceTraitsImpl<SmallVector<_type, N>, false> {}; \ |
1797 | template <> \ |
1798 | struct DocumentListTraits<std::vector<_type>> \ |
1799 | : public SequenceTraitsImpl<std::vector<_type>, false> {}; \ |
1800 | } \ |
1801 | } |
1802 | |
1803 | /// Utility for declaring that std::map<std::string, _type> should be considered |
1804 | /// a YAML map. |
1805 | #define LLVM_YAML_IS_STRING_MAP(_type)namespace llvm { namespace yaml { template <> struct CustomMappingTraits <std::map<std::string, _type>> : public StdMapStringCustomMappingTraitsImpl <_type> {}; } } \ |
1806 | namespace llvm { \ |
1807 | namespace yaml { \ |
1808 | template <> \ |
1809 | struct CustomMappingTraits<std::map<std::string, _type>> \ |
1810 | : public StdMapStringCustomMappingTraitsImpl<_type> {}; \ |
1811 | } \ |
1812 | } |
1813 | |
1814 | #endif // LLVM_SUPPORT_YAMLTRAITS_H |