1 // Member templates for the -*- C++ -*- string classes.
2 // Copyright (C) 1994, 1999 Free Software Foundation
3
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)
8 // any later version.
9
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.
14
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.
18
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.
24
25 // Written by Jason Merrill based upon the specification by Takanori Adachi
26 // in ANSI X3J16/94-0013R2.
27
28 extern "C++" {
29 template <class charT, class traits, class Allocator>
30 inline void * basic_string <charT, traits, Allocator>::Rep::
operator new(size_t s,size_t extra)31 operator new (size_t s, size_t extra)
32 {
33 return Allocator::allocate(s + extra * sizeof (charT));
34 }
35
36 template <class charT, class traits, class Allocator>
37 inline void basic_string <charT, traits, Allocator>::Rep::
operator delete(void * ptr)38 operator delete (void * ptr)
39 {
40 Allocator::deallocate(ptr, sizeof(Rep) +
41 reinterpret_cast<Rep *>(ptr)->res *
42 sizeof (charT));
43 }
44
45 template <class charT, class traits, class Allocator>
46 inline size_t basic_string <charT, traits, Allocator>::Rep::
frob_size(size_t s)47 frob_size (size_t s)
48 {
49 size_t i = 16;
50 while (i < s) i *= 2;
51 return i;
52 }
53
54 template <class charT, class traits, class Allocator>
55 inline basic_string <charT, traits, Allocator>::Rep *
56 basic_string <charT, traits, Allocator>::Rep::
create(size_t extra)57 create (size_t extra)
58 {
59 extra = frob_size (extra + 1);
60 Rep *p = new (extra) Rep;
61 p->res = extra;
62 p->ref = 1;
63 p->selfish = false;
64 return p;
65 }
66
67 template <class charT, class traits, class Allocator>
68 charT * basic_string <charT, traits, Allocator>::Rep::
clone()69 clone ()
70 {
71 Rep *p = Rep::create (len);
72 p->copy (0, data (), len);
73 p->len = len;
74 return p->data ();
75 }
76
77 template <class charT, class traits, class Allocator>
78 inline bool basic_string <charT, traits, Allocator>::Rep::
excess_slop(size_t s,size_t r)79 excess_slop (size_t s, size_t r)
80 {
81 return 2 * (s <= 16 ? 16 : s) < r;
82 }
83
84 template <class charT, class traits, class Allocator>
85 inline bool basic_string <charT, traits, Allocator>::
check_realloc(basic_string::size_type s) const86 check_realloc (basic_string::size_type s) const
87 {
88 s += sizeof (charT);
89 rep ()->selfish = false;
90 return (rep ()->ref > 1
91 || s > capacity ()
92 || Rep::excess_slop (s, capacity ()));
93 }
94
95 template <class charT, class traits, class Allocator>
96 void basic_string <charT, traits, Allocator>::
alloc(basic_string::size_type __size,bool __save)97 alloc (basic_string::size_type __size, bool __save)
98 {
99 if (! check_realloc (__size))
100 return;
101
102 Rep *p = Rep::create (__size);
103
104 if (__save)
105 {
106 p->copy (0, data (), length ());
107 p->len = length ();
108 }
109 else
110 p->len = 0;
111
112 repup (p);
113 }
114
115 template <class charT, class traits, class Allocator>
116 basic_string <charT, traits, Allocator>&
117 basic_string <charT, traits, Allocator>::
replace(size_type pos1,size_type n1,const basic_string & _str,size_type pos2,size_type n2)118 replace (size_type pos1, size_type n1,
119 const basic_string& _str, size_type pos2, size_type n2)
120 {
121 const size_t len2 = _str.length ();
122
123 if (pos1 == 0 && n1 >= length () && pos2 == 0 && n2 >= len2)
124 return operator= (_str);
125
126 OUTOFRANGE (pos2 > len2);
127
128 if (n2 > len2 - pos2)
129 n2 = len2 - pos2;
130
131 return replace (pos1, n1, _str.data () + pos2, n2);
132 }
133
134 template <class charT, class traits, class Allocator>
135 inline void basic_string <charT, traits, Allocator>::Rep::
copy(size_t pos,const charT * s,size_t n)136 copy (size_t pos, const charT *s, size_t n)
137 {
138 if (n)
139 traits::copy (data () + pos, s, n);
140 }
141
142 template <class charT, class traits, class Allocator>
143 inline void basic_string <charT, traits, Allocator>::Rep::
move(size_t pos,const charT * s,size_t n)144 move (size_t pos, const charT *s, size_t n)
145 {
146 if (n)
147 traits::move (data () + pos, s, n);
148 }
149
150 template <class charT, class traits, class Allocator>
151 basic_string <charT, traits, Allocator>&
152 basic_string <charT, traits, Allocator>::
replace(size_type pos,size_type n1,const charT * s,size_type n2)153 replace (size_type pos, size_type n1, const charT* s, size_type n2)
154 {
155 const size_type len = length ();
156 OUTOFRANGE (pos > len);
157 if (n1 > len - pos)
158 n1 = len - pos;
159 LENGTHERROR (len - n1 > max_size () - n2);
160 size_t newlen = len - n1 + n2;
161
162 if (check_realloc (newlen))
163 {
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);
168 repup (p);
169 }
170 else
171 {
172 rep ()->move (pos + n2, data () + pos + n1, len - (pos + n1));
173 rep ()->copy (pos, s, n2);
174 }
175 rep ()->len = newlen;
176
177 return *this;
178 }
179
180 template <class charT, class traits, class Allocator>
181 inline void basic_string <charT, traits, Allocator>::Rep::
set(size_t pos,const charT c,size_t n)182 set (size_t pos, const charT c, size_t n)
183 {
184 traits::set (data () + pos, c, n);
185 }
186
187 template <class charT, class traits, class Allocator>
188 basic_string <charT, traits, Allocator>& basic_string <charT, traits, Allocator>::
replace(size_type pos,size_type n1,size_type n2,charT c)189 replace (size_type pos, size_type n1, size_type n2, charT c)
190 {
191 const size_t len = length ();
192 OUTOFRANGE (pos > len);
193 if (n1 > len - pos)
194 n1 = len - pos;
195 LENGTHERROR (len - n1 > max_size () - n2);
196 size_t newlen = len - n1 + n2;
197
198 if (check_realloc (newlen))
199 {
200 Rep *p = Rep::create (newlen);
201 p->copy (0, data (), pos);
202 p->copy (pos + n2, data () + pos + n1, len - (pos + n1));
203 p->set (pos, c, n2);
204 repup (p);
205 }
206 else
207 {
208 rep ()->move (pos + n2, data () + pos + n1, len - (pos + n1));
209 rep ()->set (pos, c, n2);
210 }
211 rep ()->len = newlen;
212
213 return *this;
214 }
215
216 template <class charT, class traits, class Allocator>
217 void basic_string <charT, traits, Allocator>::
resize(size_type n,charT c)218 resize (size_type n, charT c)
219 {
220 LENGTHERROR (n > max_size ());
221
222 if (n > length ())
223 append (n - length (), c);
224 else
225 erase (n);
226 }
227
228 template <class charT, class traits, class Allocator>
229 basic_string <charT, traits, Allocator>::size_type
230 basic_string <charT, traits, Allocator>::
copy(charT * s,size_type n,size_type pos) const231 copy (charT* s, size_type n, size_type pos) const
232 {
233 OUTOFRANGE (pos > length ());
234
235 if (n > length () - pos)
236 n = length () - pos;
237
238 traits::copy (s, data () + pos, n);
239 return n;
240 }
241
242 template <class charT, class traits, class Allocator>
243 basic_string <charT, traits, Allocator>::size_type
244 basic_string <charT, traits, Allocator>::
find(const charT * s,size_type pos,size_type n) const245 find (const charT* s, size_type pos, size_type n) const
246 {
247 size_t xpos = pos;
248 for (; xpos + n <= length (); ++xpos)
249 if (traits::eq (data () [xpos], *s)
250 && traits::compare (data () + xpos, s, n) == 0)
251 return xpos;
252 return npos;
253 }
254
255 template <class charT, class traits, class Allocator>
256 inline basic_string <charT, traits, Allocator>::size_type
257 basic_string <charT, traits, Allocator>::
_find(const charT * ptr,charT c,size_type xpos,size_type len)258 _find (const charT* ptr, charT c, size_type xpos, size_type len)
259 {
260 for (; xpos < len; ++xpos)
261 if (traits::eq (ptr [xpos], c))
262 return xpos;
263 return npos;
264 }
265
266 template <class charT, class traits, class Allocator>
267 basic_string <charT, traits, Allocator>::size_type
268 basic_string <charT, traits, Allocator>::
find(charT c,size_type pos) const269 find (charT c, size_type pos) const
270 {
271 return _find (data (), c, pos, length ());
272 }
273
274 template <class charT, class traits, class Allocator>
275 basic_string <charT, traits, Allocator>::size_type
276 basic_string <charT, traits, Allocator>::
rfind(const charT * s,size_type pos,size_type n) const277 rfind (const charT* s, size_type pos, size_type n) const
278 {
279 if (n > length ())
280 return npos;
281
282 size_t xpos = length () - n;
283 if (xpos > pos)
284 xpos = pos;
285
286 for (++xpos; xpos-- > 0; )
287 if (traits::eq (data () [xpos], *s)
288 && traits::compare (data () + xpos, s, n) == 0)
289 return xpos;
290 return npos;
291 }
292
293 template <class charT, class traits, class Allocator>
294 basic_string <charT, traits, Allocator>::size_type
295 basic_string <charT, traits, Allocator>::
rfind(charT c,size_type pos) const296 rfind (charT c, size_type pos) const
297 {
298 if (1 > length ())
299 return npos;
300
301 size_t xpos = length () - 1;
302 if (xpos > pos)
303 xpos = pos;
304
305 for (++xpos; xpos-- > 0; )
306 if (traits::eq (data () [xpos], c))
307 return xpos;
308 return npos;
309 }
310
311 template <class charT, class traits, class Allocator>
312 basic_string <charT, traits, Allocator>::size_type
313 basic_string <charT, traits, Allocator>::
find_first_of(const charT * s,size_type pos,size_type n) const314 find_first_of (const charT* s, size_type pos, size_type n) const
315 {
316 size_t xpos = pos;
317 for (; xpos < length (); ++xpos)
318 if (_find (s, data () [xpos], 0, n) != npos)
319 return xpos;
320 return npos;
321 }
322
323 template <class charT, class traits, class Allocator>
324 basic_string <charT, traits, Allocator>::size_type
325 basic_string <charT, traits, Allocator>::
find_last_of(const charT * s,size_type pos,size_type n) const326 find_last_of (const charT* s, size_type pos, size_type n) const
327 {
328 if (length() == 0)
329 return npos;
330 size_t xpos = length () - 1;
331 if (xpos > pos)
332 xpos = pos;
333 for (++xpos; xpos-- > 0;)
334 if (_find (s, data () [xpos], 0, n) != npos)
335 return xpos;
336 return npos;
337 }
338
339 template <class charT, class traits, class Allocator>
340 basic_string <charT, traits, Allocator>::size_type
341 basic_string <charT, traits, Allocator>::
find_first_not_of(const charT * s,size_type pos,size_type n) const342 find_first_not_of (const charT* s, size_type pos, size_type n) const
343 {
344 size_t xpos = pos;
345 for (; xpos < length (); ++xpos)
346 if (_find (s, data () [xpos], 0, n) == npos)
347 return xpos;
348 return npos;
349 }
350
351 template <class charT, class traits, class Allocator>
352 basic_string <charT, traits, Allocator>::size_type
353 basic_string <charT, traits, Allocator>::
find_first_not_of(charT c,size_type pos) const354 find_first_not_of (charT c, size_type pos) const
355 {
356 size_t xpos = pos;
357 for (; xpos < length (); ++xpos)
358 if (traits::ne (data () [xpos], c))
359 return xpos;
360 return npos;
361 }
362
363 template <class charT, class traits, class Allocator>
364 basic_string <charT, traits, Allocator>::size_type
365 basic_string <charT, traits, Allocator>::
find_last_not_of(const charT * s,size_type pos,size_type n) const366 find_last_not_of (const charT* s, size_type pos, size_type n) const
367 {
368 if (length() == 0)
369 return npos;
370 size_t xpos = length () - 1;
371 if (xpos > pos)
372 xpos = pos;
373 for (++xpos; xpos-- > 0;)
374 if (_find (s, data () [xpos], 0, n) == npos)
375 return xpos;
376 return npos;
377 }
378
379 template <class charT, class traits, class Allocator>
380 basic_string <charT, traits, Allocator>::size_type
381 basic_string <charT, traits, Allocator>::
find_last_not_of(charT c,size_type pos) const382 find_last_not_of (charT c, size_type pos) const
383 {
384 if (length() == 0)
385 return npos;
386 size_t xpos = length () - 1;
387 if (xpos > pos)
388 xpos = pos;
389 for (++xpos; xpos-- > 0;)
390 if (traits::ne (data () [xpos], c))
391 return xpos;
392 return npos;
393 }
394
395 template <class charT, class traits, class Allocator>
396 int basic_string <charT, traits, Allocator>::
compare(const basic_string & _str,size_type pos,size_type n) const397 compare (const basic_string& _str, size_type pos, size_type n) const
398 {
399 OUTOFRANGE (pos > length ());
400
401 size_t rlen = length () - pos;
402 if (rlen > n)
403 rlen = n;
404 if (rlen > _str.length ())
405 rlen = _str.length ();
406 int r = traits::compare (data () + pos, _str.data (), rlen);
407 if (r != 0)
408 return r;
409 if (rlen == n)
410 return 0;
411 return (length () - pos) - _str.length ();
412 }
413
414 template <class charT, class traits, class Allocator>
415 int basic_string <charT, traits, Allocator>::
compare(const charT * s,size_type pos,size_type n) const416 compare (const charT* s, size_type pos, size_type n) const
417 {
418 OUTOFRANGE (pos > length ());
419
420 size_t rlen = length () - pos;
421 if (rlen > n)
422 rlen = n;
423 int r = traits::compare (data () + pos, s, rlen);
424 if (r != 0)
425 return r;
426 return (length () - pos) - n;
427 }
428
429 #include <iostream.h>
430
431 template <class charT, class traits, class Allocator>
432 istream &
operator >>(istream & is,basic_string<charT,traits,Allocator> & s)433 operator>> (istream &is, basic_string <charT, traits, Allocator> &s)
434 {
435 int w = is.width (0);
436 if (is.ipfx0 ())
437 {
438 register streambuf *sb = is.rdbuf ();
439 s.resize (0);
440 while (1)
441 {
442 int ch = sb->sbumpc ();
443 if (ch == EOF)
444 {
445 is.setstate (ios::eofbit);
446 break;
447 }
448 else if (traits::is_del (ch))
449 {
450 sb->sungetc ();
451 break;
452 }
453 s += static_cast<charT> (ch);
454 if (--w == 1)
455 break;
456 }
457 }
458
459 is.isfx ();
460 if (s.length () == 0)
461 is.setstate (ios::failbit);
462
463 return is;
464 }
465
466 template <class charT, class traits, class Allocator>
467 ostream &
operator <<(ostream & o,const basic_string<charT,traits,Allocator> & s)468 operator<< (ostream &o, const basic_string <charT, traits, Allocator>& s)
469 {
470 return o.write (s.data (), s.length ());
471 }
472
473 template <class charT, class traits, class Allocator>
474 istream&
getline(istream & is,basic_string<charT,traits,Allocator> & s,charT delim)475 getline (istream &is, basic_string <charT, traits, Allocator>& s, charT delim)
476 {
477 if (is.ipfx1 ())
478 {
479 _IO_size_t _count = 0;
480 streambuf *sb = is.rdbuf ();
481 s.resize (0);
482
483 while (1)
484 {
485 int ch = sb->sbumpc ();
486 if (ch == EOF)
487 {
488 is.setstate (_count == 0
489 ? (ios::failbit|ios::eofbit)
490 : ios::eofbit);
491 break;
492 }
493
494 ++_count;
495
496 if (ch == delim)
497 break;
498
499 s += static_cast<charT> (ch);
500
501 if (s.length () == s.npos - 1)
502 {
503 is.setstate (ios::failbit);
504 break;
505 }
506 }
507 }
508
509 // We need to be friends with istream to do this.
510 // is._gcount = _count;
511 is.isfx ();
512
513 return is;
514 }
515
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 };
519
520 template <class charT, class traits, class Allocator>
521 const basic_string <charT, traits, Allocator>::size_type
522 basic_string <charT, traits, Allocator>::npos;
523
524 } // extern "C++"
525