1 // -*- C++ -*- 2 //===----------------------------------------------------------------------===// 3 // 4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5 // See https://llvm.org/LICENSE.txt for license information. 6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef _LIBCPP___FORMAT_FORMATTER_CHAR_H 11 #define _LIBCPP___FORMAT_FORMATTER_CHAR_H 12 13 #include <__availability> 14 #include <__config> 15 #include <__format/format_error.h> 16 #include <__format/format_fwd.h> 17 #include <__format/formatter.h> 18 #include <__format/formatter_integral.h> 19 #include <__format/parser_std_format_spec.h> 20 21 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 22 #pragma GCC system_header 23 #endif 24 25 _LIBCPP_BEGIN_NAMESPACE_STD 26 27 #if _LIBCPP_STD_VER > 17 28 29 // TODO FMT Remove this once we require compilers with proper C++20 support. 30 // If the compiler has no concepts support, the format header will be disabled. 31 // Without concepts support enable_if needs to be used and that too much effort 32 // to support compilers with partial C++20 support. 33 #if !defined(_LIBCPP_HAS_NO_CONCEPTS) 34 35 namespace __format_spec { 36 37 template <class _CharT> 38 class _LIBCPP_TEMPLATE_VIS __parser_char : public __parser_integral<_CharT> { 39 public: 40 _LIBCPP_HIDE_FROM_ABI constexpr auto parse(auto& __parse_ctx) 41 -> decltype(__parse_ctx.begin()) { 42 auto __it = __parser_integral<_CharT>::__parse(__parse_ctx); 43 44 switch (this->__type) { 45 case _Flags::_Type::__default: 46 this->__type = _Flags::_Type::__char; 47 [[fallthrough]]; 48 case _Flags::_Type::__char: 49 this->__handle_char(); 50 break; 51 52 case _Flags::_Type::__binary_lower_case: 53 case _Flags::_Type::__binary_upper_case: 54 case _Flags::_Type::__octal: 55 case _Flags::_Type::__decimal: 56 case _Flags::_Type::__hexadecimal_lower_case: 57 case _Flags::_Type::__hexadecimal_upper_case: 58 this->__handle_integer(); 59 break; 60 61 default: 62 __throw_format_error( 63 "The format-spec type has a type not supported for a char argument"); 64 } 65 66 return __it; 67 } 68 }; 69 70 template <class _CharT> 71 using __formatter_char = __formatter_integral<__parser_char<_CharT>>; 72 73 } // namespace __format_spec 74 75 // [format.formatter.spec]/2.1 The specializations 76 77 template <> 78 struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<char, char> 79 : public __format_spec::__formatter_char<char> {}; 80 81 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 82 template <> 83 struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<char, wchar_t> 84 : public __format_spec::__formatter_char<wchar_t> { 85 using _Base = __format_spec::__formatter_char<wchar_t>; 86 87 _LIBCPP_HIDE_FROM_ABI auto format(char __value, auto& __ctx) 88 -> decltype(__ctx.out()) { 89 return _Base::format(static_cast<wchar_t>(__value), __ctx); 90 } 91 }; 92 93 template <> 94 struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT 95 formatter<wchar_t, wchar_t> 96 : public __format_spec::__formatter_char<wchar_t> {}; 97 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS 98 #endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) 99 100 #endif //_LIBCPP_STD_VER > 17 101 102 _LIBCPP_END_NAMESPACE_STD 103 104 #endif // _LIBCPP___FORMAT_FORMATTER_CHAR_H 105