Line data Source code
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 62233 : 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 62233 : 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 124527 : 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 4 : return S.size() > 2 &&
468 6 : S.drop_front(2).find_first_not_of("01234567") == StringRef::npos;
469 :
470 : if (S.startswith("0x"))
471 7 : 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 62217 : 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 994 : (S.equals(".") ||
482 1988 : (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 60263 : S = skipDigits(S);
496 :
497 : // Accept decimal integer.
498 60263 : if (S.empty())
499 : return true;
500 :
501 119364 : if (S.front() == '.') {
502 : State = FoundDot;
503 18 : S = S.drop_front();
504 59664 : } else if (S.front() == 'e' || S.front() == 'E') {
505 : State = FoundExponent;
506 12 : S = S.drop_front();
507 : } else {
508 : return false;
509 : }
510 :
511 : if (State == FoundDot) {
512 18 : S = skipDigits(S);
513 18 : if (S.empty())
514 : return true;
515 :
516 20 : if (S.front() == 'e' || S.front() == 'E') {
517 : State = FoundExponent;
518 9 : S = S.drop_front();
519 : } else {
520 : return false;
521 : }
522 : }
523 :
524 : assert(State == FoundExponent && "Should have found exponent at this point.");
525 21 : if (S.empty())
526 : return false;
527 :
528 40 : if (S.front() == '+' || S.front() == '-') {
529 6 : S = S.drop_front();
530 6 : if (S.empty())
531 : return false;
532 : }
533 :
534 19 : return skipDigits(S).empty();
535 : }
536 :
537 62200 : inline bool isNull(StringRef S) {
538 : return S.equals("null") || S.equals("Null") || S.equals("NULL") ||
539 62200 : S.equals("~");
540 : }
541 :
542 62188 : inline bool isBool(StringRef S) {
543 : return S.equals("true") || S.equals("True") || S.equals("TRUE") ||
544 62188 : 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 166542 : inline QuotingType needsQuotes(StringRef S) {
553 166542 : if (S.empty())
554 : return QuotingType::Single;
555 125758 : if (isspace(S.front()) || isspace(S.back()))
556 : return QuotingType::Single;
557 62195 : if (isNull(S))
558 : return QuotingType::Single;
559 62188 : if (isBool(S))
560 : return QuotingType::Single;
561 62182 : 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 61600 : if (S.find_first_of(Indicators) == 0)
569 : return QuotingType::Single;
570 :
571 : QuotingType MaxQuotingNeeded = QuotingType::None;
572 821937 : for (unsigned char C : S) {
573 : // Alphanum is safe.
574 : if (isAlnum(C))
575 : continue;
576 :
577 91093 : 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 2 : case 0xA:
591 : case 0xD:
592 : MaxQuotingNeeded = QuotingType::Single;
593 2 : 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 18684 : case '/':
603 : default: {
604 : // C0 control block (0x0 - 0x1F) is excluded from the allowed character
605 : // range.
606 18684 : if (C <= 0x1F)
607 : return QuotingType::Double;
608 :
609 : // Always double quote UTF-8.
610 18680 : 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 11187 : 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 2049989 : void enumCase(T &Val, const char* Str, const T ConstVal) {
691 4053608 : if ( matchEnumScalar(Str, outputting() && Val == ConstVal) ) {
692 16775 : Val = ConstVal;
693 : }
694 2049989 : }
695 245968 :
696 472626 : // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF
697 1267 : template <typename T>
698 131630 : void enumCase(T &Val, const char* Str, const uint32_t ConstVal) {
699 410797 : if ( matchEnumScalar(Str, outputting() && Val == static_cast<T>(ConstVal)) ) {
700 197675 : Val = ConstVal;
701 379476 : }
702 132899 : }
703 2577 :
704 201293 : template <typename FBT, typename T>
705 93466 : void enumFallback(T &Val) {
706 178704 : if (matchEnumFallback()) {
707 3566 : EmptyContext Context;
708 132 : // FIXME: Force integral conversion to allow strong typedefs to convert.
709 93543 : FBT Res = static_cast<typename FBT::BaseType>(Val);
710 113410 : yamlize(*this, Res, true, Context);
711 225604 : Val = static_cast<T>(static_cast<typename FBT::BaseType>(Res));
712 1100 : }
713 1938 : }
714 116700 :
715 6399 : template <typename T>
716 12781 : void bitSetCase(T &Val, const char* Str, const T ConstVal) {
717 2248 : if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) {
718 1793 : Val = static_cast<T>(Val | ConstVal);
719 9389 : }
720 209512 : }
721 411852 :
722 4170 : // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF
723 13964 : template <typename T>
724 222956 : void bitSetCase(T &Val, const char* Str, const uint32_t ConstVal) {
725 47038 : if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) {
726 93943 : Val = static_cast<T>(Val | ConstVal);
727 15720 : }
728 7861 : }
729 55330 :
730 51256 : template <typename T>
731 89905 : void maskedBitSetCase(T &Val, const char *Str, T ConstVal, T Mask) {
732 3260 : if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal))
733 86 : Val = Val | ConstVal;
734 45283 : }
735 7291 :
736 14520 : template <typename T>
737 6798 : void maskedBitSetCase(T &Val, const char *Str, uint32_t ConstVal,
738 12560 : uint32_t Mask) {
739 28104 : if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal))
740 1774 : Val = Val | ConstVal;
741 1816 : }
742 12585 :
743 972 : void *getContext();
744 1350 : void setContext(void *);
745 1084324 :
746 2168737 : template <typename T> void mapRequired(const char *Key, T &Val) {
747 8857 : EmptyContext Ctx;
748 49888 : this->processKey(Key, Val, true, Ctx);
749 1124744 : }
750 3635 :
751 2149 : template <typename T, typename Context>
752 38648 : void mapRequired(const char *Key, T &Val, Context &Ctx) {
753 1663 : this->processKey(Key, Val, true, Ctx);
754 2160 : }
755 1797 :
756 727 : template <typename T> void mapOptional(const char *Key, T &Val) {
757 2297 : EmptyContext Ctx;
758 3932 : mapOptionalWithContext(Key, Val, Ctx);
759 1629 : }
760 1062 :
761 436 : template <typename T>
762 1897 : void mapOptional(const char *Key, T &Val, const T &Default) {
763 52329 : EmptyContext Ctx;
764 876 : mapOptionalWithContext(Key, Val, Default, Ctx);
765 756 : }
766 71 :
767 1149 : template <typename T, typename Context>
768 80323 : typename std::enable_if<has_SequenceTraits<T>::value, void>::type
769 65946 : mapOptionalWithContext(const char *Key, T &Val, Context &Ctx) {
770 21 : // omit key/value instead of outputting empty sequence
771 16128 : if (this->canElideEmptySequence() && !(Val.begin() != Val.end()))
772 74009 : return;
773 7382 : this->processKey(Key, Val, false, Ctx);
774 525 : }
775 15395 :
776 19984 : template <typename T, typename Context>
777 40989 : void mapOptionalWithContext(const char *Key, Optional<T> &Val, Context &Ctx) {
778 11252 : this->processKeyWithDefault(Key, Val, Optional<T>(), /*Required=*/false,
779 7738 : Ctx);
780 22631 : }
781 13426 :
782 16832 : template <typename T, typename Context>
783 5981 : typename std::enable_if<!has_SequenceTraits<T>::value, void>::type
784 1327 : mapOptionalWithContext(const char *Key, T &Val, Context &Ctx) {
785 13965 : this->processKey(Key, Val, false, Ctx);
786 19305 : }
787 33117 :
788 10864 : template <typename T, typename Context>
789 8978 : void mapOptionalWithContext(const char *Key, T &Val, const T &Default,
790 29949 : Context &Ctx) {
791 9818 : this->processKeyWithDefault(Key, Val, Default, false, Ctx);
792 11921 : }
793 7043 :
794 2238 : private:
795 5645 : template <typename T, typename Context>
796 2463 : void processKeyWithDefault(const char *Key, Optional<T> &Val,
797 3270 : const Optional<T> &DefaultValue, bool Required,
798 5240 : Context &Ctx) {
799 2238 : assert(DefaultValue.hasValue() == false &&
800 12826 : "Optional<T> shouldn't have a value!");
801 4701 : void *SaveInfo;
802 1185 : bool UseDefault = true;
803 6868 : const bool sameAsDefault = outputting() && !Val.hasValue();
804 1365 : if (!outputting() && !Val.hasValue())
805 5272 : Val = T();
806 146145 : if (Val.hasValue() &&
807 294 : this->preflightKey(Key, Required, sameAsDefault, UseDefault,
808 1145 : SaveInfo)) {
809 1977 : yamlize(*this, Val.getValue(), Required, Ctx);
810 558 : this->postflightKey(SaveInfo);
811 25178 : } else {
812 679 : if (UseDefault)
813 17152 : Val = DefaultValue;
814 27 : }
815 1671 : }
816 3779 :
817 16225 : template <typename T, typename Context>
818 11632 : void processKeyWithDefault(const char *Key, T &Val, const T &DefaultValue,
819 10676 : bool Required, Context &Ctx) {
820 4681 : void *SaveInfo;
821 15791 : bool UseDefault;
822 9730 : const bool sameAsDefault = outputting() && Val == DefaultValue;
823 67209 : if ( this->preflightKey(Key, Required, sameAsDefault, UseDefault,
824 4506 : SaveInfo) ) {
825 3949 : yamlize(*this, Val, Required, Ctx);
826 7547 : this->postflightKey(SaveInfo);
827 13884 : }
828 22260 : else {
829 2665 : if ( UseDefault )
830 11276 : Val = DefaultValue;
831 10563 : }
832 4442 : }
833 2264 :
834 : template <typename T, typename Context>
835 21484 : void processKey(const char *Key, T &Val, bool Required, Context &Ctx) {
836 1113 : void *SaveInfo;
837 9823 : bool UseDefault;
838 27922 : if ( this->preflightKey(Key, Required, false, UseDefault, SaveInfo) ) {
839 24555 : yamlize(*this, Val, Required, Ctx);
840 25894 : this->postflightKey(SaveInfo);
841 27895 : }
842 23305 : }
843 9525 :
844 8285 : private:
845 2315 : void *Ctxt;
846 5815 : };
847 17219 :
848 2455 : namespace detail {
849 11272 :
850 197606 : template <typename T, typename Context>
851 7406 : void doMapping(IO &io, T &Val, Context &Ctx) {
852 2469 : MappingContextTraits<T, Context>::mapping(io, Val, Ctx);
853 17179 : }
854 187462 :
855 187508 : template <typename T> void doMapping(IO &io, T &Val, EmptyContext &Ctx) {
856 16197 : MappingTraits<T>::mapping(io, Val);
857 47937 : }
858 49843 :
859 4106 : } // end namespace detail
860 15854 :
861 156854 : template <typename T>
862 13268 : typename std::enable_if<has_ScalarEnumerationTraits<T>::value, void>::type
863 5854 : yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
864 198838 : io.beginEnumScalar();
865 4357 : ScalarEnumerationTraits<T>::enumeration(io, Val);
866 11099 : io.endEnumScalar();
867 7371 : }
868 2744 :
869 11858 : template <typename T>
870 5525 : typename std::enable_if<has_ScalarBitSetTraits<T>::value, void>::type
871 5905 : yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
872 14114 : bool DoClear;
873 297902 : if ( io.beginBitSetScalar(DoClear) ) {
874 16703 : if ( DoClear )
875 6839 : Val = static_cast<T>(0);
876 10676 : ScalarBitSetTraits<T>::bitset(io, Val);
877 293399 : io.endBitSetScalar();
878 295308 : }
879 8882 : }
880 248238 :
881 229138 : template <typename T>
882 5470 : typename std::enable_if<has_ScalarTraits<T>::value, void>::type
883 6863 : yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
884 87630 : if ( io.outputting() ) {
885 71245 : std::string Storage;
886 4673 : raw_string_ostream Buffer(Storage);
887 302522 : ScalarTraits<T>::output(Val, io.getContext(), Buffer);
888 10626 : StringRef Str = Buffer.str();
889 1568 : io.scalarString(Str, ScalarTraits<T>::mustQuote(Str));
890 1618 : }
891 13373 : else {
892 4251 : StringRef Str;
893 8919 : io.scalarString(Str, ScalarTraits<T>::mustQuote(Str));
894 24936 : StringRef Result = ScalarTraits<T>::input(Str, io.getContext(), Val);
895 75827 : if ( !Result.empty() ) {
896 3967 : io.setError(Twine(Result));
897 7902 : }
898 15161 : }
899 75052 : }
900 72333 :
901 562 : template <typename T>
902 10144 : typename std::enable_if<has_BlockScalarTraits<T>::value, void>::type
903 73641 : yamlize(IO &YamlIO, T &Val, bool, EmptyContext &Ctx) {
904 9981 : if (YamlIO.outputting()) {
905 8217 : std::string Storage;
906 78163 : raw_string_ostream Buffer(Storage);
907 81560 : BlockScalarTraits<T>::output(Val, YamlIO.getContext(), Buffer);
908 69814 : StringRef Str = Buffer.str();
909 65798 : YamlIO.blockScalarString(Str);
910 78888 : } else {
911 52197 : StringRef Str;
912 884 : YamlIO.blockScalarString(Str);
913 6889 : StringRef Result =
914 41191 : BlockScalarTraits<T>::input(Str, YamlIO.getContext(), Val);
915 53474 : if (!Result.empty())
916 7158 : YamlIO.setError(Twine(Result));
917 67434 : }
918 26403 : }
919 19815 :
920 24122 : template <typename T, typename Context>
921 27686 : typename std::enable_if<validatedMappingTraits<T, Context>::value, void>::type
922 26673 : yamlize(IO &io, T &Val, bool, Context &Ctx) {
923 5096 : if (has_FlowTraits<MappingTraits<T>>::value)
924 36349 : io.beginFlowMapping();
925 23474 : else
926 4569 : io.beginMapping();
927 9926 : if (io.outputting()) {
928 3363 : StringRef Err = MappingTraits<T>::validate(io, Val);
929 52225 : if (!Err.empty()) {
930 79428 : errs() << Err << "\n";
931 10393 : assert(Err.empty() && "invalid struct trying to be written as yaml");
932 42496 : }
933 63020 : }
934 34505 : detail::doMapping(io, Val, Ctx);
935 54179 : if (!io.outputting()) {
936 15049 : StringRef Err = MappingTraits<T>::validate(io, Val);
937 23363 : if (!Err.empty())
938 16699 : io.setError(Err);
939 27967 : }
940 39488 : if (has_FlowTraits<MappingTraits<T>>::value)
941 17246 : io.endFlowMapping();
942 2190 : else
943 5452 : io.endMapping();
944 25258 : }
945 58694 :
946 819 : template <typename T, typename Context>
947 7354 : typename std::enable_if<unvalidatedMappingTraits<T, Context>::value, void>::type
948 100620 : yamlize(IO &io, T &Val, bool, Context &Ctx) {
949 6350 : if (has_FlowTraits<MappingTraits<T>>::value) {
950 354 : io.beginFlowMapping();
951 66768 : detail::doMapping(io, Val, Ctx);
952 39372 : io.endFlowMapping();
953 35977 : } else {
954 26365 : io.beginMapping();
955 119532 : detail::doMapping(io, Val, Ctx);
956 32078 : io.endMapping();
957 5512 : }
958 18176 : }
959 49654 :
960 38876 : template <typename T>
961 5299 : typename std::enable_if<has_CustomMappingTraits<T>::value, void>::type
962 46842 : yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
963 122968 : if ( io.outputting() ) {
964 2715 : io.beginMapping();
965 1566 : CustomMappingTraits<T>::output(io, Val);
966 25176 : io.endMapping();
967 124499 : } else {
968 116970 : io.beginMapping();
969 39993 : for (StringRef key : io.keys())
970 106292 : CustomMappingTraits<T>::inputOne(io, key, Val);
971 89905 : io.endMapping();
972 7306 : }
973 7275 : }
974 41849 :
975 34191 : template <typename T>
976 4006 : typename std::enable_if<missingTraits<T, EmptyContext>::value, void>::type
977 111850 : yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
978 6413 : char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
979 3112 : }
980 2361 :
981 17544 : template <typename T, typename Context>
982 13402 : typename std::enable_if<has_SequenceTraits<T>::value, void>::type
983 11693 : yamlize(IO &io, T &Seq, bool, Context &Ctx) {
984 23556 : if ( has_FlowTraits< SequenceTraits<T>>::value ) {
985 7340 : unsigned incnt = io.beginFlowSequence();
986 6778 : unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt;
987 105621 : for(unsigned i=0; i < count; ++i) {
988 62668 : void *SaveInfo;
989 1822 : if ( io.preflightFlowElement(i, SaveInfo) ) {
990 104792 : yamlize(io, SequenceTraits<T>::element(io, Seq, i), true, Ctx);
991 155012 : io.postflightFlowElement(SaveInfo);
992 129153 : }
993 33920 : }
994 107874 : io.endFlowSequence();
995 63791 : }
996 3181 : else {
997 49931 : unsigned incnt = io.beginSequence();
998 60388 : unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt;
999 18902 : for(unsigned i=0; i < count; ++i) {
1000 44137 : void *SaveInfo;
1001 36375 : if ( io.preflightElement(i, SaveInfo) ) {
1002 12776 : yamlize(io, SequenceTraits<T>::element(io, Seq, i), true, Ctx);
1003 28923 : io.postflightElement(SaveInfo);
1004 3494 : }
1005 2386 : }
1006 15903 : io.endSequence();
1007 22679 : }
1008 14330 : }
1009 12523 :
1010 9805 : template<>
1011 7251 : struct ScalarTraits<bool> {
1012 2833 : static void output(const bool &, void* , raw_ostream &);
1013 47246 : static StringRef input(StringRef, void *, bool &);
1014 14913 : static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1015 17258 : };
1016 8651 :
1017 11972 : template<>
1018 7557 : struct ScalarTraits<StringRef> {
1019 10510 : static void output(const StringRef &, void *, raw_ostream &);
1020 2016 : static StringRef input(StringRef, void *, StringRef &);
1021 517 : static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
1022 8773 : };
1023 18867 :
1024 10369 : template<>
1025 2555 : struct ScalarTraits<std::string> {
1026 11257 : static void output(const std::string &, void *, raw_ostream &);
1027 14596 : static StringRef input(StringRef, void *, std::string &);
1028 12319 : static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
1029 850 : };
1030 12497 :
1031 12256 : template<>
1032 3011 : struct ScalarTraits<uint8_t> {
1033 3730 : static void output(const uint8_t &, void *, raw_ostream &);
1034 3427 : static StringRef input(StringRef, void *, uint8_t &);
1035 4609 : static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1036 2922 : };
1037 11446 :
1038 8270 : template<>
1039 4704 : struct ScalarTraits<uint16_t> {
1040 4651 : static void output(const uint16_t &, void *, raw_ostream &);
1041 3083 : static StringRef input(StringRef, void *, uint16_t &);
1042 9943 : static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1043 19066 : };
1044 9075 :
1045 7199 : template<>
1046 18812 : struct ScalarTraits<uint32_t> {
1047 20041 : static void output(const uint32_t &, void *, raw_ostream &);
1048 19358 : static StringRef input(StringRef, void *, uint32_t &);
1049 8195 : static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1050 12139 : };
1051 13824 :
1052 14418 : template<>
1053 11330 : struct ScalarTraits<uint64_t> {
1054 14133 : static void output(const uint64_t &, void *, raw_ostream &);
1055 12259 : static StringRef input(StringRef, void *, uint64_t &);
1056 15703 : static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1057 17124 : };
1058 25713 :
1059 29429 : template<>
1060 9194 : struct ScalarTraits<int8_t> {
1061 12173 : static void output(const int8_t &, void *, raw_ostream &);
1062 19258 : static StringRef input(StringRef, void *, int8_t &);
1063 16020 : static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1064 16794 : };
1065 8204 :
1066 19694 : template<>
1067 25178 : struct ScalarTraits<int16_t> {
1068 21247 : static void output(const int16_t &, void *, raw_ostream &);
1069 2468 : static StringRef input(StringRef, void *, int16_t &);
1070 16355 : static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1071 15483 : };
1072 26001 :
1073 12548 : template<>
1074 16202 : struct ScalarTraits<int32_t> {
1075 57634 : static void output(const int32_t &, void *, raw_ostream &);
1076 7170 : static StringRef input(StringRef, void *, int32_t &);
1077 662 : static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1078 48976 : };
1079 59370 :
1080 53336 : template<>
1081 2111 : struct ScalarTraits<int64_t> {
1082 57911 : static void output(const int64_t &, void *, raw_ostream &);
1083 17370 : static StringRef input(StringRef, void *, int64_t &);
1084 7252 : static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1085 1972 : };
1086 3633 :
1087 11983 : template<>
1088 10639 : struct ScalarTraits<float> {
1089 2146 : static void output(const float &, void *, raw_ostream &);
1090 11676 : static StringRef input(StringRef, void *, float &);
1091 10387 : static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1092 1225 : };
1093 4506 :
1094 7501 : template<>
1095 6197 : struct ScalarTraits<double> {
1096 26563 : static void output(const double &, void *, raw_ostream &);
1097 9592 : static StringRef input(StringRef, void *, double &);
1098 13136 : static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1099 9933 : };
1100 12602 :
1101 1603 : // For endian types, we just use the existing ScalarTraits for the underlying
1102 17318 : // type. This way endian aware types are supported whenever a ScalarTraits
1103 25567 : // is defined for the underlying type.
1104 8335 : template <typename value_type, support::endianness endian, size_t alignment>
1105 8456 : struct ScalarTraits<support::detail::packed_endian_specific_integral<
1106 17551 : value_type, endian, alignment>> {
1107 13605 : using endian_type =
1108 8078 : support::detail::packed_endian_specific_integral<value_type, endian,
1109 7287 : alignment>;
1110 12689 :
1111 6878 : static void output(const endian_type &E, void *Ctx, raw_ostream &Stream) {
1112 13417 : ScalarTraits<value_type>::output(static_cast<value_type>(E), Ctx, Stream);
1113 11704 : }
1114 8530 :
1115 2254 : static StringRef input(StringRef Str, void *Ctx, endian_type &E) {
1116 2492 : value_type V;
1117 13505 : auto R = ScalarTraits<value_type>::input(Str, Ctx, V);
1118 12669 : E = static_cast<endian_type>(V);
1119 9047 : return R;
1120 7975 : }
1121 48411 :
1122 38670 : static QuotingType mustQuote(StringRef Str) {
1123 41061 : return ScalarTraits<value_type>::mustQuote(Str);
1124 45890 : }
1125 43070 : };
1126 3182 :
1127 15037 : // Utility for use within MappingTraits<>::mapping() method
1128 21324 : // to [de]normalize an object for use with YAML conversion.
1129 5487 : template <typename TNorm, typename TFinal>
1130 2381 : struct MappingNormalization {
1131 14605 : MappingNormalization(IO &i_o, TFinal &Obj)
1132 18835 : : io(i_o), BufPtr(nullptr), Result(Obj) {
1133 18376 : if ( io.outputting() ) {
1134 11275 : BufPtr = new (&Buffer) TNorm(io, Obj);
1135 19701 : }
1136 22256 : else {
1137 15413 : BufPtr = new (&Buffer) TNorm(io);
1138 18706 : }
1139 22800 : }
1140 18706 :
1141 29452 : ~MappingNormalization() {
1142 25216 : if ( ! io.outputting() ) {
1143 21577 : Result = BufPtr->denormalize(io);
1144 34414 : }
1145 28432 : BufPtr->~TNorm();
1146 15958 : }
1147 6295 :
1148 22860 : TNorm* operator->() { return BufPtr; }
1149 5429 :
1150 9390 : private:
1151 10205 : using Storage = AlignedCharArrayUnion<TNorm>;
1152 11778 :
1153 8908 : Storage Buffer;
1154 15346 : IO &io;
1155 2361 : TNorm *BufPtr;
1156 3080 : TFinal &Result;
1157 43857 : };
1158 3388 :
1159 1461 : // Utility for use within MappingTraits<>::mapping() method
1160 97503 : // to [de]normalize an object for use with YAML conversion.
1161 249019 : template <typename TNorm, typename TFinal>
1162 250008 : struct MappingNormalizationHeap {
1163 96862 : MappingNormalizationHeap(IO &i_o, TFinal &Obj, BumpPtrAllocator *allocator)
1164 300197 : : io(i_o), Result(Obj) {
1165 295790 : if ( io.outputting() ) {
1166 1991 : BufPtr = new (&Buffer) TNorm(io, Obj);
1167 293818 : }
1168 5341 : else if (allocator) {
1169 4984 : BufPtr = allocator->Allocate<TNorm>();
1170 43763 : new (BufPtr) TNorm(io);
1171 42204 : } else {
1172 50759 : BufPtr = new TNorm(io);
1173 45539 : }
1174 1607 : }
1175 11395 :
1176 19462 : ~MappingNormalizationHeap() {
1177 251103 : if ( io.outputting() ) {
1178 14954 : BufPtr->~TNorm();
1179 31149 : }
1180 11684 : else {
1181 20651 : Result = BufPtr->denormalize(io);
1182 11286 : }
1183 12102 : }
1184 11949 :
1185 3002 : TNorm* operator->() { return BufPtr; }
1186 2534 :
1187 5333 : private:
1188 13783 : using Storage = AlignedCharArrayUnion<TNorm>;
1189 6206 :
1190 3748 : Storage Buffer;
1191 2125 : IO &io;
1192 2218 : TNorm *BufPtr = nullptr;
1193 587 : TFinal &Result;
1194 16057 : };
1195 90994 :
1196 90600 : ///
1197 12791 : /// The Input class is used to parse a yaml document into in-memory structs
1198 74002 : /// and vectors.
1199 74936 : ///
1200 53506 : /// It works by using YAMLParser to do a syntax parse of the entire yaml
1201 81808 : /// document, then the Input class builds a graph of HNodes which wraps
1202 8671 : /// each yaml Node. The extra layer is buffering. The low level yaml
1203 42212 : /// parser only lets you look at each node once. The buffering layer lets
1204 69374 : /// you search and interate multiple times. This is necessary because
1205 59379 : /// the mapRequired() method calls may not be in the same order
1206 18514 : /// as the keys in the document.
1207 58259 : ///
1208 52829 : class Input : public IO {
1209 3328 : public:
1210 2022 : // Construct a yaml Input object from a StringRef and optional
1211 126881 : // user-data. The DiagHandler can be specified to provide
1212 62826 : // alternative error reporting.
1213 62057 : Input(StringRef InputContent,
1214 214 : void *Ctxt = nullptr,
1215 60373 : SourceMgr::DiagHandlerTy DiagHandler = nullptr,
1216 23684 : void *DiagHandlerCtxt = nullptr);
1217 1230 : Input(MemoryBufferRef Input,
1218 24166 : void *Ctxt = nullptr,
1219 279 : SourceMgr::DiagHandlerTy DiagHandler = nullptr,
1220 1522 : void *DiagHandlerCtxt = nullptr);
1221 1579 : ~Input() override;
1222 1457 :
1223 2151 : // Check if there was an syntax or semantic error during parsing.
1224 1774 : std::error_code error();
1225 1235 :
1226 1250 : private:
1227 934 : bool outputting() override;
1228 23475 : bool mapTag(StringRef, bool) override;
1229 72985 : void beginMapping() override;
1230 16144 : void endMapping() override;
1231 2553 : bool preflightKey(const char *, bool, bool, bool &, void *&) override;
1232 14185 : void postflightKey(void *) override;
1233 13887 : std::vector<StringRef> keys() override;
1234 3331 : void beginFlowMapping() override;
1235 15317 : void endFlowMapping() override;
1236 3242 : unsigned beginSequence() override;
1237 814 : void endSequence() override;
1238 5347 : bool preflightElement(unsigned index, void *&) override;
1239 3463 : void postflightElement(void *) override;
1240 3940 : unsigned beginFlowSequence() override;
1241 3909 : bool preflightFlowElement(unsigned , void *&) override;
1242 850 : void postflightFlowElement(void *) override;
1243 332 : void endFlowSequence() override;
1244 643 : void beginEnumScalar() override;
1245 16543 : bool matchEnumScalar(const char*, bool) override;
1246 99851 : bool matchEnumFallback() override;
1247 99814 : void endEnumScalar() override;
1248 1042 : bool beginBitSetScalar(bool &) override;
1249 85794 : bool bitSetMatch(const char *, bool ) override;
1250 86050 : void endBitSetScalar() override;
1251 4165 : void scalarString(StringRef &, QuotingType) override;
1252 85577 : void blockScalarString(StringRef &) override;
1253 4410 : void setError(const Twine &message) override;
1254 3338 : bool canElideEmptySequence() override;
1255 18910 :
1256 16197 : class HNode {
1257 15973 : virtual void anchor();
1258 16776 :
1259 741 : public:
1260 179464 : HNode(Node *n) : _node(n) { }
1261 2170 : virtual ~HNode() = default;
1262 100168 :
1263 2110 : static bool classof(const HNode *) { return true; }
1264 4647 :
1265 3422 : Node *_node;
1266 4106 : };
1267 2011 :
1268 3191 : class EmptyHNode : public HNode {
1269 2222 : void anchor() override;
1270 2430 :
1271 615 : public:
1272 5986 : EmptyHNode(Node *n) : HNode(n) { }
1273 2580 :
1274 5029 : static bool classof(const HNode *n) { return NullNode::classof(n->_node); }
1275 1646 :
1276 2458 : static bool classof(const EmptyHNode *) { return true; }
1277 3761 : };
1278 874 :
1279 863 : class ScalarHNode : public HNode {
1280 1844 : void anchor() override;
1281 9498 :
1282 2073 : public:
1283 162230 : ScalarHNode(Node *n, StringRef s) : HNode(n), _value(s) { }
1284 2027 :
1285 844 : StringRef value() const { return _value; }
1286 390 :
1287 795 : static bool classof(const HNode *n) {
1288 485427 : return ScalarNode::classof(n->_node) ||
1289 853 : BlockScalarNode::classof(n->_node);
1290 993 : }
1291 625 :
1292 738 : static bool classof(const ScalarHNode *) { return true; }
1293 1133 :
1294 656 : protected:
1295 1150 : StringRef _value;
1296 676 : };
1297 1120 :
1298 146715 : class MapHNode : public HNode {
1299 146502 : void anchor() override;
1300 279 :
1301 105279 : public:
1302 105216 : MapHNode(Node *n) : HNode(n) { }
1303 377 :
1304 105570 : static bool classof(const HNode *n) {
1305 378 : return MappingNode::classof(n->_node);
1306 723 : }
1307 41287 :
1308 42434 : static bool classof(const MapHNode *) { return true; }
1309 41601 :
1310 41224 : using NameToNode = StringMap<std::unique_ptr<HNode>>;
1311 26495 :
1312 13205 : NameToNode Mapping;
1313 13270 : SmallVector<std::string, 6> ValidKeys;
1314 147196 : };
1315 6979 :
1316 7994 : class SequenceHNode : public HNode {
1317 25505 : void anchor() override;
1318 6887 :
1319 25517 : public:
1320 14571 : SequenceHNode(Node *n) : HNode(n) { }
1321 34509 :
1322 14311 : static bool classof(const HNode *n) {
1323 8711 : return SequenceNode::classof(n->_node);
1324 10046 : }
1325 1860 :
1326 990 : static bool classof(const SequenceHNode *) { return true; }
1327 886 :
1328 19114 : std::vector<std::unique_ptr<HNode>> Entries;
1329 1789 : };
1330 7090 :
1331 1830 : std::unique_ptr<Input::HNode> createHNodes(Node *node);
1332 14709 : void setError(HNode *hnode, const Twine &message);
1333 29319 : void setError(Node *node, const Twine &message);
1334 6984 :
1335 12925 : public:
1336 12851 : // These are only used by operator>>. They could be private
1337 6778 : // if those templated things could be made friends.
1338 6975 : bool setCurrentDocument();
1339 14759 : bool nextDocument();
1340 2605 :
1341 18718 : /// Returns the current node that's being parsed by the YAML Parser.
1342 3611 : const Node *getCurrentNode() const;
1343 23175 :
1344 9511 : private:
1345 7450 : SourceMgr SrcMgr; // must be before Strm
1346 6928 : std::unique_ptr<llvm::yaml::Stream> Strm;
1347 6699 : std::unique_ptr<HNode> TopNode;
1348 8803 : std::error_code EC;
1349 1402 : BumpPtrAllocator StringAllocator;
1350 842 : document_iterator DocIterator;
1351 1286 : std::vector<bool> BitValuesUsed;
1352 5069 : HNode *CurrentNode = nullptr;
1353 519 : bool ScalarMatchFound;
1354 926 : };
1355 5753 :
1356 1676 : ///
1357 468 : /// The Output class is used to generate a yaml document from in-memory structs
1358 669 : /// and vectors.
1359 481 : ///
1360 7667 : class Output : public IO {
1361 5329 : public:
1362 7579 : Output(raw_ostream &, void *Ctxt = nullptr, int WrapColumn = 70);
1363 5687 : ~Output() override;
1364 634 :
1365 5411 : /// Set whether or not to output optional values which are equal
1366 8482 : /// to the default value. By default, when outputting if you attempt
1367 8164 : /// to write a value that is equal to the default, the value gets ignored.
1368 1477 : /// Sometimes, it is useful to be able to see these in the resulting YAML
1369 8752 : /// anyway.
1370 7665 : void setWriteDefaultValues(bool Write) { WriteDefaultValues = Write; }
1371 6499 :
1372 8641 : bool outputting() override;
1373 393 : bool mapTag(StringRef, bool) override;
1374 6723 : void beginMapping() override;
1375 12016 : void endMapping() override;
1376 12153 : bool preflightKey(const char *key, bool, bool, bool &, void *&) override;
1377 1839 : void postflightKey(void *) override;
1378 10178 : std::vector<StringRef> keys() override;
1379 4170 : void beginFlowMapping() override;
1380 880 : void endFlowMapping() override;
1381 3956 : unsigned beginSequence() override;
1382 8252 : void endSequence() override;
1383 1068 : bool preflightElement(unsigned, void *&) override;
1384 4976 : void postflightElement(void *) override;
1385 4329 : unsigned beginFlowSequence() override;
1386 3892 : bool preflightFlowElement(unsigned, void *&) override;
1387 4438 : void postflightFlowElement(void *) override;
1388 1304 : void endFlowSequence() override;
1389 488 : void beginEnumScalar() override;
1390 921 : bool matchEnumScalar(const char*, bool) override;
1391 7517 : bool matchEnumFallback() override;
1392 860 : void endEnumScalar() override;
1393 225 : bool beginBitSetScalar(bool &) override;
1394 518 : bool bitSetMatch(const char *, bool ) override;
1395 587 : void endBitSetScalar() override;
1396 5237 : void scalarString(StringRef &, QuotingType) override;
1397 5114 : void blockScalarString(StringRef &) override;
1398 1101 : void setError(const Twine &message) override;
1399 3486 : bool canElideEmptySequence() override;
1400 5840 :
1401 1913 : // These are only used by operator<<. They could be private
1402 3540 : // if that templated operator could be made a friend.
1403 1613 : void beginDocuments();
1404 1478 : bool preflightDocument(unsigned);
1405 1809 : void postflightDocument();
1406 3043 : void endDocuments();
1407 1941 :
1408 2629 : private:
1409 1230 : void output(StringRef s);
1410 1154 : void outputUpToEndOfLine(StringRef s);
1411 6376 : void newLineCheck();
1412 18183 : void outputNewLine();
1413 7832 : void paddedKey(StringRef key);
1414 31403 : void flowKey(StringRef Key);
1415 17652 :
1416 20418 : enum InState {
1417 17655 : inSeq,
1418 20297 : inFlowSeq,
1419 8098 : inMapFirstKey,
1420 11815 : inMapOtherKey,
1421 5045 : inFlowMapFirstKey,
1422 4721 : inFlowMapOtherKey
1423 12952 : };
1424 9061 :
1425 8798 : raw_ostream &Out;
1426 13318 : int WrapColumn;
1427 7834 : SmallVector<InState, 8> StateStack;
1428 26000 : int Column = 0;
1429 3868 : int ColumnAtFlowStart = 0;
1430 32015 : int ColumnAtMapFlowStart = 0;
1431 21448 : bool NeedBitValueComma = false;
1432 22283 : bool NeedFlowSequenceComma = false;
1433 1607 : bool EnumerationMatchFound = false;
1434 3275 : bool NeedsNewLine = false;
1435 7512 : bool WriteDefaultValues = false;
1436 1973 : };
1437 8003 :
1438 988 : /// YAML I/O does conversion based on types. But often native data types
1439 478 : /// are just a typedef of built in intergral types (e.g. int). But the C++
1440 3362 : /// type matching system sees through the typedef and all the typedefed types
1441 1773 : /// look like a built in type. This will cause the generic YAML I/O conversion
1442 451 : /// to be used. To provide better control over the YAML conversion, you can
1443 1124 : /// use this macro instead of typedef. It will create a class with one field
1444 591 : /// and automatic conversion operators to and from the base type.
1445 1637 : /// Based on BOOST_STRONG_TYPEDEF
1446 9609 : #define LLVM_YAML_STRONG_TYPEDEF(_base, _type) \
1447 1827 : struct _type { \
1448 10014 : _type() = default; \
1449 888 : _type(const _base v) : value(v) {} \
1450 3733 : _type(const _type &v) = default; \
1451 90107 : _type &operator=(const _type &rhs) = default; \
1452 91010 : _type &operator=(const _base &rhs) { value = rhs; return *this; } \
1453 1102 : operator const _base & () const { return value; } \
1454 72827 : bool operator==(const _type &rhs) const { return value == rhs.value; } \
1455 67098 : bool operator==(const _base &rhs) const { return value == rhs; } \
1456 5997 : bool operator<(const _type &rhs) const { return value < rhs.value; } \
1457 72771 : _base value; \
1458 6101 : using BaseType = _base; \
1459 2056 : };
1460 24197 :
1461 24908 : ///
1462 26993 : /// Use these types instead of uintXX_t in any mapping to have
1463 24776 : /// its yaml output formatted as hexadecimal.
1464 1527 : ///
1465 8976 : LLVM_YAML_STRONG_TYPEDEF(uint8_t, Hex8)
1466 2866 : LLVM_YAML_STRONG_TYPEDEF(uint16_t, Hex16)
1467 96781 : LLVM_YAML_STRONG_TYPEDEF(uint32_t, Hex32)
1468 50885 : LLVM_YAML_STRONG_TYPEDEF(uint64_t, Hex64)
1469 39538 :
1470 5155 : template<>
1471 26181 : struct ScalarTraits<Hex8> {
1472 27219 : static void output(const Hex8 &, void *, raw_ostream &);
1473 1895 : static StringRef input(StringRef, void *, Hex8 &);
1474 27715 : static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1475 2320 : };
1476 2107 :
1477 15139 : template<>
1478 14750 : struct ScalarTraits<Hex16> {
1479 16085 : static void output(const Hex16 &, void *, raw_ostream &);
1480 16101 : static StringRef input(StringRef, void *, Hex16 &);
1481 5010 : static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1482 3856 : };
1483 1329 :
1484 40087 : template<>
1485 2473 : struct ScalarTraits<Hex32> {
1486 1188 : static void output(const Hex32 &, void *, raw_ostream &);
1487 2583 : static StringRef input(StringRef, void *, Hex32 &);
1488 11092 : static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1489 10536 : };
1490 6238 :
1491 7468 : template<>
1492 6816 : struct ScalarTraits<Hex64> {
1493 1250 : static void output(const Hex64 &, void *, raw_ostream &);
1494 8645 : static StringRef input(StringRef, void *, Hex64 &);
1495 2335 : static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1496 5684 : };
1497 7784 :
1498 1526 : // Define non-member operator>> so that Input can stream in a document list.
1499 5753 : template <typename T>
1500 6471 : inline
1501 6355 : typename std::enable_if<has_DocumentListTraits<T>::value, Input &>::type
1502 7059 : operator>>(Input &yin, T &docList) {
1503 12904 : int i = 0;
1504 20506 : EmptyContext Ctx;
1505 20871 : while ( yin.setCurrentDocument() ) {
1506 20029 : yamlize(yin, DocumentListTraits<T>::element(yin, docList, i), true, Ctx);
1507 9877 : if ( yin.error() )
1508 19252 : return yin;
1509 13739 : yin.nextDocument();
1510 21471 : ++i;
1511 6729 : }
1512 11549 : return yin;
1513 11384 : }
1514 4492 :
1515 13634 : // Define non-member operator>> so that Input can stream in a map as a document.
1516 6542 : template <typename T>
1517 8354 : inline typename std::enable_if<has_MappingTraits<T, EmptyContext>::value,
1518 17048 : Input &>::type
1519 15947 : operator>>(Input &yin, T &docMap) {
1520 17997 : EmptyContext Ctx;
1521 17810 : yin.setCurrentDocument();
1522 21099 : yamlize(yin, docMap, true, Ctx);
1523 7300 : return yin;
1524 12127 : }
1525 192 :
1526 4110 : // Define non-member operator>> so that Input can stream in a sequence as
1527 9339 : // a document.
1528 4254 : template <typename T>
1529 1276 : inline
1530 1026 : typename std::enable_if<has_SequenceTraits<T>::value, Input &>::type
1531 1117 : operator>>(Input &yin, T &docSeq) {
1532 406 : EmptyContext Ctx;
1533 5390 : if (yin.setCurrentDocument())
1534 5988 : yamlize(yin, docSeq, true, Ctx);
1535 1361 : return yin;
1536 247 : }
1537 157 :
1538 309 : // Define non-member operator>> so that Input can stream in a block scalar.
1539 4900 : template <typename T>
1540 650 : inline
1541 6586 : typename std::enable_if<has_BlockScalarTraits<T>::value, Input &>::type
1542 966 : operator>>(Input &In, T &Val) {
1543 5052 : EmptyContext Ctx;
1544 4244 : if (In.setCurrentDocument())
1545 302 : yamlize(In, Val, true, Ctx);
1546 2687 : return In;
1547 1143 : }
1548 1296 :
1549 433 : // Define non-member operator>> so that Input can stream in a string map.
1550 876 : template <typename T>
1551 425 : inline
1552 2077 : typename std::enable_if<has_CustomMappingTraits<T>::value, Input &>::type
1553 601 : operator>>(Input &In, T &Val) {
1554 2017 : EmptyContext Ctx;
1555 70 : if (In.setCurrentDocument())
1556 2035 : yamlize(In, Val, true, Ctx);
1557 637 : return In;
1558 438 : }
1559 646 :
1560 438 : // Provide better error message about types missing a trait specialization
1561 23511 : template <typename T>
1562 496 : inline typename std::enable_if<missingTraits<T, EmptyContext>::value,
1563 445 : Input &>::type
1564 496 : operator>>(Input &yin, T &docSeq) {
1565 51897 : char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
1566 542 : return yin;
1567 41274 : }
1568 499 :
1569 41601 : // Define non-member operator<< so that Output can stream out document list.
1570 620 : template <typename T>
1571 10409 : inline
1572 154 : typename std::enable_if<has_DocumentListTraits<T>::value, Output &>::type
1573 10643 : operator<<(Output &yout, T &docList) {
1574 859 : EmptyContext Ctx;
1575 54628 : yout.beginDocuments();
1576 4826 : const size_t count = DocumentListTraits<T>::size(yout, docList);
1577 3929 : for(size_t i=0; i < count; ++i) {
1578 3969 : if ( yout.preflightDocument(i) ) {
1579 4070 : yamlize(yout, DocumentListTraits<T>::element(yout, docList, i), true,
1580 897 : Ctx);
1581 42 : yout.postflightDocument();
1582 912 : }
1583 201 : }
1584 119 : yout.endDocuments();
1585 559 : return yout;
1586 339 : }
1587 2360 :
1588 399 : // Define non-member operator<< so that Output can stream out a map.
1589 2303 : template <typename T>
1590 298 : inline typename std::enable_if<has_MappingTraits<T, EmptyContext>::value,
1591 1075 : Output &>::type
1592 867 : operator<<(Output &yout, T &map) {
1593 227 : EmptyContext Ctx;
1594 940 : yout.beginDocuments();
1595 689 : if ( yout.preflightDocument(0) ) {
1596 800 : yamlize(yout, map, true, Ctx);
1597 1533 : yout.postflightDocument();
1598 645 : }
1599 698 : yout.endDocuments();
1600 1268 : return yout;
1601 183 : }
1602 646 :
1603 262 : // Define non-member operator<< so that Output can stream out a sequence.
1604 255 : template <typename T>
1605 128 : inline
1606 199 : typename std::enable_if<has_SequenceTraits<T>::value, Output &>::type
1607 273 : operator<<(Output &yout, T &seq) {
1608 639 : EmptyContext Ctx;
1609 3568 : yout.beginDocuments();
1610 1844 : if ( yout.preflightDocument(0) ) {
1611 3943 : yamlize(yout, seq, true, Ctx);
1612 1687 : yout.postflightDocument();
1613 4118 : }
1614 629 : yout.endDocuments();
1615 411 : return yout;
1616 1634 : }
1617 63 :
1618 2688 : // Define non-member operator<< so that Output can stream out a block scalar.
1619 3694 : template <typename T>
1620 38763 : inline
1621 624 : typename std::enable_if<has_BlockScalarTraits<T>::value, Output &>::type
1622 37878 : operator<<(Output &Out, T &Val) {
1623 488 : EmptyContext Ctx;
1624 36763 : Out.beginDocuments();
1625 429 : if (Out.preflightDocument(0)) {
1626 92 : yamlize(Out, Val, true, Ctx);
1627 517 : Out.postflightDocument();
1628 125 : }
1629 271 : Out.endDocuments();
1630 37304 : return Out;
1631 13465 : }
1632 17850 :
1633 1111 : // Define non-member operator<< so that Output can stream out a string map.
1634 2399 : template <typename T>
1635 1350 : inline
1636 61 : typename std::enable_if<has_CustomMappingTraits<T>::value, Output &>::type
1637 1854 : operator<<(Output &Out, T &Val) {
1638 6025 : EmptyContext Ctx;
1639 181 : Out.beginDocuments();
1640 16621 : if (Out.preflightDocument(0)) {
1641 12110 : yamlize(Out, Val, true, Ctx);
1642 16877 : Out.postflightDocument();
1643 11709 : }
1644 1136 : Out.endDocuments();
1645 1121 : return Out;
1646 1065 : }
1647 12484 :
1648 6547 : // Provide better error message about types missing a trait specialization
1649 6865 : template <typename T>
1650 420 : inline typename std::enable_if<missingTraits<T, EmptyContext>::value,
1651 402 : Output &>::type
1652 909 : operator<<(Output &yout, T &seq) {
1653 6905 : char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
1654 10706 : return yout;
1655 375 : }
1656 2547 :
1657 8637 : template <bool B> struct IsFlowSequenceBase {};
1658 8712 : template <> struct IsFlowSequenceBase<true> { static const bool flow = true; };
1659 11961 :
1660 13728 : template <typename T, bool Flow>
1661 6071 : struct SequenceTraitsImpl : IsFlowSequenceBase<Flow> {
1662 7654 : private:
1663 7044 : using type = typename T::value_type;
1664 18861 :
1665 789 : public:
1666 1048 : static size_t size(IO &io, T &seq) { return seq.size(); }
1667 892 :
1668 8767 : static type &element(IO &io, T &seq, size_t index) {
1669 592 : if (index >= seq.size())
1670 5486 : seq.resize(index + 1);
1671 1399 : return seq[index];
1672 5576 : }
1673 213 : };
1674 12027 :
1675 537 : // Simple helper to check an expression can be used as a bool-valued template
1676 7751 : // argument.
1677 75 : template <bool> struct CheckIsBool { static const bool value = true; };
1678 7144 :
1679 763 : // If T has SequenceElementTraits, then vector<T> and SmallVector<T, N> have
1680 5 : // SequenceTraits that do the obvious thing.
1681 145 : template <typename T>
1682 582 : struct SequenceTraits<std::vector<T>,
1683 110 : typename std::enable_if<CheckIsBool<
1684 648 : SequenceElementTraits<T>::flow>::value>::type>
1685 1034 : : SequenceTraitsImpl<std::vector<T>, SequenceElementTraits<T>::flow> {};
1686 579 : template <typename T, unsigned N>
1687 1159 : struct SequenceTraits<SmallVector<T, N>,
1688 26 : typename std::enable_if<CheckIsBool<
1689 1129 : SequenceElementTraits<T>::flow>::value>::type>
1690 7455 : : SequenceTraitsImpl<SmallVector<T, N>, SequenceElementTraits<T>::flow> {};
1691 7 :
1692 479 : // Sequences of fundamental types use flow formatting.
1693 798 : template <typename T>
1694 347 : struct SequenceElementTraits<
1695 791 : T, typename std::enable_if<std::is_fundamental<T>::value>::type> {
1696 7421 : static const bool flow = true;
1697 386 : };
1698 13922 :
1699 29707 : // Sequences of strings use block formatting.
1700 7375 : template<> struct SequenceElementTraits<std::string> {
1701 673 : static const bool flow = false;
1702 1706 : };
1703 1536 : template<> struct SequenceElementTraits<StringRef> {
1704 6769 : static const bool flow = false;
1705 1529 : };
1706 8216 : template<> struct SequenceElementTraits<std::pair<std::string, std::string>> {
1707 2021 : static const bool flow = false;
1708 8059 : };
1709 1139 :
1710 1702 : /// Implementation of CustomMappingTraits for std::map<std::string, T>.
1711 795 : template <typename T> struct StdMapStringCustomMappingTraitsImpl {
1712 2724 : using map_type = std::map<std::string, T>;
1713 30169 :
1714 29516 : static void inputOne(IO &io, StringRef key, map_type &v) {
1715 70731 : io.mapRequired(key.str().c_str(), v[key]);
1716 223 : }
1717 41398 :
1718 44183 : static void output(IO &io, map_type &v) {
1719 41702 : for (auto &p : v)
1720 3526 : io.mapRequired(p.first.c_str(), p.second);
1721 2024 : }
1722 32544 : };
1723 1439 :
1724 29507 : } // end namespace yaml
1725 5586 : } // end namespace llvm
1726 514 :
1727 325 : #define LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(TYPE, FLOW) \
1728 489 : namespace llvm { \
1729 865 : namespace yaml { \
1730 450 : static_assert( \
1731 1344 : !std::is_fundamental<TYPE>::value && \
1732 25 : !std::is_same<TYPE, std::string>::value && \
1733 862 : !std::is_same<TYPE, llvm::StringRef>::value, \
1734 299 : "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control"); \
1735 2 : template <> struct SequenceElementTraits<TYPE> { \
1736 0 : static const bool flow = FLOW; \
1737 484 : }; \
1738 0 : } \
1739 5770 : }
1740 5583 :
1741 5859 : /// Utility for declaring that a std::vector of a particular type
1742 323 : /// should be considered a YAML sequence.
1743 108 : #define LLVM_YAML_IS_SEQUENCE_VECTOR(type) \
1744 439 : LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(type, false)
1745 194 :
1746 52 : /// Utility for declaring that a std::vector of a particular type
1747 38 : /// should be considered a YAML flow sequence.
1748 5333 : #define LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(type) \
1749 7 : LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(type, true)
1750 5297 :
1751 5479 : #define LLVM_YAML_DECLARE_MAPPING_TRAITS(Type) \
1752 36 : namespace llvm { \
1753 170 : namespace yaml { \
1754 43 : template <> struct MappingTraits<Type> { \
1755 100 : static void mapping(IO &IO, Type &Obj); \
1756 484 : }; \
1757 51 : } \
1758 3 : }
1759 59 :
1760 1 : #define LLVM_YAML_DECLARE_ENUM_TRAITS(Type) \
1761 60 : namespace llvm { \
1762 464 : namespace yaml { \
1763 108 : template <> struct ScalarEnumerationTraits<Type> { \
1764 486 : static void enumeration(IO &io, Type &Value); \
1765 5413 : }; \
1766 5831 : } \
1767 7763 : }
1768 1128 :
1769 893 : #define LLVM_YAML_DECLARE_BITSET_TRAITS(Type) \
1770 1440 : namespace llvm { \
1771 1358 : namespace yaml { \
1772 63 : template <> struct ScalarBitSetTraits<Type> { \
1773 1202 : static void bitset(IO &IO, Type &Options); \
1774 5769 : }; \
1775 759 : } \
1776 6023 : }
1777 6379 :
1778 683 : #define LLVM_YAML_DECLARE_SCALAR_TRAITS(Type, MustQuote) \
1779 685 : namespace llvm { \
1780 16 : namespace yaml { \
1781 56 : template <> struct ScalarTraits<Type> { \
1782 16 : static void output(const Type &Value, void *ctx, raw_ostream &Out); \
1783 831 : static StringRef input(StringRef Scalar, void *ctxt, Type &Value); \
1784 924 : static QuotingType mustQuote(StringRef) { return MustQuote; } \
1785 1259 : }; \
1786 39 : } \
1787 353 : }
1788 492 :
1789 345 : /// Utility for declaring that a std::vector of a particular type
1790 19 : /// should be considered a YAML document list.
1791 5346 : #define LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(_type) \
1792 5466 : namespace llvm { \
1793 6722 : namespace yaml { \
1794 1005 : template <unsigned N> \
1795 1552 : struct DocumentListTraits<SmallVector<_type, N>> \
1796 1546 : : public SequenceTraitsImpl<SmallVector<_type, N>, false> {}; \
1797 665 : template <> \
1798 57 : struct DocumentListTraits<std::vector<_type>> \
1799 42 : : public SequenceTraitsImpl<std::vector<_type>, false> {}; \
1800 7004 : } \
1801 773 : }
1802 6927 :
1803 6374 : /// Utility for declaring that std::map<std::string, _type> should be considered
1804 1805 : /// a YAML map.
1805 3020 : #define LLVM_YAML_IS_STRING_MAP(_type) \
1806 2178 : namespace llvm { \
1807 1391 : namespace yaml { \
1808 2139 : template <> \
1809 3 : struct CustomMappingTraits<std::map<std::string, _type>> \
1810 1528 : : public StdMapStringCustomMappingTraitsImpl<_type> {}; \
1811 1209 : } \
1812 746 : }
1813 1198 :
1814 584 : #endif // LLVM_SUPPORT_YAMLTRAITS_H
|