Home | History | Annotate | Line # | Download | only in bits
      1 // Helpers for quoted stream manipulators -*- C++ -*-
      2 
      3 // Copyright (C) 2013-2024 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 */
    187