Commit 05968b70 authored by Milo Yip's avatar Milo Yip

Fix schema tests and added SchemaValidatingReader

parent 6978f878
...@@ -1869,6 +1869,21 @@ public: ...@@ -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: ...@@ -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 @@ ...@@ -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; ...@@ -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 @@ ...@@ -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 ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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),
documentStack_(allocator, documentStackCapacity),
valid_(true)
#if RAPIDJSON_SCHEMA_VERBOSE
, depth_(0)
#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), 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();
} }
~GenericSchemaValidator() { ~GenericSchemaValidator() {
...@@ -1475,7 +1512,7 @@ public: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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 @@ ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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);
...@@ -1088,3 +1093,38 @@ TEST(SchemaValidator, TestSuite) { ...@@ -1088,3 +1093,38 @@ TEST(SchemaValidator, TestSuite) {
// 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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment