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