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