1249259Sdim//===- llvm/Supporrt/YAMLTraits.h -------------------------------*- C++ -*-===// 2249259Sdim// 3249259Sdim// The LLVM Linker 4249259Sdim// 5249259Sdim// This file is distributed under the University of Illinois Open Source 6249259Sdim// License. See LICENSE.TXT for details. 7249259Sdim// 8249259Sdim//===----------------------------------------------------------------------===// 9249259Sdim 10249259Sdim#ifndef LLVM_SUPPORT_YAMLTRAITS_H 11249259Sdim#define LLVM_SUPPORT_YAMLTRAITS_H 12249259Sdim 13249259Sdim 14249259Sdim#include "llvm/ADT/DenseMap.h" 15249259Sdim#include "llvm/ADT/DenseMapInfo.h" 16249259Sdim#include "llvm/ADT/SmallVector.h" 17263509Sdim#include "llvm/ADT/StringMap.h" 18249259Sdim#include "llvm/ADT/StringRef.h" 19249259Sdim#include "llvm/ADT/StringSwitch.h" 20249259Sdim#include "llvm/ADT/Twine.h" 21263509Sdim#include "llvm/Support/Casting.h" 22249259Sdim#include "llvm/Support/Compiler.h" 23249259Sdim#include "llvm/Support/SourceMgr.h" 24249259Sdim#include "llvm/Support/YAMLParser.h" 25249259Sdim#include "llvm/Support/raw_ostream.h" 26249259Sdim#include "llvm/Support/system_error.h" 27249259Sdim#include "llvm/Support/type_traits.h" 28249259Sdim 29249259Sdim 30249259Sdimnamespace llvm { 31249259Sdimnamespace yaml { 32249259Sdim 33249259Sdim 34249259Sdim/// This class should be specialized by any type that needs to be converted 35249259Sdim/// to/from a YAML mapping. For example: 36249259Sdim/// 37249259Sdim/// struct ScalarBitSetTraits<MyStruct> { 38249259Sdim/// static void mapping(IO &io, MyStruct &s) { 39249259Sdim/// io.mapRequired("name", s.name); 40249259Sdim/// io.mapRequired("size", s.size); 41249259Sdim/// io.mapOptional("age", s.age); 42249259Sdim/// } 43249259Sdim/// }; 44249259Sdimtemplate<class T> 45249259Sdimstruct MappingTraits { 46249259Sdim // Must provide: 47249259Sdim // static void mapping(IO &io, T &fields); 48249259Sdim}; 49249259Sdim 50249259Sdim 51249259Sdim/// This class should be specialized by any integral type that converts 52249259Sdim/// to/from a YAML scalar where there is a one-to-one mapping between 53249259Sdim/// in-memory values and a string in YAML. For example: 54249259Sdim/// 55249259Sdim/// struct ScalarEnumerationTraits<Colors> { 56249259Sdim/// static void enumeration(IO &io, Colors &value) { 57249259Sdim/// io.enumCase(value, "red", cRed); 58249259Sdim/// io.enumCase(value, "blue", cBlue); 59249259Sdim/// io.enumCase(value, "green", cGreen); 60249259Sdim/// } 61249259Sdim/// }; 62249259Sdimtemplate<typename T> 63249259Sdimstruct ScalarEnumerationTraits { 64249259Sdim // Must provide: 65249259Sdim // static void enumeration(IO &io, T &value); 66249259Sdim}; 67249259Sdim 68249259Sdim 69249259Sdim/// This class should be specialized by any integer type that is a union 70249259Sdim/// of bit values and the YAML representation is a flow sequence of 71249259Sdim/// strings. For example: 72249259Sdim/// 73249259Sdim/// struct ScalarBitSetTraits<MyFlags> { 74249259Sdim/// static void bitset(IO &io, MyFlags &value) { 75249259Sdim/// io.bitSetCase(value, "big", flagBig); 76249259Sdim/// io.bitSetCase(value, "flat", flagFlat); 77249259Sdim/// io.bitSetCase(value, "round", flagRound); 78249259Sdim/// } 79249259Sdim/// }; 80249259Sdimtemplate<typename T> 81249259Sdimstruct ScalarBitSetTraits { 82249259Sdim // Must provide: 83249259Sdim // static void bitset(IO &io, T &value); 84249259Sdim}; 85249259Sdim 86249259Sdim 87249259Sdim/// This class should be specialized by type that requires custom conversion 88249259Sdim/// to/from a yaml scalar. For example: 89249259Sdim/// 90249259Sdim/// template<> 91249259Sdim/// struct ScalarTraits<MyType> { 92249259Sdim/// static void output(const MyType &val, void*, llvm::raw_ostream &out) { 93249259Sdim/// // stream out custom formatting 94249259Sdim/// out << llvm::format("%x", val); 95249259Sdim/// } 96249259Sdim/// static StringRef input(StringRef scalar, void*, MyType &value) { 97249259Sdim/// // parse scalar and set `value` 98249259Sdim/// // return empty string on success, or error string 99249259Sdim/// return StringRef(); 100249259Sdim/// } 101249259Sdim/// }; 102249259Sdimtemplate<typename T> 103249259Sdimstruct ScalarTraits { 104249259Sdim // Must provide: 105249259Sdim // 106249259Sdim // Function to write the value as a string: 107249259Sdim //static void output(const T &value, void *ctxt, llvm::raw_ostream &out); 108249259Sdim // 109249259Sdim // Function to convert a string to a value. Returns the empty 110249259Sdim // StringRef on success or an error string if string is malformed: 111249259Sdim //static StringRef input(StringRef scalar, void *ctxt, T &value); 112249259Sdim}; 113249259Sdim 114249259Sdim 115249259Sdim/// This class should be specialized by any type that needs to be converted 116249259Sdim/// to/from a YAML sequence. For example: 117249259Sdim/// 118249259Sdim/// template<> 119249259Sdim/// struct SequenceTraits< std::vector<MyType> > { 120249259Sdim/// static size_t size(IO &io, std::vector<MyType> &seq) { 121249259Sdim/// return seq.size(); 122249259Sdim/// } 123249259Sdim/// static MyType& element(IO &, std::vector<MyType> &seq, size_t index) { 124249259Sdim/// if ( index >= seq.size() ) 125249259Sdim/// seq.resize(index+1); 126249259Sdim/// return seq[index]; 127249259Sdim/// } 128249259Sdim/// }; 129249259Sdimtemplate<typename T> 130249259Sdimstruct SequenceTraits { 131249259Sdim // Must provide: 132249259Sdim // static size_t size(IO &io, T &seq); 133249259Sdim // static T::value_type& element(IO &io, T &seq, size_t index); 134249259Sdim // 135249259Sdim // The following is option and will cause generated YAML to use 136249259Sdim // a flow sequence (e.g. [a,b,c]). 137249259Sdim // static const bool flow = true; 138249259Sdim}; 139249259Sdim 140249259Sdim 141249259Sdim/// This class should be specialized by any type that needs to be converted 142249259Sdim/// to/from a list of YAML documents. 143249259Sdimtemplate<typename T> 144249259Sdimstruct DocumentListTraits { 145249259Sdim // Must provide: 146249259Sdim // static size_t size(IO &io, T &seq); 147249259Sdim // static T::value_type& element(IO &io, T &seq, size_t index); 148249259Sdim}; 149249259Sdim 150249259Sdim 151249259Sdim// Only used by compiler if both template types are the same 152249259Sdimtemplate <typename T, T> 153249259Sdimstruct SameType; 154249259Sdim 155249259Sdim// Only used for better diagnostics of missing traits 156249259Sdimtemplate <typename T> 157249259Sdimstruct MissingTrait; 158249259Sdim 159249259Sdim 160249259Sdim 161249259Sdim// Test if ScalarEnumerationTraits<T> is defined on type T. 162249259Sdimtemplate <class T> 163249259Sdimstruct has_ScalarEnumerationTraits 164249259Sdim{ 165249259Sdim typedef void (*Signature_enumeration)(class IO&, T&); 166249259Sdim 167249259Sdim template <typename U> 168249259Sdim static char test(SameType<Signature_enumeration, &U::enumeration>*); 169249259Sdim 170249259Sdim template <typename U> 171249259Sdim static double test(...); 172249259Sdim 173249259Sdimpublic: 174249259Sdim static bool const value = (sizeof(test<ScalarEnumerationTraits<T> >(0)) == 1); 175249259Sdim}; 176249259Sdim 177249259Sdim 178249259Sdim// Test if ScalarBitSetTraits<T> is defined on type T. 179249259Sdimtemplate <class T> 180249259Sdimstruct has_ScalarBitSetTraits 181249259Sdim{ 182249259Sdim typedef void (*Signature_bitset)(class IO&, T&); 183249259Sdim 184249259Sdim template <typename U> 185249259Sdim static char test(SameType<Signature_bitset, &U::bitset>*); 186249259Sdim 187249259Sdim template <typename U> 188249259Sdim static double test(...); 189249259Sdim 190249259Sdimpublic: 191249259Sdim static bool const value = (sizeof(test<ScalarBitSetTraits<T> >(0)) == 1); 192249259Sdim}; 193249259Sdim 194249259Sdim 195249259Sdim// Test if ScalarTraits<T> is defined on type T. 196249259Sdimtemplate <class T> 197249259Sdimstruct has_ScalarTraits 198249259Sdim{ 199249259Sdim typedef StringRef (*Signature_input)(StringRef, void*, T&); 200249259Sdim typedef void (*Signature_output)(const T&, void*, llvm::raw_ostream&); 201249259Sdim 202249259Sdim template <typename U> 203249259Sdim static char test(SameType<Signature_input, &U::input>*, 204249259Sdim SameType<Signature_output, &U::output>*); 205249259Sdim 206249259Sdim template <typename U> 207249259Sdim static double test(...); 208249259Sdim 209249259Sdimpublic: 210249259Sdim static bool const value = (sizeof(test<ScalarTraits<T> >(0,0)) == 1); 211249259Sdim}; 212249259Sdim 213249259Sdim 214249259Sdim// Test if MappingTraits<T> is defined on type T. 215249259Sdimtemplate <class T> 216249259Sdimstruct has_MappingTraits 217249259Sdim{ 218249259Sdim typedef void (*Signature_mapping)(class IO&, T&); 219249259Sdim 220249259Sdim template <typename U> 221249259Sdim static char test(SameType<Signature_mapping, &U::mapping>*); 222249259Sdim 223249259Sdim template <typename U> 224249259Sdim static double test(...); 225249259Sdim 226249259Sdimpublic: 227249259Sdim static bool const value = (sizeof(test<MappingTraits<T> >(0)) == 1); 228249259Sdim}; 229249259Sdim 230249259Sdim 231249259Sdim// Test if SequenceTraits<T> is defined on type T. 232249259Sdimtemplate <class T> 233249259Sdimstruct has_SequenceMethodTraits 234249259Sdim{ 235249259Sdim typedef size_t (*Signature_size)(class IO&, T&); 236249259Sdim 237249259Sdim template <typename U> 238249259Sdim static char test(SameType<Signature_size, &U::size>*); 239249259Sdim 240249259Sdim template <typename U> 241249259Sdim static double test(...); 242249259Sdim 243249259Sdimpublic: 244249259Sdim static bool const value = (sizeof(test<SequenceTraits<T> >(0)) == 1); 245249259Sdim}; 246249259Sdim 247249259Sdim 248249259Sdim// has_FlowTraits<int> will cause an error with some compilers because 249249259Sdim// it subclasses int. Using this wrapper only instantiates the 250249259Sdim// real has_FlowTraits only if the template type is a class. 251249259Sdimtemplate <typename T, bool Enabled = llvm::is_class<T>::value> 252249259Sdimclass has_FlowTraits 253249259Sdim{ 254249259Sdimpublic: 255249259Sdim static const bool value = false; 256249259Sdim}; 257249259Sdim 258249259Sdim// Some older gcc compilers don't support straight forward tests 259249259Sdim// for members, so test for ambiguity cause by the base and derived 260249259Sdim// classes both defining the member. 261249259Sdimtemplate <class T> 262249259Sdimstruct has_FlowTraits<T, true> 263249259Sdim{ 264249259Sdim struct Fallback { bool flow; }; 265249259Sdim struct Derived : T, Fallback { }; 266249259Sdim 267249259Sdim template<typename C> 268249259Sdim static char (&f(SameType<bool Fallback::*, &C::flow>*))[1]; 269249259Sdim 270249259Sdim template<typename C> 271249259Sdim static char (&f(...))[2]; 272249259Sdim 273249259Sdimpublic: 274249259Sdim static bool const value = sizeof(f<Derived>(0)) == 2; 275249259Sdim}; 276249259Sdim 277249259Sdim 278249259Sdim 279249259Sdim// Test if SequenceTraits<T> is defined on type T 280249259Sdimtemplate<typename T> 281249259Sdimstruct has_SequenceTraits : public llvm::integral_constant<bool, 282249259Sdim has_SequenceMethodTraits<T>::value > { }; 283249259Sdim 284249259Sdim 285249259Sdim// Test if DocumentListTraits<T> is defined on type T 286249259Sdimtemplate <class T> 287249259Sdimstruct has_DocumentListTraits 288249259Sdim{ 289249259Sdim typedef size_t (*Signature_size)(class IO&, T&); 290249259Sdim 291249259Sdim template <typename U> 292249259Sdim static char test(SameType<Signature_size, &U::size>*); 293249259Sdim 294249259Sdim template <typename U> 295249259Sdim static double test(...); 296249259Sdim 297249259Sdimpublic: 298249259Sdim static bool const value = (sizeof(test<DocumentListTraits<T> >(0)) == 1); 299249259Sdim}; 300249259Sdim 301249259Sdim 302249259Sdim 303249259Sdim 304249259Sdimtemplate<typename T> 305249259Sdimstruct missingTraits : public llvm::integral_constant<bool, 306249259Sdim !has_ScalarEnumerationTraits<T>::value 307249259Sdim && !has_ScalarBitSetTraits<T>::value 308249259Sdim && !has_ScalarTraits<T>::value 309249259Sdim && !has_MappingTraits<T>::value 310249259Sdim && !has_SequenceTraits<T>::value 311249259Sdim && !has_DocumentListTraits<T>::value > {}; 312249259Sdim 313249259Sdim 314249259Sdim// Base class for Input and Output. 315249259Sdimclass IO { 316249259Sdimpublic: 317249259Sdim 318249259Sdim IO(void *Ctxt=NULL); 319249259Sdim virtual ~IO(); 320249259Sdim 321263509Sdim virtual bool outputting() const = 0; 322249259Sdim 323249259Sdim virtual unsigned beginSequence() = 0; 324249259Sdim virtual bool preflightElement(unsigned, void *&) = 0; 325249259Sdim virtual void postflightElement(void*) = 0; 326249259Sdim virtual void endSequence() = 0; 327263509Sdim virtual bool canElideEmptySequence() = 0; 328249259Sdim 329249259Sdim virtual unsigned beginFlowSequence() = 0; 330249259Sdim virtual bool preflightFlowElement(unsigned, void *&) = 0; 331249259Sdim virtual void postflightFlowElement(void*) = 0; 332249259Sdim virtual void endFlowSequence() = 0; 333249259Sdim 334263509Sdim virtual bool mapTag(StringRef Tag, bool Default=false) = 0; 335249259Sdim virtual void beginMapping() = 0; 336249259Sdim virtual void endMapping() = 0; 337249259Sdim virtual bool preflightKey(const char*, bool, bool, bool &, void *&) = 0; 338249259Sdim virtual void postflightKey(void*) = 0; 339249259Sdim 340249259Sdim virtual void beginEnumScalar() = 0; 341249259Sdim virtual bool matchEnumScalar(const char*, bool) = 0; 342249259Sdim virtual void endEnumScalar() = 0; 343249259Sdim 344249259Sdim virtual bool beginBitSetScalar(bool &) = 0; 345249259Sdim virtual bool bitSetMatch(const char*, bool) = 0; 346249259Sdim virtual void endBitSetScalar() = 0; 347249259Sdim 348249259Sdim virtual void scalarString(StringRef &) = 0; 349249259Sdim 350249259Sdim virtual void setError(const Twine &) = 0; 351249259Sdim 352249259Sdim template <typename T> 353249259Sdim void enumCase(T &Val, const char* Str, const T ConstVal) { 354249259Sdim if ( matchEnumScalar(Str, outputting() && Val == ConstVal) ) { 355249259Sdim Val = ConstVal; 356249259Sdim } 357249259Sdim } 358249259Sdim 359249259Sdim // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF 360249259Sdim template <typename T> 361249259Sdim void enumCase(T &Val, const char* Str, const uint32_t ConstVal) { 362249259Sdim if ( matchEnumScalar(Str, outputting() && Val == static_cast<T>(ConstVal)) ) { 363249259Sdim Val = ConstVal; 364249259Sdim } 365249259Sdim } 366249259Sdim 367249259Sdim template <typename T> 368249259Sdim void bitSetCase(T &Val, const char* Str, const T ConstVal) { 369249259Sdim if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) { 370249259Sdim Val = Val | ConstVal; 371249259Sdim } 372249259Sdim } 373249259Sdim 374249259Sdim // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF 375249259Sdim template <typename T> 376249259Sdim void bitSetCase(T &Val, const char* Str, const uint32_t ConstVal) { 377249259Sdim if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) { 378249259Sdim Val = Val | ConstVal; 379249259Sdim } 380249259Sdim } 381249259Sdim 382249259Sdim void *getContext(); 383249259Sdim void setContext(void *); 384249259Sdim 385249259Sdim template <typename T> 386249259Sdim void mapRequired(const char* Key, T& Val) { 387249259Sdim this->processKey(Key, Val, true); 388249259Sdim } 389249259Sdim 390249259Sdim template <typename T> 391249259Sdim typename llvm::enable_if_c<has_SequenceTraits<T>::value,void>::type 392249259Sdim mapOptional(const char* Key, T& Val) { 393249259Sdim // omit key/value instead of outputting empty sequence 394263509Sdim if ( this->canElideEmptySequence() && !(Val.begin() != Val.end()) ) 395249259Sdim return; 396249259Sdim this->processKey(Key, Val, false); 397249259Sdim } 398249259Sdim 399249259Sdim template <typename T> 400249259Sdim typename llvm::enable_if_c<!has_SequenceTraits<T>::value,void>::type 401249259Sdim mapOptional(const char* Key, T& Val) { 402249259Sdim this->processKey(Key, Val, false); 403249259Sdim } 404249259Sdim 405249259Sdim template <typename T> 406249259Sdim void mapOptional(const char* Key, T& Val, const T& Default) { 407249259Sdim this->processKeyWithDefault(Key, Val, Default, false); 408249259Sdim } 409263509Sdim 410249259Sdimprivate: 411249259Sdim template <typename T> 412249259Sdim void processKeyWithDefault(const char *Key, T &Val, const T& DefaultValue, 413249259Sdim bool Required) { 414249259Sdim void *SaveInfo; 415249259Sdim bool UseDefault; 416249259Sdim const bool sameAsDefault = outputting() && Val == DefaultValue; 417249259Sdim if ( this->preflightKey(Key, Required, sameAsDefault, UseDefault, 418249259Sdim SaveInfo) ) { 419249259Sdim yamlize(*this, Val, Required); 420249259Sdim this->postflightKey(SaveInfo); 421249259Sdim } 422249259Sdim else { 423249259Sdim if ( UseDefault ) 424249259Sdim Val = DefaultValue; 425249259Sdim } 426249259Sdim } 427249259Sdim 428249259Sdim template <typename T> 429249259Sdim void processKey(const char *Key, T &Val, bool Required) { 430249259Sdim void *SaveInfo; 431249259Sdim bool UseDefault; 432249259Sdim if ( this->preflightKey(Key, Required, false, UseDefault, SaveInfo) ) { 433249259Sdim yamlize(*this, Val, Required); 434249259Sdim this->postflightKey(SaveInfo); 435249259Sdim } 436249259Sdim } 437249259Sdim 438249259Sdimprivate: 439249259Sdim void *Ctxt; 440249259Sdim}; 441249259Sdim 442249259Sdim 443249259Sdim 444249259Sdimtemplate<typename T> 445249259Sdimtypename llvm::enable_if_c<has_ScalarEnumerationTraits<T>::value,void>::type 446249259Sdimyamlize(IO &io, T &Val, bool) { 447249259Sdim io.beginEnumScalar(); 448249259Sdim ScalarEnumerationTraits<T>::enumeration(io, Val); 449249259Sdim io.endEnumScalar(); 450249259Sdim} 451249259Sdim 452249259Sdimtemplate<typename T> 453249259Sdimtypename llvm::enable_if_c<has_ScalarBitSetTraits<T>::value,void>::type 454249259Sdimyamlize(IO &io, T &Val, bool) { 455249259Sdim bool DoClear; 456249259Sdim if ( io.beginBitSetScalar(DoClear) ) { 457249259Sdim if ( DoClear ) 458249259Sdim Val = static_cast<T>(0); 459249259Sdim ScalarBitSetTraits<T>::bitset(io, Val); 460249259Sdim io.endBitSetScalar(); 461249259Sdim } 462249259Sdim} 463249259Sdim 464249259Sdim 465249259Sdimtemplate<typename T> 466249259Sdimtypename llvm::enable_if_c<has_ScalarTraits<T>::value,void>::type 467249259Sdimyamlize(IO &io, T &Val, bool) { 468249259Sdim if ( io.outputting() ) { 469249259Sdim std::string Storage; 470249259Sdim llvm::raw_string_ostream Buffer(Storage); 471249259Sdim ScalarTraits<T>::output(Val, io.getContext(), Buffer); 472249259Sdim StringRef Str = Buffer.str(); 473249259Sdim io.scalarString(Str); 474249259Sdim } 475249259Sdim else { 476249259Sdim StringRef Str; 477249259Sdim io.scalarString(Str); 478249259Sdim StringRef Result = ScalarTraits<T>::input(Str, io.getContext(), Val); 479249259Sdim if ( !Result.empty() ) { 480249259Sdim io.setError(llvm::Twine(Result)); 481249259Sdim } 482249259Sdim } 483249259Sdim} 484249259Sdim 485249259Sdim 486249259Sdimtemplate<typename T> 487249259Sdimtypename llvm::enable_if_c<has_MappingTraits<T>::value, void>::type 488249259Sdimyamlize(IO &io, T &Val, bool) { 489249259Sdim io.beginMapping(); 490249259Sdim MappingTraits<T>::mapping(io, Val); 491249259Sdim io.endMapping(); 492249259Sdim} 493249259Sdim 494249259Sdimtemplate<typename T> 495249259Sdimtypename llvm::enable_if_c<missingTraits<T>::value, void>::type 496249259Sdimyamlize(IO &io, T &Val, bool) { 497249259Sdim char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)]; 498249259Sdim} 499249259Sdim 500249259Sdimtemplate<typename T> 501249259Sdimtypename llvm::enable_if_c<has_SequenceTraits<T>::value,void>::type 502249259Sdimyamlize(IO &io, T &Seq, bool) { 503249259Sdim if ( has_FlowTraits< SequenceTraits<T> >::value ) { 504249259Sdim unsigned incnt = io.beginFlowSequence(); 505249259Sdim unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt; 506249259Sdim for(unsigned i=0; i < count; ++i) { 507249259Sdim void *SaveInfo; 508249259Sdim if ( io.preflightFlowElement(i, SaveInfo) ) { 509249259Sdim yamlize(io, SequenceTraits<T>::element(io, Seq, i), true); 510249259Sdim io.postflightFlowElement(SaveInfo); 511249259Sdim } 512249259Sdim } 513249259Sdim io.endFlowSequence(); 514249259Sdim } 515249259Sdim else { 516249259Sdim unsigned incnt = io.beginSequence(); 517249259Sdim unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt; 518249259Sdim for(unsigned i=0; i < count; ++i) { 519249259Sdim void *SaveInfo; 520249259Sdim if ( io.preflightElement(i, SaveInfo) ) { 521249259Sdim yamlize(io, SequenceTraits<T>::element(io, Seq, i), true); 522249259Sdim io.postflightElement(SaveInfo); 523249259Sdim } 524249259Sdim } 525249259Sdim io.endSequence(); 526249259Sdim } 527249259Sdim} 528249259Sdim 529249259Sdim 530249259Sdimtemplate<> 531249259Sdimstruct ScalarTraits<bool> { 532249259Sdim static void output(const bool &, void*, llvm::raw_ostream &); 533249259Sdim static StringRef input(StringRef, void*, bool &); 534249259Sdim}; 535249259Sdim 536249259Sdimtemplate<> 537249259Sdimstruct ScalarTraits<StringRef> { 538249259Sdim static void output(const StringRef &, void*, llvm::raw_ostream &); 539249259Sdim static StringRef input(StringRef, void*, StringRef &); 540249259Sdim}; 541249259Sdim 542249259Sdimtemplate<> 543249259Sdimstruct ScalarTraits<uint8_t> { 544249259Sdim static void output(const uint8_t &, void*, llvm::raw_ostream &); 545249259Sdim static StringRef input(StringRef, void*, uint8_t &); 546249259Sdim}; 547249259Sdim 548249259Sdimtemplate<> 549249259Sdimstruct ScalarTraits<uint16_t> { 550249259Sdim static void output(const uint16_t &, void*, llvm::raw_ostream &); 551249259Sdim static StringRef input(StringRef, void*, uint16_t &); 552249259Sdim}; 553249259Sdim 554249259Sdimtemplate<> 555249259Sdimstruct ScalarTraits<uint32_t> { 556249259Sdim static void output(const uint32_t &, void*, llvm::raw_ostream &); 557249259Sdim static StringRef input(StringRef, void*, uint32_t &); 558249259Sdim}; 559249259Sdim 560249259Sdimtemplate<> 561249259Sdimstruct ScalarTraits<uint64_t> { 562249259Sdim static void output(const uint64_t &, void*, llvm::raw_ostream &); 563249259Sdim static StringRef input(StringRef, void*, uint64_t &); 564249259Sdim}; 565249259Sdim 566249259Sdimtemplate<> 567249259Sdimstruct ScalarTraits<int8_t> { 568249259Sdim static void output(const int8_t &, void*, llvm::raw_ostream &); 569249259Sdim static StringRef input(StringRef, void*, int8_t &); 570249259Sdim}; 571249259Sdim 572249259Sdimtemplate<> 573249259Sdimstruct ScalarTraits<int16_t> { 574249259Sdim static void output(const int16_t &, void*, llvm::raw_ostream &); 575249259Sdim static StringRef input(StringRef, void*, int16_t &); 576249259Sdim}; 577249259Sdim 578249259Sdimtemplate<> 579249259Sdimstruct ScalarTraits<int32_t> { 580249259Sdim static void output(const int32_t &, void*, llvm::raw_ostream &); 581249259Sdim static StringRef input(StringRef, void*, int32_t &); 582249259Sdim}; 583249259Sdim 584249259Sdimtemplate<> 585249259Sdimstruct ScalarTraits<int64_t> { 586249259Sdim static void output(const int64_t &, void*, llvm::raw_ostream &); 587249259Sdim static StringRef input(StringRef, void*, int64_t &); 588249259Sdim}; 589249259Sdim 590249259Sdimtemplate<> 591249259Sdimstruct ScalarTraits<float> { 592249259Sdim static void output(const float &, void*, llvm::raw_ostream &); 593249259Sdim static StringRef input(StringRef, void*, float &); 594249259Sdim}; 595249259Sdim 596249259Sdimtemplate<> 597249259Sdimstruct ScalarTraits<double> { 598249259Sdim static void output(const double &, void*, llvm::raw_ostream &); 599249259Sdim static StringRef input(StringRef, void*, double &); 600249259Sdim}; 601249259Sdim 602249259Sdim 603249259Sdim 604249259Sdim// Utility for use within MappingTraits<>::mapping() method 605249259Sdim// to [de]normalize an object for use with YAML conversion. 606249259Sdimtemplate <typename TNorm, typename TFinal> 607249259Sdimstruct MappingNormalization { 608249259Sdim MappingNormalization(IO &i_o, TFinal &Obj) 609249259Sdim : io(i_o), BufPtr(NULL), Result(Obj) { 610249259Sdim if ( io.outputting() ) { 611249259Sdim BufPtr = new (&Buffer) TNorm(io, Obj); 612249259Sdim } 613249259Sdim else { 614249259Sdim BufPtr = new (&Buffer) TNorm(io); 615249259Sdim } 616249259Sdim } 617249259Sdim 618249259Sdim ~MappingNormalization() { 619249259Sdim if ( ! io.outputting() ) { 620249259Sdim Result = BufPtr->denormalize(io); 621249259Sdim } 622249259Sdim BufPtr->~TNorm(); 623249259Sdim } 624249259Sdim 625249259Sdim TNorm* operator->() { return BufPtr; } 626249259Sdim 627249259Sdimprivate: 628249259Sdim typedef llvm::AlignedCharArrayUnion<TNorm> Storage; 629249259Sdim 630249259Sdim Storage Buffer; 631249259Sdim IO &io; 632249259Sdim TNorm *BufPtr; 633249259Sdim TFinal &Result; 634249259Sdim}; 635249259Sdim 636249259Sdim 637249259Sdim 638249259Sdim// Utility for use within MappingTraits<>::mapping() method 639249259Sdim// to [de]normalize an object for use with YAML conversion. 640249259Sdimtemplate <typename TNorm, typename TFinal> 641249259Sdimstruct MappingNormalizationHeap { 642249259Sdim MappingNormalizationHeap(IO &i_o, TFinal &Obj) 643249259Sdim : io(i_o), BufPtr(NULL), Result(Obj) { 644249259Sdim if ( io.outputting() ) { 645249259Sdim BufPtr = new (&Buffer) TNorm(io, Obj); 646249259Sdim } 647249259Sdim else { 648249259Sdim BufPtr = new TNorm(io); 649249259Sdim } 650249259Sdim } 651249259Sdim 652249259Sdim ~MappingNormalizationHeap() { 653249259Sdim if ( io.outputting() ) { 654249259Sdim BufPtr->~TNorm(); 655249259Sdim } 656249259Sdim else { 657249259Sdim Result = BufPtr->denormalize(io); 658249259Sdim } 659249259Sdim } 660249259Sdim 661249259Sdim TNorm* operator->() { return BufPtr; } 662249259Sdim 663249259Sdimprivate: 664249259Sdim typedef llvm::AlignedCharArrayUnion<TNorm> Storage; 665249259Sdim 666249259Sdim Storage Buffer; 667249259Sdim IO &io; 668249259Sdim TNorm *BufPtr; 669249259Sdim TFinal &Result; 670249259Sdim}; 671249259Sdim 672249259Sdim 673249259Sdim 674249259Sdim/// 675249259Sdim/// The Input class is used to parse a yaml document into in-memory structs 676249259Sdim/// and vectors. 677249259Sdim/// 678249259Sdim/// It works by using YAMLParser to do a syntax parse of the entire yaml 679249259Sdim/// document, then the Input class builds a graph of HNodes which wraps 680249259Sdim/// each yaml Node. The extra layer is buffering. The low level yaml 681249259Sdim/// parser only lets you look at each node once. The buffering layer lets 682249259Sdim/// you search and interate multiple times. This is necessary because 683249259Sdim/// the mapRequired() method calls may not be in the same order 684249259Sdim/// as the keys in the document. 685249259Sdim/// 686249259Sdimclass Input : public IO { 687249259Sdimpublic: 688263509Sdim // Construct a yaml Input object from a StringRef and optional 689263509Sdim // user-data. The DiagHandler can be specified to provide 690263509Sdim // alternative error reporting. 691263509Sdim Input(StringRef InputContent, 692263509Sdim void *Ctxt = NULL, 693263509Sdim SourceMgr::DiagHandlerTy DiagHandler = NULL, 694263509Sdim void *DiagHandlerCtxt = NULL); 695249259Sdim ~Input(); 696263509Sdim 697249259Sdim // Check if there was an syntax or semantic error during parsing. 698249259Sdim llvm::error_code error(); 699249259Sdim 700263509Sdim static bool classof(const IO *io) { return !io->outputting(); } 701249259Sdim 702249259Sdimprivate: 703263509Sdim virtual bool outputting() const; 704263509Sdim virtual bool mapTag(StringRef, bool); 705249259Sdim virtual void beginMapping(); 706249259Sdim virtual void endMapping(); 707249259Sdim virtual bool preflightKey(const char *, bool, bool, bool &, void *&); 708249259Sdim virtual void postflightKey(void *); 709249259Sdim virtual unsigned beginSequence(); 710249259Sdim virtual void endSequence(); 711249259Sdim virtual bool preflightElement(unsigned index, void *&); 712249259Sdim virtual void postflightElement(void *); 713249259Sdim virtual unsigned beginFlowSequence(); 714249259Sdim virtual bool preflightFlowElement(unsigned , void *&); 715249259Sdim virtual void postflightFlowElement(void *); 716249259Sdim virtual void endFlowSequence(); 717249259Sdim virtual void beginEnumScalar(); 718249259Sdim virtual bool matchEnumScalar(const char*, bool); 719249259Sdim virtual void endEnumScalar(); 720249259Sdim virtual bool beginBitSetScalar(bool &); 721249259Sdim virtual bool bitSetMatch(const char *, bool ); 722249259Sdim virtual void endBitSetScalar(); 723249259Sdim virtual void scalarString(StringRef &); 724249259Sdim virtual void setError(const Twine &message); 725263509Sdim virtual bool canElideEmptySequence(); 726249259Sdim 727249259Sdim class HNode { 728263509Sdim virtual void anchor(); 729249259Sdim public: 730249259Sdim HNode(Node *n) : _node(n) { } 731249259Sdim virtual ~HNode() { } 732249259Sdim static inline bool classof(const HNode *) { return true; } 733249259Sdim 734249259Sdim Node *_node; 735249259Sdim }; 736249259Sdim 737249259Sdim class EmptyHNode : public HNode { 738263509Sdim virtual void anchor(); 739249259Sdim public: 740249259Sdim EmptyHNode(Node *n) : HNode(n) { } 741249259Sdim static inline bool classof(const HNode *n) { 742249259Sdim return NullNode::classof(n->_node); 743249259Sdim } 744249259Sdim static inline bool classof(const EmptyHNode *) { return true; } 745249259Sdim }; 746249259Sdim 747249259Sdim class ScalarHNode : public HNode { 748263509Sdim virtual void anchor(); 749249259Sdim public: 750249259Sdim ScalarHNode(Node *n, StringRef s) : HNode(n), _value(s) { } 751249259Sdim 752249259Sdim StringRef value() const { return _value; } 753249259Sdim 754249259Sdim static inline bool classof(const HNode *n) { 755249259Sdim return ScalarNode::classof(n->_node); 756249259Sdim } 757249259Sdim static inline bool classof(const ScalarHNode *) { return true; } 758249259Sdim protected: 759249259Sdim StringRef _value; 760249259Sdim }; 761249259Sdim 762249259Sdim class MapHNode : public HNode { 763249259Sdim public: 764249259Sdim MapHNode(Node *n) : HNode(n) { } 765249259Sdim virtual ~MapHNode(); 766249259Sdim 767249259Sdim static inline bool classof(const HNode *n) { 768249259Sdim return MappingNode::classof(n->_node); 769249259Sdim } 770249259Sdim static inline bool classof(const MapHNode *) { return true; } 771249259Sdim 772263509Sdim typedef llvm::StringMap<HNode*> NameToNode; 773249259Sdim 774249259Sdim bool isValidKey(StringRef key); 775249259Sdim 776249259Sdim NameToNode Mapping; 777249259Sdim llvm::SmallVector<const char*, 6> ValidKeys; 778249259Sdim }; 779249259Sdim 780249259Sdim class SequenceHNode : public HNode { 781249259Sdim public: 782249259Sdim SequenceHNode(Node *n) : HNode(n) { } 783249259Sdim virtual ~SequenceHNode(); 784249259Sdim 785249259Sdim static inline bool classof(const HNode *n) { 786249259Sdim return SequenceNode::classof(n->_node); 787249259Sdim } 788249259Sdim static inline bool classof(const SequenceHNode *) { return true; } 789249259Sdim 790249259Sdim std::vector<HNode*> Entries; 791249259Sdim }; 792249259Sdim 793249259Sdim Input::HNode *createHNodes(Node *node); 794249259Sdim void setError(HNode *hnode, const Twine &message); 795249259Sdim void setError(Node *node, const Twine &message); 796249259Sdim 797249259Sdim 798249259Sdimpublic: 799249259Sdim // These are only used by operator>>. They could be private 800249259Sdim // if those templated things could be made friends. 801249259Sdim bool setCurrentDocument(); 802249259Sdim void nextDocument(); 803249259Sdim 804249259Sdimprivate: 805249259Sdim llvm::SourceMgr SrcMgr; // must be before Strm 806249259Sdim OwningPtr<llvm::yaml::Stream> Strm; 807249259Sdim OwningPtr<HNode> TopNode; 808249259Sdim llvm::error_code EC; 809249259Sdim llvm::BumpPtrAllocator StringAllocator; 810249259Sdim llvm::yaml::document_iterator DocIterator; 811249259Sdim std::vector<bool> BitValuesUsed; 812249259Sdim HNode *CurrentNode; 813249259Sdim bool ScalarMatchFound; 814249259Sdim}; 815249259Sdim 816249259Sdim 817249259Sdim 818249259Sdim 819249259Sdim/// 820249259Sdim/// The Output class is used to generate a yaml document from in-memory structs 821249259Sdim/// and vectors. 822249259Sdim/// 823249259Sdimclass Output : public IO { 824249259Sdimpublic: 825249259Sdim Output(llvm::raw_ostream &, void *Ctxt=NULL); 826249259Sdim virtual ~Output(); 827249259Sdim 828263509Sdim static bool classof(const IO *io) { return io->outputting(); } 829263509Sdim 830263509Sdim virtual bool outputting() const; 831263509Sdim virtual bool mapTag(StringRef, bool); 832249259Sdim virtual void beginMapping(); 833249259Sdim virtual void endMapping(); 834249259Sdim virtual bool preflightKey(const char *key, bool, bool, bool &, void *&); 835249259Sdim virtual void postflightKey(void *); 836249259Sdim virtual unsigned beginSequence(); 837249259Sdim virtual void endSequence(); 838249259Sdim virtual bool preflightElement(unsigned, void *&); 839249259Sdim virtual void postflightElement(void *); 840249259Sdim virtual unsigned beginFlowSequence(); 841249259Sdim virtual bool preflightFlowElement(unsigned, void *&); 842249259Sdim virtual void postflightFlowElement(void *); 843249259Sdim virtual void endFlowSequence(); 844249259Sdim virtual void beginEnumScalar(); 845249259Sdim virtual bool matchEnumScalar(const char*, bool); 846249259Sdim virtual void endEnumScalar(); 847249259Sdim virtual bool beginBitSetScalar(bool &); 848249259Sdim virtual bool bitSetMatch(const char *, bool ); 849249259Sdim virtual void endBitSetScalar(); 850249259Sdim virtual void scalarString(StringRef &); 851249259Sdim virtual void setError(const Twine &message); 852263509Sdim virtual bool canElideEmptySequence(); 853249259Sdimpublic: 854249259Sdim // These are only used by operator<<. They could be private 855249259Sdim // if that templated operator could be made a friend. 856249259Sdim void beginDocuments(); 857249259Sdim bool preflightDocument(unsigned); 858249259Sdim void postflightDocument(); 859249259Sdim void endDocuments(); 860249259Sdim 861249259Sdimprivate: 862249259Sdim void output(StringRef s); 863249259Sdim void outputUpToEndOfLine(StringRef s); 864249259Sdim void newLineCheck(); 865249259Sdim void outputNewLine(); 866249259Sdim void paddedKey(StringRef key); 867249259Sdim 868249259Sdim enum InState { inSeq, inFlowSeq, inMapFirstKey, inMapOtherKey }; 869249259Sdim 870249259Sdim llvm::raw_ostream &Out; 871249259Sdim SmallVector<InState, 8> StateStack; 872249259Sdim int Column; 873249259Sdim int ColumnAtFlowStart; 874249259Sdim bool NeedBitValueComma; 875249259Sdim bool NeedFlowSequenceComma; 876249259Sdim bool EnumerationMatchFound; 877249259Sdim bool NeedsNewLine; 878249259Sdim}; 879249259Sdim 880249259Sdim 881249259Sdim 882249259Sdim 883249259Sdim/// YAML I/O does conversion based on types. But often native data types 884249259Sdim/// are just a typedef of built in intergral types (e.g. int). But the C++ 885249259Sdim/// type matching system sees through the typedef and all the typedefed types 886249259Sdim/// look like a built in type. This will cause the generic YAML I/O conversion 887249259Sdim/// to be used. To provide better control over the YAML conversion, you can 888249259Sdim/// use this macro instead of typedef. It will create a class with one field 889249259Sdim/// and automatic conversion operators to and from the base type. 890249259Sdim/// Based on BOOST_STRONG_TYPEDEF 891249259Sdim#define LLVM_YAML_STRONG_TYPEDEF(_base, _type) \ 892249259Sdim struct _type { \ 893249259Sdim _type() { } \ 894249259Sdim _type(const _base v) : value(v) { } \ 895249259Sdim _type(const _type &v) : value(v.value) {} \ 896249259Sdim _type &operator=(const _type &rhs) { value = rhs.value; return *this; }\ 897249259Sdim _type &operator=(const _base &rhs) { value = rhs; return *this; } \ 898249259Sdim operator const _base & () const { return value; } \ 899249259Sdim bool operator==(const _type &rhs) const { return value == rhs.value; } \ 900249259Sdim bool operator==(const _base &rhs) const { return value == rhs; } \ 901249259Sdim bool operator<(const _type &rhs) const { return value < rhs.value; } \ 902249259Sdim _base value; \ 903249259Sdim }; 904249259Sdim 905249259Sdim 906249259Sdim 907249259Sdim/// 908249259Sdim/// Use these types instead of uintXX_t in any mapping to have 909249259Sdim/// its yaml output formatted as hexadecimal. 910249259Sdim/// 911249259SdimLLVM_YAML_STRONG_TYPEDEF(uint8_t, Hex8) 912249259SdimLLVM_YAML_STRONG_TYPEDEF(uint16_t, Hex16) 913249259SdimLLVM_YAML_STRONG_TYPEDEF(uint32_t, Hex32) 914249259SdimLLVM_YAML_STRONG_TYPEDEF(uint64_t, Hex64) 915249259Sdim 916249259Sdim 917249259Sdimtemplate<> 918249259Sdimstruct ScalarTraits<Hex8> { 919249259Sdim static void output(const Hex8 &, void*, llvm::raw_ostream &); 920249259Sdim static StringRef input(StringRef, void*, Hex8 &); 921249259Sdim}; 922249259Sdim 923249259Sdimtemplate<> 924249259Sdimstruct ScalarTraits<Hex16> { 925249259Sdim static void output(const Hex16 &, void*, llvm::raw_ostream &); 926249259Sdim static StringRef input(StringRef, void*, Hex16 &); 927249259Sdim}; 928249259Sdim 929249259Sdimtemplate<> 930249259Sdimstruct ScalarTraits<Hex32> { 931249259Sdim static void output(const Hex32 &, void*, llvm::raw_ostream &); 932249259Sdim static StringRef input(StringRef, void*, Hex32 &); 933249259Sdim}; 934249259Sdim 935249259Sdimtemplate<> 936249259Sdimstruct ScalarTraits<Hex64> { 937249259Sdim static void output(const Hex64 &, void*, llvm::raw_ostream &); 938249259Sdim static StringRef input(StringRef, void*, Hex64 &); 939249259Sdim}; 940249259Sdim 941249259Sdim 942249259Sdim// Define non-member operator>> so that Input can stream in a document list. 943249259Sdimtemplate <typename T> 944249259Sdiminline 945249259Sdimtypename llvm::enable_if_c<has_DocumentListTraits<T>::value,Input &>::type 946249259Sdimoperator>>(Input &yin, T &docList) { 947249259Sdim int i = 0; 948249259Sdim while ( yin.setCurrentDocument() ) { 949249259Sdim yamlize(yin, DocumentListTraits<T>::element(yin, docList, i), true); 950249259Sdim if ( yin.error() ) 951249259Sdim return yin; 952249259Sdim yin.nextDocument(); 953249259Sdim ++i; 954249259Sdim } 955249259Sdim return yin; 956249259Sdim} 957249259Sdim 958249259Sdim// Define non-member operator>> so that Input can stream in a map as a document. 959249259Sdimtemplate <typename T> 960249259Sdiminline 961249259Sdimtypename llvm::enable_if_c<has_MappingTraits<T>::value,Input &>::type 962249259Sdimoperator>>(Input &yin, T &docMap) { 963249259Sdim yin.setCurrentDocument(); 964249259Sdim yamlize(yin, docMap, true); 965249259Sdim return yin; 966249259Sdim} 967249259Sdim 968249259Sdim// Define non-member operator>> so that Input can stream in a sequence as 969249259Sdim// a document. 970249259Sdimtemplate <typename T> 971249259Sdiminline 972249259Sdimtypename llvm::enable_if_c<has_SequenceTraits<T>::value,Input &>::type 973249259Sdimoperator>>(Input &yin, T &docSeq) { 974263509Sdim if (yin.setCurrentDocument()) 975263509Sdim yamlize(yin, docSeq, true); 976249259Sdim return yin; 977249259Sdim} 978249259Sdim 979249259Sdim// Provide better error message about types missing a trait specialization 980249259Sdimtemplate <typename T> 981249259Sdiminline 982249259Sdimtypename llvm::enable_if_c<missingTraits<T>::value,Input &>::type 983249259Sdimoperator>>(Input &yin, T &docSeq) { 984249259Sdim char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)]; 985249259Sdim return yin; 986249259Sdim} 987249259Sdim 988249259Sdim 989249259Sdim// Define non-member operator<< so that Output can stream out document list. 990249259Sdimtemplate <typename T> 991249259Sdiminline 992249259Sdimtypename llvm::enable_if_c<has_DocumentListTraits<T>::value,Output &>::type 993249259Sdimoperator<<(Output &yout, T &docList) { 994249259Sdim yout.beginDocuments(); 995249259Sdim const size_t count = DocumentListTraits<T>::size(yout, docList); 996249259Sdim for(size_t i=0; i < count; ++i) { 997249259Sdim if ( yout.preflightDocument(i) ) { 998249259Sdim yamlize(yout, DocumentListTraits<T>::element(yout, docList, i), true); 999249259Sdim yout.postflightDocument(); 1000249259Sdim } 1001249259Sdim } 1002249259Sdim yout.endDocuments(); 1003249259Sdim return yout; 1004249259Sdim} 1005249259Sdim 1006249259Sdim// Define non-member operator<< so that Output can stream out a map. 1007249259Sdimtemplate <typename T> 1008249259Sdiminline 1009249259Sdimtypename llvm::enable_if_c<has_MappingTraits<T>::value,Output &>::type 1010249259Sdimoperator<<(Output &yout, T &map) { 1011249259Sdim yout.beginDocuments(); 1012249259Sdim if ( yout.preflightDocument(0) ) { 1013249259Sdim yamlize(yout, map, true); 1014249259Sdim yout.postflightDocument(); 1015249259Sdim } 1016249259Sdim yout.endDocuments(); 1017249259Sdim return yout; 1018249259Sdim} 1019249259Sdim 1020249259Sdim// Define non-member operator<< so that Output can stream out a sequence. 1021249259Sdimtemplate <typename T> 1022249259Sdiminline 1023249259Sdimtypename llvm::enable_if_c<has_SequenceTraits<T>::value,Output &>::type 1024249259Sdimoperator<<(Output &yout, T &seq) { 1025249259Sdim yout.beginDocuments(); 1026249259Sdim if ( yout.preflightDocument(0) ) { 1027249259Sdim yamlize(yout, seq, true); 1028249259Sdim yout.postflightDocument(); 1029249259Sdim } 1030249259Sdim yout.endDocuments(); 1031249259Sdim return yout; 1032249259Sdim} 1033249259Sdim 1034249259Sdim// Provide better error message about types missing a trait specialization 1035249259Sdimtemplate <typename T> 1036249259Sdiminline 1037249259Sdimtypename llvm::enable_if_c<missingTraits<T>::value,Output &>::type 1038249259Sdimoperator<<(Output &yout, T &seq) { 1039249259Sdim char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)]; 1040249259Sdim return yout; 1041249259Sdim} 1042249259Sdim 1043249259Sdim 1044249259Sdim} // namespace yaml 1045249259Sdim} // namespace llvm 1046249259Sdim 1047249259Sdim 1048249259Sdim/// Utility for declaring that a std::vector of a particular type 1049249259Sdim/// should be considered a YAML sequence. 1050249259Sdim#define LLVM_YAML_IS_SEQUENCE_VECTOR(_type) \ 1051249259Sdim namespace llvm { \ 1052249259Sdim namespace yaml { \ 1053249259Sdim template<> \ 1054249259Sdim struct SequenceTraits< std::vector<_type> > { \ 1055249259Sdim static size_t size(IO &io, std::vector<_type> &seq) { \ 1056249259Sdim return seq.size(); \ 1057249259Sdim } \ 1058249259Sdim static _type& element(IO &io, std::vector<_type> &seq, size_t index) {\ 1059249259Sdim if ( index >= seq.size() ) \ 1060249259Sdim seq.resize(index+1); \ 1061249259Sdim return seq[index]; \ 1062249259Sdim } \ 1063249259Sdim }; \ 1064249259Sdim } \ 1065249259Sdim } 1066249259Sdim 1067249259Sdim/// Utility for declaring that a std::vector of a particular type 1068249259Sdim/// should be considered a YAML flow sequence. 1069249259Sdim#define LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(_type) \ 1070249259Sdim namespace llvm { \ 1071249259Sdim namespace yaml { \ 1072249259Sdim template<> \ 1073249259Sdim struct SequenceTraits< std::vector<_type> > { \ 1074249259Sdim static size_t size(IO &io, std::vector<_type> &seq) { \ 1075249259Sdim return seq.size(); \ 1076249259Sdim } \ 1077249259Sdim static _type& element(IO &io, std::vector<_type> &seq, size_t index) {\ 1078249259Sdim if ( index >= seq.size() ) \ 1079249259Sdim seq.resize(index+1); \ 1080249259Sdim return seq[index]; \ 1081249259Sdim } \ 1082249259Sdim static const bool flow = true; \ 1083249259Sdim }; \ 1084249259Sdim } \ 1085249259Sdim } 1086249259Sdim 1087249259Sdim/// Utility for declaring that a std::vector of a particular type 1088249259Sdim/// should be considered a YAML document list. 1089249259Sdim#define LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(_type) \ 1090249259Sdim namespace llvm { \ 1091249259Sdim namespace yaml { \ 1092249259Sdim template<> \ 1093249259Sdim struct DocumentListTraits< std::vector<_type> > { \ 1094249259Sdim static size_t size(IO &io, std::vector<_type> &seq) { \ 1095249259Sdim return seq.size(); \ 1096249259Sdim } \ 1097249259Sdim static _type& element(IO &io, std::vector<_type> &seq, size_t index) {\ 1098249259Sdim if ( index >= seq.size() ) \ 1099249259Sdim seq.resize(index+1); \ 1100249259Sdim return seq[index]; \ 1101249259Sdim } \ 1102249259Sdim }; \ 1103249259Sdim } \ 1104249259Sdim } 1105249259Sdim 1106249259Sdim 1107249259Sdim 1108249259Sdim#endif // LLVM_SUPPORT_YAMLTRAITS_H 1109