X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FSupport%2FYAMLTraits.h;h=c04294a5e87a735b3bf79b3475d60f47d01afab3;hb=00552e3875ee5f382db6c98286a241a7d0efe1b8;hp=d736b2637f1fbf0ad23ddb924659af86c0a38d69;hpb=0b6cb7104b15504cd41f48cc2babcbcee70775f3;p=oota-llvm.git diff --git a/include/llvm/Support/YAMLTraits.h b/include/llvm/Support/YAMLTraits.h index d736b2637f1..c04294a5e87 100644 --- a/include/llvm/Support/YAMLTraits.h +++ b/include/llvm/Support/YAMLTraits.h @@ -24,7 +24,7 @@ #include "llvm/Support/SourceMgr.h" #include "llvm/Support/YAMLParser.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Support/system_error.h" +#include namespace llvm { namespace yaml { @@ -46,6 +46,10 @@ struct MappingTraits { // static void mapping(IO &io, T &fields); // Optionally may provide: // static StringRef validate(IO &io, T &fields); + // + // The optional flow flag will cause generated YAML to use a flow mapping + // (e.g. { a: 0, b: 1 }): + // static const bool flow = true; }; @@ -117,6 +121,35 @@ 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: /// @@ -220,6 +253,26 @@ public: }; +// 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 struct has_MappingTraits @@ -249,7 +302,7 @@ struct has_MappingValidateTraits static double test(...); public: - static bool const value = (sizeof(test >(0)) == 1); + static bool const value = (sizeof(test >(nullptr)) == 1); }; @@ -321,7 +374,7 @@ struct has_DocumentListTraits static double test(...); public: - static bool const value = (sizeof(test >(0)) == 1); + static bool const value = (sizeof(test >(nullptr))==1); }; inline bool isNumber(StringRef S) { @@ -406,6 +459,7 @@ 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 > {}; @@ -445,8 +499,12 @@ public: virtual bool preflightKey(const char*, bool, bool, bool &, void *&) = 0; virtual void postflightKey(void*) = 0; + virtual void beginFlowMapping() = 0; + virtual void endFlowMapping() = 0; + virtual void beginEnumScalar() = 0; virtual bool matchEnumScalar(const char*, bool) = 0; + virtual bool matchEnumFallback() = 0; virtual void endEnumScalar() = 0; virtual bool beginBitSetScalar(bool &) = 0; @@ -454,6 +512,7 @@ public: virtual void endBitSetScalar() = 0; virtual void scalarString(StringRef &, bool) = 0; + virtual void blockScalarString(StringRef &) = 0; virtual void setError(const Twine &) = 0; @@ -472,6 +531,16 @@ public: } } + template + void enumFallback(T &Val) { + if ( matchEnumFallback() ) { + // FIXME: Force integral conversion to allow strong typedefs to convert. + FBT Res = (uint64_t)Val; + yamlize(*this, Res, true); + Val = (uint64_t)Res; + } + } + template void bitSetCase(T &Val, const char* Str, const T ConstVal) { if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) { @@ -487,6 +556,19 @@ public: } } + template + void maskedBitSetCase(T &Val, const char *Str, T ConstVal, T Mask) { + if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal)) + Val = Val | ConstVal; + } + + template + void maskedBitSetCase(T &Val, const char *Str, uint32_t ConstVal, + uint32_t Mask) { + if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal)) + Val = Val | ConstVal; + } + void *getContext(); void setContext(void *); @@ -519,7 +601,7 @@ public: void mapOptional(const char* Key, T& Val, const T& Default) { this->processKeyWithDefault(Key, Val, Default, false); } - + private: template void processKeyWithDefault(const char *Key, Optional &Val, @@ -615,11 +697,32 @@ 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 yamlize(IO &io, T &Val, bool) { - io.beginMapping(); + if (has_FlowTraits>::value) + io.beginFlowMapping(); + else + io.beginMapping(); if (io.outputting()) { StringRef Err = MappingTraits::validate(io, Val); if (!Err.empty()) { @@ -633,15 +736,24 @@ yamlize(IO &io, T &Val, bool) { if (!Err.empty()) io.setError(Err); } - io.endMapping(); + if (has_FlowTraits>::value) + io.endFlowMapping(); + else + io.endMapping(); } template typename std::enable_if::value, void>::type yamlize(IO &io, T &Val, bool) { - io.beginMapping(); - MappingTraits::mapping(io, Val); - io.endMapping(); + if (has_FlowTraits>::value) { + io.beginFlowMapping(); + MappingTraits::mapping(io, Val); + io.endFlowMapping(); + } else { + io.beginMapping(); + MappingTraits::mapping(io, Val); + io.endMapping(); + } } template @@ -693,7 +805,7 @@ struct ScalarTraits { static StringRef input(StringRef, void*, StringRef &); static bool mustQuote(StringRef S) { return needsQuotes(S); } }; - + template<> struct ScalarTraits { static void output(const std::string &, void*, llvm::raw_ostream &); @@ -864,10 +976,10 @@ public: void *Ctxt = nullptr, SourceMgr::DiagHandlerTy DiagHandler = nullptr, void *DiagHandlerCtxt = nullptr); - ~Input(); + ~Input() override; // Check if there was an syntax or semantic error during parsing. - llvm::error_code error(); + std::error_code error(); private: bool outputting() override; @@ -876,6 +988,8 @@ private: void endMapping() override; bool preflightKey(const char *, bool, bool, bool &, void *&) override; void postflightKey(void *) override; + void beginFlowMapping() override; + void endFlowMapping() override; unsigned beginSequence() override; void endSequence() override; bool preflightElement(unsigned index, void *&) override; @@ -886,11 +1000,13 @@ private: void endFlowSequence() override; void beginEnumScalar() override; bool matchEnumScalar(const char*, bool) override; + bool matchEnumFallback() override; void endEnumScalar() override; bool beginBitSetScalar(bool &) override; 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; @@ -922,7 +1038,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: @@ -930,16 +1047,17 @@ private: }; class MapHNode : public HNode { + void anchor() override; + public: MapHNode(Node *n) : HNode(n) { } - virtual ~MapHNode(); static inline bool classof(const HNode *n) { return MappingNode::classof(n->_node); } static inline bool classof(const MapHNode *) { return true; } - typedef llvm::StringMap NameToNode; + typedef llvm::StringMap> NameToNode; bool isValidKey(StringRef key); @@ -948,19 +1066,20 @@ private: }; class SequenceHNode : public HNode { + void anchor() override; + public: SequenceHNode(Node *n) : HNode(n) { } - virtual ~SequenceHNode(); static inline bool classof(const HNode *n) { return SequenceNode::classof(n->_node); } static inline bool classof(const SequenceHNode *) { return true; } - std::vector Entries; + std::vector> Entries; }; - Input::HNode *createHNodes(Node *node); + std::unique_ptr createHNodes(Node *node); void setError(HNode *hnode, const Twine &message); void setError(Node *node, const Twine &message); @@ -969,13 +1088,16 @@ public: // These are only used by operator>>. They could be private // if those templated things could be made friends. bool setCurrentDocument(); - void nextDocument(); + 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; std::unique_ptr TopNode; - llvm::error_code EC; + std::error_code EC; llvm::BumpPtrAllocator StringAllocator; llvm::yaml::document_iterator DocIterator; std::vector BitValuesUsed; @@ -992,8 +1114,8 @@ private: /// class Output : public IO { public: - Output(llvm::raw_ostream &, void *Ctxt=nullptr); - virtual ~Output(); + Output(llvm::raw_ostream &, void *Ctxt = nullptr, int WrapColumn = 70); + ~Output() override; bool outputting() override; bool mapTag(StringRef, bool) override; @@ -1001,6 +1123,8 @@ public: void endMapping() override; bool preflightKey(const char *key, bool, bool, bool &, void *&) override; void postflightKey(void *) override; + void beginFlowMapping() override; + void endFlowMapping() override; unsigned beginSequence() override; void endSequence() override; bool preflightElement(unsigned, void *&) override; @@ -1011,11 +1135,13 @@ public: void endFlowSequence() override; void beginEnumScalar() override; bool matchEnumScalar(const char*, bool) override; + bool matchEnumFallback() override; void endEnumScalar() override; bool beginBitSetScalar(bool &) override; 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: @@ -1032,13 +1158,23 @@ private: void newLineCheck(); void outputNewLine(); void paddedKey(StringRef key); - - enum InState { inSeq, inFlowSeq, inMapFirstKey, inMapOtherKey }; + void flowKey(StringRef Key); + + enum InState { + inSeq, + inFlowSeq, + inMapFirstKey, + inMapOtherKey, + inFlowMapFirstKey, + inFlowMapOtherKey + }; llvm::raw_ostream &Out; + int WrapColumn; SmallVector StateStack; int Column; int ColumnAtFlowStart; + int ColumnAtMapFlowStart; bool NeedBitValueComma; bool NeedFlowSequenceComma; bool EnumerationMatchFound; @@ -1148,6 +1284,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 @@ -1203,6 +1349,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