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___FORMAT_FORMATTER_STRING_H
11 #define _LIBCPP___FORMAT_FORMATTER_STRING_H
13 #include <__availability>
15 #include <__format/concepts.h>
16 #include <__format/format_parse_context.h>
17 #include <__format/formatter.h>
18 #include <__format/formatter_output.h>
19 #include <__format/parser_std_format_spec.h>
20 #include <__format/write_escaped.h>
22 #include <string_view>
24 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
25 # pragma GCC system_header
28 _LIBCPP_BEGIN_NAMESPACE_STD
30 #if _LIBCPP_STD_VER >= 20
32 template <__fmt_char_type _CharT
>
33 struct _LIBCPP_TEMPLATE_VIS __formatter_string
{
35 template <class _ParseContext
>
36 _LIBCPP_HIDE_FROM_ABI
constexpr typename
_ParseContext::iterator
parse(_ParseContext
& __ctx
) {
37 typename
_ParseContext::iterator __result
= __parser_
.__parse(__ctx
, __format_spec::__fields_string
);
38 __format_spec::__process_display_type_string(__parser_
.__type_
);
42 template <class _FormatContext
>
43 _LIBCPP_HIDE_FROM_ABI typename
_FormatContext::iterator
44 format(basic_string_view
<_CharT
> __str
, _FormatContext
& __ctx
) const {
45 # if _LIBCPP_STD_VER >= 23
46 if (__parser_
.__type_
== __format_spec::__type::__debug
)
47 return __formatter::__format_escaped_string(__str
, __ctx
.out(), __parser_
.__get_parsed_std_specifications(__ctx
));
50 return __formatter::__write_string(__str
, __ctx
.out(), __parser_
.__get_parsed_std_specifications(__ctx
));
53 # if _LIBCPP_STD_VER >= 23
54 _LIBCPP_HIDE_FROM_ABI
constexpr void set_debug_format() { __parser_
.__type_
= __format_spec::__type::__debug
; }
57 __format_spec::__parser
<_CharT
> __parser_
{.__alignment_
= __format_spec::__alignment::__left
};
60 // Formatter const char*.
61 template <__fmt_char_type _CharT
>
62 struct _LIBCPP_TEMPLATE_VIS formatter
<const _CharT
*, _CharT
>
63 : public __formatter_string
<_CharT
> {
64 using _Base
= __formatter_string
<_CharT
>;
66 template <class _FormatContext
>
67 _LIBCPP_HIDE_FROM_ABI typename
_FormatContext::iterator
format(const _CharT
* __str
, _FormatContext
& __ctx
) const {
68 _LIBCPP_ASSERT_UNCATEGORIZED(__str
, "The basic_format_arg constructor should have "
69 "prevented an invalid pointer.");
71 __format_spec::__parsed_specifications
<_CharT
> __specs
= _Base::__parser_
.__get_parsed_std_specifications(__ctx
);
72 # if _LIBCPP_STD_VER >= 23
73 if (_Base::__parser_
.__type_
== __format_spec::__type::__debug
)
74 return __formatter::__format_escaped_string(basic_string_view
<_CharT
>{__str
}, __ctx
.out(), __specs
);
77 // When using a center or right alignment and the width option the length
78 // of __str must be known to add the padding upfront. This case is handled
79 // by the base class by converting the argument to a basic_string_view.
81 // When using left alignment and the width option the padding is added
82 // after outputting __str so the length can be determined while outputting
83 // __str. The same holds true for the precision, during outputting __str it
84 // can be validated whether the precision threshold has been reached. For
85 // now these optimizations aren't implemented. Instead the base class
86 // handles these options.
87 // TODO FMT Implement these improvements.
88 if (__specs
.__has_width() || __specs
.__has_precision())
89 return __formatter::__write_string(basic_string_view
<_CharT
>{__str
}, __ctx
.out(), __specs
);
91 // No formatting required, copy the string to the output.
92 auto __out_it
= __ctx
.out();
94 *__out_it
++ = *__str
++;
100 template <__fmt_char_type _CharT
>
101 struct _LIBCPP_TEMPLATE_VIS formatter
<_CharT
*, _CharT
>
102 : public formatter
<const _CharT
*, _CharT
> {
103 using _Base
= formatter
<const _CharT
*, _CharT
>;
105 template <class _FormatContext
>
106 _LIBCPP_HIDE_FROM_ABI typename
_FormatContext::iterator
format(_CharT
* __str
, _FormatContext
& __ctx
) const {
107 return _Base::format(__str
, __ctx
);
112 template <__fmt_char_type _CharT
, size_t _Size
>
113 struct _LIBCPP_TEMPLATE_VIS formatter
<_CharT
[_Size
], _CharT
>
114 : public __formatter_string
<_CharT
> {
115 using _Base
= __formatter_string
<_CharT
>;
117 template <class _FormatContext
>
118 _LIBCPP_HIDE_FROM_ABI typename
_FormatContext::iterator
119 format(const _CharT (&__str
)[_Size
], _FormatContext
& __ctx
) const {
120 return _Base::format(basic_string_view
<_CharT
>(__str
, _Size
), __ctx
);
124 // Formatter std::string.
125 template <__fmt_char_type _CharT
, class _Traits
, class _Allocator
>
126 struct _LIBCPP_TEMPLATE_VIS formatter
<basic_string
<_CharT
, _Traits
, _Allocator
>, _CharT
>
127 : public __formatter_string
<_CharT
> {
128 using _Base
= __formatter_string
<_CharT
>;
130 template <class _FormatContext
>
131 _LIBCPP_HIDE_FROM_ABI typename
_FormatContext::iterator
132 format(const basic_string
<_CharT
, _Traits
, _Allocator
>& __str
, _FormatContext
& __ctx
) const {
133 // Drop _Traits and _Allocator to have one std::basic_string formatter.
134 return _Base::format(basic_string_view
<_CharT
>(__str
.data(), __str
.size()), __ctx
);
138 // Formatter std::string_view.
139 template <__fmt_char_type _CharT
, class _Traits
>
140 struct _LIBCPP_TEMPLATE_VIS formatter
<basic_string_view
<_CharT
, _Traits
>, _CharT
>
141 : public __formatter_string
<_CharT
> {
142 using _Base
= __formatter_string
<_CharT
>;
144 template <class _FormatContext
>
145 _LIBCPP_HIDE_FROM_ABI typename
_FormatContext::iterator
146 format(basic_string_view
<_CharT
, _Traits
> __str
, _FormatContext
& __ctx
) const {
147 // Drop _Traits to have one std::basic_string_view formatter.
148 return _Base::format(basic_string_view
<_CharT
>(__str
.data(), __str
.size()), __ctx
);
152 #endif //_LIBCPP_STD_VER >= 20
154 _LIBCPP_END_NAMESPACE_STD
156 #endif // _LIBCPP___FORMAT_FORMATTER_STRING_H