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