[libcxx-commits] [libcxx] 207e7e4 - [libc++[format][NFC] Removes dead code.
Mark de Wever via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Jul 6 23:00:48 PDT 2022
Author: Mark de Wever
Date: 2022-07-07T08:00:43+02:00
New Revision: 207e7e4a70f49b4dda8edeb37f87157def0a51ab
URL: https://github.com/llvm/llvm-project/commit/207e7e4a70f49b4dda8edeb37f87157def0a51ab
DIFF: https://github.com/llvm/llvm-project/commit/207e7e4a70f49b4dda8edeb37f87157def0a51ab.diff
LOG: [libc++[format][NFC] Removes dead code.
This removes a part of the now obsolete formater code.
The removal also removes the _v2 suffix where it's no longer needed.
Depends on D128785
Reviewed By: #libc, ldionne
Differential Revision: https://reviews.llvm.org/D128846
Added:
Modified:
libcxx/include/__format/formatter.h
libcxx/include/__format/formatter_floating_point.h
libcxx/include/__format/formatter_output.h
libcxx/include/__format/parser_std_format_spec.h
Removed:
################################################################################
diff --git a/libcxx/include/__format/formatter.h b/libcxx/include/__format/formatter.h
index c39e25b354eb..4816f961c445 100644
--- a/libcxx/include/__format/formatter.h
+++ b/libcxx/include/__format/formatter.h
@@ -10,20 +10,10 @@
#ifndef _LIBCPP___FORMAT_FORMATTER_H
#define _LIBCPP___FORMAT_FORMATTER_H
-#include <__algorithm/copy.h>
-#include <__algorithm/fill_n.h>
-#include <__algorithm/transform.h>
-#include <__assert>
#include <__availability>
#include <__concepts/same_as.h>
#include <__config>
-#include <__format/format_error.h>
#include <__format/format_fwd.h>
-#include <__format/format_string.h>
-#include <__format/parser_std_format_spec.h>
-#include <__utility/move.h>
-#include <__utility/unreachable.h>
-#include <string_view>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -49,229 +39,12 @@ struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter {
formatter& operator=(const formatter&) = delete;
};
-namespace __format_spec {
-
-_LIBCPP_HIDE_FROM_ABI inline char* __insert_sign(char* __buf, bool __negative,
- _Flags::_Sign __sign) {
- if (__negative)
- *__buf++ = '-';
- else
- switch (__sign) {
- case _Flags::_Sign::__default:
- case _Flags::_Sign::__minus:
- // No sign added.
- break;
- case _Flags::_Sign::__plus:
- *__buf++ = '+';
- break;
- case _Flags::_Sign::__space:
- *__buf++ = ' ';
- break;
- }
-
- return __buf;
-}
-
-_LIBCPP_HIDE_FROM_ABI constexpr char __hex_to_upper(char c) {
- switch (c) {
- case 'a':
- return 'A';
- case 'b':
- return 'B';
- case 'c':
- return 'C';
- case 'd':
- return 'D';
- case 'e':
- return 'E';
- case 'f':
- return 'F';
- }
- return c;
-}
-
-} // namespace __format_spec
-
namespace __formatter {
/** The character types that formatters are specialized for. */
template <class _CharT>
concept __char_type = same_as<_CharT, char> || same_as<_CharT, wchar_t>;
-struct _LIBCPP_TEMPLATE_VIS __padding_size_result {
- size_t __before;
- size_t __after;
-};
-
-_LIBCPP_HIDE_FROM_ABI constexpr __padding_size_result
-__padding_size(size_t __size, size_t __width,
- __format_spec::_Flags::_Alignment __align) {
- _LIBCPP_ASSERT(__width > __size,
- "Don't call this function when no padding is required");
- _LIBCPP_ASSERT(
- __align != __format_spec::_Flags::_Alignment::__default,
- "Caller should adjust the default to the value required by the type");
-
- size_t __fill = __width - __size;
- switch (__align) {
- case __format_spec::_Flags::_Alignment::__default:
- __libcpp_unreachable();
-
- case __format_spec::_Flags::_Alignment::__left:
- return {0, __fill};
-
- case __format_spec::_Flags::_Alignment::__center: {
- // The extra padding is divided per [format.string.std]/3
- // __before = floor(__fill, 2);
- // __after = ceil(__fill, 2);
- size_t __before = __fill / 2;
- size_t __after = __fill - __before;
- return {__before, __after};
- }
- case __format_spec::_Flags::_Alignment::__right:
- return {__fill, 0};
- }
- __libcpp_unreachable();
-}
-
-/**
- * Writes the input to the output with the required padding.
- *
- * Since the output column width is specified the function can be used for
- * ASCII and Unicode input.
- *
- * @pre [@a __first, @a __last) is a valid range.
- * @pre @a __size <= @a __width. Using this function when this pre-condition
- * doesn't hold incurs an unwanted overhead.
- *
- * @param __out_it The output iterator to write to.
- * @param __first Pointer to the first element to write.
- * @param __last Pointer beyond the last element to write.
- * @param __size The (estimated) output column width. When the elements
- * to be written are ASCII the following condition holds
- * @a __size == @a __last - @a __first.
- * @param __width The number of output columns to write.
- * @param __fill The character used for the alignment of the output.
- * TODO FMT Will probably change to support Unicode grapheme
- * cluster.
- * @param __alignment The requested alignment.
- *
- * @returns An iterator pointing beyond the last element written.
- *
- * @note The type of the elements in range [@a __first, @a __last) can
diff er
- * from the type of @a __fill. Integer output uses @c std::to_chars for its
- * conversion, which means the [@a __first, @a __last) always contains elements
- * of the type @c char.
- */
-template <class _CharT, class _Fill>
-_LIBCPP_HIDE_FROM_ABI auto
-__write(output_iterator<const _CharT&> auto __out_it, const _CharT* __first,
- const _CharT* __last, size_t __size, size_t __width, _Fill __fill,
- __format_spec::_Flags::_Alignment __alignment) -> decltype(__out_it) {
-
- _LIBCPP_ASSERT(__first <= __last, "Not a valid range");
- _LIBCPP_ASSERT(__size < __width, "Precondition failure");
-
- __padding_size_result __padding =
- __padding_size(__size, __width, __alignment);
- __out_it = _VSTD::fill_n(_VSTD::move(__out_it), __padding.__before, __fill);
- __out_it = _VSTD::copy(__first, __last, _VSTD::move(__out_it));
- return _VSTD::fill_n(_VSTD::move(__out_it), __padding.__after, __fill);
-}
-
-/**
- * @overload
- *
- * Writes additional zero's for the precision before the exponent.
- * This is used when the precision requested in the format string is larger
- * than the maximum precision of the floating-point type. These precision
- * digits are always 0.
- *
- * @param __exponent The location of the exponent character.
- * @param __num_trailing_zeros The number of 0's to write before the exponent
- * character.
- */
-template <class _CharT, class _Fill>
-_LIBCPP_HIDE_FROM_ABI auto __write(output_iterator<const _CharT&> auto __out_it, const _CharT* __first,
- const _CharT* __last, size_t __size, size_t __width, _Fill __fill,
- __format_spec::_Flags::_Alignment __alignment, const _CharT* __exponent,
- size_t __num_trailing_zeros) -> decltype(__out_it) {
- _LIBCPP_ASSERT(__first <= __last, "Not a valid range");
- _LIBCPP_ASSERT(__num_trailing_zeros > 0, "The overload not writing trailing zeros should have been used");
-
- __padding_size_result __padding = __padding_size(__size + __num_trailing_zeros, __width, __alignment);
- __out_it = _VSTD::fill_n(_VSTD::move(__out_it), __padding.__before, __fill);
- __out_it = _VSTD::copy(__first, __exponent, _VSTD::move(__out_it));
- __out_it = _VSTD::fill_n(_VSTD::move(__out_it), __num_trailing_zeros, _CharT('0'));
- __out_it = _VSTD::copy(__exponent, __last, _VSTD::move(__out_it));
- return _VSTD::fill_n(_VSTD::move(__out_it), __padding.__after, __fill);
-}
-
-/**
- * @overload
- *
- * Uses a transformation operation before writing an element.
- *
- * TODO FMT Fill will probably change to support Unicode grapheme cluster.
- */
-template <class _CharT, class _UnaryOperation, class _Fill>
-_LIBCPP_HIDE_FROM_ABI auto
-__write(output_iterator<const _CharT&> auto __out_it, const _CharT* __first,
- const _CharT* __last, size_t __size, _UnaryOperation __op,
- size_t __width, _Fill __fill,
- __format_spec::_Flags::_Alignment __alignment) -> decltype(__out_it) {
-
- _LIBCPP_ASSERT(__first <= __last, "Not a valid range");
- _LIBCPP_ASSERT(__size < __width, "Precondition failure");
-
- __padding_size_result __padding =
- __padding_size(__size, __width, __alignment);
- __out_it = _VSTD::fill_n(_VSTD::move(__out_it), __padding.__before, __fill);
- __out_it = _VSTD::transform(__first, __last, _VSTD::move(__out_it), __op);
- return _VSTD::fill_n(_VSTD::move(__out_it), __padding.__after, __fill);
-}
-
-/**
- * Writes Unicode input to the output with the required padding.
- *
- * This function does almost the same as the @ref __write function, but handles
- * the width estimation of the Unicode input.
- *
- * @param __str The range [@a __first, @a __last).
- * @param __precision The width to truncate the input string to, use @c -1 for
- * no limit.
- */
-template <class _CharT, class _Fill>
-_LIBCPP_HIDE_FROM_ABI auto
-__write_unicode(output_iterator<const _CharT&> auto __out_it,
- basic_string_view<_CharT> __str, ptr
diff _t __width,
- ptr
diff _t __precision, _Fill __fill,
- __format_spec::_Flags::_Alignment __alignment)
- -> decltype(__out_it) {
-
- // This value changes when there Unicode column width limits the output
- // size.
- auto __last = __str.end();
- if (__width != 0 || __precision != -1) {
- __format_spec::__string_alignment<_CharT> __format_traits =
- __format_spec::__get_string_alignment(__str.begin(), __str.end(),
- __width, __precision);
-
- if (__format_traits.__align)
- return __write(_VSTD::move(__out_it), __str.begin(),
- __format_traits.__last, __format_traits.__size, __width,
- __fill, __alignment);
-
- // No alignment required update the output based on the precision.
- // This might be the same as __str.end().
- __last = __format_traits.__last;
- }
-
- // Copy the input to the output. The output size might be limited by the
- // precision.
- return _VSTD::copy(__str.begin(), __last, _VSTD::move(__out_it));
-}
-
} // namespace __formatter
#endif //_LIBCPP_STD_VER > 17
diff --git a/libcxx/include/__format/formatter_floating_point.h b/libcxx/include/__format/formatter_floating_point.h
index 9d8de95a7005..90a76193196e 100644
--- a/libcxx/include/__format/formatter_floating_point.h
+++ b/libcxx/include/__format/formatter_floating_point.h
@@ -514,7 +514,7 @@ _LIBCPP_HIDE_FROM_ABI _OutIt __format_locale_specific_form(
__grouping.size() - // Grouping contains one
!__grouping.empty(); // additional character
- __formatter::__padding_size_result_v2 __padding = {0, 0};
+ __formatter::__padding_size_result __padding = {0, 0};
bool __zero_padding = __specs.__alignment_ == __format_spec::__alignment::__zero_padding;
if (__size < __specs.__width_) {
if (__zero_padding) {
@@ -522,7 +522,7 @@ _LIBCPP_HIDE_FROM_ABI _OutIt __format_locale_specific_form(
__specs.__fill_ = _CharT('0');
}
- __padding = __formatter::__padding_size_v2(__size, __specs.__width_, __specs.__alignment_);
+ __padding = __formatter::__padding_size(__size, __specs.__width_, __specs.__alignment_);
}
// sign and (zero padding or alignment)
diff --git a/libcxx/include/__format/formatter_output.h b/libcxx/include/__format/formatter_output.h
index f9f18a01c5bb..fc2cc2fb28a0 100644
--- a/libcxx/include/__format/formatter_output.h
+++ b/libcxx/include/__format/formatter_output.h
@@ -51,15 +51,13 @@ _LIBCPP_HIDE_FROM_ABI constexpr char __hex_to_upper(char c) {
return c;
}
-// TODO FMT remove _v2 suffix.
-struct _LIBCPP_TYPE_VIS __padding_size_result_v2 {
+struct _LIBCPP_TYPE_VIS __padding_size_result {
size_t __before_;
size_t __after_;
};
-// TODO FMT remove _v2 suffix.
-_LIBCPP_HIDE_FROM_ABI constexpr __padding_size_result_v2 __padding_size_v2(size_t __size, size_t __width,
- __format_spec::__alignment __align) {
+_LIBCPP_HIDE_FROM_ABI constexpr __padding_size_result
+__padding_size(size_t __size, size_t __width, __format_spec::__alignment __align) {
_LIBCPP_ASSERT(__width > __size, "don't call this function when no padding is required");
_LIBCPP_ASSERT(__align != __format_spec::__alignment::__default,
"the caller should adjust the default to the value required by the type");
@@ -100,7 +98,7 @@ _LIBCPP_HIDE_FROM_ABI _OutIt __write_using_decimal_separators(_OutIt __out_it, c
(__last - __first) + // data
(__grouping.size() - 1); // number of separator characters
- __padding_size_result_v2 __padding = {0, 0};
+ __padding_size_result __padding = {0, 0};
if (__specs.__alignment_ == __format_spec::__alignment::__zero_padding) {
// Write [sign][prefix].
__out_it = _VSTD::copy(__begin, __first, _VSTD::move(__out_it));
@@ -113,7 +111,7 @@ _LIBCPP_HIDE_FROM_ABI _OutIt __write_using_decimal_separators(_OutIt __out_it, c
} else {
if (__specs.__width_ > __size) {
// Determine padding and write padding.
- __padding = __padding_size_v2(__size, __specs.__width_, __specs.__alignment_);
+ __padding = __padding_size(__size, __specs.__width_, __specs.__alignment_);
__out_it = _VSTD::fill_n(_VSTD::move(__out_it), __padding.__before_, __specs.__fill_);
}
@@ -189,8 +187,7 @@ _LIBCPP_HIDE_FROM_ABI auto __write(const _CharT* __first, const _CharT* __last,
if (__size >= __specs.__width_)
return _VSTD::copy(__first, __last, _VSTD::move(__out_it));
- __padding_size_result_v2 __padding =
- __formatter::__padding_size_v2(__size, __specs.__width_, __specs.__std_.__alignment_);
+ __padding_size_result __padding = __formatter::__padding_size(__size, __specs.__width_, __specs.__std_.__alignment_);
__out_it = _VSTD::fill_n(_VSTD::move(__out_it), __padding.__before_, __specs.__fill_);
__out_it = _VSTD::copy(__first, __last, _VSTD::move(__out_it));
return _VSTD::fill_n(_VSTD::move(__out_it), __padding.__after_, __specs.__fill_);
@@ -216,7 +213,7 @@ _LIBCPP_HIDE_FROM_ABI auto __write_transformed(const _CharT* __first, const _Cha
if (__size >= __specs.__width_)
return _VSTD::transform(__first, __last, _VSTD::move(__out_it), __op);
- __padding_size_result_v2 __padding = __padding_size_v2(__size, __specs.__width_, __specs.__alignment_);
+ __padding_size_result __padding = __padding_size(__size, __specs.__width_, __specs.__alignment_);
__out_it = _VSTD::fill_n(_VSTD::move(__out_it), __padding.__before_, __specs.__fill_);
__out_it = _VSTD::transform(__first, __last, _VSTD::move(__out_it), __op);
return _VSTD::fill_n(_VSTD::move(__out_it), __padding.__after_, __specs.__fill_);
@@ -242,8 +239,8 @@ _LIBCPP_HIDE_FROM_ABI auto __write_using_trailing_zeros(
_LIBCPP_ASSERT(__first <= __last, "Not a valid range");
_LIBCPP_ASSERT(__num_trailing_zeros > 0, "The overload not writing trailing zeros should have been used");
- __padding_size_result_v2 __padding =
- __padding_size_v2(__size + __num_trailing_zeros, __specs.__width_, __specs.__alignment_);
+ __padding_size_result __padding =
+ __padding_size(__size + __num_trailing_zeros, __specs.__width_, __specs.__alignment_);
__out_it = _VSTD::fill_n(_VSTD::move(__out_it), __padding.__before_, __specs.__fill_);
__out_it = _VSTD::copy(__first, __exponent, _VSTD::move(__out_it));
__out_it = _VSTD::fill_n(_VSTD::move(__out_it), __num_trailing_zeros, _CharT('0'));
diff --git a/libcxx/include/__format/parser_std_format_spec.h b/libcxx/include/__format/parser_std_format_spec.h
index de513b051a04..630f6fde24a8 100644
--- a/libcxx/include/__format/parser_std_format_spec.h
+++ b/libcxx/include/__format/parser_std_format_spec.h
@@ -44,168 +44,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD
namespace __format_spec {
-/**
- * Contains the flags for the std-format-spec.
- *
- * Some format-options can only be used for specific C++ types and may depend on
- * the selected format-type.
- * * The C++type filtering can be done using the proper policies for
- * @ref __parser_std.
- * * The format-type filtering needs to be done post parsing in the parser
- * derived from @ref __parser_std.
- */
-_LIBCPP_PACKED_BYTE_FOR_AIX
-class _LIBCPP_TYPE_VIS _Flags {
-public:
- enum class _LIBCPP_ENUM_VIS _Alignment : uint8_t {
- /**
- * No alignment is set in the format string.
- *
- * Zero-padding is ignored when an alignment is selected.
- * The default alignment depends on the selected format-type.
- */
- __default,
- __left,
- __center,
- __right
- };
- enum class _LIBCPP_ENUM_VIS _Sign : uint8_t {
- /**
- * No sign is set in the format string.
- *
- * The sign isn't allowed for certain format-types. By using this value
- * it's possible to detect whether or not the user explicitly set the sign
- * flag. For formatting purposes it behaves the same as @ref __minus.
- */
- __default,
- __minus,
- __plus,
- __space
- };
-
- _Alignment __alignment : 2 {_Alignment::__default};
- _Sign __sign : 2 {_Sign::__default};
- uint8_t __alternate_form : 1 {false};
- uint8_t __zero_padding : 1 {false};
- uint8_t __locale_specific_form : 1 {false};
-
- enum class _LIBCPP_ENUM_VIS _Type : uint8_t {
- __default,
- __string,
- __binary_lower_case,
- __binary_upper_case,
- __octal,
- __decimal,
- __hexadecimal_lower_case,
- __hexadecimal_upper_case,
- __pointer,
- __char,
- __float_hexadecimal_lower_case,
- __float_hexadecimal_upper_case,
- __scientific_lower_case,
- __scientific_upper_case,
- __fixed_lower_case,
- __fixed_upper_case,
- __general_lower_case,
- __general_upper_case
- };
-
- _Type __type{_Type::__default};
-};
-_LIBCPP_PACKED_BYTE_FOR_AIX_END
-
-namespace __detail {
-template <class _CharT>
-_LIBCPP_HIDE_FROM_ABI constexpr bool
-__parse_alignment(_CharT __c, _Flags& __flags) noexcept {
- switch (__c) {
- case _CharT('<'):
- __flags.__alignment = _Flags::_Alignment::__left;
- return true;
-
- case _CharT('^'):
- __flags.__alignment = _Flags::_Alignment::__center;
- return true;
-
- case _CharT('>'):
- __flags.__alignment = _Flags::_Alignment::__right;
- return true;
- }
- return false;
-}
-} // namespace __detail
-
-template <class _CharT>
-class _LIBCPP_TEMPLATE_VIS __parser_fill_align {
-public:
- // TODO FMT The standard doesn't specify this character is a Unicode
- // character. Validate what fmt and MSVC have implemented.
- _CharT __fill{_CharT(' ')};
-
-protected:
- _LIBCPP_HIDE_FROM_ABI constexpr const _CharT*
- __parse(const _CharT* __begin, const _CharT* __end, _Flags& __flags) {
- _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) {
- if (__detail::__parse_alignment(*(__begin + 1), __flags)) {
- if (*__begin == _CharT('{') || *__begin == _CharT('}'))
- __throw_format_error(
- "The format-spec fill field contains an invalid character");
- __fill = *__begin;
- return __begin + 2;
- }
- }
-
- if (__detail::__parse_alignment(*__begin, __flags))
- return __begin + 1;
-
- return __begin;
- }
-};
-
-template <class _CharT>
-_LIBCPP_HIDE_FROM_ABI constexpr const _CharT*
-__parse_sign(const _CharT* __begin, _Flags& __flags) noexcept {
- switch (*__begin) {
- case _CharT('-'):
- __flags.__sign = _Flags::_Sign::__minus;
- break;
- case _CharT('+'):
- __flags.__sign = _Flags::_Sign::__plus;
- break;
- case _CharT(' '):
- __flags.__sign = _Flags::_Sign::__space;
- break;
- default:
- return __begin;
- }
- return __begin + 1;
-}
-
-template <class _CharT>
-_LIBCPP_HIDE_FROM_ABI constexpr const _CharT*
-__parse_alternate_form(const _CharT* __begin, _Flags& __flags) noexcept {
- if (*__begin == _CharT('#')) {
- __flags.__alternate_form = true;
- ++__begin;
- }
-
- return __begin;
-}
-
-template <class _CharT>
-_LIBCPP_HIDE_FROM_ABI constexpr const _CharT*
-__parse_zero_padding(const _CharT* __begin, _Flags& __flags) noexcept {
- if (*__begin == _CharT('0')) {
- __flags.__zero_padding = true;
- ++__begin;
- }
-
- return __begin;
-}
-
template <class _CharT>
_LIBCPP_HIDE_FROM_ABI constexpr __format::__parse_number_result< _CharT>
__parse_arg_id(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) {
@@ -253,682 +91,6 @@ __substitute_arg_id(basic_format_arg<_Context> _Arg) {
_Arg);
}
-class _LIBCPP_TYPE_VIS __parser_width {
-public:
- /** Contains a width or an arg-id. */
- uint32_t __width : 31 {0};
- /** Determines whether the value stored is a width or an arg-id. */
- uint32_t __width_as_arg : 1 {0};
-
- /**
- * Does the supplied width field contain an arg-id?
- *
- * If @c true the formatter needs to call @ref __substitute_width_arg_id.
- */
- constexpr bool __width_needs_substitution() const noexcept { return __width_as_arg; }
-
-protected:
- /**
- * Does the supplied std-format-spec contain a width field?
- *
- * When the field isn't present there's no padding required. This can be used
- * to optimize the formatting.
- */
- constexpr bool __has_width_field() const noexcept { return __width_as_arg || __width; }
-
- template <class _CharT>
- _LIBCPP_HIDE_FROM_ABI constexpr const _CharT*
- __parse(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) {
- if (*__begin == _CharT('0'))
- __throw_format_error(
- "A format-spec width field shouldn't have a leading zero");
-
- if (*__begin == _CharT('{')) {
- __format::__parse_number_result __r =
- __parse_arg_id(++__begin, __end, __parse_ctx);
- __width = __r.__value;
- __width_as_arg = 1;
- return __r.__ptr;
- }
-
- if (*__begin < _CharT('0') || *__begin > _CharT('9'))
- return __begin;
-
- __format::__parse_number_result __r =
- __format::__parse_number(__begin, __end);
- __width = __r.__value;
- _LIBCPP_ASSERT(__width != 0,
- "A zero value isn't allowed and should be impossible, "
- "due to validations in this function");
- return __r.__ptr;
- }
-
- _LIBCPP_HIDE_FROM_ABI constexpr void __substitute_width_arg_id(auto __arg) {
- _LIBCPP_ASSERT(__width_as_arg == 1,
- "Substitute width called when no substitution is required");
-
- // The clearing of the flag isn't required but looks better when debugging
- // the code.
- __width_as_arg = 0;
- __width = __substitute_arg_id(__arg);
- if (__width == 0)
- __throw_format_error(
- "A format-spec width field replacement should have a positive value");
- }
-};
-
-class _LIBCPP_TYPE_VIS __parser_precision {
-public:
- /** Contains a precision or an arg-id. */
- uint32_t __precision : 31 {__format::__number_max};
- /**
- * Determines whether the value stored is a precision or an arg-id.
- *
- * @note Since @ref __precision == @ref __format::__number_max is a valid
- * value, the default value contains an arg-id of INT32_MAX. (This number of
- * arguments isn't supported by compilers.) This is used to detect whether
- * the std-format-spec contains a precision field.
- */
- uint32_t __precision_as_arg : 1 {1};
-
- /**
- * Does the supplied precision field contain an arg-id?
- *
- * If @c true the formatter needs to call @ref __substitute_precision_arg_id.
- */
- constexpr bool __precision_needs_substitution() const noexcept {
- return __precision_as_arg && __precision != __format::__number_max;
- }
-
-protected:
- /**
- * Does the supplied std-format-spec contain a precision field?
- *
- * When the field isn't present there's no truncating required. This can be
- * used to optimize the formatting.
- */
- constexpr bool __has_precision_field() const noexcept {
-
- return __precision_as_arg == 0 || // Contains a value?
- __precision != __format::__number_max; // The arg-id is valid?
- }
-
- template <class _CharT>
- _LIBCPP_HIDE_FROM_ABI constexpr const _CharT*
- __parse(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) {
- if (*__begin != _CharT('.'))
- return __begin;
-
- ++__begin;
- if (__begin == __end)
- __throw_format_error("End of input while parsing format-spec precision");
-
- if (*__begin == _CharT('{')) {
- __format::__parse_number_result __arg_id =
- __parse_arg_id(++__begin, __end, __parse_ctx);
- _LIBCPP_ASSERT(__arg_id.__value != __format::__number_max,
- "Unsupported number of arguments, since this number of "
- "arguments is used a special value");
- __precision = __arg_id.__value;
- return __arg_id.__ptr;
- }
-
- if (*__begin < _CharT('0') || *__begin > _CharT('9'))
- __throw_format_error(
- "The format-spec precision field doesn't contain a value or arg-id");
-
- __format::__parse_number_result __r =
- __format::__parse_number(__begin, __end);
- __precision = __r.__value;
- __precision_as_arg = 0;
- return __r.__ptr;
- }
-
- _LIBCPP_HIDE_FROM_ABI constexpr void __substitute_precision_arg_id(
- auto __arg) {
- _LIBCPP_ASSERT(
- __precision_as_arg == 1 && __precision != __format::__number_max,
- "Substitute precision called when no substitution is required");
-
- // The clearing of the flag isn't required but looks better when debugging
- // the code.
- __precision_as_arg = 0;
- __precision = __substitute_arg_id(__arg);
- }
-};
-
-template <class _CharT>
-_LIBCPP_HIDE_FROM_ABI constexpr const _CharT*
-__parse_locale_specific_form(const _CharT* __begin, _Flags& __flags) noexcept {
- if (*__begin == _CharT('L')) {
- __flags.__locale_specific_form = true;
- ++__begin;
- }
-
- return __begin;
-}
-
-template <class _CharT>
-_LIBCPP_HIDE_FROM_ABI constexpr const _CharT*
-__parse_type(const _CharT* __begin, _Flags& __flags) {
-
- // 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
- // been parsed. So its easier to implement the validation for all types in
- // the specific parse function.
- switch (*__begin) {
- case 'A':
- __flags.__type = _Flags::_Type::__float_hexadecimal_upper_case;
- break;
- case 'B':
- __flags.__type = _Flags::_Type::__binary_upper_case;
- break;
- case 'E':
- __flags.__type = _Flags::_Type::__scientific_upper_case;
- break;
- case 'F':
- __flags.__type = _Flags::_Type::__fixed_upper_case;
- break;
- case 'G':
- __flags.__type = _Flags::_Type::__general_upper_case;
- break;
- case 'X':
- __flags.__type = _Flags::_Type::__hexadecimal_upper_case;
- break;
- case 'a':
- __flags.__type = _Flags::_Type::__float_hexadecimal_lower_case;
- break;
- case 'b':
- __flags.__type = _Flags::_Type::__binary_lower_case;
- break;
- case 'c':
- __flags.__type = _Flags::_Type::__char;
- break;
- case 'd':
- __flags.__type = _Flags::_Type::__decimal;
- break;
- case 'e':
- __flags.__type = _Flags::_Type::__scientific_lower_case;
- break;
- case 'f':
- __flags.__type = _Flags::_Type::__fixed_lower_case;
- break;
- case 'g':
- __flags.__type = _Flags::_Type::__general_lower_case;
- break;
- case 'o':
- __flags.__type = _Flags::_Type::__octal;
- break;
- case 'p':
- __flags.__type = _Flags::_Type::__pointer;
- break;
- case 's':
- __flags.__type = _Flags::_Type::__string;
- break;
- case 'x':
- __flags.__type = _Flags::_Type::__hexadecimal_lower_case;
- break;
- default:
- return __begin;
- }
- return ++__begin;
-}
-
-/**
- * Process the parsed alignment and zero-padding state of arithmetic types.
- *
- * [format.string.std]/13
- * If the 0 character and an align option both appear, the 0 character is
- * ignored.
- *
- * For the formatter a @ref __default alignment means zero-padding.
- */
-_LIBCPP_HIDE_FROM_ABI constexpr void __process_arithmetic_alignment(_Flags& __flags) {
- __flags.__zero_padding &= __flags.__alignment == _Flags::_Alignment::__default;
- if (!__flags.__zero_padding && __flags.__alignment == _Flags::_Alignment::__default)
- __flags.__alignment = _Flags::_Alignment::__right;
-}
-
-/**
- * The parser for the std-format-spec.
- *
- * [format.string.std]/1 specifies the std-format-spec:
- * fill-and-align sign # 0 width precision L type
- *
- * All these fields are optional. Whether these fields can be used depend on:
- * - The type supplied to the format string.
- * E.g. A string never uses the sign field so the field may not be set.
- * This constrain is validated by the parsers in this file.
- * - The supplied value for the optional type field.
- * E.g. A int formatted as decimal uses the sign field.
- * When formatted as a char the sign field may no longer be set.
- * This constrain isn't validated by the parsers in this file.
- *
- * The base classes are ordered to minimize the amount of padding.
- *
- * This implements the parser for the string types.
- */
-template <class _CharT>
-class _LIBCPP_TEMPLATE_VIS __parser_string
- : public __parser_width, // provides __width(|as_arg)
- public __parser_precision, // provides __precision(|as_arg)
- public __parser_fill_align<_CharT>, // provides __fill and uses __flags
- public _Flags // provides __flags
-{
-public:
- using char_type = _CharT;
-
- _LIBCPP_HIDE_FROM_ABI constexpr __parser_string() {
- this->__alignment = _Flags::_Alignment::__left;
- }
-
- /**
- * The low-level std-format-spec parse function.
- *
- * @pre __begin points at the beginning of the std-format-spec. This means
- * directly after the ':'.
- * @pre The std-format-spec parses the entire input, or the first unmatched
- * character is a '}'.
- *
- * @returns The iterator pointing at the last parsed character.
- */
- _LIBCPP_HIDE_FROM_ABI constexpr auto parse(auto& __parse_ctx)
- -> decltype(__parse_ctx.begin()) {
- auto __it = __parse(__parse_ctx);
- __process_display_type();
- return __it;
- }
-
-private:
- /**
- * Parses the std-format-spec.
- *
- * @throws __throw_format_error When @a __parse_ctx contains an ill-formed
- * std-format-spec.
- *
- * @returns An iterator to the end of input or point at the closing '}'.
- */
- _LIBCPP_HIDE_FROM_ABI constexpr auto __parse(auto& __parse_ctx)
- -> decltype(__parse_ctx.begin()) {
-
- auto __begin = __parse_ctx.begin();
- auto __end = __parse_ctx.end();
- if (__begin == __end)
- return __begin;
-
- __begin = __parser_fill_align<_CharT>::__parse(__begin, __end,
- static_cast<_Flags&>(*this));
- if (__begin == __end)
- return __begin;
-
- __begin = __parser_width::__parse(__begin, __end, __parse_ctx);
- if (__begin == __end)
- return __begin;
-
- __begin = __parser_precision::__parse(__begin, __end, __parse_ctx);
- if (__begin == __end)
- return __begin;
-
- __begin = __parse_type(__begin, static_cast<_Flags&>(*this));
-
- if (__begin != __end && *__begin != _CharT('}'))
- __throw_format_error(
- "The format-spec should consume the input or end with a '}'");
-
- return __begin;
- }
-
- /** Processes the parsed std-format-spec based on the parsed display type. */
- _LIBCPP_HIDE_FROM_ABI constexpr void __process_display_type() {
- switch (this->__type) {
- case _Flags::_Type::__default:
- case _Flags::_Type::__string:
- break;
-
- default:
- __throw_format_error("The format-spec type has a type not supported for "
- "a string argument");
- }
- }
-};
-
-/**
- * The parser for the std-format-spec.
- *
- * This implements the parser for the integral types. This includes the
- * character type and boolean type.
- *
- * See @ref __parser_string.
- */
-template <class _CharT>
-class _LIBCPP_TEMPLATE_VIS __parser_integral
- : public __parser_width, // provides __width(|as_arg)
- public __parser_fill_align<_CharT>, // provides __fill and uses __flags
- public _Flags // provides __flags
-{
-public:
- using char_type = _CharT;
-
-protected:
- /**
- * The low-level std-format-spec parse function.
- *
- * @pre __begin points at the beginning of the std-format-spec. This means
- * directly after the ':'.
- * @pre The std-format-spec parses the entire input, or the first unmatched
- * character is a '}'.
- *
- * @returns The iterator pointing at the last parsed character.
- */
- _LIBCPP_HIDE_FROM_ABI constexpr auto __parse(auto& __parse_ctx)
- -> decltype(__parse_ctx.begin()) {
- auto __begin = __parse_ctx.begin();
- auto __end = __parse_ctx.end();
- if (__begin == __end)
- return __begin;
-
- __begin = __parser_fill_align<_CharT>::__parse(__begin, __end,
- static_cast<_Flags&>(*this));
- if (__begin == __end)
- return __begin;
-
- __begin = __parse_sign(__begin, static_cast<_Flags&>(*this));
- if (__begin == __end)
- return __begin;
-
- __begin = __parse_alternate_form(__begin, static_cast<_Flags&>(*this));
- if (__begin == __end)
- return __begin;
-
- __begin = __parse_zero_padding(__begin, static_cast<_Flags&>(*this));
- if (__begin == __end)
- return __begin;
-
- __begin = __parser_width::__parse(__begin, __end, __parse_ctx);
- if (__begin == __end)
- return __begin;
-
- __begin =
- __parse_locale_specific_form(__begin, static_cast<_Flags&>(*this));
- if (__begin == __end)
- return __begin;
-
- __begin = __parse_type(__begin, static_cast<_Flags&>(*this));
-
- if (__begin != __end && *__begin != _CharT('}'))
- __throw_format_error(
- "The format-spec should consume the input or end with a '}'");
-
- return __begin;
- }
-
- /** Handles the post-parsing updates for the integer types. */
- _LIBCPP_HIDE_FROM_ABI constexpr void __handle_integer() noexcept {
- __process_arithmetic_alignment(static_cast<_Flags&>(*this));
- }
-
- /**
- * Handles the post-parsing updates for the character types.
- *
- * Sets the alignment and validates the format flags set for a character type.
- *
- * At the moment the validation for a character and a Boolean behave the
- * same, but this may change in the future.
- * Specifically at the moment the locale-specific form is allowed for the
- * char output type, but it has no effect on the output.
- */
- _LIBCPP_HIDE_FROM_ABI constexpr void __handle_char() { __handle_bool(); }
-
- /**
- * Handles the post-parsing updates for the Boolean types.
- *
- * Sets the alignment and validates the format flags set for a Boolean type.
- */
- _LIBCPP_HIDE_FROM_ABI constexpr void __handle_bool() {
- if (this->__sign != _Flags::_Sign::__default)
- __throw_format_error("A sign field isn't allowed in this format-spec");
-
- if (this->__alternate_form)
- __throw_format_error(
- "An alternate form field isn't allowed in this format-spec");
-
- if (this->__zero_padding)
- __throw_format_error(
- "A zero-padding field isn't allowed in this format-spec");
-
- if (this->__alignment == _Flags::_Alignment::__default)
- this->__alignment = _Flags::_Alignment::__left;
- }
-};
-
-/**
- * The parser for the std-format-spec.
- *
- * This implements the parser for the floating-point types.
- *
- * See @ref __parser_string.
- */
-template <class _CharT>
-class _LIBCPP_TEMPLATE_VIS __parser_floating_point
- : public __parser_width, // provides __width(|as_arg)
- public __parser_precision, // provides __precision(|as_arg)
- public __parser_fill_align<_CharT>, // provides __fill and uses __flags
- public _Flags // provides __flags
-{
-public:
- using char_type = _CharT;
-
- /**
- * The low-level std-format-spec parse function.
- *
- * @pre __begin points at the beginning of the std-format-spec. This means
- * directly after the ':'.
- * @pre The std-format-spec parses the entire input, or the first unmatched
- * character is a '}'.
- *
- * @returns The iterator pointing at the last parsed character.
- */
- _LIBCPP_HIDE_FROM_ABI constexpr auto parse(auto& __parse_ctx)
- -> decltype(__parse_ctx.begin()) {
- auto __it = __parse(__parse_ctx);
- __process_arithmetic_alignment(static_cast<_Flags&>(*this));
- __process_display_type();
- return __it;
- }
-protected:
- /**
- * The low-level std-format-spec parse function.
- *
- * @pre __begin points at the beginning of the std-format-spec. This means
- * directly after the ':'.
- * @pre The std-format-spec parses the entire input, or the first unmatched
- * character is a '}'.
- *
- * @returns The iterator pointing at the last parsed character.
- */
- _LIBCPP_HIDE_FROM_ABI constexpr auto __parse(auto& __parse_ctx)
- -> decltype(__parse_ctx.begin()) {
- auto __begin = __parse_ctx.begin();
- auto __end = __parse_ctx.end();
- if (__begin == __end)
- return __begin;
-
- __begin = __parser_fill_align<_CharT>::__parse(__begin, __end,
- static_cast<_Flags&>(*this));
- if (__begin == __end)
- return __begin;
-
- __begin = __parse_sign(__begin, static_cast<_Flags&>(*this));
- if (__begin == __end)
- return __begin;
-
- __begin = __parse_alternate_form(__begin, static_cast<_Flags&>(*this));
- if (__begin == __end)
- return __begin;
-
- __begin = __parse_zero_padding(__begin, static_cast<_Flags&>(*this));
- if (__begin == __end)
- return __begin;
-
- __begin = __parser_width::__parse(__begin, __end, __parse_ctx);
- if (__begin == __end)
- return __begin;
-
- __begin = __parser_precision::__parse(__begin, __end, __parse_ctx);
- if (__begin == __end)
- return __begin;
-
- __begin =
- __parse_locale_specific_form(__begin, static_cast<_Flags&>(*this));
- if (__begin == __end)
- return __begin;
-
- __begin = __parse_type(__begin, static_cast<_Flags&>(*this));
-
- if (__begin != __end && *__begin != _CharT('}'))
- __throw_format_error(
- "The format-spec should consume the input or end with a '}'");
-
- return __begin;
- }
-
- /** Processes the parsed std-format-spec based on the parsed display type. */
- _LIBCPP_HIDE_FROM_ABI constexpr void __process_display_type() {
- switch (this->__type) {
- case _Flags::_Type::__default:
- // When no precision specified then it keeps default since that
- // formatting
diff ers from the other types.
- if (this->__has_precision_field())
- this->__type = _Flags::_Type::__general_lower_case;
- break;
- case _Flags::_Type::__float_hexadecimal_lower_case:
- case _Flags::_Type::__float_hexadecimal_upper_case:
- // Precision specific behavior will be handled later.
- break;
- case _Flags::_Type::__scientific_lower_case:
- case _Flags::_Type::__scientific_upper_case:
- case _Flags::_Type::__fixed_lower_case:
- case _Flags::_Type::__fixed_upper_case:
- case _Flags::_Type::__general_lower_case:
- case _Flags::_Type::__general_upper_case:
- if (!this->__has_precision_field()) {
- // Set the default precision for the call to to_chars.
- this->__precision = 6;
- this->__precision_as_arg = false;
- }
- break;
-
- default:
- __throw_format_error("The format-spec type has a type not supported for "
- "a floating-point argument");
- }
- }
-};
-
-/**
- * The parser for the std-format-spec.
- *
- * This implements the parser for the pointer types.
- *
- * See @ref __parser_string.
- */
-template <class _CharT>
-class _LIBCPP_TEMPLATE_VIS __parser_pointer : public __parser_width, // provides __width(|as_arg)
- public __parser_fill_align<_CharT>, // provides __fill and uses __flags
- public _Flags // provides __flags
-{
-public:
- using char_type = _CharT;
-
- _LIBCPP_HIDE_FROM_ABI constexpr __parser_pointer() {
- // Implements LWG3612 Inconsistent pointer alignment in std::format.
- // The issue's current status is "Tentatively Ready" and libc++ status is
- // still experimental.
- //
- // TODO FMT Validate this with the final resolution of LWG3612.
- this->__alignment = _Flags::_Alignment::__right;
- }
-
- /**
- * The low-level std-format-spec parse function.
- *
- * @pre __begin points at the beginning of the std-format-spec. This means
- * directly after the ':'.
- * @pre The std-format-spec parses the entire input, or the first unmatched
- * character is a '}'.
- *
- * @returns The iterator pointing at the last parsed character.
- */
- _LIBCPP_HIDE_FROM_ABI constexpr auto parse(auto& __parse_ctx) -> decltype(__parse_ctx.begin()) {
- auto __it = __parse(__parse_ctx);
- __process_display_type();
- return __it;
- }
-
-protected:
- /**
- * The low-level std-format-spec parse function.
- *
- * @pre __begin points at the beginning of the std-format-spec. This means
- * directly after the ':'.
- * @pre The std-format-spec parses the entire input, or the first unmatched
- * character is a '}'.
- *
- * @returns The iterator pointing at the last parsed character.
- */
- _LIBCPP_HIDE_FROM_ABI constexpr auto __parse(auto& __parse_ctx) -> decltype(__parse_ctx.begin()) {
- auto __begin = __parse_ctx.begin();
- auto __end = __parse_ctx.end();
- if (__begin == __end)
- return __begin;
-
- __begin = __parser_fill_align<_CharT>::__parse(__begin, __end, static_cast<_Flags&>(*this));
- if (__begin == __end)
- return __begin;
-
- // An integer presentation type isn't defined in the Standard.
- // Since a pointer is formatted as an integer it can be argued it's an
- // integer presentation type. However there are two LWG-issues asserting it
- // isn't an integer presentation type:
- // - LWG3612 Inconsistent pointer alignment in std::format
- // - LWG3644 std::format does not define "integer presentation type"
- //
- // There's a paper to make additional clarifications on the status of
- // formatting pointers and proposes additional fields to be valid. That
- // paper hasn't been reviewed by the Committee yet.
- // - P2510 Formatting pointers
- //
- // The current implementation assumes formatting pointers isn't covered by
- // "integer presentation type".
- // TODO FMT Apply the LWG-issues/papers after approval/rejection by the Committee.
-
- __begin = __parser_width::__parse(__begin, __end, __parse_ctx);
- if (__begin == __end)
- return __begin;
-
- __begin = __parse_type(__begin, static_cast<_Flags&>(*this));
-
- if (__begin != __end && *__begin != _CharT('}'))
- __throw_format_error("The format-spec should consume the input or end with a '}'");
-
- return __begin;
- }
-
- /** Processes the parsed std-format-spec based on the parsed display type. */
- _LIBCPP_HIDE_FROM_ABI constexpr void __process_display_type() {
- switch (this->__type) {
- case _Flags::_Type::__default:
- this->__type = _Flags::_Type::__pointer;
- break;
- case _Flags::_Type::__pointer:
- break;
- default:
- __throw_format_error("The format-spec type has a type not supported for a pointer argument");
- }
- }
-};
-
/** Helper struct returned from @ref __get_string_alignment. */
template <class _CharT>
struct _LIBCPP_TEMPLATE_VIS __string_alignment {
More information about the libcxx-commits
mailing list