1// Versatile string -*- C++ -*-
2
3// Copyright (C) 2005, 2006, 2007 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 2, 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// You should have received a copy of the GNU General Public License along
17// with this library; see the file COPYING.  If not, write to the Free
18// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19// USA.
20
21// As a special exception, you may use this file as part of a free software
22// library without restriction.  Specifically, if other files instantiate
23// templates or use macros or inline functions from this file, or you compile
24// this file and link it with other files to produce an executable, this
25// file does not by itself cause the resulting executable to be covered by
26// the GNU General Public License.  This exception does not however
27// invalidate any other reasons why the executable file might be covered by
28// the GNU General Public License.
29
30/** @file ext/vstring.tcc
31 *  This file is a GNU extension to the Standard C++ Library.
32 *  This is an internal header file, included by other library headers.
33 *  You should not attempt to use it directly.
34 */
35
36#ifndef _VSTRING_TCC
37#define _VSTRING_TCC 1
38
39#pragma GCC system_header
40
41_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
42
43  template<typename _CharT, typename _Traits, typename _Alloc,
44	   template <typename, typename, typename> class _Base>
45    const typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
46    __versa_string<_CharT, _Traits, _Alloc, _Base>::npos;
47
48  template<typename _CharT, typename _Traits, typename _Alloc,
49	   template <typename, typename, typename> class _Base>
50    void
51    __versa_string<_CharT, _Traits, _Alloc, _Base>::
52    resize(size_type __n, _CharT __c)
53    {
54      const size_type __size = this->size();
55      if (__size < __n)
56	this->append(__n - __size, __c);
57      else if (__n < __size)
58	this->_M_erase(__n, __size - __n);
59    }
60
61  template<typename _CharT, typename _Traits, typename _Alloc,
62	   template <typename, typename, typename> class _Base>
63    __versa_string<_CharT, _Traits, _Alloc, _Base>&
64    __versa_string<_CharT, _Traits, _Alloc, _Base>::
65    _M_append(const _CharT* __s, size_type __n)
66    {
67      const size_type __len = __n + this->size();
68
69      if (__len <= this->capacity() && !this->_M_is_shared())
70	{
71	  if (__n)
72	    this->_S_copy(this->_M_data() + this->size(), __s, __n);
73	}
74      else
75	this->_M_mutate(this->size(), size_type(0), __s, __n);
76
77      this->_M_set_length(__len);
78      return *this;
79    }
80
81  template<typename _CharT, typename _Traits, typename _Alloc,
82	   template <typename, typename, typename> class _Base>
83    template<typename _InputIterator>
84      __versa_string<_CharT, _Traits, _Alloc, _Base>&
85      __versa_string<_CharT, _Traits, _Alloc, _Base>::
86      _M_replace_dispatch(iterator __i1, iterator __i2, _InputIterator __k1,
87			  _InputIterator __k2, std::__false_type)
88      {
89	const __versa_string __s(__k1, __k2);
90	const size_type __n1 = __i2 - __i1;
91	return _M_replace(__i1 - _M_ibegin(), __n1, __s._M_data(),
92			  __s.size());
93      }
94
95  template<typename _CharT, typename _Traits, typename _Alloc,
96	   template <typename, typename, typename> class _Base>
97    __versa_string<_CharT, _Traits, _Alloc, _Base>&
98    __versa_string<_CharT, _Traits, _Alloc, _Base>::
99    _M_replace_aux(size_type __pos1, size_type __n1, size_type __n2,
100		   _CharT __c)
101    {
102      _M_check_length(__n1, __n2, "__versa_string::_M_replace_aux");
103
104      const size_type __old_size = this->size();
105      const size_type __new_size = __old_size + __n2 - __n1;
106
107      if (__new_size <= this->capacity() && !this->_M_is_shared())
108	{
109	  _CharT* __p = this->_M_data() + __pos1;
110
111	  const size_type __how_much = __old_size - __pos1 - __n1;
112	  if (__how_much && __n1 != __n2)
113	    this->_S_move(__p + __n2, __p + __n1, __how_much);
114	}
115      else
116	this->_M_mutate(__pos1, __n1, 0, __n2);
117
118      if (__n2)
119	this->_S_assign(this->_M_data() + __pos1, __n2, __c);
120
121      this->_M_set_length(__new_size);
122      return *this;
123    }
124
125  template<typename _CharT, typename _Traits, typename _Alloc,
126	   template <typename, typename, typename> class _Base>
127    __versa_string<_CharT, _Traits, _Alloc, _Base>&
128    __versa_string<_CharT, _Traits, _Alloc, _Base>::
129    _M_replace(size_type __pos, size_type __len1, const _CharT* __s,
130	       const size_type __len2)
131    {
132      _M_check_length(__len1, __len2, "__versa_string::_M_replace");
133
134      const size_type __old_size = this->size();
135      const size_type __new_size = __old_size + __len2 - __len1;
136      
137      if (__new_size <= this->capacity() && !this->_M_is_shared())
138	{
139	  _CharT* __p = this->_M_data() + __pos;
140
141	  const size_type __how_much = __old_size - __pos - __len1;
142	  if (_M_disjunct(__s))
143	    {
144	      if (__how_much && __len1 != __len2)
145		this->_S_move(__p + __len2, __p + __len1, __how_much);
146	      if (__len2)
147		this->_S_copy(__p, __s, __len2);
148	    }
149	  else
150	    {
151	      // Work in-place.
152	      if (__len2 && __len2 <= __len1)
153		this->_S_move(__p, __s, __len2);
154	      if (__how_much && __len1 != __len2)
155		this->_S_move(__p + __len2, __p + __len1, __how_much);
156	      if (__len2 > __len1)
157		{
158		  if (__s + __len2 <= __p + __len1)
159		    this->_S_move(__p, __s, __len2);
160		  else if (__s >= __p + __len1)
161		    this->_S_copy(__p, __s + __len2 - __len1, __len2);
162		  else
163		    {
164		      const size_type __nleft = (__p + __len1) - __s;
165		      this->_S_move(__p, __s, __nleft);
166		      this->_S_copy(__p + __nleft, __p + __len2,
167				    __len2 - __nleft);
168		    }
169		}
170	    }
171	}
172      else
173	this->_M_mutate(__pos, __len1, __s, __len2);
174
175      this->_M_set_length(__new_size);
176      return *this;
177    }
178  
179  template<typename _CharT, typename _Traits, typename _Alloc,
180	   template <typename, typename, typename> class _Base>
181    __versa_string<_CharT, _Traits, _Alloc, _Base>
182    operator+(const __versa_string<_CharT, _Traits, _Alloc, _Base>& __lhs,
183	      const __versa_string<_CharT, _Traits, _Alloc, _Base>& __rhs)
184    {
185      __versa_string<_CharT, _Traits, _Alloc, _Base> __str;
186      __str.reserve(__lhs.size() + __rhs.size());
187      __str.append(__lhs);
188      __str.append(__rhs);
189      return __str;
190    }
191
192  template<typename _CharT, typename _Traits, typename _Alloc,
193	   template <typename, typename, typename> class _Base>
194    __versa_string<_CharT, _Traits, _Alloc, _Base>
195    operator+(const _CharT* __lhs,
196	      const __versa_string<_CharT, _Traits, _Alloc, _Base>& __rhs)
197    {
198      __glibcxx_requires_string(__lhs);
199      typedef __versa_string<_CharT, _Traits, _Alloc, _Base> __string_type;
200      typedef typename __string_type::size_type	  __size_type;
201      const __size_type __len = _Traits::length(__lhs);
202      __string_type __str;
203      __str.reserve(__len + __rhs.size());
204      __str.append(__lhs, __len);
205      __str.append(__rhs);
206      return __str;
207    }
208
209  template<typename _CharT, typename _Traits, typename _Alloc,
210	   template <typename, typename, typename> class _Base>
211    __versa_string<_CharT, _Traits, _Alloc, _Base>
212    operator+(_CharT __lhs,
213	      const __versa_string<_CharT, _Traits, _Alloc, _Base>& __rhs)
214    {
215      __versa_string<_CharT, _Traits, _Alloc, _Base> __str;
216      __str.reserve(__rhs.size() + 1);
217      __str.push_back(__lhs);
218      __str.append(__rhs);
219      return __str;
220    }
221
222  template<typename _CharT, typename _Traits, typename _Alloc,
223	   template <typename, typename, typename> class _Base>
224    __versa_string<_CharT, _Traits, _Alloc, _Base>
225    operator+(const __versa_string<_CharT, _Traits, _Alloc, _Base>& __lhs,
226	      const _CharT* __rhs)
227    {
228      __glibcxx_requires_string(__rhs);
229      typedef __versa_string<_CharT, _Traits, _Alloc, _Base> __string_type;
230      typedef typename __string_type::size_type	  __size_type;
231      const __size_type __len = _Traits::length(__rhs);
232      __string_type __str;
233      __str.reserve(__lhs.size() + __len);
234      __str.append(__lhs);
235      __str.append(__rhs, __len);
236      return __str;
237    }
238
239  template<typename _CharT, typename _Traits, typename _Alloc,
240	   template <typename, typename, typename> class _Base>
241    __versa_string<_CharT, _Traits, _Alloc, _Base>
242    operator+(const __versa_string<_CharT, _Traits, _Alloc, _Base>& __lhs,
243	      _CharT __rhs)
244    {
245      __versa_string<_CharT, _Traits, _Alloc, _Base> __str;
246      __str.reserve(__lhs.size() + 1);
247      __str.append(__lhs);
248      __str.push_back(__rhs);
249      return __str;
250    }
251
252  template<typename _CharT, typename _Traits, typename _Alloc,
253	   template <typename, typename, typename> class _Base>
254    typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
255    __versa_string<_CharT, _Traits, _Alloc, _Base>::
256    copy(_CharT* __s, size_type __n, size_type __pos) const
257    {
258      _M_check(__pos, "__versa_string::copy");
259      __n = _M_limit(__pos, __n);
260      __glibcxx_requires_string_len(__s, __n);
261      if (__n)
262	this->_S_copy(__s, this->_M_data() + __pos, __n);
263      // 21.3.5.7 par 3: do not append null.  (good.)
264      return __n;
265    }
266
267  template<typename _CharT, typename _Traits, typename _Alloc,
268	   template <typename, typename, typename> class _Base>
269    typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
270    __versa_string<_CharT, _Traits, _Alloc, _Base>::
271    find(const _CharT* __s, size_type __pos, size_type __n) const
272    {
273      __glibcxx_requires_string_len(__s, __n);
274      const size_type __size = this->size();
275      const _CharT* __data = this->_M_data();
276
277      if (__n == 0)
278	return __pos <= __size ? __pos : npos;
279
280      if (__n <= __size)
281	{
282	  for (; __pos <= __size - __n; ++__pos)
283	    if (traits_type::eq(__data[__pos], __s[0])
284		&& traits_type::compare(__data + __pos + 1,
285					__s + 1, __n - 1) == 0)
286	      return __pos;
287	}
288      return npos;
289    }
290
291  template<typename _CharT, typename _Traits, typename _Alloc,
292	   template <typename, typename, typename> class _Base>
293    typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
294    __versa_string<_CharT, _Traits, _Alloc, _Base>::
295    find(_CharT __c, size_type __pos) const
296    {
297      size_type __ret = npos;
298      const size_type __size = this->size();
299      if (__pos < __size)
300	{
301	  const _CharT* __data = this->_M_data();
302	  const size_type __n = __size - __pos;
303	  const _CharT* __p = traits_type::find(__data + __pos, __n, __c);
304	  if (__p)
305	    __ret = __p - __data;
306	}
307      return __ret;
308    }
309
310  template<typename _CharT, typename _Traits, typename _Alloc,
311	   template <typename, typename, typename> class _Base>
312    typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
313    __versa_string<_CharT, _Traits, _Alloc, _Base>::
314    rfind(const _CharT* __s, size_type __pos, size_type __n) const
315    {
316      __glibcxx_requires_string_len(__s, __n);
317      const size_type __size = this->size();
318      if (__n <= __size)
319	{
320	  __pos = std::min(size_type(__size - __n), __pos);
321	  const _CharT* __data = this->_M_data();
322	  do
323	    {
324	      if (traits_type::compare(__data + __pos, __s, __n) == 0)
325		return __pos;
326	    }
327	  while (__pos-- > 0);
328	}
329      return npos;
330    }
331
332  template<typename _CharT, typename _Traits, typename _Alloc,
333	   template <typename, typename, typename> class _Base>
334    typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
335    __versa_string<_CharT, _Traits, _Alloc, _Base>::
336    rfind(_CharT __c, size_type __pos) const
337    {
338      size_type __size = this->size();
339      if (__size)
340	{
341	  if (--__size > __pos)
342	    __size = __pos;
343	  for (++__size; __size-- > 0; )
344	    if (traits_type::eq(this->_M_data()[__size], __c))
345	      return __size;
346	}
347      return npos;
348    }
349
350  template<typename _CharT, typename _Traits, typename _Alloc,
351	   template <typename, typename, typename> class _Base>
352    typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
353    __versa_string<_CharT, _Traits, _Alloc, _Base>::
354    find_first_of(const _CharT* __s, size_type __pos, size_type __n) const
355    {
356      __glibcxx_requires_string_len(__s, __n);
357      for (; __n && __pos < this->size(); ++__pos)
358	{
359	  const _CharT* __p = traits_type::find(__s, __n,
360						this->_M_data()[__pos]);
361	  if (__p)
362	    return __pos;
363	}
364      return npos;
365    }
366
367  template<typename _CharT, typename _Traits, typename _Alloc,
368	   template <typename, typename, typename> class _Base>
369    typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
370    __versa_string<_CharT, _Traits, _Alloc, _Base>::
371    find_last_of(const _CharT* __s, size_type __pos, size_type __n) const
372    {
373      __glibcxx_requires_string_len(__s, __n);
374      size_type __size = this->size();
375      if (__size && __n)
376	{
377	  if (--__size > __pos)
378	    __size = __pos;
379	  do
380	    {
381	      if (traits_type::find(__s, __n, this->_M_data()[__size]))
382		return __size;
383	    }
384	  while (__size-- != 0);
385	}
386      return npos;
387    }
388
389  template<typename _CharT, typename _Traits, typename _Alloc,
390	   template <typename, typename, typename> class _Base>
391    typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
392    __versa_string<_CharT, _Traits, _Alloc, _Base>::
393    find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const
394    {
395      __glibcxx_requires_string_len(__s, __n);
396      for (; __pos < this->size(); ++__pos)
397	if (!traits_type::find(__s, __n, this->_M_data()[__pos]))
398	  return __pos;
399      return npos;
400    }
401
402  template<typename _CharT, typename _Traits, typename _Alloc,
403	   template <typename, typename, typename> class _Base>
404    typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
405    __versa_string<_CharT, _Traits, _Alloc, _Base>::
406    find_first_not_of(_CharT __c, size_type __pos) const
407    {
408      for (; __pos < this->size(); ++__pos)
409	if (!traits_type::eq(this->_M_data()[__pos], __c))
410	  return __pos;
411      return npos;
412    }
413
414  template<typename _CharT, typename _Traits, typename _Alloc,
415	   template <typename, typename, typename> class _Base>
416    typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
417    __versa_string<_CharT, _Traits, _Alloc, _Base>::
418    find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const
419    {
420      __glibcxx_requires_string_len(__s, __n);
421      size_type __size = this->size();
422      if (__size)
423	{
424	  if (--__size > __pos)
425	    __size = __pos;
426	  do
427	    {
428	      if (!traits_type::find(__s, __n, this->_M_data()[__size]))
429		return __size;
430	    }
431	  while (__size--);
432	}
433      return npos;
434    }
435
436  template<typename _CharT, typename _Traits, typename _Alloc,
437	   template <typename, typename, typename> class _Base>
438    typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
439    __versa_string<_CharT, _Traits, _Alloc, _Base>::
440    find_last_not_of(_CharT __c, size_type __pos) const
441    {
442      size_type __size = this->size();
443      if (__size)
444	{
445	  if (--__size > __pos)
446	    __size = __pos;
447	  do
448	    {
449	      if (!traits_type::eq(this->_M_data()[__size], __c))
450		return __size;
451	    }
452	  while (__size--);
453	}
454      return npos;
455    }
456
457  template<typename _CharT, typename _Traits, typename _Alloc,
458	   template <typename, typename, typename> class _Base>
459    int
460    __versa_string<_CharT, _Traits, _Alloc, _Base>::
461    compare(size_type __pos, size_type __n, const __versa_string& __str) const
462    {
463      _M_check(__pos, "__versa_string::compare");
464      __n = _M_limit(__pos, __n);
465      const size_type __osize = __str.size();
466      const size_type __len = std::min(__n, __osize);
467      int __r = traits_type::compare(this->_M_data() + __pos,
468				     __str.data(), __len);
469      if (!__r)
470	__r = __n - __osize;
471      return __r;
472    }
473
474  template<typename _CharT, typename _Traits, typename _Alloc,
475	   template <typename, typename, typename> class _Base>
476    int
477    __versa_string<_CharT, _Traits, _Alloc, _Base>::
478    compare(size_type __pos1, size_type __n1, const __versa_string& __str,
479	    size_type __pos2, size_type __n2) const
480    {
481      _M_check(__pos1, "__versa_string::compare");
482      __str._M_check(__pos2, "__versa_string::compare");
483      __n1 = _M_limit(__pos1, __n1);
484      __n2 = __str._M_limit(__pos2, __n2);
485      const size_type __len = std::min(__n1, __n2);
486      int __r = traits_type::compare(this->_M_data() + __pos1,
487				     __str.data() + __pos2, __len);
488      if (!__r)
489	__r = __n1 - __n2;
490      return __r;
491    }
492
493  template<typename _CharT, typename _Traits, typename _Alloc,
494	   template <typename, typename, typename> class _Base>
495    int
496    __versa_string<_CharT, _Traits, _Alloc, _Base>::
497    compare(const _CharT* __s) const
498    {
499      __glibcxx_requires_string(__s);
500      const size_type __size = this->size();
501      const size_type __osize = traits_type::length(__s);
502      const size_type __len = std::min(__size, __osize);
503      int __r = traits_type::compare(this->_M_data(), __s, __len);
504      if (!__r)
505	__r = __size - __osize;
506      return __r;
507    }
508
509  template<typename _CharT, typename _Traits, typename _Alloc,
510	   template <typename, typename, typename> class _Base>
511    int
512    __versa_string <_CharT, _Traits, _Alloc, _Base>::
513    compare(size_type __pos, size_type __n1, const _CharT* __s) const
514    {
515      __glibcxx_requires_string(__s);
516      _M_check(__pos, "__versa_string::compare");
517      __n1 = _M_limit(__pos, __n1);
518      const size_type __osize = traits_type::length(__s);
519      const size_type __len = std::min(__n1, __osize);
520      int __r = traits_type::compare(this->_M_data() + __pos, __s, __len);
521      if (!__r)
522	__r = __n1 - __osize;
523      return __r;
524    }
525
526  template<typename _CharT, typename _Traits, typename _Alloc,
527	   template <typename, typename, typename> class _Base>
528    int
529    __versa_string <_CharT, _Traits, _Alloc, _Base>::
530    compare(size_type __pos, size_type __n1, const _CharT* __s,
531	    size_type __n2) const
532    {
533      __glibcxx_requires_string_len(__s, __n2);
534      _M_check(__pos, "__versa_string::compare");
535      __n1 = _M_limit(__pos, __n1);
536      const size_type __len = std::min(__n1, __n2);
537      int __r = traits_type::compare(this->_M_data() + __pos, __s, __len);
538      if (!__r)
539	__r = __n1 - __n2;
540      return __r;
541    }
542
543_GLIBCXX_END_NAMESPACE
544
545_GLIBCXX_BEGIN_NAMESPACE(std)
546
547  template<typename _CharT, typename _Traits, typename _Alloc,
548           template <typename, typename, typename> class _Base>
549    basic_istream<_CharT, _Traits>&
550    operator>>(basic_istream<_CharT, _Traits>& __in,
551	       __gnu_cxx::__versa_string<_CharT, _Traits,
552	                                 _Alloc, _Base>& __str)
553    {
554      typedef basic_istream<_CharT, _Traits>	        __istream_type;
555      typedef typename __istream_type::int_type		__int_type;
556      typedef typename __istream_type::__streambuf_type __streambuf_type;
557      typedef typename __istream_type::__ctype_type	__ctype_type;
558      typedef __gnu_cxx::__versa_string<_CharT, _Traits, _Alloc, _Base>
559	                                                __string_type;
560      typedef typename __string_type::size_type		__size_type;
561
562      __size_type __extracted = 0;
563      ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
564      typename __istream_type::sentry __cerb(__in, false);
565      if (__cerb)
566	{
567	  try
568	    {
569	      // Avoid reallocation for common case.
570	      __str.erase();
571	      _CharT __buf[128];
572	      __size_type __len = 0;
573	      const streamsize __w = __in.width();
574	      const __size_type __n = __w > 0 ? static_cast<__size_type>(__w)
575		                              : __str.max_size();
576	      const __ctype_type& __ct = use_facet<__ctype_type>(__in.getloc());
577	      const __int_type __eof = _Traits::eof();
578	      __streambuf_type* __sb = __in.rdbuf();
579	      __int_type __c = __sb->sgetc();
580
581	      while (__extracted < __n
582		     && !_Traits::eq_int_type(__c, __eof)
583		     && !__ct.is(ctype_base::space, _Traits::to_char_type(__c)))
584		{
585		  if (__len == sizeof(__buf) / sizeof(_CharT))
586		    {
587		      __str.append(__buf, sizeof(__buf) / sizeof(_CharT));
588		      __len = 0;
589		    }
590		  __buf[__len++] = _Traits::to_char_type(__c);
591		  ++__extracted;
592		  __c = __sb->snextc();
593		}
594	      __str.append(__buf, __len);
595
596	      if (_Traits::eq_int_type(__c, __eof))
597		__err |= ios_base::eofbit;
598	      __in.width(0);
599	    }
600	  catch(...)
601	    {
602	      // _GLIBCXX_RESOLVE_LIB_DEFECTS
603	      // 91. Description of operator>> and getline() for string<>
604	      // might cause endless loop
605	      __in._M_setstate(ios_base::badbit);
606	    }
607	}
608      // 211.  operator>>(istream&, string&) doesn't set failbit
609      if (!__extracted)
610	__err |= ios_base::failbit;
611      if (__err)
612	__in.setstate(__err);
613      return __in;
614    }      
615
616  template<typename _CharT, typename _Traits, typename _Alloc,
617           template <typename, typename, typename> class _Base>
618    basic_istream<_CharT, _Traits>&
619    getline(basic_istream<_CharT, _Traits>& __in,
620	    __gnu_cxx::__versa_string<_CharT, _Traits, _Alloc, _Base>& __str,
621	    _CharT __delim)
622    {
623      typedef basic_istream<_CharT, _Traits>	        __istream_type;
624      typedef typename __istream_type::int_type		__int_type;
625      typedef typename __istream_type::__streambuf_type __streambuf_type;
626      typedef typename __istream_type::__ctype_type	__ctype_type;
627      typedef __gnu_cxx::__versa_string<_CharT, _Traits, _Alloc, _Base>
628	                                                __string_type;
629      typedef typename __string_type::size_type		__size_type;
630
631      __size_type __extracted = 0;
632      const __size_type __n = __str.max_size();
633      ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
634      typename __istream_type::sentry __cerb(__in, true);
635      if (__cerb)
636	{
637	  try
638	    {
639	      // Avoid reallocation for common case.
640	      __str.erase();
641	      _CharT __buf[128];
642	      __size_type __len = 0;
643	      const __int_type __idelim = _Traits::to_int_type(__delim);
644	      const __int_type __eof = _Traits::eof();
645	      __streambuf_type* __sb = __in.rdbuf();
646	      __int_type __c = __sb->sgetc();
647
648	      while (__extracted < __n
649		     && !_Traits::eq_int_type(__c, __eof)
650		     && !_Traits::eq_int_type(__c, __idelim))
651		{
652		  if (__len == sizeof(__buf) / sizeof(_CharT))
653		    {
654		      __str.append(__buf, sizeof(__buf) / sizeof(_CharT));
655		      __len = 0;
656		    }
657		  __buf[__len++] = _Traits::to_char_type(__c);
658		  ++__extracted;
659		  __c = __sb->snextc();
660		}
661	      __str.append(__buf, __len);
662
663	      if (_Traits::eq_int_type(__c, __eof))
664		__err |= ios_base::eofbit;
665	      else if (_Traits::eq_int_type(__c, __idelim))
666		{
667		  ++__extracted;		  
668		  __sb->sbumpc();
669		}
670	      else
671		__err |= ios_base::failbit;
672	    }
673	  catch(...)
674	    {
675	      // _GLIBCXX_RESOLVE_LIB_DEFECTS
676	      // 91. Description of operator>> and getline() for string<>
677	      // might cause endless loop
678	      __in._M_setstate(ios_base::badbit);
679	    }
680	}
681      if (!__extracted)
682	__err |= ios_base::failbit;
683      if (__err)
684	__in.setstate(__err);
685      return __in;
686    }      
687  
688_GLIBCXX_END_NAMESPACE
689
690#endif // _VSTRING_TCC
691