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