Commit 3873bcb7 authored by miloyip's avatar miloyip

Fix some remote ref issues

parent 42f1194a
...@@ -121,9 +121,24 @@ public: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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) { ...@@ -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) { ...@@ -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++;
} }
......
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