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