OSDN Git Service

2001-01-12 Benjamin Kosnik <bkoz@redhat.com>
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / include / bits / basic_string.tcc
1 // Components for manipulating sequences of characters -*- C++ -*-
2
3 // Copyright (C) 1997, 1998, 1999, 2000, 2001 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
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 //
31 // ISO C++ 14882: 21  Strings library
32 //
33
34 // This file is included by <string>.  It is not meant to be included
35 // separately.
36
37 // Written by Jason Merrill based upon the specification by Takanori Adachi
38 // in ANSI X3J16/94-0013R2.  Rewritten by Nathan Myers to ISO-14882.
39
40 #ifndef _CPP_BITS_STRING_TCC
41 #define _CPP_BITS_STRING_TCC 1
42
43 namespace std
44 {
45   template<typename _CharT, typename _Traits, typename _Alloc>
46     const _CharT 
47     basic_string<_CharT, _Traits, _Alloc>::
48     _Rep::_S_terminal = _CharT();
49
50   template<typename _CharT, typename _Traits, typename _Alloc>
51     const typename basic_string<_CharT, _Traits, _Alloc>::size_type 
52     basic_string<_CharT, _Traits, _Alloc>::
53     _Rep::_S_max_size = (((npos - sizeof(_Rep))/sizeof(_CharT)) - 1) / 4;
54
55   template<typename _CharT, typename _Traits, typename _Alloc>
56     const typename basic_string<_CharT, _Traits, _Alloc>::size_type
57     basic_string<_CharT, _Traits, _Alloc>::npos;
58
59   // Linker sets _S_empty_rep_storage to all 0s (one reference, empty string)
60   // at static init time (before static ctors are run).
61   template<typename _CharT, typename _Traits, typename _Alloc>
62     typename basic_string<_CharT, _Traits, _Alloc>::size_type
63     basic_string<_CharT, _Traits, _Alloc>::_S_empty_rep_storage[
64     (sizeof(_Rep) + sizeof(_CharT) + sizeof(size_type) - 1)/sizeof(size_type)];
65
66   // NB: This is the special case for Input Iterators, used in
67   // istreambuf_iterators, etc.
68   // Input Iterators have a cost structure very different from
69   // pointers, calling for a different coding style.
70   template<typename _CharT, typename _Traits, typename _Alloc>
71     template<typename _InIter>
72       _CharT*
73       basic_string<_CharT, _Traits, _Alloc>::
74       _S_construct(_InIter __beg, _InIter __end, const _Alloc& __a,
75                    input_iterator_tag)
76       {
77         if (__beg == __end && __a == _Alloc())
78           return _S_empty_rep()._M_refcopy();
79         // Avoid reallocation for common case.
80         _CharT __buf[100];
81         size_type __i = 0;
82         while (__beg != __end && __i < sizeof(__buf) / sizeof(_CharT))
83           { 
84             __buf[__i++] = *__beg; 
85             ++__beg; 
86           }
87         _Rep* __r = _Rep::_S_create(__i, __a);
88         traits_type::copy(__r->_M_refdata(), __buf, __i);
89         __r->_M_length = __i;
90         try {
91           // NB: this loop looks precisely this way because
92           // it avoids comparing __beg != __end any more
93           // than strictly necessary; != might be expensive!
94           for (;;)
95             {
96               _CharT* __p = __r->_M_refdata() + __r->_M_length;
97               _CharT* __last = __r->_M_refdata() + __r->_M_capacity;
98               for (;;)
99                 {
100                   if (__beg == __end)
101                     {
102                       __r->_M_length = __p - __r->_M_refdata();
103                       *__p = _Rep::_S_terminal;       // grrr.
104                       return __r->_M_refdata();
105                     }
106                   if (__p == __last)
107                     break;
108                   *__p++ = *__beg; 
109                   ++__beg;
110                 }
111               // Allocate more space.
112               size_type __len = __p - __r->_M_refdata();
113               _Rep* __another = _Rep::_S_create(__len + 1, __a);
114               traits_type::copy(__another->_M_refdata(), 
115                                 __r->_M_refdata(), __len);
116               __r->_M_destroy(__a);
117               __r = __another;
118               __r->_M_length = __len;
119             }
120         }
121         catch (...) {
122             __r->_M_destroy(__a); 
123             throw;
124         }
125         return 0;
126       }
127
128   template<typename _CharT, typename _Traits, typename _Alloc>
129     template <class _InIter>
130       _CharT*
131       basic_string<_CharT,_Traits,_Alloc>::
132       _S_construct(_InIter __beg, _InIter __end, const _Alloc& __a, 
133                    forward_iterator_tag)
134       {
135         size_type __dnew = static_cast<size_type>(distance(__beg, __end));
136
137         if (__beg == __end && __a == _Alloc())
138           return _S_empty_rep()._M_refcopy();
139
140         // Check for out_of_range and length_error exceptions.
141         _Rep* __r = _Rep::_S_create(__dnew, __a);
142         try { 
143           _S_copy_chars(__r->_M_refdata(), __beg, __end); 
144         }
145         catch (...) { 
146           __r->_M_destroy(__a); 
147           throw; 
148         }
149         __r->_M_length = __dnew;
150
151         __r->_M_refdata()[__dnew] = _Rep::_S_terminal;  // grrr.
152         return __r->_M_refdata();
153       }
154
155   template<typename _CharT, typename _Traits, typename _Alloc>
156     _CharT*
157     basic_string<_CharT,_Traits, _Alloc>::
158     _S_construct(size_type __n, _CharT __c, const _Alloc& __a)
159     {
160       if (__n == 0 && __a == _Alloc())
161         return _S_empty_rep()._M_refcopy();
162
163       // Check for out_of_range and length_error exceptions.
164       _Rep* __r = _Rep::_S_create(__n, __a);
165       try { 
166         if (__n) 
167           traits_type::assign(__r->_M_refdata(), __n, __c); 
168       }
169       catch (...) { 
170         __r->_M_destroy(__a); 
171         throw; 
172       }
173       __r->_M_length = __n;
174       __r->_M_refdata()[__n] = _Rep::_S_terminal;  // grrr
175       return __r->_M_refdata();
176     }
177
178   template<typename _CharT, typename _Traits, typename _Alloc>
179     basic_string<_CharT, _Traits, _Alloc>::
180     basic_string(const basic_string& __str)
181     : _M_dataplus(__str._M_rep()->_M_grab(_Alloc(), __str.get_allocator()),
182                  __str.get_allocator())
183     { }
184
185   template<typename _CharT, typename _Traits, typename _Alloc>
186     basic_string<_CharT, _Traits, _Alloc>::
187     basic_string(const _Alloc& __a)
188     : _M_dataplus(_S_construct(size_type(), _CharT(), __a), __a)
189     { }
190  
191   template<typename _CharT, typename _Traits, typename _Alloc>
192     basic_string<_CharT, _Traits, _Alloc>::
193     basic_string(const basic_string& __str, size_type __pos, size_type __n)
194     : _M_dataplus(_S_construct(__str._M_check(__pos), 
195                                __str._M_fold(__pos, __n), _Alloc()), _Alloc())
196     { }
197
198   template<typename _CharT, typename _Traits, typename _Alloc>
199     basic_string<_CharT, _Traits, _Alloc>::
200     basic_string(const basic_string& __str, size_type __pos,
201                  size_type __n, const _Alloc& __a)
202     : _M_dataplus(_S_construct(__str._M_check(__pos), 
203                                __str._M_fold(__pos, __n), __a), __a)
204     { }
205
206   template<typename _CharT, typename _Traits, typename _Alloc>
207     basic_string<_CharT, _Traits, _Alloc>::
208     basic_string(const _CharT* __s, size_type __n, const _Alloc& __a)
209     : _M_dataplus(_S_construct(__s, __s + __n, __a), __a)
210     { }
211
212   template<typename _CharT, typename _Traits, typename _Alloc>
213     basic_string<_CharT, _Traits, _Alloc>::
214     basic_string(const _CharT* __s, const _Alloc& __a)
215     : _M_dataplus(_S_construct(__s, __s + traits_type::length(__s), __a), __a)
216     { }
217
218   template<typename _CharT, typename _Traits, typename _Alloc>
219     basic_string<_CharT, _Traits, _Alloc>::
220     basic_string(size_type __n, _CharT __c, const _Alloc& __a)
221     : _M_dataplus(_S_construct(__n, __c, __a), __a)
222     { }
223  
224   template<typename _CharT, typename _Traits, typename _Alloc>
225     template<typename _InputIter>
226     basic_string<_CharT, _Traits, _Alloc>::
227     basic_string(_InputIter __beg, _InputIter __end, const _Alloc& __a)
228     : _M_dataplus(_S_construct(__beg, __end, __a), __a)
229     { }
230
231   template<typename _CharT, typename _Traits, typename _Alloc>
232     basic_string<_CharT, _Traits, _Alloc>&
233     basic_string<_CharT, _Traits, _Alloc>::assign(const basic_string& __str)
234     {
235       if (_M_rep() != __str._M_rep())
236         {
237           // XXX MT
238           allocator_type __a = this->get_allocator();
239           _CharT* __tmp = __str._M_rep()->_M_grab(__a, __str.get_allocator());
240           _M_rep()->_M_dispose(__a);
241           _M_data(__tmp);
242         }
243       return *this;
244     }
245   
246   template<typename _CharT, typename _Traits, typename _Alloc>
247     void
248     basic_string<_CharT, _Traits, _Alloc>::_Rep::
249     _M_destroy(const _Alloc& __a) throw ()
250     {
251       size_type __size = sizeof(_Rep) + (_M_capacity + 1) * sizeof(_CharT);
252       _Raw_bytes_alloc(__a).deallocate(reinterpret_cast<char*>(this), __size);
253     }
254
255   template<typename _CharT, typename _Traits, typename _Alloc>
256     void
257     basic_string<_CharT, _Traits, _Alloc>::_M_leak_hard()
258     {
259       if (_M_rep()->_M_is_shared()) 
260         _M_mutate(0, 0, 0);
261       _M_rep()->_M_set_leaked();
262     }
263
264   template<typename _CharT, typename _Traits, typename _Alloc>
265     void
266     basic_string<_CharT, _Traits, _Alloc>::
267     _M_mutate(size_type __pos, size_type __len1, size_type __len2)
268     {
269       size_type       __old_size = this->size();
270       const size_type __new_size = __old_size + __len2 - __len1;
271       const _CharT*        __src = _M_data()  + __pos + __len1;
272       const size_type __how_much = __old_size - __pos - __len1;
273       
274       if (_M_rep()->_M_is_shared() || __new_size > capacity())
275         {
276           // Must reallocate.
277           allocator_type __a = get_allocator();
278           _Rep* __r = _Rep::_S_create(__new_size, __a);
279           try {
280             if (__pos)
281               traits_type::copy(__r->_M_refdata(), _M_data(), __pos);
282             if (__how_much)
283               traits_type::copy(__r->_M_refdata() + __pos + __len2, 
284                                 __src, __how_much);
285           }
286           catch (...) { 
287             __r->_M_dispose(get_allocator()); 
288             throw; 
289           }
290           _M_rep()->_M_dispose(__a);
291           _M_data(__r->_M_refdata());
292       }
293       else if (__how_much && __len1 != __len2)
294         {
295           // Work in-place
296           traits_type::move(_M_data() + __pos + __len2, __src, __how_much);
297         }
298       _M_rep()->_M_set_sharable();
299       _M_rep()->_M_length = __new_size;
300       _M_data()[__new_size] = _Rep::_S_terminal; // grrr. (per 21.3.4)
301     // You cannot leave those LWG people alone for a second.
302     }
303   
304   template<typename _CharT, typename _Traits, typename _Alloc>
305     void
306     basic_string<_CharT, _Traits, _Alloc>::reserve(size_type __res)
307     {
308       if (__res > this->capacity() || _M_rep()->_M_is_shared())
309         {
310           __LENGTHERROR(__res > this->max_size());
311           allocator_type __a = get_allocator();
312           _CharT* __tmp = _M_rep()->_M_clone(__a, __res - this->size());
313           _M_rep()->_M_dispose(__a);
314           _M_data(__tmp);
315         }
316     }
317   
318   template<typename _CharT, typename _Traits, typename _Alloc>
319     void basic_string<_CharT, _Traits, _Alloc>::swap(basic_string& __s)
320     {
321       if (_M_rep()->_M_is_leaked()) 
322         _M_rep()->_M_set_sharable();
323       if (__s._M_rep()->_M_is_leaked()) 
324         __s._M_rep()->_M_set_sharable();
325       if (this->get_allocator() == __s.get_allocator())
326         {
327           _CharT* __tmp = _M_data();
328           _M_data(__s._M_data());
329           __s._M_data(__tmp);
330         }
331       // The code below can usually be optimized away.
332       else 
333         {
334           basic_string __tmp1(_M_ibegin(), _M_iend(), __s.get_allocator());
335           basic_string __tmp2(__s._M_ibegin(), __s._M_iend(), 
336                               this->get_allocator());
337           *this = __tmp2;
338           __s = __tmp1;
339         }
340     }
341
342 #ifdef _GLIBCPP_ALLOC_CONTROL
343   template<typename _CharT, typename _Traits, typename _Alloc>
344     bool (*basic_string<_CharT, _Traits, _Alloc>::_Rep::_S_excess_slop) 
345     (size_t, size_t) = 
346     basic_string<_CharT, _Traits, _Alloc>::_Rep::_S_default_excess;
347 #endif
348
349   template<typename _CharT, typename _Traits, typename _Alloc>
350     basic_string<_CharT, _Traits, _Alloc>::_Rep*
351     basic_string<_CharT, _Traits, _Alloc>::_Rep::
352     _S_create(size_t __capacity, const _Alloc& __alloc)
353     {
354 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
355       // 83.  String::npos vs. string::max_size()
356       typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
357       __LENGTHERROR(__capacity > _S_max_size);
358 #else
359       __LENGTHERROR(__capacity == npos);
360 #endif
361
362       // NB: Need an array of char_type[__capacity], plus a
363       // terminating null char_type() element, plus enough for the
364       // _Rep data structure. Whew. Seemingly so needy, yet so elemental.
365       size_t __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep);
366       // NB: Might throw, but no worries about a leak, mate: _Rep()
367       // does not throw.
368       void* __place = _Raw_bytes_alloc(__alloc).allocate(__size);
369       _Rep *__p = new (__place) _Rep;
370       __p->_M_capacity = __capacity;
371       __p->_M_set_sharable();  // one reference
372       __p->_M_length = 0;
373       return __p;
374     }
375
376   template<typename _CharT, typename _Traits, typename _Alloc>
377     _CharT*
378     basic_string<_CharT, _Traits, _Alloc>::_Rep::
379     _M_clone(const _Alloc& __alloc, size_type __res)
380     {
381       _Rep* __r = _Rep::_S_create(_M_length + __res, __alloc);
382       if (_M_length)
383         {
384           try { 
385             traits_type::copy(__r->_M_refdata(), _M_refdata(), _M_length); 
386           }
387           catch (...)  { 
388             __r->_M_destroy(__alloc); 
389             throw; 
390           }
391         }
392       __r->_M_length = _M_length;
393       return __r->_M_refdata();
394     }
395   
396   template<typename _CharT, typename _Traits, typename _Alloc>
397   inline bool
398 #ifdef _GLIBCPP_ALLOC_CONTROL
399     basic_string<_CharT, _Traits, _Alloc>::_Rep::
400     _S_default_excess(size_t __s, size_t __r)
401 #else
402     basic_string<_CharT, _Traits, _Alloc>::_Rep::
403     _S_excess_slop(size_t __s, size_t __r)
404 #endif
405     {
406       return 2 * (__s <= 16 ? 16 : __s) < __r;
407     }
408   
409   template<typename _CharT, typename _Traits, typename _Alloc>
410     void
411     basic_string<_CharT, _Traits, _Alloc>::resize(size_type __n, _CharT __c)
412     {
413       __LENGTHERROR(__n > max_size());
414       size_type __size = this->size();
415       if (__size < __n)
416         this->append(__n - __size, __c);
417       else if (__n < __size)
418         this->erase(__n);
419       // else nothing (in particular, avoid calling _M_mutate() unnecessarily.)
420     }
421   
422   template<typename _CharT, typename _Traits, typename _Alloc>
423     template<typename _InputIter>
424       basic_string<_CharT, _Traits, _Alloc>&
425       basic_string<_CharT, _Traits, _Alloc>::
426       _M_replace(iterator __i1, iterator __i2, _InputIter __k1, 
427                  _InputIter __k2, input_iterator_tag)
428       {
429         basic_string __s(__k1, __k2);
430         return this->replace(__i1, __i2, __s._M_ibegin(), __s._M_iend());
431       }
432
433   template<typename _CharT, typename _Traits, typename _Alloc>
434     template<typename _ForwardIter>
435       basic_string<_CharT, _Traits, _Alloc>&
436       basic_string<_CharT, _Traits, _Alloc>::
437       _M_replace(iterator __i1, iterator __i2, _ForwardIter __k1, 
438                  _ForwardIter __k2, forward_iterator_tag)
439       {
440         size_type __dold = __i2 - __i1;
441         size_type __dmax = this->max_size();
442         size_type __dnew = static_cast<size_type>(distance(__k1, __k2));
443
444         __LENGTHERROR(__dmax <= __dnew);
445         size_type __off = __i1 - _M_ibegin();
446         _M_mutate(__off, __dold, __dnew);
447         // Invalidated __i1, __i2
448         if (__dnew)
449           _S_copy_chars(_M_data() + __off, __k1, __k2);
450         
451         return *this;
452       }
453
454   template<typename _CharT, typename _Traits, typename _Alloc>
455     basic_string<_CharT, _Traits, _Alloc>&
456     basic_string<_CharT, _Traits, _Alloc>::
457     replace(size_type __pos1, size_type __n1, const basic_string& __str,
458             size_type __pos2, size_type __n2)
459     {
460       return this->replace(_M_check(__pos1), _M_fold(__pos1, __n1),
461                            __str._M_check(__pos2), 
462                            __str._M_fold(__pos2, __n2));
463     }
464
465   template<typename _CharT, typename _Traits, typename _Alloc>
466     basic_string<_CharT,_Traits,_Alloc>&
467     basic_string<_CharT,_Traits,_Alloc>::
468     append(const basic_string& __str)
469     {
470       // Iff appending itself, string needs to pre-reserve the
471       // correct size so that _M_mutate does not clobber the
472       // iterators formed here.
473       size_type __size = __str.size();
474       size_type __len = __size + this->size();
475       if (__len > this->capacity())
476         this->reserve(__len);
477       return this->replace(_M_iend(), _M_iend(), __str._M_ibegin(),
478                            __str._M_iend());
479     }
480
481   template<typename _CharT, typename _Traits, typename _Alloc>
482     basic_string<_CharT,_Traits,_Alloc>&
483     basic_string<_CharT,_Traits,_Alloc>::
484     append(const basic_string& __str, size_type __pos, size_type __n)
485     {
486       // Iff appending itself, string needs to pre-reserve the
487       // correct size so that _M_mutate does not clobber the
488       // iterators formed here.
489       size_type __len = min(__str.size() - __pos, __n) + this->size();
490       if (__len > this->capacity())
491         this->reserve(__len);
492       return this->replace(_M_iend(), _M_iend(), __str._M_check(__pos),
493                            __str._M_fold(__pos, __n));
494     }
495
496   template<typename _CharT, typename _Traits, typename _Alloc>
497     basic_string<_CharT,_Traits,_Alloc>&
498     basic_string<_CharT,_Traits,_Alloc>::
499     append(const _CharT* __s, size_type __n)
500     {
501       size_type __len = __n + this->size();
502       if (__len > this->capacity())
503         this->reserve(__len);
504       return this->replace(_M_iend(), _M_iend(), __s, __s + __n);
505     }
506
507   template<typename _CharT, typename _Traits, typename _Alloc>
508     basic_string<_CharT,_Traits,_Alloc>&
509     basic_string<_CharT,_Traits,_Alloc>::
510     append(size_type __n, _CharT __c)
511     {
512       size_type __len = __n + this->size();
513       if (__len > this->capacity())
514         this->reserve(__len);
515        return this->replace(_M_iend(), _M_iend(), __n, __c);
516     }
517
518   template<typename _CharT, typename _Traits, typename _Alloc>
519     basic_string<_CharT,_Traits,_Alloc>
520     operator+(const _CharT* __lhs,
521              const basic_string<_CharT,_Traits,_Alloc>& __rhs)
522     {
523       typedef basic_string<_CharT,_Traits,_Alloc> __string_type;
524       typedef typename __string_type::size_type   __size_type;
525       __size_type __len = _Traits::length(__lhs);
526       __string_type __str;
527       __str.reserve(__len + __rhs.size());
528       __str.append(__lhs, __lhs + __len);
529       __str.append(__rhs);
530       return __str;
531     }
532
533   template<typename _CharT, typename _Traits, typename _Alloc>
534     basic_string<_CharT,_Traits,_Alloc>
535     operator+(_CharT __lhs, const basic_string<_CharT,_Traits,_Alloc>& __rhs)
536     {
537       typedef basic_string<_CharT,_Traits,_Alloc> __string_type;
538       typedef typename __string_type::size_type   __size_type;
539       __string_type __str;
540       __size_type __len = __rhs.size();
541       __str.reserve(__len + 1);
542       __str.append(__string_type::size_type(1), __lhs);
543       __str.append(__rhs);
544       return __str;
545     }
546
547   template<typename _CharT, typename _Traits, typename _Alloc>
548     basic_string<_CharT, _Traits, _Alloc>&
549     basic_string<_CharT, _Traits, _Alloc>::
550     replace(iterator __i1, iterator __i2, size_type __n2, _CharT __c)
551     {
552       size_type __n1 = __i2 - __i1;
553       size_type __off1 = __i1 - _M_ibegin();
554       __LENGTHERROR(max_size() - (this->size() - __n1) <= __n2);
555       _M_mutate (__off1, __n1, __n2);
556       // Invalidated __i1, __i2
557       if (__n2)
558         traits_type::assign(_M_data() + __off1, __n2, __c);
559       return *this;
560     }
561   
562   template<typename _CharT, typename _Traits, typename _Alloc>
563     basic_string<_CharT, _Traits, _Alloc>::size_type
564     basic_string<_CharT, _Traits, _Alloc>::
565     copy(_CharT* __s, size_type __n, size_type __pos) const
566     {
567       __OUTOFRANGE(__pos > this->size());
568       
569       if (__n > this->size() - __pos)
570         __n = this->size() - __pos;
571       
572       traits_type::copy(__s, _M_data() + __pos, __n);
573       // 21.3.5.7 par 3: do not append null.  (good.)
574       return __n;
575     }
576
577   template<typename _CharT, typename _Traits, typename _Alloc>
578     basic_string<_CharT, _Traits, _Alloc>::size_type
579     basic_string<_CharT, _Traits, _Alloc>::
580     find(const _CharT* __s, size_type __pos, size_type __n) const
581     {
582       size_type __size = this->size();
583       size_t __xpos = __pos;
584       const _CharT* __data = _M_data();
585       for (; __xpos + __n <= __size; ++__xpos)
586         if (traits_type::compare(__data + __xpos, __s, __n) == 0)
587           return __xpos;
588       return npos;
589     }
590
591   template<typename _CharT, typename _Traits, typename _Alloc>
592     basic_string<_CharT, _Traits, _Alloc>::size_type
593     basic_string<_CharT, _Traits, _Alloc>::
594     find(_CharT __c, size_type __pos) const
595     {
596       size_type __size = this->size();
597       size_type __ret = npos;
598       if (__pos < __size)
599         {
600           const _CharT* __data = _M_data();
601           size_type __n = __size - __pos;
602           const _CharT* __p = traits_type::find(__data + __pos, __n, __c);
603           if (__p)
604             __ret = __p - __data;
605         }
606       return __ret;
607     }
608
609
610   template<typename _CharT, typename _Traits, typename _Alloc>
611     basic_string<_CharT, _Traits, _Alloc>::size_type
612     basic_string<_CharT, _Traits, _Alloc>::
613     rfind(const _CharT* __s, size_type __pos, size_type __n) const
614     {
615       size_type __size = this->size();
616       if (__n <= __size)
617         {
618           __pos = std::min(__size - __n ,__pos);
619           const _CharT* __data = _M_data();
620           do 
621             {
622               if (traits_type::compare(__data + __pos, __s, __n) == 0)
623                 return __pos;
624             } 
625           while (__pos-- > 0);
626         }
627       return npos;
628     }
629   
630   template<typename _CharT, typename _Traits, typename _Alloc>
631     basic_string<_CharT, _Traits, _Alloc>::size_type
632     basic_string<_CharT, _Traits, _Alloc>::
633     rfind(_CharT __c, size_type __pos) const
634     {
635       size_type __size = this->size();
636       if (__size)
637         {
638           size_t __xpos = __size - 1;
639           if (__xpos > __pos)
640             __xpos = __pos;
641       
642           for (++__xpos; __xpos-- > 0; )
643             if (traits_type::eq(_M_data()[__xpos], __c))
644               return __xpos;
645         }
646       return npos;
647     }
648   
649   template<typename _CharT, typename _Traits, typename _Alloc>
650     basic_string<_CharT, _Traits, _Alloc>::size_type
651     basic_string<_CharT, _Traits, _Alloc>::
652     find_first_of(const _CharT* __s, size_type __pos, size_type __n) const
653     {
654       for (; __n && __pos < this->size(); ++__pos)
655         {
656           const _CharT* __p = traits_type::find(__s, __n, _M_data()[__pos]);
657           if (__p)
658             return __pos;
659         }
660       return npos;
661     }
662  
663   template<typename _CharT, typename _Traits, typename _Alloc>
664     basic_string<_CharT, _Traits, _Alloc>::size_type
665     basic_string<_CharT, _Traits, _Alloc>::
666     find_last_of(const _CharT* __s, size_type __pos, size_type __n) const
667     {
668       size_type __size = this->size();
669       if (__size && __n)
670         { 
671           if (--__size > __pos) 
672             __size = __pos;
673           do
674             {
675               if (traits_type::find(__s, __n, _M_data()[__size]))
676                 return __size;
677             } 
678           while (__size-- != 0);
679         }
680       return npos;
681     }
682   
683   template<typename _CharT, typename _Traits, typename _Alloc>
684     basic_string<_CharT, _Traits, _Alloc>::size_type
685     basic_string<_CharT, _Traits, _Alloc>::
686     find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const
687     {
688       size_t __xpos = __pos;
689       for (; __n && __xpos < this->size(); ++__xpos)
690         if (!traits_type::find(__s, __n, _M_data()[__xpos]))
691           return __xpos;
692       return npos;
693     }
694
695   template<typename _CharT, typename _Traits, typename _Alloc>
696     basic_string<_CharT, _Traits, _Alloc>::size_type
697     basic_string<_CharT, _Traits, _Alloc>::
698     find_first_not_of(_CharT __c, size_type __pos) const
699     {
700       size_t __xpos = __pos;
701       for (; __xpos < this->size(); ++__xpos)
702         if (!traits_type::eq(_M_data()[__xpos], __c))
703           return __xpos;
704       return npos;
705     }
706
707   template<typename _CharT, typename _Traits, typename _Alloc>
708     basic_string<_CharT, _Traits, _Alloc>::size_type
709     basic_string<_CharT, _Traits, _Alloc>::
710     find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const
711     {
712       size_type __size = this->size();
713       if (__size && __n)
714         { 
715           if (--__size > __pos) 
716             __size = __pos;
717           do
718             {
719               if (!traits_type::find(__s, __n, _M_data()[__size]))
720                 return __size;
721             } 
722           while (__size--);
723         }
724       return npos;
725     }
726
727   template<typename _CharT, typename _Traits, typename _Alloc>
728     basic_string<_CharT, _Traits, _Alloc>::size_type
729     basic_string<_CharT, _Traits, _Alloc>::
730     find_last_not_of(_CharT __c, size_type __pos) const
731     {
732       size_type __size = this->size();
733       if (__size)
734         { 
735           if (--__size > __pos) 
736             __size = __pos;
737           do
738             {
739               if (!traits_type::eq(_M_data()[__size], __c))
740                 return __size;
741             } 
742           while (__size--);
743         }
744       return npos;
745     }
746   
747   template<typename _CharT, typename _Traits, typename _Alloc>
748     int
749     basic_string<_CharT, _Traits, _Alloc>::
750     compare(size_type __pos, size_type __n, const basic_string& __str) const
751     {
752       size_type __size = this->size();
753       size_type __osize = __str.size();
754       __OUTOFRANGE(__pos > __size);
755       
756       size_type __rsize= min(__size - __pos, __n);
757       size_type __len = min(__rsize, __osize);
758       int __r = traits_type::compare(_M_data() + __pos, __str.data(), __len);
759       if (!__r)
760         __r = __rsize - __osize;
761       return __r;
762     }
763
764   template<typename _CharT, typename _Traits, typename _Alloc>
765     int
766     basic_string<_CharT, _Traits, _Alloc>::
767     compare(size_type __pos1, size_type __n1, const basic_string& __str,
768             size_type __pos2, size_type __n2) const
769     {
770       size_type __size = this->size();
771       size_type __osize = __str.size();
772       __OUTOFRANGE(__pos1 > __size);
773       __OUTOFRANGE(__pos2 > __osize);
774       
775       size_type __rsize = min(__size - __pos1, __n1);
776       size_type __rosize = min(__osize - __pos2, __n2);
777       size_type __len = min(__rsize, __rosize);
778       int __r = traits_type::compare(_M_data() + __pos1, 
779                                      __str.data() + __pos2, __len);
780       if (!__r)
781         __r = __rsize - __rosize;
782       return __r;
783     }
784
785
786   template<typename _CharT, typename _Traits, typename _Alloc>
787     int
788     basic_string<_CharT, _Traits, _Alloc>::
789     compare(const _CharT* __s) const
790     {
791       size_type __size = this->size();
792       int __r = traits_type::compare(_M_data(), __s, __size);
793       if (!__r)
794         __r = __size - traits_type::length(__s);
795       return __r;
796     }
797
798
799   template<typename _CharT, typename _Traits, typename _Alloc>
800     int
801     basic_string <_CharT,_Traits,_Alloc>::
802     compare(size_type __pos, size_type __n1, const _CharT* __s, 
803             size_type __n2) const
804     {
805       size_type __size = this->size();
806       __OUTOFRANGE(__pos > __size);
807       
808       size_type __osize = min(traits_type::length(__s), __n2);
809       size_type __rsize = min(__size - __pos, __n1);
810       size_type __len = min(__rsize, __osize);
811       int __r = traits_type::compare(_M_data() + __pos, __s, __len);
812       if (!__r)
813         __r = __rsize - __osize;
814       return __r;
815     }
816
817   template <class _CharT, class _Traits, class _Alloc>
818     void
819     _S_string_copy(const basic_string<_CharT, _Traits, _Alloc>& __str,
820                    _CharT* __buf, typename _Alloc::size_type __bufsiz)
821     {
822       typedef typename _Alloc::size_type size_type;
823       size_type __strsize = __str.size();
824       size_type __bytes = min(__strsize, __bufsiz - 1);
825       _Traits::copy(__buf, __str.data(), __bytes);
826       __buf[__bytes] = _CharT();
827     }
828
829 } // std::
830
831 #endif /* _CPP_BITS_STRING_TCC */