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
7ef7ba13
Commit
7ef7ba13
authored
May 17, 2015
by
miloyip
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactor: aggregate parallel validators
parent
5e220bbf
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
103 additions
and
106 deletions
+103
-106
schema.h
include/rapidjson/schema.h
+103
-106
No files found.
include/rapidjson/schema.h
View file @
7ef7ba13
...
...
@@ -122,13 +122,14 @@ public:
};
///////////////////////////////////////////////////////////////////////////////
// ISchema
Validator
Factory
// ISchema
State
Factory
template
<
typename
SchemaType
>
class
ISchema
Validator
Factory
{
class
ISchema
State
Factory
{
public
:
virtual
~
ISchemaValidatorFactory
()
{}
virtual
ISchemaValidator
*
CreateSchemaValidator
(
const
SchemaType
&
)
const
=
0
;
virtual
~
ISchemaStateFactory
()
{}
virtual
ISchemaValidator
*
CreateSchemaValidator
(
const
SchemaType
&
)
=
0
;
virtual
void
DestroySchemaValidator
(
ISchemaValidator
*
validator
)
=
0
;
};
///////////////////////////////////////////////////////////////////////////////
...
...
@@ -229,7 +230,7 @@ private:
template
<
typename
SchemaDocumentType
>
struct
SchemaValidationContext
{
typedef
Schema
<
SchemaDocumentType
>
SchemaType
;
typedef
ISchema
Validator
Factory
<
SchemaType
>
SchemaValidatorFactoryType
;
typedef
ISchema
State
Factory
<
SchemaType
>
SchemaValidatorFactoryType
;
typedef
GenericValue
<
UTF8
<>
,
CrtAllocator
>
HashCodeArray
;
typedef
typename
SchemaType
::
ValueType
ValueType
;
typedef
typename
ValueType
::
Ch
Ch
;
...
...
@@ -241,27 +242,17 @@ struct SchemaValidationContext {
kPatternValidatorWithAdditionalProperty
};
struct
SchemaValidatorArray
{
SchemaValidatorArray
()
:
validators
(),
count
()
{}
~
SchemaValidatorArray
()
{
for
(
SizeType
i
=
0
;
i
<
count
;
i
++
)
delete
validators
[
i
];
delete
[]
validators
;
}
ISchemaValidator
**
validators
;
SizeType
count
;
};
SchemaValidationContext
(
const
SchemaValidatorFactoryType
*
f
,
CrtAllocator
*
a
,
const
SchemaType
*
s
)
:
SchemaValidationContext
(
SchemaValidatorFactoryType
*
f
,
const
SchemaType
*
s
)
:
factory
(
f
),
allocator
(
a
),
schema
(
s
),
valueSchema
(),
invalidKeyword
(),
hasher
(),
validators
(),
validatorCount
(),
patternPropertiesValidators
(),
patternPropertiesValidatorCount
(),
patternPropertiesSchemas
(),
notValidator
(),
patternPropertiesSchemaCount
(),
valuePatternValidatorType
(
kPatternValidatorOnly
),
objectDependencies
(),
...
...
@@ -273,24 +264,31 @@ struct SchemaValidationContext {
~
SchemaValidationContext
()
{
delete
hasher
;
delete
notValidator
;
if
(
validators
)
{
for
(
SizeType
i
=
0
;
i
<
validatorCount
;
i
++
)
factory
->
DestroySchemaValidator
(
validators
[
i
]);
delete
[]
validators
;
}
if
(
patternPropertiesValidators
)
{
for
(
SizeType
i
=
0
;
i
<
patternPropertiesValidatorCount
;
i
++
)
factory
->
DestroySchemaValidator
(
patternPropertiesValidators
[
i
]);
delete
[]
patternPropertiesValidators
;
}
delete
[]
patternPropertiesSchemas
;
delete
[]
objectDependencies
;
}
const
SchemaValidatorFactoryType
*
factory
;
CrtAllocator
*
allocator
;
// For allocating memory for context
SchemaValidatorFactoryType
*
factory
;
const
SchemaType
*
schema
;
const
SchemaType
*
valueSchema
;
const
Ch
*
invalidKeyword
;
HasherType
*
hasher
;
SchemaValidatorArray
allOfValidators
;
SchemaValidatorArray
anyOfValidators
;
SchemaValidatorArray
oneOfValidators
;
SchemaValidatorArray
dependencyValidators
;
SchemaValidatorArray
patternPropertiesValidators
;
ISchemaValidator
**
validators
;
SizeType
validatorCount
;
ISchemaValidator
**
patternPropertiesValidators
;
SizeType
patternPropertiesValidatorCount
;
const
SchemaType
**
patternPropertiesSchemas
;
ISchemaValidator
*
notValidator
;
//
ISchemaValidator* notValidator;
SizeType
patternPropertiesSchemaCount
;
PatternValidatorType
valuePatternValidatorType
;
PatternValidatorType
objectPatternValidatorType
;
...
...
@@ -326,6 +324,7 @@ public:
enumCount_
(),
not_
(),
type_
((
1
<<
kTotalSchemaType
)
-
1
),
// typeless
validatorCount_
(),
properties_
(),
additionalPropertiesSchema_
(),
patternProperties_
(),
...
...
@@ -381,8 +380,11 @@ public:
AssignIfExist
(
anyOf_
,
document
,
p
,
value
,
GetAnyOfString
());
AssignIfExist
(
oneOf_
,
document
,
p
,
value
,
GetOneOfString
());
if
(
const
ValueType
*
v
=
GetMember
(
value
,
GetNotString
()))
if
(
const
ValueType
*
v
=
GetMember
(
value
,
GetNotString
()))
{
document
->
CreateSchema
(
&
not_
,
p
.
Append
(
GetNotString
()),
*
v
);
notValidatorIndex_
=
validatorCount_
;
validatorCount_
++
;
}
// Object
...
...
@@ -472,6 +474,8 @@ public:
else
if
(
itr
->
value
.
IsObject
())
{
hasSchemaDependencies_
=
true
;
document
->
CreateSchema
(
&
properties_
[
sourceIndex
].
dependenciesSchema
,
q
.
Append
(
itr
->
name
),
itr
->
value
);
properties_
[
sourceIndex
].
dependenciesValidatorIndex
=
validatorCount_
;
validatorCount_
++
;
}
}
}
...
...
@@ -583,15 +587,15 @@ public:
}
bool
EndValue
(
Context
&
context
)
const
{
if
(
context
.
patternPropertiesValidator
s
.
c
ount
>
0
)
{
if
(
context
.
patternPropertiesValidator
C
ount
>
0
)
{
bool
otherValid
=
false
;
SizeType
count
=
context
.
patternPropertiesValidator
s
.
c
ount
;
SizeType
count
=
context
.
patternPropertiesValidator
C
ount
;
if
(
context
.
objectPatternValidatorType
!=
Context
::
kPatternValidatorOnly
)
otherValid
=
context
.
patternPropertiesValidators
.
validators
[
--
count
]
->
IsValid
();
otherValid
=
context
.
patternPropertiesValidators
[
--
count
]
->
IsValid
();
bool
patternValid
=
true
;
for
(
SizeType
i
=
0
;
i
<
count
;
i
++
)
if
(
!
context
.
patternPropertiesValidators
.
validators
[
i
]
->
IsValid
())
{
if
(
!
context
.
patternPropertiesValidators
[
i
]
->
IsValid
())
{
patternValid
=
false
;
break
;
}
...
...
@@ -618,13 +622,13 @@ public:
}
if
(
allOf_
.
schemas
)
for
(
SizeType
i
=
0
;
i
<
allOf_
.
count
;
i
++
)
if
(
!
context
.
allOfValidators
.
validators
[
i
]
->
IsValid
())
for
(
SizeType
i
=
allOf_
.
begin
;
i
<
allOf_
.
begin
+
allOf_
.
count
;
i
++
)
if
(
!
context
.
validators
[
i
]
->
IsValid
())
RAPIDJSON_INVALID_KEYWORD_RETURN
(
GetAllOfString
());
if
(
anyOf_
.
schemas
)
{
for
(
SizeType
i
=
0
;
i
<
anyOf_
.
count
;
i
++
)
if
(
context
.
anyOfValidators
.
validators
[
i
]
->
IsValid
())
for
(
SizeType
i
=
anyOf_
.
begin
;
i
<
anyOf_
.
begin
+
anyOf_
.
count
;
i
++
)
if
(
context
.
validators
[
i
]
->
IsValid
())
goto
foundAny
;
RAPIDJSON_INVALID_KEYWORD_RETURN
(
GetAnyOfString
());
foundAny
:
;
...
...
@@ -632,8 +636,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
=
oneOf_
.
begin
;
i
<
oneOf_
.
begin
+
oneOf_
.
count
;
i
++
)
if
(
context
.
validators
[
i
]
->
IsValid
())
{
if
(
oneValid
)
RAPIDJSON_INVALID_KEYWORD_RETURN
(
GetOneOfString
());
else
...
...
@@ -643,7 +647,7 @@ public:
RAPIDJSON_INVALID_KEYWORD_RETURN
(
GetOneOfString
());
}
if
(
not_
&&
context
.
notValidator
->
IsValid
())
if
(
not_
&&
context
.
validators
[
notValidatorIndex_
]
->
IsValid
())
RAPIDJSON_INVALID_KEYWORD_RETURN
(
GetNotString
());
return
true
;
...
...
@@ -808,7 +812,7 @@ public:
RAPIDJSON_INVALID_KEYWORD_RETURN
(
GetDependenciesString
());
}
else
if
(
properties_
[
sourceIndex
].
dependenciesSchema
)
if
(
!
context
.
dependencyValidators
.
validators
[
source
Index
]
->
IsValid
())
if
(
!
context
.
validators
[
properties_
[
sourceIndex
].
dependenciesValidator
Index
]
->
IsValid
())
RAPIDJSON_INVALID_KEYWORD_RETURN
(
GetDependenciesString
());
}
}
...
...
@@ -907,6 +911,7 @@ private:
SchemaArray
()
:
schemas
(),
count
()
{}
~
SchemaArray
()
{
AllocatorType
::
Free
(
schemas
);
}
const
SchemaType
**
schemas
;
SizeType
begin
;
// begin index of context.validators
SizeType
count
;
};
...
...
@@ -954,6 +959,8 @@ private:
memset
(
out
.
schemas
,
0
,
sizeof
(
Schema
*
)
*
out
.
count
);
for
(
SizeType
i
=
0
;
i
<
out
.
count
;
i
++
)
document
->
CreateSchema
(
&
out
.
schemas
[
i
],
q
.
Append
(
i
),
(
*
v
)[
i
]);
out
.
begin
=
validatorCount_
;
validatorCount_
+=
out
.
count
;
}
}
}
...
...
@@ -995,34 +1002,35 @@ private:
if
(
enum_
||
context
.
arrayUniqueness
)
context
.
hasher
=
new
HasherType
;
if
(
validatorCount_
)
{
RAPIDJSON_ASSERT
(
context
.
validators
==
0
);
context
.
validators
=
new
ISchemaValidator
*
[
validatorCount_
];
context
.
validatorCount
=
validatorCount_
;
if
(
allOf_
.
schemas
)
CreateSchemaValidators
(
context
,
context
.
allOfValidators
,
allOf_
);
CreateSchemaValidators
(
context
,
allOf_
);
if
(
anyOf_
.
schemas
)
CreateSchemaValidators
(
context
,
context
.
anyOfValidators
,
anyOf_
);
CreateSchemaValidators
(
context
,
anyOf_
);
if
(
oneOf_
.
schemas
)
CreateSchemaValidators
(
context
,
context
.
oneOfValidators
,
oneOf_
);
CreateSchemaValidators
(
context
,
oneOf_
);
if
(
not_
&&
!
context
.
notValidator
)
context
.
notValidator
=
context
.
factory
->
CreateSchemaValidator
(
*
not_
);
if
(
not_
)
context
.
validators
[
notValidatorIndex_
]
=
context
.
factory
->
CreateSchemaValidator
(
*
not_
);
if
(
hasSchemaDependencies_
&&
!
context
.
dependencyValidators
.
validators
)
{
context
.
dependencyValidators
.
validators
=
new
ISchemaValidator
*
[
propertyCount_
];
context
.
dependencyValidators
.
count
=
propertyCount_
;
if
(
hasSchemaDependencies_
)
{
for
(
SizeType
i
=
0
;
i
<
propertyCount_
;
i
++
)
context
.
dependencyValidators
.
validators
[
i
]
=
properties_
[
i
].
dependenciesSchema
?
context
.
factory
->
CreateSchemaValidator
(
*
properties_
[
i
].
dependenciesSchema
)
:
0
;
if
(
properties_
[
i
].
dependenciesSchema
)
context
.
validators
[
properties_
[
i
].
dependenciesValidatorIndex
]
=
context
.
factory
->
CreateSchemaValidator
(
*
properties_
[
i
].
dependenciesSchema
);
}
}
return
true
;
}
void
CreateSchemaValidators
(
Context
&
context
,
typename
Context
::
SchemaValidatorArray
&
validators
,
const
SchemaArray
&
schemas
)
const
{
if
(
!
validators
.
validators
)
{
validators
.
validators
=
new
ISchemaValidator
*
[
schemas
.
count
];
validators
.
count
=
schemas
.
count
;
void
CreateSchemaValidators
(
Context
&
context
,
const
SchemaArray
&
schemas
)
const
{
for
(
SizeType
i
=
0
;
i
<
schemas
.
count
;
i
++
)
validators
.
validators
[
i
]
=
context
.
factory
->
CreateSchemaValidator
(
*
schemas
.
schemas
[
i
]);
}
context
.
validators
[
schemas
.
begin
+
i
]
=
context
.
factory
->
CreateSchemaValidator
(
*
schemas
.
schemas
[
i
]);
}
// O(n)
...
...
@@ -1126,11 +1134,12 @@ private:
}
struct
Property
{
Property
()
:
schema
(),
dependenciesSchema
(),
dependencies
(),
required
(
false
)
{}
Property
()
:
schema
(),
dependenciesSchema
(),
dependencies
ValidatorIndex
(),
dependencies
(),
required
(
false
)
{}
~
Property
()
{
AllocatorType
::
Free
(
dependencies
);
}
SValue
name
;
const
SchemaType
*
schema
;
const
SchemaType
*
dependenciesSchema
;
SizeType
dependenciesValidatorIndex
;
bool
*
dependencies
;
bool
required
;
};
...
...
@@ -1155,6 +1164,8 @@ private:
SchemaArray
oneOf_
;
const
SchemaType
*
not_
;
unsigned
type_
;
// bitmask of kSchemaType
SizeType
validatorCount_
;
SizeType
notValidatorIndex_
;
Property
*
properties_
;
const
SchemaType
*
additionalPropertiesSchema_
;
...
...
@@ -1394,7 +1405,7 @@ typedef IGenericRemoteSchemaDocumentProvider<SchemaDocument> IRemoteSchemaDocume
template
<
typename
SchemaDocumentType
,
typename
OutputHandler
=
BaseReaderHandler
<
typename
SchemaDocumentType
::
SchemaType
::
EncodingType
>
,
typename
StateAllocator
=
CrtAllocator
>
class
GenericSchemaValidator
:
public
internal
::
ISchema
Validator
Factory
<
typename
SchemaDocumentType
::
SchemaType
>
,
public
internal
::
ISchema
State
Factory
<
typename
SchemaDocumentType
::
SchemaType
>
,
public
internal
::
ISchemaValidator
{
public
:
...
...
@@ -1413,26 +1424,7 @@ public:
root_
(
schemaDocument
.
GetRoot
()),
outputHandler_
(
nullOutputHandler_
),
schemaStack_
(
allocator
,
schemaStackCapacity
),
documentStack_
(
allocator
,
documentStackCapacity
),
valid_
(
true
)
#if RAPIDJSON_SCHEMA_VERBOSE
,
depth_
(
0
)
#endif
{
}
GenericSchemaValidator
(
const
SchemaDocumentType
&
schemaDocument
,
OutputHandler
&
outputHandler
,
StateAllocator
*
allocator
=
0
,
size_t
schemaStackCapacity
=
kDefaultSchemaStackCapacity
,
size_t
documentStackCapacity
=
kDefaultDocumentStackCapacity
)
:
schemaDocument_
(
&
schemaDocument
),
root_
(
schemaDocument
.
GetRoot
()),
outputHandler_
(
outputHandler
),
schemaStack_
(
allocator
,
schemaStackCapacity
),
documentStack_
(
allocator
,
documentStackCapacity
),
documentStack_
(
&
GetStateAllocator
(),
documentStackCapacity
),
valid_
(
true
)
#if RAPIDJSON_SCHEMA_VERBOSE
,
depth_
(
0
)
...
...
@@ -1466,6 +1458,10 @@ public:
return
documentStack_
.
Empty
()
?
PointerType
()
:
PointerType
(
documentStack_
.
template
Bottom
<
Ch
>
(),
documentStack_
.
GetSize
()
/
sizeof
(
Ch
));
}
StateAllocator
&
GetStateAllocator
()
{
return
schemaStack_
.
GetAllocator
();
}
#if RAPIDJSON_SCHEMA_VERBOSE
#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_() \
RAPIDJSON_MULTILINEMACRO_BEGIN\
...
...
@@ -1488,25 +1484,12 @@ RAPIDJSON_MULTILINEMACRO_END
for (Context* context = schemaStack_.template Bottom<Context>(); context != schemaStack_.template End<Context>(); context++) {\
if (context->hasher)\
context->hasher->method arg2;\
if (context->allOfValidators.validators)\
for (SizeType i_ = 0; i_ < context->allOfValidators.count; i_++)\
static_cast<GenericSchemaValidator*>(context->allOfValidators.validators[i_])->method arg2;\
if (context->anyOfValidators.validators)\
for (SizeType i_ = 0; i_ < context->anyOfValidators.count; i_++)\
static_cast<GenericSchemaValidator*>(context->anyOfValidators.validators[i_])->method arg2;\
if (context->oneOfValidators.validators)\
for (SizeType i_ = 0; i_ < context->oneOfValidators.count; i_++)\
static_cast<GenericSchemaValidator*>(context->oneOfValidators.validators[i_])->method arg2;\
if (context->notValidator)\
static_cast<GenericSchemaValidator*>(context->notValidator)->method arg2;\
if (context->dependencyValidators.validators)\
for (SizeType i_ = 0; i_ < context->dependencyValidators.count; i_++)\
if (context->dependencyValidators.validators[i_])\
static_cast<GenericSchemaValidator*>(context->dependencyValidators.validators[i_])->method arg2;\
if (context->patternPropertiesValidators.validators)\
for (SizeType i_ = 0; i_ < context->patternPropertiesValidators.count; i_++)\
if (context->patternPropertiesValidators.validators[i_])\
static_cast<GenericSchemaValidator*>(context->patternPropertiesValidators.validators[i_])->method arg2; \
if (context->validators)\
for (SizeType i_ = 0; i_ < context->validatorCount; i_++)\
static_cast<GenericSchemaValidator*>(context->validators[i_])->method arg2;\
if (context->patternPropertiesValidators)\
for (SizeType i_ = 0; i_ < context->patternPropertiesValidatorCount; i_++)\
static_cast<GenericSchemaValidator*>(context->patternPropertiesValidators[i_])->method arg2;\
}
#define RAPIDJSON_SCHEMA_HANDLE_END_(method, arg2)\
...
...
@@ -1566,13 +1549,27 @@ RAPIDJSON_MULTILINEMACRO_END
#undef RAPIDJSON_SCHEMA_HANDLE_PARALLEL_
#undef RAPIDJSON_SCHEMA_HANDLE_VALUE_
// Implementation of ISchema
Validator
Factory<SchemaType>
virtual
ISchemaValidator
*
CreateSchemaValidator
(
const
SchemaType
&
root
)
const
{
// Implementation of ISchema
State
Factory<SchemaType>
virtual
ISchemaValidator
*
CreateSchemaValidator
(
const
SchemaType
&
root
)
{
return
new
GenericSchemaValidator
(
*
schemaDocument_
,
root
#if RAPIDJSON_SCHEMA_VERBOSE
,
depth_
+
1
#endif
);
// GenericSchemaValidator *validator = GetStateAllocator().Malloc(sizeof(GenericSchemaValidator));
// new (validator) GenericSchemaValidator(*schemaDocument_, root
// #if RAPIDJSON_SCHEMA_VERBOSE
// , depth_ + 1
// #endif
// );
// return validator;
}
virtual
void
DestroySchemaValidator
(
ISchemaValidator
*
validator
)
{
delete
validator
;
// validator->~ISchemaValidator();
// StateAllocator::Free(validator);
}
private
:
...
...
@@ -1619,10 +1616,11 @@ private:
if
(
count
>
0
)
{
CurrentContext
().
objectPatternValidatorType
=
patternValidatorType
;
typename
Context
::
SchemaValidatorArray
&
va
=
CurrentContext
().
patternPropertiesValidators
;
va
.
validators
=
new
ISchemaValidator
*
[
count
];
ISchemaValidator
**&
va
=
CurrentContext
().
patternPropertiesValidators
;
SizeType
&
validatorCount
=
CurrentContext
().
patternPropertiesValidatorCount
;
va
=
new
ISchemaValidator
*
[
count
];
for
(
SizeType
i
=
0
;
i
<
count
;
i
++
)
va
.
validators
[
va
.
c
ount
++
]
=
CreateSchemaValidator
(
*
sa
[
i
]);
va
[
validatorC
ount
++
]
=
CreateSchemaValidator
(
*
sa
[
i
]);
}
CurrentContext
().
arrayUniqueness
=
valueUniqueness
;
...
...
@@ -1653,7 +1651,7 @@ private:
for
(
typename
Context
::
HashCodeArray
::
ConstValueIterator
itr
=
context
.
arrayElementHashCodes
.
Begin
();
itr
!=
context
.
arrayElementHashCodes
.
End
();
++
itr
)
if
(
itr
->
GetUint64
()
==
h
)
RAPIDJSON_INVALID_KEYWORD_RETURN
(
SchemaType
::
GetUniqueItemsString
());
context
.
arrayElementHashCodes
.
PushBack
(
h
,
*
context
.
allocator
);
context
.
arrayElementHashCodes
.
PushBack
(
h
,
GetStateAllocator
()
);
}
}
...
...
@@ -1688,7 +1686,7 @@ private:
*
documentStack_
.
template
Push
<
Ch
>
()
=
buffer
[
i
];
}
void
PushSchema
(
const
SchemaType
&
schema
)
{
new
(
schemaStack_
.
template
Push
<
Context
>
())
Context
(
this
,
&
contextAllocator_
,
&
schema
);
}
void
PushSchema
(
const
SchemaType
&
schema
)
{
new
(
schemaStack_
.
template
Push
<
Context
>
())
Context
(
this
,
&
schema
);
}
void
PopSchema
()
{
schemaStack_
.
template
Pop
<
Context
>
(
1
)
->~
Context
();
}
const
SchemaType
&
CurrentSchema
()
const
{
return
*
schemaStack_
.
template
Top
<
Context
>
()
->
schema
;
}
Context
&
CurrentContext
()
{
return
*
schemaStack_
.
template
Top
<
Context
>
();
}
...
...
@@ -1700,7 +1698,6 @@ private:
const
SchemaType
&
root_
;
BaseReaderHandler
<
EncodingType
>
nullOutputHandler_
;
OutputHandler
&
outputHandler_
;
CrtAllocator
contextAllocator_
;
internal
::
Stack
<
StateAllocator
>
schemaStack_
;
//!< stack to store the current path of schema (BaseSchemaType *)
internal
::
Stack
<
StateAllocator
>
documentStack_
;
//!< stack to store the current path of validating document (Ch)
bool
valid_
;
...
...
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