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