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_FORMATTER_STRING_H 11 #define _LIBCPP___FORMAT_FORMATTER_STRING_H 12 13 #include <__config> 14 #include <__format/format_error.h> 15 #include <__format/format_fwd.h> 16 #include <__format/format_string.h> 17 #include <__format/formatter.h> 18 #include <__format/parser_std_format_spec.h> 19 #include <algorithm> 20 #include <string_view> 21 22 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 23 #pragma GCC system_header 24 #endif 25 26 _LIBCPP_PUSH_MACROS 27 #include <__undef_macros> 28 29 _LIBCPP_BEGIN_NAMESPACE_STD 30 31 #if _LIBCPP_STD_VER > 17 32 33 // TODO FMT Remove this once we require compilers with proper C++20 support. 34 // If the compiler has no concepts support, the format header will be disabled. 35 // Without concepts support enable_if needs to be used and that too much effort 36 // to support compilers with partial C++20 support. 37 #if !defined(_LIBCPP_HAS_NO_CONCEPTS) 38 39 namespace __format_spec { 40 41 template <__formatter::__char_type _CharT> 42 class _LIBCPP_TEMPLATE_VIS __formatter_string : public __parser_string<_CharT> { 43 public: 44 _LIBCPP_HIDE_FROM_ABI auto format(basic_string_view<_CharT> __str, 45 auto& __ctx) -> decltype(__ctx.out()) { 46 47 _LIBCPP_ASSERT(this->__alignment != _Flags::_Alignment::__default, 48 "The parser should not use these defaults"); 49 50 if (this->__width_needs_substitution()) 51 this->__substitute_width_arg_id(__ctx.arg(this->__width)); 52 53 if (this->__precision_needs_substitution()) 54 this->__substitute_precision_arg_id(__ctx.arg(this->__precision)); 55 56 return __formatter::__write_unicode( 57 __ctx.out(), __str, this->__width, 58 this->__has_precision_field() ? this->__precision : -1, this->__fill, 59 this->__alignment); 60 } 61 }; 62 63 } //namespace __format_spec 64 65 // [format.formatter.spec]/2.2 For each charT, the string type specializations 66 67 // Formatter const char*. 68 template <class _CharT> 69 struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT 70 formatter<const _CharT*, _CharT> 71 : public __format_spec::__formatter_string<_CharT> { 72 using _Base = __format_spec::__formatter_string<_CharT>; 73 74 _LIBCPP_HIDE_FROM_ABI auto format(const _CharT* __str, auto& __ctx) 75 -> decltype(__ctx.out()) { 76 _LIBCPP_ASSERT(__str, "The basic_format_arg constructor should have " 77 "prevented an invalid pointer."); 78 79 // When using a center or right alignment and the width option the length 80 // of __str must be known to add the padding upfront. This case is handled 81 // by the base class by converting the argument to a basic_string_view. 82 // 83 // When using left alignment and the width option the padding is added 84 // after outputting __str so the length can be determined while outputting 85 // __str. The same holds true for the precision, during outputting __str it 86 // can be validated whether the precision threshold has been reached. For 87 // now these optimizations aren't implemented. Instead the base class 88 // handles these options. 89 // TODO FMT Implement these improvements. 90 if (this->__has_width_field() || this->__has_precision_field()) 91 return _Base::format(__str, __ctx); 92 93 // No formatting required, copy the string to the output. 94 auto __out_it = __ctx.out(); 95 while (*__str) 96 *__out_it++ = *__str++; 97 return __out_it; 98 } 99 }; 100 101 // Formatter char*. 102 template <class _CharT> 103 struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT 104 formatter<_CharT*, _CharT> : public formatter<const _CharT*, _CharT> { 105 using _Base = formatter<const _CharT*, _CharT>; 106 107 _LIBCPP_HIDE_FROM_ABI auto format(_CharT* __str, auto& __ctx) 108 -> decltype(__ctx.out()) { 109 return _Base::format(__str, __ctx); 110 } 111 }; 112 113 // Formatter const char[]. 114 template <class _CharT, size_t _Size> 115 struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT 116 formatter<const _CharT[_Size], _CharT> 117 : public __format_spec::__formatter_string<_CharT> { 118 using _Base = __format_spec::__formatter_string<_CharT>; 119 120 _LIBCPP_HIDE_FROM_ABI auto format(const _CharT __str[_Size], auto& __ctx) 121 -> decltype(__ctx.out()) { 122 return _Base::format(_VSTD::basic_string_view<_CharT>(__str, _Size), __ctx); 123 } 124 }; 125 126 // Formatter std::string. 127 template <class _CharT, class _Traits, class _Allocator> 128 struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT 129 formatter<basic_string<_CharT, _Traits, _Allocator>, _CharT> 130 : public __format_spec::__formatter_string<_CharT> { 131 using _Base = __format_spec::__formatter_string<_CharT>; 132 133 _LIBCPP_HIDE_FROM_ABI auto 134 format(const basic_string<_CharT, _Traits, _Allocator>& __str, auto& __ctx) 135 -> decltype(__ctx.out()) { 136 return _Base::format(_VSTD::basic_string_view<_CharT>(__str), __ctx); 137 } 138 }; 139 140 // Formatter std::string_view. 141 template <class _CharT, class _Traits> 142 struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT 143 formatter<basic_string_view<_CharT, _Traits>, _CharT> 144 : public __format_spec::__formatter_string<_CharT> {}; 145 146 #endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) 147 148 #endif //_LIBCPP_STD_VER > 17 149 150 _LIBCPP_END_NAMESPACE_STD 151 152 _LIBCPP_POP_MACROS 153 154 #endif // _LIBCPP___FORMAT_FORMATTER_STRING_H 155