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