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 template <class _OutIt, class _CharT> 74 requires output_iterator<_OutIt, const _CharT&> 75 class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT basic_format_context { 76 public: 77 using iterator = _OutIt; 78 using char_type = _CharT; 79 template <class _Tp> 80 using formatter_type = formatter<_Tp, _CharT>; 81 82 basic_format_context(const basic_format_context&) = delete; 83 basic_format_context& operator=(const basic_format_context&) = delete; 84 85 _LIBCPP_HIDE_FROM_ABI basic_format_arg<basic_format_context> 86 arg(size_t __id) const { 87 return __args_.get(__id); 88 } 89 #ifndef _LIBCPP_HAS_NO_LOCALIZATION 90 _LIBCPP_HIDE_FROM_ABI _VSTD::locale locale() { 91 if (!__loc_) 92 __loc_ = _VSTD::locale{}; 93 return *__loc_; 94 } 95 #endif 96 _LIBCPP_HIDE_FROM_ABI iterator out() { return __out_it_; } 97 _LIBCPP_HIDE_FROM_ABI void advance_to(iterator __it) { __out_it_ = __it; } 98 99 private: 100 iterator __out_it_; 101 basic_format_args<basic_format_context> __args_; 102 #ifndef _LIBCPP_HAS_NO_LOCALIZATION 103 104 // The Standard doesn't specify how the locale is stored. 105 // [format.context]/6 106 // std::locale locale(); 107 // Returns: The locale passed to the formatting function if the latter 108 // takes one, and std::locale() otherwise. 109 // This is done by storing the locale of the constructor in this optional. If 110 // locale() is called and the optional has no value the value will be created. 111 // This allows the implementation to lazily create the locale. 112 // TODO FMT Validate whether lazy creation is the best solution. 113 optional<_VSTD::locale> __loc_; 114 115 template <class __OutIt, class __CharT> 116 friend _LIBCPP_HIDE_FROM_ABI basic_format_context<__OutIt, __CharT> 117 _VSTD::__format_context_create( 118 __OutIt, basic_format_args<basic_format_context<__OutIt, __CharT>>, 119 optional<_VSTD::locale>&&); 120 121 // Note: the Standard doesn't specify the required constructors. 122 _LIBCPP_HIDE_FROM_ABI 123 explicit basic_format_context(_OutIt __out_it, 124 basic_format_args<basic_format_context> __args, 125 optional<_VSTD::locale>&& __loc) 126 : __out_it_(_VSTD::move(__out_it)), __args_(__args), 127 __loc_(_VSTD::move(__loc)) {} 128 #else 129 template <class __OutIt, class __CharT> 130 friend _LIBCPP_HIDE_FROM_ABI basic_format_context<__OutIt, __CharT> 131 _VSTD::__format_context_create( 132 __OutIt, basic_format_args<basic_format_context<__OutIt, __CharT>>); 133 134 _LIBCPP_HIDE_FROM_ABI 135 explicit basic_format_context(_OutIt __out_it, 136 basic_format_args<basic_format_context> __args) 137 : __out_it_(_VSTD::move(__out_it)), __args_(__args) {} 138 #endif 139 }; 140 141 // TODO FMT Implement [format.context]/4 142 // [Note 1: For a given type charT, implementations are encouraged to provide a 143 // single instantiation of basic_format_context for appending to 144 // basic_string<charT>, vector<charT>, or any other container with contiguous 145 // storage by wrapping those in temporary objects with a uniform interface 146 // (such as a span<charT>) and polymorphic reallocation. - end note] 147 148 using format_context = basic_format_context<back_insert_iterator<string>, char>; 149 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 150 using wformat_context = basic_format_context<back_insert_iterator<wstring>, wchar_t>; 151 #endif 152 153 #endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) 154 155 #endif //_LIBCPP_STD_VER > 17 156 157 _LIBCPP_END_NAMESPACE_STD 158 159 _LIBCPP_POP_MACROS 160 161 #endif // _LIBCPP___FORMAT_FORMAT_CONTEXT_H 162