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_(),
|
||||
minLength_(0),
|
||||
maxLength_(~SizeType(0)),
|
||||
minimum_(-HUGE_VAL),
|
||||
maximum_(HUGE_VAL),
|
||||
multipleOf_(0),
|
||||
hasMultipleOf_(false),
|
||||
exclusiveMinimum_(false),
|
||||
exclusiveMaximum_(false)
|
||||
{
|
||||
@ -478,26 +474,20 @@ public:
|
||||
pattern_ = CreatePattern(*v);
|
||||
|
||||
// Number
|
||||
ConstMemberIterator minimumItr = value.FindMember("minimum");
|
||||
if (minimumItr != value.MemberEnd())
|
||||
if (minimumItr->value.IsNumber())
|
||||
minimum_ = minimumItr->value.GetDouble();
|
||||
if (const ValueType* v = GetMember(value, "minimum"))
|
||||
if (v->IsNumber())
|
||||
minimum_.CopyFrom(*v, *allocator_);
|
||||
|
||||
ConstMemberIterator maximumItr = value.FindMember("maximum");
|
||||
if (maximumItr != value.MemberEnd())
|
||||
if (maximumItr->value.IsNumber())
|
||||
maximum_ = maximumItr->value.GetDouble();
|
||||
if (const ValueType* v = GetMember(value, "maximum"))
|
||||
if (v->IsNumber())
|
||||
maximum_.CopyFrom(*v, *allocator_);
|
||||
|
||||
AssignIfExist(exclusiveMinimum_, value, "exclusiveMinimum");
|
||||
AssignIfExist(exclusiveMaximum_, value, "exclusiveMaximum");
|
||||
|
||||
ConstMemberIterator multipleOfItr = value.FindMember("multipleOf");
|
||||
if (multipleOfItr != value.MemberEnd()) {
|
||||
if (multipleOfItr->value.IsNumber()) {
|
||||
multipleOf_ = multipleOfItr->value.GetDouble();
|
||||
hasMultipleOf_ = true;
|
||||
}
|
||||
}
|
||||
if (const ValueType* v = GetMember(value, "multipleOf"))
|
||||
if (v->IsNumber() && v->GetDouble() > 0.0)
|
||||
multipleOf_.CopyFrom(*v, *allocator_);
|
||||
}
|
||||
|
||||
~Schema() {
|
||||
@ -629,33 +619,43 @@ public:
|
||||
}
|
||||
|
||||
bool Int(Context& context, int i) const {
|
||||
if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType))))
|
||||
RAPIDJSON_INVALID_KEYWORD_RETURN("type");
|
||||
return CheckDouble(context, i) && CreateParallelValidator(context);
|
||||
if (!CheckInt(context, i))
|
||||
return false;
|
||||
return CreateParallelValidator(context);
|
||||
}
|
||||
|
||||
bool Uint(Context& context, unsigned u) const {
|
||||
if ((type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType))))
|
||||
RAPIDJSON_INVALID_KEYWORD_RETURN("type");
|
||||
return CheckDouble(context, u) && CreateParallelValidator(context);
|
||||
if (!CheckUint(context, u))
|
||||
return false;
|
||||
return CreateParallelValidator(context);
|
||||
}
|
||||
|
||||
bool Int64(Context& context, int64_t i) const {
|
||||
if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType))))
|
||||
RAPIDJSON_INVALID_KEYWORD_RETURN("type");
|
||||
return CheckDouble(context, i) && CreateParallelValidator(context);
|
||||
if (!CheckInt(context, i))
|
||||
return false;
|
||||
return CreateParallelValidator(context);
|
||||
}
|
||||
|
||||
bool Uint64(Context& context, uint64_t u) const {
|
||||
if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType))))
|
||||
RAPIDJSON_INVALID_KEYWORD_RETURN("type");
|
||||
return CheckDouble(context, u) && CreateParallelValidator(context);
|
||||
if (!CheckUint(context, u))
|
||||
return false;
|
||||
return CreateParallelValidator(context);
|
||||
}
|
||||
|
||||
bool Double(Context& context, double d) const {
|
||||
if (!(type_ & (1 << kNumberSchemaType)))
|
||||
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 {
|
||||
@ -963,20 +963,92 @@ private:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CheckDouble(Context& context, double d) const {
|
||||
if (exclusiveMinimum_ ? d <= minimum_ : d < minimum_)
|
||||
bool CheckInt(Context& context, int64_t i) const {
|
||||
if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType))))
|
||||
RAPIDJSON_INVALID_KEYWORD_RETURN("type");
|
||||
|
||||
if (!minimum_.IsNull()) {
|
||||
if (minimum_.IsInt64()) {
|
||||
if (exclusiveMinimum_ ? i <= minimum_.GetInt64() : i < minimum_.GetInt64())
|
||||
RAPIDJSON_INVALID_KEYWORD_RETURN("minimum");
|
||||
}
|
||||
else if (!CheckDoubleMinimum(context, static_cast<double>(i)))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (exclusiveMaximum_ ? d >= maximum_ : d > maximum_)
|
||||
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 (hasMultipleOf_) {
|
||||
double a = std::abs(d), b = std::abs(multipleOf_);
|
||||
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;
|
||||
}
|
||||
|
||||
@ -1038,9 +1110,9 @@ private:
|
||||
SizeType minLength_;
|
||||
SizeType maxLength_;
|
||||
|
||||
double minimum_;
|
||||
double maximum_;
|
||||
double multipleOf_;
|
||||
SValue minimum_;
|
||||
SValue maximum_;
|
||||
SValue multipleOf_;
|
||||
bool hasMultipleOf_;
|
||||
bool exclusiveMinimum_;
|
||||
bool exclusiveMaximum_;
|
||||
|
@ -125,6 +125,7 @@ TEST(SchemaValidator, Hasher) {
|
||||
printf("GetInvalidSchemaPointer() Expected: %s Actual: %s\n", invalidSchemaPointer, sb.GetString());\
|
||||
ADD_FAILURE();\
|
||||
}\
|
||||
ASSERT_TRUE(validator.GetInvalidSchemaKeyword() != 0);\
|
||||
if (strcmp(validator.GetInvalidSchemaKeyword(), invalidSchemaKeyword) != 0) {\
|
||||
printf("GetInvalidSchemaKeyword() Expected: %s Actual %s\n", invalidSchemaKeyword, validator.GetInvalidSchemaKeyword());\
|
||||
ADD_FAILURE();\
|
||||
@ -358,15 +359,49 @@ TEST(SchemaValidator, Integer_Range) {
|
||||
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) {
|
||||
Document sd;
|
||||
sd.Parse("{\"type\":\"integer\",\"multipleOf\":10}");
|
||||
SchemaDocument s(sd);
|
||||
|
||||
VALIDATE(s, "0", true);
|
||||
VALIDATE(s, "10", true);
|
||||
// VALIDATE(s, "0", true);
|
||||
// VALIDATE(s, "10", true);
|
||||
VALIDATE(s, "-10", true);
|
||||
VALIDATE(s, "20", true);
|
||||
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) {
|
||||
@ -384,11 +419,12 @@ TEST(SchemaValidator, Number_Range) {
|
||||
|
||||
TEST(SchemaValidator, Number_MultipleOf) {
|
||||
Document sd;
|
||||
sd.Parse("{\"type\":\"number\",\"multipleOf\":10}");
|
||||
sd.Parse("{\"type\":\"number\",\"multipleOf\":10.0}");
|
||||
SchemaDocument s(sd);
|
||||
|
||||
VALIDATE(s, "0", true);
|
||||
VALIDATE(s, "10", true);
|
||||
VALIDATE(s, "-10", true);
|
||||
VALIDATE(s, "20", true);
|
||||
INVALIDATE(s, "23", "", "multipleOf", "");
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user