mirror of
https://github.com/Tencent/rapidjson.git
synced 2025-03-10 03:29:59 +01:00
Add 64-bit integer schema validations
This commit is contained in:
parent
1a59ab50dc
commit
979088de60
@ -298,10 +298,6 @@ public:
|
|||||||
pattern_(),
|
pattern_(),
|
||||||
minLength_(0),
|
minLength_(0),
|
||||||
maxLength_(~SizeType(0)),
|
maxLength_(~SizeType(0)),
|
||||||
minimum_(-HUGE_VAL),
|
|
||||||
maximum_(HUGE_VAL),
|
|
||||||
multipleOf_(0),
|
|
||||||
hasMultipleOf_(false),
|
|
||||||
exclusiveMinimum_(false),
|
exclusiveMinimum_(false),
|
||||||
exclusiveMaximum_(false)
|
exclusiveMaximum_(false)
|
||||||
{
|
{
|
||||||
@ -478,26 +474,20 @@ public:
|
|||||||
pattern_ = CreatePattern(*v);
|
pattern_ = CreatePattern(*v);
|
||||||
|
|
||||||
// Number
|
// Number
|
||||||
ConstMemberIterator minimumItr = value.FindMember("minimum");
|
if (const ValueType* v = GetMember(value, "minimum"))
|
||||||
if (minimumItr != value.MemberEnd())
|
if (v->IsNumber())
|
||||||
if (minimumItr->value.IsNumber())
|
minimum_.CopyFrom(*v, *allocator_);
|
||||||
minimum_ = minimumItr->value.GetDouble();
|
|
||||||
|
|
||||||
ConstMemberIterator maximumItr = value.FindMember("maximum");
|
if (const ValueType* v = GetMember(value, "maximum"))
|
||||||
if (maximumItr != value.MemberEnd())
|
if (v->IsNumber())
|
||||||
if (maximumItr->value.IsNumber())
|
maximum_.CopyFrom(*v, *allocator_);
|
||||||
maximum_ = maximumItr->value.GetDouble();
|
|
||||||
|
|
||||||
AssignIfExist(exclusiveMinimum_, value, "exclusiveMinimum");
|
AssignIfExist(exclusiveMinimum_, value, "exclusiveMinimum");
|
||||||
AssignIfExist(exclusiveMaximum_, value, "exclusiveMaximum");
|
AssignIfExist(exclusiveMaximum_, value, "exclusiveMaximum");
|
||||||
|
|
||||||
ConstMemberIterator multipleOfItr = value.FindMember("multipleOf");
|
if (const ValueType* v = GetMember(value, "multipleOf"))
|
||||||
if (multipleOfItr != value.MemberEnd()) {
|
if (v->IsNumber() && v->GetDouble() > 0.0)
|
||||||
if (multipleOfItr->value.IsNumber()) {
|
multipleOf_.CopyFrom(*v, *allocator_);
|
||||||
multipleOf_ = multipleOfItr->value.GetDouble();
|
|
||||||
hasMultipleOf_ = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~Schema() {
|
~Schema() {
|
||||||
@ -629,33 +619,43 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Int(Context& context, int i) const {
|
bool Int(Context& context, int i) const {
|
||||||
if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType))))
|
if (!CheckInt(context, i))
|
||||||
RAPIDJSON_INVALID_KEYWORD_RETURN("type");
|
return false;
|
||||||
return CheckDouble(context, i) && CreateParallelValidator(context);
|
return CreateParallelValidator(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Uint(Context& context, unsigned u) const {
|
bool Uint(Context& context, unsigned u) const {
|
||||||
if ((type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType))))
|
if (!CheckUint(context, u))
|
||||||
RAPIDJSON_INVALID_KEYWORD_RETURN("type");
|
return false;
|
||||||
return CheckDouble(context, u) && CreateParallelValidator(context);
|
return CreateParallelValidator(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Int64(Context& context, int64_t i) const {
|
bool Int64(Context& context, int64_t i) const {
|
||||||
if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType))))
|
if (!CheckInt(context, i))
|
||||||
RAPIDJSON_INVALID_KEYWORD_RETURN("type");
|
return false;
|
||||||
return CheckDouble(context, i) && CreateParallelValidator(context);
|
return CreateParallelValidator(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Uint64(Context& context, uint64_t u) const {
|
bool Uint64(Context& context, uint64_t u) const {
|
||||||
if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType))))
|
if (!CheckUint(context, u))
|
||||||
RAPIDJSON_INVALID_KEYWORD_RETURN("type");
|
return false;
|
||||||
return CheckDouble(context, u) && CreateParallelValidator(context);
|
return CreateParallelValidator(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Double(Context& context, double d) const {
|
bool Double(Context& context, double d) const {
|
||||||
if (!(type_ & (1 << kNumberSchemaType)))
|
if (!(type_ & (1 << kNumberSchemaType)))
|
||||||
RAPIDJSON_INVALID_KEYWORD_RETURN("type");
|
RAPIDJSON_INVALID_KEYWORD_RETURN("type");
|
||||||
return CheckDouble(context, d) && CreateParallelValidator(context);
|
|
||||||
|
if (!minimum_.IsNull() && !CheckDoubleMinimum(context, d))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!maximum_.IsNull() && !CheckDoubleMaximum(context, d))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!multipleOf_.IsNull() && !CheckDoubleMultipleOf(context, d))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return CreateParallelValidator(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool String(Context& context, const Ch* str, SizeType length, bool) const {
|
bool String(Context& context, const Ch* str, SizeType length, bool) const {
|
||||||
@ -963,20 +963,92 @@ private:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CheckDouble(Context& context, double d) const {
|
bool CheckInt(Context& context, int64_t i) const {
|
||||||
if (exclusiveMinimum_ ? d <= minimum_ : d < minimum_)
|
if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType))))
|
||||||
RAPIDJSON_INVALID_KEYWORD_RETURN("minimum");
|
RAPIDJSON_INVALID_KEYWORD_RETURN("type");
|
||||||
|
|
||||||
if (exclusiveMaximum_ ? d >= maximum_ : d > maximum_)
|
|
||||||
RAPIDJSON_INVALID_KEYWORD_RETURN("maximum");
|
|
||||||
|
|
||||||
if (hasMultipleOf_) {
|
if (!minimum_.IsNull()) {
|
||||||
double a = std::abs(d), b = std::abs(multipleOf_);
|
if (minimum_.IsInt64()) {
|
||||||
double q = std::floor(a / b);
|
if (exclusiveMinimum_ ? i <= minimum_.GetInt64() : i < minimum_.GetInt64())
|
||||||
double r = a - q * b;
|
RAPIDJSON_INVALID_KEYWORD_RETURN("minimum");
|
||||||
if (r > 0.0)
|
}
|
||||||
RAPIDJSON_INVALID_KEYWORD_RETURN("multipleOf");
|
else if (!CheckDoubleMinimum(context, static_cast<double>(i)))
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!maximum_.IsNull()) {
|
||||||
|
if (maximum_.IsInt64()) {
|
||||||
|
if (exclusiveMaximum_ ? i >= maximum_.GetInt64() : i > maximum_.GetInt64())
|
||||||
|
RAPIDJSON_INVALID_KEYWORD_RETURN("maximum");
|
||||||
|
}
|
||||||
|
else if (!CheckDoubleMaximum(context, static_cast<double>(i)))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!multipleOf_.IsNull()) {
|
||||||
|
if (multipleOf_.IsUint64()) {
|
||||||
|
if (static_cast<uint64_t>(i >= 0 ? i : -i) % multipleOf_.GetUint64() != 0)
|
||||||
|
RAPIDJSON_INVALID_KEYWORD_RETURN("multipleOf");
|
||||||
|
}
|
||||||
|
else if (!CheckDoubleMultipleOf(context, static_cast<double>(i)))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CheckUint(Context& context, uint64_t i) const {
|
||||||
|
if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType))))
|
||||||
|
RAPIDJSON_INVALID_KEYWORD_RETURN("type");
|
||||||
|
|
||||||
|
if (!minimum_.IsNull()) {
|
||||||
|
if (minimum_.IsUint64()) {
|
||||||
|
if (exclusiveMinimum_ ? i <= minimum_.GetUint64() : i < minimum_.GetUint64())
|
||||||
|
RAPIDJSON_INVALID_KEYWORD_RETURN("minimum");
|
||||||
|
}
|
||||||
|
else if (!CheckDoubleMinimum(context, static_cast<double>(i)))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!maximum_.IsNull()) {
|
||||||
|
if (maximum_.IsUint64()) {
|
||||||
|
if (exclusiveMaximum_ ? i >= maximum_.GetUint64() : i > maximum_.GetUint64())
|
||||||
|
RAPIDJSON_INVALID_KEYWORD_RETURN("maximum");
|
||||||
|
}
|
||||||
|
else if (!CheckDoubleMaximum(context, static_cast<double>(i)))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!multipleOf_.IsNull()) {
|
||||||
|
if (multipleOf_.IsUint64()) {
|
||||||
|
if (i % multipleOf_.GetUint64() != 0)
|
||||||
|
RAPIDJSON_INVALID_KEYWORD_RETURN("multipleOf");
|
||||||
|
}
|
||||||
|
else if (!CheckDoubleMultipleOf(context, static_cast<double>(i)))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CheckDoubleMinimum(Context& context, double d) const {
|
||||||
|
if (exclusiveMinimum_ ? d <= minimum_.GetDouble() : d < minimum_.GetDouble())
|
||||||
|
RAPIDJSON_INVALID_KEYWORD_RETURN("minimum");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CheckDoubleMaximum(Context& context, double d) const {
|
||||||
|
if (exclusiveMaximum_ ? d >= maximum_.GetDouble() : d > maximum_.GetDouble())
|
||||||
|
RAPIDJSON_INVALID_KEYWORD_RETURN("maximum");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CheckDoubleMultipleOf(Context& context, double d) const {
|
||||||
|
double a = std::abs(d), b = std::abs(multipleOf_.GetDouble());
|
||||||
|
double q = std::floor(a / b);
|
||||||
|
double r = a - q * b;
|
||||||
|
if (r > 0.0)
|
||||||
|
RAPIDJSON_INVALID_KEYWORD_RETURN("multipleOf");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1038,9 +1110,9 @@ private:
|
|||||||
SizeType minLength_;
|
SizeType minLength_;
|
||||||
SizeType maxLength_;
|
SizeType maxLength_;
|
||||||
|
|
||||||
double minimum_;
|
SValue minimum_;
|
||||||
double maximum_;
|
SValue maximum_;
|
||||||
double multipleOf_;
|
SValue multipleOf_;
|
||||||
bool hasMultipleOf_;
|
bool hasMultipleOf_;
|
||||||
bool exclusiveMinimum_;
|
bool exclusiveMinimum_;
|
||||||
bool exclusiveMaximum_;
|
bool exclusiveMaximum_;
|
||||||
|
@ -125,6 +125,7 @@ TEST(SchemaValidator, Hasher) {
|
|||||||
printf("GetInvalidSchemaPointer() Expected: %s Actual: %s\n", invalidSchemaPointer, sb.GetString());\
|
printf("GetInvalidSchemaPointer() Expected: %s Actual: %s\n", invalidSchemaPointer, sb.GetString());\
|
||||||
ADD_FAILURE();\
|
ADD_FAILURE();\
|
||||||
}\
|
}\
|
||||||
|
ASSERT_TRUE(validator.GetInvalidSchemaKeyword() != 0);\
|
||||||
if (strcmp(validator.GetInvalidSchemaKeyword(), invalidSchemaKeyword) != 0) {\
|
if (strcmp(validator.GetInvalidSchemaKeyword(), invalidSchemaKeyword) != 0) {\
|
||||||
printf("GetInvalidSchemaKeyword() Expected: %s Actual %s\n", invalidSchemaKeyword, validator.GetInvalidSchemaKeyword());\
|
printf("GetInvalidSchemaKeyword() Expected: %s Actual %s\n", invalidSchemaKeyword, validator.GetInvalidSchemaKeyword());\
|
||||||
ADD_FAILURE();\
|
ADD_FAILURE();\
|
||||||
@ -358,15 +359,49 @@ TEST(SchemaValidator, Integer_Range) {
|
|||||||
INVALIDATE(s, "101", "", "maximum", "");
|
INVALIDATE(s, "101", "", "maximum", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(SchemaValidator, Integer_Range64Boundary) {
|
||||||
|
Document sd;
|
||||||
|
sd.Parse("{\"type\":\"integer\",\"minimum\":-9223372036854775807,\"maximum\":18446744073709551614}");
|
||||||
|
SchemaDocument s(sd);
|
||||||
|
|
||||||
|
INVALIDATE(s, "-9223372036854775808", "", "minimum", "");
|
||||||
|
VALIDATE(s, "-9223372036854775807", true);
|
||||||
|
VALIDATE(s, "18446744073709551614", true);
|
||||||
|
INVALIDATE(s, "18446744073709551615", "", "maximum", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SchemaValidator, Integer_Range64BoundaryExclusive) {
|
||||||
|
Document sd;
|
||||||
|
sd.Parse("{\"type\":\"integer\",\"minimum\":-9223372036854775808,\"maximum\":18446744073709551615,\"exclusiveMinimum\":true,\"exclusiveMaximum\":true}");
|
||||||
|
SchemaDocument s(sd);
|
||||||
|
|
||||||
|
INVALIDATE(s, "-9223372036854775808", "", "minimum", "");
|
||||||
|
VALIDATE(s, "-9223372036854775807", true);
|
||||||
|
VALIDATE(s, "18446744073709551614", true);
|
||||||
|
INVALIDATE(s, "18446744073709551615", "", "maximum", "");
|
||||||
|
}
|
||||||
|
|
||||||
TEST(SchemaValidator, Integer_MultipleOf) {
|
TEST(SchemaValidator, Integer_MultipleOf) {
|
||||||
Document sd;
|
Document sd;
|
||||||
sd.Parse("{\"type\":\"integer\",\"multipleOf\":10}");
|
sd.Parse("{\"type\":\"integer\",\"multipleOf\":10}");
|
||||||
SchemaDocument s(sd);
|
SchemaDocument s(sd);
|
||||||
|
|
||||||
VALIDATE(s, "0", true);
|
// VALIDATE(s, "0", true);
|
||||||
VALIDATE(s, "10", true);
|
// VALIDATE(s, "10", true);
|
||||||
|
VALIDATE(s, "-10", true);
|
||||||
VALIDATE(s, "20", true);
|
VALIDATE(s, "20", true);
|
||||||
INVALIDATE(s, "23", "", "multipleOf", "");
|
INVALIDATE(s, "23", "", "multipleOf", "");
|
||||||
|
INVALIDATE(s, "-23", "", "multipleOf", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SchemaValidator, Integer_MultipleOf64Boundary) {
|
||||||
|
Document sd;
|
||||||
|
sd.Parse("{\"type\":\"integer\",\"multipleOf\":18446744073709551615}");
|
||||||
|
SchemaDocument s(sd);
|
||||||
|
|
||||||
|
VALIDATE(s, "0", true);
|
||||||
|
VALIDATE(s, "18446744073709551615", true);
|
||||||
|
INVALIDATE(s, "18446744073709551614", "", "multipleOf", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(SchemaValidator, Number_Range) {
|
TEST(SchemaValidator, Number_Range) {
|
||||||
@ -384,11 +419,12 @@ TEST(SchemaValidator, Number_Range) {
|
|||||||
|
|
||||||
TEST(SchemaValidator, Number_MultipleOf) {
|
TEST(SchemaValidator, Number_MultipleOf) {
|
||||||
Document sd;
|
Document sd;
|
||||||
sd.Parse("{\"type\":\"number\",\"multipleOf\":10}");
|
sd.Parse("{\"type\":\"number\",\"multipleOf\":10.0}");
|
||||||
SchemaDocument s(sd);
|
SchemaDocument s(sd);
|
||||||
|
|
||||||
VALIDATE(s, "0", true);
|
VALIDATE(s, "0", true);
|
||||||
VALIDATE(s, "10", true);
|
VALIDATE(s, "10", true);
|
||||||
|
VALIDATE(s, "-10", true);
|
||||||
VALIDATE(s, "20", true);
|
VALIDATE(s, "20", true);
|
||||||
INVALIDATE(s, "23", "", "multipleOf", "");
|
INVALIDATE(s, "23", "", "multipleOf", "");
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user