On 06/05/2013 04:01 PM, Jonathan Wakely wrote:
On 5 June 2013 20:18, Ed Smith-Rowland wrote:
Greetings,
This patch implements quoted string manipulators for C++14.

27.7.6 - Quoted manipulators        [quoted.manip].

The idea is to allow round trip insert and extract of strings with spaces.

   std::stringstream ss;
   std::string original = "thing1  thing1";
   std::string round_trip;
   ss << std::quoted(original);
   ss >> std::quoted(round_trip);
   assert( original == round_trip );

Builds and tests clean on x86-64-linux.
As I suggested for your literals patch, couldn't the test for:
#if __cplusplus > 201103L
go inside the existing one?

i.e.

#if __cplusplus >= 201103L
[...]
#if __cplusplus > 201103L
[...]
#endif
#endif
Certainly. I forgot that in the last literals patch. I'll fix that after I finish this one. (I just noticed junk comments in the testcases for literals also).


_Quoted_string appears to do two copies of the string, one for the
constructor argument and one for the member variable, do they
definitely get elided?
I looks that way. But all used of the template parm String are either references or pointers so these operations should be efficient.
_Quoted_string should be used as a non-owning string thing.

The members of _Quoted_string should be named _M_xxx not __xxx, to
follow the coding style guidelines.
Done.

What is __delim2 for?

What if the first extraction in the operator>> fails, is doing
__is.unget() the right thing to do?
Thanks. I'll return with __is rather than attempting to continue reading.

You could simplify the quoted() overloads by using auto return type
deduction, is it an intentional choice not to use that?
For some reason I forgot about auto return type in C++14. It sure cleans things up nicely. Done.
Rebuilt and retested on x86_64

2013-06-05  Ed Smith-Rowland  <3dw...@verizon.net>

        Implement N3654 - Quoted Strings Library Proposal
        * include/std/iomanip: Add quoted(String, Char delim, Char escape)
        manipulators and supporting machinery in c++1y mode.
        * testsuite/27_io/manipulators/standard/char/quoted.cc: New.
        * testsuite/27_io/manipulators/standard/wchar_t/quoted.cc: New.
Index: include/std/iomanip
===================================================================
--- include/std/iomanip (revision 199730)
+++ include/std/iomanip (working copy)
@@ -334,8 +334,157 @@
       return __os; 
     }
 
-#endif
+#if __cplusplus > 201103L
 
+  namespace __detail {
+
+    /**
+     * @brief Struct for delimited strings.
+     *        The left and right delimiters can be different.
+     */
+    template<typename _String, typename _CharT>
+      struct _Quoted_string
+      {
+       _Quoted_string(_String __str, _CharT __del, _CharT __esc)
+       : _M_string(__str), _M_delim{__del}, _M_escape{__esc}
+       { }
+
+       _Quoted_string&
+       operator=(_Quoted_string&) = delete;
+
+       _String _M_string;
+       _CharT _M_delim;
+       _CharT _M_escape;
+      };
+
+    /**
+     * @brief Inserter for delimited strings.
+     *        The left and right delimiters can be different.
+     */
+    template<typename _CharT, typename _Traits>
+      auto&
+      operator<<(std::basic_ostream<_CharT, _Traits>& __os,
+                const _Quoted_string<const _CharT*, _CharT>& __str)
+      {
+       __os << __str._M_delim;
+       for (const _CharT* __c = __str._M_string; *__c; ++__c)
+         {
+           if (*__c == __str._M_delim || *__c == __str._M_escape)
+             __os << __str._M_escape;
+           __os << *__c;
+         }
+       __os << __str._M_delim;
+
+       return __os;
+      }
+
+    /**
+     * @brief Inserter for delimited strings.
+     *        The left and right delimiters can be different.
+     */
+    template<typename _CharT, typename _Traits, typename _String>
+      auto&
+      operator<<(std::basic_ostream<_CharT, _Traits>& __os,
+                const _Quoted_string<_String, _CharT>& __str)
+      {
+       __os << __str._M_delim;
+       for (auto& __c : __str._M_string)
+         {
+           if (__c == __str._M_delim || __c == __str._M_escape)
+             __os << __str._M_escape;
+           __os << __c;
+         }
+       __os << __str._M_delim;
+
+       return __os;
+      }
+
+    /**
+     * @brief Extractor for delimited strings.
+     *        The left and right delimiters can be different.
+     */
+    template<typename _CharT, typename _Traits, typename _Alloc>
+      auto&
+      operator>>(std::basic_istream<_CharT, _Traits>& __is,
+                const _Quoted_string<basic_string<_CharT, _Traits, _Alloc>&,
+                                     _CharT>& __str)
+      {
+       __str._M_string.clear();
+
+       _CharT __c;
+       __is >> __c;
+       if (!__is.good())
+         return __is;
+       if (__c != __str._M_delim)
+         {
+           __is.unget();
+           __is >> __str._M_string;
+           return __is;
+         }
+       std::ios_base::fmtflags __flags
+         = __is.flags(__is.flags() & ~std::ios_base::skipws);
+       do
+         {
+           __is >> __c;
+           if (!__is.good())
+             break;
+           if (__c == __str._M_escape)
+             {
+               __is >> __c;
+               if (!__is.good())
+                 break;
+             }
+           else if (__c == __str._M_delim)
+             break;
+           __str._M_string += __c;
+         }
+       while (true);
+       __is.setf(__flags);
+
+       return __is;
+      }
+
+  } // namespace __detail
+
+  /**
+   * @brief Manipulator for quoted strings.
+   * @param __str    String to quote.
+   * @param __delim  Character to quote string with.
+   * @param __escape Escape character to escape itself or quote character.
+   */
+  template<typename _CharT>
+    inline auto
+    quoted(const _CharT* __string,
+          _CharT __delim = _CharT('"'), _CharT __escape = _CharT('\\'))
+    {
+      return __detail::_Quoted_string<const _CharT*, _CharT>(__string, __delim,
+                                                            __escape);
+    }
+
+  template<typename _CharT, typename _Traits, typename _Alloc>
+    inline auto
+    quoted(const basic_string<_CharT, _Traits, _Alloc>& __string,
+          _CharT __delim = _CharT('"'), _CharT __escape = _CharT('\\'))
+    {
+      return __detail::_Quoted_string<
+                       const basic_string<_CharT, _Traits, _Alloc>&, _CharT>(
+                               __string, __delim, __escape);
+    }
+
+  template<typename _CharT, typename _Traits, typename _Alloc>
+    inline auto
+    quoted(basic_string<_CharT, _Traits, _Alloc>& __string,
+          _CharT __delim = _CharT('"'), _CharT __escape = _CharT('\\'))
+    {
+      return __detail::_Quoted_string<
+                       basic_string<_CharT, _Traits, _Alloc>&, _CharT>(
+                               __string, __delim, __escape);
+    }
+
+#endif // __cplusplus > 201103L
+
+#endif // __cplusplus >= 201103L
+
   // Inhibit implicit instantiations for required instantiations,
   // which are defined via explicit instantiations elsewhere.  
   // NB:  This syntax is a GNU extension.
Index: testsuite/27_io/manipulators/standard/char/quoted.cc
===================================================================
--- testsuite/27_io/manipulators/standard/char/quoted.cc        (revision 0)
+++ testsuite/27_io/manipulators/standard/char/quoted.cc        (working copy)
@@ -0,0 +1,75 @@
+// { dg-do run }
+// { dg-options "-std=gnu++1y" }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// 27.7.6 - Quoted manipulators                [quoted.manip]
+
+#include <string>
+#include <sstream>
+#include <iomanip>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+  bool test [[gnu::unused]] = true;
+  std::stringstream ss;
+  std::string original = "foolish me";
+  std::string round_trip;
+  ss << std::quoted(original);
+  ss >> std::quoted(round_trip);
+  VERIFY( original == round_trip );
+}
+
+void
+test02()
+{
+  //  Test skipws correctness.
+  bool test [[gnu::unused]] = true;
+  std::stringstream ss;
+  ss << std::quoted("Hello Goodbye") << ' ' << 1 << ' ' << 2;
+  std::string song;
+  int thing1, thing2;
+  ss >> std::quoted(song) >> thing1 >> thing2;
+  VERIFY( song == "Hello Goodbye" );
+  VERIFY( thing1 == 1 );
+  VERIFY( thing2 == 2 );
+}
+
+void
+test03()
+{
+  //  Test read of unquoted string.
+  bool test [[gnu::unused]] = true;
+  std::stringstream ss;
+  ss << "Alpha Omega";
+  std::string testit;
+  ss >> std::quoted(testit);
+  VERIFY( testit == "Alpha" );
+}
+
+int
+main()
+{
+  test01();
+  test02();
+  test03();
+
+  return 0;
+}
Index: testsuite/27_io/manipulators/standard/wchar_t/quoted.cc
===================================================================
--- testsuite/27_io/manipulators/standard/wchar_t/quoted.cc     (revision 0)
+++ testsuite/27_io/manipulators/standard/wchar_t/quoted.cc     (working copy)
@@ -0,0 +1,76 @@
+// { dg-do run }
+// { dg-options "-std=gnu++1y" }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// 27.7.6 - Quoted manipulators                [quoted.manip]
+
+#include <string>
+#include <sstream>
+#include <iomanip>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+  //  Basic test from paper.
+  bool test [[gnu::unused]] = true;
+  std::wstringstream ss;
+  std::wstring original = L"foolish me";
+  std::wstring round_trip;
+  ss << std::quoted(original);
+  ss >> std::quoted(round_trip);
+  VERIFY( original == round_trip );
+}
+
+void
+test02()
+{
+  //  Test skipws correctness.
+  bool test [[gnu::unused]] = true;
+  std::wstringstream ss;
+  ss << std::quoted(L"Hello Goodbye") << L' ' << 1 << L' ' << 2;
+  std::wstring song;
+  int thing1, thing2;
+  ss >> std::quoted(song) >> thing1 >> thing2;
+  VERIFY( song == L"Hello Goodbye" );
+  VERIFY( thing1 == 1 );
+  VERIFY( thing2 == 2 );
+}
+
+void
+test03()
+{
+  //  Test read of unquoted string.
+  bool test [[gnu::unused]] = true;
+  std::wstringstream ss;
+  ss << L"Alpha Omega";
+  std::wstring testit;
+  ss >> std::quoted(testit);
+  VERIFY( testit == L"Alpha" );
+}
+
+int
+main()
+{
+  test01();
+  test02();
+  test03();
+
+  return 0;
+}

Reply via email to