diff options
author | Marshall Clow <mclow.lists@gmail.com> | 2013-09-05 04:48:45 +0000 |
---|---|---|
committer | Marshall Clow <mclow.lists@gmail.com> | 2013-09-05 04:48:45 +0000 |
commit | ef44edfde470d2f03f6cd808a139f2feafbedee4 (patch) | |
tree | 55703bed679bb34e6d48f2b0fd4c27ecc6b289df | |
parent | fc09df0fe95d273b8be9e3916c2aab6e5c2f4cf2 (diff) | |
download | bcm5719-llvm-ef44edfde470d2f03f6cd808a139f2feafbedee4.tar.gz bcm5719-llvm-ef44edfde470d2f03f6cd808a139f2feafbedee4.zip |
N3545: Quoted strings
llvm-svn: 190032
5 files changed, 418 insertions, 1 deletions
diff --git a/libcxx/include/iomanip b/libcxx/include/iomanip index 0c58e1980f3..cdb0d5f0dbf 100644 --- a/libcxx/include/iomanip +++ b/libcxx/include/iomanip @@ -26,6 +26,17 @@ template <class charT, class moneyT> T8 put_money(const moneyT& mon, bool intl = template <class charT> T9 get_time(struct tm* tmb, const charT* fmt); template <class charT> T10 put_time(const struct tm* tmb, const charT* fmt); +template <class charT> + T11 quoted(const charT* s, charT delim=charT('"'), charT escape=charT('\\')); // C++14 + +template <class charT, class traits, class Allocator> + T12 quoted(const basic_string<charT, traits, Allocator>& s, + charT delim=charT('"'), charT escape=charT('\\')); // C++14 + +template <class charT, class traits, class Allocator> + T13 quoted(basic_string<charT, traits, Allocator>& s, + charT delim=charT('"'), charT escape=charT('\\')); // C++14 + } // std */ @@ -499,6 +510,142 @@ put_time(const tm* __tm, const _CharT* __fmt) return __iom_t10<_CharT>(__tm, __fmt); } +#if _LIBCPP_STD_VER > 11 + +template <class _CharT, class _Traits, class _ForwardIterator> +std::basic_ostream<_CharT, _Traits> & +__quoted_output ( basic_ostream<_CharT, _Traits> &__os, + _ForwardIterator __first, _ForwardIterator __last, _CharT __delim, _CharT __escape ) +{ + __os << __delim; + for ( ; __first != __last; ++ __first ) + { + if (_Traits::eq (*__first, __escape) || _Traits::eq (*__first, __delim)) + __os << __escape; + __os << *__first; + } + __os << __delim; + return __os; +} + +template <class _CharT, class _Traits, class _String> +basic_istream<_CharT, _Traits> & +__quoted_input ( basic_istream<_CharT, _Traits> &__is, _String & __string, _CharT __delim, _CharT __escape ) +{ + __string.clear (); + _CharT __c; + __is >> __c; + if ( __is.fail ()) + return __is; + + if (!_Traits::eq (__c, __delim)) // no delimiter, read the whole string + { + __is.unget (); + __is >> __string; + return __is; + } + + __save_flags<_CharT, _Traits> sf(__is); + noskipws (__is); + while (true) + { + __is >> __c; + if ( __is.fail ()) + break; + if (_Traits::eq (__c, __escape)) + { + __is >> __c; + if ( __is.fail ()) + break; + } + else if (_Traits::eq (__c, __delim)) + break; + __string.push_back ( __c ); + } + return __is; +} + + +template <class _CharT, class _Iter, class _Traits=char_traits<_CharT>> +struct __quoted_output_proxy +{ + _Iter __first; + _Iter __last; + _CharT __delim; + _CharT __escape; + + __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 +}; + +template <class _CharT, class _Traits, class _Iter> +basic_ostream<_CharT, _Traits>& operator<<( + basic_ostream<_CharT, _Traits>& __os, + const __quoted_output_proxy<_CharT, _Iter, _Traits> & __proxy) +{ + return __quoted_output (__os, __proxy.__first, __proxy.__last, __proxy.__delim, __proxy.__escape); +} + +template <class _CharT, class _Traits, class _Allocator> +struct __quoted_proxy +{ + basic_string<_CharT, _Traits, _Allocator> &__string; + _CharT __delim; + _CharT __escape; + + __quoted_proxy(basic_string<_CharT, _Traits, _Allocator> &__s, _CharT __d, _CharT __e) + : __string(__s), __delim(__d), __escape(__e) {} +}; + +template <class _CharT, class _Traits, class _Allocator> +_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 <class _CharT, class _Traits, class _Allocator> +_LIBCPP_INLINE_VISIBILITY +basic_istream<_CharT, _Traits>& operator>>( + basic_istream<_CharT, _Traits>& __is, + const __quoted_proxy<_CharT, _Traits, _Allocator> & __proxy) +{ + return __quoted_input ( __is, __proxy.__string, __proxy.__delim, __proxy.__escape ); +} + + +template <class _CharT> +_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 ); +} + +template <class _CharT, class _Traits, class _Allocator> +_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('\\')) +{ + return __quoted_output_proxy<_CharT, + typename basic_string <_CharT, _Traits, _Allocator>::const_iterator> + ( __s.cbegin(), __s.cend (), __delim, __escape ); +} + +template <class _CharT, class _Traits, class _Allocator> +__quoted_proxy<_CharT, _Traits, _Allocator> +quoted ( basic_string <_CharT, _Traits, _Allocator> &__s, _CharT __delim = _CharT('"'), _CharT __escape=_CharT('\\')) +{ + return __quoted_proxy<_CharT, _Traits, _Allocator>( __s, __delim, __escape ); +} +#endif + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_IOMANIP diff --git a/libcxx/test/input.output/iostream.format/quoted.manip/quoted.pass.cpp b/libcxx/test/input.output/iostream.format/quoted.manip/quoted.pass.cpp new file mode 100644 index 00000000000..9f2d7c8ecce --- /dev/null +++ b/libcxx/test/input.output/iostream.format/quoted.manip/quoted.pass.cpp @@ -0,0 +1,192 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <iomanip> + +// quoted + +#include <iomanip> +#include <sstream> +#include <string> +#include <cassert> + +#if _LIBCPP_STD_VER > 11 + +bool is_skipws ( const std::istream *is ) { + return ( is->flags() & std::ios_base::skipws ) != 0; + } + + +bool is_skipws ( const std::wistream *is ) { + return ( is->flags() & std::ios_base::skipws ) != 0; + } + +void round_trip ( const char *p ) { + std::stringstream ss; + bool skippingws = is_skipws ( &ss ); + ss << std::quoted(p); + std::string s; + ss >> std::quoted(s); + assert ( s == p ); + assert ( skippingws == is_skipws ( &ss )); + } + +void round_trip_ws ( const char *p ) { + std::stringstream ss; + std::noskipws ( ss ); + bool skippingws = is_skipws ( &ss ); + ss << std::quoted(p); + std::string s; + ss >> std::quoted(s); + assert ( s == p ); + assert ( skippingws == is_skipws ( &ss )); + } + +void round_trip_d ( const char *p, char delim ) { + std::stringstream ss; + ss << std::quoted(p, delim); + std::string s; + ss >> std::quoted(s, delim); + assert ( s == p ); + } + +void round_trip_e ( const char *p, char escape ) { + std::stringstream ss; + ss << std::quoted(p, '"', escape ); + std::string s; + ss >> std::quoted(s, '"', escape ); + assert ( s == p ); + } + + + +std::string quote ( const char *p, char delim='"', char escape='\\' ) { + std::stringstream ss; + ss << std::quoted(p, delim, escape); + std::string s; + ss >> s; // no quote + return s; +} + +std::string unquote ( const char *p, char delim='"', char escape='\\' ) { + std::stringstream ss; + ss << p; + std::string s; + ss >> std::quoted(s, delim, escape); + return s; +} + + +void round_trip ( const wchar_t *p ) { + std::wstringstream ss; + bool skippingws = is_skipws ( &ss ); + ss << std::quoted(p); + std::wstring s; + ss >> std::quoted(s); + assert ( s == p ); + assert ( skippingws == is_skipws ( &ss )); + } + + +void round_trip_ws ( const wchar_t *p ) { + std::wstringstream ss; + std::noskipws ( ss ); + bool skippingws = is_skipws ( &ss ); + ss << std::quoted(p); + std::wstring s; + ss >> std::quoted(s); + assert ( s == p ); + assert ( skippingws == is_skipws ( &ss )); + } + +void round_trip_d ( const wchar_t *p, wchar_t delim ) { + std::wstringstream ss; + ss << std::quoted(p, delim); + std::wstring s; + ss >> std::quoted(s, delim); + assert ( s == p ); + } + +void round_trip_e ( const wchar_t *p, wchar_t escape ) { + std::wstringstream ss; + ss << std::quoted(p, wchar_t('"'), escape ); + std::wstring s; + ss >> std::quoted(s, wchar_t('"'), escape ); + assert ( s == p ); + } + + +std::wstring quote ( const wchar_t *p, wchar_t delim='"', wchar_t escape='\\' ) { + std::wstringstream ss; + ss << std::quoted(p, delim, escape); + std::wstring s; + ss >> s; // no quote + return s; +} + +std::wstring unquote ( const wchar_t *p, wchar_t delim='"', wchar_t escape='\\' ) { + std::wstringstream ss; + ss << p; + std::wstring s; + ss >> std::quoted(s, delim, escape); + return s; +} + +int main() +{ + round_trip ( "" ); + round_trip_ws ( "" ); + round_trip_d ( "", 'q' ); + round_trip_e ( "", 'q' ); + + round_trip ( L"" ); + round_trip_ws ( L"" ); + round_trip_d ( L"", 'q' ); + round_trip_e ( L"", 'q' ); + + round_trip ( "Hi" ); + round_trip_ws ( "Hi" ); + round_trip_d ( "Hi", '!' ); + round_trip_e ( "Hi", '!' ); + assert ( quote ( "Hi", '!' ) == "!Hi!" ); + assert ( quote ( "Hi!", '!' ) == R"(!Hi\!!)" ); + + round_trip ( L"Hi" ); + round_trip_ws ( L"Hi" ); + round_trip_d ( L"Hi", '!' ); + round_trip_e ( L"Hi", '!' ); + assert ( quote ( L"Hi", '!' ) == L"!Hi!" ); + assert ( quote ( L"Hi!", '!' ) == LR"(!Hi\!!)" ); + + round_trip ( "Hi Mom" ); + round_trip_ws ( "Hi Mom" ); + round_trip ( L"Hi Mom" ); + round_trip_ws ( L"Hi Mom" ); + + assert ( quote ( "" ) == "\"\"" ); + assert ( quote ( L"" ) == L"\"\"" ); + assert ( quote ( "a" ) == "\"a\"" ); + assert ( quote ( L"a" ) == L"\"a\"" ); + +// missing end quote - must not hang + assert ( unquote ( "\"abc" ) == "abc" ); + assert ( unquote ( L"\"abc" ) == L"abc" ); + + assert ( unquote ( "abc" ) == "abc" ); // no delimiter + assert ( unquote ( L"abc" ) == L"abc" ); // no delimiter + assert ( unquote ( "abc def" ) == "abc" ); // no delimiter + assert ( unquote ( L"abc def" ) == L"abc" ); // no delimiter + + assert ( unquote ( "" ) == "" ); // nothing there + assert ( unquote ( L"" ) == L"" ); // nothing there + } + +#else +int main() {} +#endif diff --git a/libcxx/test/input.output/iostream.format/quoted.manip/quoted_char.fail.cpp b/libcxx/test/input.output/iostream.format/quoted.manip/quoted_char.fail.cpp new file mode 100644 index 00000000000..2f516f8fbc9 --- /dev/null +++ b/libcxx/test/input.output/iostream.format/quoted.manip/quoted_char.fail.cpp @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <iomanip> + +// quoted + +#include <iomanip> +#include <sstream> +#include <string> +#include <cassert> + +#if _LIBCPP_STD_VER > 11 + +void round_trip ( const char *p ) { + std::wstringstream ss; + ss << std::quoted(p); + std::string s; + ss >> std::quoted(s); + } + + + +int main() +{ + round_trip ( "Hi Mom" ); +} +#else +#error +#endif diff --git a/libcxx/test/input.output/iostream.format/quoted.manip/quoted_traits.fail.cpp b/libcxx/test/input.output/iostream.format/quoted.manip/quoted_traits.fail.cpp new file mode 100644 index 00000000000..bdd362df19c --- /dev/null +++ b/libcxx/test/input.output/iostream.format/quoted.manip/quoted_traits.fail.cpp @@ -0,0 +1,42 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <iomanip> + +// quoted + +#include <iomanip> +#include <sstream> +#include <string> +#include <cassert> + +#if _LIBCPP_STD_VER > 11 + +template <class charT> +struct test_traits +{ + typedef charT char_type; +}; + +void round_trip ( const char *p ) { + std::stringstream ss; + ss << std::quoted(p); + std::basic_string<char, test_traits<char>> s; + ss >> std::quoted(s); + } + + + +int main() +{ + round_trip ( "Hi Mom" ); +} +#else +#error +#endif diff --git a/libcxx/www/cxx1y_status.html b/libcxx/www/cxx1y_status.html index 0d489cb14d5..4fe5bb3c8ca 100644 --- a/libcxx/www/cxx1y_status.html +++ b/libcxx/www/cxx1y_status.html @@ -83,7 +83,7 @@ <tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3670.html">3670</a></td><td>LWG</td><td>Addressing Tuples by Type</td><td>Bristol</td><td>Complete</td><td>3.4</td></tr> <tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3671.html">3671</a></td><td>LWG</td><td>Making non-modifying sequence operations more robust</td><td>Bristol</td><td>Complete</td><td>3.4</td></tr> <tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3656.htm">3656</a></td><td>LWG</td><td>make_unique</td><td>Bristol</td><td>Complete</td><td>3.4</td></tr> - <tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3654.html">3654</a></td><td>LWG</td><td>Quoted Strings</td><td>Bristol</td><td>Implemented, but not checked in</td><td></td></tr> + <tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3654.html">3654</a></td><td>LWG</td><td>Quoted Strings</td><td>Bristol</td><td>Complete</td><td>3.4</td></tr> <tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3642.pdf">3642</a></td><td>LWG</td><td>User-defined Literals</td><td>Bristol</td><td>Complete</td><td>3.4</td></tr> <tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3655.pdf">3655</a></td><td>LWG</td><td>TransformationTraits Redux (excluding part 4)</td><td>Bristol</td><td>Complete</td><td>3.4</td></tr> <tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3657.htm">3657</a></td><td>LWG</td><td>Adding heterogeneous comparison lookup to associative containers</td><td>Bristol</td><td>Complete</td><td>3.4</td></tr> |