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
;