diff --git a/libcxx/include/__filesystem/path.h b/libcxx/include/__filesystem/path.h --- a/libcxx/include/__filesystem/path.h +++ b/libcxx/include/__filesystem/path.h @@ -968,7 +968,7 @@ _LIBCPP_INLINE_VISIBILITY friend basic_istream<_CharT, _Traits>& operator>>(basic_istream<_CharT, _Traits>& __is, path& __p) { basic_string<_CharT, _Traits> __tmp; - __is >> __quoted(__tmp); + __is >> _VSTD::__quoted(__tmp); __p = __tmp; return __is; } diff --git a/libcxx/include/__string b/libcxx/include/__string --- a/libcxx/include/__string +++ b/libcxx/include/__string @@ -1155,19 +1155,6 @@ return __murmur2_or_cityhash()(__p, (__e-__p)*sizeof(value_type)); } -template > -struct __quoted_output_proxy -{ - _Iter __first; - _Iter __last; - _CharT __delim; - _CharT __escape; - - explicit __quoted_output_proxy(_Iter __f, _Iter __l, _CharT __d, _CharT __e) - : __first(__f), __last(__l), __delim(__d), __escape(__e) {} - // This would be a nice place for a string_ref -}; - _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS diff --git a/libcxx/include/iomanip b/libcxx/include/iomanip --- a/libcxx/include/iomanip +++ b/libcxx/include/iomanip @@ -513,157 +513,151 @@ return __iom_t10<_CharT>(__tm, __fmt); } -template -basic_ostream<_CharT, _Traits> & -__quoted_output ( basic_ostream<_CharT, _Traits> &__os, - _ForwardIterator __first, _ForwardIterator __last, _CharT __delim, _CharT __escape ) +#if _LIBCPP_STD_VER >= 11 + +template +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& +__quoted_output(basic_ostream<_CharT, _Traits>& __os, + const _CharT *__first, const _CharT *__last, _CharT __delim, _CharT __escape) { basic_string<_CharT, _Traits> __str; __str.push_back(__delim); - for ( ; __first != __last; ++ __first ) + for ( ; __first != __last; ++__first) { - if (_Traits::eq (*__first, __escape) || _Traits::eq (*__first, __delim)) + if (_Traits::eq(*__first, __escape) || _Traits::eq(*__first, __delim)) __str.push_back(__escape); __str.push_back(*__first); } __str.push_back(__delim); - return _VSTD::__put_character_sequence(__os, __str.data(), __str.size()); + return std::__put_character_sequence(__os, __str.data(), __str.size()); } template -basic_istream<_CharT, _Traits> & -__quoted_input ( basic_istream<_CharT, _Traits> &__is, _String & __string, _CharT __delim, _CharT __escape ) +_LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>& +__quoted_input(basic_istream<_CharT, _Traits>& __is, _String& __string, _CharT __delim, _CharT __escape) { - __string.clear (); + __string.clear(); _CharT __c; __is >> __c; - if ( __is.fail ()) + if (__is.fail()) return __is; - if (!_Traits::eq (__c, __delim)) // no delimiter, read the whole string + if (!_Traits::eq(__c, __delim)) // no delimiter, read the whole string { - __is.unget (); + __is.unget(); __is >> __string; return __is; } - __save_flags<_CharT, _Traits> sf(__is); - noskipws (__is); - while (true) - { + __save_flags<_CharT, _Traits> __sf(__is); + std::noskipws(__is); + while (true) { __is >> __c; - if ( __is.fail ()) + if (__is.fail()) break; - if (_Traits::eq (__c, __escape)) - { + if (_Traits::eq(__c, __delim)) + break; + if (_Traits::eq(__c, __escape)) { __is >> __c; - if ( __is.fail ()) + if (__is.fail()) break; } - else if (_Traits::eq (__c, __delim)) - break; - __string.push_back ( __c ); - } + __string.push_back(__c); + } return __is; } - -template -basic_ostream<_CharT, _Traits>& operator<<( - basic_ostream<_CharT, _Traits>& __os, - const __quoted_output_proxy<_CharT, _Iter, _Traits> & __proxy) +template +struct _LIBCPP_HIDDEN __quoted_output_proxy { - return __quoted_output(__os, __proxy.__first, __proxy.__last, __proxy.__delim, __proxy.__escape); -} + const _CharT *__first_; + const _CharT *__last_; + _CharT __delim_; + _CharT __escape_; -template -struct __quoted_proxy -{ - basic_string<_CharT, _Traits, _Allocator> &__string; - _CharT __delim; - _CharT __escape; + _LIBCPP_HIDE_FROM_ABI + explicit __quoted_output_proxy(const _CharT *__f, const _CharT *__l, _CharT __d, _CharT __e) + : __first_(__f), __last_(__l), __delim_(__d), __escape_(__e) {} - explicit __quoted_proxy(basic_string<_CharT, _Traits, _Allocator> &__s, _CharT __d, _CharT __e) - : __string(__s), __delim(__d), __escape(__e) {} + template::value || _IsSame<_Traits, _T2>::value>* = nullptr> + friend _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _T2>& + operator<<(basic_ostream<_CharT, _T2>& __os, const __quoted_output_proxy& __p) { + return std::__quoted_output(__os, __p.__first_, __p.__last_, __p.__delim_, __p.__escape_); + } }; template -_LIBCPP_INLINE_VISIBILITY -basic_ostream<_CharT, _Traits>& operator<<( - basic_ostream<_CharT, _Traits>& __os, - const __quoted_proxy<_CharT, _Traits, _Allocator> & __proxy) -{ - return __quoted_output (__os, __proxy.__string.cbegin (), __proxy.__string.cend (), __proxy.__delim, __proxy.__escape); -} - -// extractor for non-const basic_string& proxies -template -_LIBCPP_INLINE_VISIBILITY -basic_istream<_CharT, _Traits>& operator>>( - basic_istream<_CharT, _Traits>& __is, - const __quoted_proxy<_CharT, _Traits, _Allocator> & __proxy) +struct _LIBCPP_HIDDEN __quoted_proxy { - return __quoted_input ( __is, __proxy.__string, __proxy.__delim, __proxy.__escape ); -} + basic_string<_CharT, _Traits, _Allocator>& __string_; + _CharT __delim_; + _CharT __escape_; + _LIBCPP_HIDE_FROM_ABI + explicit __quoted_proxy(basic_string<_CharT, _Traits, _Allocator>& __s, _CharT __d, _CharT __e) + : __string_(__s), __delim_(__d), __escape_(__e) {} -template -_LIBCPP_INLINE_VISIBILITY -__quoted_output_proxy<_CharT, const _CharT *> -quoted ( const _CharT *__s, _CharT __delim = _CharT('"'), _CharT __escape =_CharT('\\')) -{ - const _CharT *__end = __s; - while ( *__end ) ++__end; - return __quoted_output_proxy<_CharT, const _CharT *> ( __s, __end, __delim, __escape ); -} + friend _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& + operator<<(basic_ostream<_CharT, _Traits>& __os, const __quoted_proxy& __p) { + return std::__quoted_output(__os, __p.__string_.data(), __p.__string_.data() + __p.__string_.size(), __p.__delim_, __p.__escape_); + } + friend _LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>& + operator>>(basic_istream<_CharT, _Traits>& __is, const __quoted_proxy& __p) { + return std::__quoted_input(__is, __p.__string_, __p.__delim_, __p.__escape_); + } +}; template -_LIBCPP_INLINE_VISIBILITY -__quoted_output_proxy<_CharT, typename basic_string <_CharT, _Traits, _Allocator>::const_iterator> -__quoted ( const basic_string <_CharT, _Traits, _Allocator> &__s, _CharT __delim = _CharT('"'), _CharT __escape=_CharT('\\')) +_LIBCPP_HIDE_FROM_ABI +__quoted_output_proxy<_CharT, _Traits> +__quoted(const basic_string<_CharT, _Traits, _Allocator>& __s, _CharT __delim = _CharT('"'), _CharT __escape = _CharT('\\')) { - return __quoted_output_proxy<_CharT, - typename basic_string <_CharT, _Traits, _Allocator>::const_iterator> - ( __s.cbegin(), __s.cend (), __delim, __escape ); + return __quoted_output_proxy<_CharT, _Traits>(__s.data(), __s.data() + __s.size(), __delim, __escape); } template -_LIBCPP_INLINE_VISIBILITY +_LIBCPP_HIDE_FROM_ABI __quoted_proxy<_CharT, _Traits, _Allocator> -__quoted ( basic_string <_CharT, _Traits, _Allocator> &__s, _CharT __delim = _CharT('"'), _CharT __escape=_CharT('\\')) +__quoted(basic_string<_CharT, _Traits, _Allocator>& __s, _CharT __delim = _CharT('"'), _CharT __escape = _CharT('\\')) { - return __quoted_proxy<_CharT, _Traits, _Allocator>( __s, __delim, __escape ); + return __quoted_proxy<_CharT, _Traits, _Allocator>(__s, __delim, __escape); } +#endif // _LIBCPP_STD_VER >= 11 #if _LIBCPP_STD_VER > 11 +template +_LIBCPP_HIDE_FROM_ABI +auto quoted(const _CharT *__s, _CharT __delim = _CharT('"'), _CharT __escape = _CharT('\\')) +{ + const _CharT *__end = __s; + while (*__end) ++__end; + return __quoted_output_proxy<_CharT, void>(__s, __end, __delim, __escape); +} + template -_LIBCPP_INLINE_VISIBILITY -__quoted_output_proxy<_CharT, typename basic_string <_CharT, _Traits, _Allocator>::const_iterator> -quoted ( const basic_string <_CharT, _Traits, _Allocator> &__s, _CharT __delim = _CharT('"'), _CharT __escape=_CharT('\\')) +_LIBCPP_HIDE_FROM_ABI +auto quoted(const basic_string<_CharT, _Traits, _Allocator>& __s, _CharT __delim = _CharT('"'), _CharT __escape = _CharT('\\')) { - return __quoted(__s, __delim, __escape); + return __quoted_output_proxy<_CharT, _Traits>(__s.data(), __s.data() + __s.size(), __delim, __escape); } template -_LIBCPP_INLINE_VISIBILITY -__quoted_proxy<_CharT, _Traits, _Allocator> -quoted ( basic_string <_CharT, _Traits, _Allocator> &__s, _CharT __delim = _CharT('"'), _CharT __escape=_CharT('\\')) +_LIBCPP_HIDE_FROM_ABI +auto quoted(basic_string<_CharT, _Traits, _Allocator>& __s, _CharT __delim = _CharT('"'), _CharT __escape = _CharT('\\')) { - return __quoted(__s, __delim, __escape); + return __quoted_proxy<_CharT, _Traits, _Allocator>(__s, __delim, __escape); } template -__quoted_output_proxy<_CharT, const _CharT *, _Traits> -quoted (basic_string_view <_CharT, _Traits> __sv, - _CharT __delim = _CharT('"'), _CharT __escape=_CharT('\\')) +auto quoted(basic_string_view<_CharT, _Traits> __sv, _CharT __delim = _CharT('"'), _CharT __escape = _CharT('\\')) { - return __quoted_output_proxy<_CharT, const _CharT *, _Traits> - ( __sv.data(), __sv.data() + __sv.size(), __delim, __escape ); + return __quoted_output_proxy<_CharT, _Traits>(__sv.data(), __sv.data() + __sv.size(), __delim, __escape); } -#endif + +#endif // _LIBCPP_STD_VER > 11 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/test/std/input.output/iostream.format/quoted.manip/quoted_traits.compile.pass.cpp b/libcxx/test/std/input.output/iostream.format/quoted.manip/quoted_traits.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/input.output/iostream.format/quoted.manip/quoted_traits.compile.pass.cpp @@ -0,0 +1,162 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11 + +// + +// quoted + +#include +#include +#include +#include +#include +#include + +#include "test_allocator.h" +#include "test_macros.h" + +template +decltype(std::declval() >> std::declval(), std::true_type()) +has_rightshift_impl(int) { return std::true_type(); } + +template +std::false_type +has_rightshift_impl(long) { return std::false_type(); } + +template +struct HasRightShift : decltype(has_rightshift_impl(0)) {}; + +template +decltype(std::declval() << std::declval(), std::true_type()) +has_leftshift_impl(int) { return std::true_type(); } + +template +std::false_type +has_leftshift_impl(long) { return std::false_type(); } + +template +struct HasLeftShift : decltype(has_leftshift_impl(0)) {}; + +template +struct FakeCharTraits : std::char_traits {}; + +void test_string_literal() +{ + using Q = decltype(std::quoted("hello")); + static_assert( HasLeftShift::value, ""); + static_assert(!HasRightShift::value, ""); + static_assert( HasLeftShift>&, Q>::value, ""); + static_assert(!HasRightShift>&, Q>::value, ""); + +#ifndef TEST_HAS_NO_WCHAR_T + using WQ = decltype(std::quoted(L"hello")); + static_assert( HasLeftShift::value, ""); + static_assert(!HasRightShift::value, ""); + static_assert( HasLeftShift>&, WQ>::value, ""); + static_assert(!HasRightShift>&, WQ>::value, ""); + + static_assert(!HasLeftShift::value, ""); + static_assert(!HasLeftShift::value, ""); +#endif // TEST_HAS_NO_WCHAR_T +} + +void test_std_string() +{ + std::string s = "hello"; + const auto& cs = s; + using Q = decltype(std::quoted(s)); + using CQ = decltype(std::quoted(cs)); + static_assert( HasLeftShift::value, ""); + static_assert( HasRightShift::value, ""); + static_assert( HasLeftShift::value, ""); + static_assert(!HasRightShift::value, ""); + static_assert(!HasLeftShift>&, Q>::value, ""); + static_assert(!HasRightShift>&, Q>::value, ""); + static_assert(!HasLeftShift>&, CQ>::value, ""); + static_assert(!HasRightShift>&, CQ>::value, ""); + + std::basic_string, test_allocator> st = "hello"; + const auto& cst = st; + using QT = decltype(std::quoted(st)); + using CQT = decltype(std::quoted(cst)); + static_assert(!HasLeftShift::value, ""); + static_assert(!HasRightShift::value, ""); + static_assert(!HasLeftShift::value, ""); + static_assert(!HasRightShift::value, ""); + static_assert( HasLeftShift>&, QT>::value, ""); + static_assert( HasRightShift>&, QT>::value, ""); + static_assert( HasLeftShift>&, CQT>::value, ""); + static_assert(!HasRightShift>&, CQT>::value, ""); + +#ifndef TEST_HAS_NO_WCHAR_T + std::wstring ws = L"hello"; + const auto& cws = ws; + using WQ = decltype(std::quoted(ws)); + using CWQ = decltype(std::quoted(cws)); + static_assert( HasLeftShift::value, ""); + static_assert( HasRightShift::value, ""); + static_assert( HasLeftShift::value, ""); + static_assert(!HasRightShift::value, ""); + static_assert(!HasLeftShift>&, WQ>::value, ""); + static_assert(!HasRightShift>&, WQ>::value, ""); + static_assert(!HasLeftShift>&, CWQ>::value, ""); + static_assert(!HasRightShift>&, CWQ>::value, ""); + + static_assert(!HasLeftShift::value, ""); + static_assert(!HasLeftShift::value, ""); +#endif // TEST_HAS_NO_WCHAR_T +} + +void test_std_string_view() +{ + std::string_view s = "hello"; + const auto& cs = s; + using Q = decltype(std::quoted(s)); + using CQ = decltype(std::quoted(cs)); + static_assert( HasLeftShift::value, ""); + static_assert(!HasRightShift::value, ""); + static_assert( HasLeftShift::value, ""); + static_assert(!HasRightShift::value, ""); + static_assert(!HasLeftShift>&, Q>::value, ""); + static_assert(!HasRightShift>&, Q>::value, ""); + static_assert(!HasLeftShift>&, CQ>::value, ""); + static_assert(!HasRightShift>&, CQ>::value, ""); + + std::basic_string_view> st = "hello"; + const auto& cst = st; + using QT = decltype(std::quoted(st)); + using CQT = decltype(std::quoted(cst)); + static_assert(!HasLeftShift::value, ""); + static_assert(!HasRightShift::value, ""); + static_assert(!HasLeftShift::value, ""); + static_assert(!HasRightShift::value, ""); + static_assert( HasLeftShift>&, QT>::value, ""); + static_assert(!HasRightShift>&, QT>::value, ""); + static_assert( HasLeftShift>&, CQT>::value, ""); + static_assert(!HasRightShift>&, CQT>::value, ""); + +#ifndef TEST_HAS_NO_WCHAR_T + std::wstring_view ws = L"hello"; + const auto& cws = ws; + using WQ = decltype(std::quoted(ws)); + using CWQ = decltype(std::quoted(cws)); + static_assert( HasLeftShift::value, ""); + static_assert(!HasRightShift::value, ""); + static_assert( HasLeftShift::value, ""); + static_assert(!HasRightShift::value, ""); + static_assert(!HasLeftShift>&, WQ>::value, ""); + static_assert(!HasRightShift>&, WQ>::value, ""); + static_assert(!HasLeftShift>&, CWQ>::value, ""); + static_assert(!HasRightShift>&, CWQ>::value, ""); + + static_assert(!HasLeftShift::value, ""); + static_assert(!HasLeftShift::value, ""); +#endif // TEST_HAS_NO_WCHAR_T +}