Skip to content

Commit 7ee918f

Browse files
author
Steve Hanson
committed
Merge branch 'master' of https://github.com/Tencent/rapidjson
2 parents 9c1002f + 48fbd8c commit 7ee918f

File tree

11 files changed

+2019
-110
lines changed

11 files changed

+2019
-110
lines changed

bin/unittestschema/idandref.json

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
{
2+
"id": "http://example.com/root.json",
3+
"definitions": {
4+
"A": {
5+
"id": "#foo",
6+
"type": "integer"
7+
},
8+
"B": {
9+
"id": "other.json",
10+
"definitions": {
11+
"X": {
12+
"id": "#bar",
13+
"type": "boolean"
14+
},
15+
"Y": {
16+
"$ref": "#/definitions/X"
17+
},
18+
"W": {
19+
"$ref": "#/definitions/Y"
20+
},
21+
"Z": {
22+
"$ref": "#bar"
23+
},
24+
"N": {
25+
"properties": {
26+
"NX": {
27+
"$ref": "#/definitions/X"
28+
}
29+
}
30+
}
31+
}
32+
}
33+
},
34+
"properties": {
35+
"PA1": {
36+
"$ref": "http://example.com/root.json#/definitions/A"
37+
},
38+
"PA2": {
39+
"$ref": "#/definitions/A"
40+
},
41+
"PA3": {
42+
"$ref": "#foo"
43+
},
44+
"PX1": {
45+
"$ref": "#/definitions/B/definitions/X"
46+
},
47+
"PX2Y": {
48+
"$ref": "#/definitions/B/definitions/Y"
49+
},
50+
"PX3Z": {
51+
"$ref": "#/definitions/B/definitions/Z"
52+
},
53+
"PX4": {
54+
"$ref": "http://example.com/other.json#/definitions/X"
55+
},
56+
"PX5": {
57+
"$ref": "other.json#/definitions/X"
58+
},
59+
"PX6": {
60+
"$ref": "other.json#bar"
61+
},
62+
"PX7W": {
63+
"$ref": "#/definitions/B/definitions/W"
64+
},
65+
"PX8N": {
66+
"$ref": "#/definitions/B/definitions/N"
67+
}
68+
}
69+
}

example/schemavalidator/schemavalidator.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

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

5+
#define RAPIDJSON_HAS_STDSTRING 1
6+
57
#include "rapidjson/error/en.h"
68
#include "rapidjson/filereadstream.h"
79
#include "rapidjson/schema.h"

include/rapidjson/document.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1951,7 +1951,7 @@ class GenericValue {
19511951
case kArrayType:
19521952
if (RAPIDJSON_UNLIKELY(!handler.StartArray()))
19531953
return false;
1954-
for (const GenericValue* v = Begin(); v != End(); ++v)
1954+
for (ConstValueIterator v = Begin(); v != End(); ++v)
19551955
if (RAPIDJSON_UNLIKELY(!v->Accept(handler)))
19561956
return false;
19571957
return handler.EndArray(data_.a.size);

include/rapidjson/internal/strfunc.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,20 @@ inline SizeType StrLen(const wchar_t* s) {
4545
return SizeType(std::wcslen(s));
4646
}
4747

48+
//! Custom strcmpn() which works on different character types.
49+
/*! \tparam Ch Character type (e.g. char, wchar_t, short)
50+
\param s1 Null-terminated input string.
51+
\param s2 Null-terminated input string.
52+
\return 0 if equal
53+
*/
54+
template<typename Ch>
55+
inline int StrCmp(const Ch* s1, const Ch* s2) {
56+
RAPIDJSON_ASSERT(s1 != 0);
57+
RAPIDJSON_ASSERT(s2 != 0);
58+
while(*s1 && (*s1 == *s2)) { s1++; s2++; }
59+
return static_cast<unsigned>(*s1) < static_cast<unsigned>(*s2) ? -1 : static_cast<unsigned>(*s1) > static_cast<unsigned>(*s2);
60+
}
61+
4862
//! Returns number of code points in a encoded string.
4963
template<typename Encoding>
5064
bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) {

include/rapidjson/pointer.h

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#define RAPIDJSON_POINTER_H_
1717

1818
#include "document.h"
19+
#include "uri.h"
1920
#include "internal/itoa.h"
2021

2122
#ifdef __clang__
@@ -80,6 +81,8 @@ class GenericPointer {
8081
public:
8182
typedef typename ValueType::EncodingType EncodingType; //!< Encoding type from Value
8283
typedef typename ValueType::Ch Ch; //!< Character type from Value
84+
typedef GenericUri<ValueType, Allocator> UriType;
85+
8386

8487
//! A token is the basic units of internal representation.
8588
/*!
@@ -163,7 +166,7 @@ class GenericPointer {
163166
GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(const_cast<Token*>(tokens)), tokenCount_(tokenCount), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {}
164167

165168
//! Copy constructor.
166-
GenericPointer(const GenericPointer& rhs) : allocator_(rhs.allocator_), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
169+
GenericPointer(const GenericPointer& rhs) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
167170
*this = rhs;
168171
}
169172

@@ -520,6 +523,70 @@ class GenericPointer {
520523

521524
//@}
522525

526+
//!@name Compute URI
527+
//@{
528+
529+
//! Compute the in-scope URI for a subtree.
530+
// For use with JSON pointers into JSON schema documents.
531+
/*!
532+
\param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
533+
\param rootUri Root URI
534+
\param unresolvedTokenIndex If the pointer cannot resolve a token in the pointer, this parameter can obtain the index of unresolved token.
535+
\param allocator Allocator for Uris
536+
\return Uri if it can be resolved. Otherwise null.
537+
538+
\note
539+
There are only 3 situations when a URI cannot be resolved:
540+
1. A value in the path is not an array nor object.
541+
2. An object value does not contain the token.
542+
3. A token is out of range of an array value.
543+
544+
Use unresolvedTokenIndex to retrieve the token index.
545+
*/
546+
UriType GetUri(ValueType& root, const UriType& rootUri, size_t* unresolvedTokenIndex = 0, Allocator* allocator = 0) const {
547+
static const Ch kIdString[] = { 'i', 'd', '\0' };
548+
static const ValueType kIdValue(kIdString, 2);
549+
UriType base = UriType(rootUri, allocator);
550+
RAPIDJSON_ASSERT(IsValid());
551+
ValueType* v = &root;
552+
for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
553+
switch (v->GetType()) {
554+
case kObjectType:
555+
{
556+
// See if we have an id, and if so resolve with the current base
557+
typename ValueType::MemberIterator m = v->FindMember(kIdValue);
558+
if (m != v->MemberEnd() && (m->value).IsString()) {
559+
UriType here = UriType(m->value, allocator).Resolve(base, allocator);
560+
base = here;
561+
}
562+
m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
563+
if (m == v->MemberEnd())
564+
break;
565+
v = &m->value;
566+
}
567+
continue;
568+
case kArrayType:
569+
if (t->index == kPointerInvalidIndex || t->index >= v->Size())
570+
break;
571+
v = &((*v)[t->index]);
572+
continue;
573+
default:
574+
break;
575+
}
576+
577+
// Error: unresolved token
578+
if (unresolvedTokenIndex)
579+
*unresolvedTokenIndex = static_cast<size_t>(t - tokens_);
580+
return UriType(allocator);
581+
}
582+
return base;
583+
}
584+
585+
UriType GetUri(const ValueType& root, const UriType& rootUri, size_t* unresolvedTokenIndex = 0, Allocator* allocator = 0) const {
586+
return GetUri(const_cast<ValueType&>(root), rootUri, unresolvedTokenIndex, allocator);
587+
}
588+
589+
523590
//!@name Query value
524591
//@{
525592

0 commit comments

Comments
 (0)