Skip to content

Commit

Permalink
Merge f6ebcb2 into 17aa824
Browse files Browse the repository at this point in the history
  • Loading branch information
smhdfdl committed Jun 9, 2021
2 parents 17aa824 + f6ebcb2 commit c9d350b
Show file tree
Hide file tree
Showing 11 changed files with 1,949 additions and 108 deletions.
69 changes: 69 additions & 0 deletions bin/unittestschema/idandref.json
@@ -0,0 +1,69 @@
{
"id": "http://example.com/root.json",
"definitions": {
"A": {
"id": "#foo",
"type": "integer"
},
"B": {
"id": "other.json",
"definitions": {
"X": {
"id": "#bar",
"type": "boolean"
},
"Y": {
"$ref": "#/definitions/X"
},
"W": {
"$ref": "#/definitions/Y"
},
"Z": {
"$ref": "#bar"
},
"N": {
"properties": {
"NX": {
"$ref": "#/definitions/X"
}
}
}
}
}
},
"properties": {
"PA1": {
"$ref": "http://example.com/root.json#/definitions/A"
},
"PA2": {
"$ref": "#/definitions/A"
},
"PA3": {
"$ref": "#foo"
},
"PX1": {
"$ref": "#/definitions/B/definitions/X"
},
"PX2Y": {
"$ref": "#/definitions/B/definitions/Y"
},
"PX3Z": {
"$ref": "#/definitions/B/definitions/Z"
},
"PX4": {
"$ref": "http://example.com/other.json#/definitions/X"
},
"PX5": {
"$ref": "other.json#/definitions/X"
},
"PX6": {
"$ref": "other.json#bar"
},
"PX7W": {
"$ref": "#/definitions/B/definitions/W"
},
"PX8N": {
"$ref": "#/definitions/B/definitions/N"
}
}
}
2 changes: 2 additions & 0 deletions example/schemavalidator/schemavalidator.cpp
Expand Up @@ -2,6 +2,8 @@

// The example validates JSON text from stdin with a JSON schema specified in the argument.

#define RAPIDJSON_HAS_STDSTRING 1

#include "rapidjson/error/en.h"
#include "rapidjson/filereadstream.h"
#include "rapidjson/schema.h"
Expand Down
2 changes: 1 addition & 1 deletion include/rapidjson/document.h
Expand Up @@ -1951,7 +1951,7 @@ class GenericValue {
case kArrayType:
if (RAPIDJSON_UNLIKELY(!handler.StartArray()))
return false;
for (const GenericValue* v = Begin(); v != End(); ++v)
for (ConstValueIterator v = Begin(); v != End(); ++v)
if (RAPIDJSON_UNLIKELY(!v->Accept(handler)))
return false;
return handler.EndArray(data_.a.size);
Expand Down
14 changes: 14 additions & 0 deletions include/rapidjson/internal/strfunc.h
Expand Up @@ -45,6 +45,20 @@ inline SizeType StrLen(const wchar_t* s) {
return SizeType(std::wcslen(s));
}

//! Custom strcmpn() which works on different character types.
/*! \tparam Ch Character type (e.g. char, wchar_t, short)
\param s1 Null-terminated input string.
\param s2 Null-terminated input string.
\return 0 if equal
*/
template<typename Ch>
inline int StrCmp(const Ch* s1, const Ch* s2) {
RAPIDJSON_ASSERT(s1 != 0);
RAPIDJSON_ASSERT(s2 != 0);
while(*s1 && (*s1 == *s2)) { s1++; s2++; }
return static_cast<unsigned>(*s1) < static_cast<unsigned>(*s2) ? -1 : static_cast<unsigned>(*s1) > static_cast<unsigned>(*s2);
}

//! Returns number of code points in a encoded string.
template<typename Encoding>
bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) {
Expand Down
67 changes: 67 additions & 0 deletions include/rapidjson/pointer.h
Expand Up @@ -16,6 +16,7 @@
#define RAPIDJSON_POINTER_H_

#include "document.h"
#include "uri.h"
#include "internal/itoa.h"

#ifdef __clang__
Expand Down Expand Up @@ -80,6 +81,8 @@ class GenericPointer {
public:
typedef typename ValueType::EncodingType EncodingType; //!< Encoding type from Value
typedef typename ValueType::Ch Ch; //!< Character type from Value
typedef GenericUri<ValueType, Allocator> UriType;


//! A token is the basic units of internal representation.
/*!
Expand Down Expand Up @@ -520,6 +523,70 @@ class GenericPointer {

//@}

//!@name Compute URI
//@{

//! Compute the in-scope URI for a subtree.
// For use with JSON pointers into JSON schema documents.
/*!
\param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
\param rootUri Root URI
\param unresolvedTokenIndex If the pointer cannot resolve a token in the pointer, this parameter can obtain the index of unresolved token.
\param allocator Allocator for Uris
\return Uri if it can be resolved. Otherwise null.
\note
There are only 3 situations when a URI cannot be resolved:
1. A value in the path is not an array nor object.
2. An object value does not contain the token.
3. A token is out of range of an array value.
Use unresolvedTokenIndex to retrieve the token index.
*/
UriType GetUri(ValueType& root, const UriType& rootUri, size_t* unresolvedTokenIndex = 0, Allocator* allocator = 0) const {
static const Ch kIdString[] = { 'i', 'd', '\0' };
static const ValueType kIdValue(kIdString, 2);
UriType base = UriType(rootUri, allocator);
RAPIDJSON_ASSERT(IsValid());
ValueType* v = &root;
for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
switch (v->GetType()) {
case kObjectType:
{
// See if we have an id, and if so resolve with the current base
typename ValueType::MemberIterator m = v->FindMember(kIdValue);
if (m != v->MemberEnd() && (m->value).IsString()) {
UriType here = UriType(m->value, allocator).Resolve(base, allocator);
base = here;
}
m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
if (m == v->MemberEnd())
break;
v = &m->value;
}
continue;
case kArrayType:
if (t->index == kPointerInvalidIndex || t->index >= v->Size())
break;
v = &((*v)[t->index]);
continue;
default:
break;
}

// Error: unresolved token
if (unresolvedTokenIndex)
*unresolvedTokenIndex = static_cast<size_t>(t - tokens_);
return UriType(allocator);
}
return base;
}

UriType GetUri(const ValueType& root, const UriType& rootUri, size_t* unresolvedTokenIndex = 0, Allocator* allocator = 0) const {
return GetUri(const_cast<ValueType&>(root), rootUri, unresolvedTokenIndex, allocator);
}


//!@name Query value
//@{

Expand Down

0 comments on commit c9d350b

Please sign in to comment.