xref: /freebsd-src/contrib/llvm-project/libcxx/include/__format/format_context.h (revision c9ccf3a32da427475985b85d7df023ccfb138c27)
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/format_args.h>
16 #include <__format/format_fwd.h>
17 #include <__iterator/back_insert_iterator.h>
18 #include <__iterator/concepts.h>
19 #include <concepts>
20 
21 #ifndef _LIBCPP_HAS_NO_LOCALIZATION
22 #include <locale>
23 #include <optional>
24 #endif
25 
26 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
27 #pragma GCC system_header
28 #endif
29 
30 _LIBCPP_PUSH_MACROS
31 #include <__undef_macros>
32 
33 _LIBCPP_BEGIN_NAMESPACE_STD
34 
35 #if _LIBCPP_STD_VER > 17
36 
37 // TODO FMT Remove this once we require compilers with proper C++20 support.
38 // If the compiler has no concepts support, the format header will be disabled.
39 // Without concepts support enable_if needs to be used and that too much effort
40 // to support compilers with partial C++20 support.
41 #if !defined(_LIBCPP_HAS_NO_CONCEPTS)
42 
43 template <class _OutIt, class _CharT>
44 requires output_iterator<_OutIt, const _CharT&>
45 class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT basic_format_context;
46 
47 #ifndef _LIBCPP_HAS_NO_LOCALIZATION
48 /**
49  * Helper to create a basic_format_context.
50  *
51  * This is needed since the constructor is private.
52  */
53 template <class _OutIt, class _CharT>
54 _LIBCPP_HIDE_FROM_ABI basic_format_context<_OutIt, _CharT>
55 __format_context_create(
56     _OutIt __out_it,
57     basic_format_args<basic_format_context<_OutIt, _CharT>> __args,
58     optional<_VSTD::locale>&& __loc = nullopt) {
59   return _VSTD::basic_format_context(_VSTD::move(__out_it), __args,
60                                      _VSTD::move(__loc));
61 }
62 #else
63 template <class _OutIt, class _CharT>
64 _LIBCPP_HIDE_FROM_ABI basic_format_context<_OutIt, _CharT>
65 __format_context_create(
66     _OutIt __out_it,
67     basic_format_args<basic_format_context<_OutIt, _CharT>> __args) {
68   return _VSTD::basic_format_context(_VSTD::move(__out_it), __args);
69 }
70 #endif
71 
72 // TODO FMT Implement [format.context]/4
73 // [Note 1: For a given type charT, implementations are encouraged to provide a
74 // single instantiation of basic_format_context for appending to
75 // basic_string<charT>, vector<charT>, or any other container with contiguous
76 // storage by wrapping those in temporary objects with a uniform interface
77 // (such as a span<charT>) and polymorphic reallocation. - end note]
78 
79 using format_context = basic_format_context<back_insert_iterator<string>, char>;
80 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
81 using wformat_context = basic_format_context<back_insert_iterator<wstring>, wchar_t>;
82 #endif
83 
84 template <class _OutIt, class _CharT>
85 requires output_iterator<_OutIt, const _CharT&>
86 class
87     // clang-format off
88     _LIBCPP_TEMPLATE_VIS
89     _LIBCPP_AVAILABILITY_FORMAT
90     _LIBCPP_PREFERRED_NAME(format_context)
91     _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wformat_context))
92     // clang-format on
93     basic_format_context {
94 public:
95   using iterator = _OutIt;
96   using char_type = _CharT;
97   template <class _Tp>
98   using formatter_type = formatter<_Tp, _CharT>;
99 
100   basic_format_context(const basic_format_context&) = delete;
101   basic_format_context& operator=(const basic_format_context&) = delete;
102 
103   _LIBCPP_HIDE_FROM_ABI basic_format_arg<basic_format_context>
104   arg(size_t __id) const {
105     return __args_.get(__id);
106   }
107 #ifndef _LIBCPP_HAS_NO_LOCALIZATION
108   _LIBCPP_HIDE_FROM_ABI _VSTD::locale locale() {
109     if (!__loc_)
110       __loc_ = _VSTD::locale{};
111     return *__loc_;
112   }
113 #endif
114   _LIBCPP_HIDE_FROM_ABI iterator out() { return __out_it_; }
115   _LIBCPP_HIDE_FROM_ABI void advance_to(iterator __it) { __out_it_ = __it; }
116 
117 private:
118   iterator __out_it_;
119   basic_format_args<basic_format_context> __args_;
120 #ifndef _LIBCPP_HAS_NO_LOCALIZATION
121 
122   // The Standard doesn't specify how the locale is stored.
123   // [format.context]/6
124   // std::locale locale();
125   //   Returns: The locale passed to the formatting function if the latter
126   //   takes one, and std::locale() otherwise.
127   // This is done by storing the locale of the constructor in this optional. If
128   // locale() is called and the optional has no value the value will be created.
129   // This allows the implementation to lazily create the locale.
130   // TODO FMT Validate whether lazy creation is the best solution.
131   optional<_VSTD::locale> __loc_;
132 
133   template <class __OutIt, class __CharT>
134   friend _LIBCPP_HIDE_FROM_ABI basic_format_context<__OutIt, __CharT>
135   __format_context_create(__OutIt, basic_format_args<basic_format_context<__OutIt, __CharT>>,
136                           optional<_VSTD::locale>&&);
137 
138   // Note: the Standard doesn't specify the required constructors.
139   _LIBCPP_HIDE_FROM_ABI
140   explicit basic_format_context(_OutIt __out_it,
141                                 basic_format_args<basic_format_context> __args,
142                                 optional<_VSTD::locale>&& __loc)
143       : __out_it_(_VSTD::move(__out_it)), __args_(__args),
144         __loc_(_VSTD::move(__loc)) {}
145 #else
146   template <class __OutIt, class __CharT>
147   friend _LIBCPP_HIDE_FROM_ABI basic_format_context<__OutIt, __CharT>
148       __format_context_create(__OutIt, basic_format_args<basic_format_context<__OutIt, __CharT>>);
149 
150   _LIBCPP_HIDE_FROM_ABI
151   explicit basic_format_context(_OutIt __out_it,
152                                 basic_format_args<basic_format_context> __args)
153       : __out_it_(_VSTD::move(__out_it)), __args_(__args) {}
154 #endif
155 };
156 
157 #endif // !defined(_LIBCPP_HAS_NO_CONCEPTS)
158 
159 #endif //_LIBCPP_STD_VER > 17
160 
161 _LIBCPP_END_NAMESPACE_STD
162 
163 _LIBCPP_POP_MACROS
164 
165 #endif // _LIBCPP___FORMAT_FORMAT_CONTEXT_H
166