X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FSupport%2FYAMLTraits.h;h=fb2badfd93bade61790aba33ba2422906c209159;hb=e36c14fbedbfccf86f2b9632bbfddf281bb95068;hp=b48c58e43522e7b6aff6607fd6f0e9be08b4c6d5;hpb=c41c3a4c3b999a05e6d04e41d3d0153bc2aca056;p=oota-llvm.git diff --git a/include/llvm/Support/YAMLTraits.h b/include/llvm/Support/YAMLTraits.h index b48c58e4352..fb2badfd93b 100644 --- a/include/llvm/Support/YAMLTraits.h +++ b/include/llvm/Support/YAMLTraits.h @@ -10,7 +10,6 @@ #ifndef LLVM_SUPPORT_YAMLTRAITS_H #define LLVM_SUPPORT_YAMLTRAITS_H - #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMapInfo.h" #include "llvm/ADT/Optional.h" @@ -29,7 +28,6 @@ namespace llvm { namespace yaml { - /// This class should be specialized by any type that needs to be converted /// to/from a YAML mapping. For example: /// @@ -52,7 +50,6 @@ struct MappingTraits { // static const bool flow = true; }; - /// This class should be specialized by any integral type that converts /// to/from a YAML scalar where there is a one-to-one mapping between /// in-memory values and a string in YAML. For example: @@ -70,7 +67,6 @@ struct ScalarEnumerationTraits { // static void enumeration(IO &io, T &value); }; - /// This class should be specialized by any integer type that is a union /// of bit values and the YAML representation is a flow sequence of /// strings. For example: @@ -88,7 +84,6 @@ struct ScalarBitSetTraits { // static void bitset(IO &io, T &value); }; - /// This class should be specialized by type that requires custom conversion /// to/from a yaml scalar. For example: /// @@ -121,6 +116,34 @@ struct ScalarTraits { }; +/// This class should be specialized by type that requires custom conversion +/// to/from a YAML literal block scalar. For example: +/// +/// template <> +/// struct BlockScalarTraits { +/// static void output(const MyType &Value, void*, llvm::raw_ostream &Out) +/// { +/// // stream out custom formatting +/// Out << Val; +/// } +/// static StringRef input(StringRef Scalar, void*, MyType &Value) { +/// // parse scalar and set `value` +/// // return empty string on success, or error string +/// return StringRef(); +/// } +/// }; +template +struct BlockScalarTraits { + // Must provide: + // + // Function to write the value as a string: + // static void output(const T &Value, void *ctx, llvm::raw_ostream &Out); + // + // Function to convert a string to a value. Returns the empty + // StringRef on success or an error string if string is malformed: + // static StringRef input(StringRef Scalar, void *ctxt, T &Value); +}; + /// This class should be specialized by any type that needs to be converted /// to/from a YAML sequence. For example: /// @@ -146,7 +169,6 @@ struct SequenceTraits { // static const bool flow = true; }; - /// This class should be specialized by any type that needs to be converted /// to/from a list of YAML documents. template @@ -156,7 +178,6 @@ struct DocumentListTraits { // static T::value_type& element(IO &io, T &seq, size_t index); }; - // Only used by compiler if both template types are the same template struct SameType; @@ -165,8 +186,6 @@ struct SameType; template struct MissingTrait; - - // Test if ScalarEnumerationTraits is defined on type T. template struct has_ScalarEnumerationTraits @@ -184,7 +203,6 @@ public: (sizeof(test >(nullptr)) == 1); }; - // Test if ScalarBitSetTraits is defined on type T. template struct has_ScalarBitSetTraits @@ -201,7 +219,6 @@ public: static bool const value = (sizeof(test >(nullptr)) == 1); }; - // Test if ScalarTraits is defined on type T. template struct has_ScalarTraits @@ -223,6 +240,24 @@ public: (sizeof(test>(nullptr, nullptr, nullptr)) == 1); }; +// Test if BlockScalarTraits is defined on type T. +template +struct has_BlockScalarTraits +{ + typedef StringRef (*Signature_input)(StringRef, void *, T &); + typedef void (*Signature_output)(const T &, void *, llvm::raw_ostream &); + + template + static char test(SameType *, + SameType *); + + template + static double test(...); + +public: + static bool const value = + (sizeof(test>(nullptr, nullptr)) == 1); +}; // Test if MappingTraits is defined on type T. template @@ -256,8 +291,6 @@ public: static bool const value = (sizeof(test >(nullptr)) == 1); }; - - // Test if SequenceTraits is defined on type T. template struct has_SequenceMethodTraits @@ -274,7 +307,6 @@ public: static bool const value = (sizeof(test >(nullptr)) == 1); }; - // has_FlowTraits will cause an error with some compilers because // it subclasses int. Using this wrapper only instantiates the // real has_FlowTraits only if the template type is a class. @@ -304,14 +336,11 @@ public: static bool const value = sizeof(f(nullptr)) == 2; }; - - // Test if SequenceTraits is defined on type T template struct has_SequenceTraits : public std::integral_constant::value > { }; - // Test if DocumentListTraits is defined on type T template struct has_DocumentListTraits @@ -404,12 +433,12 @@ inline bool needsQuotes(StringRef S) { return false; } - template struct missingTraits : public std::integral_constant::value && !has_ScalarBitSetTraits::value && !has_ScalarTraits::value + && !has_BlockScalarTraits::value && !has_MappingTraits::value && !has_SequenceTraits::value && !has_DocumentListTraits::value > {}; @@ -462,6 +491,7 @@ public: virtual void endBitSetScalar() = 0; virtual void scalarString(StringRef &, bool) = 0; + virtual void blockScalarString(StringRef &) = 0; virtual void setError(const Twine &) = 0; @@ -603,8 +633,6 @@ private: void *Ctxt; }; - - template typename std::enable_if::value,void>::type yamlize(IO &io, T &Val, bool) { @@ -625,7 +653,6 @@ yamlize(IO &io, T &Val, bool) { } } - template typename std::enable_if::value,void>::type yamlize(IO &io, T &Val, bool) { @@ -646,6 +673,24 @@ yamlize(IO &io, T &Val, bool) { } } +template +typename std::enable_if::value, void>::type +yamlize(IO &YamlIO, T &Val, bool) { + if (YamlIO.outputting()) { + std::string Storage; + llvm::raw_string_ostream Buffer(Storage); + BlockScalarTraits::output(Val, YamlIO.getContext(), Buffer); + StringRef Str = Buffer.str(); + YamlIO.blockScalarString(Str); + } else { + StringRef Str; + YamlIO.blockScalarString(Str); + StringRef Result = + BlockScalarTraits::input(Str, YamlIO.getContext(), Val); + if (!Result.empty()) + YamlIO.setError(llvm::Twine(Result)); + } +} template typename std::enable_if::value, void>::type @@ -722,7 +767,6 @@ yamlize(IO &io, T &Seq, bool) { } } - template<> struct ScalarTraits { static void output(const bool &, void*, llvm::raw_ostream &); @@ -814,8 +858,6 @@ struct ScalarTraits { static bool mustQuote(StringRef) { return false; } }; - - // Utility for use within MappingTraits<>::mapping() method // to [de]normalize an object for use with YAML conversion. template @@ -848,14 +890,12 @@ private: TFinal &Result; }; - - // Utility for use within MappingTraits<>::mapping() method // to [de]normalize an object for use with YAML conversion. template struct MappingNormalizationHeap { MappingNormalizationHeap(IO &i_o, TFinal &Obj) - : io(i_o), BufPtr(NULL), Result(Obj) { + : io(i_o), BufPtr(nullptr), Result(Obj) { if ( io.outputting() ) { BufPtr = new (&Buffer) TNorm(io, Obj); } @@ -884,8 +924,6 @@ private: TFinal &Result; }; - - /// /// The Input class is used to parse a yaml document into in-memory structs /// and vectors. @@ -937,6 +975,7 @@ private: bool bitSetMatch(const char *, bool ) override; void endBitSetScalar() override; void scalarString(StringRef &, bool) override; + void blockScalarString(StringRef &) override; void setError(const Twine &message) override; bool canElideEmptySequence() override; @@ -968,7 +1007,8 @@ private: StringRef value() const { return _value; } static inline bool classof(const HNode *n) { - return ScalarNode::classof(n->_node); + return ScalarNode::classof(n->_node) || + BlockScalarNode::classof(n->_node); } static inline bool classof(const ScalarHNode *) { return true; } protected: @@ -1012,13 +1052,15 @@ private: void setError(HNode *hnode, const Twine &message); void setError(Node *node, const Twine &message); - public: // These are only used by operator>>. They could be private // if those templated things could be made friends. bool setCurrentDocument(); bool nextDocument(); + /// Returns the current node that's being parsed by the YAML Parser. + const Node *getCurrentNode() const; + private: llvm::SourceMgr SrcMgr; // must be before Strm std::unique_ptr Strm; @@ -1031,16 +1073,13 @@ private: bool ScalarMatchFound; }; - - - /// /// The Output class is used to generate a yaml document from in-memory structs /// and vectors. /// class Output : public IO { public: - Output(llvm::raw_ostream &, void *Ctxt=nullptr); + Output(llvm::raw_ostream &, void *Ctxt = nullptr, int WrapColumn = 70); ~Output() override; bool outputting() override; @@ -1067,6 +1106,7 @@ public: bool bitSetMatch(const char *, bool ) override; void endBitSetScalar() override; void scalarString(StringRef &, bool) override; + void blockScalarString(StringRef &) override; void setError(const Twine &message) override; bool canElideEmptySequence() override; public: @@ -1095,6 +1135,7 @@ private: }; llvm::raw_ostream &Out; + int WrapColumn; SmallVector StateStack; int Column; int ColumnAtFlowStart; @@ -1105,9 +1146,6 @@ private: bool NeedsNewLine; }; - - - /// YAML I/O does conversion based on types. But often native data types /// are just a typedef of built in intergral types (e.g. int). But the C++ /// type matching system sees through the typedef and all the typedefed types @@ -1130,8 +1168,6 @@ private: _base value; \ }; - - /// /// Use these types instead of uintXX_t in any mapping to have /// its yaml output formatted as hexadecimal. @@ -1141,7 +1177,6 @@ LLVM_YAML_STRONG_TYPEDEF(uint16_t, Hex16) LLVM_YAML_STRONG_TYPEDEF(uint32_t, Hex32) LLVM_YAML_STRONG_TYPEDEF(uint64_t, Hex64) - template<> struct ScalarTraits { static void output(const Hex8 &, void*, llvm::raw_ostream &); @@ -1170,7 +1205,6 @@ struct ScalarTraits { static bool mustQuote(StringRef) { return false; } }; - // Define non-member operator>> so that Input can stream in a document list. template inline @@ -1208,6 +1242,16 @@ operator>>(Input &yin, T &docSeq) { return yin; } +// Define non-member operator>> so that Input can stream in a block scalar. +template +inline +typename std::enable_if::value, Input &>::type +operator>>(Input &In, T &Val) { + if (In.setCurrentDocument()) + yamlize(In, Val, true); + return In; +} + // Provide better error message about types missing a trait specialization template inline @@ -1217,7 +1261,6 @@ operator>>(Input &yin, T &docSeq) { return yin; } - // Define non-member operator<< so that Output can stream out document list. template inline @@ -1263,6 +1306,20 @@ operator<<(Output &yout, T &seq) { return yout; } +// Define non-member operator<< so that Output can stream out a block scalar. +template +inline +typename std::enable_if::value, Output &>::type +operator<<(Output &Out, T &Val) { + Out.beginDocuments(); + if (Out.preflightDocument(0)) { + yamlize(Out, Val, true); + Out.postflightDocument(); + } + Out.endDocuments(); + return Out; +} + // Provide better error message about types missing a trait specialization template inline @@ -1272,11 +1329,9 @@ operator<<(Output &yout, T &seq) { return yout; } - } // namespace yaml } // namespace llvm - /// Utility for declaring that a std::vector of a particular type /// should be considered a YAML sequence. #define LLVM_YAML_IS_SEQUENCE_VECTOR(_type) \ @@ -1336,6 +1391,4 @@ operator<<(Output &yout, T &seq) { } \ } - - #endif // LLVM_SUPPORT_YAMLTRAITS_H