File indexing completed on 2026-05-03 08:13:30
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef _LIBCPP___CXX03___FORMAT_WRITE_ESCAPED_H
0011 #define _LIBCPP___CXX03___FORMAT_WRITE_ESCAPED_H
0012
0013 #include <__cxx03/__algorithm/ranges_copy.h>
0014 #include <__cxx03/__algorithm/ranges_for_each.h>
0015 #include <__cxx03/__charconv/to_chars_integral.h>
0016 #include <__cxx03/__charconv/to_chars_result.h>
0017 #include <__cxx03/__chrono/statically_widen.h>
0018 #include <__cxx03/__format/escaped_output_table.h>
0019 #include <__cxx03/__format/formatter_output.h>
0020 #include <__cxx03/__format/parser_std_format_spec.h>
0021 #include <__cxx03/__format/unicode.h>
0022 #include <__cxx03/__iterator/back_insert_iterator.h>
0023 #include <__cxx03/__memory/addressof.h>
0024 #include <__cxx03/__system_error/errc.h>
0025 #include <__cxx03/__type_traits/make_unsigned.h>
0026 #include <__cxx03/__utility/move.h>
0027 #include <__cxx03/string_view>
0028
0029 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0030 # pragma GCC system_header
0031 #endif
0032
0033 _LIBCPP_PUSH_MACROS
0034 #include <__cxx03/__undef_macros>
0035
0036 _LIBCPP_BEGIN_NAMESPACE_STD
0037
0038 namespace __formatter {
0039
0040 #if _LIBCPP_STD_VER >= 20
0041
0042
0043
0044
0045
0046 template <class _CharT>
0047 _LIBCPP_HIDE_FROM_ABI auto
0048 __write_string(basic_string_view<_CharT> __str,
0049 output_iterator<const _CharT&> auto __out_it,
0050 __format_spec::__parsed_specifications<_CharT> __specs) -> decltype(__out_it) {
0051 if (!__specs.__has_precision())
0052 return __formatter::__write_string_no_precision(__str, std::move(__out_it), __specs);
0053
0054 int __size = __formatter::__truncate(__str, __specs.__precision_);
0055
0056 return __formatter::__write(__str.begin(), __str.end(), std::move(__out_it), __specs, __size);
0057 }
0058
0059 #endif
0060 #if _LIBCPP_STD_VER >= 23
0061
0062 struct __nul_terminator {};
0063
0064 template <class _CharT>
0065 _LIBCPP_HIDE_FROM_ABI bool operator==(const _CharT* __cstr, __nul_terminator) {
0066 return *__cstr == _CharT('\0');
0067 }
0068
0069 template <class _CharT>
0070 _LIBCPP_HIDE_FROM_ABI void
0071 __write_escaped_code_unit(basic_string<_CharT>& __str, char32_t __value, const _CharT* __prefix) {
0072 back_insert_iterator __out_it{__str};
0073 std::ranges::copy(__prefix, __nul_terminator{}, __out_it);
0074
0075 char __buffer[8];
0076 to_chars_result __r = std::to_chars(std::begin(__buffer), std::end(__buffer), __value, 16);
0077 _LIBCPP_ASSERT_INTERNAL(__r.ec == errc(0), "Internal buffer too small");
0078 std::ranges::copy(std::begin(__buffer), __r.ptr, __out_it);
0079
0080 __str += _CharT('}');
0081 }
0082
0083
0084
0085
0086
0087
0088 template <class _CharT>
0089 _LIBCPP_HIDE_FROM_ABI void __write_well_formed_escaped_code_unit(basic_string<_CharT>& __str, char32_t __value) {
0090 __formatter::__write_escaped_code_unit(__str, __value, _LIBCPP_STATICALLY_WIDEN(_CharT, "\\u{"));
0091 }
0092
0093
0094
0095
0096
0097
0098 template <class _CharT>
0099 _LIBCPP_HIDE_FROM_ABI void __write_escape_ill_formed_code_unit(basic_string<_CharT>& __str, char32_t __value) {
0100 __formatter::__write_escaped_code_unit(__str, __value, _LIBCPP_STATICALLY_WIDEN(_CharT, "\\x{"));
0101 }
0102
0103 template <class _CharT>
0104 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool
0105 __is_escaped_sequence_written(basic_string<_CharT>& __str, bool __last_escaped, char32_t __value) {
0106 # ifdef _LIBCPP_HAS_NO_UNICODE
0107
0108 if (__value > 127)
0109 return false;
0110 # endif
0111
0112
0113
0114
0115
0116 if (!__escaped_output_table::__needs_escape(__value))
0117
0118
0119
0120
0121
0122 if (!__last_escaped || __extended_grapheme_custer_property_boundary::__get_property(__value) !=
0123 __extended_grapheme_custer_property_boundary::__property::__Extend)
0124 return false;
0125
0126 __formatter::__write_well_formed_escaped_code_unit(__str, __value);
0127 return true;
0128 }
0129
0130 template <class _CharT>
0131 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr char32_t __to_char32(_CharT __value) {
0132 return static_cast<make_unsigned_t<_CharT>>(__value);
0133 }
0134
0135 enum class __escape_quotation_mark { __apostrophe, __double_quote };
0136
0137
0138 template <class _CharT>
0139 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool __is_escaped_sequence_written(
0140 basic_string<_CharT>& __str, char32_t __value, bool __last_escaped, __escape_quotation_mark __mark) {
0141
0142 switch (__value) {
0143 case _CharT('\t'):
0144 __str += _LIBCPP_STATICALLY_WIDEN(_CharT, "\\t");
0145 return true;
0146 case _CharT('\n'):
0147 __str += _LIBCPP_STATICALLY_WIDEN(_CharT, "\\n");
0148 return true;
0149 case _CharT('\r'):
0150 __str += _LIBCPP_STATICALLY_WIDEN(_CharT, "\\r");
0151 return true;
0152 case _CharT('\''):
0153 if (__mark == __escape_quotation_mark::__apostrophe)
0154 __str += _LIBCPP_STATICALLY_WIDEN(_CharT, R"(\')");
0155 else
0156 __str += __value;
0157 return true;
0158 case _CharT('"'):
0159 if (__mark == __escape_quotation_mark::__double_quote)
0160 __str += _LIBCPP_STATICALLY_WIDEN(_CharT, R"(\")");
0161 else
0162 __str += __value;
0163 return true;
0164 case _CharT('\\'):
0165 __str += _LIBCPP_STATICALLY_WIDEN(_CharT, R"(\\)");
0166 return true;
0167
0168
0169 case _CharT(' '):
0170 __str += __value;
0171 return true;
0172 }
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182 return __formatter::__is_escaped_sequence_written(__str, __last_escaped, __formatter::__to_char32(__value));
0183 }
0184
0185 template <class _CharT>
0186 _LIBCPP_HIDE_FROM_ABI void
0187 __escape(basic_string<_CharT>& __str, basic_string_view<_CharT> __values, __escape_quotation_mark __mark) {
0188 __unicode::__code_point_view<_CharT> __view{__values.begin(), __values.end()};
0189
0190
0191
0192 bool __escape = true;
0193 while (!__view.__at_end()) {
0194 auto __first = __view.__position();
0195 typename __unicode::__consume_result __result = __view.__consume();
0196 if (__result.__status == __unicode::__consume_result::__ok) {
0197 __escape = __formatter::__is_escaped_sequence_written(__str, __result.__code_point, __escape, __mark);
0198 if (!__escape)
0199
0200 ranges::copy(__first, __view.__position(), std::back_insert_iterator(__str));
0201 } else {
0202
0203 ranges::for_each(__first, __view.__position(), [&](_CharT __value) {
0204 __formatter::__write_escape_ill_formed_code_unit(__str, __formatter::__to_char32(__value));
0205 });
0206 }
0207 }
0208 }
0209
0210 template <class _CharT>
0211 _LIBCPP_HIDE_FROM_ABI auto
0212 __format_escaped_char(_CharT __value,
0213 output_iterator<const _CharT&> auto __out_it,
0214 __format_spec::__parsed_specifications<_CharT> __specs) -> decltype(__out_it) {
0215 basic_string<_CharT> __str;
0216 __str += _CharT('\'');
0217 __formatter::__escape(__str, basic_string_view{std::addressof(__value), 1}, __escape_quotation_mark::__apostrophe);
0218 __str += _CharT('\'');
0219 return __formatter::__write(__str.data(), __str.data() + __str.size(), std::move(__out_it), __specs, __str.size());
0220 }
0221
0222 template <class _CharT>
0223 _LIBCPP_HIDE_FROM_ABI auto
0224 __format_escaped_string(basic_string_view<_CharT> __values,
0225 output_iterator<const _CharT&> auto __out_it,
0226 __format_spec::__parsed_specifications<_CharT> __specs) -> decltype(__out_it) {
0227 basic_string<_CharT> __str;
0228 __str += _CharT('"');
0229 __formatter::__escape(__str, __values, __escape_quotation_mark::__double_quote);
0230 __str += _CharT('"');
0231 return __formatter::__write_string(basic_string_view{__str}, std::move(__out_it), __specs);
0232 }
0233
0234 #endif
0235
0236 }
0237
0238 _LIBCPP_END_NAMESPACE_STD
0239
0240 _LIBCPP_POP_MACROS
0241
0242 #endif