diff --git a/libcxx/include/__format/format_functions.h b/libcxx/include/__format/format_functions.h --- a/libcxx/include/__format/format_functions.h +++ b/libcxx/include/__format/format_functions.h @@ -236,10 +236,11 @@ __throw_format_error("Invalid argument"); } -template -_LIBCPP_HIDE_FROM_ABI constexpr const _CharT* -__handle_replacement_field(const _CharT* __begin, const _CharT* __end, +template +_LIBCPP_HIDE_FROM_ABI constexpr _Iterator +__handle_replacement_field(_Iterator __begin, _Iterator __end, _ParseCtx& __parse_ctx, _Ctx& __ctx) { + using _CharT = iter_value_t<_Iterator>; __format::__parse_number_result __r = __format::__parse_arg_id(__begin, __end, __parse_ctx); bool __parse = *__r.__ptr == _CharT(':'); @@ -292,8 +293,8 @@ using _CharT = typename _ParseCtx::char_type; static_assert(same_as); - const _CharT* __begin = __parse_ctx.begin(); - const _CharT* __end = __parse_ctx.end(); + auto __begin = __parse_ctx.begin(); + auto __end = __parse_ctx.end(); typename _Ctx::iterator __out_it = __ctx.out(); while (__begin != __end) { switch (*__begin) { diff --git a/libcxx/include/__format/format_string.h b/libcxx/include/__format/format_string.h --- a/libcxx/include/__format/format_string.h +++ b/libcxx/include/__format/format_string.h @@ -26,18 +26,18 @@ namespace __format { -template +template struct _LIBCPP_TEMPLATE_VIS __parse_number_result { - const _CharT* __ptr; + _Iterator __ptr; uint32_t __value; }; -template -__parse_number_result(const _CharT*, uint32_t) -> __parse_number_result<_CharT>; +template +__parse_number_result(_Iterator, uint32_t) -> __parse_number_result<_Iterator>; -template -_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> -__parse_number(const _CharT* __begin, const _CharT* __end); +template +_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator> +__parse_number(_Iterator __begin, _Iterator __end); /** * The maximum value of a numeric argument. @@ -53,16 +53,16 @@ inline constexpr uint32_t __number_max = INT32_MAX; namespace __detail { -template -_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> -__parse_zero(const _CharT* __begin, const _CharT*, auto& __parse_ctx) { +template +_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator> +__parse_zero(_Iterator __begin, _Iterator, auto& __parse_ctx) { __parse_ctx.check_arg_id(0); return {++__begin, 0}; // can never be larger than the maximum. } -template -_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> -__parse_automatic(const _CharT* __begin, const _CharT*, auto& __parse_ctx) { +template +_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator> +__parse_automatic(_Iterator __begin, _Iterator, auto& __parse_ctx) { size_t __value = __parse_ctx.next_arg_id(); _LIBCPP_ASSERT(__value <= __number_max, "Compilers don't support this number of arguments"); @@ -70,10 +70,10 @@ return {__begin, uint32_t(__value)}; } -template -_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> -__parse_manual(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) { - __parse_number_result<_CharT> __r = __parse_number(__begin, __end); +template +_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator> +__parse_manual(_Iterator __begin, _Iterator __end, auto& __parse_ctx) { + __parse_number_result<_Iterator> __r = __parse_number(__begin, __end); __parse_ctx.check_arg_id(__r.__value); return __r; } @@ -86,9 +86,10 @@ * The number is used for the 31-bit values @em width and @em precision. This * allows a maximum value of 2147483647. */ -template -_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> -__parse_number(const _CharT* __begin, const _CharT* __end_input) { +template +_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator> +__parse_number(_Iterator __begin, _Iterator __end_input) { + using _CharT = iter_value_t<_Iterator>; static_assert(__format::__number_max == INT32_MAX, "The algorithm is implemented based on this value."); /* @@ -98,7 +99,7 @@ * - Does the value exceed width of an uint32_t? (Switching to uint64_t would * have the same issue, but with a higher maximum.) */ - const _CharT* __end = __end_input - __begin > 9 ? __begin + 9 : __end_input; + _Iterator __end = __end_input - __begin > 9 ? __begin + 9 : __end_input; uint32_t __value = *__begin - _CharT('0'); while (++__begin != __end) { if (*__begin < _CharT('0') || *__begin > _CharT('9')) @@ -134,9 +135,10 @@ * The parser will return a pointer beyond the last consumed character. This * should be the closing '}' of the arg-id. */ -template -_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> -__parse_arg_id(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) { +template +_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator> +__parse_arg_id(_Iterator __begin, _Iterator __end, auto& __parse_ctx) { + using _CharT = iter_value_t<_Iterator>; switch (*__begin) { case _CharT('0'): return __detail::__parse_zero(__begin, __end, __parse_ctx); diff --git a/libcxx/include/__format/formatter_output.h b/libcxx/include/__format/formatter_output.h --- a/libcxx/include/__format/formatter_output.h +++ b/libcxx/include/__format/formatter_output.h @@ -250,10 +250,11 @@ return __formatter::__fill(_VSTD::move(__out_it), __padding.__after_, __specs.__fill_); } -template +template > _LIBCPP_HIDE_FROM_ABI auto -__write(const _CharT* __first, - const _CharT* __last, +__write(_Iterator __first, + _Iterator __last, output_iterator auto __out_it, __format_spec::__parsed_specifications<_ParserCharT> __specs, ptrdiff_t __size) -> decltype(__out_it) { @@ -264,10 +265,11 @@ /// \overload /// /// Calls the function above where \a __size = \a __last - \a __first. -template +template > _LIBCPP_HIDE_FROM_ABI auto -__write(const _CharT* __first, - const _CharT* __last, +__write(_Iterator __first, + _Iterator __last, output_iterator auto __out_it, __format_spec::__parsed_specifications<_ParserCharT> __specs) -> decltype(__out_it) { _LIBCPP_ASSERT(__first <= __last, "Not a valid range"); @@ -348,7 +350,7 @@ template _LIBCPP_HIDE_FROM_ABI int __truncate(basic_string_view<_CharT>& __str, int __precision) { - __format_spec::__column_width_result<_CharT> __result = + __format_spec::__column_width_result __result = __format_spec::__estimate_column_width(__str, __precision, __format_spec::__column_width_rounding::__down); __str = basic_string_view<_CharT>{__str.begin(), __result.__last_}; return __result.__width_; diff --git a/libcxx/include/__format/parser_std_format_spec.h b/libcxx/include/__format/parser_std_format_spec.h --- a/libcxx/include/__format/parser_std_format_spec.h +++ b/libcxx/include/__format/parser_std_format_spec.h @@ -46,9 +46,10 @@ namespace __format_spec { -template -_LIBCPP_HIDE_FROM_ABI constexpr __format::__parse_number_result< _CharT> -__parse_arg_id(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) { +template +_LIBCPP_HIDE_FROM_ABI constexpr __format::__parse_number_result<_Iterator> +__parse_arg_id(_Iterator __begin, _Iterator __end, auto& __parse_ctx) { + using _CharT = iter_value_t<_Iterator>; // This function is a wrapper to call the real parser. But it does the // validation for the pre-conditions and post-conditions. if (__begin == __end) @@ -254,8 +255,8 @@ _LIBCPP_HIDE_FROM_ABI constexpr auto __parse(basic_format_parse_context<_CharT>& __parse_ctx, __fields __fields) -> decltype(__parse_ctx.begin()) { - const _CharT* __begin = __parse_ctx.begin(); - const _CharT* __end = __parse_ctx.end(); + auto __begin = __parse_ctx.begin(); + auto __end = __parse_ctx.end(); if (__begin == __end) return __begin; @@ -367,7 +368,8 @@ return false; } - _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_fill_align(const _CharT*& __begin, const _CharT* __end) { + template + _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_fill_align(_Iterator& __begin, _Iterator __end) { _LIBCPP_ASSERT(__begin != __end, "when called with an empty input the function will cause " "undefined behavior by evaluating data not in the input"); if (__begin + 1 != __end) { @@ -388,7 +390,8 @@ return true; } - _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_sign(const _CharT*& __begin) { + template + _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_sign(_Iterator& __begin) { switch (*__begin) { case _CharT('-'): __sign_ = __sign::__minus; @@ -406,7 +409,8 @@ return true; } - _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_alternate_form(const _CharT*& __begin) { + template + _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_alternate_form(_Iterator& __begin) { if (*__begin != _CharT('#')) return false; @@ -415,7 +419,8 @@ return true; } - _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_zero_padding(const _CharT*& __begin) { + template + _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_zero_padding(_Iterator& __begin) { if (*__begin != _CharT('0')) return false; @@ -425,7 +430,8 @@ return true; } - _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_width(const _CharT*& __begin, const _CharT* __end, auto& __parse_ctx) { + template + _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_width(_Iterator& __begin, _Iterator __end, auto& __parse_ctx) { if (*__begin == _CharT('0')) __throw_format_error("A format-spec width field shouldn't have a leading zero"); @@ -448,8 +454,8 @@ return true; } - _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_precision(const _CharT*& __begin, const _CharT* __end, - auto& __parse_ctx) { + template + _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_precision(_Iterator& __begin, _Iterator __end, auto& __parse_ctx) { if (*__begin != _CharT('.')) return false; @@ -475,7 +481,8 @@ return true; } - _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_locale_specific_form(const _CharT*& __begin) { + template + _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_locale_specific_form(_Iterator& __begin) { if (*__begin != _CharT('L')) return false; @@ -484,7 +491,8 @@ return true; } - _LIBCPP_HIDE_FROM_ABI constexpr void __parse_type(const _CharT*& __begin) { + template + _LIBCPP_HIDE_FROM_ABI constexpr void __parse_type(_Iterator& __begin) { // Determines the type. It does not validate whether the selected type is // valid. Most formatters have optional fields that are only allowed for // certain types. These parsers need to do validation after the type has @@ -707,18 +715,18 @@ } } -template +template struct __column_width_result { /// The number of output columns. size_t __width_; /// One beyond the last code unit used in the estimation. /// /// This limits the original output to fit in the wanted number of columns. - const _CharT* __last_; + _Iterator __last_; }; -template -__column_width_result(size_t, const _CharT*) -> __column_width_result<_CharT>; +template +__column_width_result(size_t, _Iterator) -> __column_width_result<_Iterator>; /// Since a column width can be two it's possible that the requested column /// width can't be achieved. Depending on the intended usage the policy can be @@ -785,12 +793,13 @@ return __detail::__column_width_4(__c); } -template -_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> __estimate_column_width_grapheme_clustering( - const _CharT* __first, const _CharT* __last, size_t __maximum, __column_width_rounding __rounding) noexcept { +template +_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_Iterator> __estimate_column_width_grapheme_clustering( + _Iterator __first, _Iterator __last, size_t __maximum, __column_width_rounding __rounding) noexcept { + using _CharT = iter_value_t<_Iterator>; __unicode::__extended_grapheme_cluster_view<_CharT> __view{__first, __last}; - __column_width_result<_CharT> __result{0, __first}; + __column_width_result<_Iterator> __result{0, __first}; while (__result.__last_ != __last && __result.__width_ <= __maximum) { typename __unicode::__extended_grapheme_cluster_view<_CharT>::__cluster __cluster = __view.__consume(); int __width = __detail::__column_width(__cluster.__code_point_); @@ -857,8 +866,8 @@ /// \param __rounding Selects the rounding method. /// \c __down result.__width_ <= __maximum /// \c __up result.__width_ <= __maximum + 1 -template -_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> __estimate_column_width( +template ::const_iterator> +_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_Iterator> __estimate_column_width( basic_string_view<_CharT> __str, size_t __maximum, __column_width_rounding __rounding) noexcept { // The width estimation is done in two steps: // - Quickly process for the ASCII part. ASCII has the following properties @@ -877,7 +886,7 @@ // need to scan one code unit beyond the requested precision. When this code // unit is non-ASCII we omit the current code unit and let the Grapheme // clustering algorithm do its work. - const _CharT* __it = __str.begin(); + auto __it = __str.begin(); if (__is_ascii(*__it)) { do { --__maximum; diff --git a/libcxx/include/__format/unicode.h b/libcxx/include/__format/unicode.h --- a/libcxx/include/__format/unicode.h +++ b/libcxx/include/__format/unicode.h @@ -61,7 +61,9 @@ inline constexpr char32_t __replacement_character = U'\ufffd'; -_LIBCPP_HIDE_FROM_ABI constexpr bool __is_continuation(const char* __char, int __count) { +template + requires same_as, char> +_LIBCPP_HIDE_FROM_ABI constexpr bool __is_continuation(_Iterator __char, int __count) { do { if ((*__char & 0b1000'0000) != 0b1000'0000) return false; @@ -81,12 +83,14 @@ /// UTF-8 specialization. template <> class __code_point_view { + using _Iterator = basic_string_view::const_iterator; + public: - _LIBCPP_HIDE_FROM_ABI constexpr explicit __code_point_view(const char* __first, const char* __last) + _LIBCPP_HIDE_FROM_ABI constexpr explicit __code_point_view(_Iterator __first, _Iterator __last) : __first_(__first), __last_(__last) {} _LIBCPP_HIDE_FROM_ABI constexpr bool __at_end() const noexcept { return __first_ == __last_; } - _LIBCPP_HIDE_FROM_ABI constexpr const char* __position() const noexcept { return __first_; } + _LIBCPP_HIDE_FROM_ABI constexpr _Iterator __position() const noexcept { return __first_; } _LIBCPP_HIDE_FROM_ABI constexpr char32_t __consume() noexcept { _LIBCPP_ASSERT(__first_ != __last_, "can't move beyond the end of input"); @@ -206,8 +210,8 @@ # endif // _LIBCPP_STD_VER > 20 private: - const char* __first_; - const char* __last_; + _Iterator __first_; + _Iterator __last_; }; # ifndef TEST_HAS_NO_WIDE_CHARACTERS @@ -224,13 +228,15 @@ /// - 4 UTF-32 (for example Linux) template <> class __code_point_view { + using _Iterator = typename basic_string_view::const_iterator; + public: static_assert(sizeof(wchar_t) == 2 || sizeof(wchar_t) == 4, "sizeof(wchar_t) has a not implemented value"); - _LIBCPP_HIDE_FROM_ABI constexpr explicit __code_point_view(const wchar_t* __first, const wchar_t* __last) + _LIBCPP_HIDE_FROM_ABI constexpr explicit __code_point_view(_Iterator __first, _Iterator __last) : __first_(__first), __last_(__last) {} - _LIBCPP_HIDE_FROM_ABI constexpr const wchar_t* __position() const noexcept { return __first_; } + _LIBCPP_HIDE_FROM_ABI constexpr _Iterator __position() const noexcept { return __first_; } _LIBCPP_HIDE_FROM_ABI constexpr bool __at_end() const noexcept { return __first_ == __last_; } _LIBCPP_HIDE_FROM_ABI constexpr char32_t __consume() noexcept { @@ -291,8 +297,8 @@ # endif // _LIBCPP_STD_VER > 20 private: - const wchar_t* __first_; - const wchar_t* __last_; + _Iterator __first_; + _Iterator __last_; }; # endif @@ -383,8 +389,10 @@ /// Therefore only this code point is extracted. template class __extended_grapheme_cluster_view { + using _Iterator = typename basic_string_view<_CharT>::const_iterator; + public: - _LIBCPP_HIDE_FROM_ABI constexpr explicit __extended_grapheme_cluster_view(const _CharT* __first, const _CharT* __last) + _LIBCPP_HIDE_FROM_ABI constexpr explicit __extended_grapheme_cluster_view(_Iterator __first, _Iterator __last) : __code_point_view_(__first, __last), __next_code_point_(__code_point_view_.__consume()), __next_prop_(__extended_grapheme_custer_property_boundary::__get_property(__next_code_point_)) {} @@ -400,7 +408,7 @@ /// /// It's expected the caller has the start position and thus can determine /// the code unit range of the extended grapheme cluster. - const _CharT* __last_; + _Iterator __last_; }; _LIBCPP_HIDE_FROM_ABI constexpr __cluster __consume() { @@ -421,11 +429,11 @@ char32_t __next_code_point_; __extended_grapheme_custer_property_boundary::__property __next_prop_; - _LIBCPP_HIDE_FROM_ABI constexpr const _CharT* __get_break() { + _LIBCPP_HIDE_FROM_ABI constexpr _Iterator __get_break() { bool __ri_break_allowed = true; bool __has_extened_pictographic = false; while (true) { - const _CharT* __result = __code_point_view_.__position(); + _Iterator __result = __code_point_view_.__position(); __extended_grapheme_custer_property_boundary::__property __prev = __next_prop_; if (__code_point_view_.__at_end()) { __next_prop_ = __extended_grapheme_custer_property_boundary::__property::__eot; @@ -443,8 +451,8 @@ } }; -template -__extended_grapheme_cluster_view(const _CharT*, const _CharT*) -> __extended_grapheme_cluster_view<_CharT>; +template +__extended_grapheme_cluster_view(_Iterator, _Iterator) -> __extended_grapheme_cluster_view>; # else // _LIBCPP_HAS_NO_UNICODE @@ -452,12 +460,14 @@ // This makes it easier to write code agnostic of the _LIBCPP_HAS_NO_UNICODE define. template class __code_point_view { + using _Iterator = basic_string_view<_CharT>::const_iterator; + public: - _LIBCPP_HIDE_FROM_ABI constexpr explicit __code_point_view(const _CharT* __first, const _CharT* __last) + _LIBCPP_HIDE_FROM_ABI constexpr explicit __code_point_view(_Iterator __first, _Iterator __last) : __first_(__first), __last_(__last) {} _LIBCPP_HIDE_FROM_ABI constexpr bool __at_end() const noexcept { return __first_ == __last_; } - _LIBCPP_HIDE_FROM_ABI constexpr const _CharT* __position() const noexcept { return __first_; } + _LIBCPP_HIDE_FROM_ABI constexpr _Iterator __position() const noexcept { return __first_; } _LIBCPP_HIDE_FROM_ABI constexpr char32_t __consume() noexcept { _LIBCPP_ASSERT(__first_ != __last_, "can't move beyond the end of input"); @@ -473,8 +483,8 @@ # endif // _LIBCPP_STD_VER > 20 private: - const _CharT* __first_; - const _CharT* __last_; + _Iterator __first_; + _Iterator __last_; }; # endif // _LIBCPP_HAS_NO_UNICODE