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_FORMAT_CONTEXT_H
11 #define _LIBCPP___FORMAT_FORMAT_CONTEXT_H
12
13 #include <__availability>
14 #include <__config>
15 #include <__format/buffer.h>
16 #include <__format/format_args.h>
17 #include <__format/format_fwd.h>
18 #include <__iterator/back_insert_iterator.h>
19 #include <__iterator/concepts.h>
20 #include <__utility/move.h>
21 #include <concepts>
22 #include <cstddef>
23
24 #ifndef _LIBCPP_HAS_NO_LOCALIZATION
25 #include <locale>
26 #include <optional>
27 #endif
28
29 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
30 # pragma GCC system_header
31 #endif
32
33 _LIBCPP_BEGIN_NAMESPACE_STD
34
35 #if _LIBCPP_STD_VER > 17
36
37 template <class _OutIt, class _CharT>
38 requires output_iterator<_OutIt, const _CharT&>
39 class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT basic_format_context;
40
41 #ifndef _LIBCPP_HAS_NO_LOCALIZATION
42 /**
43 * Helper to create a basic_format_context.
44 *
45 * This is needed since the constructor is private.
46 */
47 template <class _OutIt, class _CharT>
48 _LIBCPP_HIDE_FROM_ABI basic_format_context<_OutIt, _CharT>
49 __format_context_create(
50 _OutIt __out_it,
51 basic_format_args<basic_format_context<_OutIt, _CharT>> __args,
52 optional<_VSTD::locale>&& __loc = nullopt) {
53 return _VSTD::basic_format_context(_VSTD::move(__out_it), __args,
54 _VSTD::move(__loc));
55 }
56 #else
57 template <class _OutIt, class _CharT>
58 _LIBCPP_HIDE_FROM_ABI basic_format_context<_OutIt, _CharT>
__format_context_create(_OutIt __out_it,basic_format_args<basic_format_context<_OutIt,_CharT>> __args)59 __format_context_create(
60 _OutIt __out_it,
61 basic_format_args<basic_format_context<_OutIt, _CharT>> __args) {
62 return _VSTD::basic_format_context(_VSTD::move(__out_it), __args);
63 }
64 #endif
65
66 using format_context =
67 basic_format_context<back_insert_iterator<__format::__output_buffer<char>>,
68 char>;
69 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
70 using wformat_context = basic_format_context<
71 back_insert_iterator<__format::__output_buffer<wchar_t>>, wchar_t>;
72 #endif
73
74 template <class _OutIt, class _CharT>
75 requires output_iterator<_OutIt, const _CharT&>
76 class
77 // clang-format off
78 _LIBCPP_TEMPLATE_VIS
79 _LIBCPP_AVAILABILITY_FORMAT
_LIBCPP_PREFERRED_NAME(format_context)80 _LIBCPP_PREFERRED_NAME(format_context)
81 _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wformat_context))
82 // clang-format on
83 basic_format_context {
84 public:
85 using iterator = _OutIt;
86 using char_type = _CharT;
87 template <class _Tp>
88 using formatter_type = formatter<_Tp, _CharT>;
89
90 basic_format_context(const basic_format_context&) = delete;
91 basic_format_context& operator=(const basic_format_context&) = delete;
92
93 _LIBCPP_HIDE_FROM_ABI basic_format_arg<basic_format_context>
94 arg(size_t __id) const noexcept {
95 return __args_.get(__id);
96 }
97 #ifndef _LIBCPP_HAS_NO_LOCALIZATION
98 _LIBCPP_HIDE_FROM_ABI _VSTD::locale locale() {
99 if (!__loc_)
100 __loc_ = _VSTD::locale{};
101 return *__loc_;
102 }
103 #endif
104 _LIBCPP_HIDE_FROM_ABI iterator out() { return __out_it_; }
105 _LIBCPP_HIDE_FROM_ABI void advance_to(iterator __it) { __out_it_ = __it; }
106
107 private:
108 iterator __out_it_;
109 basic_format_args<basic_format_context> __args_;
110 #ifndef _LIBCPP_HAS_NO_LOCALIZATION
111
112 // The Standard doesn't specify how the locale is stored.
113 // [format.context]/6
114 // std::locale locale();
115 // Returns: The locale passed to the formatting function if the latter
116 // takes one, and std::locale() otherwise.
117 // This is done by storing the locale of the constructor in this optional. If
118 // locale() is called and the optional has no value the value will be created.
119 // This allows the implementation to lazily create the locale.
120 // TODO FMT Validate whether lazy creation is the best solution.
121 optional<_VSTD::locale> __loc_;
122
123 template <class __OutIt, class __CharT>
124 friend _LIBCPP_HIDE_FROM_ABI basic_format_context<__OutIt, __CharT>
125 __format_context_create(__OutIt, basic_format_args<basic_format_context<__OutIt, __CharT>>,
126 optional<_VSTD::locale>&&);
127
128 // Note: the Standard doesn't specify the required constructors.
129 _LIBCPP_HIDE_FROM_ABI
130 explicit basic_format_context(_OutIt __out_it,
131 basic_format_args<basic_format_context> __args,
132 optional<_VSTD::locale>&& __loc)
133 : __out_it_(_VSTD::move(__out_it)), __args_(__args),
134 __loc_(_VSTD::move(__loc)) {}
135 #else
136 template <class __OutIt, class __CharT>
137 friend _LIBCPP_HIDE_FROM_ABI basic_format_context<__OutIt, __CharT>
138 __format_context_create(__OutIt, basic_format_args<basic_format_context<__OutIt, __CharT>>);
139
140 _LIBCPP_HIDE_FROM_ABI
141 explicit basic_format_context(_OutIt __out_it,
142 basic_format_args<basic_format_context> __args)
143 : __out_it_(_VSTD::move(__out_it)), __args_(__args) {}
144 #endif
145 };
146
147 #endif //_LIBCPP_STD_VER > 17
148
149 _LIBCPP_END_NAMESPACE_STD
150
151 #endif // _LIBCPP___FORMAT_FORMAT_CONTEXT_H
152