LLVM API Documentation
00001 //===- llvm/Support/YAMLTraits.h --------------------------------*- C++ -*-===// 00002 // 00003 // The LLVM Linker 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 00010 #ifndef LLVM_SUPPORT_YAMLTRAITS_H 00011 #define LLVM_SUPPORT_YAMLTRAITS_H 00012 00013 00014 #include "llvm/ADT/DenseMap.h" 00015 #include "llvm/ADT/DenseMapInfo.h" 00016 #include "llvm/ADT/Optional.h" 00017 #include "llvm/ADT/SmallVector.h" 00018 #include "llvm/ADT/StringMap.h" 00019 #include "llvm/ADT/StringRef.h" 00020 #include "llvm/ADT/StringSwitch.h" 00021 #include "llvm/ADT/Twine.h" 00022 #include "llvm/Support/Compiler.h" 00023 #include "llvm/Support/Regex.h" 00024 #include "llvm/Support/SourceMgr.h" 00025 #include "llvm/Support/YAMLParser.h" 00026 #include "llvm/Support/raw_ostream.h" 00027 #include <system_error> 00028 00029 namespace llvm { 00030 namespace yaml { 00031 00032 00033 /// This class should be specialized by any type that needs to be converted 00034 /// to/from a YAML mapping. For example: 00035 /// 00036 /// struct MappingTraits<MyStruct> { 00037 /// static void mapping(IO &io, MyStruct &s) { 00038 /// io.mapRequired("name", s.name); 00039 /// io.mapRequired("size", s.size); 00040 /// io.mapOptional("age", s.age); 00041 /// } 00042 /// }; 00043 template<class T> 00044 struct MappingTraits { 00045 // Must provide: 00046 // static void mapping(IO &io, T &fields); 00047 // Optionally may provide: 00048 // static StringRef validate(IO &io, T &fields); 00049 }; 00050 00051 00052 /// This class should be specialized by any integral type that converts 00053 /// to/from a YAML scalar where there is a one-to-one mapping between 00054 /// in-memory values and a string in YAML. For example: 00055 /// 00056 /// struct ScalarEnumerationTraits<Colors> { 00057 /// static void enumeration(IO &io, Colors &value) { 00058 /// io.enumCase(value, "red", cRed); 00059 /// io.enumCase(value, "blue", cBlue); 00060 /// io.enumCase(value, "green", cGreen); 00061 /// } 00062 /// }; 00063 template<typename T> 00064 struct ScalarEnumerationTraits { 00065 // Must provide: 00066 // static void enumeration(IO &io, T &value); 00067 }; 00068 00069 00070 /// This class should be specialized by any integer type that is a union 00071 /// of bit values and the YAML representation is a flow sequence of 00072 /// strings. For example: 00073 /// 00074 /// struct ScalarBitSetTraits<MyFlags> { 00075 /// static void bitset(IO &io, MyFlags &value) { 00076 /// io.bitSetCase(value, "big", flagBig); 00077 /// io.bitSetCase(value, "flat", flagFlat); 00078 /// io.bitSetCase(value, "round", flagRound); 00079 /// } 00080 /// }; 00081 template<typename T> 00082 struct ScalarBitSetTraits { 00083 // Must provide: 00084 // static void bitset(IO &io, T &value); 00085 }; 00086 00087 00088 /// This class should be specialized by type that requires custom conversion 00089 /// to/from a yaml scalar. For example: 00090 /// 00091 /// template<> 00092 /// struct ScalarTraits<MyType> { 00093 /// static void output(const MyType &val, void*, llvm::raw_ostream &out) { 00094 /// // stream out custom formatting 00095 /// out << llvm::format("%x", val); 00096 /// } 00097 /// static StringRef input(StringRef scalar, void*, MyType &value) { 00098 /// // parse scalar and set `value` 00099 /// // return empty string on success, or error string 00100 /// return StringRef(); 00101 /// } 00102 /// static bool mustQuote(StringRef) { return true; } 00103 /// }; 00104 template<typename T> 00105 struct ScalarTraits { 00106 // Must provide: 00107 // 00108 // Function to write the value as a string: 00109 //static void output(const T &value, void *ctxt, llvm::raw_ostream &out); 00110 // 00111 // Function to convert a string to a value. Returns the empty 00112 // StringRef on success or an error string if string is malformed: 00113 //static StringRef input(StringRef scalar, void *ctxt, T &value); 00114 // 00115 // Function to determine if the value should be quoted. 00116 //static bool mustQuote(StringRef); 00117 }; 00118 00119 00120 /// This class should be specialized by any type that needs to be converted 00121 /// to/from a YAML sequence. For example: 00122 /// 00123 /// template<> 00124 /// struct SequenceTraits< std::vector<MyType> > { 00125 /// static size_t size(IO &io, std::vector<MyType> &seq) { 00126 /// return seq.size(); 00127 /// } 00128 /// static MyType& element(IO &, std::vector<MyType> &seq, size_t index) { 00129 /// if ( index >= seq.size() ) 00130 /// seq.resize(index+1); 00131 /// return seq[index]; 00132 /// } 00133 /// }; 00134 template<typename T> 00135 struct SequenceTraits { 00136 // Must provide: 00137 // static size_t size(IO &io, T &seq); 00138 // static T::value_type& element(IO &io, T &seq, size_t index); 00139 // 00140 // The following is option and will cause generated YAML to use 00141 // a flow sequence (e.g. [a,b,c]). 00142 // static const bool flow = true; 00143 }; 00144 00145 00146 /// This class should be specialized by any type that needs to be converted 00147 /// to/from a list of YAML documents. 00148 template<typename T> 00149 struct DocumentListTraits { 00150 // Must provide: 00151 // static size_t size(IO &io, T &seq); 00152 // static T::value_type& element(IO &io, T &seq, size_t index); 00153 }; 00154 00155 00156 // Only used by compiler if both template types are the same 00157 template <typename T, T> 00158 struct SameType; 00159 00160 // Only used for better diagnostics of missing traits 00161 template <typename T> 00162 struct MissingTrait; 00163 00164 00165 00166 // Test if ScalarEnumerationTraits<T> is defined on type T. 00167 template <class T> 00168 struct has_ScalarEnumerationTraits 00169 { 00170 typedef void (*Signature_enumeration)(class IO&, T&); 00171 00172 template <typename U> 00173 static char test(SameType<Signature_enumeration, &U::enumeration>*); 00174 00175 template <typename U> 00176 static double test(...); 00177 00178 public: 00179 static bool const value = 00180 (sizeof(test<ScalarEnumerationTraits<T> >(nullptr)) == 1); 00181 }; 00182 00183 00184 // Test if ScalarBitSetTraits<T> is defined on type T. 00185 template <class T> 00186 struct has_ScalarBitSetTraits 00187 { 00188 typedef void (*Signature_bitset)(class IO&, T&); 00189 00190 template <typename U> 00191 static char test(SameType<Signature_bitset, &U::bitset>*); 00192 00193 template <typename U> 00194 static double test(...); 00195 00196 public: 00197 static bool const value = (sizeof(test<ScalarBitSetTraits<T> >(nullptr)) == 1); 00198 }; 00199 00200 00201 // Test if ScalarTraits<T> is defined on type T. 00202 template <class T> 00203 struct has_ScalarTraits 00204 { 00205 typedef StringRef (*Signature_input)(StringRef, void*, T&); 00206 typedef void (*Signature_output)(const T&, void*, llvm::raw_ostream&); 00207 typedef bool (*Signature_mustQuote)(StringRef); 00208 00209 template <typename U> 00210 static char test(SameType<Signature_input, &U::input> *, 00211 SameType<Signature_output, &U::output> *, 00212 SameType<Signature_mustQuote, &U::mustQuote> *); 00213 00214 template <typename U> 00215 static double test(...); 00216 00217 public: 00218 static bool const value = 00219 (sizeof(test<ScalarTraits<T>>(nullptr, nullptr, nullptr)) == 1); 00220 }; 00221 00222 00223 // Test if MappingTraits<T> is defined on type T. 00224 template <class T> 00225 struct has_MappingTraits 00226 { 00227 typedef void (*Signature_mapping)(class IO&, T&); 00228 00229 template <typename U> 00230 static char test(SameType<Signature_mapping, &U::mapping>*); 00231 00232 template <typename U> 00233 static double test(...); 00234 00235 public: 00236 static bool const value = (sizeof(test<MappingTraits<T> >(nullptr)) == 1); 00237 }; 00238 00239 // Test if MappingTraits<T>::validate() is defined on type T. 00240 template <class T> 00241 struct has_MappingValidateTraits 00242 { 00243 typedef StringRef (*Signature_validate)(class IO&, T&); 00244 00245 template <typename U> 00246 static char test(SameType<Signature_validate, &U::validate>*); 00247 00248 template <typename U> 00249 static double test(...); 00250 00251 public: 00252 static bool const value = (sizeof(test<MappingTraits<T> >(nullptr)) == 1); 00253 }; 00254 00255 00256 00257 // Test if SequenceTraits<T> is defined on type T. 00258 template <class T> 00259 struct has_SequenceMethodTraits 00260 { 00261 typedef size_t (*Signature_size)(class IO&, T&); 00262 00263 template <typename U> 00264 static char test(SameType<Signature_size, &U::size>*); 00265 00266 template <typename U> 00267 static double test(...); 00268 00269 public: 00270 static bool const value = (sizeof(test<SequenceTraits<T> >(nullptr)) == 1); 00271 }; 00272 00273 00274 // has_FlowTraits<int> will cause an error with some compilers because 00275 // it subclasses int. Using this wrapper only instantiates the 00276 // real has_FlowTraits only if the template type is a class. 00277 template <typename T, bool Enabled = std::is_class<T>::value> 00278 class has_FlowTraits 00279 { 00280 public: 00281 static const bool value = false; 00282 }; 00283 00284 // Some older gcc compilers don't support straight forward tests 00285 // for members, so test for ambiguity cause by the base and derived 00286 // classes both defining the member. 00287 template <class T> 00288 struct has_FlowTraits<T, true> 00289 { 00290 struct Fallback { bool flow; }; 00291 struct Derived : T, Fallback { }; 00292 00293 template<typename C> 00294 static char (&f(SameType<bool Fallback::*, &C::flow>*))[1]; 00295 00296 template<typename C> 00297 static char (&f(...))[2]; 00298 00299 public: 00300 static bool const value = sizeof(f<Derived>(nullptr)) == 2; 00301 }; 00302 00303 00304 00305 // Test if SequenceTraits<T> is defined on type T 00306 template<typename T> 00307 struct has_SequenceTraits : public std::integral_constant<bool, 00308 has_SequenceMethodTraits<T>::value > { }; 00309 00310 00311 // Test if DocumentListTraits<T> is defined on type T 00312 template <class T> 00313 struct has_DocumentListTraits 00314 { 00315 typedef size_t (*Signature_size)(class IO&, T&); 00316 00317 template <typename U> 00318 static char test(SameType<Signature_size, &U::size>*); 00319 00320 template <typename U> 00321 static double test(...); 00322 00323 public: 00324 static bool const value = (sizeof(test<DocumentListTraits<T> >(nullptr))==1); 00325 }; 00326 00327 inline bool isNumber(StringRef S) { 00328 static const char OctalChars[] = "01234567"; 00329 if (S.startswith("0") && 00330 S.drop_front().find_first_not_of(OctalChars) == StringRef::npos) 00331 return true; 00332 00333 if (S.startswith("0o") && 00334 S.drop_front(2).find_first_not_of(OctalChars) == StringRef::npos) 00335 return true; 00336 00337 static const char HexChars[] = "0123456789abcdefABCDEF"; 00338 if (S.startswith("0x") && 00339 S.drop_front(2).find_first_not_of(HexChars) == StringRef::npos) 00340 return true; 00341 00342 static const char DecChars[] = "0123456789"; 00343 if (S.find_first_not_of(DecChars) == StringRef::npos) 00344 return true; 00345 00346 if (S.equals(".inf") || S.equals(".Inf") || S.equals(".INF")) 00347 return true; 00348 00349 Regex FloatMatcher("^(\\.[0-9]+|[0-9]+(\\.[0-9]*)?)([eE][-+]?[0-9]+)?$"); 00350 if (FloatMatcher.match(S)) 00351 return true; 00352 00353 return false; 00354 } 00355 00356 inline bool isNumeric(StringRef S) { 00357 if ((S.front() == '-' || S.front() == '+') && isNumber(S.drop_front())) 00358 return true; 00359 00360 if (isNumber(S)) 00361 return true; 00362 00363 if (S.equals(".nan") || S.equals(".NaN") || S.equals(".NAN")) 00364 return true; 00365 00366 return false; 00367 } 00368 00369 inline bool isNull(StringRef S) { 00370 return S.equals("null") || S.equals("Null") || S.equals("NULL") || 00371 S.equals("~"); 00372 } 00373 00374 inline bool isBool(StringRef S) { 00375 return S.equals("true") || S.equals("True") || S.equals("TRUE") || 00376 S.equals("false") || S.equals("False") || S.equals("FALSE"); 00377 } 00378 00379 inline bool needsQuotes(StringRef S) { 00380 if (S.empty()) 00381 return true; 00382 if (isspace(S.front()) || isspace(S.back())) 00383 return true; 00384 if (S.front() == ',') 00385 return true; 00386 00387 static const char ScalarSafeChars[] = 00388 "abcdefghijklmnopqrstuvwxyz" 00389 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-/^., \t"; 00390 if (S.find_first_not_of(ScalarSafeChars) != StringRef::npos) 00391 return true; 00392 00393 if (isNull(S)) 00394 return true; 00395 if (isBool(S)) 00396 return true; 00397 if (isNumeric(S)) 00398 return true; 00399 00400 return false; 00401 } 00402 00403 00404 template<typename T> 00405 struct missingTraits : public std::integral_constant<bool, 00406 !has_ScalarEnumerationTraits<T>::value 00407 && !has_ScalarBitSetTraits<T>::value 00408 && !has_ScalarTraits<T>::value 00409 && !has_MappingTraits<T>::value 00410 && !has_SequenceTraits<T>::value 00411 && !has_DocumentListTraits<T>::value > {}; 00412 00413 template<typename T> 00414 struct validatedMappingTraits : public std::integral_constant<bool, 00415 has_MappingTraits<T>::value 00416 && has_MappingValidateTraits<T>::value> {}; 00417 00418 template<typename T> 00419 struct unvalidatedMappingTraits : public std::integral_constant<bool, 00420 has_MappingTraits<T>::value 00421 && !has_MappingValidateTraits<T>::value> {}; 00422 // Base class for Input and Output. 00423 class IO { 00424 public: 00425 00426 IO(void *Ctxt=nullptr); 00427 virtual ~IO(); 00428 00429 virtual bool outputting() = 0; 00430 00431 virtual unsigned beginSequence() = 0; 00432 virtual bool preflightElement(unsigned, void *&) = 0; 00433 virtual void postflightElement(void*) = 0; 00434 virtual void endSequence() = 0; 00435 virtual bool canElideEmptySequence() = 0; 00436 00437 virtual unsigned beginFlowSequence() = 0; 00438 virtual bool preflightFlowElement(unsigned, void *&) = 0; 00439 virtual void postflightFlowElement(void*) = 0; 00440 virtual void endFlowSequence() = 0; 00441 00442 virtual bool mapTag(StringRef Tag, bool Default=false) = 0; 00443 virtual void beginMapping() = 0; 00444 virtual void endMapping() = 0; 00445 virtual bool preflightKey(const char*, bool, bool, bool &, void *&) = 0; 00446 virtual void postflightKey(void*) = 0; 00447 00448 virtual void beginEnumScalar() = 0; 00449 virtual bool matchEnumScalar(const char*, bool) = 0; 00450 virtual void endEnumScalar() = 0; 00451 00452 virtual bool beginBitSetScalar(bool &) = 0; 00453 virtual bool bitSetMatch(const char*, bool) = 0; 00454 virtual void endBitSetScalar() = 0; 00455 00456 virtual void scalarString(StringRef &, bool) = 0; 00457 00458 virtual void setError(const Twine &) = 0; 00459 00460 template <typename T> 00461 void enumCase(T &Val, const char* Str, const T ConstVal) { 00462 if ( matchEnumScalar(Str, outputting() && Val == ConstVal) ) { 00463 Val = ConstVal; 00464 } 00465 } 00466 00467 // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF 00468 template <typename T> 00469 void enumCase(T &Val, const char* Str, const uint32_t ConstVal) { 00470 if ( matchEnumScalar(Str, outputting() && Val == static_cast<T>(ConstVal)) ) { 00471 Val = ConstVal; 00472 } 00473 } 00474 00475 template <typename T> 00476 void bitSetCase(T &Val, const char* Str, const T ConstVal) { 00477 if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) { 00478 Val = Val | ConstVal; 00479 } 00480 } 00481 00482 // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF 00483 template <typename T> 00484 void bitSetCase(T &Val, const char* Str, const uint32_t ConstVal) { 00485 if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) { 00486 Val = Val | ConstVal; 00487 } 00488 } 00489 00490 template <typename T> 00491 void maskedBitSetCase(T &Val, const char *Str, T ConstVal, T Mask) { 00492 if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal)) 00493 Val = Val | ConstVal; 00494 } 00495 00496 template <typename T> 00497 void maskedBitSetCase(T &Val, const char *Str, uint32_t ConstVal, 00498 uint32_t Mask) { 00499 if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal)) 00500 Val = Val | ConstVal; 00501 } 00502 00503 void *getContext(); 00504 void setContext(void *); 00505 00506 template <typename T> 00507 void mapRequired(const char* Key, T& Val) { 00508 this->processKey(Key, Val, true); 00509 } 00510 00511 template <typename T> 00512 typename std::enable_if<has_SequenceTraits<T>::value,void>::type 00513 mapOptional(const char* Key, T& Val) { 00514 // omit key/value instead of outputting empty sequence 00515 if ( this->canElideEmptySequence() && !(Val.begin() != Val.end()) ) 00516 return; 00517 this->processKey(Key, Val, false); 00518 } 00519 00520 template <typename T> 00521 void mapOptional(const char* Key, Optional<T> &Val) { 00522 processKeyWithDefault(Key, Val, Optional<T>(), /*Required=*/false); 00523 } 00524 00525 template <typename T> 00526 typename std::enable_if<!has_SequenceTraits<T>::value,void>::type 00527 mapOptional(const char* Key, T& Val) { 00528 this->processKey(Key, Val, false); 00529 } 00530 00531 template <typename T> 00532 void mapOptional(const char* Key, T& Val, const T& Default) { 00533 this->processKeyWithDefault(Key, Val, Default, false); 00534 } 00535 00536 private: 00537 template <typename T> 00538 void processKeyWithDefault(const char *Key, Optional<T> &Val, 00539 const Optional<T> &DefaultValue, bool Required) { 00540 assert(DefaultValue.hasValue() == false && 00541 "Optional<T> shouldn't have a value!"); 00542 void *SaveInfo; 00543 bool UseDefault; 00544 const bool sameAsDefault = outputting() && !Val.hasValue(); 00545 if (!outputting() && !Val.hasValue()) 00546 Val = T(); 00547 if (this->preflightKey(Key, Required, sameAsDefault, UseDefault, 00548 SaveInfo)) { 00549 yamlize(*this, Val.getValue(), Required); 00550 this->postflightKey(SaveInfo); 00551 } else { 00552 if (UseDefault) 00553 Val = DefaultValue; 00554 } 00555 } 00556 00557 template <typename T> 00558 void processKeyWithDefault(const char *Key, T &Val, const T& DefaultValue, 00559 bool Required) { 00560 void *SaveInfo; 00561 bool UseDefault; 00562 const bool sameAsDefault = outputting() && Val == DefaultValue; 00563 if ( this->preflightKey(Key, Required, sameAsDefault, UseDefault, 00564 SaveInfo) ) { 00565 yamlize(*this, Val, Required); 00566 this->postflightKey(SaveInfo); 00567 } 00568 else { 00569 if ( UseDefault ) 00570 Val = DefaultValue; 00571 } 00572 } 00573 00574 template <typename T> 00575 void processKey(const char *Key, T &Val, bool Required) { 00576 void *SaveInfo; 00577 bool UseDefault; 00578 if ( this->preflightKey(Key, Required, false, UseDefault, SaveInfo) ) { 00579 yamlize(*this, Val, Required); 00580 this->postflightKey(SaveInfo); 00581 } 00582 } 00583 00584 private: 00585 void *Ctxt; 00586 }; 00587 00588 00589 00590 template<typename T> 00591 typename std::enable_if<has_ScalarEnumerationTraits<T>::value,void>::type 00592 yamlize(IO &io, T &Val, bool) { 00593 io.beginEnumScalar(); 00594 ScalarEnumerationTraits<T>::enumeration(io, Val); 00595 io.endEnumScalar(); 00596 } 00597 00598 template<typename T> 00599 typename std::enable_if<has_ScalarBitSetTraits<T>::value,void>::type 00600 yamlize(IO &io, T &Val, bool) { 00601 bool DoClear; 00602 if ( io.beginBitSetScalar(DoClear) ) { 00603 if ( DoClear ) 00604 Val = static_cast<T>(0); 00605 ScalarBitSetTraits<T>::bitset(io, Val); 00606 io.endBitSetScalar(); 00607 } 00608 } 00609 00610 00611 template<typename T> 00612 typename std::enable_if<has_ScalarTraits<T>::value,void>::type 00613 yamlize(IO &io, T &Val, bool) { 00614 if ( io.outputting() ) { 00615 std::string Storage; 00616 llvm::raw_string_ostream Buffer(Storage); 00617 ScalarTraits<T>::output(Val, io.getContext(), Buffer); 00618 StringRef Str = Buffer.str(); 00619 io.scalarString(Str, ScalarTraits<T>::mustQuote(Str)); 00620 } 00621 else { 00622 StringRef Str; 00623 io.scalarString(Str, ScalarTraits<T>::mustQuote(Str)); 00624 StringRef Result = ScalarTraits<T>::input(Str, io.getContext(), Val); 00625 if ( !Result.empty() ) { 00626 io.setError(llvm::Twine(Result)); 00627 } 00628 } 00629 } 00630 00631 00632 template<typename T> 00633 typename std::enable_if<validatedMappingTraits<T>::value, void>::type 00634 yamlize(IO &io, T &Val, bool) { 00635 io.beginMapping(); 00636 if (io.outputting()) { 00637 StringRef Err = MappingTraits<T>::validate(io, Val); 00638 if (!Err.empty()) { 00639 llvm::errs() << Err << "\n"; 00640 assert(Err.empty() && "invalid struct trying to be written as yaml"); 00641 } 00642 } 00643 MappingTraits<T>::mapping(io, Val); 00644 if (!io.outputting()) { 00645 StringRef Err = MappingTraits<T>::validate(io, Val); 00646 if (!Err.empty()) 00647 io.setError(Err); 00648 } 00649 io.endMapping(); 00650 } 00651 00652 template<typename T> 00653 typename std::enable_if<unvalidatedMappingTraits<T>::value, void>::type 00654 yamlize(IO &io, T &Val, bool) { 00655 io.beginMapping(); 00656 MappingTraits<T>::mapping(io, Val); 00657 io.endMapping(); 00658 } 00659 00660 template<typename T> 00661 typename std::enable_if<missingTraits<T>::value, void>::type 00662 yamlize(IO &io, T &Val, bool) { 00663 char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)]; 00664 } 00665 00666 template<typename T> 00667 typename std::enable_if<has_SequenceTraits<T>::value,void>::type 00668 yamlize(IO &io, T &Seq, bool) { 00669 if ( has_FlowTraits< SequenceTraits<T> >::value ) { 00670 unsigned incnt = io.beginFlowSequence(); 00671 unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt; 00672 for(unsigned i=0; i < count; ++i) { 00673 void *SaveInfo; 00674 if ( io.preflightFlowElement(i, SaveInfo) ) { 00675 yamlize(io, SequenceTraits<T>::element(io, Seq, i), true); 00676 io.postflightFlowElement(SaveInfo); 00677 } 00678 } 00679 io.endFlowSequence(); 00680 } 00681 else { 00682 unsigned incnt = io.beginSequence(); 00683 unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt; 00684 for(unsigned i=0; i < count; ++i) { 00685 void *SaveInfo; 00686 if ( io.preflightElement(i, SaveInfo) ) { 00687 yamlize(io, SequenceTraits<T>::element(io, Seq, i), true); 00688 io.postflightElement(SaveInfo); 00689 } 00690 } 00691 io.endSequence(); 00692 } 00693 } 00694 00695 00696 template<> 00697 struct ScalarTraits<bool> { 00698 static void output(const bool &, void*, llvm::raw_ostream &); 00699 static StringRef input(StringRef, void*, bool &); 00700 static bool mustQuote(StringRef) { return false; } 00701 }; 00702 00703 template<> 00704 struct ScalarTraits<StringRef> { 00705 static void output(const StringRef &, void*, llvm::raw_ostream &); 00706 static StringRef input(StringRef, void*, StringRef &); 00707 static bool mustQuote(StringRef S) { return needsQuotes(S); } 00708 }; 00709 00710 template<> 00711 struct ScalarTraits<std::string> { 00712 static void output(const std::string &, void*, llvm::raw_ostream &); 00713 static StringRef input(StringRef, void*, std::string &); 00714 static bool mustQuote(StringRef S) { return needsQuotes(S); } 00715 }; 00716 00717 template<> 00718 struct ScalarTraits<uint8_t> { 00719 static void output(const uint8_t &, void*, llvm::raw_ostream &); 00720 static StringRef input(StringRef, void*, uint8_t &); 00721 static bool mustQuote(StringRef) { return false; } 00722 }; 00723 00724 template<> 00725 struct ScalarTraits<uint16_t> { 00726 static void output(const uint16_t &, void*, llvm::raw_ostream &); 00727 static StringRef input(StringRef, void*, uint16_t &); 00728 static bool mustQuote(StringRef) { return false; } 00729 }; 00730 00731 template<> 00732 struct ScalarTraits<uint32_t> { 00733 static void output(const uint32_t &, void*, llvm::raw_ostream &); 00734 static StringRef input(StringRef, void*, uint32_t &); 00735 static bool mustQuote(StringRef) { return false; } 00736 }; 00737 00738 template<> 00739 struct ScalarTraits<uint64_t> { 00740 static void output(const uint64_t &, void*, llvm::raw_ostream &); 00741 static StringRef input(StringRef, void*, uint64_t &); 00742 static bool mustQuote(StringRef) { return false; } 00743 }; 00744 00745 template<> 00746 struct ScalarTraits<int8_t> { 00747 static void output(const int8_t &, void*, llvm::raw_ostream &); 00748 static StringRef input(StringRef, void*, int8_t &); 00749 static bool mustQuote(StringRef) { return false; } 00750 }; 00751 00752 template<> 00753 struct ScalarTraits<int16_t> { 00754 static void output(const int16_t &, void*, llvm::raw_ostream &); 00755 static StringRef input(StringRef, void*, int16_t &); 00756 static bool mustQuote(StringRef) { return false; } 00757 }; 00758 00759 template<> 00760 struct ScalarTraits<int32_t> { 00761 static void output(const int32_t &, void*, llvm::raw_ostream &); 00762 static StringRef input(StringRef, void*, int32_t &); 00763 static bool mustQuote(StringRef) { return false; } 00764 }; 00765 00766 template<> 00767 struct ScalarTraits<int64_t> { 00768 static void output(const int64_t &, void*, llvm::raw_ostream &); 00769 static StringRef input(StringRef, void*, int64_t &); 00770 static bool mustQuote(StringRef) { return false; } 00771 }; 00772 00773 template<> 00774 struct ScalarTraits<float> { 00775 static void output(const float &, void*, llvm::raw_ostream &); 00776 static StringRef input(StringRef, void*, float &); 00777 static bool mustQuote(StringRef) { return false; } 00778 }; 00779 00780 template<> 00781 struct ScalarTraits<double> { 00782 static void output(const double &, void*, llvm::raw_ostream &); 00783 static StringRef input(StringRef, void*, double &); 00784 static bool mustQuote(StringRef) { return false; } 00785 }; 00786 00787 00788 00789 // Utility for use within MappingTraits<>::mapping() method 00790 // to [de]normalize an object for use with YAML conversion. 00791 template <typename TNorm, typename TFinal> 00792 struct MappingNormalization { 00793 MappingNormalization(IO &i_o, TFinal &Obj) 00794 : io(i_o), BufPtr(nullptr), Result(Obj) { 00795 if ( io.outputting() ) { 00796 BufPtr = new (&Buffer) TNorm(io, Obj); 00797 } 00798 else { 00799 BufPtr = new (&Buffer) TNorm(io); 00800 } 00801 } 00802 00803 ~MappingNormalization() { 00804 if ( ! io.outputting() ) { 00805 Result = BufPtr->denormalize(io); 00806 } 00807 BufPtr->~TNorm(); 00808 } 00809 00810 TNorm* operator->() { return BufPtr; } 00811 00812 private: 00813 typedef llvm::AlignedCharArrayUnion<TNorm> Storage; 00814 00815 Storage Buffer; 00816 IO &io; 00817 TNorm *BufPtr; 00818 TFinal &Result; 00819 }; 00820 00821 00822 00823 // Utility for use within MappingTraits<>::mapping() method 00824 // to [de]normalize an object for use with YAML conversion. 00825 template <typename TNorm, typename TFinal> 00826 struct MappingNormalizationHeap { 00827 MappingNormalizationHeap(IO &i_o, TFinal &Obj) 00828 : io(i_o), BufPtr(NULL), Result(Obj) { 00829 if ( io.outputting() ) { 00830 BufPtr = new (&Buffer) TNorm(io, Obj); 00831 } 00832 else { 00833 BufPtr = new TNorm(io); 00834 } 00835 } 00836 00837 ~MappingNormalizationHeap() { 00838 if ( io.outputting() ) { 00839 BufPtr->~TNorm(); 00840 } 00841 else { 00842 Result = BufPtr->denormalize(io); 00843 } 00844 } 00845 00846 TNorm* operator->() { return BufPtr; } 00847 00848 private: 00849 typedef llvm::AlignedCharArrayUnion<TNorm> Storage; 00850 00851 Storage Buffer; 00852 IO &io; 00853 TNorm *BufPtr; 00854 TFinal &Result; 00855 }; 00856 00857 00858 00859 /// 00860 /// The Input class is used to parse a yaml document into in-memory structs 00861 /// and vectors. 00862 /// 00863 /// It works by using YAMLParser to do a syntax parse of the entire yaml 00864 /// document, then the Input class builds a graph of HNodes which wraps 00865 /// each yaml Node. The extra layer is buffering. The low level yaml 00866 /// parser only lets you look at each node once. The buffering layer lets 00867 /// you search and interate multiple times. This is necessary because 00868 /// the mapRequired() method calls may not be in the same order 00869 /// as the keys in the document. 00870 /// 00871 class Input : public IO { 00872 public: 00873 // Construct a yaml Input object from a StringRef and optional 00874 // user-data. The DiagHandler can be specified to provide 00875 // alternative error reporting. 00876 Input(StringRef InputContent, 00877 void *Ctxt = nullptr, 00878 SourceMgr::DiagHandlerTy DiagHandler = nullptr, 00879 void *DiagHandlerCtxt = nullptr); 00880 ~Input(); 00881 00882 // Check if there was an syntax or semantic error during parsing. 00883 std::error_code error(); 00884 00885 private: 00886 bool outputting() override; 00887 bool mapTag(StringRef, bool) override; 00888 void beginMapping() override; 00889 void endMapping() override; 00890 bool preflightKey(const char *, bool, bool, bool &, void *&) override; 00891 void postflightKey(void *) override; 00892 unsigned beginSequence() override; 00893 void endSequence() override; 00894 bool preflightElement(unsigned index, void *&) override; 00895 void postflightElement(void *) override; 00896 unsigned beginFlowSequence() override; 00897 bool preflightFlowElement(unsigned , void *&) override; 00898 void postflightFlowElement(void *) override; 00899 void endFlowSequence() override; 00900 void beginEnumScalar() override; 00901 bool matchEnumScalar(const char*, bool) override; 00902 void endEnumScalar() override; 00903 bool beginBitSetScalar(bool &) override; 00904 bool bitSetMatch(const char *, bool ) override; 00905 void endBitSetScalar() override; 00906 void scalarString(StringRef &, bool) override; 00907 void setError(const Twine &message) override; 00908 bool canElideEmptySequence() override; 00909 00910 class HNode { 00911 virtual void anchor(); 00912 public: 00913 HNode(Node *n) : _node(n) { } 00914 virtual ~HNode() { } 00915 static inline bool classof(const HNode *) { return true; } 00916 00917 Node *_node; 00918 }; 00919 00920 class EmptyHNode : public HNode { 00921 void anchor() override; 00922 public: 00923 EmptyHNode(Node *n) : HNode(n) { } 00924 static inline bool classof(const HNode *n) { 00925 return NullNode::classof(n->_node); 00926 } 00927 static inline bool classof(const EmptyHNode *) { return true; } 00928 }; 00929 00930 class ScalarHNode : public HNode { 00931 void anchor() override; 00932 public: 00933 ScalarHNode(Node *n, StringRef s) : HNode(n), _value(s) { } 00934 00935 StringRef value() const { return _value; } 00936 00937 static inline bool classof(const HNode *n) { 00938 return ScalarNode::classof(n->_node); 00939 } 00940 static inline bool classof(const ScalarHNode *) { return true; } 00941 protected: 00942 StringRef _value; 00943 }; 00944 00945 class MapHNode : public HNode { 00946 virtual void anchor(); 00947 00948 public: 00949 MapHNode(Node *n) : HNode(n) { } 00950 00951 static inline bool classof(const HNode *n) { 00952 return MappingNode::classof(n->_node); 00953 } 00954 static inline bool classof(const MapHNode *) { return true; } 00955 00956 typedef llvm::StringMap<std::unique_ptr<HNode>> NameToNode; 00957 00958 bool isValidKey(StringRef key); 00959 00960 NameToNode Mapping; 00961 llvm::SmallVector<const char*, 6> ValidKeys; 00962 }; 00963 00964 class SequenceHNode : public HNode { 00965 virtual void anchor(); 00966 00967 public: 00968 SequenceHNode(Node *n) : HNode(n) { } 00969 00970 static inline bool classof(const HNode *n) { 00971 return SequenceNode::classof(n->_node); 00972 } 00973 static inline bool classof(const SequenceHNode *) { return true; } 00974 00975 std::vector<std::unique_ptr<HNode>> Entries; 00976 }; 00977 00978 std::unique_ptr<Input::HNode> createHNodes(Node *node); 00979 void setError(HNode *hnode, const Twine &message); 00980 void setError(Node *node, const Twine &message); 00981 00982 00983 public: 00984 // These are only used by operator>>. They could be private 00985 // if those templated things could be made friends. 00986 bool setCurrentDocument(); 00987 bool nextDocument(); 00988 00989 private: 00990 llvm::SourceMgr SrcMgr; // must be before Strm 00991 std::unique_ptr<llvm::yaml::Stream> Strm; 00992 std::unique_ptr<HNode> TopNode; 00993 std::error_code EC; 00994 llvm::BumpPtrAllocator StringAllocator; 00995 llvm::yaml::document_iterator DocIterator; 00996 std::vector<bool> BitValuesUsed; 00997 HNode *CurrentNode; 00998 bool ScalarMatchFound; 00999 }; 01000 01001 01002 01003 01004 /// 01005 /// The Output class is used to generate a yaml document from in-memory structs 01006 /// and vectors. 01007 /// 01008 class Output : public IO { 01009 public: 01010 Output(llvm::raw_ostream &, void *Ctxt=nullptr); 01011 virtual ~Output(); 01012 01013 bool outputting() override; 01014 bool mapTag(StringRef, bool) override; 01015 void beginMapping() override; 01016 void endMapping() override; 01017 bool preflightKey(const char *key, bool, bool, bool &, void *&) override; 01018 void postflightKey(void *) override; 01019 unsigned beginSequence() override; 01020 void endSequence() override; 01021 bool preflightElement(unsigned, void *&) override; 01022 void postflightElement(void *) override; 01023 unsigned beginFlowSequence() override; 01024 bool preflightFlowElement(unsigned, void *&) override; 01025 void postflightFlowElement(void *) override; 01026 void endFlowSequence() override; 01027 void beginEnumScalar() override; 01028 bool matchEnumScalar(const char*, bool) override; 01029 void endEnumScalar() override; 01030 bool beginBitSetScalar(bool &) override; 01031 bool bitSetMatch(const char *, bool ) override; 01032 void endBitSetScalar() override; 01033 void scalarString(StringRef &, bool) override; 01034 void setError(const Twine &message) override; 01035 bool canElideEmptySequence() override; 01036 public: 01037 // These are only used by operator<<. They could be private 01038 // if that templated operator could be made a friend. 01039 void beginDocuments(); 01040 bool preflightDocument(unsigned); 01041 void postflightDocument(); 01042 void endDocuments(); 01043 01044 private: 01045 void output(StringRef s); 01046 void outputUpToEndOfLine(StringRef s); 01047 void newLineCheck(); 01048 void outputNewLine(); 01049 void paddedKey(StringRef key); 01050 01051 enum InState { inSeq, inFlowSeq, inMapFirstKey, inMapOtherKey }; 01052 01053 llvm::raw_ostream &Out; 01054 SmallVector<InState, 8> StateStack; 01055 int Column; 01056 int ColumnAtFlowStart; 01057 bool NeedBitValueComma; 01058 bool NeedFlowSequenceComma; 01059 bool EnumerationMatchFound; 01060 bool NeedsNewLine; 01061 }; 01062 01063 01064 01065 01066 /// YAML I/O does conversion based on types. But often native data types 01067 /// are just a typedef of built in intergral types (e.g. int). But the C++ 01068 /// type matching system sees through the typedef and all the typedefed types 01069 /// look like a built in type. This will cause the generic YAML I/O conversion 01070 /// to be used. To provide better control over the YAML conversion, you can 01071 /// use this macro instead of typedef. It will create a class with one field 01072 /// and automatic conversion operators to and from the base type. 01073 /// Based on BOOST_STRONG_TYPEDEF 01074 #define LLVM_YAML_STRONG_TYPEDEF(_base, _type) \ 01075 struct _type { \ 01076 _type() { } \ 01077 _type(const _base v) : value(v) { } \ 01078 _type(const _type &v) : value(v.value) {} \ 01079 _type &operator=(const _type &rhs) { value = rhs.value; return *this; }\ 01080 _type &operator=(const _base &rhs) { value = rhs; return *this; } \ 01081 operator const _base & () const { return value; } \ 01082 bool operator==(const _type &rhs) const { return value == rhs.value; } \ 01083 bool operator==(const _base &rhs) const { return value == rhs; } \ 01084 bool operator<(const _type &rhs) const { return value < rhs.value; } \ 01085 _base value; \ 01086 }; 01087 01088 01089 01090 /// 01091 /// Use these types instead of uintXX_t in any mapping to have 01092 /// its yaml output formatted as hexadecimal. 01093 /// 01094 LLVM_YAML_STRONG_TYPEDEF(uint8_t, Hex8) 01095 LLVM_YAML_STRONG_TYPEDEF(uint16_t, Hex16) 01096 LLVM_YAML_STRONG_TYPEDEF(uint32_t, Hex32) 01097 LLVM_YAML_STRONG_TYPEDEF(uint64_t, Hex64) 01098 01099 01100 template<> 01101 struct ScalarTraits<Hex8> { 01102 static void output(const Hex8 &, void*, llvm::raw_ostream &); 01103 static StringRef input(StringRef, void*, Hex8 &); 01104 static bool mustQuote(StringRef) { return false; } 01105 }; 01106 01107 template<> 01108 struct ScalarTraits<Hex16> { 01109 static void output(const Hex16 &, void*, llvm::raw_ostream &); 01110 static StringRef input(StringRef, void*, Hex16 &); 01111 static bool mustQuote(StringRef) { return false; } 01112 }; 01113 01114 template<> 01115 struct ScalarTraits<Hex32> { 01116 static void output(const Hex32 &, void*, llvm::raw_ostream &); 01117 static StringRef input(StringRef, void*, Hex32 &); 01118 static bool mustQuote(StringRef) { return false; } 01119 }; 01120 01121 template<> 01122 struct ScalarTraits<Hex64> { 01123 static void output(const Hex64 &, void*, llvm::raw_ostream &); 01124 static StringRef input(StringRef, void*, Hex64 &); 01125 static bool mustQuote(StringRef) { return false; } 01126 }; 01127 01128 01129 // Define non-member operator>> so that Input can stream in a document list. 01130 template <typename T> 01131 inline 01132 typename std::enable_if<has_DocumentListTraits<T>::value, Input &>::type 01133 operator>>(Input &yin, T &docList) { 01134 int i = 0; 01135 while ( yin.setCurrentDocument() ) { 01136 yamlize(yin, DocumentListTraits<T>::element(yin, docList, i), true); 01137 if ( yin.error() ) 01138 return yin; 01139 yin.nextDocument(); 01140 ++i; 01141 } 01142 return yin; 01143 } 01144 01145 // Define non-member operator>> so that Input can stream in a map as a document. 01146 template <typename T> 01147 inline 01148 typename std::enable_if<has_MappingTraits<T>::value, Input &>::type 01149 operator>>(Input &yin, T &docMap) { 01150 yin.setCurrentDocument(); 01151 yamlize(yin, docMap, true); 01152 return yin; 01153 } 01154 01155 // Define non-member operator>> so that Input can stream in a sequence as 01156 // a document. 01157 template <typename T> 01158 inline 01159 typename std::enable_if<has_SequenceTraits<T>::value, Input &>::type 01160 operator>>(Input &yin, T &docSeq) { 01161 if (yin.setCurrentDocument()) 01162 yamlize(yin, docSeq, true); 01163 return yin; 01164 } 01165 01166 // Provide better error message about types missing a trait specialization 01167 template <typename T> 01168 inline 01169 typename std::enable_if<missingTraits<T>::value, Input &>::type 01170 operator>>(Input &yin, T &docSeq) { 01171 char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)]; 01172 return yin; 01173 } 01174 01175 01176 // Define non-member operator<< so that Output can stream out document list. 01177 template <typename T> 01178 inline 01179 typename std::enable_if<has_DocumentListTraits<T>::value, Output &>::type 01180 operator<<(Output &yout, T &docList) { 01181 yout.beginDocuments(); 01182 const size_t count = DocumentListTraits<T>::size(yout, docList); 01183 for(size_t i=0; i < count; ++i) { 01184 if ( yout.preflightDocument(i) ) { 01185 yamlize(yout, DocumentListTraits<T>::element(yout, docList, i), true); 01186 yout.postflightDocument(); 01187 } 01188 } 01189 yout.endDocuments(); 01190 return yout; 01191 } 01192 01193 // Define non-member operator<< so that Output can stream out a map. 01194 template <typename T> 01195 inline 01196 typename std::enable_if<has_MappingTraits<T>::value, Output &>::type 01197 operator<<(Output &yout, T &map) { 01198 yout.beginDocuments(); 01199 if ( yout.preflightDocument(0) ) { 01200 yamlize(yout, map, true); 01201 yout.postflightDocument(); 01202 } 01203 yout.endDocuments(); 01204 return yout; 01205 } 01206 01207 // Define non-member operator<< so that Output can stream out a sequence. 01208 template <typename T> 01209 inline 01210 typename std::enable_if<has_SequenceTraits<T>::value, Output &>::type 01211 operator<<(Output &yout, T &seq) { 01212 yout.beginDocuments(); 01213 if ( yout.preflightDocument(0) ) { 01214 yamlize(yout, seq, true); 01215 yout.postflightDocument(); 01216 } 01217 yout.endDocuments(); 01218 return yout; 01219 } 01220 01221 // Provide better error message about types missing a trait specialization 01222 template <typename T> 01223 inline 01224 typename std::enable_if<missingTraits<T>::value, Output &>::type 01225 operator<<(Output &yout, T &seq) { 01226 char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)]; 01227 return yout; 01228 } 01229 01230 01231 } // namespace yaml 01232 } // namespace llvm 01233 01234 01235 /// Utility for declaring that a std::vector of a particular type 01236 /// should be considered a YAML sequence. 01237 #define LLVM_YAML_IS_SEQUENCE_VECTOR(_type) \ 01238 namespace llvm { \ 01239 namespace yaml { \ 01240 template<> \ 01241 struct SequenceTraits< std::vector<_type> > { \ 01242 static size_t size(IO &io, std::vector<_type> &seq) { \ 01243 return seq.size(); \ 01244 } \ 01245 static _type& element(IO &io, std::vector<_type> &seq, size_t index) {\ 01246 if ( index >= seq.size() ) \ 01247 seq.resize(index+1); \ 01248 return seq[index]; \ 01249 } \ 01250 }; \ 01251 } \ 01252 } 01253 01254 /// Utility for declaring that a std::vector of a particular type 01255 /// should be considered a YAML flow sequence. 01256 #define LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(_type) \ 01257 namespace llvm { \ 01258 namespace yaml { \ 01259 template<> \ 01260 struct SequenceTraits< std::vector<_type> > { \ 01261 static size_t size(IO &io, std::vector<_type> &seq) { \ 01262 return seq.size(); \ 01263 } \ 01264 static _type& element(IO &io, std::vector<_type> &seq, size_t index) {\ 01265 (void)flow; /* Remove this workaround after PR17897 is fixed */ \ 01266 if ( index >= seq.size() ) \ 01267 seq.resize(index+1); \ 01268 return seq[index]; \ 01269 } \ 01270 static const bool flow = true; \ 01271 }; \ 01272 } \ 01273 } 01274 01275 /// Utility for declaring that a std::vector of a particular type 01276 /// should be considered a YAML document list. 01277 #define LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(_type) \ 01278 namespace llvm { \ 01279 namespace yaml { \ 01280 template<> \ 01281 struct DocumentListTraits< std::vector<_type> > { \ 01282 static size_t size(IO &io, std::vector<_type> &seq) { \ 01283 return seq.size(); \ 01284 } \ 01285 static _type& element(IO &io, std::vector<_type> &seq, size_t index) {\ 01286 if ( index >= seq.size() ) \ 01287 seq.resize(index+1); \ 01288 return seq[index]; \ 01289 } \ 01290 }; \ 01291 } \ 01292 } 01293 01294 01295 01296 #endif // LLVM_SUPPORT_YAMLTRAITS_H