1// Input streams operating on strings-*- C++ -*-
2
3// Copyright (C) 2004-2020 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//
26// ISO C++ 14882: 27.6.1  Input streams
27//
28
29#ifndef _GLIBCXX_USE_CXX11_ABI
30// Instantiations in this file use the new SSO std::string ABI unless included
31// by another file which defines _GLIBCXX_USE_CXX11_ABI=0.
32# define _GLIBCXX_USE_CXX11_ABI 1
33#endif
34#include <istream>
35#include <string>
36
37namespace std _GLIBCXX_VISIBILITY(default)
38{
39_GLIBCXX_BEGIN_NAMESPACE_VERSION
40
41  template<>
42    basic_istream<char>&
43    operator>>(basic_istream<char>& __in, basic_string<char>& __str)
44    {
45      typedef basic_istream<char>       	__istream_type;
46      typedef __istream_type::int_type		__int_type;
47      typedef __istream_type::traits_type	__traits_type;
48      typedef __istream_type::__streambuf_type  __streambuf_type;
49      typedef __istream_type::__ctype_type	__ctype_type;
50      typedef basic_string<char>        	__string_type;
51      typedef __string_type::size_type		__size_type;
52
53      __size_type __extracted = 0;
54      ios_base::iostate __err = ios_base::goodbit;
55      __istream_type::sentry __cerb(__in, false);
56      if (__cerb)
57	{
58	  __try
59	    {
60	      __str.erase();
61	      const streamsize __w = __in.width();
62	      const __size_type __n = __w > 0 ? static_cast<__size_type>(__w)
63		                              : __str.max_size();
64	      const __ctype_type& __ct = use_facet<__ctype_type>(__in.getloc());
65	      const __int_type __eof = __traits_type::eof();
66	      __streambuf_type* __sb = __in.rdbuf();
67	      __int_type __c = __sb->sgetc();
68
69	      while (__extracted < __n
70		     && !__traits_type::eq_int_type(__c, __eof)
71		     && !__ct.is(ctype_base::space,
72				 __traits_type::to_char_type(__c)))
73		{
74		  streamsize __size = std::min(streamsize(__sb->egptr()
75							  - __sb->gptr()),
76					       streamsize(__n - __extracted));
77		  if (__size > 1)
78		    {
79		      __size = (__ct.scan_is(ctype_base::space,
80					     __sb->gptr() + 1,
81					     __sb->gptr() + __size)
82				- __sb->gptr());
83		      __str.append(__sb->gptr(), __size);
84		      __sb->__safe_gbump(__size);
85		      __extracted += __size;
86		      __c = __sb->sgetc();
87		    }
88		  else
89		    {
90		      __str += __traits_type::to_char_type(__c);
91		      ++__extracted;
92		      __c = __sb->snextc();
93		    }
94		}
95
96	      if (__traits_type::eq_int_type(__c, __eof))
97		__err |= ios_base::eofbit;
98	      __in.width(0);
99	    }
100	  __catch(__cxxabiv1::__forced_unwind&)
101	    {
102	      __in._M_setstate(ios_base::badbit);
103	      __throw_exception_again;
104	    }
105	  __catch(...)
106	    {
107	      // _GLIBCXX_RESOLVE_LIB_DEFECTS
108	      // 91. Description of operator>> and getline() for string<>
109	      // might cause endless loop
110	      __in._M_setstate(ios_base::badbit);
111	    }
112	}
113      if (!__extracted)
114	__err |= ios_base::failbit;
115      if (__err)
116	__in.setstate(__err);
117      return __in;
118    }
119
120  template<>
121    basic_istream<char>&
122    getline(basic_istream<char>& __in, basic_string<char>& __str,
123	    char __delim)
124    {
125      typedef basic_istream<char>       	__istream_type;
126      typedef __istream_type::int_type		__int_type;
127      typedef __istream_type::char_type		__char_type;
128      typedef __istream_type::traits_type	__traits_type;
129      typedef __istream_type::__streambuf_type  __streambuf_type;
130      typedef basic_string<char>        	__string_type;
131      typedef __string_type::size_type		__size_type;
132
133      __size_type __extracted = 0;
134      const __size_type __n = __str.max_size();
135      ios_base::iostate __err = ios_base::goodbit;
136      __istream_type::sentry __cerb(__in, true);
137      if (__cerb)
138	{
139	  __try
140	    {
141	      __str.erase();
142	      const __int_type __idelim = __traits_type::to_int_type(__delim);
143	      const __int_type __eof = __traits_type::eof();
144	      __streambuf_type* __sb = __in.rdbuf();
145	      __int_type __c = __sb->sgetc();
146
147	      while (__extracted < __n
148		     && !__traits_type::eq_int_type(__c, __eof)
149		     && !__traits_type::eq_int_type(__c, __idelim))
150		{
151		  streamsize __size = std::min(streamsize(__sb->egptr()
152							  - __sb->gptr()),
153					       streamsize(__n - __extracted));
154		  if (__size > 1)
155		    {
156		      const __char_type* __p = __traits_type::find(__sb->gptr(),
157								   __size,
158								   __delim);
159		      if (__p)
160			__size = __p - __sb->gptr();
161		      __str.append(__sb->gptr(), __size);
162		      __sb->__safe_gbump(__size);
163		      __extracted += __size;
164		      __c = __sb->sgetc();
165		    }
166		  else
167		    {
168		      __str += __traits_type::to_char_type(__c);
169		      ++__extracted;
170		      __c = __sb->snextc();
171		    }
172		}
173
174	      if (__traits_type::eq_int_type(__c, __eof))
175		__err |= ios_base::eofbit;
176	      else if (__traits_type::eq_int_type(__c, __idelim))
177		{
178		  ++__extracted;
179		  __sb->sbumpc();
180		}
181	      else
182		__err |= ios_base::failbit;
183	    }
184	  __catch(__cxxabiv1::__forced_unwind&)
185	    {
186	      __in._M_setstate(ios_base::badbit);
187	      __throw_exception_again;
188	    }
189	  __catch(...)
190	    {
191	      // _GLIBCXX_RESOLVE_LIB_DEFECTS
192	      // 91. Description of operator>> and getline() for string<>
193	      // might cause endless loop
194	      __in._M_setstate(ios_base::badbit);
195	    }
196	}
197      if (!__extracted)
198	__err |= ios_base::failbit;
199      if (__err)
200	__in.setstate(__err);
201      return __in;
202    }
203
204#ifdef _GLIBCXX_USE_WCHAR_T
205  template<>
206    basic_istream<wchar_t>&
207    getline(basic_istream<wchar_t>& __in, basic_string<wchar_t>& __str,
208	    wchar_t __delim)
209    {
210      typedef basic_istream<wchar_t>       	__istream_type;
211      typedef __istream_type::int_type		__int_type;
212      typedef __istream_type::char_type		__char_type;
213      typedef __istream_type::traits_type	__traits_type;
214      typedef __istream_type::__streambuf_type  __streambuf_type;
215      typedef basic_string<wchar_t>        	__string_type;
216      typedef __string_type::size_type		__size_type;
217
218      __size_type __extracted = 0;
219      const __size_type __n = __str.max_size();
220      ios_base::iostate __err = ios_base::goodbit;
221      __istream_type::sentry __cerb(__in, true);
222      if (__cerb)
223	{
224	  __try
225	    {
226	      __str.erase();
227	      const __int_type __idelim = __traits_type::to_int_type(__delim);
228	      const __int_type __eof = __traits_type::eof();
229	      __streambuf_type* __sb = __in.rdbuf();
230	      __int_type __c = __sb->sgetc();
231
232	      while (__extracted < __n
233		     && !__traits_type::eq_int_type(__c, __eof)
234		     && !__traits_type::eq_int_type(__c, __idelim))
235		{
236		  streamsize __size = std::min(streamsize(__sb->egptr()
237							  - __sb->gptr()),
238					       streamsize(__n - __extracted));
239		  if (__size > 1)
240		    {
241		      const __char_type* __p = __traits_type::find(__sb->gptr(),
242								   __size,
243								   __delim);
244		      if (__p)
245			__size = __p - __sb->gptr();
246		      __str.append(__sb->gptr(), __size);
247		      __sb->__safe_gbump(__size);
248		      __extracted += __size;
249		      __c = __sb->sgetc();
250		    }
251		  else
252		    {
253		      __str += __traits_type::to_char_type(__c);
254		      ++__extracted;
255		      __c = __sb->snextc();
256		    }
257		}
258
259	      if (__traits_type::eq_int_type(__c, __eof))
260		__err |= ios_base::eofbit;
261	      else if (__traits_type::eq_int_type(__c, __idelim))
262		{
263		  ++__extracted;
264		  __sb->sbumpc();
265		}
266	      else
267		__err |= ios_base::failbit;
268	    }
269	  __catch(__cxxabiv1::__forced_unwind&)
270	    {
271	      __in._M_setstate(ios_base::badbit);
272	      __throw_exception_again;
273	    }
274	  __catch(...)
275	    {
276	      // _GLIBCXX_RESOLVE_LIB_DEFECTS
277	      // 91. Description of operator>> and getline() for string<>
278	      // might cause endless loop
279	      __in._M_setstate(ios_base::badbit);
280	    }
281	}
282      if (!__extracted)
283	__err |= ios_base::failbit;
284      if (__err)
285	__in.setstate(__err);
286      return __in;
287    }
288#endif
289
290_GLIBCXX_END_NAMESPACE_VERSION
291} // namespace
292