Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
R
rapidjson
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
rapidjson
Commits
314ee228
Commit
314ee228
authored
May 08, 2015
by
Milo Yip
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add multiple patternProperties match
parent
3d3555d3
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
133 additions
and
52 deletions
+133
-52
schema.h
include/rapidjson/schema.h
+132
-52
schematest.cpp
test/unittest/schematest.cpp
+1
-0
No files found.
include/rapidjson/schema.h
View file @
314ee228
...
...
@@ -82,15 +82,30 @@ struct BaseSchemaArray {
SizeType
count
;
};
enum
PatternValidatorType
{
kPatternValidatorOnly
,
kPatternValidatorWithProperty
,
kPatternValidatorWithAdditionalProperty
};
template
<
typename
Encoding
>
struct
SchemaValidationContext
{
SchemaValidationContext
(
const
BaseSchema
<
Encoding
>*
s
)
:
schema
(
s
),
valueSchema
(),
notValidator
(),
objectDependencies
(),
inArray
(
false
)
schema
(
s
),
valueSchema
(),
notValidator
(),
objectDependencies
(),
#if RAPIDJSON_SCHEMA_HAS_REGEX
patternPropertiesSchemas
(),
patternPropertiesSchemaCount
(),
valuePatternValidatorType
(
kPatternValidatorOnly
),
#endif
inArray
(
false
)
{
}
~
SchemaValidationContext
()
{
delete
notValidator
;
#if RAPIDJSON_SCHEMA_HAS_REGEX
delete
patternPropertiesSchemas
;
#endif
delete
[]
objectDependencies
;
}
...
...
@@ -100,6 +115,13 @@ struct SchemaValidationContext {
SchemaValidatorArray
<
Encoding
>
anyOfValidators
;
SchemaValidatorArray
<
Encoding
>
oneOfValidators
;
SchemaValidatorArray
<
Encoding
>
dependencyValidators
;
#if RAPIDJSON_SCHEMA_HAS_REGEX
SchemaValidatorArray
<
Encoding
>
patternPropertiesValidators
;
const
BaseSchema
<
Encoding
>**
patternPropertiesSchemas
;
SizeType
patternPropertiesSchemaCount
;
PatternValidatorType
valuePatternValidatorType
;
PatternValidatorType
objectPatternValidatorType
;
#endif
GenericSchemaValidator
<
Encoding
,
BaseReaderHandler
<>
,
CrtAllocator
>*
notValidator
;
SizeType
objectRequiredCount
;
SizeType
arrayElementIndex
;
...
...
@@ -368,14 +390,43 @@ public:
}
bool
EndValue
(
Context
&
context
)
const
{
if
(
context
.
patternPropertiesValidators
.
count
>
0
)
{
bool
otherValid
=
false
;
SizeType
count
=
context
.
patternPropertiesValidators
.
count
;
if
(
context
.
objectPatternValidatorType
!=
kPatternValidatorOnly
)
otherValid
=
context
.
patternPropertiesValidators
.
validators
[
--
count
]
->
IsValid
();
bool
patternValid
=
true
;
for
(
SizeType
i
=
0
;
i
<
count
;
i
++
)
if
(
!
context
.
patternPropertiesValidators
.
validators
[
i
]
->
IsValid
())
{
patternValid
=
false
;
break
;
}
switch
(
context
.
objectPatternValidatorType
)
{
case
kPatternValidatorOnly
:
if
(
!
patternValid
)
return
false
;
break
;
case
kPatternValidatorWithProperty
:
if
(
!
patternValid
||
!
otherValid
)
return
false
;
break
;
case
kPatternValidatorWithAdditionalProperty
:
if
(
!
patternValid
&&
!
otherValid
)
return
false
;
break
;
}
}
if
(
allOf_
.
schemas
)
for
(
SizeType
i
_
=
0
;
i_
<
allOf_
.
count
;
i_
++
)
if
(
!
context
.
allOfValidators
.
validators
[
i
_
]
->
IsValid
())
for
(
SizeType
i
=
0
;
i
<
allOf_
.
count
;
i
++
)
if
(
!
context
.
allOfValidators
.
validators
[
i
]
->
IsValid
())
return
false
;
if
(
anyOf_
.
schemas
)
{
for
(
SizeType
i
_
=
0
;
i_
<
anyOf_
.
count
;
i_
++
)
if
(
context
.
anyOfValidators
.
validators
[
i
_
]
->
IsValid
())
for
(
SizeType
i
=
0
;
i
<
anyOf_
.
count
;
i
++
)
if
(
context
.
anyOfValidators
.
validators
[
i
]
->
IsValid
())
goto
foundAny
;
return
false
;
foundAny
:
;
...
...
@@ -383,8 +434,8 @@ public:
if
(
oneOf_
.
schemas
)
{
bool
oneValid
=
false
;
for
(
SizeType
i
_
=
0
;
i_
<
oneOf_
.
count
;
i_
++
)
if
(
context
.
oneOfValidators
.
validators
[
i
_
]
->
IsValid
())
{
for
(
SizeType
i
=
0
;
i
<
oneOf_
.
count
;
i
++
)
if
(
context
.
oneOfValidators
.
validators
[
i
]
->
IsValid
())
{
if
(
oneValid
)
return
false
;
else
...
...
@@ -398,21 +449,21 @@ public:
}
bool
Null
(
Context
&
context
)
const
{
Create
LogicValidators
(
context
);
Create
ParallelValidator
(
context
);
return
(
type_
&
(
1
<<
kNullSchemaType
))
&&
(
!
enum_
.
IsArray
()
||
CheckEnum
(
GenericValue
<
Encoding
>
().
Move
()));
}
bool
Bool
(
Context
&
context
,
bool
b
)
const
{
Create
LogicValidators
(
context
);
Create
ParallelValidator
(
context
);
return
(
type_
&
(
1
<<
kBooleanSchemaType
))
&&
(
!
enum_
.
IsArray
()
||
CheckEnum
(
GenericValue
<
Encoding
>
(
b
).
Move
()));
}
bool
Int
(
Context
&
context
,
int
i
)
const
{
Create
LogicValidators
(
context
);
Create
ParallelValidator
(
context
);
if
((
type_
&
((
1
<<
kIntegerSchemaType
)
|
(
1
<<
kNumberSchemaType
)))
==
0
)
return
false
;
...
...
@@ -420,7 +471,7 @@ public:
}
bool
Uint
(
Context
&
context
,
unsigned
u
)
const
{
Create
LogicValidators
(
context
);
Create
ParallelValidator
(
context
);
if
((
type_
&
((
1
<<
kIntegerSchemaType
)
|
(
1
<<
kNumberSchemaType
)))
==
0
)
return
false
;
...
...
@@ -428,7 +479,7 @@ public:
}
bool
Int64
(
Context
&
context
,
int64_t
i
)
const
{
Create
LogicValidators
(
context
);
Create
ParallelValidator
(
context
);
if
((
type_
&
((
1
<<
kIntegerSchemaType
)
|
(
1
<<
kNumberSchemaType
)))
==
0
)
return
false
;
...
...
@@ -436,7 +487,7 @@ public:
}
bool
Uint64
(
Context
&
context
,
uint64_t
u
)
const
{
Create
LogicValidators
(
context
);
Create
ParallelValidator
(
context
);
if
((
type_
&
((
1
<<
kIntegerSchemaType
)
|
(
1
<<
kNumberSchemaType
)))
==
0
)
return
false
;
...
...
@@ -444,7 +495,7 @@ public:
}
bool
Double
(
Context
&
context
,
double
d
)
const
{
Create
LogicValidators
(
context
);
Create
ParallelValidator
(
context
);
if
((
type_
&
(
1
<<
kNumberSchemaType
))
==
0
)
return
false
;
...
...
@@ -453,7 +504,7 @@ public:
bool
String
(
Context
&
context
,
const
Ch
*
str
,
SizeType
length
,
bool
)
const
{
(
void
)
str
;
Create
LogicValidators
(
context
);
Create
ParallelValidator
(
context
);
if
((
type_
&
(
1
<<
kStringSchemaType
))
==
0
)
return
false
;
...
...
@@ -474,7 +525,7 @@ public:
}
bool
StartObject
(
Context
&
context
)
const
{
Create
LogicValidators
(
context
);
Create
ParallelValidator
(
context
);
if
((
type_
&
(
1
<<
kObjectSchemaType
))
==
0
)
return
false
;
...
...
@@ -483,17 +534,37 @@ public:
context
.
objectDependencies
=
new
bool
[
propertyCount_
];
std
::
memset
(
context
.
objectDependencies
,
0
,
sizeof
(
bool
)
*
propertyCount_
);
}
if
(
patternProperties_
)
{
// pre-allocate schema array
SizeType
count
=
patternPropertyCount_
+
1
;
// extra for valuePatternValidatorType
context
.
patternPropertiesSchemas
=
new
const
BaseSchema
<
Encoding
>*
[
count
];
context
.
patternPropertiesSchemaCount
=
0
;
std
::
memset
(
context
.
patternPropertiesSchemas
,
0
,
sizeof
(
BaseSchema
<
Encoding
>*
)
*
count
);
}
return
true
;
}
bool
Key
(
Context
&
context
,
const
Ch
*
str
,
SizeType
len
,
bool
)
const
{
CreateLogicValidators
(
context
);
if
((
type_
&
(
1
<<
kObjectSchemaType
))
==
0
)
return
false
;
#if RAPIDJSON_SCHEMA_HAS_REGEX
if
(
patternProperties_
)
{
context
.
patternPropertiesSchemaCount
=
0
;
for
(
SizeType
i
=
0
;
i
<
patternPropertyCount_
;
i
++
)
if
(
patternProperties_
[
i
].
pattern
&&
IsPatternMatch
(
*
patternProperties_
[
i
].
pattern
,
str
,
len
))
context
.
patternPropertiesSchemas
[
context
.
patternPropertiesSchemaCount
++
]
=
patternProperties_
[
i
].
schema
;
}
#endif
SizeType
index
;
if
(
FindPropertyIndex
(
str
,
len
,
&
index
))
{
context
.
valueSchema
=
properties_
[
index
].
typeless
?
GetTypeless
()
:
properties_
[
index
].
schema
;
const
BaseSchema
<
Encoding
>*
propertySchema
=
properties_
[
index
].
typeless
?
GetTypeless
()
:
properties_
[
index
].
schema
;
if
(
context
.
patternPropertiesSchemaCount
>
0
)
{
context
.
patternPropertiesSchemas
[
context
.
patternPropertiesSchemaCount
++
]
=
propertySchema
;
context
.
valueSchema
=
GetTypeless
();
context
.
valuePatternValidatorType
=
kPatternValidatorWithProperty
;
}
else
context
.
valueSchema
=
propertySchema
;
if
(
properties_
[
index
].
required
)
context
.
objectRequiredCount
++
;
...
...
@@ -504,16 +575,13 @@ public:
return
true
;
}
#if RAPIDJSON_SCHEMA_HAS_REGEX
if
(
patternProperties_
)
for
(
SizeType
i
=
0
;
i
<
patternPropertyCount_
;
i
++
)
if
(
patternProperties_
[
i
].
pattern
&&
IsPatternMatch
(
*
patternProperties_
[
i
].
pattern
,
str
,
len
))
{
context
.
valueSchema
=
patternProperties_
[
i
].
schema
;
return
true
;
}
#endif
if
(
additionalPropertiesSchema_
)
{
if
(
additionalPropertiesSchema_
&&
context
.
patternPropertiesSchemaCount
>
0
)
{
context
.
patternPropertiesSchemas
[
context
.
patternPropertiesSchemaCount
++
]
=
additionalPropertiesSchema_
;
context
.
valueSchema
=
GetTypeless
();
context
.
valuePatternValidatorType
=
kPatternValidatorWithAdditionalProperty
;
}
else
context
.
valueSchema
=
additionalPropertiesSchema_
;
return
true
;
}
...
...
@@ -521,15 +589,15 @@ public:
context
.
valueSchema
=
GetTypeless
();
return
true
;
}
else
#if RAPIDJSON_SCHEMA_HAS_REGEX
return
context
.
patternPropertiesSchemaCount
!=
0
;
// patternProperties are not additional properties
#else
return
false
;
#endif
}
bool
EndObject
(
Context
&
context
,
SizeType
memberCount
)
const
{
CreateLogicValidators
(
context
);
if
((
type_
&
(
1
<<
kObjectSchemaType
))
==
0
)
return
false
;
if
(
context
.
objectRequiredCount
!=
requiredCount_
||
memberCount
<
minProperties_
||
memberCount
>
maxProperties_
)
return
false
;
...
...
@@ -551,7 +619,7 @@ public:
}
bool
StartArray
(
Context
&
context
)
const
{
Create
LogicValidators
(
context
);
Create
ParallelValidator
(
context
);
if
((
type_
&
(
1
<<
kArraySchemaType
))
==
0
)
return
false
;
...
...
@@ -561,10 +629,6 @@ public:
}
bool
EndArray
(
Context
&
context
,
SizeType
elementCount
)
const
{
CreateLogicValidators
(
context
);
if
((
type_
&
(
1
<<
kArraySchemaType
))
==
0
)
return
false
;
context
.
inArray
=
false
;
return
elementCount
>=
minItems_
&&
elementCount
<=
maxItems_
;
}
...
...
@@ -652,7 +716,7 @@ private:
return
false
;
}
void
Create
LogicValidators
(
Context
&
context
)
const
{
void
Create
ParallelValidator
(
Context
&
context
)
const
{
if
(
allOf_
.
schemas
)
CreateSchemaValidators
(
context
.
allOfValidators
,
allOf_
);
if
(
anyOf_
.
schemas
)
CreateSchemaValidators
(
context
.
anyOfValidators
,
anyOf_
);
if
(
oneOf_
.
schemas
)
CreateSchemaValidators
(
context
.
oneOfValidators
,
oneOf_
);
...
...
@@ -859,7 +923,7 @@ public:
if (!valid_) return false; \
if (!BeginValue() || !CurrentSchema().method arg1) return valid_ = false;
#define RAPIDJSON_SCHEMA_HANDLE_
LOGIC
_(method, arg2)\
#define RAPIDJSON_SCHEMA_HANDLE_
PARALLEL
_(method, arg2)\
for (Context* context = schemaStack_.template Bottom<Context>(); context <= schemaStack_.template Top<Context>(); context++) {\
if (context->allOfValidators.validators)\
for (SizeType i_ = 0; i_ < context->allOfValidators.count; i_++)\
...
...
@@ -876,14 +940,18 @@ public:
for (SizeType i_ = 0; i_ < context->dependencyValidators.count; i_++)\
if (context->dependencyValidators.validators[i_])\
context->dependencyValidators.validators[i_]->method arg2;\
if (context->patternPropertiesValidators.validators)\
for (SizeType i_ = 0; i_ < context->patternPropertiesValidators.count; i_++)\
if (context->patternPropertiesValidators.validators[i_])\
context->patternPropertiesValidators.validators[i_]->method arg2; \
}
#define RAPIDJSON_SCHEMA_HANDLE_END_(method, arg2)\
return valid_ = EndValue() && outputHandler_.method arg2
#define RAPIDJSON_SCHEMA_HANDLE_VALUE_(method, arg1, arg2) \
RAPIDJSON_SCHEMA_HANDLE_BEGIN_(method, arg1);\
RAPIDJSON_SCHEMA_HANDLE_
LOGIC
_(method, arg2);\
RAPIDJSON_SCHEMA_HANDLE_BEGIN_
(method, arg1);\
RAPIDJSON_SCHEMA_HANDLE_
PARALLEL
_(method, arg2);\
RAPIDJSON_SCHEMA_HANDLE_END_ (method, arg2)
bool
Null
()
{
RAPIDJSON_SCHEMA_HANDLE_VALUE_
(
Null
,
(
CurrentContext
()
),
(
));
}
...
...
@@ -898,39 +966,39 @@ public:
bool
StartObject
()
{
RAPIDJSON_SCHEMA_HANDLE_BEGIN_
(
StartObject
,
(
CurrentContext
()));
RAPIDJSON_SCHEMA_HANDLE_
LOGIC
_
(
StartObject
,
());
RAPIDJSON_SCHEMA_HANDLE_
PARALLEL
_
(
StartObject
,
());
return
valid_
=
outputHandler_
.
StartObject
();
}
bool
Key
(
const
Ch
*
str
,
SizeType
len
,
bool
copy
)
{
if
(
!
valid_
)
return
false
;
if
(
!
CurrentSchema
().
Key
(
CurrentContext
(),
str
,
len
,
copy
))
return
valid_
=
false
;
RAPIDJSON_SCHEMA_HANDLE_
LOGIC
_
(
Key
,
(
str
,
len
,
copy
));
RAPIDJSON_SCHEMA_HANDLE_
PARALLEL
_
(
Key
,
(
str
,
len
,
copy
));
return
valid_
=
outputHandler_
.
Key
(
str
,
len
,
copy
);
}
bool
EndObject
(
SizeType
memberCount
)
{
if
(
!
valid_
)
return
false
;
RAPIDJSON_SCHEMA_HANDLE_
LOGIC
_
(
EndObject
,
(
memberCount
));
RAPIDJSON_SCHEMA_HANDLE_
PARALLEL
_
(
EndObject
,
(
memberCount
));
if
(
!
CurrentSchema
().
EndObject
(
CurrentContext
(),
memberCount
))
return
valid_
=
false
;
RAPIDJSON_SCHEMA_HANDLE_END_
(
EndObject
,
(
memberCount
));
RAPIDJSON_SCHEMA_HANDLE_END_
(
EndObject
,
(
memberCount
));
}
bool
StartArray
()
{
RAPIDJSON_SCHEMA_HANDLE_BEGIN_
(
StartArray
,
(
CurrentContext
()));
RAPIDJSON_SCHEMA_HANDLE_
LOGIC
_
(
StartArray
,
());
RAPIDJSON_SCHEMA_HANDLE_
PARALLEL
_
(
StartArray
,
());
return
valid_
=
outputHandler_
.
StartArray
();
}
bool
EndArray
(
SizeType
elementCount
)
{
if
(
!
valid_
)
return
false
;
RAPIDJSON_SCHEMA_HANDLE_
LOGIC
_
(
EndArray
,
(
elementCount
));
RAPIDJSON_SCHEMA_HANDLE_
PARALLEL
_
(
EndArray
,
(
elementCount
));
if
(
!
CurrentSchema
().
EndArray
(
CurrentContext
(),
elementCount
))
return
valid_
=
false
;
RAPIDJSON_SCHEMA_HANDLE_END_
(
EndArray
,
(
elementCount
));
RAPIDJSON_SCHEMA_HANDLE_END_
(
EndArray
,
(
elementCount
));
}
#undef RAPIDJSON_SCHEMA_HANDLE_BEGIN_
#undef RAPIDJSON_SCHEMA_HANDLE_
LOGIC
_
#undef RAPIDJSON_SCHEMA_HANDLE_
PARALLEL
_
#undef RAPIDJSON_SCHEMA_HANDLE_VALUE_
// Implementation of ISchemaValidatorFactory<Encoding>
...
...
@@ -963,8 +1031,20 @@ private:
if
(
!
CurrentSchema
().
BeginValue
(
CurrentContext
()))
return
false
;
SizeType
count
=
CurrentContext
().
patternPropertiesSchemaCount
;
const
BaseSchemaType
**
sa
=
CurrentContext
().
patternPropertiesSchemas
;
PatternValidatorType
patternValidatorType
=
CurrentContext
().
valuePatternValidatorType
;
if
(
CurrentContext
().
valueSchema
)
PushSchema
(
*
CurrentContext
().
valueSchema
);
if
(
count
>
0
)
{
CurrentContext
().
objectPatternValidatorType
=
patternValidatorType
;
SchemaValidatorArray
<
Encoding
>&
va
=
CurrentContext
().
patternPropertiesValidators
;
va
.
validators
=
new
GenericSchemaValidator
*
[
count
];
for
(
SizeType
i
=
0
;
i
<
count
;
i
++
)
va
.
validators
[
va
.
count
++
]
=
CreateSchemaValidator
(
*
sa
[
i
]);
}
}
return
true
;
}
...
...
@@ -982,7 +1062,7 @@ private:
const
BaseSchemaType
&
CurrentSchema
()
{
return
*
schemaStack_
.
template
Top
<
Context
>
()
->
schema
;
}
Context
&
CurrentContext
()
{
return
*
schemaStack_
.
template
Top
<
Context
>
();
}
static
const
size_t
kDefaultSchemaStackCapacity
=
256
;
static
const
size_t
kDefaultSchemaStackCapacity
=
1024
;
//static const size_t kDefaultDocumentStackCapacity = 256;
const
BaseSchemaType
&
root_
;
BaseReaderHandler
<
Encoding
>
nullOutputHandler_
;
...
...
test/unittest/schematest.cpp
View file @
314ee228
...
...
@@ -666,6 +666,7 @@ static char* ReadFile(const char* filename, size_t& length) {
TEST
(
SchemaValidator
,
TestSuite
)
{
const
char
*
filenames
[]
=
{
"properties.json"
,
"additionalItems.json"
,
"additionalProperties.json"
,
"allOf.json"
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment