summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/include/llvm/Support/YAMLTraits.h
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/include/llvm/Support/YAMLTraits.h')
-rw-r--r--contrib/llvm/include/llvm/Support/YAMLTraits.h543
1 files changed, 372 insertions, 171 deletions
diff --git a/contrib/llvm/include/llvm/Support/YAMLTraits.h b/contrib/llvm/include/llvm/Support/YAMLTraits.h
index bc3fa8a..cbba9c0 100644
--- a/contrib/llvm/include/llvm/Support/YAMLTraits.h
+++ b/contrib/llvm/include/llvm/Support/YAMLTraits.h
@@ -14,19 +14,30 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Twine.h"
-#include "llvm/Support/Compiler.h"
+#include "llvm/Support/AlignOf.h"
+#include "llvm/Support/Allocator.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/YAMLParser.h"
#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <cctype>
+#include <cstddef>
+#include <cstdint>
+#include <memory>
+#include <new>
+#include <string>
#include <system_error>
+#include <type_traits>
+#include <vector>
namespace llvm {
namespace yaml {
+struct EmptyContext {};
+
/// This class should be specialized by any type that needs to be converted
/// to/from a YAML mapping. For example:
///
@@ -49,6 +60,28 @@ struct MappingTraits {
// static const bool flow = true;
};
+/// This class is similar to MappingTraits<T> but allows you to pass in
+/// additional context for each map operation. For example:
+///
+/// struct MappingContextTraits<MyStruct, MyContext> {
+/// static void mapping(IO &io, MyStruct &s, MyContext &c) {
+/// io.mapRequired("name", s.name);
+/// io.mapRequired("size", s.size);
+/// io.mapOptional("age", s.age);
+/// ++c.TimesMapped;
+/// }
+/// };
+template <class T, class Context> struct MappingContextTraits {
+ // Must provide:
+ // static void mapping(IO &io, T &fields, Context &Ctx);
+ // Optionally may provide:
+ // static StringRef validate(IO &io, T &fields, Context &Ctx);
+ //
+ // The optional flow flag will cause generated YAML to use a flow mapping
+ // (e.g. { a: 0, b: 1 }):
+ // 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:
@@ -114,7 +147,6 @@ struct ScalarTraits {
//static bool mustQuote(StringRef);
};
-
/// This class should be specialized by type that requires custom conversion
/// to/from a YAML literal block scalar. For example:
///
@@ -147,7 +179,7 @@ struct BlockScalarTraits {
/// to/from a YAML sequence. For example:
///
/// template<>
-/// struct SequenceTraits< std::vector<MyType> > {
+/// struct SequenceTraits< std::vector<MyType>> {
/// static size_t size(IO &io, std::vector<MyType> &seq) {
/// return seq.size();
/// }
@@ -177,9 +209,14 @@ 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 <typename T, T>
-struct SameType;
+/// This class should be specialized by any type that needs to be converted
+/// to/from a YAML mapping in the case where the names of the keys are not known
+/// in advance, e.g. a string map.
+template <typename T>
+struct CustomMappingTraits {
+ // static void inputOne(IO &io, StringRef key, T &elem);
+ // static void output(IO &io, T &elem);
+};
// Only used for better diagnostics of missing traits
template <typename T>
@@ -199,7 +236,7 @@ struct has_ScalarEnumerationTraits
public:
static bool const value =
- (sizeof(test<ScalarEnumerationTraits<T> >(nullptr)) == 1);
+ (sizeof(test<ScalarEnumerationTraits<T>>(nullptr)) == 1);
};
// Test if ScalarBitSetTraits<T> is defined on type T.
@@ -215,7 +252,7 @@ struct has_ScalarBitSetTraits
static double test(...);
public:
- static bool const value = (sizeof(test<ScalarBitSetTraits<T> >(nullptr)) == 1);
+ static bool const value = (sizeof(test<ScalarBitSetTraits<T>>(nullptr)) == 1);
};
// Test if ScalarTraits<T> is defined on type T.
@@ -258,11 +295,9 @@ public:
(sizeof(test<BlockScalarTraits<T>>(nullptr, nullptr)) == 1);
};
-// Test if MappingTraits<T> is defined on type T.
-template <class T>
-struct has_MappingTraits
-{
- typedef void (*Signature_mapping)(class IO&, T&);
+// Test if MappingContextTraits<T> is defined on type T.
+template <class T, class Context> struct has_MappingTraits {
+ typedef void (*Signature_mapping)(class IO &, T &, Context &);
template <typename U>
static char test(SameType<Signature_mapping, &U::mapping>*);
@@ -271,14 +306,26 @@ struct has_MappingTraits
static double test(...);
public:
- static bool const value = (sizeof(test<MappingTraits<T> >(nullptr)) == 1);
+ static bool const value =
+ (sizeof(test<MappingContextTraits<T, Context>>(nullptr)) == 1);
};
-// Test if MappingTraits<T>::validate() is defined on type T.
-template <class T>
-struct has_MappingValidateTraits
-{
- typedef StringRef (*Signature_validate)(class IO&, T&);
+// Test if MappingTraits<T> is defined on type T.
+template <class T> struct has_MappingTraits<T, EmptyContext> {
+ typedef void (*Signature_mapping)(class IO &, T &);
+
+ template <typename U>
+ static char test(SameType<Signature_mapping, &U::mapping> *);
+
+ template <typename U> static double test(...);
+
+public:
+ static bool const value = (sizeof(test<MappingTraits<T>>(nullptr)) == 1);
+};
+
+// Test if MappingContextTraits<T>::validate() is defined on type T.
+template <class T, class Context> struct has_MappingValidateTraits {
+ typedef StringRef (*Signature_validate)(class IO &, T &, Context &);
template <typename U>
static char test(SameType<Signature_validate, &U::validate>*);
@@ -287,7 +334,21 @@ struct has_MappingValidateTraits
static double test(...);
public:
- static bool const value = (sizeof(test<MappingTraits<T> >(nullptr)) == 1);
+ static bool const value =
+ (sizeof(test<MappingContextTraits<T, Context>>(nullptr)) == 1);
+};
+
+// Test if MappingTraits<T>::validate() is defined on type T.
+template <class T> struct has_MappingValidateTraits<T, EmptyContext> {
+ typedef StringRef (*Signature_validate)(class IO &, T &);
+
+ template <typename U>
+ static char test(SameType<Signature_validate, &U::validate> *);
+
+ template <typename U> static double test(...);
+
+public:
+ static bool const value = (sizeof(test<MappingTraits<T>>(nullptr)) == 1);
};
// Test if SequenceTraits<T> is defined on type T.
@@ -303,7 +364,24 @@ struct has_SequenceMethodTraits
static double test(...);
public:
- static bool const value = (sizeof(test<SequenceTraits<T> >(nullptr)) == 1);
+ static bool const value = (sizeof(test<SequenceTraits<T>>(nullptr)) == 1);
+};
+
+// Test if CustomMappingTraits<T> is defined on type T.
+template <class T>
+struct has_CustomMappingTraits
+{
+ typedef void (*Signature_input)(IO &io, StringRef key, T &v);
+
+ template <typename U>
+ static char test(SameType<Signature_input, &U::inputOne>*);
+
+ template <typename U>
+ static double test(...);
+
+public:
+ static bool const value =
+ (sizeof(test<CustomMappingTraits<T>>(nullptr)) == 1);
};
// has_FlowTraits<int> will cause an error with some compilers because
@@ -353,7 +431,7 @@ struct has_DocumentListTraits
static double test(...);
public:
- static bool const value = (sizeof(test<DocumentListTraits<T> >(nullptr))==1);
+ static bool const value = (sizeof(test<DocumentListTraits<T>>(nullptr))==1);
};
inline bool isNumber(StringRef S) {
@@ -432,29 +510,33 @@ inline bool needsQuotes(StringRef S) {
return false;
}
-template<typename T>
-struct missingTraits : public std::integral_constant<bool,
- !has_ScalarEnumerationTraits<T>::value
- && !has_ScalarBitSetTraits<T>::value
- && !has_ScalarTraits<T>::value
- && !has_BlockScalarTraits<T>::value
- && !has_MappingTraits<T>::value
- && !has_SequenceTraits<T>::value
- && !has_DocumentListTraits<T>::value > {};
-
-template<typename T>
-struct validatedMappingTraits : public std::integral_constant<bool,
- has_MappingTraits<T>::value
- && has_MappingValidateTraits<T>::value> {};
+template <typename T, typename Context>
+struct missingTraits
+ : public std::integral_constant<bool,
+ !has_ScalarEnumerationTraits<T>::value &&
+ !has_ScalarBitSetTraits<T>::value &&
+ !has_ScalarTraits<T>::value &&
+ !has_BlockScalarTraits<T>::value &&
+ !has_MappingTraits<T, Context>::value &&
+ !has_SequenceTraits<T>::value &&
+ !has_CustomMappingTraits<T>::value &&
+ !has_DocumentListTraits<T>::value> {};
+
+template <typename T, typename Context>
+struct validatedMappingTraits
+ : public std::integral_constant<
+ bool, has_MappingTraits<T, Context>::value &&
+ has_MappingValidateTraits<T, Context>::value> {};
+
+template <typename T, typename Context>
+struct unvalidatedMappingTraits
+ : public std::integral_constant<
+ bool, has_MappingTraits<T, Context>::value &&
+ !has_MappingValidateTraits<T, Context>::value> {};
-template<typename T>
-struct unvalidatedMappingTraits : public std::integral_constant<bool,
- has_MappingTraits<T>::value
- && !has_MappingValidateTraits<T>::value> {};
// Base class for Input and Output.
class IO {
public:
-
IO(void *Ctxt=nullptr);
virtual ~IO();
@@ -476,6 +558,7 @@ public:
virtual void endMapping() = 0;
virtual bool preflightKey(const char*, bool, bool, bool &, void *&) = 0;
virtual void postflightKey(void*) = 0;
+ virtual std::vector<StringRef> keys() = 0;
virtual void beginFlowMapping() = 0;
virtual void endFlowMapping() = 0;
@@ -512,9 +595,10 @@ public:
template <typename FBT, typename T>
void enumFallback(T &Val) {
if (matchEnumFallback()) {
+ EmptyContext Context;
// FIXME: Force integral conversion to allow strong typedefs to convert.
FBT Res = static_cast<typename FBT::BaseType>(Val);
- yamlize(*this, Res, true);
+ yamlize(*this, Res, true, Context);
Val = static_cast<T>(static_cast<typename FBT::BaseType>(Res));
}
}
@@ -550,40 +634,58 @@ public:
void *getContext();
void setContext(void *);
- template <typename T>
- void mapRequired(const char* Key, T& Val) {
- this->processKey(Key, Val, true);
+ template <typename T> void mapRequired(const char *Key, T &Val) {
+ EmptyContext Ctx;
+ this->processKey(Key, Val, true, Ctx);
+ }
+ template <typename T, typename Context>
+ void mapRequired(const char *Key, T &Val, Context &Ctx) {
+ this->processKey(Key, Val, true, Ctx);
+ }
+
+ template <typename T> void mapOptional(const char *Key, T &Val) {
+ EmptyContext Ctx;
+ mapOptionalWithContext(Key, Val, Ctx);
}
template <typename T>
- typename std::enable_if<has_SequenceTraits<T>::value,void>::type
- mapOptional(const char* Key, T& Val) {
+ void mapOptional(const char *Key, T &Val, const T &Default) {
+ EmptyContext Ctx;
+ mapOptionalWithContext(Key, Val, Default, Ctx);
+ }
+
+ template <typename T, typename Context>
+ typename std::enable_if<has_SequenceTraits<T>::value, void>::type
+ mapOptionalWithContext(const char *Key, T &Val, Context &Ctx) {
// omit key/value instead of outputting empty sequence
- if ( this->canElideEmptySequence() && !(Val.begin() != Val.end()) )
+ if (this->canElideEmptySequence() && !(Val.begin() != Val.end()))
return;
- this->processKey(Key, Val, false);
+ this->processKey(Key, Val, false, Ctx);
}
- template <typename T>
- void mapOptional(const char* Key, Optional<T> &Val) {
- processKeyWithDefault(Key, Val, Optional<T>(), /*Required=*/false);
+ template <typename T, typename Context>
+ void mapOptionalWithContext(const char *Key, Optional<T> &Val, Context &Ctx) {
+ this->processKeyWithDefault(Key, Val, Optional<T>(), /*Required=*/false,
+ Ctx);
}
- template <typename T>
- typename std::enable_if<!has_SequenceTraits<T>::value,void>::type
- mapOptional(const char* Key, T& Val) {
- this->processKey(Key, Val, false);
+ template <typename T, typename Context>
+ typename std::enable_if<!has_SequenceTraits<T>::value, void>::type
+ mapOptionalWithContext(const char *Key, T &Val, Context &Ctx) {
+ this->processKey(Key, Val, false, Ctx);
}
- template <typename T>
- void mapOptional(const char* Key, T& Val, const T& Default) {
- this->processKeyWithDefault(Key, Val, Default, false);
+ template <typename T, typename Context>
+ void mapOptionalWithContext(const char *Key, T &Val, const T &Default,
+ Context &Ctx) {
+ this->processKeyWithDefault(Key, Val, Default, false, Ctx);
}
private:
- template <typename T>
+ template <typename T, typename Context>
void processKeyWithDefault(const char *Key, Optional<T> &Val,
- const Optional<T> &DefaultValue, bool Required) {
+ const Optional<T> &DefaultValue, bool Required,
+ Context &Ctx) {
assert(DefaultValue.hasValue() == false &&
"Optional<T> shouldn't have a value!");
void *SaveInfo;
@@ -593,7 +695,7 @@ private:
Val = T();
if (this->preflightKey(Key, Required, sameAsDefault, UseDefault,
SaveInfo)) {
- yamlize(*this, Val.getValue(), Required);
+ yamlize(*this, Val.getValue(), Required, Ctx);
this->postflightKey(SaveInfo);
} else {
if (UseDefault)
@@ -601,15 +703,15 @@ private:
}
}
- template <typename T>
- void processKeyWithDefault(const char *Key, T &Val, const T& DefaultValue,
- bool Required) {
+ template <typename T, typename Context>
+ void processKeyWithDefault(const char *Key, T &Val, const T &DefaultValue,
+ bool Required, Context &Ctx) {
void *SaveInfo;
bool UseDefault;
const bool sameAsDefault = outputting() && Val == DefaultValue;
if ( this->preflightKey(Key, Required, sameAsDefault, UseDefault,
SaveInfo) ) {
- yamlize(*this, Val, Required);
+ yamlize(*this, Val, Required, Ctx);
this->postflightKey(SaveInfo);
}
else {
@@ -618,12 +720,12 @@ private:
}
}
- template <typename T>
- void processKey(const char *Key, T &Val, bool Required) {
+ template <typename T, typename Context>
+ void processKey(const char *Key, T &Val, bool Required, Context &Ctx) {
void *SaveInfo;
bool UseDefault;
if ( this->preflightKey(Key, Required, false, UseDefault, SaveInfo) ) {
- yamlize(*this, Val, Required);
+ yamlize(*this, Val, Required, Ctx);
this->postflightKey(SaveInfo);
}
}
@@ -632,17 +734,30 @@ private:
void *Ctxt;
};
-template<typename T>
-typename std::enable_if<has_ScalarEnumerationTraits<T>::value,void>::type
-yamlize(IO &io, T &Val, bool) {
+namespace detail {
+
+template <typename T, typename Context>
+void doMapping(IO &io, T &Val, Context &Ctx) {
+ MappingContextTraits<T, Context>::mapping(io, Val, Ctx);
+}
+
+template <typename T> void doMapping(IO &io, T &Val, EmptyContext &Ctx) {
+ MappingTraits<T>::mapping(io, Val);
+}
+
+} // end namespace detail
+
+template <typename T>
+typename std::enable_if<has_ScalarEnumerationTraits<T>::value, void>::type
+yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
io.beginEnumScalar();
ScalarEnumerationTraits<T>::enumeration(io, Val);
io.endEnumScalar();
}
-template<typename T>
-typename std::enable_if<has_ScalarBitSetTraits<T>::value,void>::type
-yamlize(IO &io, T &Val, bool) {
+template <typename T>
+typename std::enable_if<has_ScalarBitSetTraits<T>::value, void>::type
+yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
bool DoClear;
if ( io.beginBitSetScalar(DoClear) ) {
if ( DoClear )
@@ -652,9 +767,9 @@ yamlize(IO &io, T &Val, bool) {
}
}
-template<typename T>
-typename std::enable_if<has_ScalarTraits<T>::value,void>::type
-yamlize(IO &io, T &Val, bool) {
+template <typename T>
+typename std::enable_if<has_ScalarTraits<T>::value, void>::type
+yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
if ( io.outputting() ) {
std::string Storage;
llvm::raw_string_ostream Buffer(Storage);
@@ -674,7 +789,7 @@ yamlize(IO &io, T &Val, bool) {
template <typename T>
typename std::enable_if<has_BlockScalarTraits<T>::value, void>::type
-yamlize(IO &YamlIO, T &Val, bool) {
+yamlize(IO &YamlIO, T &Val, bool, EmptyContext &Ctx) {
if (YamlIO.outputting()) {
std::string Storage;
llvm::raw_string_ostream Buffer(Storage);
@@ -691,9 +806,9 @@ yamlize(IO &YamlIO, T &Val, bool) {
}
}
-template<typename T>
-typename std::enable_if<validatedMappingTraits<T>::value, void>::type
-yamlize(IO &io, T &Val, bool) {
+template <typename T, typename Context>
+typename std::enable_if<validatedMappingTraits<T, Context>::value, void>::type
+yamlize(IO &io, T &Val, bool, Context &Ctx) {
if (has_FlowTraits<MappingTraits<T>>::value)
io.beginFlowMapping();
else
@@ -705,7 +820,7 @@ yamlize(IO &io, T &Val, bool) {
assert(Err.empty() && "invalid struct trying to be written as yaml");
}
}
- MappingTraits<T>::mapping(io, Val);
+ detail::doMapping(io, Val, Ctx);
if (!io.outputting()) {
StringRef Err = MappingTraits<T>::validate(io, Val);
if (!Err.empty())
@@ -717,36 +832,51 @@ yamlize(IO &io, T &Val, bool) {
io.endMapping();
}
-template<typename T>
-typename std::enable_if<unvalidatedMappingTraits<T>::value, void>::type
-yamlize(IO &io, T &Val, bool) {
+template <typename T, typename Context>
+typename std::enable_if<unvalidatedMappingTraits<T, Context>::value, void>::type
+yamlize(IO &io, T &Val, bool, Context &Ctx) {
if (has_FlowTraits<MappingTraits<T>>::value) {
io.beginFlowMapping();
- MappingTraits<T>::mapping(io, Val);
+ detail::doMapping(io, Val, Ctx);
io.endFlowMapping();
} else {
io.beginMapping();
- MappingTraits<T>::mapping(io, Val);
+ detail::doMapping(io, Val, Ctx);
io.endMapping();
}
}
-template<typename T>
-typename std::enable_if<missingTraits<T>::value, void>::type
-yamlize(IO &io, T &Val, bool) {
+template <typename T>
+typename std::enable_if<has_CustomMappingTraits<T>::value, void>::type
+yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
+ if ( io.outputting() ) {
+ io.beginMapping();
+ CustomMappingTraits<T>::output(io, Val);
+ io.endMapping();
+ } else {
+ io.beginMapping();
+ for (StringRef key : io.keys())
+ CustomMappingTraits<T>::inputOne(io, key, Val);
+ io.endMapping();
+ }
+}
+
+template <typename T>
+typename std::enable_if<missingTraits<T, EmptyContext>::value, void>::type
+yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
}
-template<typename T>
-typename std::enable_if<has_SequenceTraits<T>::value,void>::type
-yamlize(IO &io, T &Seq, bool) {
+template <typename T, typename Context>
+typename std::enable_if<has_SequenceTraits<T>::value, void>::type
+yamlize(IO &io, T &Seq, bool, Context &Ctx) {
if ( has_FlowTraits< SequenceTraits<T> >::value ) {
unsigned incnt = io.beginFlowSequence();
unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt;
for(unsigned i=0; i < count; ++i) {
void *SaveInfo;
if ( io.preflightFlowElement(i, SaveInfo) ) {
- yamlize(io, SequenceTraits<T>::element(io, Seq, i), true);
+ yamlize(io, SequenceTraits<T>::element(io, Seq, i), true, Ctx);
io.postflightFlowElement(SaveInfo);
}
}
@@ -758,7 +888,7 @@ yamlize(IO &io, T &Seq, bool) {
for(unsigned i=0; i < count; ++i) {
void *SaveInfo;
if ( io.preflightElement(i, SaveInfo) ) {
- yamlize(io, SequenceTraits<T>::element(io, Seq, i), true);
+ yamlize(io, SequenceTraits<T>::element(io, Seq, i), true, Ctx);
io.postflightElement(SaveInfo);
}
}
@@ -871,6 +1001,7 @@ struct ScalarTraits<support::detail::packed_endian_specific_integral<
llvm::raw_ostream &Stream) {
ScalarTraits<value_type>::output(static_cast<value_type>(E), Ctx, Stream);
}
+
static StringRef input(StringRef Str, void *Ctx, endian_type &E) {
value_type V;
auto R = ScalarTraits<value_type>::input(Str, Ctx, V);
@@ -986,6 +1117,7 @@ private:
void endMapping() override;
bool preflightKey(const char *, bool, bool, bool &, void *&) override;
void postflightKey(void *) override;
+ std::vector<StringRef> keys() override;
void beginFlowMapping() override;
void endFlowMapping() override;
unsigned beginSequence() override;
@@ -1010,9 +1142,11 @@ private:
class HNode {
virtual void anchor();
+
public:
HNode(Node *n) : _node(n) { }
- virtual ~HNode() { }
+ virtual ~HNode() = default;
+
static inline bool classof(const HNode *) { return true; }
Node *_node;
@@ -1020,16 +1154,20 @@ private:
class EmptyHNode : public HNode {
void anchor() override;
+
public:
EmptyHNode(Node *n) : HNode(n) { }
+
static inline bool classof(const HNode *n) {
return NullNode::classof(n->_node);
}
+
static inline bool classof(const EmptyHNode *) { return true; }
};
class ScalarHNode : public HNode {
void anchor() override;
+
public:
ScalarHNode(Node *n, StringRef s) : HNode(n), _value(s) { }
@@ -1039,7 +1177,9 @@ private:
return ScalarNode::classof(n->_node) ||
BlockScalarNode::classof(n->_node);
}
+
static inline bool classof(const ScalarHNode *) { return true; }
+
protected:
StringRef _value;
};
@@ -1053,14 +1193,13 @@ private:
static inline bool classof(const HNode *n) {
return MappingNode::classof(n->_node);
}
+
static inline bool classof(const MapHNode *) { return true; }
typedef llvm::StringMap<std::unique_ptr<HNode>> NameToNode;
- bool isValidKey(StringRef key);
-
NameToNode Mapping;
- llvm::SmallVector<const char*, 6> ValidKeys;
+ llvm::SmallVector<std::string, 6> ValidKeys;
};
class SequenceHNode : public HNode {
@@ -1072,6 +1211,7 @@ private:
static inline bool classof(const HNode *n) {
return SequenceNode::classof(n->_node);
}
+
static inline bool classof(const SequenceHNode *) { return true; }
std::vector<std::unique_ptr<HNode>> Entries;
@@ -1117,6 +1257,7 @@ public:
void endMapping() override;
bool preflightKey(const char *key, bool, bool, bool &, void *&) override;
void postflightKey(void *) override;
+ std::vector<StringRef> keys() override;
void beginFlowMapping() override;
void endFlowMapping() override;
unsigned beginSequence() override;
@@ -1138,7 +1279,7 @@ public:
void blockScalarString(StringRef &) override;
void setError(const Twine &message) override;
bool canElideEmptySequence() override;
-public:
+
// These are only used by operator<<. They could be private
// if that templated operator could be made a friend.
void beginDocuments();
@@ -1185,10 +1326,10 @@ private:
/// Based on BOOST_STRONG_TYPEDEF
#define LLVM_YAML_STRONG_TYPEDEF(_base, _type) \
struct _type { \
- _type() { } \
- _type(const _base v) : value(v) { } \
- _type(const _type &v) : value(v.value) {} \
- _type &operator=(const _type &rhs) { value = rhs.value; return *this; }\
+ _type() = default; \
+ _type(const _base v) : value(v) {} \
+ _type(const _type &v) = default; \
+ _type &operator=(const _type &rhs) = default; \
_type &operator=(const _base &rhs) { value = rhs; return *this; } \
operator const _base & () const { return value; } \
bool operator==(const _type &rhs) const { return value == rhs.value; } \
@@ -1241,8 +1382,9 @@ inline
typename std::enable_if<has_DocumentListTraits<T>::value, Input &>::type
operator>>(Input &yin, T &docList) {
int i = 0;
+ EmptyContext Ctx;
while ( yin.setCurrentDocument() ) {
- yamlize(yin, DocumentListTraits<T>::element(yin, docList, i), true);
+ yamlize(yin, DocumentListTraits<T>::element(yin, docList, i), true, Ctx);
if ( yin.error() )
return yin;
yin.nextDocument();
@@ -1253,11 +1395,12 @@ operator>>(Input &yin, T &docList) {
// Define non-member operator>> so that Input can stream in a map as a document.
template <typename T>
-inline
-typename std::enable_if<has_MappingTraits<T>::value, Input &>::type
+inline typename std::enable_if<has_MappingTraits<T, EmptyContext>::value,
+ Input &>::type
operator>>(Input &yin, T &docMap) {
+ EmptyContext Ctx;
yin.setCurrentDocument();
- yamlize(yin, docMap, true);
+ yamlize(yin, docMap, true, Ctx);
return yin;
}
@@ -1267,8 +1410,9 @@ template <typename T>
inline
typename std::enable_if<has_SequenceTraits<T>::value, Input &>::type
operator>>(Input &yin, T &docSeq) {
+ EmptyContext Ctx;
if (yin.setCurrentDocument())
- yamlize(yin, docSeq, true);
+ yamlize(yin, docSeq, true, Ctx);
return yin;
}
@@ -1277,15 +1421,27 @@ template <typename T>
inline
typename std::enable_if<has_BlockScalarTraits<T>::value, Input &>::type
operator>>(Input &In, T &Val) {
+ EmptyContext Ctx;
if (In.setCurrentDocument())
- yamlize(In, Val, true);
+ yamlize(In, Val, true, Ctx);
return In;
}
-// Provide better error message about types missing a trait specialization
+// Define non-member operator>> so that Input can stream in a string map.
template <typename T>
inline
-typename std::enable_if<missingTraits<T>::value, Input &>::type
+typename std::enable_if<has_CustomMappingTraits<T>::value, Input &>::type
+operator>>(Input &In, T &Val) {
+ EmptyContext Ctx;
+ if (In.setCurrentDocument())
+ yamlize(In, Val, true, Ctx);
+ return In;
+}
+
+// Provide better error message about types missing a trait specialization
+template <typename T>
+inline typename std::enable_if<missingTraits<T, EmptyContext>::value,
+ Input &>::type
operator>>(Input &yin, T &docSeq) {
char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
return yin;
@@ -1296,11 +1452,13 @@ template <typename T>
inline
typename std::enable_if<has_DocumentListTraits<T>::value, Output &>::type
operator<<(Output &yout, T &docList) {
+ EmptyContext Ctx;
yout.beginDocuments();
const size_t count = DocumentListTraits<T>::size(yout, docList);
for(size_t i=0; i < count; ++i) {
if ( yout.preflightDocument(i) ) {
- yamlize(yout, DocumentListTraits<T>::element(yout, docList, i), true);
+ yamlize(yout, DocumentListTraits<T>::element(yout, docList, i), true,
+ Ctx);
yout.postflightDocument();
}
}
@@ -1310,12 +1468,13 @@ operator<<(Output &yout, T &docList) {
// Define non-member operator<< so that Output can stream out a map.
template <typename T>
-inline
-typename std::enable_if<has_MappingTraits<T>::value, Output &>::type
+inline typename std::enable_if<has_MappingTraits<T, EmptyContext>::value,
+ Output &>::type
operator<<(Output &yout, T &map) {
+ EmptyContext Ctx;
yout.beginDocuments();
if ( yout.preflightDocument(0) ) {
- yamlize(yout, map, true);
+ yamlize(yout, map, true, Ctx);
yout.postflightDocument();
}
yout.endDocuments();
@@ -1327,9 +1486,10 @@ template <typename T>
inline
typename std::enable_if<has_SequenceTraits<T>::value, Output &>::type
operator<<(Output &yout, T &seq) {
+ EmptyContext Ctx;
yout.beginDocuments();
if ( yout.preflightDocument(0) ) {
- yamlize(yout, seq, true);
+ yamlize(yout, seq, true, Ctx);
yout.postflightDocument();
}
yout.endDocuments();
@@ -1341,84 +1501,125 @@ template <typename T>
inline
typename std::enable_if<has_BlockScalarTraits<T>::value, Output &>::type
operator<<(Output &Out, T &Val) {
+ EmptyContext Ctx;
Out.beginDocuments();
if (Out.preflightDocument(0)) {
- yamlize(Out, Val, true);
+ yamlize(Out, Val, true, Ctx);
Out.postflightDocument();
}
Out.endDocuments();
return Out;
}
-// Provide better error message about types missing a trait specialization
+// Define non-member operator<< so that Output can stream out a string map.
template <typename T>
inline
-typename std::enable_if<missingTraits<T>::value, Output &>::type
+typename std::enable_if<has_CustomMappingTraits<T>::value, Output &>::type
+operator<<(Output &Out, T &Val) {
+ EmptyContext Ctx;
+ Out.beginDocuments();
+ if (Out.preflightDocument(0)) {
+ yamlize(Out, Val, true, Ctx);
+ Out.postflightDocument();
+ }
+ Out.endDocuments();
+ return Out;
+}
+
+// Provide better error message about types missing a trait specialization
+template <typename T>
+inline typename std::enable_if<missingTraits<T, EmptyContext>::value,
+ Output &>::type
operator<<(Output &yout, T &seq) {
char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
return yout;
}
-} // namespace yaml
-} // namespace llvm
+template <typename T> struct SequenceTraitsImpl {
+ typedef typename T::value_type _type;
+ static size_t size(IO &io, T &seq) { return seq.size(); }
+ static _type &element(IO &io, T &seq, size_t index) {
+ if (index >= seq.size())
+ seq.resize(index + 1);
+ return seq[index];
+ }
+};
+
+/// Implementation of CustomMappingTraits for std::map<std::string, T>.
+template <typename T> struct StdMapStringCustomMappingTraitsImpl {
+ typedef std::map<std::string, T> map_type;
+ static void inputOne(IO &io, StringRef key, map_type &v) {
+ io.mapRequired(key.str().c_str(), v[key]);
+ }
+ static void output(IO &io, map_type &v) {
+ for (auto &p : v)
+ io.mapRequired(p.first.c_str(), p.second);
+ }
+};
+
+} // end namespace yaml
+} // end 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) \
- namespace llvm { \
- namespace yaml { \
- template<> \
- struct SequenceTraits< std::vector<_type> > { \
- static size_t size(IO &io, std::vector<_type> &seq) { \
- return seq.size(); \
- } \
- static _type& element(IO &io, std::vector<_type> &seq, size_t index) {\
- if ( index >= seq.size() ) \
- seq.resize(index+1); \
- return seq[index]; \
- } \
- }; \
- } \
+#define LLVM_YAML_IS_SEQUENCE_VECTOR(_type) \
+ namespace llvm { \
+ namespace yaml { \
+ template <> \
+ struct SequenceTraits<std::vector<_type>> \
+ : public SequenceTraitsImpl<std::vector<_type>> {}; \
+ template <unsigned N> \
+ struct SequenceTraits<SmallVector<_type, N>> \
+ : public SequenceTraitsImpl<SmallVector<_type, N>> {}; \
+ } \
}
/// Utility for declaring that a std::vector of a particular type
/// should be considered a YAML flow sequence.
-#define LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(_type) \
- namespace llvm { \
- namespace yaml { \
- template<> \
- struct SequenceTraits< std::vector<_type> > { \
- static size_t size(IO &io, std::vector<_type> &seq) { \
- return seq.size(); \
- } \
- static _type& element(IO &io, std::vector<_type> &seq, size_t index) {\
- (void)flow; /* Remove this workaround after PR17897 is fixed */ \
- if ( index >= seq.size() ) \
- seq.resize(index+1); \
- return seq[index]; \
- } \
- static const bool flow = true; \
- }; \
- } \
+/// We need to do a partial specialization on the vector version, not a full.
+/// If this is a full specialization, the compiler is a bit too "smart" and
+/// decides to warn on -Wunused-const-variable. This workaround can be
+/// removed and we can do a full specialization on std::vector<T> once
+/// PR28878 is fixed.
+#define LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(_type) \
+ namespace llvm { \
+ namespace yaml { \
+ template <unsigned N> \
+ struct SequenceTraits<SmallVector<_type, N>> \
+ : public SequenceTraitsImpl<SmallVector<_type, N>> { \
+ static const bool flow = true; \
+ }; \
+ template <typename Allocator> \
+ struct SequenceTraits<std::vector<_type, Allocator>> \
+ : public SequenceTraitsImpl<std::vector<_type, Allocator>> { \
+ static const bool flow = true; \
+ }; \
+ } \
}
/// Utility for declaring that a std::vector of a particular type
/// should be considered a YAML document list.
-#define LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(_type) \
- namespace llvm { \
- namespace yaml { \
- template<> \
- struct DocumentListTraits< std::vector<_type> > { \
- static size_t size(IO &io, std::vector<_type> &seq) { \
- return seq.size(); \
- } \
- static _type& element(IO &io, std::vector<_type> &seq, size_t index) {\
- if ( index >= seq.size() ) \
- seq.resize(index+1); \
- return seq[index]; \
- } \
- }; \
- } \
+#define LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(_type) \
+ namespace llvm { \
+ namespace yaml { \
+ template <unsigned N> \
+ struct DocumentListTraits<SmallVector<_type, N>> \
+ : public SequenceTraitsImpl<SmallVector<_type, N>> {}; \
+ template <> \
+ struct DocumentListTraits<std::vector<_type>> \
+ : public SequenceTraitsImpl<std::vector<_type>> {}; \
+ } \
+ }
+
+/// Utility for declaring that std::map<std::string, _type> should be considered
+/// a YAML map.
+#define LLVM_YAML_IS_STRING_MAP(_type) \
+ namespace llvm { \
+ namespace yaml { \
+ template <> \
+ struct CustomMappingTraits<std::map<std::string, _type>> \
+ : public StdMapStringCustomMappingTraitsImpl<_type> {}; \
+ } \
}
#endif // LLVM_SUPPORT_YAMLTRAITS_H
OpenPOWER on IntegriCloud