| //===----------------------------------------------------------------------===// |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| // UNSUPPORTED: c++03, c++11, c++14, c++17 |
| // UNSUPPORTED: libcpp-has-no-incomplete-format |
| // TODO FMT Fix this test using GCC, it currently times out. |
| // UNSUPPORTED: gcc-12 |
| |
| // <format> |
| |
| // Tests the implementation of the extended grapheme cluster boundaries per |
| // https://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundary_Rules |
| // |
| // The tests are based on the test data provided by Unicode |
| // https://www.unicode.org/Public/UCD/latest/ucd/auxiliary/GraphemeBreakTest.txt |
| |
| #include <cassert> |
| #include <format> |
| #include <functional> |
| #include <numeric> |
| |
| #include "extended_grapheme_cluster.h" |
| |
| // Validates whether the number of code points in our "database" matches with |
| // the number in the Unicode. The assumption is when the number of items per |
| // property matches the code points themselves also match. |
| namespace { |
| namespace cluster = std::__extended_grapheme_custer_property_boundary; |
| constexpr int count_entries(cluster::__property property) { |
| return std::transform_reduce( |
| std::begin(cluster::__entries), std::end(cluster::__entries), 0, std::plus{}, [property](auto entry) { |
| if (static_cast<cluster::__property>(entry & 0xf) != property) |
| return 0; |
| |
| return 1 + static_cast<int>((entry >> 4) & 0x7f); |
| }); |
| } |
| |
| static_assert(count_entries(cluster::__property::__Prepend) == 27); |
| static_assert(count_entries(cluster::__property::__CR) == 1); |
| static_assert(count_entries(cluster::__property::__LF) == 1); |
| static_assert(count_entries(cluster::__property::__Control) == 3893); |
| static_assert(count_entries(cluster::__property::__Extend) == 2130); |
| static_assert(count_entries(cluster::__property::__Regional_Indicator) == 26); |
| static_assert(count_entries(cluster::__property::__SpacingMark) == 395); |
| static_assert(count_entries(cluster::__property::__L) == 125); |
| static_assert(count_entries(cluster::__property::__V) == 95); |
| static_assert(count_entries(cluster::__property::__T) == 137); |
| static_assert(count_entries(cluster::__property::__LV) == 399); |
| static_assert(count_entries(cluster::__property::__LVT) == 10773); |
| static_assert(count_entries(cluster::__property::__ZWJ) == 1); |
| static_assert(count_entries(cluster::__property::__Extended_Pictographic) == 3537); |
| |
| } // namespace |
| |
| template <class Data> |
| constexpr void test(const Data& data) { |
| for (const auto& d : data) { |
| assert(d.code_points.size() == d.breaks.size()); |
| |
| std::__unicode::__extended_grapheme_cluster_view view{d.input.begin(), d.input.end()}; |
| for (std::size_t i = 0; i < d.breaks.size(); ++i) { |
| auto r = view.__consume(); |
| assert(r.__code_point_ == d.code_points[i]); |
| assert(r.__last_ == d.input.begin() + d.breaks[i]); |
| } |
| } |
| } |
| |
| constexpr bool test() { |
| test(data_utf8); |
| |
| #ifndef TEST_HAS_NO_WIDE_CHARACTERS |
| if constexpr (sizeof(wchar_t) == 2) |
| test(data_utf16); |
| else |
| test(data_utf32); |
| #endif |
| |
| return true; |
| } |
| |
| int main(int, char**) { |
| test(); |
| // static_assert(test()); |
| |
| return 0; |
| } |