2 //===----------------------------------------------------------------------===//
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
8 //===----------------------------------------------------------------------===//
10 #ifndef _LIBCPP___CXX03___FORMAT_FORMATTER_STRING_H
11 #define _LIBCPP___CXX03___FORMAT_FORMATTER_STRING_H
13 #include <__cxx03/__config>
14 #include <__cxx03/__format/concepts.h>
15 #include <__cxx03/__format/format_parse_context.h>
16 #include <__cxx03/__format/formatter.h>
17 #include <__cxx03/__format/formatter_output.h>
18 #include <__cxx03/__format/parser_std_format_spec.h>
19 #include <__cxx03/__format/write_escaped.h>
20 #include <__cxx03/string>
21 #include <__cxx03/string_view>
23 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
24 # pragma GCC system_header
27 _LIBCPP_BEGIN_NAMESPACE_STD
29 #if _LIBCPP_STD_VER >= 20
31 template <__fmt_char_type _CharT
>
32 struct _LIBCPP_TEMPLATE_VIS __formatter_string
{
34 template <class _ParseContext
>
35 _LIBCPP_HIDE_FROM_ABI
constexpr typename
_ParseContext::iterator
parse(_ParseContext
& __ctx
) {
36 typename
_ParseContext::iterator __result
= __parser_
.__parse(__ctx
, __format_spec::__fields_string
);
37 __format_spec::__process_display_type_string(__parser_
.__type_
);
41 template <class _FormatContext
>
42 _LIBCPP_HIDE_FROM_ABI typename
_FormatContext::iterator
43 format(basic_string_view
<_CharT
> __str
, _FormatContext
& __ctx
) const {
44 # if _LIBCPP_STD_VER >= 23
45 if (__parser_
.__type_
== __format_spec::__type::__debug
)
46 return __formatter::__format_escaped_string(__str
, __ctx
.out(), __parser_
.__get_parsed_std_specifications(__ctx
));
49 return __formatter::__write_string(__str
, __ctx
.out(), __parser_
.__get_parsed_std_specifications(__ctx
));
52 # if _LIBCPP_STD_VER >= 23
53 _LIBCPP_HIDE_FROM_ABI
constexpr void set_debug_format() { __parser_
.__type_
= __format_spec::__type::__debug
; }
56 __format_spec::__parser
<_CharT
> __parser_
{.__alignment_
= __format_spec::__alignment::__left
};
59 // Formatter const char*.
60 template <__fmt_char_type _CharT
>
61 struct _LIBCPP_TEMPLATE_VIS formatter
<const _CharT
*, _CharT
> : public __formatter_string
<_CharT
> {
62 using _Base
= __formatter_string
<_CharT
>;
64 template <class _FormatContext
>
65 _LIBCPP_HIDE_FROM_ABI typename
_FormatContext::iterator
format(const _CharT
* __str
, _FormatContext
& __ctx
) const {
66 _LIBCPP_ASSERT_INTERNAL(__str
, "The basic_format_arg constructor should have prevented an invalid pointer.");
68 __format_spec::__parsed_specifications
<_CharT
> __specs
= _Base::__parser_
.__get_parsed_std_specifications(__ctx
);
69 # if _LIBCPP_STD_VER >= 23
70 if (_Base::__parser_
.__type_
== __format_spec::__type::__debug
)
71 return __formatter::__format_escaped_string(basic_string_view
<_CharT
>{__str
}, __ctx
.out(), __specs
);
74 // When using a center or right alignment and the width option the length
75 // of __str must be known to add the padding upfront. This case is handled
76 // by the base class by converting the argument to a basic_string_view.
78 // When using left alignment and the width option the padding is added
79 // after outputting __str so the length can be determined while outputting
80 // __str. The same holds true for the precision, during outputting __str it
81 // can be validated whether the precision threshold has been reached. For
82 // now these optimizations aren't implemented. Instead the base class
83 // handles these options.
84 // TODO FMT Implement these improvements.
85 if (__specs
.__has_width() || __specs
.__has_precision())
86 return __formatter::__write_string(basic_string_view
<_CharT
>{__str
}, __ctx
.out(), __specs
);
88 // No formatting required, copy the string to the output.
89 auto __out_it
= __ctx
.out();
91 *__out_it
++ = *__str
++;
97 template <__fmt_char_type _CharT
>
98 struct _LIBCPP_TEMPLATE_VIS formatter
<_CharT
*, _CharT
> : public formatter
<const _CharT
*, _CharT
> {
99 using _Base
= formatter
<const _CharT
*, _CharT
>;
101 template <class _FormatContext
>
102 _LIBCPP_HIDE_FROM_ABI typename
_FormatContext::iterator
format(_CharT
* __str
, _FormatContext
& __ctx
) const {
103 return _Base::format(__str
, __ctx
);
108 template <__fmt_char_type _CharT
, size_t _Size
>
109 struct _LIBCPP_TEMPLATE_VIS formatter
<_CharT
[_Size
], _CharT
> : public __formatter_string
<_CharT
> {
110 using _Base
= __formatter_string
<_CharT
>;
112 template <class _FormatContext
>
113 _LIBCPP_HIDE_FROM_ABI typename
_FormatContext::iterator
114 format(const _CharT (&__str
)[_Size
], _FormatContext
& __ctx
) const {
115 return _Base::format(basic_string_view
<_CharT
>(__str
, _Size
), __ctx
);
119 // Formatter std::string.
120 template <__fmt_char_type _CharT
, class _Traits
, class _Allocator
>
121 struct _LIBCPP_TEMPLATE_VIS formatter
<basic_string
<_CharT
, _Traits
, _Allocator
>, _CharT
>
122 : public __formatter_string
<_CharT
> {
123 using _Base
= __formatter_string
<_CharT
>;
125 template <class _FormatContext
>
126 _LIBCPP_HIDE_FROM_ABI typename
_FormatContext::iterator
127 format(const basic_string
<_CharT
, _Traits
, _Allocator
>& __str
, _FormatContext
& __ctx
) const {
128 // Drop _Traits and _Allocator to have one std::basic_string formatter.
129 return _Base::format(basic_string_view
<_CharT
>(__str
.data(), __str
.size()), __ctx
);
133 // Formatter std::string_view.
134 template <__fmt_char_type _CharT
, class _Traits
>
135 struct _LIBCPP_TEMPLATE_VIS formatter
<basic_string_view
<_CharT
, _Traits
>, _CharT
> : public __formatter_string
<_CharT
> {
136 using _Base
= __formatter_string
<_CharT
>;
138 template <class _FormatContext
>
139 _LIBCPP_HIDE_FROM_ABI typename
_FormatContext::iterator
140 format(basic_string_view
<_CharT
, _Traits
> __str
, _FormatContext
& __ctx
) const {
141 // Drop _Traits to have one std::basic_string_view formatter.
142 return _Base::format(basic_string_view
<_CharT
>(__str
.data(), __str
.size()), __ctx
);
146 #endif //_LIBCPP_STD_VER >= 20
148 _LIBCPP_END_NAMESPACE_STD
150 #endif // _LIBCPP___CXX03___FORMAT_FORMATTER_STRING_H