1169691Skan// Versatile string -*- C++ -*-
2169691Skan
3169691Skan// Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
4169691Skan//
5169691Skan// This file is part of the GNU ISO C++ Library.  This library is free
6169691Skan// software; you can redistribute it and/or modify it under the
7169691Skan// terms of the GNU General Public License as published by the
8169691Skan// Free Software Foundation; either version 2, or (at your option)
9169691Skan// any later version.
10169691Skan
11169691Skan// This library is distributed in the hope that it will be useful,
12169691Skan// but WITHOUT ANY WARRANTY; without even the implied warranty of
13169691Skan// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14169691Skan// GNU General Public License for more details.
15169691Skan
16169691Skan// You should have received a copy of the GNU General Public License along
17169691Skan// with this library; see the file COPYING.  If not, write to the Free
18169691Skan// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19169691Skan// USA.
20169691Skan
21169691Skan// As a special exception, you may use this file as part of a free software
22169691Skan// library without restriction.  Specifically, if other files instantiate
23169691Skan// templates or use macros or inline functions from this file, or you compile
24169691Skan// this file and link it with other files to produce an executable, this
25169691Skan// file does not by itself cause the resulting executable to be covered by
26169691Skan// the GNU General Public License.  This exception does not however
27169691Skan// invalidate any other reasons why the executable file might be covered by
28169691Skan// the GNU General Public License.
29169691Skan
30169691Skan/** @file ext/vstring.tcc
31169691Skan *  This file is a GNU extension to the Standard C++ Library.
32169691Skan *  This is an internal header file, included by other library headers.
33169691Skan *  You should not attempt to use it directly.
34169691Skan */
35169691Skan
36169691Skan#ifndef _VSTRING_TCC
37169691Skan#define _VSTRING_TCC 1
38169691Skan
39169691Skan#pragma GCC system_header
40169691Skan
41169691Skan_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
42169691Skan
43169691Skan  template<typename _CharT, typename _Traits, typename _Alloc,
44169691Skan	   template <typename, typename, typename> class _Base>
45169691Skan    const typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
46169691Skan    __versa_string<_CharT, _Traits, _Alloc, _Base>::npos;
47169691Skan
48169691Skan  template<typename _CharT, typename _Traits, typename _Alloc,
49169691Skan	   template <typename, typename, typename> class _Base>
50169691Skan    void
51169691Skan    __versa_string<_CharT, _Traits, _Alloc, _Base>::
52169691Skan    resize(size_type __n, _CharT __c)
53169691Skan    {
54169691Skan      const size_type __size = this->size();
55169691Skan      if (__size < __n)
56169691Skan	this->append(__n - __size, __c);
57169691Skan      else if (__n < __size)
58169691Skan	this->_M_erase(__n, __size - __n);
59169691Skan    }
60169691Skan
61169691Skan  template<typename _CharT, typename _Traits, typename _Alloc,
62169691Skan	   template <typename, typename, typename> class _Base>
63169691Skan    __versa_string<_CharT, _Traits, _Alloc, _Base>&
64169691Skan    __versa_string<_CharT, _Traits, _Alloc, _Base>::
65169691Skan    _M_append(const _CharT* __s, size_type __n)
66169691Skan    {
67169691Skan      const size_type __len = __n + this->size();
68169691Skan
69169691Skan      if (__len <= this->capacity() && !this->_M_is_shared())
70169691Skan	{
71169691Skan	  if (__n)
72169691Skan	    this->_S_copy(this->_M_data() + this->size(), __s, __n);
73169691Skan	}
74169691Skan      else
75169691Skan	this->_M_mutate(this->size(), size_type(0), __s, __n);
76169691Skan
77169691Skan      this->_M_set_length(__len);
78169691Skan      return *this;
79169691Skan    }
80169691Skan
81169691Skan  template<typename _CharT, typename _Traits, typename _Alloc,
82169691Skan	   template <typename, typename, typename> class _Base>
83169691Skan    template<typename _InputIterator>
84169691Skan      __versa_string<_CharT, _Traits, _Alloc, _Base>&
85169691Skan      __versa_string<_CharT, _Traits, _Alloc, _Base>::
86169691Skan      _M_replace_dispatch(iterator __i1, iterator __i2, _InputIterator __k1,
87169691Skan			  _InputIterator __k2, std::__false_type)
88169691Skan      {
89169691Skan	const __versa_string __s(__k1, __k2);
90169691Skan	const size_type __n1 = __i2 - __i1;
91169691Skan	return _M_replace(__i1 - _M_ibegin(), __n1, __s._M_data(),
92169691Skan			  __s.size());
93169691Skan      }
94169691Skan
95169691Skan  template<typename _CharT, typename _Traits, typename _Alloc,
96169691Skan	   template <typename, typename, typename> class _Base>
97169691Skan    __versa_string<_CharT, _Traits, _Alloc, _Base>&
98169691Skan    __versa_string<_CharT, _Traits, _Alloc, _Base>::
99169691Skan    _M_replace_aux(size_type __pos1, size_type __n1, size_type __n2,
100169691Skan		   _CharT __c)
101169691Skan    {
102169691Skan      _M_check_length(__n1, __n2, "__versa_string::_M_replace_aux");
103169691Skan
104169691Skan      const size_type __old_size = this->size();
105169691Skan      const size_type __new_size = __old_size + __n2 - __n1;
106169691Skan
107169691Skan      if (__new_size <= this->capacity() && !this->_M_is_shared())
108169691Skan	{
109169691Skan	  _CharT* __p = this->_M_data() + __pos1;
110169691Skan
111169691Skan	  const size_type __how_much = __old_size - __pos1 - __n1;
112169691Skan	  if (__how_much && __n1 != __n2)
113169691Skan	    this->_S_move(__p + __n2, __p + __n1, __how_much);
114169691Skan	}
115169691Skan      else
116169691Skan	this->_M_mutate(__pos1, __n1, 0, __n2);
117169691Skan
118169691Skan      if (__n2)
119169691Skan	this->_S_assign(this->_M_data() + __pos1, __n2, __c);
120169691Skan
121169691Skan      this->_M_set_length(__new_size);
122169691Skan      return *this;
123169691Skan    }
124169691Skan
125169691Skan  template<typename _CharT, typename _Traits, typename _Alloc,
126169691Skan	   template <typename, typename, typename> class _Base>
127169691Skan    __versa_string<_CharT, _Traits, _Alloc, _Base>&
128169691Skan    __versa_string<_CharT, _Traits, _Alloc, _Base>::
129169691Skan    _M_replace(size_type __pos, size_type __len1, const _CharT* __s,
130169691Skan	       const size_type __len2)
131169691Skan    {
132169691Skan      _M_check_length(__len1, __len2, "__versa_string::_M_replace");
133169691Skan
134169691Skan      const size_type __old_size = this->size();
135169691Skan      const size_type __new_size = __old_size + __len2 - __len1;
136169691Skan      
137169691Skan      if (__new_size <= this->capacity() && !this->_M_is_shared())
138169691Skan	{
139169691Skan	  _CharT* __p = this->_M_data() + __pos;
140169691Skan
141169691Skan	  const size_type __how_much = __old_size - __pos - __len1;
142169691Skan	  if (_M_disjunct(__s))
143169691Skan	    {
144169691Skan	      if (__how_much && __len1 != __len2)
145169691Skan		this->_S_move(__p + __len2, __p + __len1, __how_much);
146169691Skan	      if (__len2)
147169691Skan		this->_S_copy(__p, __s, __len2);
148169691Skan	    }
149169691Skan	  else
150169691Skan	    {
151169691Skan	      // Work in-place.
152169691Skan	      if (__len2 && __len2 <= __len1)
153169691Skan		this->_S_move(__p, __s, __len2);
154169691Skan	      if (__how_much && __len1 != __len2)
155169691Skan		this->_S_move(__p + __len2, __p + __len1, __how_much);
156169691Skan	      if (__len2 > __len1)
157169691Skan		{
158169691Skan		  if (__s + __len2 <= __p + __len1)
159169691Skan		    this->_S_move(__p, __s, __len2);
160169691Skan		  else if (__s >= __p + __len1)
161169691Skan		    this->_S_copy(__p, __s + __len2 - __len1, __len2);
162169691Skan		  else
163169691Skan		    {
164169691Skan		      const size_type __nleft = (__p + __len1) - __s;
165169691Skan		      this->_S_move(__p, __s, __nleft);
166169691Skan		      this->_S_copy(__p + __nleft, __p + __len2,
167169691Skan				    __len2 - __nleft);
168169691Skan		    }
169169691Skan		}
170169691Skan	    }
171169691Skan	}
172169691Skan      else
173169691Skan	this->_M_mutate(__pos, __len1, __s, __len2);
174169691Skan
175169691Skan      this->_M_set_length(__new_size);
176169691Skan      return *this;
177169691Skan    }
178169691Skan  
179169691Skan  template<typename _CharT, typename _Traits, typename _Alloc,
180169691Skan	   template <typename, typename, typename> class _Base>
181169691Skan    __versa_string<_CharT, _Traits, _Alloc, _Base>
182169691Skan    operator+(const __versa_string<_CharT, _Traits, _Alloc, _Base>& __lhs,
183169691Skan	      const __versa_string<_CharT, _Traits, _Alloc, _Base>& __rhs)
184169691Skan    {
185169691Skan      __versa_string<_CharT, _Traits, _Alloc, _Base> __str;
186169691Skan      __str.reserve(__lhs.size() + __rhs.size());
187169691Skan      __str.append(__lhs);
188169691Skan      __str.append(__rhs);
189169691Skan      return __str;
190169691Skan    }
191169691Skan
192169691Skan  template<typename _CharT, typename _Traits, typename _Alloc,
193169691Skan	   template <typename, typename, typename> class _Base>
194169691Skan    __versa_string<_CharT, _Traits, _Alloc, _Base>
195169691Skan    operator+(const _CharT* __lhs,
196169691Skan	      const __versa_string<_CharT, _Traits, _Alloc, _Base>& __rhs)
197169691Skan    {
198169691Skan      __glibcxx_requires_string(__lhs);
199169691Skan      typedef __versa_string<_CharT, _Traits, _Alloc, _Base> __string_type;
200169691Skan      typedef typename __string_type::size_type	  __size_type;
201169691Skan      const __size_type __len = _Traits::length(__lhs);
202169691Skan      __string_type __str;
203169691Skan      __str.reserve(__len + __rhs.size());
204169691Skan      __str.append(__lhs, __len);
205169691Skan      __str.append(__rhs);
206169691Skan      return __str;
207169691Skan    }
208169691Skan
209169691Skan  template<typename _CharT, typename _Traits, typename _Alloc,
210169691Skan	   template <typename, typename, typename> class _Base>
211169691Skan    __versa_string<_CharT, _Traits, _Alloc, _Base>
212169691Skan    operator+(_CharT __lhs,
213169691Skan	      const __versa_string<_CharT, _Traits, _Alloc, _Base>& __rhs)
214169691Skan    {
215169691Skan      __versa_string<_CharT, _Traits, _Alloc, _Base> __str;
216169691Skan      __str.reserve(__rhs.size() + 1);
217169691Skan      __str.push_back(__lhs);
218169691Skan      __str.append(__rhs);
219169691Skan      return __str;
220169691Skan    }
221169691Skan
222169691Skan  template<typename _CharT, typename _Traits, typename _Alloc,
223169691Skan	   template <typename, typename, typename> class _Base>
224169691Skan    __versa_string<_CharT, _Traits, _Alloc, _Base>
225169691Skan    operator+(const __versa_string<_CharT, _Traits, _Alloc, _Base>& __lhs,
226169691Skan	      const _CharT* __rhs)
227169691Skan    {
228169691Skan      __glibcxx_requires_string(__rhs);
229169691Skan      typedef __versa_string<_CharT, _Traits, _Alloc, _Base> __string_type;
230169691Skan      typedef typename __string_type::size_type	  __size_type;
231169691Skan      const __size_type __len = _Traits::length(__rhs);
232169691Skan      __string_type __str;
233169691Skan      __str.reserve(__lhs.size() + __len);
234169691Skan      __str.append(__lhs);
235169691Skan      __str.append(__rhs, __len);
236169691Skan      return __str;
237169691Skan    }
238169691Skan
239169691Skan  template<typename _CharT, typename _Traits, typename _Alloc,
240169691Skan	   template <typename, typename, typename> class _Base>
241169691Skan    __versa_string<_CharT, _Traits, _Alloc, _Base>
242169691Skan    operator+(const __versa_string<_CharT, _Traits, _Alloc, _Base>& __lhs,
243169691Skan	      _CharT __rhs)
244169691Skan    {
245169691Skan      __versa_string<_CharT, _Traits, _Alloc, _Base> __str;
246169691Skan      __str.reserve(__lhs.size() + 1);
247169691Skan      __str.append(__lhs);
248169691Skan      __str.push_back(__rhs);
249169691Skan      return __str;
250169691Skan    }
251169691Skan
252169691Skan  template<typename _CharT, typename _Traits, typename _Alloc,
253169691Skan	   template <typename, typename, typename> class _Base>
254169691Skan    typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
255169691Skan    __versa_string<_CharT, _Traits, _Alloc, _Base>::
256169691Skan    copy(_CharT* __s, size_type __n, size_type __pos) const
257169691Skan    {
258169691Skan      _M_check(__pos, "__versa_string::copy");
259169691Skan      __n = _M_limit(__pos, __n);
260169691Skan      __glibcxx_requires_string_len(__s, __n);
261169691Skan      if (__n)
262169691Skan	this->_S_copy(__s, this->_M_data() + __pos, __n);
263169691Skan      // 21.3.5.7 par 3: do not append null.  (good.)
264169691Skan      return __n;
265169691Skan    }
266169691Skan
267169691Skan  template<typename _CharT, typename _Traits, typename _Alloc,
268169691Skan	   template <typename, typename, typename> class _Base>
269169691Skan    typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
270169691Skan    __versa_string<_CharT, _Traits, _Alloc, _Base>::
271169691Skan    find(const _CharT* __s, size_type __pos, size_type __n) const
272169691Skan    {
273169691Skan      __glibcxx_requires_string_len(__s, __n);
274169691Skan      const size_type __size = this->size();
275169691Skan      const _CharT* __data = this->_M_data();
276169691Skan
277169691Skan      if (__n == 0)
278169691Skan	return __pos <= __size ? __pos : npos;
279169691Skan
280169691Skan      if (__n <= __size)
281169691Skan	{
282169691Skan	  for (; __pos <= __size - __n; ++__pos)
283169691Skan	    if (traits_type::eq(__data[__pos], __s[0])
284169691Skan		&& traits_type::compare(__data + __pos + 1,
285169691Skan					__s + 1, __n - 1) == 0)
286169691Skan	      return __pos;
287169691Skan	}
288169691Skan      return npos;
289169691Skan    }
290169691Skan
291169691Skan  template<typename _CharT, typename _Traits, typename _Alloc,
292169691Skan	   template <typename, typename, typename> class _Base>
293169691Skan    typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
294169691Skan    __versa_string<_CharT, _Traits, _Alloc, _Base>::
295169691Skan    find(_CharT __c, size_type __pos) const
296169691Skan    {
297169691Skan      size_type __ret = npos;
298169691Skan      const size_type __size = this->size();
299169691Skan      if (__pos < __size)
300169691Skan	{
301169691Skan	  const _CharT* __data = this->_M_data();
302169691Skan	  const size_type __n = __size - __pos;
303169691Skan	  const _CharT* __p = traits_type::find(__data + __pos, __n, __c);
304169691Skan	  if (__p)
305169691Skan	    __ret = __p - __data;
306169691Skan	}
307169691Skan      return __ret;
308169691Skan    }
309169691Skan
310169691Skan  template<typename _CharT, typename _Traits, typename _Alloc,
311169691Skan	   template <typename, typename, typename> class _Base>
312169691Skan    typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
313169691Skan    __versa_string<_CharT, _Traits, _Alloc, _Base>::
314169691Skan    rfind(const _CharT* __s, size_type __pos, size_type __n) const
315169691Skan    {
316169691Skan      __glibcxx_requires_string_len(__s, __n);
317169691Skan      const size_type __size = this->size();
318169691Skan      if (__n <= __size)
319169691Skan	{
320169691Skan	  __pos = std::min(size_type(__size - __n), __pos);
321169691Skan	  const _CharT* __data = this->_M_data();
322169691Skan	  do
323169691Skan	    {
324169691Skan	      if (traits_type::compare(__data + __pos, __s, __n) == 0)
325169691Skan		return __pos;
326169691Skan	    }
327169691Skan	  while (__pos-- > 0);
328169691Skan	}
329169691Skan      return npos;
330169691Skan    }
331169691Skan
332169691Skan  template<typename _CharT, typename _Traits, typename _Alloc,
333169691Skan	   template <typename, typename, typename> class _Base>
334169691Skan    typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
335169691Skan    __versa_string<_CharT, _Traits, _Alloc, _Base>::
336169691Skan    rfind(_CharT __c, size_type __pos) const
337169691Skan    {
338169691Skan      size_type __size = this->size();
339169691Skan      if (__size)
340169691Skan	{
341169691Skan	  if (--__size > __pos)
342169691Skan	    __size = __pos;
343169691Skan	  for (++__size; __size-- > 0; )
344169691Skan	    if (traits_type::eq(this->_M_data()[__size], __c))
345169691Skan	      return __size;
346169691Skan	}
347169691Skan      return npos;
348169691Skan    }
349169691Skan
350169691Skan  template<typename _CharT, typename _Traits, typename _Alloc,
351169691Skan	   template <typename, typename, typename> class _Base>
352169691Skan    typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
353169691Skan    __versa_string<_CharT, _Traits, _Alloc, _Base>::
354169691Skan    find_first_of(const _CharT* __s, size_type __pos, size_type __n) const
355169691Skan    {
356169691Skan      __glibcxx_requires_string_len(__s, __n);
357169691Skan      for (; __n && __pos < this->size(); ++__pos)
358169691Skan	{
359169691Skan	  const _CharT* __p = traits_type::find(__s, __n,
360169691Skan						this->_M_data()[__pos]);
361169691Skan	  if (__p)
362169691Skan	    return __pos;
363169691Skan	}
364169691Skan      return npos;
365169691Skan    }
366169691Skan
367169691Skan  template<typename _CharT, typename _Traits, typename _Alloc,
368169691Skan	   template <typename, typename, typename> class _Base>
369169691Skan    typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
370169691Skan    __versa_string<_CharT, _Traits, _Alloc, _Base>::
371169691Skan    find_last_of(const _CharT* __s, size_type __pos, size_type __n) const
372169691Skan    {
373169691Skan      __glibcxx_requires_string_len(__s, __n);
374169691Skan      size_type __size = this->size();
375169691Skan      if (__size && __n)
376169691Skan	{
377169691Skan	  if (--__size > __pos)
378169691Skan	    __size = __pos;
379169691Skan	  do
380169691Skan	    {
381169691Skan	      if (traits_type::find(__s, __n, this->_M_data()[__size]))
382169691Skan		return __size;
383169691Skan	    }
384169691Skan	  while (__size-- != 0);
385169691Skan	}
386169691Skan      return npos;
387169691Skan    }
388169691Skan
389169691Skan  template<typename _CharT, typename _Traits, typename _Alloc,
390169691Skan	   template <typename, typename, typename> class _Base>
391169691Skan    typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
392169691Skan    __versa_string<_CharT, _Traits, _Alloc, _Base>::
393169691Skan    find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const
394169691Skan    {
395169691Skan      __glibcxx_requires_string_len(__s, __n);
396169691Skan      for (; __pos < this->size(); ++__pos)
397169691Skan	if (!traits_type::find(__s, __n, this->_M_data()[__pos]))
398169691Skan	  return __pos;
399169691Skan      return npos;
400169691Skan    }
401169691Skan
402169691Skan  template<typename _CharT, typename _Traits, typename _Alloc,
403169691Skan	   template <typename, typename, typename> class _Base>
404169691Skan    typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
405169691Skan    __versa_string<_CharT, _Traits, _Alloc, _Base>::
406169691Skan    find_first_not_of(_CharT __c, size_type __pos) const
407169691Skan    {
408169691Skan      for (; __pos < this->size(); ++__pos)
409169691Skan	if (!traits_type::eq(this->_M_data()[__pos], __c))
410169691Skan	  return __pos;
411169691Skan      return npos;
412169691Skan    }
413169691Skan
414169691Skan  template<typename _CharT, typename _Traits, typename _Alloc,
415169691Skan	   template <typename, typename, typename> class _Base>
416169691Skan    typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
417169691Skan    __versa_string<_CharT, _Traits, _Alloc, _Base>::
418169691Skan    find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const
419169691Skan    {
420169691Skan      __glibcxx_requires_string_len(__s, __n);
421169691Skan      size_type __size = this->size();
422169691Skan      if (__size)
423169691Skan	{
424169691Skan	  if (--__size > __pos)
425169691Skan	    __size = __pos;
426169691Skan	  do
427169691Skan	    {
428169691Skan	      if (!traits_type::find(__s, __n, this->_M_data()[__size]))
429169691Skan		return __size;
430169691Skan	    }
431169691Skan	  while (__size--);
432169691Skan	}
433169691Skan      return npos;
434169691Skan    }
435169691Skan
436169691Skan  template<typename _CharT, typename _Traits, typename _Alloc,
437169691Skan	   template <typename, typename, typename> class _Base>
438169691Skan    typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
439169691Skan    __versa_string<_CharT, _Traits, _Alloc, _Base>::
440169691Skan    find_last_not_of(_CharT __c, size_type __pos) const
441169691Skan    {
442169691Skan      size_type __size = this->size();
443169691Skan      if (__size)
444169691Skan	{
445169691Skan	  if (--__size > __pos)
446169691Skan	    __size = __pos;
447169691Skan	  do
448169691Skan	    {
449169691Skan	      if (!traits_type::eq(this->_M_data()[__size], __c))
450169691Skan		return __size;
451169691Skan	    }
452169691Skan	  while (__size--);
453169691Skan	}
454169691Skan      return npos;
455169691Skan    }
456169691Skan
457169691Skan  template<typename _CharT, typename _Traits, typename _Alloc,
458169691Skan	   template <typename, typename, typename> class _Base>
459169691Skan    int
460169691Skan    __versa_string<_CharT, _Traits, _Alloc, _Base>::
461169691Skan    compare(size_type __pos, size_type __n, const __versa_string& __str) const
462169691Skan    {
463169691Skan      _M_check(__pos, "__versa_string::compare");
464169691Skan      __n = _M_limit(__pos, __n);
465169691Skan      const size_type __osize = __str.size();
466169691Skan      const size_type __len = std::min(__n, __osize);
467169691Skan      int __r = traits_type::compare(this->_M_data() + __pos,
468169691Skan				     __str.data(), __len);
469169691Skan      if (!__r)
470169691Skan	__r = __n - __osize;
471169691Skan      return __r;
472169691Skan    }
473169691Skan
474169691Skan  template<typename _CharT, typename _Traits, typename _Alloc,
475169691Skan	   template <typename, typename, typename> class _Base>
476169691Skan    int
477169691Skan    __versa_string<_CharT, _Traits, _Alloc, _Base>::
478169691Skan    compare(size_type __pos1, size_type __n1, const __versa_string& __str,
479169691Skan	    size_type __pos2, size_type __n2) const
480169691Skan    {
481169691Skan      _M_check(__pos1, "__versa_string::compare");
482169691Skan      __str._M_check(__pos2, "__versa_string::compare");
483169691Skan      __n1 = _M_limit(__pos1, __n1);
484169691Skan      __n2 = __str._M_limit(__pos2, __n2);
485169691Skan      const size_type __len = std::min(__n1, __n2);
486169691Skan      int __r = traits_type::compare(this->_M_data() + __pos1,
487169691Skan				     __str.data() + __pos2, __len);
488169691Skan      if (!__r)
489169691Skan	__r = __n1 - __n2;
490169691Skan      return __r;
491169691Skan    }
492169691Skan
493169691Skan  template<typename _CharT, typename _Traits, typename _Alloc,
494169691Skan	   template <typename, typename, typename> class _Base>
495169691Skan    int
496169691Skan    __versa_string<_CharT, _Traits, _Alloc, _Base>::
497169691Skan    compare(const _CharT* __s) const
498169691Skan    {
499169691Skan      __glibcxx_requires_string(__s);
500169691Skan      const size_type __size = this->size();
501169691Skan      const size_type __osize = traits_type::length(__s);
502169691Skan      const size_type __len = std::min(__size, __osize);
503169691Skan      int __r = traits_type::compare(this->_M_data(), __s, __len);
504169691Skan      if (!__r)
505169691Skan	__r = __size - __osize;
506169691Skan      return __r;
507169691Skan    }
508169691Skan
509169691Skan  template<typename _CharT, typename _Traits, typename _Alloc,
510169691Skan	   template <typename, typename, typename> class _Base>
511169691Skan    int
512169691Skan    __versa_string <_CharT, _Traits, _Alloc, _Base>::
513169691Skan    compare(size_type __pos, size_type __n1, const _CharT* __s) const
514169691Skan    {
515169691Skan      __glibcxx_requires_string(__s);
516169691Skan      _M_check(__pos, "__versa_string::compare");
517169691Skan      __n1 = _M_limit(__pos, __n1);
518169691Skan      const size_type __osize = traits_type::length(__s);
519169691Skan      const size_type __len = std::min(__n1, __osize);
520169691Skan      int __r = traits_type::compare(this->_M_data() + __pos, __s, __len);
521169691Skan      if (!__r)
522169691Skan	__r = __n1 - __osize;
523169691Skan      return __r;
524169691Skan    }
525169691Skan
526169691Skan  template<typename _CharT, typename _Traits, typename _Alloc,
527169691Skan	   template <typename, typename, typename> class _Base>
528169691Skan    int
529169691Skan    __versa_string <_CharT, _Traits, _Alloc, _Base>::
530169691Skan    compare(size_type __pos, size_type __n1, const _CharT* __s,
531169691Skan	    size_type __n2) const
532169691Skan    {
533169691Skan      __glibcxx_requires_string_len(__s, __n2);
534169691Skan      _M_check(__pos, "__versa_string::compare");
535169691Skan      __n1 = _M_limit(__pos, __n1);
536169691Skan      const size_type __len = std::min(__n1, __n2);
537169691Skan      int __r = traits_type::compare(this->_M_data() + __pos, __s, __len);
538169691Skan      if (!__r)
539169691Skan	__r = __n1 - __n2;
540169691Skan      return __r;
541169691Skan    }
542169691Skan
543169691Skan_GLIBCXX_END_NAMESPACE
544169691Skan
545169691Skan_GLIBCXX_BEGIN_NAMESPACE(std)
546169691Skan
547169691Skan  template<typename _CharT, typename _Traits, typename _Alloc,
548169691Skan           template <typename, typename, typename> class _Base>
549169691Skan    basic_istream<_CharT, _Traits>&
550169691Skan    operator>>(basic_istream<_CharT, _Traits>& __in,
551169691Skan	       __gnu_cxx::__versa_string<_CharT, _Traits,
552169691Skan	                                 _Alloc, _Base>& __str)
553169691Skan    {
554169691Skan      typedef basic_istream<_CharT, _Traits>	        __istream_type;
555169691Skan      typedef typename __istream_type::int_type		__int_type;
556169691Skan      typedef typename __istream_type::__streambuf_type __streambuf_type;
557169691Skan      typedef typename __istream_type::__ctype_type	__ctype_type;
558169691Skan      typedef __gnu_cxx::__versa_string<_CharT, _Traits, _Alloc, _Base>
559169691Skan	                                                __string_type;
560169691Skan      typedef typename __string_type::size_type		__size_type;
561169691Skan
562169691Skan      __size_type __extracted = 0;
563169691Skan      ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
564169691Skan      typename __istream_type::sentry __cerb(__in, false);
565169691Skan      if (__cerb)
566169691Skan	{
567169691Skan	  try
568169691Skan	    {
569169691Skan	      // Avoid reallocation for common case.
570169691Skan	      __str.erase();
571169691Skan	      _CharT __buf[128];
572169691Skan	      __size_type __len = 0;
573169691Skan	      const streamsize __w = __in.width();
574169691Skan	      const __size_type __n = __w > 0 ? static_cast<__size_type>(__w)
575169691Skan		                              : __str.max_size();
576169691Skan	      const __ctype_type& __ct = use_facet<__ctype_type>(__in.getloc());
577169691Skan	      const __int_type __eof = _Traits::eof();
578169691Skan	      __streambuf_type* __sb = __in.rdbuf();
579169691Skan	      __int_type __c = __sb->sgetc();
580169691Skan
581169691Skan	      while (__extracted < __n
582169691Skan		     && !_Traits::eq_int_type(__c, __eof)
583169691Skan		     && !__ct.is(ctype_base::space, _Traits::to_char_type(__c)))
584169691Skan		{
585169691Skan		  if (__len == sizeof(__buf) / sizeof(_CharT))
586169691Skan		    {
587169691Skan		      __str.append(__buf, sizeof(__buf) / sizeof(_CharT));
588169691Skan		      __len = 0;
589169691Skan		    }
590169691Skan		  __buf[__len++] = _Traits::to_char_type(__c);
591169691Skan		  ++__extracted;
592169691Skan		  __c = __sb->snextc();
593169691Skan		}
594169691Skan	      __str.append(__buf, __len);
595169691Skan
596169691Skan	      if (_Traits::eq_int_type(__c, __eof))
597169691Skan		__err |= ios_base::eofbit;
598169691Skan	      __in.width(0);
599169691Skan	    }
600169691Skan	  catch(...)
601169691Skan	    {
602169691Skan	      // _GLIBCXX_RESOLVE_LIB_DEFECTS
603169691Skan	      // 91. Description of operator>> and getline() for string<>
604169691Skan	      // might cause endless loop
605169691Skan	      __in._M_setstate(ios_base::badbit);
606169691Skan	    }
607169691Skan	}
608169691Skan      // 211.  operator>>(istream&, string&) doesn't set failbit
609169691Skan      if (!__extracted)
610169691Skan	__err |= ios_base::failbit;
611169691Skan      if (__err)
612169691Skan	__in.setstate(__err);
613169691Skan      return __in;
614169691Skan    }      
615169691Skan
616169691Skan  template<typename _CharT, typename _Traits, typename _Alloc,
617169691Skan           template <typename, typename, typename> class _Base>
618169691Skan    basic_istream<_CharT, _Traits>&
619169691Skan    getline(basic_istream<_CharT, _Traits>& __in,
620169691Skan	    __gnu_cxx::__versa_string<_CharT, _Traits, _Alloc, _Base>& __str,
621169691Skan	    _CharT __delim)
622169691Skan    {
623169691Skan      typedef basic_istream<_CharT, _Traits>	        __istream_type;
624169691Skan      typedef typename __istream_type::int_type		__int_type;
625169691Skan      typedef typename __istream_type::__streambuf_type __streambuf_type;
626169691Skan      typedef typename __istream_type::__ctype_type	__ctype_type;
627169691Skan      typedef __gnu_cxx::__versa_string<_CharT, _Traits, _Alloc, _Base>
628169691Skan	                                                __string_type;
629169691Skan      typedef typename __string_type::size_type		__size_type;
630169691Skan
631169691Skan      __size_type __extracted = 0;
632169691Skan      const __size_type __n = __str.max_size();
633169691Skan      ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
634169691Skan      typename __istream_type::sentry __cerb(__in, true);
635169691Skan      if (__cerb)
636169691Skan	{
637169691Skan	  try
638169691Skan	    {
639169691Skan	      // Avoid reallocation for common case.
640169691Skan	      __str.erase();
641169691Skan	      _CharT __buf[128];
642169691Skan	      __size_type __len = 0;
643169691Skan	      const __int_type __idelim = _Traits::to_int_type(__delim);
644169691Skan	      const __int_type __eof = _Traits::eof();
645169691Skan	      __streambuf_type* __sb = __in.rdbuf();
646169691Skan	      __int_type __c = __sb->sgetc();
647169691Skan
648169691Skan	      while (__extracted < __n
649169691Skan		     && !_Traits::eq_int_type(__c, __eof)
650169691Skan		     && !_Traits::eq_int_type(__c, __idelim))
651169691Skan		{
652169691Skan		  if (__len == sizeof(__buf) / sizeof(_CharT))
653169691Skan		    {
654169691Skan		      __str.append(__buf, sizeof(__buf) / sizeof(_CharT));
655169691Skan		      __len = 0;
656169691Skan		    }
657169691Skan		  __buf[__len++] = _Traits::to_char_type(__c);
658169691Skan		  ++__extracted;
659169691Skan		  __c = __sb->snextc();
660169691Skan		}
661169691Skan	      __str.append(__buf, __len);
662169691Skan
663169691Skan	      if (_Traits::eq_int_type(__c, __eof))
664169691Skan		__err |= ios_base::eofbit;
665169691Skan	      else if (_Traits::eq_int_type(__c, __idelim))
666169691Skan		{
667169691Skan		  ++__extracted;		  
668169691Skan		  __sb->sbumpc();
669169691Skan		}
670169691Skan	      else
671169691Skan		__err |= ios_base::failbit;
672169691Skan	    }
673169691Skan	  catch(...)
674169691Skan	    {
675169691Skan	      // _GLIBCXX_RESOLVE_LIB_DEFECTS
676169691Skan	      // 91. Description of operator>> and getline() for string<>
677169691Skan	      // might cause endless loop
678169691Skan	      __in._M_setstate(ios_base::badbit);
679169691Skan	    }
680169691Skan	}
681169691Skan      if (!__extracted)
682169691Skan	__err |= ios_base::failbit;
683169691Skan      if (__err)
684169691Skan	__in.setstate(__err);
685169691Skan      return __in;
686169691Skan    }      
687169691Skan  
688169691Skan_GLIBCXX_END_NAMESPACE
689169691Skan
690169691Skan#endif // _VSTRING_TCC
691