diff --git a/include/rapidjson/encodings.h b/include/rapidjson/encodings.h index bc3cd81..fa9979e 100644 --- a/include/rapidjson/encodings.h +++ b/include/rapidjson/encodings.h @@ -616,6 +616,22 @@ struct Transcoder { } }; +//! Returns number of code points in a encoded string. +template +bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) { + GenericStringStream is(s); + const typename Encoding::Ch* end = s + length; + SizeType count = 0; + while (is.src_ < end) { + unsigned codepoint; + if (!Encoding::Decode(is, &codepoint)) + return false; + count++; + } + *outCount = count; + return true; +} + RAPIDJSON_NAMESPACE_END #if defined(__GNUC__) || defined(_MSV_VER) diff --git a/include/rapidjson/schema.h b/include/rapidjson/schema.h index 1856b21..de27bda 100644 --- a/include/rapidjson/schema.h +++ b/include/rapidjson/schema.h @@ -428,8 +428,13 @@ public: if ((type_ & (1 << kStringSchemaType)) == 0) return false; - if (length < minLength_ || length > maxLength_) - return false; + //if (length < minLength_ || length > maxLength_) + // return false; + if (minLength_ != 0 || maxLength_ != SizeType(~0)) { + SizeType count; + if (CountStringCodePoint(str, length, &count) && (count < minLength_ || count > maxLength_)) + return false; + } #if RAPIDJSON_SCHEMA_HAS_REGEX if (pattern_ && !IsPatternMatch(*pattern_, str, length)) diff --git a/test/unittest/encodingstest.cpp b/test/unittest/encodingstest.cpp index b697d91..f3e90d2 100644 --- a/test/unittest/encodingstest.cpp +++ b/test/unittest/encodingstest.cpp @@ -424,3 +424,14 @@ TEST(EncodingsTest, UTF32) { } } } + +TEST(EncodingsTest, CountStringCodePoint) { + SizeType count; + EXPECT_TRUE(CountStringCodePoint >("", 0, &count)); + EXPECT_EQ(0u, count); + EXPECT_TRUE(CountStringCodePoint >("Hello", 5, &count)); + EXPECT_EQ(5u, count); + EXPECT_TRUE(CountStringCodePoint >("\xC2\xA2\xE2\x82\xAC\xF0\x9D\x84\x9E", 9, &count)); // cents euro G-clef + EXPECT_EQ(3u, count); + EXPECT_FALSE(CountStringCodePoint >("\xC2\xA2\xE2\x82\xAC\xF0\x9D\x84\x9E\x80", 10, &count)); +}