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_FORMAT_CONTEXT_H
11 #define _LIBCPP___FORMAT_FORMAT_CONTEXT_H
13 #include <__concepts/same_as.h>
15 #include <__format/buffer.h>
16 #include <__format/format_arg.h>
17 #include <__format/format_arg_store.h>
18 #include <__format/format_args.h>
19 #include <__format/format_error.h>
20 #include <__fwd/format.h>
21 #include <__iterator/back_insert_iterator.h>
22 #include <__iterator/concepts.h>
23 #include <__memory/addressof.h>
24 #include <__utility/move.h>
25 #include <__variant/monostate.h>
27 #if _LIBCPP_HAS_LOCALIZATION
32 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
33 # pragma GCC system_header
37 #include <__undef_macros>
39 _LIBCPP_BEGIN_NAMESPACE_STD
41 #if _LIBCPP_STD_VER >= 20
43 template <class _OutIt
, class _CharT
>
44 requires output_iterator
<_OutIt
, const _CharT
&>
45 class _LIBCPP_TEMPLATE_VIS basic_format_context
;
47 # if _LIBCPP_HAS_LOCALIZATION
49 * Helper to create a basic_format_context.
51 * This is needed since the constructor is private.
53 template <class _OutIt
, class _CharT
>
54 _LIBCPP_HIDE_FROM_ABI basic_format_context
<_OutIt
, _CharT
>
55 __format_context_create(_OutIt __out_it
,
56 basic_format_args
<basic_format_context
<_OutIt
, _CharT
>> __args
,
57 optional
<std::locale
>&& __loc
= nullopt
) {
58 return std::basic_format_context(std::move(__out_it
), __args
, std::move(__loc
));
61 template <class _OutIt
, class _CharT
>
62 _LIBCPP_HIDE_FROM_ABI basic_format_context
<_OutIt
, _CharT
>
63 __format_context_create(_OutIt __out_it
, basic_format_args
<basic_format_context
<_OutIt
, _CharT
>> __args
) {
64 return std::basic_format_context(std::move(__out_it
), __args
);
68 using format_context
= basic_format_context
<back_insert_iterator
<__format::__output_buffer
<char>>, char>;
69 # if _LIBCPP_HAS_WIDE_CHARACTERS
70 using wformat_context
= basic_format_context
< back_insert_iterator
<__format::__output_buffer
<wchar_t>>, wchar_t>;
73 template <class _OutIt
, class _CharT
>
74 requires output_iterator
<_OutIt
, const _CharT
&>
78 _LIBCPP_PREFERRED_NAME(format_context
)
79 _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wformat_context
))
81 basic_format_context
{
83 using iterator
= _OutIt
;
84 using char_type
= _CharT
;
86 using formatter_type
= formatter
<_Tp
, _CharT
>;
88 _LIBCPP_HIDE_FROM_ABI basic_format_arg
<basic_format_context
> arg(size_t __id
) const noexcept
{
89 return __args_
.get(__id
);
91 # if _LIBCPP_HAS_LOCALIZATION
92 _LIBCPP_HIDE_FROM_ABI
std::locale
locale() {
94 __loc_
= std::locale
{};
98 _LIBCPP_HIDE_FROM_ABI iterator
out() { return std::move(__out_it_
); }
99 _LIBCPP_HIDE_FROM_ABI
void advance_to(iterator __it
) { __out_it_
= std::move(__it
); }
103 basic_format_args
<basic_format_context
> __args_
;
104 # if _LIBCPP_HAS_LOCALIZATION
106 // The Standard doesn't specify how the locale is stored.
107 // [format.context]/6
108 // std::locale locale();
109 // Returns: The locale passed to the formatting function if the latter
110 // takes one, and std::locale() otherwise.
111 // This is done by storing the locale of the constructor in this optional. If
112 // locale() is called and the optional has no value the value will be created.
113 // This allows the implementation to lazily create the locale.
114 // TODO FMT Validate whether lazy creation is the best solution.
115 optional
<std::locale
> __loc_
;
117 template <class _OtherOutIt
, class _OtherCharT
>
118 friend _LIBCPP_HIDE_FROM_ABI basic_format_context
<_OtherOutIt
, _OtherCharT
> __format_context_create(
119 _OtherOutIt
, basic_format_args
<basic_format_context
<_OtherOutIt
, _OtherCharT
>>, optional
<std::locale
>&&);
121 // Note: the Standard doesn't specify the required constructors.
122 _LIBCPP_HIDE_FROM_ABI
explicit basic_format_context(
123 _OutIt __out_it
, basic_format_args
<basic_format_context
> __args
, optional
<std::locale
>&& __loc
)
124 : __out_it_(std::move(__out_it
)), __args_(__args
), __loc_(std::move(__loc
)) {}
126 template <class _OtherOutIt
, class _OtherCharT
>
127 friend _LIBCPP_HIDE_FROM_ABI basic_format_context
<_OtherOutIt
, _OtherCharT
>
128 __format_context_create(_OtherOutIt
, basic_format_args
<basic_format_context
<_OtherOutIt
, _OtherCharT
>>);
130 _LIBCPP_HIDE_FROM_ABI
explicit basic_format_context(_OutIt __out_it
, basic_format_args
<basic_format_context
> __args
)
131 : __out_it_(std::move(__out_it
)), __args_(__args
) {}
135 basic_format_context(const basic_format_context
&) = delete;
136 basic_format_context
& operator=(const basic_format_context
&) = delete;
139 // A specialization for __retarget_buffer
141 // See __retarget_buffer for the motivation for this specialization.
143 // This context holds a reference to the instance of the basic_format_context
144 // that is retargeted. It converts a formatting argument when it is requested
145 // during formatting. It is expected that the usage of the arguments is rare so
146 // the lookups are not expected to be used often. An alternative would be to
147 // convert all elements during construction.
149 // The elements of the retargets context are only used when an underlying
150 // formatter uses a locale specific formatting or an formatting argument is
151 // part for the format spec. For example
152 // format("{:256:{}}", input, 8);
153 // Here the width of an element in input is determined dynamically.
154 // Note when the top-level element has no width the retargeting is not needed.
155 template <class _CharT
>
156 class _LIBCPP_TEMPLATE_VIS basic_format_context
<typename
__format::__retarget_buffer
<_CharT
>::__iterator
, _CharT
> {
158 using iterator
= typename
__format::__retarget_buffer
<_CharT
>::__iterator
;
159 using char_type
= _CharT
;
161 using formatter_type
= formatter
<_Tp
, _CharT
>;
163 template <class _Context
>
164 _LIBCPP_HIDE_FROM_ABI
explicit basic_format_context(iterator __out_it
, _Context
& __ctx
)
165 : __out_it_(std::move(__out_it
)),
166 # if _LIBCPP_HAS_LOCALIZATION
167 __loc_([](void* __c
) { return static_cast<_Context
*>(__c
)->locale(); }),
169 __ctx_(std::addressof(__ctx
)),
170 __arg_([](void* __c
, size_t __id
) {
171 auto __visitor
= [&](auto __arg
) -> basic_format_arg
<basic_format_context
> {
172 if constexpr (same_as
<decltype(__arg
), monostate
>)
174 else if constexpr (same_as
<decltype(__arg
), typename basic_format_arg
<_Context
>::handle
>)
175 // At the moment it's not possible for formatting to use a re-targeted handle.
176 // TODO FMT add this when support is needed.
177 std::__throw_format_error("Re-targeting handle not supported");
179 return basic_format_arg
<basic_format_context
>{
180 __format::__determine_arg_t
<basic_format_context
, decltype(__arg
)>(),
181 __basic_format_arg_value
<basic_format_context
>(__arg
)};
183 # if _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER
184 return static_cast<_Context
*>(__c
)->arg(__id
).visit(std::move(__visitor
));
186 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
187 return std::visit_format_arg(std::move(__visitor
), static_cast<_Context
*>(__c
)->arg(__id
));
188 _LIBCPP_SUPPRESS_DEPRECATED_POP
189 # endif // _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER
193 _LIBCPP_HIDE_FROM_ABI basic_format_arg
<basic_format_context
> arg(size_t __id
) const noexcept
{
194 return __arg_(__ctx_
, __id
);
196 # if _LIBCPP_HAS_LOCALIZATION
197 _LIBCPP_HIDE_FROM_ABI
std::locale
locale() { return __loc_(__ctx_
); }
199 _LIBCPP_HIDE_FROM_ABI iterator
out() { return std::move(__out_it_
); }
200 _LIBCPP_HIDE_FROM_ABI
void advance_to(iterator __it
) { __out_it_
= std::move(__it
); }
205 # if _LIBCPP_HAS_LOCALIZATION
206 std::locale (*__loc_
)(void* __ctx
);
210 basic_format_arg
<basic_format_context
> (*__arg_
)(void* __ctx
, size_t __id
);
213 _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(basic_format_context
);
214 #endif // _LIBCPP_STD_VER >= 20
216 _LIBCPP_END_NAMESPACE_STD
220 #endif // _LIBCPP___FORMAT_FORMAT_CONTEXT_H