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