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_BOOL_H
11 #define _LIBCPP___FORMAT_FORMATTER_BOOL_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 #include <string_view>
21 
22 #ifndef _LIBCPP_HAS_NO_LOCALIZATION
23 #include <locale>
24 #endif
25 
26 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
27 #  pragma GCC system_header
28 #endif
29 
30 _LIBCPP_BEGIN_NAMESPACE_STD
31 
32 #if _LIBCPP_STD_VER > 17
33 
34 namespace __format_spec {
35 
36 template <class _CharT>
37 class _LIBCPP_TEMPLATE_VIS __parser_bool : public __parser_integral<_CharT> {
38 public:
39   _LIBCPP_HIDE_FROM_ABI constexpr auto parse(auto& __parse_ctx)
40       -> decltype(__parse_ctx.begin()) {
41     auto __it = __parser_integral<_CharT>::__parse(__parse_ctx);
42 
43     switch (this->__type) {
44     case _Flags::_Type::__default:
45       this->__type = _Flags::_Type::__string;
46       [[fallthrough]];
47     case _Flags::_Type::__string:
48       this->__handle_bool();
49       break;
50 
51     case _Flags::_Type::__binary_lower_case:
52     case _Flags::_Type::__binary_upper_case:
53     case _Flags::_Type::__octal:
54     case _Flags::_Type::__decimal:
55     case _Flags::_Type::__hexadecimal_lower_case:
56     case _Flags::_Type::__hexadecimal_upper_case:
57       this->__handle_integer();
58       break;
59 
60     default:
61       __throw_format_error(
62           "The format-spec type has a type not supported for a bool argument");
63     }
64 
65     return __it;
66   }
67 };
68 
69 template <class _CharT>
70 struct _LIBCPP_TEMPLATE_VIS __bool_strings;
71 
72 template <>
73 struct _LIBCPP_TEMPLATE_VIS __bool_strings<char> {
74   static constexpr string_view __true{"true"};
75   static constexpr string_view __false{"false"};
76 };
77 
78 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
79 template <>
80 struct _LIBCPP_TEMPLATE_VIS __bool_strings<wchar_t> {
81   static constexpr wstring_view __true{L"true"};
82   static constexpr wstring_view __false{L"false"};
83 };
84 #endif
85 
86 template <class _CharT>
87 using __formatter_bool = __formatter_integral<__parser_bool<_CharT>>;
88 
89 } //namespace __format_spec
90 
91 // [format.formatter.spec]/2.3
92 // For each charT, for each cv-unqualified arithmetic type ArithmeticT other
93 // than char, wchar_t, char8_t, char16_t, or char32_t, a specialization
94 
95 template <__formatter::__char_type _CharT>
96 struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<bool, _CharT>
97     : public __format_spec::__formatter_bool<_CharT> {
98   using _Base = __format_spec::__formatter_bool<_CharT>;
99 
100   _LIBCPP_HIDE_FROM_ABI auto format(bool __value, auto& __ctx)
101       -> decltype(__ctx.out()) {
102     if (this->__type != __format_spec::_Flags::_Type::__string)
103       return _Base::format(static_cast<unsigned char>(__value), __ctx);
104 
105     if (this->__width_needs_substitution())
106       this->__substitute_width_arg_id(__ctx.arg(this->__width));
107 
108 #ifndef _LIBCPP_HAS_NO_LOCALIZATION
109     if (this->__locale_specific_form) {
110       const auto& __np = use_facet<numpunct<_CharT>>(__ctx.locale());
111       basic_string<_CharT> __str = __value ? __np.truename() : __np.falsename();
112       return __formatter::__write_unicode(
113           __ctx.out(), basic_string_view<_CharT>{__str}, this->__width, -1,
114           this->__fill, this->__alignment);
115     }
116 #endif
117     basic_string_view<_CharT> __str =
118         __value ? __format_spec::__bool_strings<_CharT>::__true
119                 : __format_spec::__bool_strings<_CharT>::__false;
120 
121     // The output only uses ASCII so every character is one column.
122     unsigned __size = __str.size();
123     if (__size >= this->__width)
124       return _VSTD::copy(__str.begin(), __str.end(), __ctx.out());
125 
126     return __formatter::__write(__ctx.out(), __str.begin(), __str.end(), __size,
127                                 this->__width, this->__fill, this->__alignment);
128   }
129 };
130 
131 #endif //_LIBCPP_STD_VER > 17
132 
133 _LIBCPP_END_NAMESPACE_STD
134 
135 #endif // _LIBCPP___FORMAT_FORMATTER_BOOL_H
136