Skip to content

Commit

Permalink
Add the latest version of Boost.Text components used here. This comes…
Browse files Browse the repository at this point in the history
… from

2c9d55a8 of the Boost.Tet clang_support branch.

Fixes #24.
  • Loading branch information
tzlaine committed Dec 16, 2023
1 parent fbcc28a commit c78113d
Show file tree
Hide file tree
Showing 20 changed files with 3,013 additions and 3,351 deletions.
4 changes: 2 additions & 2 deletions include/boost/parser/detail/printing.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ namespace boost { namespace parser { namespace detail {
static_assert(
std::is_integral<std::decay_t<decltype(*first_)>>{}, "");
static_assert(SizeofValueType == 4, "");
auto utf8 = text::as_utf8(first_, last_);
auto utf8 = BOOST_PARSER_DETAIL_TEXT_SUBRANGE(first_, last_) | text::as_utf8;
auto first = utf8.begin();
auto last = utf8.end();
if (quote)
Expand All @@ -330,7 +330,7 @@ namespace boost { namespace parser { namespace detail {
bool quote,
int64_t trace_input_cps)
{
auto utf32 = text::as_utf32(first_, last_);
auto utf32 = BOOST_PARSER_DETAIL_TEXT_SUBRANGE(first_, last_) | text::as_utf32;
auto first = utf32.begin();
auto const last = utf32.end();
static_assert(sizeof(*first_) == 1);
Expand Down
19 changes: 12 additions & 7 deletions include/boost/parser/detail/printing_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@ namespace boost { namespace parser { namespace detail {
static void
call(Context const & context, std::ostream & os, Expected expected)
{
std::array<uint32_t, 1> cps = {{(uint32_t)expected}};
std::array<char32_t, 1> cps = {{(char32_t)expected}};
auto const r = text::as_utf8(cps);
os << "'";
for (auto c : r) {
Expand Down Expand Up @@ -579,9 +579,13 @@ namespace boost { namespace parser { namespace detail {
int components)
{
os << "string(\"";
for (auto c :
text::as_utf8(parser.expected_first_, parser.expected_last_)) {
detail::print_char(os, c);
auto r = BOOST_PARSER_DETAIL_TEXT_SUBRANGE(
parser.expected_first_, parser.expected_last_) |
text::as_utf8;
auto it = r.begin();
for (; it != r.end();
++it) {
detail::print_char(os, *it);
}
os << "\")";
}
Expand All @@ -594,9 +598,10 @@ namespace boost { namespace parser { namespace detail {
int components)
{
os << "\"";
for (auto c : text::as_utf8(
parser.parser_.expected_first_,
parser.parser_.expected_last_)) {
for (auto c : BOOST_PARSER_DETAIL_TEXT_SUBRANGE(
parser.parser_.expected_first_,
parser.parser_.expected_last_) |
text::as_utf8) {
detail::print_char(os, c);
}
os << "\"";
Expand Down
6 changes: 3 additions & 3 deletions include/boost/parser/detail/text/algorithm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -321,9 +321,9 @@ namespace boost::parser::detail { namespace text {
if (first1 == last1 || first2 == last2)
return {first1, first1};

if (std::next(first2) == last2) {
if (detail::next(first2) == last2) {
auto const it = parser::detail::text::find(first1, last1, *first2);
return {it, std::next(it)};
return {it, detail::next(it)};
}

auto it = first1;
Expand All @@ -333,7 +333,7 @@ namespace boost::parser::detail { namespace text {
if (first1 == last1)
return {first1, first1};

auto it2 = std::next(first2);
auto it2 = detail::next(first2);
it = first1;
if (++it == last1)
return {it, it};
Expand Down
140 changes: 106 additions & 34 deletions include/boost/parser/detail/text/concepts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,30 @@

#include <boost/parser/detail/text/config.hpp>
#include <boost/parser/detail/text/utf.hpp>
#include <boost/parser/detail/text/detail/begin_end.hpp>

#if defined(BOOST_TEXT_DOXYGEN) || BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS

#include <ranges>
#include <string_view>


namespace boost::parser::detail { namespace text { BOOST_PARSER_DETAIL_TEXT_NAMESPACE_V2 {

//[ concepts_concepts

#ifdef _MSC_VER
inline constexpr format wchar_t_format = format::utf16;
#else
inline constexpr format wchar_t_format = format::utf32;
#endif

template<typename T, format F>
concept code_unit = std::integral<T> && sizeof(T) == (int)F;
concept code_unit = (std::same_as<T, char8_t> && F == format::utf8) ||
(std::same_as<T, char16_t> && F == format::utf16) ||
(std::same_as<T, char32_t> && F == format::utf32) ||
(std::same_as<T, char> && F == format::utf8) ||
(std::same_as<T, wchar_t> && F == wchar_t_format);

template<typename T>
concept utf8_code_unit = code_unit<T, format::utf8>;
Expand All @@ -32,14 +44,19 @@ namespace boost::parser::detail { namespace text { BOOST_PARSER_DETAIL_TEXT_NAME

template<typename T, format F>
concept code_unit_iter =
std::bidirectional_iterator<T> && code_unit<std::iter_value_t<T>, F>;
std::input_iterator<T> && code_unit<std::iter_value_t<T>, F>;

template<typename T>
concept utf_code_unit =
utf8_code_unit<T> || utf16_code_unit<T> || utf32_code_unit<T>;


template<typename T, format F>
concept code_unit_pointer =
std::is_pointer_v<T> && code_unit<std::iter_value_t<T>, F>;

template<typename T, format F>
concept code_unit_range = std::ranges::bidirectional_range<T> &&
concept code_unit_range = std::ranges::input_range<T> &&
code_unit<std::ranges::range_value_t<T>, F>;

template<typename T, format F>
Expand Down Expand Up @@ -82,19 +99,27 @@ namespace boost::parser::detail { namespace text { BOOST_PARSER_DETAIL_TEXT_NAME
template<typename T>
concept code_point_range = utf32_range<T>;

template<typename T>
concept utf_iter = utf8_iter<T> || utf16_iter<T> || utf32_iter<T>;
template<typename T>
concept utf_pointer =
utf8_pointer<T> || utf16_pointer<T> || utf32_pointer<T>;
template<typename T>
concept utf_range = utf8_range<T> || utf16_range<T> || utf32_range<T>;


template<typename T>
concept grapheme_iter =
// clang-format off
std::bidirectional_iterator<T> &&
std::input_iterator<T> &&
code_point_range<std::iter_reference_t<T>> &&
requires(T t) {
{ t.base() } -> code_point_iter;
// clang-format on
};

template<typename T>
concept grapheme_range = std::ranges::bidirectional_range<T> &&
concept grapheme_range = std::ranges::input_range<T> &&
grapheme_iter<std::ranges::iterator_t<T>>;

template<typename R>
Expand All @@ -118,63 +143,62 @@ namespace boost::parser::detail { namespace text { BOOST_PARSER_DETAIL_TEXT_NAME


namespace dtl {
template<typename T>
concept eraseable_sized_bidi_range =
template<typename T, class CodeUnit>
concept eraseable_insertable_sized_bidi_range =
// clang-format off
std::ranges::sized_range<T> &&
std::ranges::bidirectional_range<T> && requires(T t) {
{ t.erase(t.begin(), t.end()) } ->
std::same_as<std::ranges::iterator_t<T>>;
// clang-format on
};
std::ranges::input_range<T> &&
requires(T t, CodeUnit const * it) {
{ t.erase(t.begin(), t.end()) } ->
std::same_as<std::ranges::iterator_t<T>>;
{ t.insert(t.end(), it, it) } ->
std::same_as<std::ranges::iterator_t<T>>;
};
// clang-format on
}

template<typename T>
concept utf8_string =
// clang-format off
dtl::eraseable_sized_bidi_range<T> &&
utf8_code_unit<std::ranges::range_value_t<T>> &&
requires(T t, char const * it) {
{ t.insert(t.end(), it, it) } ->
std::same_as<std::ranges::iterator_t<T>>;
dtl::eraseable_insertable_sized_bidi_range<
T, std::ranges::range_value_t<T>>;
// clang-format on
};

template<typename T>
concept utf16_string =
// clang-format off
dtl::eraseable_sized_bidi_range<T> &&
utf16_code_unit<std::ranges::range_value_t<T>> &&
requires(T t, uint16_t const * it) {
{ t.insert(t.end(), it, it) } ->
std::same_as<std::ranges::iterator_t<T>>;
dtl::eraseable_insertable_sized_bidi_range<
T, std::ranges::range_value_t<T>>;
// clang-format on
};

template<typename T>
concept utf_string = utf8_string<T> || utf16_string<T>;

template<typename T>
// clang-format off
concept transcoding_error_handler = requires(T t) {
{ t("") } -> code_point;
concept transcoding_error_handler = requires(T t, std::string_view msg) {
{ t(msg) } -> std::same_as<char32_t>;
// clang-format on
};

template<typename T>
concept utf_iter = utf8_iter<T> || utf16_iter<T> || utf32_iter<T>;

template<typename T>
// clang-format off
concept utf_range_like =
utf8_range<std::remove_reference_t<T>> ||
utf16_range<std::remove_reference_t<T>> ||
utf32_range<std::remove_reference_t<T>> ||
utf8_pointer<std::remove_reference_t<T>> ||
utf16_pointer<std::remove_reference_t<T>> ||
utf32_pointer<std::remove_reference_t<T>>;
utf_range<std::remove_reference_t<T>> ||
utf_pointer<std::remove_reference_t<T>>;
// clang-format on

template<typename T>
concept utf8_range_like = utf8_code_unit<std::iter_value_t<T>> ||
utf8_pointer<std::remove_reference_t<T>>;
template<typename T>
concept utf16_range_like = utf16_code_unit<std::iter_value_t<T>> ||
utf16_pointer<std::remove_reference_t<T>>;
template<typename T>
concept utf32_range_like = utf32_code_unit<std::iter_value_t<T>> ||
utf32_pointer<std::remove_reference_t<T>>;
//]

// Clang 13 defines __cpp_lib_concepts but not std::indirectly copyable.
Expand All @@ -194,4 +218,52 @@ namespace boost::parser::detail { namespace text { BOOST_PARSER_DETAIL_TEXT_NAME

#endif

namespace boost::parser::detail { namespace text { namespace detail {

#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS

template<typename T>
using iterator_t = std::ranges::iterator_t<T>;
template<typename T>
using sentinel_t = std::ranges::sentinel_t<T>;
template<typename T>
using iter_value_t = std::iter_value_t<T>;
template<typename T>
using iter_reference_t = std::iter_reference_t<T>;
template<typename T>
using range_value_t = std::ranges::range_value_t<T>;
template<typename T>
using range_reference_t = std::ranges::range_reference_t<T>;
template<typename T>
using range_difference_t = std::ranges::range_difference_t<T>;

#else

template<typename T>
using iterator_t = decltype(detail::begin(std::declval<T &>()));
template<typename T>
using sentinel_t = decltype(detail::end(std::declval<T &>()));
template<typename T>
using iter_value_t = typename std::iterator_traits<T>::value_type;
template<typename T>
using iter_reference_t = decltype(*std::declval<T &>());
template<typename T>
using range_value_t = iter_value_t<iterator_t<T>>;
template<typename T>
using range_reference_t = iter_reference_t<iterator_t<T>>;
template<typename T>
using range_difference_t = std::ptrdiff_t;

template<typename T>
constexpr bool code_unit_v =
#if defined(__cpp_char8_t)
std::is_same_v<T, char8_t> ||
#endif
std::is_same_v<T, char16_t> || std::is_same_v<T, char32_t> ||
std::is_same_v<T, char> || std::is_same_v<T, wchar_t>;

#endif

}}}

#endif
56 changes: 42 additions & 14 deletions include/boost/parser/detail/text/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,54 @@

#include <boost/parser/config.hpp>

// Included for definition of __cpp_lib_concepts.
#include <iterator>

#if 202002L <= __cplusplus && defined(__cpp_impl_coroutine) && __has_include(<coroutine>)
#include <coroutine>
#endif


// The contents of <ranges> in libstdc++ is incomplete (e.g. no owning_view)
// before GCC 12.
#if !BOOST_PARSER_USE_CONCEPTS
# define BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS 0
#else
// This is now hard-coded to use the pre-C++20 code path. There are a bunch
// of really odd compile errorswith Clang+libstdc++ I can't be bothered to
// address right now. (The latest version of Boost.Text might fix these
// errors, but there's also no pre-C++20 code path in that version of Text.)
# define BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS 0
# define BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS 1
#endif

// GCC 12 claims to support 201907L <= __cpp_deduction_guides, but does not.
#if defined(__cpp_deduction_guides) && 201907L <= __cpp_deduction_guides && \
(!defined(__GNUC__) || 13 <= __GNUC__)
#define BOOST_PARSER_DETAIL_TEXT_USE_ALIAS_CTAD 1
#else
#define BOOST_PARSER_DETAIL_TEXT_USE_ALIAS_CTAD 0
#endif

#if defined(__cpp_lib_ranges)
namespace boost::parser::detail { namespace text { namespace detail {
inline constexpr auto begin = std::ranges::begin;
inline constexpr auto end = std::ranges::end;
}}}
#else
#include <boost/parser/detail/text/detail/begin_end.hpp>
#endif

#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
# define BOOST_PARSER_DETAIL_TEXT_SUBRANGE std::ranges::subrange
#else
# include <boost/parser/detail/text/subrange.hpp>
# define BOOST_PARSER_DETAIL_TEXT_SUBRANGE boost::parser::detail::text::subrange
#endif

namespace boost::parser::detail { namespace text {
#if defined(__cpp_char8_t)
using char8_type = char8_t;
#else
using char8_type = char;
#endif
}}

// The inline namespaces v1 and v2 represent pre- and post-C++20. v1 is
// inline for standards before C++20, and v2 is inline for C++20 and later.
// Note that this only applies to code for which a v2 namespace alternative
Expand All @@ -32,13 +69,4 @@
# define BOOST_PARSER_DETAIL_TEXT_NAMESPACE_V2 namespace v2
#endif

#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
namespace boost::parser::detail { namespace text { namespace detail {
inline constexpr auto begin = std::ranges::begin;
inline constexpr auto end = std::ranges::end;
}}}
#else
#include <boost/parser/detail/text/detail/begin_end.hpp>
#endif

#endif
Loading

0 comments on commit c78113d

Please sign in to comment.