/*============================================================================= Copyright (c) 2001-2015 Joel de Guzman Copyright (c) 2001-2011 Hartmut Kaiser Copyright (c) 2019 Christian Mazakas Copyright (c) 2025 Nana Sakisaka Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) =============================================================================*/ #define BOOST_SPIRIT_X4_UNICODE #include "test.hpp" #include #include #include #include #include #include #include #include #include TEST_CASE("char") { static_assert(x4::traits::is_container_v); static_assert(x4::traits::X4Container); static_assert(x4::traits::CategorizedAttr); static_assert(!x4::traits::is_container_v); static_assert(!x4::traits::X4Container); static_assert(x4::traits::CategorizedAttr); namespace standard = x4::standard; namespace standard_wide = x4::standard_wide; namespace unicode = x4::unicode; { std::string_view sv; auto first = sv.begin(); auto const last = sv.end(); constexpr auto parser = standard::char_('x'); char ch{}; static_assert(noexcept(parser.parse(first, last, unused, ch))); (void)parser.parse(first, last, unused, ch); // Make sure this is static (void)std::remove_const_t::parse(first, last, unused, ch); } { std::u32string_view sv; auto first = sv.begin(); auto const last = sv.end(); constexpr auto parser = unicode::char_(U'x'); char32_t ch{}; static_assert(noexcept(parser.parse(first, last, unused, ch))); (void)parser.parse(first, last, unused, ch); // Make sure this is static (void)std::remove_const_t::parse(first, last, unused, ch); } { using namespace x4::standard; BOOST_SPIRIT_X4_ASSERT_CONSTEXPR_CTORS(char_); BOOST_SPIRIT_X4_ASSERT_CONSTEXPR_CTORS(char_('x')); BOOST_SPIRIT_X4_ASSERT_CONSTEXPR_CTORS(char_('a', 'z')); BOOST_SPIRIT_X4_ASSERT_CONSTEXPR_CTORS(~char_('x')); BOOST_SPIRIT_X4_ASSERT_CONSTEXPR_CTORS(~char_('a', 'z')); BOOST_SPIRIT_X4_ASSERT_CONSTEXPR_CTORS(~~char_('x')); BOOST_SPIRIT_X4_ASSERT_CONSTEXPR_CTORS(~~char_('a', 'z')); CHECK(parse("x", 'x')); CHECK(parse(L"x", L'x')); CHECK(!parse("y", 'x')); CHECK(!parse(L"y", L'x')); CHECK(parse("x", char_)); CHECK(parse("x", char_('x'))); CHECK(!parse("x", char_('y'))); CHECK(parse("x", char_('a', 'z'))); CHECK(!parse("x", char_('0', '9'))); CHECK(parse("0", char_('0', '9'))); CHECK(parse("9", char_('0', '9'))); CHECK(!parse("0", ~char_('0', '9'))); CHECK(!parse("9", ~char_('0', '9'))); CHECK(!parse("x", ~char_)); CHECK(!parse("x", ~char_('x'))); CHECK(parse(" ", ~char_('x'))); CHECK(parse("X", ~char_('x'))); CHECK(!parse("x", ~char_('b', 'y'))); CHECK(parse("a", ~char_('b', 'y'))); CHECK(parse("z", ~char_('b', 'y'))); CHECK(parse("x", ~~char_)); CHECK(parse("x", ~~char_('x'))); CHECK(!parse(" ", ~~char_('x'))); CHECK(!parse("X", ~~char_('x'))); CHECK(parse("x", ~~char_('b', 'y'))); CHECK(!parse("a", ~~char_('b', 'y'))); CHECK(!parse("z", ~~char_('b', 'y'))); } { using namespace x4::standard_wide; BOOST_SPIRIT_X4_ASSERT_CONSTEXPR_CTORS(char_); BOOST_SPIRIT_X4_ASSERT_CONSTEXPR_CTORS(char_(L'x')); BOOST_SPIRIT_X4_ASSERT_CONSTEXPR_CTORS(char_(L'a', L'z')); BOOST_SPIRIT_X4_ASSERT_CONSTEXPR_CTORS(~char_(L'x')); BOOST_SPIRIT_X4_ASSERT_CONSTEXPR_CTORS(~char_(L'a', L'z')); BOOST_SPIRIT_X4_ASSERT_CONSTEXPR_CTORS(~~char_(L'x')); BOOST_SPIRIT_X4_ASSERT_CONSTEXPR_CTORS(~~char_(L'a', L'z')); CHECK(parse(L"x", char_)); CHECK(parse(L"x", char_(L'x'))); CHECK(!parse(L"x", char_(L'y'))); CHECK(parse(L"x", char_(L'a', L'z'))); CHECK(!parse(L"x", char_(L'0', L'9'))); CHECK(!parse(L"x", ~char_)); CHECK(!parse(L"x", ~char_(L'x'))); CHECK(parse(L" ", ~char_(L'x'))); CHECK(parse(L"X", ~char_(L'x'))); CHECK(!parse(L"x", ~char_(L'b', L'y'))); CHECK(parse(L"a", ~char_(L'b', L'y'))); CHECK(parse(L"z", ~char_(L'b', L'y'))); CHECK(parse(L"x", ~~char_)); CHECK(parse(L"x", ~~char_(L'x'))); CHECK(!parse(L" ", ~~char_(L'x'))); CHECK(!parse(L"X", ~~char_(L'x'))); CHECK(parse(L"x", ~~char_(L'b', L'y'))); CHECK(!parse(L"a", ~~char_(L'b', L'y'))); CHECK(!parse(L"z", ~~char_(L'b', L'y'))); } { using namespace x4::standard; CHECK(parse(" x", 'x', space)); CHECK(parse(" x", char_, space)); CHECK(parse(" x", char_('x'), space)); CHECK(!parse(" x", char_('y'), space)); CHECK(parse(" x", char_('a', 'z'), space)); CHECK(!parse(" x", char_('0', '9'), space)); } { using namespace x4::standard_wide; CHECK(parse(L" x", L'x', space)); CHECK(parse(L" x", char_, space)); CHECK(parse(L" x", char_(L'x'), space)); CHECK(!parse(L" x", char_(L'y'), space)); CHECK(parse(L" x", char_(L'a', L'z'), space)); CHECK(!parse(L" x", char_(L'0', L'9'), space)); } // unicode (normal ASCII) { using namespace x4::unicode; CHECK(parse(U"abcd", +char_(U"abcd"))); CHECK(!parse(U"abcd", +char_(U"qwer"))); auto const sub_delims = char_(U"!$&'()*+,;="); auto const delims = std::vector{ U"!", U"$", U"&", U"'", U"(", U")", U"*", U"+", U",", U";", U"=" }; auto const matched_all_sub_delims = std::ranges::all_of(delims, [&](auto const delim) -> bool { return parse(delim, sub_delims).completed(); }); CHECK(matched_all_sub_delims); } // unicode (escaped Unicode char literals) { using namespace x4::unicode; auto const chars = char_(U"\u0024\u00a2\u0939\u20ac\U00010348"); auto const test_strings = std::vector{ U"\u0024", U"\u00a2", U"\u0939", U"\u20ac", U"\U00010348" }; auto const bad_test_strings = std::vector{ U"a", U"B", U"c", U"\u0409" }; auto const all_matched = std::ranges::all_of(test_strings, [&](auto const test_str) -> bool { return parse(test_str, chars).completed(); }); auto const none_matched = std::ranges::all_of(bad_test_strings, [&](auto const bad_test_str) -> bool { return !parse(bad_test_str, chars).completed(); }); CHECK(all_matched); CHECK(none_matched); } // single char strings { CHECK(parse("x", "x")); CHECK(parse(L"x", L"x")); CHECK(parse("x", standard::char_("x"))); CHECK(parse(L"x", standard_wide::char_(L"x"))); CHECK(parse("x", standard::char_('a', 'z'))); CHECK(parse(L"x", standard_wide::char_(L'a', L'z'))); } // chsets { CHECK(parse("x", standard::char_("a-z"))); CHECK(!parse("1", standard::char_("a-z"))); CHECK(parse("1", standard::char_("a-z0-9"))); CHECK(parse(L"x", standard_wide::char_(L"a-z"))); CHECK(!parse(L"1", standard_wide::char_(L"a-z"))); CHECK(parse(L"1", standard_wide::char_(L"a-z0-9"))); CHECK(parse("x", standard::char_(std::string("a-z0-9")))); } }