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>
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
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