LLVM API Documentation

YAMLTraits.h
Go to the documentation of this file.
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