summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorDominick Allen <djallen@librehumanitas.org>2024-10-20 10:48:19 -0500
committerDominick Allen <djallen@librehumanitas.org>2024-10-20 10:48:19 -0500
commit6a27a2a4032e88fa9154ef0f0741edc584f7a701 (patch)
tree92ca58cbcdd2c1d11b7d69deb0d4925d0f979a3f /test
parente94db4695e236b42ae1be44b2605075161d5144f (diff)
Lots of work.
Diffstat (limited to 'test')
-rw-r--r--test/CMakeLists.txt12
-rw-r--r--test/test_common.hpp11
-rw-r--r--test/test_format.cpp12
-rw-r--r--test/test_utf8.cpp1163
4 files changed, 1180 insertions, 18 deletions
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 0860c0d..c4d957b 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -59,23 +59,17 @@ endfunction()
fud_add_test(test_fud SOURCES test_fud.cpp)
fud_add_test(test_allocator SOURCES test_allocator.cpp)
fud_add_test(test_assert SOURCES test_assert.cpp)
+# fud_add_test(test_c_file SOURCES test_c_file.cpp)
fud_add_test(test_directory SOURCES test_directory.cpp)
fud_add_test(test_format SOURCES test_format.cpp)
fud_add_test(test_result SOURCES test_result.cpp)
fud_add_test(test_span SOURCES test_span.cpp)
fud_add_test(test_sqlite SOURCES test_sqlite.cpp)
fud_add_test(test_string SOURCES test_string.cpp)
+fud_add_test(test_utf8 SOURCES test_utf8.cpp)
+
# fud_add_test(test_deserialize_number SOURCES test_deserialize_number.cpp)
# fud_add_test(test_ext_algorithm SOURCES test_algorithm.cpp)
# fud_add_test(test_ext_array SOURCES
# test_ext_array.cpp
# test_ext_unique_array.cpp)
-# fud_add_test(test_ext_utf8 SOURCES
-# test_ext_utf8.cpp)
-# fud_add_test(test_ext_string SOURCES
-# test_ext_string.cpp
-# test_ext_string_cxx.cpp)
-# fud_add_test(test_ext_string_format SOURCES
-# test_ext_string_format.cpp)
-
-# fud_add_test(test_c_file SOURCES test_c_file.cpp)
diff --git a/test/test_common.hpp b/test/test_common.hpp
index 05f86db..0ca8eb4 100644
--- a/test/test_common.hpp
+++ b/test/test_common.hpp
@@ -34,7 +34,16 @@ static_assert(sizeof(THREE_BYTE) == 3 + 1);
static_assert(sizeof(FOUR_BYTE) == 4 + 1);
#define CHQUOTE "why waste time learning, when ignorance is instantaneous?"
-#define CHARACTER_SET "abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+
+#define LOWERCASE_CHARS "abcdefghijklmnopqrstuvwxyz"
+#define UPPERCASE_CHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+#define DECIMAL_CHARS "0123456789"
+#define ALPHA_CHARS LOWERCASE_CHARS UPPERCASE_CHARS
+#define ALPHA_NUMERIC_CHARS ALPHA_CHARS DECIMAL_CHARS
+#define PUNCTUATION_CHARS "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"
+#define GRAPHICAL_CHARS ALPHA_NUMERIC_CHARS PUNCTUATION_CHARS
+#define CHARACTER_SET LOWERCASE_CHARS " " UPPERCASE_CHARS
+
// NOLINTEND(cppcoreguidelines-macro-usage)
constexpr size_t charSetSize = sizeof(CHARACTER_SET) - 1;
diff --git a/test/test_format.cpp b/test/test_format.cpp
index a373fec..319ed22 100644
--- a/test/test_format.cpp
+++ b/test/test_format.cpp
@@ -15,21 +15,17 @@
* limitations under the License.
*/
-#include "fud_array.hpp"
-#include "fud_format.hpp"
-#include "fud_span.hpp"
+// #include "fud_array.hpp"
+// #include "fud_format.hpp"
+// #include "fud_span.hpp"
#include "gtest/gtest.h"
namespace fud {
-TEST(FormatTest, BasicTest)
+TEST(FormatTest, FormatSpecTest)
{
- auto buffer{Array<char, 64>::constFill('\0')};
- auto span = Span<char, buffer.size() - 1U>::makeCStringBuffer(buffer);
- auto formatResult = format(span, "Hello, {}! {}", "world", 42);
- printf("%s\n", buffer.data());
}
} // namespace fud
diff --git a/test/test_utf8.cpp b/test/test_utf8.cpp
new file mode 100644
index 0000000..8f1d655
--- /dev/null
+++ b/test/test_utf8.cpp
@@ -0,0 +1,1163 @@
+/*
+ * libfud
+ * Copyright 2024 Dominick Allen
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "fud_algorithm.hpp"
+#include "fud_allocator.hpp"
+#include "fud_array.hpp"
+#include "fud_string.hpp"
+#include "fud_utf8.hpp"
+#include "fud_utf8_iterator.hpp"
+#include "fud_vector.hpp"
+#include "test_common.hpp"
+// #include "fud_format.hpp"
+// #include "fud_span.hpp"
+
+#include "gtest/gtest.h"
+
+namespace fud {
+
+constexpr size_t validAsciiSize = INT8_MAX + 1;
+constexpr size_t invalidAsciiSize = UINT8_MAX + 1 - validAsciiSize;
+
+constexpr size_t numControlChars = 33;
+constexpr char printableCharOffset = 0x20;
+
+constexpr auto invalidAscii = FudUtf8::invalidAsciiCode.character();
+
+auto generateInvalidAsciiChars()
+{
+ Iota<utf8> iota{};
+ return generate([]() { return Array<utf8, invalidAsciiSize>{}; }, [&]() { return iota().value(); });
+}
+
+TEST(Utf8Test, Utf8Creation)
+{
+ const Array<utf8, 4> threeByte = {THREE_BYTE};
+
+ FudUtf8 utf8Point{FudUtf8::make(threeByte)};
+ ASSERT_NE(utf8Point.data(), nullptr);
+ ASSERT_EQ(utf8Point.size(), 3);
+ ASSERT_NE(utf8Point.hash(), -1);
+
+ const Array<utf8, 4> asciiLetter = {'A'};
+ utf8Point = FudUtf8::make(asciiLetter);
+ ASSERT_NE(utf8Point.data(), nullptr);
+ ASSERT_EQ(utf8Point.size(), 1);
+
+ const Array<utf8, 4> twoByte = {TWO_BYTE};
+ utf8Point = FudUtf8::make(twoByte);
+ ASSERT_NE(utf8Point.data(), nullptr);
+ ASSERT_EQ(utf8Point.size(), 2);
+ ASSERT_NE(utf8Point.hash(), -1);
+
+ Array<utf8, 4> fourByte = {
+ static_cast<utf8>(FOUR_BYTE[0]),
+ static_cast<utf8>(FOUR_BYTE[1]),
+ static_cast<utf8>(FOUR_BYTE[2]),
+ static_cast<utf8>(FOUR_BYTE[3])};
+ utf8Point = FudUtf8::make(fourByte);
+ ASSERT_NE(utf8Point.data(), nullptr);
+ ASSERT_EQ(utf8Point.size(), 4);
+ ASSERT_NE(utf8Point.hash(), -1);
+
+ const Array<utf8, 4> invalidBytes = {0xFF, 0xFF, 0xFF, 0xFF};
+ utf8Point = FudUtf8::make(invalidBytes);
+ ASSERT_EQ(utf8Point.data(), nullptr);
+ ASSERT_EQ(utf8Point.size(), 0);
+ ASSERT_EQ(utf8Point.hash(), -1);
+}
+
+TEST(Utf8Test, Utf8MultiByte)
+{
+ Array<utf8, sizeof(MULTI_BYTE_LITERAL)> data{MULTI_BYTE_LITERAL};
+ constexpr size_t bufSize = data.size();
+ EXPECT_EQ(data[bufSize - 1], '\0');
+
+ class FixedAllocator final : public Allocator {
+ private:
+ Array<utf8, bufSize> m_memory{};
+ size_t m_allocated{0};
+
+ public:
+ virtual ~FixedAllocator() override final = default;
+
+ virtual Result<void*, FudStatus> allocate(size_t bytes, size_t alignment) override final
+ {
+ static_cast<void>(alignment);
+ if (bytes > m_memory.size() - m_allocated) {
+ return FudStatus::AllocFailure;
+ }
+ auto* data = m_memory.data() + m_allocated;
+ m_allocated += bytes;
+ return data;
+ }
+
+ virtual FudStatus deallocate(void* pointer, size_t bytes) override final
+ {
+ static_cast<void>(pointer);
+ static_cast<void>(bytes);
+ return FudStatus::Success;
+ }
+
+ virtual bool isEqual(const Allocator& rhs) const override final
+ {
+ return &rhs == this;
+ }
+ };
+ FixedAllocator fixedAllocator;
+
+ auto stringBufferRes{String::makeFromCString(MULTI_BYTE_LITERAL, &fixedAllocator)};
+
+ ASSERT_TRUE(stringBufferRes.isOkay());
+ auto stringBuffer{stringBufferRes.takeOkay()};
+ EXPECT_EQ(stringBuffer.size(), bufSize);
+ EXPECT_EQ(stringBuffer.size(), sizeof(data));
+ EXPECT_EQ(stringBuffer.length(), bufSize - 1);
+ EXPECT_TRUE(stringBuffer.nullTerminated());
+ EXPECT_TRUE(stringBuffer.valid());
+ ASSERT_TRUE(stringBuffer.utf8Valid());
+
+ Utf8Iterator utf8Iter{stringBuffer};
+ auto characterOpt = utf8Iter.next();
+ ASSERT_TRUE(characterOpt.has_value());
+
+ // MULTI_BYTE_LITERAL "test今日素敵はですねƩ®😀z"
+ const Array<FudUtf8, 16> multiByteCharacters{
+ FudUtf8::make(Utf8Variant{Ascii{'t'}}),
+ FudUtf8::make(Utf8Variant{Ascii{'e'}}),
+ FudUtf8::make(Utf8Variant{Ascii{'s'}}),
+ FudUtf8::make(Utf8Variant{Ascii{'t'}}),
+ FudUtf8::from(StringView{sizeof("今"), "今"}, 0),
+ FudUtf8::from(StringView{sizeof("日"), "日"}, 0),
+ FudUtf8::from(StringView{sizeof("素"), "素"}, 0),
+ FudUtf8::from(StringView{sizeof("敵"), "敵"}, 0),
+ FudUtf8::from(StringView{sizeof("は"), "は"}, 0),
+ FudUtf8::from(StringView{sizeof("で"), "で"}, 0),
+ FudUtf8::from(StringView{sizeof("す"), "す"}, 0),
+ FudUtf8::from(StringView{sizeof("ね"), "ね"}, 0),
+ FudUtf8::from(StringView{sizeof("Ʃ"), "Ʃ"}, 0),
+ FudUtf8::from(StringView{sizeof("®"), "®"}, 0),
+ FudUtf8::from(StringView{sizeof("😀"), "😀"}, 0),
+ FudUtf8::make(Utf8Variant{Ascii{'z'}}),
+ };
+
+ size_t idx = 0;
+ while (characterOpt.has_value()) {
+ auto character = *characterOpt;
+ if (character != FudUtf8{Utf8Variant{Ascii{'\0'}}}) {
+ EXPECT_TRUE(character.size() >= 1);
+ ASSERT_LT(idx, multiByteCharacters.size());
+ EXPECT_EQ(character.size(), multiByteCharacters[idx].size());
+ EXPECT_EQ(character, multiByteCharacters[idx]);
+ EXPECT_TRUE(multiByteCharacters[idx].valid());
+ if (character != multiByteCharacters[idx]) {
+ printf("idx = %zu, %.*s\n", idx, static_cast<int>(character.size()), character.data());
+ }
+ idx++;
+ }
+ characterOpt = utf8Iter.next();
+ }
+ utf8Iter.reset();
+ ASSERT_TRUE(utf8Iter.next().has_value());
+
+ FudUtf8 invalid = FudUtf8::invalidAscii();
+ ASSERT_FALSE(invalid.valid());
+ ASSERT_EQ(invalid.size(), 0);
+ ASSERT_EQ(invalid.data(), nullptr);
+ ASSERT_EQ(invalid.hash(), -1);
+}
+
+TEST(Utf8Test, Utf8IsAscii)
+{
+ ASSERT_FALSE(charIsAscii(invalidAscii));
+
+ Iota<int16_t> charIota{0, 1, validAsciiSize};
+
+ ASSERT_TRUE(allOf(
+ [&]() -> std::optional<char> {
+ auto value = charIota();
+ return value ? std::optional<char>(static_cast<char>(*value)) : std::nullopt;
+ },
+ charIsAscii));
+
+ Iota<int16_t> invalidCharIota{validAsciiSize, 1, invalidAsciiSize};
+
+ ASSERT_FALSE(anyOf(
+ [&]() -> std::optional<char> {
+ auto value = invalidCharIota();
+ return value ? std::optional<char>(static_cast<char>(*value)) : std::nullopt;
+ },
+ charIsAscii));
+
+ FudUtf8 unicode{FudUtf8::invalidAscii()};
+ ASSERT_FALSE(utf8IsAscii(unicode));
+
+ charIota.set(0);
+ ASSERT_TRUE(allOf(
+ [&]() -> std::optional<FudUtf8> {
+ auto value = charIota();
+ return value ? std::optional<FudUtf8>(FudUtf8::make(static_cast<utf8>(*value))) : std::nullopt;
+ },
+ utf8IsAscii));
+
+ invalidCharIota.set(invalidAsciiSize);
+ ASSERT_FALSE(anyOf(
+ [&]() -> std::optional<FudUtf8> {
+ auto value = invalidCharIota();
+ return value ? std::optional<FudUtf8>(FudUtf8::make(static_cast<utf8>(*value))) : std::nullopt;
+ },
+ utf8IsAscii));
+}
+
+TEST(Utf8Test, Utf8IsAlphaNumeric)
+{
+ constexpr size_t numAlphaNumericChars = 26 * 2 + 10;
+ Array<char, numAlphaNumericChars + 1> alphaNumericCharLiteral{ALPHA_NUMERIC_CHARS};
+ Array<char, numAlphaNumericChars> alphaNumericChars{};
+ copyMem<numAlphaNumericChars>(alphaNumericChars, alphaNumericCharLiteral);
+#if 0
+ ASSERT_TRUE(allOf(alphaNumericChars, charIsAlphanumeric));
+
+ auto alphaNumericSetResult{StaticSet<char, numAlphaNumericChars>::makeFromArray(alphaNumericChars)};
+ ASSERT_TRUE(alphaNumericSetResult.isOkay());
+ auto alphaNumericSet{std::move(alphaNumericSetResult.getOkay())};
+
+ constexpr size_t numNonAlphaNumericChars = validAsciiSize - numAlphaNumericChars;
+ FixedVector<char, numNonAlphaNumericChars> nonAlphaNumericChars{};
+ for (char idx = 0; idx < INT8_MAX; ++idx) {
+ if (!alphaNumericSet.isKey(idx)) {
+ ASSERT_TRUE(nonAlphaNumericChars.pushBack(idx));
+ }
+ }
+ ASSERT_FALSE(anyOf(nonAlphaNumericChars, charIsAlphanumeric));
+
+ auto invalidAsciiChars = generateInvalidAsciiChars();
+ ASSERT_FALSE(anyOf(invalidAsciiChars, charIsAlphanumeric));
+
+ ASSERT_TRUE(allOf(
+ map(alphaNumericChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_alphanumeric));
+ ASSERT_FALSE(anyOf(
+ map(nonAlphaNumericChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_alphanumeric));
+ ASSERT_FALSE(anyOf(
+ map(invalidAsciiChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_alphanumeric));
+
+ ASSERT_TRUE(allOf(
+ map(alphaNumericChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_alphanumeric));
+ ASSERT_FALSE(anyOf(
+ map(nonAlphaNumericChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_alphanumeric));
+ ASSERT_FALSE(anyOf(
+ map(invalidAsciiChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_alphanumeric));
+
+ Utf8 utf8{invalidAscii};
+ bool isAscii = false;
+ ASSERT_EQ(ext_lib_utf8_is_alphanumeric(nullptr, nullptr), ExtNullPointer);
+ ASSERT_EQ(ext_lib_utf8_is_alphanumeric(&utf8, nullptr), ExtNullPointer);
+ ASSERT_EQ(ext_lib_utf8_is_alphanumeric(nullptr, &isAscii), ExtNullPointer);
+ ASSERT_EQ(ext_lib_utf8_is_alphanumeric(&utf8, &isAscii), ExtInvalidInput);
+ ASSERT_FALSE(isAscii);
+
+ ASSERT_TRUE(allOf(
+ map(alphaNumericChars,
+ [](char letter) { return FudUtf8::makeUtf8(ExtUtf8Char4{static_cast<utf8>(letter)}); }),
+ [](auto& utf8Letter) {
+ bool predicate = false;
+ auto isPredicateStatus = ext_lib_utf8_is_alphanumeric(&utf8Letter, &predicate);
+ return isPredicateStatus == ExtSuccess && predicate;
+ }));
+ ASSERT_FALSE(anyOf(
+ map(nonAlphaNumericChars,
+ [](char letter) { return FudUtf8::makeUtf8(ExtUtf8Char4{static_cast<utf8>(letter)}); }),
+ [](auto& utf8Letter) {
+ bool predicate = false;
+ auto isPredicateStatus = ext_lib_utf8_is_alphanumeric(&utf8Letter, &predicate);
+ return isPredicateStatus != ExtSuccess || predicate;
+ }));
+ ASSERT_FALSE(allOf(
+ map(nonAlphaNumericChars,
+ [](char letter) { return FudUtf8::makeUtf8(ExtUtf8Char4{static_cast<utf8>(letter)}); }),
+ [](auto& utf8Letter) {
+ bool predicate = false;
+ auto isPredicateStatus = ext_lib_utf8_is_alphanumeric(&utf8Letter, &predicate);
+ return isPredicateStatus == ExtInvalidInput && !predicate;
+ }));
+#endif
+}
+
+#if 0
+TEST(Utf8Test, Utf8IsAlpha)
+{
+ constexpr size_t numAlphaChars = sizeof(ALPHA_CHARS) - 1;
+ Array<char, numAlphaChars + 1> alphaCharLiteral{ALPHA_CHARS};
+ Array<char, numAlphaChars> alphaChars{};
+ copyMem<numAlphaChars>(alphaChars, alphaCharLiteral);
+
+ ASSERT_TRUE(allOf(alphaChars, ext_lib_char_is_alpha));
+
+ auto alphaSetResult{StaticSet<char, numAlphaChars>::makeFromArray(alphaChars)};
+ ASSERT_TRUE(alphaSetResult.isOkay());
+ auto alphaSet{std::move(alphaSetResult.getOkay())};
+
+ constexpr size_t numNonAlphaChars = validAsciiSize - numAlphaChars;
+ FixedVector<char, numNonAlphaChars> nonAlphaChars{};
+ for (char idx = 0; idx < INT8_MAX; ++idx) {
+ if (!alphaSet.isKey(idx)) {
+ ASSERT_TRUE(nonAlphaChars.pushBack(idx));
+ }
+ }
+ ASSERT_FALSE(anyOf(nonAlphaChars, ext_lib_char_is_alpha));
+
+ auto invalidAsciiChars = generateInvalidAsciiChars();
+ ASSERT_FALSE(anyOf(invalidAsciiChars, ext_lib_char_is_alpha));
+
+ ASSERT_TRUE(allOf(
+ map(alphaChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_alpha));
+ ASSERT_FALSE(anyOf(
+ map(nonAlphaChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_alpha));
+ ASSERT_FALSE(anyOf(
+ map(invalidAsciiChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_alpha));
+
+ ASSERT_TRUE(allOf(
+ map(alphaChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_alpha));
+ ASSERT_FALSE(anyOf(
+ map(nonAlphaChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_alpha));
+ ASSERT_FALSE(anyOf(
+ map(invalidAsciiChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_alpha));
+
+ Utf8 utf8{invalidAscii};
+ bool isAscii = false;
+ ASSERT_EQ(ext_lib_utf8_is_alpha(nullptr, nullptr), ExtNullPointer);
+ ASSERT_EQ(ext_lib_utf8_is_alpha(&utf8, nullptr), ExtNullPointer);
+ ASSERT_EQ(ext_lib_utf8_is_alpha(nullptr, &isAscii), ExtNullPointer);
+ ASSERT_EQ(ext_lib_utf8_is_alpha(&utf8, &isAscii), ExtInvalidInput);
+ ASSERT_FALSE(isAscii);
+
+ ASSERT_TRUE(allOf(
+ map(alphaChars, [](char letter) { return FudUtf8::makeUtf8(ExtUtf8Char4{static_cast<utf8>(letter)}); }),
+ [](auto& utf8Letter) {
+ bool predicate = false;
+ auto isPredicateStatus = ext_lib_utf8_is_alpha(&utf8Letter, &predicate);
+ return isPredicateStatus == ExtSuccess && predicate;
+ }));
+ ASSERT_FALSE(anyOf(
+ map(nonAlphaChars,
+ [](char letter) { return FudUtf8::makeUtf8(ExtUtf8Char4{static_cast<utf8>(letter)}); }),
+ [](auto& utf8Letter) {
+ bool predicate = false;
+ auto isPredicateStatus = ext_lib_utf8_is_alpha(&utf8Letter, &predicate);
+ return isPredicateStatus != ExtSuccess || predicate;
+ }));
+ ASSERT_FALSE(allOf(
+ map(nonAlphaChars,
+ [](char letter) { return FudUtf8::makeUtf8(ExtUtf8Char4{static_cast<utf8>(letter)}); }),
+ [](auto& utf8Letter) {
+ bool predicate = false;
+ auto isPredicateStatus = ext_lib_utf8_is_alpha(&utf8Letter, &predicate);
+ return isPredicateStatus == ExtInvalidInput && !predicate;
+ }));
+}
+
+TEST(Utf8Test, Utf8IsLower)
+{
+ constexpr size_t numLowerChars = 26;
+ Array<char, numLowerChars + 1> lowerCharLiteral{LOWERCASE_CHARS};
+ Array<char, numLowerChars> lowerChars{};
+ copyMem<numLowerChars>(lowerChars, lowerCharLiteral);
+
+ ASSERT_TRUE(allOf(lowerChars, ext_lib_char_is_lowercase));
+
+ auto lowerSetResult{StaticSet<char, numLowerChars>::makeFromArray(lowerChars)};
+ ASSERT_TRUE(lowerSetResult.isOkay());
+ auto lowerSet{std::move(lowerSetResult.getOkay())};
+
+ constexpr size_t numNonLowerChars = validAsciiSize - numLowerChars;
+ FixedVector<char, numNonLowerChars> nonLowerChars{};
+ for (char idx = 0; idx < INT8_MAX; ++idx) {
+ if (!lowerSet.isKey(idx)) {
+ ASSERT_TRUE(nonLowerChars.pushBack(idx));
+ }
+ }
+ ASSERT_FALSE(anyOf(nonLowerChars, ext_lib_char_is_lowercase));
+
+ auto invalidAsciiChars = generateInvalidAsciiChars();
+ ASSERT_FALSE(anyOf(invalidAsciiChars, ext_lib_char_is_lowercase));
+
+ ASSERT_TRUE(allOf(
+ map(lowerChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_lowercase));
+ ASSERT_FALSE(anyOf(
+ map(nonLowerChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_lowercase));
+ ASSERT_FALSE(anyOf(
+ map(invalidAsciiChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_lowercase));
+
+ ASSERT_TRUE(allOf(
+ map(lowerChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_lowercase));
+ ASSERT_FALSE(anyOf(
+ map(nonLowerChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_lowercase));
+ ASSERT_FALSE(anyOf(
+ map(invalidAsciiChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_lowercase));
+
+ Utf8 utf8{invalidAscii};
+ bool isAscii = false;
+ ASSERT_EQ(ext_lib_utf8_is_lowercase(nullptr, nullptr), ExtNullPointer);
+ ASSERT_EQ(ext_lib_utf8_is_lowercase(&utf8, nullptr), ExtNullPointer);
+ ASSERT_EQ(ext_lib_utf8_is_lowercase(nullptr, &isAscii), ExtNullPointer);
+ ASSERT_EQ(ext_lib_utf8_is_lowercase(&utf8, &isAscii), ExtInvalidInput);
+ ASSERT_FALSE(isAscii);
+
+ ASSERT_TRUE(allOf(
+ map(lowerChars, [](char letter) { return FudUtf8::makeUtf8(ExtUtf8Char4{static_cast<utf8>(letter)}); }),
+ [](auto& utf8Letter) {
+ bool predicate = false;
+ auto isPredicateStatus = ext_lib_utf8_is_lowercase(&utf8Letter, &predicate);
+ return isPredicateStatus == ExtSuccess && predicate;
+ }));
+ ASSERT_FALSE(anyOf(
+ map(nonLowerChars,
+ [](char letter) { return FudUtf8::makeUtf8(ExtUtf8Char4{static_cast<utf8>(letter)}); }),
+ [](auto& utf8Letter) {
+ bool predicate = false;
+ auto isPredicateStatus = ext_lib_utf8_is_lowercase(&utf8Letter, &predicate);
+ return isPredicateStatus != ExtSuccess || predicate;
+ }));
+ ASSERT_FALSE(allOf(
+ map(nonLowerChars,
+ [](char letter) { return FudUtf8::makeUtf8(ExtUtf8Char4{static_cast<utf8>(letter)}); }),
+ [](auto& utf8Letter) {
+ bool predicate = false;
+ auto isPredicateStatus = ext_lib_utf8_is_lowercase(&utf8Letter, &predicate);
+ return isPredicateStatus == ExtInvalidInput && !predicate;
+ }));
+}
+
+TEST(Utf8Test, Utf8IsUpper)
+{
+ constexpr size_t numUpperChars = 26;
+ Array<char, numUpperChars + 1> upperCharLiteral{UPPERCASE_CHARS};
+ Array<char, numUpperChars> upperChars{};
+ copyMem<numUpperChars>(upperChars, upperCharLiteral);
+
+ ASSERT_TRUE(allOf(upperChars, ext_lib_char_is_uppercase));
+
+ auto upperSetResult{StaticSet<char, numUpperChars>::makeFromArray(upperChars)};
+ ASSERT_TRUE(upperSetResult.isOkay());
+ auto upperSet{std::move(upperSetResult.getOkay())};
+
+ constexpr size_t numNonUpperChars = validAsciiSize - numUpperChars;
+ FixedVector<char, numNonUpperChars> nonUpperChars{};
+ for (char idx = 0; idx < INT8_MAX; ++idx) {
+ if (!upperSet.isKey(idx)) {
+ ASSERT_TRUE(nonUpperChars.pushBack(idx));
+ }
+ }
+ ASSERT_FALSE(anyOf(nonUpperChars, ext_lib_char_is_uppercase));
+
+ auto invalidAsciiChars = generateInvalidAsciiChars();
+ ASSERT_FALSE(anyOf(invalidAsciiChars, ext_lib_char_is_uppercase));
+
+ ASSERT_TRUE(allOf(
+ map(upperChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_uppercase));
+ ASSERT_FALSE(anyOf(
+ map(nonUpperChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_uppercase));
+ ASSERT_FALSE(anyOf(
+ map(invalidAsciiChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_uppercase));
+
+ ASSERT_TRUE(allOf(
+ map(upperChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_uppercase));
+ ASSERT_FALSE(anyOf(
+ map(nonUpperChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_uppercase));
+ ASSERT_FALSE(anyOf(
+ map(invalidAsciiChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_uppercase));
+
+ Utf8 utf8{invalidAscii};
+ bool isAscii = false;
+ ASSERT_EQ(ext_lib_utf8_is_uppercase(nullptr, nullptr), ExtNullPointer);
+ ASSERT_EQ(ext_lib_utf8_is_uppercase(&utf8, nullptr), ExtNullPointer);
+ ASSERT_EQ(ext_lib_utf8_is_uppercase(nullptr, &isAscii), ExtNullPointer);
+ ASSERT_EQ(ext_lib_utf8_is_uppercase(&utf8, &isAscii), ExtInvalidInput);
+ ASSERT_FALSE(isAscii);
+
+ ASSERT_TRUE(allOf(
+ map(upperChars, [](char letter) { return FudUtf8::makeUtf8(ExtUtf8Char4{static_cast<utf8>(letter)}); }),
+ [](auto& utf8Letter) {
+ bool predicate = false;
+ auto isPredicateStatus = ext_lib_utf8_is_uppercase(&utf8Letter, &predicate);
+ return isPredicateStatus == ExtSuccess && predicate;
+ }));
+ ASSERT_FALSE(anyOf(
+ map(nonUpperChars,
+ [](char letter) { return FudUtf8::makeUtf8(ExtUtf8Char4{static_cast<utf8>(letter)}); }),
+ [](auto& utf8Letter) {
+ bool predicate = false;
+ auto isPredicateStatus = ext_lib_utf8_is_uppercase(&utf8Letter, &predicate);
+ return isPredicateStatus != ExtSuccess || predicate;
+ }));
+ ASSERT_FALSE(allOf(
+ map(nonUpperChars,
+ [](char letter) { return FudUtf8::makeUtf8(ExtUtf8Char4{static_cast<utf8>(letter)}); }),
+ [](auto& utf8Letter) {
+ bool predicate = false;
+ auto isPredicateStatus = ext_lib_utf8_is_uppercase(&utf8Letter, &predicate);
+ return isPredicateStatus == ExtInvalidInput && !predicate;
+ }));
+}
+
+TEST(Utf8Test, Utf8IsDigit)
+{
+ constexpr size_t numDigitChars = 10;
+ Array<char, numDigitChars + 1> digitCharLiteral{"0123456789"};
+ Array<char, numDigitChars> digitChars{};
+ copyMem<numDigitChars>(digitChars, digitCharLiteral);
+
+ ASSERT_TRUE(allOf(digitChars, ext_lib_char_is_digit));
+
+ auto digitSetResult{StaticSet<char, numDigitChars>::makeFromArray(digitChars)};
+ ASSERT_TRUE(digitSetResult.isOkay());
+ auto digitSet{std::move(digitSetResult.getOkay())};
+
+ constexpr size_t numNonDigitChars = validAsciiSize - numDigitChars;
+ FixedVector<char, numNonDigitChars> nonDigitChars{};
+ for (char idx = 0; idx < INT8_MAX; ++idx) {
+ if (!digitSet.isKey(idx)) {
+ ASSERT_TRUE(nonDigitChars.pushBack(idx));
+ }
+ }
+ ASSERT_FALSE(anyOf(nonDigitChars, ext_lib_char_is_digit));
+
+ auto invalidAsciiChars = generateInvalidAsciiChars();
+ ASSERT_FALSE(anyOf(invalidAsciiChars, ext_lib_char_is_digit));
+
+ ASSERT_TRUE(allOf(
+ map(digitChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_digit));
+ ASSERT_FALSE(anyOf(
+ map(nonDigitChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_digit));
+ ASSERT_FALSE(anyOf(
+ map(invalidAsciiChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_digit));
+
+ ASSERT_TRUE(allOf(
+ map(digitChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_digit));
+ ASSERT_FALSE(anyOf(
+ map(nonDigitChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_digit));
+ ASSERT_FALSE(anyOf(
+ map(invalidAsciiChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_digit));
+
+ Utf8 utf8{invalidAscii};
+ bool isAscii = false;
+ ASSERT_EQ(ext_lib_utf8_is_digit(nullptr, nullptr), ExtNullPointer);
+ ASSERT_EQ(ext_lib_utf8_is_digit(&utf8, nullptr), ExtNullPointer);
+ ASSERT_EQ(ext_lib_utf8_is_digit(nullptr, &isAscii), ExtNullPointer);
+ ASSERT_EQ(ext_lib_utf8_is_digit(&utf8, &isAscii), ExtInvalidInput);
+ ASSERT_FALSE(isAscii);
+
+ ASSERT_TRUE(allOf(
+ map(digitChars, [](char letter) { return FudUtf8::makeUtf8(ExtUtf8Char4{static_cast<utf8>(letter)}); }),
+ [](auto& utf8Letter) {
+ bool predicate = false;
+ auto isPredicateStatus = ext_lib_utf8_is_digit(&utf8Letter, &predicate);
+ return isPredicateStatus == ExtSuccess && predicate;
+ }));
+ ASSERT_FALSE(anyOf(
+ map(nonDigitChars,
+ [](char letter) { return FudUtf8::makeUtf8(ExtUtf8Char4{static_cast<utf8>(letter)}); }),
+ [](auto& utf8Letter) {
+ bool predicate = false;
+ auto isPredicateStatus = ext_lib_utf8_is_digit(&utf8Letter, &predicate);
+ return isPredicateStatus != ExtSuccess || predicate;
+ }));
+ ASSERT_FALSE(allOf(
+ map(nonDigitChars,
+ [](char letter) { return FudUtf8::makeUtf8(ExtUtf8Char4{static_cast<utf8>(letter)}); }),
+ [](auto& utf8Letter) {
+ bool predicate = false;
+ auto isPredicateStatus = ext_lib_utf8_is_digit(&utf8Letter, &predicate);
+ return isPredicateStatus == ExtInvalidInput && !predicate;
+ }));
+}
+
+TEST(Utf8Test, Utf8IsHexDigit)
+{
+ constexpr size_t numHexDigitChars = 6 * 2 + 10;
+ Array<char, numHexDigitChars + 1> hexDigitCharLiteral{"abcdefABCDEF0123456789"};
+ Array<char, numHexDigitChars> hexDigitChars{};
+ copyMem<numHexDigitChars>(hexDigitChars, hexDigitCharLiteral);
+
+ ASSERT_TRUE(allOf(hexDigitChars, ext_lib_char_is_hex_digit));
+
+ auto hexDigitSetResult{StaticSet<char, numHexDigitChars>::makeFromArray(hexDigitChars)};
+ ASSERT_TRUE(hexDigitSetResult.isOkay());
+ auto hexDigitSet{std::move(hexDigitSetResult.getOkay())};
+
+ constexpr size_t numNonHexDigitChars = validAsciiSize - numHexDigitChars;
+ FixedVector<char, numNonHexDigitChars> nonHexDigitChars{};
+ for (char idx = 0; idx < INT8_MAX; ++idx) {
+ if (!hexDigitSet.isKey(idx)) {
+ ASSERT_TRUE(nonHexDigitChars.pushBack(idx));
+ }
+ }
+ ASSERT_FALSE(anyOf(nonHexDigitChars, ext_lib_char_is_hex_digit));
+
+ auto invalidAsciiChars = generateInvalidAsciiChars();
+ ASSERT_FALSE(anyOf(invalidAsciiChars, ext_lib_char_is_hex_digit));
+
+ ASSERT_TRUE(allOf(
+ map(hexDigitChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_hex_digit));
+ ASSERT_FALSE(anyOf(
+ map(nonHexDigitChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_hex_digit));
+ ASSERT_FALSE(anyOf(
+ map(invalidAsciiChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_hex_digit));
+
+ ASSERT_TRUE(allOf(
+ map(hexDigitChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_hex_digit));
+ ASSERT_FALSE(anyOf(
+ map(nonHexDigitChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_hex_digit));
+ ASSERT_FALSE(anyOf(
+ map(invalidAsciiChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_hex_digit));
+
+ Utf8 utf8{invalidAscii};
+ bool isAscii = false;
+ ASSERT_EQ(ext_lib_utf8_is_hex_digit(nullptr, nullptr), ExtNullPointer);
+ ASSERT_EQ(ext_lib_utf8_is_hex_digit(&utf8, nullptr), ExtNullPointer);
+ ASSERT_EQ(ext_lib_utf8_is_hex_digit(nullptr, &isAscii), ExtNullPointer);
+ ASSERT_EQ(ext_lib_utf8_is_hex_digit(&utf8, &isAscii), ExtInvalidInput);
+ ASSERT_FALSE(isAscii);
+
+ ASSERT_TRUE(allOf(
+ map(hexDigitChars,
+ [](char letter) { return FudUtf8::makeUtf8(ExtUtf8Char4{static_cast<utf8>(letter)}); }),
+ [](auto& utf8Letter) {
+ bool predicate = false;
+ auto isPredicateStatus = ext_lib_utf8_is_hex_digit(&utf8Letter, &predicate);
+ return isPredicateStatus == ExtSuccess && predicate;
+ }));
+ ASSERT_FALSE(anyOf(
+ map(nonHexDigitChars,
+ [](char letter) { return FudUtf8::makeUtf8(ExtUtf8Char4{static_cast<utf8>(letter)}); }),
+ [](auto& utf8Letter) {
+ bool predicate = false;
+ auto isPredicateStatus = ext_lib_utf8_is_hex_digit(&utf8Letter, &predicate);
+ return isPredicateStatus != ExtSuccess || predicate;
+ }));
+ ASSERT_FALSE(allOf(
+ map(nonHexDigitChars,
+ [](char letter) { return FudUtf8::makeUtf8(ExtUtf8Char4{static_cast<utf8>(letter)}); }),
+ [](auto& utf8Letter) {
+ bool predicate = false;
+ auto isPredicateStatus = ext_lib_utf8_is_hex_digit(&utf8Letter, &predicate);
+ return isPredicateStatus == ExtInvalidInput && !predicate;
+ }));
+}
+
+TEST(Utf8Test, Utf8IsControl)
+{
+ auto controlChars = generateIndexArray<Array, char, numControlChars>([](int idx) { return static_cast<char>(idx); });
+ constexpr const char deleteChar = 0x7F;
+ controlChars.back() = deleteChar;
+
+ ASSERT_TRUE(allOf(controlChars, ext_lib_char_is_control));
+
+ constexpr size_t numNonControlChars = 256 - numControlChars;
+ auto nonControlChars = generateIndexArray<Array, char, numControlChars>([](int idx) {
+ return static_cast<char>(idx + printableCharOffset);
+ });
+ ASSERT_FALSE(anyOf(nonControlChars, ext_lib_char_is_control));
+
+ auto invalidAsciiChars = generateInvalidAsciiChars();
+ ASSERT_FALSE(anyOf(invalidAsciiChars, ext_lib_char_is_control));
+
+ ASSERT_TRUE(allOf(
+ map(controlChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_control));
+ ASSERT_FALSE(anyOf(
+ map(nonControlChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_control));
+ ASSERT_FALSE(anyOf(
+ map(invalidAsciiChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_control));
+
+ ASSERT_TRUE(allOf(
+ map(controlChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_control));
+ ASSERT_FALSE(anyOf(
+ map(nonControlChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_control));
+ ASSERT_FALSE(anyOf(
+ map(invalidAsciiChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_control));
+
+ Utf8 utf8{invalidAscii};
+ bool isAscii = false;
+ ASSERT_EQ(ext_lib_utf8_is_control(nullptr, nullptr), ExtNullPointer);
+ ASSERT_EQ(ext_lib_utf8_is_control(&utf8, nullptr), ExtNullPointer);
+ ASSERT_EQ(ext_lib_utf8_is_control(nullptr, &isAscii), ExtNullPointer);
+ ASSERT_EQ(ext_lib_utf8_is_control(&utf8, &isAscii), ExtInvalidInput);
+ ASSERT_FALSE(isAscii);
+
+ ASSERT_TRUE(allOf(
+ map(controlChars,
+ [](char letter) { return FudUtf8::makeUtf8(ExtUtf8Char4{static_cast<utf8>(letter)}); }),
+ [](auto& utf8Letter) {
+ bool predicate = false;
+ auto isPredicateStatus = ext_lib_utf8_is_control(&utf8Letter, &predicate);
+ return isPredicateStatus == ExtSuccess && predicate;
+ }));
+ ASSERT_FALSE(anyOf(
+ map(nonControlChars,
+ [](char letter) { return FudUtf8::makeUtf8(ExtUtf8Char4{static_cast<utf8>(letter)}); }),
+ [](auto& utf8Letter) {
+ bool predicate = false;
+ auto isPredicateStatus = ext_lib_utf8_is_control(&utf8Letter, &predicate);
+ return isPredicateStatus != ExtSuccess || predicate;
+ }));
+ ASSERT_FALSE(allOf(
+ map(nonControlChars,
+ [](char letter) { return FudUtf8::makeUtf8(ExtUtf8Char4{static_cast<utf8>(letter)}); }),
+ [](auto& utf8Letter) {
+ bool predicate = false;
+ auto isPredicateStatus = ext_lib_utf8_is_control(&utf8Letter, &predicate);
+ return isPredicateStatus == ExtInvalidInput && !predicate;
+ }));
+}
+
+TEST(Utf8Test, Utf8IsGraphical)
+{
+ constexpr size_t numGraphicalChars = sizeof(GRAPHICAL_CHARS) - 1;
+ Array<char, numGraphicalChars + 1> graphicalCharLiteral{GRAPHICAL_CHARS};
+ Array<char, numGraphicalChars> graphicalChars{};
+ copyMem<numGraphicalChars>(graphicalChars, graphicalCharLiteral);
+
+ ASSERT_TRUE(allOf(graphicalChars, ext_lib_char_is_graphical));
+
+ auto graphicalSetResult{StaticSet<char, numGraphicalChars>::makeFromArray(graphicalChars)};
+ ASSERT_TRUE(graphicalSetResult.isOkay());
+ auto graphicalSet{std::move(graphicalSetResult.getOkay())};
+
+ constexpr size_t numNonGraphicalChars = validAsciiSize - numGraphicalChars;
+ FixedVector<char, numNonGraphicalChars> nonGraphicalChars{};
+ for (char idx = 0; idx < INT8_MAX; ++idx) {
+ if (!graphicalSet.isKey(idx)) {
+ ASSERT_TRUE(nonGraphicalChars.pushBack(idx));
+ }
+ }
+ ASSERT_FALSE(anyOf(nonGraphicalChars, ext_lib_char_is_graphical));
+
+ auto invalidAsciiChars = generateInvalidAsciiChars();
+ ASSERT_FALSE(anyOf(invalidAsciiChars, ext_lib_char_is_graphical));
+
+ ASSERT_TRUE(allOf(
+ map(graphicalChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_graphical));
+ ASSERT_FALSE(anyOf(
+ map(nonGraphicalChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_graphical));
+ ASSERT_FALSE(anyOf(
+ map(invalidAsciiChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_graphical));
+
+ ASSERT_TRUE(allOf(
+ map(graphicalChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_graphical));
+ ASSERT_FALSE(anyOf(
+ map(nonGraphicalChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_graphical));
+ ASSERT_FALSE(anyOf(
+ map(invalidAsciiChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_graphical));
+
+ Utf8 utf8{invalidAscii};
+ bool isAscii = false;
+ ASSERT_EQ(ext_lib_utf8_is_graphical(nullptr, nullptr), ExtNullPointer);
+ ASSERT_EQ(ext_lib_utf8_is_graphical(&utf8, nullptr), ExtNullPointer);
+ ASSERT_EQ(ext_lib_utf8_is_graphical(nullptr, &isAscii), ExtNullPointer);
+ ASSERT_EQ(ext_lib_utf8_is_graphical(&utf8, &isAscii), ExtInvalidInput);
+ ASSERT_FALSE(isAscii);
+
+ ASSERT_TRUE(allOf(
+ map(graphicalChars,
+ [](char letter) { return FudUtf8::makeUtf8(ExtUtf8Char4{static_cast<utf8>(letter)}); }),
+ [](auto& utf8Letter) {
+ bool predicate = false;
+ auto isPredicateStatus = ext_lib_utf8_is_graphical(&utf8Letter, &predicate);
+ return isPredicateStatus == ExtSuccess && predicate;
+ }));
+ ASSERT_FALSE(anyOf(
+ map(nonGraphicalChars,
+ [](char letter) { return FudUtf8::makeUtf8(ExtUtf8Char4{static_cast<utf8>(letter)}); }),
+ [](auto& utf8Letter) {
+ bool predicate = false;
+ auto isPredicateStatus = ext_lib_utf8_is_graphical(&utf8Letter, &predicate);
+ return isPredicateStatus != ExtSuccess || predicate;
+ }));
+ ASSERT_FALSE(allOf(
+ map(nonGraphicalChars,
+ [](char letter) { return FudUtf8::makeUtf8(ExtUtf8Char4{static_cast<utf8>(letter)}); }),
+ [](auto& utf8Letter) {
+ bool predicate = false;
+ auto isPredicateStatus = ext_lib_utf8_is_graphical(&utf8Letter, &predicate);
+ return isPredicateStatus == ExtInvalidInput && !predicate;
+ }));
+}
+
+TEST(Utf8Test, Utf8IsSpace)
+{
+ constexpr size_t numSpaceChars = sizeof(" \t\v\r\n") - 1;
+ Array<char, numSpaceChars + 1> spaceCharLiteral{" \t\v\r\n"};
+ Array<char, numSpaceChars> spaceChars{};
+ copyMem<numSpaceChars>(spaceChars, spaceCharLiteral);
+
+ ASSERT_TRUE(allOf(spaceChars, ext_lib_char_is_space));
+
+ auto spaceSetResult{StaticSet<char, numSpaceChars>::makeFromArray(spaceChars)};
+ ASSERT_TRUE(spaceSetResult.isOkay());
+ auto spaceSet{std::move(spaceSetResult.getOkay())};
+
+ constexpr size_t numNonSpaceChars = validAsciiSize - numSpaceChars;
+ FixedVector<char, numNonSpaceChars> nonSpaceChars{};
+ for (char idx = 0; idx < INT8_MAX; ++idx) {
+ if (!spaceSet.isKey(idx)) {
+ ASSERT_TRUE(nonSpaceChars.pushBack(idx));
+ }
+ }
+ ASSERT_FALSE(anyOf(nonSpaceChars, ext_lib_char_is_space));
+
+ auto invalidAsciiChars = generateInvalidAsciiChars();
+ ASSERT_FALSE(anyOf(invalidAsciiChars, ext_lib_char_is_space));
+
+ ASSERT_TRUE(allOf(
+ map(spaceChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_space));
+ ASSERT_FALSE(anyOf(
+ map(nonSpaceChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_space));
+ ASSERT_FALSE(anyOf(
+ map(invalidAsciiChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_space));
+
+ ASSERT_TRUE(allOf(
+ map(spaceChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_space));
+ ASSERT_FALSE(anyOf(
+ map(nonSpaceChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_space));
+ ASSERT_FALSE(anyOf(
+ map(invalidAsciiChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_space));
+
+ Utf8 utf8{invalidAscii};
+ bool isAscii = false;
+ ASSERT_EQ(ext_lib_utf8_is_space(nullptr, nullptr), ExtNullPointer);
+ ASSERT_EQ(ext_lib_utf8_is_space(&utf8, nullptr), ExtNullPointer);
+ ASSERT_EQ(ext_lib_utf8_is_space(nullptr, &isAscii), ExtNullPointer);
+ ASSERT_EQ(ext_lib_utf8_is_space(&utf8, &isAscii), ExtInvalidInput);
+ ASSERT_FALSE(isAscii);
+
+ ASSERT_TRUE(allOf(
+ map(spaceChars, [](char letter) { return FudUtf8::makeUtf8(ExtUtf8Char4{static_cast<utf8>(letter)}); }),
+ [](auto& utf8Letter) {
+ bool predicate = false;
+ auto isPredicateStatus = ext_lib_utf8_is_space(&utf8Letter, &predicate);
+ return isPredicateStatus == ExtSuccess && predicate;
+ }));
+ ASSERT_FALSE(anyOf(
+ map(nonSpaceChars,
+ [](char letter) { return FudUtf8::makeUtf8(ExtUtf8Char4{static_cast<utf8>(letter)}); }),
+ [](auto& utf8Letter) {
+ bool predicate = false;
+ auto isPredicateStatus = ext_lib_utf8_is_space(&utf8Letter, &predicate);
+ return isPredicateStatus != ExtSuccess || predicate;
+ }));
+ ASSERT_FALSE(allOf(
+ map(nonSpaceChars,
+ [](char letter) { return FudUtf8::makeUtf8(ExtUtf8Char4{static_cast<utf8>(letter)}); }),
+ [](auto& utf8Letter) {
+ bool predicate = false;
+ auto isPredicateStatus = ext_lib_utf8_is_space(&utf8Letter, &predicate);
+ return isPredicateStatus == ExtInvalidInput && !predicate;
+ }));
+}
+
+TEST(Utf8Test, Utf8IsBlank)
+{
+ constexpr size_t numBlankChars = sizeof(" \t") - 1;
+ Array<char, numBlankChars + 1> blankCharLiteral{" \t"};
+ Array<char, numBlankChars> blankChars{};
+ copyMem<numBlankChars>(blankChars, blankCharLiteral);
+
+ ASSERT_TRUE(allOf(blankChars, ext_lib_char_is_blank));
+
+ auto blankSetResult{StaticSet<char, numBlankChars>::makeFromArray(blankChars)};
+ ASSERT_TRUE(blankSetResult.isOkay());
+ auto blankSet{std::move(blankSetResult.getOkay())};
+
+ constexpr size_t numNonBlankChars = validAsciiSize - numBlankChars;
+ FixedVector<char, numNonBlankChars> nonBlankChars{};
+ for (char idx = 0; idx < INT8_MAX; ++idx) {
+ if (!blankSet.isKey(idx)) {
+ ASSERT_TRUE(nonBlankChars.pushBack(idx));
+ }
+ }
+ ASSERT_FALSE(anyOf(nonBlankChars, ext_lib_char_is_blank));
+
+ auto invalidAsciiChars = generateInvalidAsciiChars();
+ ASSERT_FALSE(anyOf(invalidAsciiChars, ext_lib_char_is_blank));
+
+ ASSERT_TRUE(allOf(
+ map(blankChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_blank));
+ ASSERT_FALSE(anyOf(
+ map(nonBlankChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_blank));
+ ASSERT_FALSE(anyOf(
+ map(invalidAsciiChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_blank));
+
+ ASSERT_TRUE(allOf(
+ map(blankChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_blank));
+ ASSERT_FALSE(anyOf(
+ map(nonBlankChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_blank));
+ ASSERT_FALSE(anyOf(
+ map(invalidAsciiChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_blank));
+
+ Utf8 utf8{invalidAscii};
+ bool isAscii = false;
+ ASSERT_EQ(ext_lib_utf8_is_blank(nullptr, nullptr), ExtNullPointer);
+ ASSERT_EQ(ext_lib_utf8_is_blank(&utf8, nullptr), ExtNullPointer);
+ ASSERT_EQ(ext_lib_utf8_is_blank(nullptr, &isAscii), ExtNullPointer);
+ ASSERT_EQ(ext_lib_utf8_is_blank(&utf8, &isAscii), ExtInvalidInput);
+ ASSERT_FALSE(isAscii);
+
+ ASSERT_TRUE(allOf(
+ map(blankChars, [](char letter) { return FudUtf8::makeUtf8(ExtUtf8Char4{static_cast<utf8>(letter)}); }),
+ [](auto& utf8Letter) {
+ bool predicate = false;
+ auto isPredicateStatus = ext_lib_utf8_is_blank(&utf8Letter, &predicate);
+ return isPredicateStatus == ExtSuccess && predicate;
+ }));
+ ASSERT_FALSE(anyOf(
+ map(nonBlankChars,
+ [](char letter) { return FudUtf8::makeUtf8(ExtUtf8Char4{static_cast<utf8>(letter)}); }),
+ [](auto& utf8Letter) {
+ bool predicate = false;
+ auto isPredicateStatus = ext_lib_utf8_is_blank(&utf8Letter, &predicate);
+ return isPredicateStatus != ExtSuccess || predicate;
+ }));
+ ASSERT_FALSE(allOf(
+ map(nonBlankChars,
+ [](char letter) { return FudUtf8::makeUtf8(ExtUtf8Char4{static_cast<utf8>(letter)}); }),
+ [](auto& utf8Letter) {
+ bool predicate = false;
+ auto isPredicateStatus = ext_lib_utf8_is_blank(&utf8Letter, &predicate);
+ return isPredicateStatus == ExtInvalidInput && !predicate;
+ }));
+}
+
+TEST(Utf8Test, Utf8IsPrintable)
+{
+ constexpr size_t numPrintableChars = validAsciiSize - numControlChars;
+ auto printableChars = generateIndexArray<Array, char, numPrintableChars>([](int idx) {
+ return static_cast<char>(idx + printableCharOffset);
+ });
+
+ ASSERT_TRUE(allOf(printableChars, ext_lib_char_is_printable));
+
+ auto printableSetResult{StaticSet<char, numPrintableChars>::makeFromArray(printableChars)};
+ ASSERT_TRUE(printableSetResult.isOkay());
+ auto printableSet{std::move(printableSetResult.getOkay())};
+
+ constexpr size_t numNonPrintableChars = validAsciiSize - numPrintableChars;
+ FixedVector<char, numNonPrintableChars> nonPrintableChars{};
+ for (char idx = 0; idx < INT8_MAX; ++idx) {
+ if (!printableSet.isKey(idx)) {
+ ASSERT_TRUE(nonPrintableChars.pushBack(idx));
+ }
+ }
+ ASSERT_FALSE(anyOf(nonPrintableChars, ext_lib_char_is_printable));
+
+ auto invalidAsciiChars = generateInvalidAsciiChars();
+ ASSERT_FALSE(anyOf(invalidAsciiChars, ext_lib_char_is_printable));
+
+ ASSERT_TRUE(allOf(
+ map(printableChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_printable));
+ ASSERT_FALSE(anyOf(
+ map(nonPrintableChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_printable));
+ ASSERT_FALSE(anyOf(
+ map(invalidAsciiChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_printable));
+
+ ASSERT_TRUE(allOf(
+ map(printableChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_printable));
+ ASSERT_FALSE(anyOf(
+ map(nonPrintableChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_printable));
+ ASSERT_FALSE(anyOf(
+ map(invalidAsciiChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_printable));
+
+ Utf8 utf8{invalidAscii};
+ bool isAscii = false;
+ ASSERT_EQ(ext_lib_utf8_is_printable(nullptr, nullptr), ExtNullPointer);
+ ASSERT_EQ(ext_lib_utf8_is_printable(&utf8, nullptr), ExtNullPointer);
+ ASSERT_EQ(ext_lib_utf8_is_printable(nullptr, &isAscii), ExtNullPointer);
+ ASSERT_EQ(ext_lib_utf8_is_printable(&utf8, &isAscii), ExtInvalidInput);
+ ASSERT_FALSE(isAscii);
+
+ ASSERT_TRUE(allOf(
+ map(printableChars,
+ [](char letter) { return FudUtf8::makeUtf8(ExtUtf8Char4{static_cast<utf8>(letter)}); }),
+ [](auto& utf8Letter) {
+ bool predicate = false;
+ auto isPredicateStatus = ext_lib_utf8_is_printable(&utf8Letter, &predicate);
+ return isPredicateStatus == ExtSuccess && predicate;
+ }));
+ ASSERT_FALSE(anyOf(
+ map(nonPrintableChars,
+ [](char letter) { return FudUtf8::makeUtf8(ExtUtf8Char4{static_cast<utf8>(letter)}); }),
+ [](auto& utf8Letter) {
+ bool predicate = false;
+ auto isPredicateStatus = ext_lib_utf8_is_printable(&utf8Letter, &predicate);
+ return isPredicateStatus != ExtSuccess || predicate;
+ }));
+ ASSERT_FALSE(allOf(
+ map(nonPrintableChars,
+ [](char letter) { return FudUtf8::makeUtf8(ExtUtf8Char4{static_cast<utf8>(letter)}); }),
+ [](auto& utf8Letter) {
+ bool predicate = false;
+ auto isPredicateStatus = ext_lib_utf8_is_printable(&utf8Letter, &predicate);
+ return isPredicateStatus == ExtInvalidInput && !predicate;
+ }));
+}
+
+TEST(Utf8Test, Utf8IsPunctuation)
+{
+ constexpr size_t numPunctuationChars = sizeof(PUNCTUATION_CHARS) - 1;
+ Array<char, numPunctuationChars + 1> punctuationCharLiteral{PUNCTUATION_CHARS};
+ Array<char, numPunctuationChars> punctuationChars{};
+ copyMem<numPunctuationChars>(punctuationChars, punctuationCharLiteral);
+
+ ASSERT_TRUE(allOf(punctuationChars, ext_lib_char_is_punctuation));
+
+ auto punctuationSetResult{StaticSet<char, numPunctuationChars>::makeFromArray(punctuationChars)};
+ ASSERT_TRUE(punctuationSetResult.isOkay());
+ auto punctuationSet{std::move(punctuationSetResult.getOkay())};
+
+ constexpr size_t numNonPunctuationChars = validAsciiSize - numPunctuationChars;
+ FixedVector<char, numNonPunctuationChars> nonPunctuationChars{};
+ for (char idx = 0; idx < INT8_MAX; ++idx) {
+ if (!punctuationSet.isKey(idx)) {
+ ASSERT_TRUE(nonPunctuationChars.pushBack(idx));
+ }
+ }
+ ASSERT_FALSE(anyOf(nonPunctuationChars, ext_lib_char_is_punctuation));
+
+ auto invalidAsciiChars = generateInvalidAsciiChars();
+ ASSERT_FALSE(anyOf(invalidAsciiChars, ext_lib_char_is_punctuation));
+
+ ASSERT_TRUE(allOf(
+ map(punctuationChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_punctuation));
+ ASSERT_FALSE(anyOf(
+ map(nonPunctuationChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_punctuation));
+ ASSERT_FALSE(anyOf(
+ map(invalidAsciiChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_punctuation));
+
+ ASSERT_TRUE(allOf(
+ map(punctuationChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_punctuation));
+ ASSERT_FALSE(anyOf(
+ map(nonPunctuationChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_punctuation));
+ ASSERT_FALSE(anyOf(
+ map(invalidAsciiChars, [](auto input) { return ExtUtf8Char4{static_cast<utf8>(input)}; }),
+ ext_lib_char4_is_punctuation));
+
+ Utf8 utf8{invalidAscii};
+ bool isAscii = false;
+ ASSERT_EQ(ext_lib_utf8_is_punctuation(nullptr, nullptr), ExtNullPointer);
+ ASSERT_EQ(ext_lib_utf8_is_punctuation(&utf8, nullptr), ExtNullPointer);
+ ASSERT_EQ(ext_lib_utf8_is_punctuation(nullptr, &isAscii), ExtNullPointer);
+ ASSERT_EQ(ext_lib_utf8_is_punctuation(&utf8, &isAscii), ExtInvalidInput);
+ ASSERT_FALSE(isAscii);
+
+ ASSERT_TRUE(allOf(
+ map(punctuationChars,
+ [](char letter) { return FudUtf8::makeUtf8(ExtUtf8Char4{static_cast<utf8>(letter)}); }),
+ [](auto& utf8Letter) {
+ bool predicate = false;
+ auto isPredicateStatus = ext_lib_utf8_is_punctuation(&utf8Letter, &predicate);
+ return isPredicateStatus == ExtSuccess && predicate;
+ }));
+ ASSERT_FALSE(anyOf(
+ map(nonPunctuationChars,
+ [](char letter) { return FudUtf8::makeUtf8(ExtUtf8Char4{static_cast<utf8>(letter)}); }),
+ [](auto& utf8Letter) {
+ bool predicate = false;
+ auto isPredicateStatus = ext_lib_utf8_is_punctuation(&utf8Letter, &predicate);
+ return isPredicateStatus != ExtSuccess || predicate;
+ }));
+ ASSERT_FALSE(allOf(
+ map(nonPunctuationChars,
+ [](char letter) { return FudUtf8::makeUtf8(ExtUtf8Char4{static_cast<utf8>(letter)}); }),
+ [](auto& utf8Letter) {
+ bool predicate = false;
+ auto isPredicateStatus = ext_lib_utf8_is_punctuation(&utf8Letter, &predicate);
+ return isPredicateStatus == ExtInvalidInput && !predicate;
+ }));
+}
+#endif
+
+} // namespace fud