mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-12 17:32:19 +00:00
YAML I/O add support for validate()
MappingTrait template specializations can now have a validate() method which performs semantic checking. For details, see <http://llvm.org/docs/YamlIO.html>. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@195286 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
25f01786ea
commit
9fd7416b3b
@ -647,6 +647,44 @@ mappings, as long as they are convertable.
|
||||
To check a tag, inside your mapping() method you can use io.mapTag() to specify
|
||||
what the tag should be. This will also add that tag when writing yaml.
|
||||
|
||||
Validation
|
||||
----------
|
||||
|
||||
Sometimes in a yaml map, each key/value pair is valid, but the combination is
|
||||
not. This is similar to something having no syntax errors, but still having
|
||||
semantic errors. To support semantic level checking, YAML I/O allows
|
||||
an optional ``validate()`` method in a MappingTraits template specialization.
|
||||
|
||||
When parsing yaml, the ``validate()`` method is call *after* all key/values in
|
||||
the map have been processed. Any error message returned by the ``validate()``
|
||||
method during input will be printed just a like a syntax error would be printed.
|
||||
When writing yaml, the ``validate()`` method is called *before* the yaml
|
||||
key/values are written. Any error during output will trigger an ``assert()``
|
||||
because it is a programming error to have invalid struct values.
|
||||
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
using llvm::yaml::MappingTraits;
|
||||
using llvm::yaml::IO;
|
||||
|
||||
struct Stuff {
|
||||
...
|
||||
};
|
||||
|
||||
template <>
|
||||
struct MappingTraits<Stuff> {
|
||||
static void mapping(IO &io, Stuff &stuff) {
|
||||
...
|
||||
}
|
||||
static StringRef validate(IO &io, Stuff &stuff) {
|
||||
// Look at all fields in 'stuff' and if there
|
||||
// are any bad values return a string describing
|
||||
// the error. Otherwise return an empty string.
|
||||
return StringRef();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Sequence
|
||||
========
|
||||
|
@ -44,6 +44,8 @@ template<class T>
|
||||
struct MappingTraits {
|
||||
// Must provide:
|
||||
// static void mapping(IO &io, T &fields);
|
||||
// Optionally may provide:
|
||||
// static StringRef validate(IO &io, T &fields);
|
||||
};
|
||||
|
||||
|
||||
@ -226,6 +228,23 @@ public:
|
||||
static bool const value = (sizeof(test<MappingTraits<T> >(0)) == 1);
|
||||
};
|
||||
|
||||
// Test if MappingTraits<T>::validate() is defined on type T.
|
||||
template <class T>
|
||||
struct has_MappingValidateTraits
|
||||
{
|
||||
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> >(0)) == 1);
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Test if SequenceTraits<T> is defined on type T.
|
||||
template <class T>
|
||||
@ -309,7 +328,15 @@ struct missingTraits : public llvm::integral_constant<bool,
|
||||
&& !has_SequenceTraits<T>::value
|
||||
&& !has_DocumentListTraits<T>::value > {};
|
||||
|
||||
template<typename T>
|
||||
struct validatedMappingTraits : public llvm::integral_constant<bool,
|
||||
has_MappingTraits<T>::value
|
||||
&& has_MappingValidateTraits<T>::value> {};
|
||||
|
||||
template<typename T>
|
||||
struct unvalidatedMappingTraits : public llvm::integral_constant<bool,
|
||||
has_MappingTraits<T>::value
|
||||
&& !has_MappingValidateTraits<T>::value> {};
|
||||
// Base class for Input and Output.
|
||||
class IO {
|
||||
public:
|
||||
@ -483,7 +510,27 @@ yamlize(IO &io, T &Val, bool) {
|
||||
|
||||
|
||||
template<typename T>
|
||||
typename llvm::enable_if_c<has_MappingTraits<T>::value, void>::type
|
||||
typename llvm::enable_if_c<validatedMappingTraits<T>::value, void>::type
|
||||
yamlize(IO &io, T &Val, bool) {
|
||||
io.beginMapping();
|
||||
if (io.outputting()) {
|
||||
StringRef Err = MappingTraits<T>::validate(io, Val);
|
||||
if (!Err.empty()) {
|
||||
llvm::errs() << Err << "\n";
|
||||
assert(Err.empty() && "invalid struct trying to be written as yaml");
|
||||
}
|
||||
}
|
||||
MappingTraits<T>::mapping(io, Val);
|
||||
if (!io.outputting()) {
|
||||
StringRef Err = MappingTraits<T>::validate(io, Val);
|
||||
if (!Err.empty())
|
||||
io.setError(Err);
|
||||
}
|
||||
io.endMapping();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
typename llvm::enable_if_c<unvalidatedMappingTraits<T>::value, void>::type
|
||||
yamlize(IO &io, T &Val, bool) {
|
||||
io.beginMapping();
|
||||
MappingTraits<T>::mapping(io, Val);
|
||||
|
@ -27,6 +27,13 @@ using llvm::yaml::Hex32;
|
||||
using llvm::yaml::Hex64;
|
||||
|
||||
|
||||
|
||||
|
||||
static void suppressErrorMessages(const llvm::SMDiagnostic &, void *) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Test MappingTraits
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -1115,17 +1122,50 @@ TEST(YAMLIO, TestTaggedDocumentsWriteAndRead) {
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Test mapping validation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
struct MyValidation {
|
||||
double value;
|
||||
};
|
||||
|
||||
LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MyValidation)
|
||||
|
||||
namespace llvm {
|
||||
namespace yaml {
|
||||
template <>
|
||||
struct MappingTraits<MyValidation> {
|
||||
static void mapping(IO &io, MyValidation &d) {
|
||||
io.mapRequired("value", d.value);
|
||||
}
|
||||
static StringRef validate(IO &io, MyValidation &d) {
|
||||
if (d.value < 0)
|
||||
return "negative value";
|
||||
return StringRef();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Test that validate() is called and complains about the negative value.
|
||||
//
|
||||
TEST(YAMLIO, TestValidatingInput) {
|
||||
std::vector<MyValidation> docList;
|
||||
Input yin("--- \nvalue: 3.0\n"
|
||||
"--- \nvalue: -1.0\n...\n",
|
||||
NULL, suppressErrorMessages);
|
||||
yin >> docList;
|
||||
EXPECT_TRUE(yin.error());
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Test error handling
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
|
||||
static void suppressErrorMessages(const llvm::SMDiagnostic &, void *) {
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Test error handling of unknown enumerated scalar
|
||||
//
|
||||
|
Loading…
x
Reference in New Issue
Block a user