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