Fix schema tests and added SchemaValidatingReader
This commit is contained in:
parent
6978f878eb
commit
05968b7031
@ -1869,6 +1869,21 @@ public:
|
|||||||
*/
|
*/
|
||||||
friend inline void swap(GenericDocument& a, GenericDocument& b) RAPIDJSON_NOEXCEPT { a.Swap(b); }
|
friend inline void swap(GenericDocument& a, GenericDocument& b) RAPIDJSON_NOEXCEPT { a.Swap(b); }
|
||||||
|
|
||||||
|
//! Populate this document by a generator which produces SAX events.
|
||||||
|
/*! \tparam Generator A functor with <tt>bool f(Handler)</tt> prototype.
|
||||||
|
\param g Generator functor which sends SAX events to the parameter.
|
||||||
|
\return The document itself for fluent API.
|
||||||
|
*/
|
||||||
|
template <typename Generator>
|
||||||
|
GenericDocument& Populate(Generator& g) {
|
||||||
|
ClearStackOnExit scope(*this);
|
||||||
|
if (g(*this)) {
|
||||||
|
RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object
|
||||||
|
ValueType::operator=(*stack_.template Pop<ValueType>(1));// Move value from stack to document
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
//!@name Parse from stream
|
//!@name Parse from stream
|
||||||
//!@{
|
//!@{
|
||||||
|
|
||||||
@ -2017,9 +2032,10 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
// callers of the following private Handler functions
|
// callers of the following private Handler functions
|
||||||
template <typename,typename,typename> friend class GenericReader; // for parsing
|
// template <typename,typename,typename> friend class GenericReader; // for parsing
|
||||||
template <typename, typename> friend class GenericValue; // for deep copying
|
template <typename, typename> friend class GenericValue; // for deep copying
|
||||||
|
|
||||||
|
public:
|
||||||
// Implementation of Handler
|
// Implementation of Handler
|
||||||
bool Null() { new (stack_.template Push<ValueType>()) ValueType(); return true; }
|
bool Null() { new (stack_.template Push<ValueType>()) ValueType(); return true; }
|
||||||
bool Bool(bool b) { new (stack_.template Push<ValueType>()) ValueType(b); return true; }
|
bool Bool(bool b) { new (stack_.template Push<ValueType>()) ValueType(b); return true; }
|
||||||
|
@ -18,6 +18,12 @@
|
|||||||
#include "../rapidjson.h"
|
#include "../rapidjson.h"
|
||||||
#include "stack.h"
|
#include "stack.h"
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_PUSH
|
||||||
|
RAPIDJSON_DIAG_OFF(padded)
|
||||||
|
RAPIDJSON_DIAG_OFF(switch-enum)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef RAPIDJSON_REGEX_VERBOSE
|
#ifndef RAPIDJSON_REGEX_VERBOSE
|
||||||
#define RAPIDJSON_REGEX_VERBOSE 0
|
#define RAPIDJSON_REGEX_VERBOSE 0
|
||||||
#endif
|
#endif
|
||||||
@ -639,4 +645,8 @@ typedef GenericRegex<UTF8<> > Regex;
|
|||||||
} // namespace internal
|
} // namespace internal
|
||||||
RAPIDJSON_NAMESPACE_END
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_POP
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // RAPIDJSON_INTERNAL_REGEX_H_
|
#endif // RAPIDJSON_INTERNAL_REGEX_H_
|
||||||
|
@ -19,6 +19,12 @@
|
|||||||
#include "pointer.h"
|
#include "pointer.h"
|
||||||
#include <cmath> // HUGE_VAL, abs, floor
|
#include <cmath> // HUGE_VAL, abs, floor
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_PUSH
|
||||||
|
RAPIDJSON_DIAG_OFF(weak-vtables)
|
||||||
|
RAPIDJSON_DIAG_OFF(exit-time-destructors)
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !defined(RAPIDJSON_SCHEMA_USE_INTERNALREGEX)
|
#if !defined(RAPIDJSON_SCHEMA_USE_INTERNALREGEX)
|
||||||
#define RAPIDJSON_SCHEMA_USE_INTERNALREGEX 1
|
#define RAPIDJSON_SCHEMA_USE_INTERNALREGEX 1
|
||||||
#else
|
#else
|
||||||
@ -56,6 +62,11 @@ RAPIDJSON_DIAG_PUSH
|
|||||||
RAPIDJSON_DIAG_OFF(effc++)
|
RAPIDJSON_DIAG_OFF(effc++)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_PUSH
|
||||||
|
RAPIDJSON_DIAG_OFF(variadic-macros)
|
||||||
|
#endif
|
||||||
|
|
||||||
RAPIDJSON_NAMESPACE_BEGIN
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -865,39 +876,39 @@ public:
|
|||||||
return v;\
|
return v;\
|
||||||
}
|
}
|
||||||
|
|
||||||
RAPIDJSON_STRING_(Null, 'n', 'u', 'l', 'l');
|
RAPIDJSON_STRING_(Null, 'n', 'u', 'l', 'l')
|
||||||
RAPIDJSON_STRING_(Boolean, 'b', 'o', 'o', 'l', 'e', 'a', 'n');
|
RAPIDJSON_STRING_(Boolean, 'b', 'o', 'o', 'l', 'e', 'a', 'n')
|
||||||
RAPIDJSON_STRING_(Object, 'o', 'b', 'j', 'e', 'c', 't');
|
RAPIDJSON_STRING_(Object, 'o', 'b', 'j', 'e', 'c', 't')
|
||||||
RAPIDJSON_STRING_(Array, 'a', 'r', 'r', 'a', 'y');
|
RAPIDJSON_STRING_(Array, 'a', 'r', 'r', 'a', 'y')
|
||||||
RAPIDJSON_STRING_(String, 's', 't', 'r', 'i', 'n', 'g');
|
RAPIDJSON_STRING_(String, 's', 't', 'r', 'i', 'n', 'g')
|
||||||
RAPIDJSON_STRING_(Number, 'n', 'u', 'm', 'b', 'e', 'r');
|
RAPIDJSON_STRING_(Number, 'n', 'u', 'm', 'b', 'e', 'r')
|
||||||
RAPIDJSON_STRING_(Integer, 'i', 'n', 't', 'e', 'g', 'e', 'r');
|
RAPIDJSON_STRING_(Integer, 'i', 'n', 't', 'e', 'g', 'e', 'r')
|
||||||
RAPIDJSON_STRING_(Type, 't', 'y', 'p', 'e');
|
RAPIDJSON_STRING_(Type, 't', 'y', 'p', 'e')
|
||||||
RAPIDJSON_STRING_(Enum, 'e', 'n', 'u', 'm');
|
RAPIDJSON_STRING_(Enum, 'e', 'n', 'u', 'm')
|
||||||
RAPIDJSON_STRING_(AllOf, 'a', 'l', 'l', 'O', 'f');
|
RAPIDJSON_STRING_(AllOf, 'a', 'l', 'l', 'O', 'f')
|
||||||
RAPIDJSON_STRING_(AnyOf, 'a', 'n', 'y', 'O', 'f');
|
RAPIDJSON_STRING_(AnyOf, 'a', 'n', 'y', 'O', 'f')
|
||||||
RAPIDJSON_STRING_(OneOf, 'o', 'n', 'e', 'O', 'f');
|
RAPIDJSON_STRING_(OneOf, 'o', 'n', 'e', 'O', 'f')
|
||||||
RAPIDJSON_STRING_(Not, 'n', 'o', 't');
|
RAPIDJSON_STRING_(Not, 'n', 'o', 't')
|
||||||
RAPIDJSON_STRING_(Properties, 'p', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's');
|
RAPIDJSON_STRING_(Properties, 'p', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
|
||||||
RAPIDJSON_STRING_(Required, 'r', 'e', 'q', 'u', 'i', 'r', 'e', 'd');
|
RAPIDJSON_STRING_(Required, 'r', 'e', 'q', 'u', 'i', 'r', 'e', 'd')
|
||||||
RAPIDJSON_STRING_(Dependencies, 'd', 'e', 'p', 'e', 'n', 'd', 'e', 'n', 'c', 'i', 'e', 's');
|
RAPIDJSON_STRING_(Dependencies, 'd', 'e', 'p', 'e', 'n', 'd', 'e', 'n', 'c', 'i', 'e', 's')
|
||||||
RAPIDJSON_STRING_(PatternProperties, 'p', 'a', 't', 't', 'e', 'r', 'n', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's');
|
RAPIDJSON_STRING_(PatternProperties, 'p', 'a', 't', 't', 'e', 'r', 'n', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
|
||||||
RAPIDJSON_STRING_(AdditionalProperties, 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's');
|
RAPIDJSON_STRING_(AdditionalProperties, 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
|
||||||
RAPIDJSON_STRING_(MinProperties, 'm', 'i', 'n', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's');
|
RAPIDJSON_STRING_(MinProperties, 'm', 'i', 'n', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
|
||||||
RAPIDJSON_STRING_(MaxProperties, 'm', 'a', 'x', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's');
|
RAPIDJSON_STRING_(MaxProperties, 'm', 'a', 'x', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
|
||||||
RAPIDJSON_STRING_(Items, 'i', 't', 'e', 'm', 's');
|
RAPIDJSON_STRING_(Items, 'i', 't', 'e', 'm', 's')
|
||||||
RAPIDJSON_STRING_(MinItems, 'm', 'i', 'n', 'I', 't', 'e', 'm', 's');
|
RAPIDJSON_STRING_(MinItems, 'm', 'i', 'n', 'I', 't', 'e', 'm', 's')
|
||||||
RAPIDJSON_STRING_(MaxItems, 'm', 'a', 'x', 'I', 't', 'e', 'm', 's');
|
RAPIDJSON_STRING_(MaxItems, 'm', 'a', 'x', 'I', 't', 'e', 'm', 's')
|
||||||
RAPIDJSON_STRING_(AdditionalItems, 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'I', 't', 'e', 'm', 's');
|
RAPIDJSON_STRING_(AdditionalItems, 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'I', 't', 'e', 'm', 's')
|
||||||
RAPIDJSON_STRING_(UniqueItems, 'u', 'n', 'i', 'q', 'u', 'e', 'I', 't', 'e', 'm', 's');
|
RAPIDJSON_STRING_(UniqueItems, 'u', 'n', 'i', 'q', 'u', 'e', 'I', 't', 'e', 'm', 's')
|
||||||
RAPIDJSON_STRING_(MinLength, 'm', 'i', 'n', 'L', 'e', 'n', 'g', 't', 'h');
|
RAPIDJSON_STRING_(MinLength, 'm', 'i', 'n', 'L', 'e', 'n', 'g', 't', 'h')
|
||||||
RAPIDJSON_STRING_(MaxLength, 'm', 'a', 'x', 'L', 'e', 'n', 'g', 't', 'h');
|
RAPIDJSON_STRING_(MaxLength, 'm', 'a', 'x', 'L', 'e', 'n', 'g', 't', 'h')
|
||||||
RAPIDJSON_STRING_(Pattern, 'p', 'a', 't', 't', 'e', 'r', 'n');
|
RAPIDJSON_STRING_(Pattern, 'p', 'a', 't', 't', 'e', 'r', 'n')
|
||||||
RAPIDJSON_STRING_(Minimum, 'm', 'i', 'n', 'i', 'm', 'u', 'm');
|
RAPIDJSON_STRING_(Minimum, 'm', 'i', 'n', 'i', 'm', 'u', 'm')
|
||||||
RAPIDJSON_STRING_(Maximum, 'm', 'a', 'x', 'i', 'm', 'u', 'm');
|
RAPIDJSON_STRING_(Maximum, 'm', 'a', 'x', 'i', 'm', 'u', 'm')
|
||||||
RAPIDJSON_STRING_(ExclusiveMinimum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'i', 'n', 'i', 'm', 'u', 'm');
|
RAPIDJSON_STRING_(ExclusiveMinimum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'i', 'n', 'i', 'm', 'u', 'm')
|
||||||
RAPIDJSON_STRING_(ExclusiveMaximum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'a', 'x', 'i', 'm', 'u', 'm');
|
RAPIDJSON_STRING_(ExclusiveMaximum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'a', 'x', 'i', 'm', 'u', 'm')
|
||||||
RAPIDJSON_STRING_(MultipleOf, 'm', 'u', 'l', 't', 'i', 'p', 'l', 'e', 'O', 'f');
|
RAPIDJSON_STRING_(MultipleOf, 'm', 'u', 'l', 't', 'i', 'p', 'l', 'e', 'O', 'f')
|
||||||
|
|
||||||
#undef RAPIDJSON_STRING_
|
#undef RAPIDJSON_STRING_
|
||||||
|
|
||||||
@ -1380,9 +1391,9 @@ private:
|
|||||||
if (const GenericSchemaDocument* remoteDocument = remoteProvider_->GetRemoteDocument(s, i - 1)) {
|
if (const GenericSchemaDocument* remoteDocument = remoteProvider_->GetRemoteDocument(s, i - 1)) {
|
||||||
PointerType pointer(&s[i], len - i, allocator_);
|
PointerType pointer(&s[i], len - i, allocator_);
|
||||||
if (pointer.IsValid()) {
|
if (pointer.IsValid()) {
|
||||||
if (const SchemaType* s = remoteDocument->GetSchema(pointer)) {
|
if (const SchemaType* sc = remoteDocument->GetSchema(pointer)) {
|
||||||
if (schema)
|
if (schema)
|
||||||
*schema = s;
|
*schema = sc;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1414,7 +1425,7 @@ private:
|
|||||||
|
|
||||||
PointerType GetPointer(const SchemaType* schema) const {
|
PointerType GetPointer(const SchemaType* schema) const {
|
||||||
for (const SchemaEntry* target = schemaMap_.template Bottom<SchemaEntry>(); target != schemaMap_.template End<SchemaEntry>(); ++target)
|
for (const SchemaEntry* target = schemaMap_.template Bottom<SchemaEntry>(); target != schemaMap_.template End<SchemaEntry>(); ++target)
|
||||||
if (schema== target->schema)
|
if (schema == target->schema)
|
||||||
return target->pointer;
|
return target->pointer;
|
||||||
return PointerType();
|
return PointerType();
|
||||||
}
|
}
|
||||||
@ -1457,13 +1468,39 @@ public:
|
|||||||
schemaDocument_(&schemaDocument),
|
schemaDocument_(&schemaDocument),
|
||||||
root_(schemaDocument.GetRoot()),
|
root_(schemaDocument.GetRoot()),
|
||||||
outputHandler_(nullOutputHandler_),
|
outputHandler_(nullOutputHandler_),
|
||||||
|
stateAllocator_(allocator),
|
||||||
|
ownStateAllocator_(0),
|
||||||
schemaStack_(allocator, schemaStackCapacity),
|
schemaStack_(allocator, schemaStackCapacity),
|
||||||
documentStack_(&GetStateAllocator(), documentStackCapacity),
|
documentStack_(allocator, documentStackCapacity),
|
||||||
valid_(true)
|
valid_(true)
|
||||||
#if RAPIDJSON_SCHEMA_VERBOSE
|
#if RAPIDJSON_SCHEMA_VERBOSE
|
||||||
, depth_(0)
|
, depth_(0)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
CreateOwnAllocator();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructor with outputHandler
|
||||||
|
GenericSchemaValidator(
|
||||||
|
const SchemaDocumentType& schemaDocument,
|
||||||
|
OutputHandler& outputHandler,
|
||||||
|
StateAllocator* allocator = 0,
|
||||||
|
size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
|
||||||
|
size_t documentStackCapacity = kDefaultDocumentStackCapacity)
|
||||||
|
:
|
||||||
|
schemaDocument_(&schemaDocument),
|
||||||
|
root_(schemaDocument.GetRoot()),
|
||||||
|
outputHandler_(outputHandler),
|
||||||
|
stateAllocator_(allocator),
|
||||||
|
ownStateAllocator_(0),
|
||||||
|
schemaStack_(allocator, schemaStackCapacity),
|
||||||
|
documentStack_(allocator, documentStackCapacity),
|
||||||
|
valid_(true)
|
||||||
|
#if RAPIDJSON_SCHEMA_VERBOSE
|
||||||
|
, depth_(0)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
CreateOwnAllocator();
|
||||||
}
|
}
|
||||||
|
|
||||||
~GenericSchemaValidator() {
|
~GenericSchemaValidator() {
|
||||||
@ -1475,7 +1512,7 @@ public:
|
|||||||
PopSchema();
|
PopSchema();
|
||||||
//documentStack_.Clear();
|
//documentStack_.Clear();
|
||||||
valid_ = true;
|
valid_ = true;
|
||||||
};
|
}
|
||||||
|
|
||||||
// Implementation of ISchemaValidator
|
// Implementation of ISchemaValidator
|
||||||
virtual bool IsValid() const { return valid_; }
|
virtual bool IsValid() const { return valid_; }
|
||||||
@ -1493,7 +1530,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
StateAllocator& GetStateAllocator() {
|
StateAllocator& GetStateAllocator() {
|
||||||
return schemaStack_.GetAllocator();
|
return *stateAllocator_;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if RAPIDJSON_SCHEMA_VERBOSE
|
#if RAPIDJSON_SCHEMA_VERBOSE
|
||||||
@ -1642,6 +1679,8 @@ private:
|
|||||||
schemaDocument_(&schemaDocument),
|
schemaDocument_(&schemaDocument),
|
||||||
root_(root),
|
root_(root),
|
||||||
outputHandler_(nullOutputHandler_),
|
outputHandler_(nullOutputHandler_),
|
||||||
|
stateAllocator_(allocator),
|
||||||
|
ownStateAllocator_(0),
|
||||||
schemaStack_(allocator, schemaStackCapacity),
|
schemaStack_(allocator, schemaStackCapacity),
|
||||||
documentStack_(allocator, documentStackCapacity),
|
documentStack_(allocator, documentStackCapacity),
|
||||||
valid_(true)
|
valid_(true)
|
||||||
@ -1649,6 +1688,12 @@ private:
|
|||||||
, depth_(depth)
|
, depth_(depth)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
CreateOwnAllocator();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CreateOwnAllocator() {
|
||||||
|
if (!stateAllocator_)
|
||||||
|
stateAllocator_ = ownStateAllocator_ = new StateAllocator;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BeginValue() {
|
bool BeginValue() {
|
||||||
@ -1738,8 +1783,8 @@ private:
|
|||||||
void AppendToken(SizeType index) {
|
void AppendToken(SizeType index) {
|
||||||
*documentStack_.template Push<Ch>() = '/';
|
*documentStack_.template Push<Ch>() = '/';
|
||||||
char buffer[21];
|
char buffer[21];
|
||||||
SizeType length = (sizeof(SizeType) == 4 ? internal::u32toa(index, buffer): internal::u64toa(index, buffer)) - buffer;
|
size_t length = static_cast<size_t>((sizeof(SizeType) == 4 ? internal::u32toa(index, buffer) : internal::u64toa(index, buffer)) - buffer);
|
||||||
for (SizeType i = 0; i < length; i++)
|
for (size_t i = 0; i < length; i++)
|
||||||
*documentStack_.template Push<Ch>() = buffer[i];
|
*documentStack_.template Push<Ch>() = buffer[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1762,8 +1807,10 @@ private:
|
|||||||
static const size_t kDefaultDocumentStackCapacity = 256;
|
static const size_t kDefaultDocumentStackCapacity = 256;
|
||||||
const SchemaDocumentType* schemaDocument_;
|
const SchemaDocumentType* schemaDocument_;
|
||||||
const SchemaType& root_;
|
const SchemaType& root_;
|
||||||
BaseReaderHandler<EncodingType> nullOutputHandler_;
|
OutputHandler nullOutputHandler_;
|
||||||
OutputHandler& outputHandler_;
|
OutputHandler& outputHandler_;
|
||||||
|
StateAllocator* stateAllocator_;
|
||||||
|
StateAllocator* ownStateAllocator_;
|
||||||
internal::Stack<StateAllocator> schemaStack_; //!< stack to store the current path of schema (BaseSchemaType *)
|
internal::Stack<StateAllocator> schemaStack_; //!< stack to store the current path of schema (BaseSchemaType *)
|
||||||
internal::Stack<StateAllocator> documentStack_; //!< stack to store the current path of validating document (Ch)
|
internal::Stack<StateAllocator> documentStack_; //!< stack to store the current path of validating document (Ch)
|
||||||
bool valid_;
|
bool valid_;
|
||||||
@ -1774,10 +1821,62 @@ private:
|
|||||||
|
|
||||||
typedef GenericSchemaValidator<SchemaDocument> SchemaValidator;
|
typedef GenericSchemaValidator<SchemaDocument> SchemaValidator;
|
||||||
|
|
||||||
|
template <
|
||||||
|
unsigned parseFlags,
|
||||||
|
typename InputStream,
|
||||||
|
typename SourceEncoding,
|
||||||
|
typename SchemaDocumentType = SchemaDocument,
|
||||||
|
typename StackAllocator = CrtAllocator>
|
||||||
|
class SchemaValidatingReader {
|
||||||
|
public:
|
||||||
|
typedef typename SchemaDocumentType::PointerType PointerType;
|
||||||
|
typedef typename InputStream::Ch Ch;
|
||||||
|
|
||||||
|
SchemaValidatingReader(InputStream& is, const SchemaDocumentType& sd) : is_(is), sd_(sd), invalidSchemaKeyword_() {}
|
||||||
|
|
||||||
|
template <typename Handler>
|
||||||
|
bool operator()(Handler& handler) {
|
||||||
|
GenericReader<SourceEncoding, typename SchemaDocumentType::EncodingType, StackAllocator> reader;
|
||||||
|
GenericSchemaValidator<SchemaDocumentType, Handler> validator(sd_, handler);
|
||||||
|
parseResult_ = reader.template Parse<parseFlags>(is_, validator);
|
||||||
|
|
||||||
|
if (validator.IsValid()) {
|
||||||
|
invalidSchemaPointer_ = PointerType();
|
||||||
|
invalidSchemaKeyword_ = 0;
|
||||||
|
invalidDocumentPointer_ = PointerType();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
invalidSchemaPointer_ = validator.GetInvalidSchemaPointer();
|
||||||
|
invalidSchemaKeyword_ = validator.GetInvalidSchemaKeyword();
|
||||||
|
invalidDocumentPointer_ = validator.GetInvalidDocumentPointer();
|
||||||
|
}
|
||||||
|
|
||||||
|
return parseResult_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ParseResult& GetParseResult() const { return parseResult_; }
|
||||||
|
const PointerType& GetInvalidSchemaPointer() const { return invalidSchemaPointer_; }
|
||||||
|
const Ch* GetInvalidSchemaKeyword() const { return invalidSchemaKeyword_; }
|
||||||
|
const PointerType& GetInvalidDocumentPointer() const { return invalidDocumentPointer_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
InputStream& is_;
|
||||||
|
const SchemaDocumentType& sd_;
|
||||||
|
|
||||||
|
ParseResult parseResult_;
|
||||||
|
PointerType invalidSchemaPointer_;
|
||||||
|
const Ch* invalidSchemaKeyword_;
|
||||||
|
PointerType invalidDocumentPointer_;
|
||||||
|
};
|
||||||
|
|
||||||
RAPIDJSON_NAMESPACE_END
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
RAPIDJSON_DIAG_POP
|
RAPIDJSON_DIAG_POP
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_POP
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // RAPIDJSON_SCHEMA_H_
|
#endif // RAPIDJSON_SCHEMA_H_
|
||||||
|
@ -16,6 +16,11 @@
|
|||||||
#include "rapidjson/schema.h"
|
#include "rapidjson/schema.h"
|
||||||
#include "rapidjson/stringbuffer.h"
|
#include "rapidjson/stringbuffer.h"
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_PUSH
|
||||||
|
RAPIDJSON_DIAG_OFF(variadic-macros)
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace rapidjson;
|
using namespace rapidjson;
|
||||||
|
|
||||||
#define TEST_HASHER(json1, json2, expected) \
|
#define TEST_HASHER(json1, json2, expected) \
|
||||||
@ -95,7 +100,7 @@ TEST(SchemaValidator, Hasher) {
|
|||||||
{\
|
{\
|
||||||
SchemaValidator validator(schema);\
|
SchemaValidator validator(schema);\
|
||||||
Document d;\
|
Document d;\
|
||||||
printf("\n%s\n", json);\
|
/*printf("\n%s\n", json);*/\
|
||||||
d.Parse(json);\
|
d.Parse(json);\
|
||||||
EXPECT_FALSE(d.HasParseError());\
|
EXPECT_FALSE(d.HasParseError());\
|
||||||
EXPECT_TRUE(expected == d.Accept(validator));\
|
EXPECT_TRUE(expected == d.Accept(validator));\
|
||||||
@ -115,7 +120,7 @@ TEST(SchemaValidator, Hasher) {
|
|||||||
{\
|
{\
|
||||||
SchemaValidator validator(schema);\
|
SchemaValidator validator(schema);\
|
||||||
Document d;\
|
Document d;\
|
||||||
printf("\n%s\n", json);\
|
/*printf("\n%s\n", json);*/\
|
||||||
d.Parse(json);\
|
d.Parse(json);\
|
||||||
EXPECT_FALSE(d.HasParseError());\
|
EXPECT_FALSE(d.HasParseError());\
|
||||||
EXPECT_FALSE(d.Accept(validator));\
|
EXPECT_FALSE(d.Accept(validator));\
|
||||||
@ -841,16 +846,16 @@ TEST(SchemaValidator, AllOf_Nested) {
|
|||||||
template <typename Allocator>
|
template <typename Allocator>
|
||||||
static char* ReadFile(const char* filename, Allocator& allocator) {
|
static char* ReadFile(const char* filename, Allocator& allocator) {
|
||||||
const char *paths[] = {
|
const char *paths[] = {
|
||||||
"%s",
|
"",
|
||||||
"bin/%s",
|
"bin/",
|
||||||
"../bin/%s",
|
"../bin/",
|
||||||
"../../bin/%s",
|
"../../bin/",
|
||||||
"../../../bin/%s"
|
"../../../bin/"
|
||||||
};
|
};
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
FILE *fp = 0;
|
FILE *fp = 0;
|
||||||
for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) {
|
for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) {
|
||||||
sprintf(buffer, paths[i], filename);
|
sprintf(buffer, "%s%s", paths[i], filename);
|
||||||
fp = fopen(buffer, "rb");
|
fp = fopen(buffer, "rb");
|
||||||
if (fp)
|
if (fp)
|
||||||
break;
|
break;
|
||||||
@ -860,9 +865,9 @@ static char* ReadFile(const char* filename, Allocator& allocator) {
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fseek(fp, 0, SEEK_END);
|
fseek(fp, 0, SEEK_END);
|
||||||
size_t length = (size_t)ftell(fp);
|
size_t length = static_cast<size_t>(ftell(fp));
|
||||||
fseek(fp, 0, SEEK_SET);
|
fseek(fp, 0, SEEK_SET);
|
||||||
char* json = (char*)allocator.Malloc(length + 1);
|
char* json = reinterpret_cast<char*>(allocator.Malloc(length + 1));
|
||||||
size_t readLength = fread(json, 1, length, fp);
|
size_t readLength = fread(json, 1, length, fp);
|
||||||
json[readLength] = '\0';
|
json[readLength] = '\0';
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
@ -1087,4 +1092,39 @@ TEST(SchemaValidator, TestSuite) {
|
|||||||
printf("%d / %d passed (%2d%%)\n", passCount, testCount, passCount * 100 / testCount);
|
printf("%d / %d passed (%2d%%)\n", passCount, testCount, passCount * 100 / testCount);
|
||||||
// if (passCount != testCount)
|
// if (passCount != testCount)
|
||||||
// ADD_FAILURE();
|
// ADD_FAILURE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(SchemaValidatingReader, Valid) {
|
||||||
|
Document sd;
|
||||||
|
sd.Parse("{ \"type\": \"string\", \"enum\" : [\"red\", \"amber\", \"green\"] }");
|
||||||
|
SchemaDocument s(sd);
|
||||||
|
|
||||||
|
Document d;
|
||||||
|
StringStream ss("\"red\"");
|
||||||
|
SchemaValidatingReader<kParseDefaultFlags, StringStream, UTF8<> > reader(ss, s);
|
||||||
|
d.Populate(reader);
|
||||||
|
EXPECT_TRUE(reader.GetParseResult());
|
||||||
|
EXPECT_TRUE(d.IsString());
|
||||||
|
EXPECT_STREQ("red", d.GetString());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SchemaValidatingReader, Invalid) {
|
||||||
|
Document sd;
|
||||||
|
sd.Parse("{\"type\":\"string\",\"minLength\":2,\"maxLength\":3}");
|
||||||
|
SchemaDocument s(sd);
|
||||||
|
|
||||||
|
Document d;
|
||||||
|
StringStream ss("\"ABCD\"");
|
||||||
|
SchemaValidatingReader<kParseDefaultFlags, StringStream, UTF8<> > reader(ss, s);
|
||||||
|
d.Populate(reader);
|
||||||
|
EXPECT_FALSE(reader.GetParseResult());
|
||||||
|
EXPECT_EQ(kParseErrorTermination, reader.GetParseResult().Code());
|
||||||
|
EXPECT_STREQ("maxLength", reader.GetInvalidSchemaKeyword());
|
||||||
|
EXPECT_TRUE(reader.GetInvalidSchemaPointer() == SchemaDocument::PointerType(""));
|
||||||
|
EXPECT_TRUE(reader.GetInvalidDocumentPointer() == SchemaDocument::PointerType(""));
|
||||||
|
EXPECT_TRUE(d.IsNull());
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_POP
|
||||||
|
#endif
|
||||||
|
@ -28,4 +28,4 @@ TEST(StrFunc, CountStringCodePoint) {
|
|||||||
EXPECT_TRUE(CountStringCodePoint<UTF8<> >("\xC2\xA2\xE2\x82\xAC\xF0\x9D\x84\x9E", 9, &count)); // cents euro G-clef
|
EXPECT_TRUE(CountStringCodePoint<UTF8<> >("\xC2\xA2\xE2\x82\xAC\xF0\x9D\x84\x9E", 9, &count)); // cents euro G-clef
|
||||||
EXPECT_EQ(3u, count);
|
EXPECT_EQ(3u, count);
|
||||||
EXPECT_FALSE(CountStringCodePoint<UTF8<> >("\xC2\xA2\xE2\x82\xAC\xF0\x9D\x84\x9E\x80", 10, &count));
|
EXPECT_FALSE(CountStringCodePoint<UTF8<> >("\xC2\xA2\xE2\x82\xAC\xF0\x9D\x84\x9E\x80", 10, &count));
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user