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/buffer.h> 16 #include <__format/format_args.h> 17 #include <__format/format_fwd.h> 18 #include <__iterator/back_insert_iterator.h> 19 #include <__iterator/concepts.h> 20 #include <__utility/move.h> 21 #include <concepts> 22 #include <cstddef> 23 24 #ifndef _LIBCPP_HAS_NO_LOCALIZATION 25 #include <locale> 26 #include <optional> 27 #endif 28 29 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 30 # pragma GCC system_header 31 #endif 32 33 _LIBCPP_BEGIN_NAMESPACE_STD 34 35 #if _LIBCPP_STD_VER > 17 36 37 template <class _OutIt, class _CharT> 38 requires output_iterator<_OutIt, const _CharT&> 39 class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT basic_format_context; 40 41 #ifndef _LIBCPP_HAS_NO_LOCALIZATION 42 /** 43 * Helper to create a basic_format_context. 44 * 45 * This is needed since the constructor is private. 46 */ 47 template <class _OutIt, class _CharT> 48 _LIBCPP_HIDE_FROM_ABI basic_format_context<_OutIt, _CharT> 49 __format_context_create( 50 _OutIt __out_it, 51 basic_format_args<basic_format_context<_OutIt, _CharT>> __args, 52 optional<_VSTD::locale>&& __loc = nullopt) { 53 return _VSTD::basic_format_context(_VSTD::move(__out_it), __args, 54 _VSTD::move(__loc)); 55 } 56 #else 57 template <class _OutIt, class _CharT> 58 _LIBCPP_HIDE_FROM_ABI basic_format_context<_OutIt, _CharT> 59 __format_context_create( 60 _OutIt __out_it, 61 basic_format_args<basic_format_context<_OutIt, _CharT>> __args) { 62 return _VSTD::basic_format_context(_VSTD::move(__out_it), __args); 63 } 64 #endif 65 66 using format_context = 67 basic_format_context<back_insert_iterator<__format::__output_buffer<char>>, 68 char>; 69 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 70 using wformat_context = basic_format_context< 71 back_insert_iterator<__format::__output_buffer<wchar_t>>, wchar_t>; 72 #endif 73 74 template <class _OutIt, class _CharT> 75 requires output_iterator<_OutIt, const _CharT&> 76 class 77 // clang-format off 78 _LIBCPP_TEMPLATE_VIS 79 _LIBCPP_AVAILABILITY_FORMAT 80 _LIBCPP_PREFERRED_NAME(format_context) 81 _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wformat_context)) 82 // clang-format on 83 basic_format_context { 84 public: 85 using iterator = _OutIt; 86 using char_type = _CharT; 87 template <class _Tp> 88 using formatter_type = formatter<_Tp, _CharT>; 89 90 basic_format_context(const basic_format_context&) = delete; 91 basic_format_context& operator=(const basic_format_context&) = delete; 92 93 _LIBCPP_HIDE_FROM_ABI basic_format_arg<basic_format_context> 94 arg(size_t __id) const noexcept { 95 return __args_.get(__id); 96 } 97 #ifndef _LIBCPP_HAS_NO_LOCALIZATION 98 _LIBCPP_HIDE_FROM_ABI _VSTD::locale locale() { 99 if (!__loc_) 100 __loc_ = _VSTD::locale{}; 101 return *__loc_; 102 } 103 #endif 104 _LIBCPP_HIDE_FROM_ABI iterator out() { return __out_it_; } 105 _LIBCPP_HIDE_FROM_ABI void advance_to(iterator __it) { __out_it_ = __it; } 106 107 private: 108 iterator __out_it_; 109 basic_format_args<basic_format_context> __args_; 110 #ifndef _LIBCPP_HAS_NO_LOCALIZATION 111 112 // The Standard doesn't specify how the locale is stored. 113 // [format.context]/6 114 // std::locale locale(); 115 // Returns: The locale passed to the formatting function if the latter 116 // takes one, and std::locale() otherwise. 117 // This is done by storing the locale of the constructor in this optional. If 118 // locale() is called and the optional has no value the value will be created. 119 // This allows the implementation to lazily create the locale. 120 // TODO FMT Validate whether lazy creation is the best solution. 121 optional<_VSTD::locale> __loc_; 122 123 template <class __OutIt, class __CharT> 124 friend _LIBCPP_HIDE_FROM_ABI basic_format_context<__OutIt, __CharT> 125 __format_context_create(__OutIt, basic_format_args<basic_format_context<__OutIt, __CharT>>, 126 optional<_VSTD::locale>&&); 127 128 // Note: the Standard doesn't specify the required constructors. 129 _LIBCPP_HIDE_FROM_ABI 130 explicit basic_format_context(_OutIt __out_it, 131 basic_format_args<basic_format_context> __args, 132 optional<_VSTD::locale>&& __loc) 133 : __out_it_(_VSTD::move(__out_it)), __args_(__args), 134 __loc_(_VSTD::move(__loc)) {} 135 #else 136 template <class __OutIt, class __CharT> 137 friend _LIBCPP_HIDE_FROM_ABI basic_format_context<__OutIt, __CharT> 138 __format_context_create(__OutIt, basic_format_args<basic_format_context<__OutIt, __CharT>>); 139 140 _LIBCPP_HIDE_FROM_ABI 141 explicit basic_format_context(_OutIt __out_it, 142 basic_format_args<basic_format_context> __args) 143 : __out_it_(_VSTD::move(__out_it)), __args_(__args) {} 144 #endif 145 }; 146 147 #endif //_LIBCPP_STD_VER > 17 148 149 _LIBCPP_END_NAMESPACE_STD 150 151 #endif // _LIBCPP___FORMAT_FORMAT_CONTEXT_H 152