1 // Member templates for the -*- C++ -*- string classes.
2 // Copyright (C) 1994, 1999 Free Software Foundation
4 // This file is part of the GNU ANSI C++ Library. This library is free
5 // software; you can redistribute it and/or modify it under the
6 // terms of the GNU General Public License as published by the
7 // Free Software Foundation; either version 2, or (at your option)
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this library; see the file COPYING. If not, write to the Free
17 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 // As a special exception, if you link this library with files
20 // compiled with a GNU compiler to produce an executable, this does not cause
21 // the resulting executable to be covered by the GNU General Public License.
22 // This exception does not however invalidate any other reasons why
23 // the executable file might be covered by the GNU General Public License.
25 // Written by Jason Merrill based upon the specification by Takanori Adachi
26 // in ANSI X3J16/94-0013R2.
29 template <class charT, class traits, class Allocator>
30 inline void * basic_string <charT, traits, Allocator>::Rep::
31 operator new (size_t s, size_t extra)
33 return Allocator::allocate(s + extra * sizeof (charT));
36 template <class charT, class traits, class Allocator>
37 inline void basic_string <charT, traits, Allocator>::Rep::
38 operator delete (void * ptr)
40 Allocator::deallocate(ptr, sizeof(Rep) +
41 reinterpret_cast<Rep *>(ptr)->res *
45 template <class charT, class traits, class Allocator>
46 inline size_t basic_string <charT, traits, Allocator>::Rep::
54 template <class charT, class traits, class Allocator>
55 inline basic_string <charT, traits, Allocator>::Rep *
56 basic_string <charT, traits, Allocator>::Rep::
59 extra = frob_size (extra + 1);
60 Rep *p = new (extra) Rep;
67 template <class charT, class traits, class Allocator>
68 charT * basic_string <charT, traits, Allocator>::Rep::
71 Rep *p = Rep::create (len);
72 p->copy (0, data (), len);
77 template <class charT, class traits, class Allocator>
78 inline bool basic_string <charT, traits, Allocator>::Rep::
79 excess_slop (size_t s, size_t r)
81 return 2 * (s <= 16 ? 16 : s) < r;
84 template <class charT, class traits, class Allocator>
85 inline bool basic_string <charT, traits, Allocator>::
86 check_realloc (basic_string::size_type s) const
89 rep ()->selfish = false;
90 return (rep ()->ref > 1
92 || Rep::excess_slop (s, capacity ()));
95 template <class charT, class traits, class Allocator>
96 void basic_string <charT, traits, Allocator>::
97 alloc (basic_string::size_type __size, bool __save)
99 if (! check_realloc (__size))
102 Rep *p = Rep::create (__size);
106 p->copy (0, data (), length ());
115 template <class charT, class traits, class Allocator>
116 basic_string <charT, traits, Allocator>&
117 basic_string <charT, traits, Allocator>::
118 replace (size_type pos1, size_type n1,
119 const basic_string& str, size_type pos2, size_type n2)
121 const size_t len2 = str.length ();
123 if (pos1 == 0 && n1 >= length () && pos2 == 0 && n2 >= len2)
124 return operator= (str);
126 OUTOFRANGE (pos2 > len2);
128 if (n2 > len2 - pos2)
131 return replace (pos1, n1, str.data () + pos2, n2);
134 template <class charT, class traits, class Allocator>
135 inline void basic_string <charT, traits, Allocator>::Rep::
136 copy (size_t pos, const charT *s, size_t n)
139 traits::copy (data () + pos, s, n);
142 template <class charT, class traits, class Allocator>
143 inline void basic_string <charT, traits, Allocator>::Rep::
144 move (size_t pos, const charT *s, size_t n)
147 traits::move (data () + pos, s, n);
150 template <class charT, class traits, class Allocator>
151 basic_string <charT, traits, Allocator>&
152 basic_string <charT, traits, Allocator>::
153 replace (size_type pos, size_type n1, const charT* s, size_type n2)
155 const size_type len = length ();
156 OUTOFRANGE (pos > len);
159 LENGTHERROR (len - n1 > max_size () - n2);
160 size_t newlen = len - n1 + n2;
162 if (check_realloc (newlen))
164 Rep *p = Rep::create (newlen);
165 p->copy (0, data (), pos);
166 p->copy (pos + n2, data () + pos + n1, len - (pos + n1));
167 p->copy (pos, s, n2);
172 rep ()->move (pos + n2, data () + pos + n1, len - (pos + n1));
173 rep ()->copy (pos, s, n2);
175 rep ()->len = newlen;
180 template <class charT, class traits, class Allocator>
181 inline void basic_string <charT, traits, Allocator>::Rep::
182 set (size_t pos, const charT c, size_t n)
184 traits::set (data () + pos, c, n);
187 template <class charT, class traits, class Allocator>
188 basic_string <charT, traits, Allocator>& basic_string <charT, traits, Allocator>::
189 replace (size_type pos, size_type n1, size_type n2, charT c)
191 const size_t len = length ();
192 OUTOFRANGE (pos > len);
195 LENGTHERROR (len - n1 > max_size () - n2);
196 size_t newlen = len - n1 + n2;
198 if (check_realloc (newlen))
200 Rep *p = Rep::create (newlen);
201 p->copy (0, data (), pos);
202 p->copy (pos + n2, data () + pos + n1, len - (pos + n1));
208 rep ()->move (pos + n2, data () + pos + n1, len - (pos + n1));
209 rep ()->set (pos, c, n2);
211 rep ()->len = newlen;
216 template <class charT, class traits, class Allocator>
217 void basic_string <charT, traits, Allocator>::
218 resize (size_type n, charT c)
220 LENGTHERROR (n > max_size ());
223 append (n - length (), c);
228 template <class charT, class traits, class Allocator>
229 basic_string <charT, traits, Allocator>::size_type
230 basic_string <charT, traits, Allocator>::
231 copy (charT* s, size_type n, size_type pos) const
233 OUTOFRANGE (pos > length ());
235 if (n > length () - pos)
238 traits::copy (s, data () + pos, n);
242 template <class charT, class traits, class Allocator>
243 basic_string <charT, traits, Allocator>::size_type
244 basic_string <charT, traits, Allocator>::
245 find (const charT* s, size_type pos, size_type n) const
248 for (; xpos + n <= length (); ++xpos)
249 if (traits::eq (data () [xpos], *s)
250 && traits::compare (data () + xpos, s, n) == 0)
255 template <class charT, class traits, class Allocator>
256 inline basic_string <charT, traits, Allocator>::size_type
257 basic_string <charT, traits, Allocator>::
258 _find (const charT* ptr, charT c, size_type xpos, size_type len)
260 for (; xpos < len; ++xpos)
261 if (traits::eq (ptr [xpos], c))
266 template <class charT, class traits, class Allocator>
267 basic_string <charT, traits, Allocator>::size_type
268 basic_string <charT, traits, Allocator>::
269 find (charT c, size_type pos) const
271 return _find (data (), c, pos, length ());
274 template <class charT, class traits, class Allocator>
275 basic_string <charT, traits, Allocator>::size_type
276 basic_string <charT, traits, Allocator>::
277 rfind (const charT* s, size_type pos, size_type n) const
282 size_t xpos = length () - n;
286 for (++xpos; xpos-- > 0; )
287 if (traits::eq (data () [xpos], *s)
288 && traits::compare (data () + xpos, s, n) == 0)
293 template <class charT, class traits, class Allocator>
294 basic_string <charT, traits, Allocator>::size_type
295 basic_string <charT, traits, Allocator>::
296 rfind (charT c, size_type pos) const
301 size_t xpos = length () - 1;
305 for (++xpos; xpos-- > 0; )
306 if (traits::eq (data () [xpos], c))
311 template <class charT, class traits, class Allocator>
312 basic_string <charT, traits, Allocator>::size_type
313 basic_string <charT, traits, Allocator>::
314 find_first_of (const charT* s, size_type pos, size_type n) const
317 for (; xpos < length (); ++xpos)
318 if (_find (s, data () [xpos], 0, n) != npos)
323 template <class charT, class traits, class Allocator>
324 basic_string <charT, traits, Allocator>::size_type
325 basic_string <charT, traits, Allocator>::
326 find_last_of (const charT* s, size_type pos, size_type n) const
330 size_t xpos = length () - 1;
333 for (++xpos; xpos-- > 0;)
334 if (_find (s, data () [xpos], 0, n) != npos)
339 template <class charT, class traits, class Allocator>
340 basic_string <charT, traits, Allocator>::size_type
341 basic_string <charT, traits, Allocator>::
342 find_first_not_of (const charT* s, size_type pos, size_type n) const
345 for (; xpos < length (); ++xpos)
346 if (_find (s, data () [xpos], 0, n) == npos)
351 template <class charT, class traits, class Allocator>
352 basic_string <charT, traits, Allocator>::size_type
353 basic_string <charT, traits, Allocator>::
354 find_first_not_of (charT c, size_type pos) const
357 for (; xpos < length (); ++xpos)
358 if (traits::ne (data () [xpos], c))
363 template <class charT, class traits, class Allocator>
364 basic_string <charT, traits, Allocator>::size_type
365 basic_string <charT, traits, Allocator>::
366 find_last_not_of (const charT* s, size_type pos, size_type n) const
370 size_t xpos = length () - 1;
373 for (++xpos; xpos-- > 0;)
374 if (_find (s, data () [xpos], 0, n) == npos)
379 template <class charT, class traits, class Allocator>
380 basic_string <charT, traits, Allocator>::size_type
381 basic_string <charT, traits, Allocator>::
382 find_last_not_of (charT c, size_type pos) const
386 size_t xpos = length () - 1;
389 for (++xpos; xpos-- > 0;)
390 if (traits::ne (data () [xpos], c))
395 template <class charT, class traits, class Allocator>
396 int basic_string <charT, traits, Allocator>::
397 compare (const basic_string& str, size_type pos, size_type n) const
399 OUTOFRANGE (pos > length ());
401 size_t rlen = length () - pos;
404 if (rlen > str.length ())
405 rlen = str.length ();
406 int r = traits::compare (data () + pos, str.data (), rlen);
411 return (length () - pos) - str.length ();
414 template <class charT, class traits, class Allocator>
415 int basic_string <charT, traits, Allocator>::
416 compare (const charT* s, size_type pos, size_type n) const
418 OUTOFRANGE (pos > length ());
420 size_t rlen = length () - pos;
423 int r = traits::compare (data () + pos, s, rlen);
426 return (length () - pos) - n;
429 #include <iostream.h>
431 template <class charT, class traits, class Allocator>
433 operator>> (istream &is, basic_string <charT, traits, Allocator> &s)
435 int w = is.width (0);
438 register streambuf *sb = is.rdbuf ();
442 int ch = sb->sbumpc ();
445 is.setstate (ios::eofbit);
448 else if (traits::is_del (ch))
453 s += static_cast<charT> (ch);
460 if (s.length () == 0)
461 is.setstate (ios::failbit);
466 template <class charT, class traits, class Allocator>
468 operator<< (ostream &o, const basic_string <charT, traits, Allocator>& s)
470 return o.write (s.data (), s.length ());
473 template <class charT, class traits, class Allocator>
475 getline (istream &is, basic_string <charT, traits, Allocator>& s, charT delim)
479 _IO_size_t count = 0;
480 streambuf *sb = is.rdbuf ();
485 int ch = sb->sbumpc ();
488 is.setstate (count == 0
489 ? (ios::failbit|ios::eofbit)
499 s += static_cast<charT> (ch);
501 if (s.length () == s.npos - 1)
503 is.setstate (ios::failbit);
509 // We need to be friends with istream to do this.
510 // is._gcount = count;
516 template <class charT, class traits, class Allocator>
517 basic_string <charT, traits, Allocator>::Rep
518 basic_string<charT, traits, Allocator>::nilRep = { 0, 0, 1, false };
520 template <class charT, class traits, class Allocator>
521 const basic_string <charT, traits, Allocator>::size_type
522 basic_string <charT, traits, Allocator>::npos;