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