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