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