1  // Helpers for quoted stream manipulators -*- C++ -*-
       2  
       3  // Copyright (C) 2013-2023 Free Software Foundation, Inc.
       4  //
       5  // This file is part of the GNU ISO C++ Library.  This library is free
       6  // software; you can redistribute it and/or modify it under the
       7  // terms of the GNU General Public License as published by the
       8  // Free Software Foundation; either version 3, or (at your option)
       9  // any later version.
      10  
      11  // This library is distributed in the hope that it will be useful,
      12  // but WITHOUT ANY WARRANTY; without even the implied warranty of
      13  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14  // GNU General Public License for more details.
      15  
      16  // Under Section 7 of GPL version 3, you are granted additional
      17  // permissions described in the GCC Runtime Library Exception, version
      18  // 3.1, as published by the Free Software Foundation.
      19  
      20  // You should have received a copy of the GNU General Public License and
      21  // a copy of the GCC Runtime Library Exception along with this program;
      22  // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
      23  // <http://www.gnu.org/licenses/>.
      24  
      25  /** @file bits/quoted_string.h
      26   *  This is an internal header file, included by other library headers.
      27   *  Do not attempt to use it directly. @headername{iomanip}
      28   */
      29  
      30  #ifndef _GLIBCXX_QUOTED_STRING_H
      31  #define _GLIBCXX_QUOTED_STRING_H 1
      32  
      33  #pragma GCC system_header
      34  
      35  #if __cplusplus < 201103L
      36  # include <bits/c++0x_warning.h>
      37  #else
      38  #include <sstream>
      39  
      40  namespace std _GLIBCXX_VISIBILITY(default)
      41  {
      42  _GLIBCXX_BEGIN_NAMESPACE_VERSION
      43  
      44    namespace __detail {
      45      /**
      46       * @brief Struct for delimited strings.
      47       */
      48      template<typename _String, typename _CharT>
      49        struct _Quoted_string
      50        {
      51  	static_assert(is_reference<_String>::value
      52  		   || is_pointer<_String>::value,
      53  		      "String type must be pointer or reference");
      54  
      55  	_Quoted_string(_String __str, _CharT __del, _CharT __esc)
      56  	: _M_string(__str), _M_delim{__del}, _M_escape{__esc}
      57  	{ }
      58  
      59  	_Quoted_string&
      60  	operator=(_Quoted_string&) = delete;
      61  
      62  	_String _M_string;
      63  	_CharT _M_delim;
      64  	_CharT _M_escape;
      65        };
      66  
      67  #if __cplusplus >= 201703L
      68      template<typename _CharT, typename _Traits>
      69        struct _Quoted_string<basic_string_view<_CharT, _Traits>, _CharT>
      70        {
      71  	_Quoted_string(basic_string_view<_CharT, _Traits> __str,
      72  		       _CharT __del, _CharT __esc)
      73  	: _M_string(__str), _M_delim{__del}, _M_escape{__esc}
      74  	{ }
      75  
      76  	_Quoted_string&
      77  	operator=(_Quoted_string&) = delete;
      78  
      79  	basic_string_view<_CharT, _Traits> _M_string;
      80  	_CharT _M_delim;
      81  	_CharT _M_escape;
      82        };
      83  #endif // C++17
      84  
      85      /**
      86       * @brief Inserter for quoted strings.
      87       *
      88       * @headerfile iomanip
      89       */
      90      template<typename _CharT, typename _Traits>
      91        std::basic_ostream<_CharT, _Traits>&
      92        operator<<(std::basic_ostream<_CharT, _Traits>& __os,
      93  		 const _Quoted_string<const _CharT*, _CharT>& __str)
      94        {
      95  	//  _GLIBCXX_RESOLVE_LIB_DEFECTS
      96  	//  DR 2344 quoted()'s interaction with padding is unclear
      97  	std::basic_ostringstream<_CharT, _Traits> __ostr;
      98  	__ostr << __str._M_delim;
      99  	for (const _CharT* __c = __str._M_string; *__c; ++__c)
     100  	  {
     101  	    if (*__c == __str._M_delim || *__c == __str._M_escape)
     102  	      __ostr << __str._M_escape;
     103  	    __ostr << *__c;
     104  	  }
     105  	__ostr << __str._M_delim;
     106  
     107  	return __os << __ostr.str();
     108        }
     109  
     110      /**
     111       * @brief Inserter for quoted strings.
     112       *
     113       * @headerfile iomanip
     114       */
     115      template<typename _CharT, typename _Traits, typename _String>
     116        std::basic_ostream<_CharT, _Traits>&
     117        operator<<(std::basic_ostream<_CharT, _Traits>& __os,
     118  		 const _Quoted_string<_String, _CharT>& __str)
     119        {
     120  	//  _GLIBCXX_RESOLVE_LIB_DEFECTS
     121  	//  DR 2344 quoted()'s interaction with padding is unclear
     122  	std::basic_ostringstream<_CharT, _Traits> __ostr;
     123  	__ostr << __str._M_delim;
     124  	for (auto __c : __str._M_string)
     125  	  {
     126  	    if (__c == __str._M_delim || __c == __str._M_escape)
     127  	      __ostr << __str._M_escape;
     128  	    __ostr << __c;
     129  	  }
     130  	__ostr << __str._M_delim;
     131  
     132  	return __os << __ostr.str();
     133        }
     134  
     135      /**
     136       * @brief Extractor for delimited strings.
     137       *        The left and right delimiters can be different.
     138       *
     139       * @headerfile iomanip
     140       */
     141      template<typename _CharT, typename _Traits, typename _Alloc>
     142        std::basic_istream<_CharT, _Traits>&
     143        operator>>(std::basic_istream<_CharT, _Traits>& __is,
     144  		 const _Quoted_string<basic_string<_CharT, _Traits, _Alloc>&,
     145  				      _CharT>& __str)
     146        {
     147  	_CharT __c;
     148  	__is >> __c;
     149  	if (!__is.good())
     150  	  return __is;
     151  	if (__c != __str._M_delim)
     152  	  {
     153  	    __is.unget();
     154  	    __is >> __str._M_string;
     155  	    return __is;
     156  	  }
     157  	__str._M_string.clear();
     158  	std::ios_base::fmtflags __flags
     159  	  = __is.flags(__is.flags() & ~std::ios_base::skipws);
     160  	do
     161  	  {
     162  	    __is >> __c;
     163  	    if (!__is.good())
     164  	      break;
     165  	    if (__c == __str._M_escape)
     166  	      {
     167  		__is >> __c;
     168  		if (!__is.good())
     169  		  break;
     170  	      }
     171  	    else if (__c == __str._M_delim)
     172  	      break;
     173  	    __str._M_string += __c;
     174  	  }
     175  	while (true);
     176  	__is.setf(__flags);
     177  
     178  	return __is;
     179        }
     180    } // namespace __detail
     181  
     182  _GLIBCXX_END_NAMESPACE_VERSION
     183  } // namespace std
     184  
     185  #endif // C++11
     186  #endif /* _GLIBCXX_QUOTED_STRING_H */