Fix some remote ref issues
This commit is contained in:
parent
42f1194a8d
commit
3873bcb714
@ -121,9 +121,24 @@ public:
|
|||||||
return reinterpret_cast<T*>(stackTop_ - sizeof(T));
|
return reinterpret_cast<T*>(stackTop_ - sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
const T* Top() const {
|
||||||
|
RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
|
||||||
|
return reinterpret_cast<T*>(stackTop_ - sizeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T* End() { return reinterpret_cast<T*>(stackTop_); }
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
const T* End() const { return reinterpret_cast<T*>(stackTop_); }
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T* Bottom() { return (T*)stack_; }
|
T* Bottom() { return (T*)stack_; }
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
const T* Bottom() const { return (T*)stack_; }
|
||||||
|
|
||||||
Allocator& GetAllocator() { return *allocator_; }
|
Allocator& GetAllocator() { return *allocator_; }
|
||||||
bool Empty() const { return stackTop_ == stack_; }
|
bool Empty() const { return stackTop_ == stack_; }
|
||||||
size_t GetSize() const { return static_cast<size_t>(stackTop_ - stack_); }
|
size_t GetSize() const { return static_cast<size_t>(stackTop_ - stack_); }
|
||||||
|
@ -882,7 +882,7 @@ public:
|
|||||||
typedef typename ValueType::Ch Ch;
|
typedef typename ValueType::Ch Ch;
|
||||||
|
|
||||||
virtual ~IGenericRemoteSchemaDocumentProvider() {}
|
virtual ~IGenericRemoteSchemaDocumentProvider() {}
|
||||||
virtual SchemaDocumentType* GetRemoteDocument(const Ch* uri, SizeType length) = 0;
|
virtual const SchemaDocumentType* GetRemoteDocument(const Ch* uri, SizeType length) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef IGenericRemoteSchemaDocumentProvider<Value> IRemoteSchemaDocumentProvider;
|
typedef IGenericRemoteSchemaDocumentProvider<Value> IRemoteSchemaDocumentProvider;
|
||||||
@ -909,10 +909,10 @@ public:
|
|||||||
schemaMap_(allocator, kInitialSchemaMapSize),
|
schemaMap_(allocator, kInitialSchemaMapSize),
|
||||||
schemaRef_(allocator, kInitialSchemaRefSize)
|
schemaRef_(allocator, kInitialSchemaRefSize)
|
||||||
{
|
{
|
||||||
|
|
||||||
// Generate root schema, it will call CreateSchema() to create sub-schemas,
|
// Generate root schema, it will call CreateSchema() to create sub-schemas,
|
||||||
// And call AddRefSchema() if there are $ref.
|
// And call AddRefSchema() if there are $ref.
|
||||||
root_ = CreateSchema(PointerType(), static_cast<const ValueType&>(document));
|
//root_ = CreateSchema(PointerType(), static_cast<const ValueType&>(document));
|
||||||
|
root_ = CreateSchemaRecursive(Pointer(), static_cast<const ValueType&>(document));
|
||||||
|
|
||||||
// Resolve $ref
|
// Resolve $ref
|
||||||
while (!schemaRef_.Empty()) {
|
while (!schemaRef_.Empty()) {
|
||||||
@ -936,12 +936,27 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
struct SchemaEntry {
|
struct SchemaEntry {
|
||||||
SchemaEntry(const GenericPointer<ValueType>& p, SchemaType* s) : pointer(p), schema(s) {}
|
SchemaEntry(const PointerType& p, SchemaType* s) : pointer(p), schema(s) {}
|
||||||
GenericPointer<ValueType> pointer;
|
PointerType pointer;
|
||||||
SchemaType* schema;
|
SchemaType* schema;
|
||||||
};
|
};
|
||||||
|
|
||||||
const SchemaType* CreateSchema(const GenericPointer<ValueType>& pointer, const ValueType& v) {
|
const SchemaType* CreateSchemaRecursive(const PointerType& pointer, const ValueType& v) {
|
||||||
|
if (v.GetType() == kObjectType) {
|
||||||
|
const SchemaType* s = GetSchema(pointer);
|
||||||
|
if (!s)
|
||||||
|
s = CreateSchema(pointer, v);
|
||||||
|
for (typename ValueType::ConstMemberIterator itr = v.MemberBegin(); itr != v.MemberEnd(); ++itr)
|
||||||
|
CreateSchemaRecursive(pointer.Append(itr->name), itr->value);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
else if (v.GetType() == kArrayType)
|
||||||
|
for (SizeType i = 0; i < v.Size(); i++)
|
||||||
|
CreateSchemaRecursive(pointer.Append(i), v[i]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SchemaType* CreateSchema(const PointerType& pointer, const ValueType& v) {
|
||||||
RAPIDJSON_ASSERT(pointer.IsValid());
|
RAPIDJSON_ASSERT(pointer.IsValid());
|
||||||
SchemaType* schema = new SchemaType(this, pointer, v);
|
SchemaType* schema = new SchemaType(this, pointer, v);
|
||||||
new (schemaMap_.template Push<SchemaEntry>()) SchemaEntry(pointer, schema);
|
new (schemaMap_.template Push<SchemaEntry>()) SchemaEntry(pointer, schema);
|
||||||
@ -959,8 +974,7 @@ private:
|
|||||||
|
|
||||||
if (i > 0) { // Remote reference, resolve immediately
|
if (i > 0) { // Remote reference, resolve immediately
|
||||||
if (remoteProvider_) {
|
if (remoteProvider_) {
|
||||||
if (GenericSchemaDocument* remoteDocument = remoteProvider_->GetRemoteDocument(s, i - 1)) {
|
if (const GenericSchemaDocument* remoteDocument = remoteProvider_->GetRemoteDocument(s, i - 1)) {
|
||||||
printf("remote fragment: %*s\n", len - i, &s[i]);
|
|
||||||
GenericPointer<ValueType> pointer(&s[i], len - i);
|
GenericPointer<ValueType> pointer(&s[i], len - i);
|
||||||
if (pointer.IsValid())
|
if (pointer.IsValid())
|
||||||
schema->ref_ = remoteDocument->GetSchema(pointer);
|
schema->ref_ = remoteDocument->GetSchema(pointer);
|
||||||
@ -968,7 +982,6 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (s[i] == '#') { // Local reference, defer resolution
|
else if (s[i] == '#') { // Local reference, defer resolution
|
||||||
printf("local fragment: %*s\n", len - i, &s[i]);
|
|
||||||
GenericPointer<ValueType> pointer(&s[i], len - i);
|
GenericPointer<ValueType> pointer(&s[i], len - i);
|
||||||
if (pointer.IsValid())
|
if (pointer.IsValid())
|
||||||
new (schemaRef_.template Push<SchemaEntry>()) SchemaEntry(pointer, schema);
|
new (schemaRef_.template Push<SchemaEntry>()) SchemaEntry(pointer, schema);
|
||||||
@ -977,15 +990,11 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const SchemaType* GetSchema(const GenericPointer<ValueType>& pointer) {
|
const SchemaType* GetSchema(const PointerType& pointer) const {
|
||||||
for (SchemaEntry* target = schemaMap_.template Bottom<SchemaEntry>(); target <= schemaMap_.template Top<SchemaEntry>(); ++target)
|
for (const SchemaEntry* target = schemaMap_.template Bottom<SchemaEntry>(); target != schemaMap_.template End<SchemaEntry>(); ++target)
|
||||||
if (pointer == target->pointer)
|
if (pointer == target->pointer)
|
||||||
return target->schema;
|
return target->schema;
|
||||||
|
return 0;
|
||||||
if (const ValueType* v = pointer.Get(document_))
|
|
||||||
return CreateSchema(pointer, *v);
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const size_t kInitialSchemaMapSize = 1024;
|
static const size_t kInitialSchemaMapSize = 1024;
|
||||||
@ -1061,7 +1070,7 @@ public:
|
|||||||
if (!BeginValue() || !CurrentSchema().method arg1) return valid_ = false;
|
if (!BeginValue() || !CurrentSchema().method arg1) return valid_ = false;
|
||||||
|
|
||||||
#define RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2)\
|
#define RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2)\
|
||||||
for (Context* context = schemaStack_.template Bottom<Context>(); context <= schemaStack_.template Top<Context>(); context++) {\
|
for (Context* context = schemaStack_.template Bottom<Context>(); context != schemaStack_.template End<Context>(); context++) {\
|
||||||
if (context->allOfValidators.validators)\
|
if (context->allOfValidators.validators)\
|
||||||
for (SizeType i_ = 0; i_ < context->allOfValidators.count; i_++)\
|
for (SizeType i_ = 0; i_ < context->allOfValidators.count; i_++)\
|
||||||
static_cast<GenericSchemaValidator*>(context->allOfValidators.validators[i_])->method arg2;\
|
static_cast<GenericSchemaValidator*>(context->allOfValidators.validators[i_])->method arg2;\
|
||||||
|
@ -763,17 +763,16 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual SchemaDocument* GetRemoteDocument(const char* uri, SizeType length) {
|
virtual const SchemaDocument* GetRemoteDocument(const char* uri, SizeType length) {
|
||||||
const char* uris[kCount] = {
|
const char* uris[kCount] = {
|
||||||
"http://localhost:1234/integer.json",
|
"http://localhost:1234/integer.json",
|
||||||
"http://localhost:1234/subSchemas.json",
|
"http://localhost:1234/subSchemas.json",
|
||||||
"http://localhost:1234/folder/folderInteger.json"
|
"http://localhost:1234/folder/folderInteger.json"
|
||||||
};
|
};
|
||||||
|
|
||||||
for (size_t i = 0; i < kCount; i++) {
|
for (size_t i = 0; i < kCount; i++)
|
||||||
if (strncmp(uri, uris[i], length) == 0)
|
if (strncmp(uri, uris[i], length) == 0)
|
||||||
return sd_[i];
|
return sd_[i];
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -809,7 +808,7 @@ TEST(SchemaValidator, TestSuite) {
|
|||||||
"patternProperties.json",
|
"patternProperties.json",
|
||||||
"properties.json",
|
"properties.json",
|
||||||
"ref.json",
|
"ref.json",
|
||||||
//"refRemote.json",
|
"refRemote.json",
|
||||||
"required.json",
|
"required.json",
|
||||||
"type.json",
|
"type.json",
|
||||||
//"uniqueItems.json"
|
//"uniqueItems.json"
|
||||||
@ -854,7 +853,7 @@ TEST(SchemaValidator, TestSuite) {
|
|||||||
validator.Reset();
|
validator.Reset();
|
||||||
bool actual = data.Accept(validator);
|
bool actual = data.Accept(validator);
|
||||||
if (expected != actual)
|
if (expected != actual)
|
||||||
printf("Fail: %30s \"%s, %s\"\n", filename, description1, description2);
|
printf("Fail: %30s \"%s\" \"%s\"\n", filename, description1, description2);
|
||||||
else
|
else
|
||||||
passCount++;
|
passCount++;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user