[multiple changes]
[gcc.git] / libstdc++ / std / bastring.cc
1 // Member templates for the -*- C++ -*- string classes.
2 // Copyright (C) 1994 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::
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::
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::
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::
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::
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::
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>::
86 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>::
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>::
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::
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::
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>::
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::
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>::
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>::
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>::
231 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>::
245 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>::
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>::
269 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>::
277 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>::
296 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>::
314 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>::
326 find_last_of (const charT* s, size_type pos, size_type n) const
327 {
328 size_t xpos = length () - 1;
329 if (xpos > pos)
330 xpos = pos;
331 for (; xpos; --xpos)
332 if (_find (s, data () [xpos], 0, n) != npos)
333 return xpos;
334 return npos;
335 }
336
337 template <class charT, class traits, class Allocator>
338 basic_string <charT, traits, Allocator>::size_type
339 basic_string <charT, traits, Allocator>::
340 find_first_not_of (const charT* s, size_type pos, size_type n) const
341 {
342 size_t xpos = pos;
343 for (; xpos < length (); ++xpos)
344 if (_find (s, data () [xpos], 0, n) == npos)
345 return xpos;
346 return npos;
347 }
348
349 template <class charT, class traits, class Allocator>
350 basic_string <charT, traits, Allocator>::size_type
351 basic_string <charT, traits, Allocator>::
352 find_first_not_of (charT c, size_type pos) const
353 {
354 size_t xpos = pos;
355 for (; xpos < length (); ++xpos)
356 if (traits::ne (data () [xpos], c))
357 return xpos;
358 return npos;
359 }
360
361 template <class charT, class traits, class Allocator>
362 basic_string <charT, traits, Allocator>::size_type
363 basic_string <charT, traits, Allocator>::
364 find_last_not_of (const charT* s, size_type pos, size_type n) const
365 {
366 size_t xpos = length () - 1;
367 if (xpos > pos)
368 xpos = pos;
369 for (; xpos; --xpos)
370 if (_find (s, data () [xpos], 0, n) == npos)
371 return xpos;
372 return npos;
373 }
374
375 template <class charT, class traits, class Allocator>
376 basic_string <charT, traits, Allocator>::size_type
377 basic_string <charT, traits, Allocator>::
378 find_last_not_of (charT c, size_type pos) const
379 {
380 size_t xpos = length () - 1;
381 if (xpos > pos)
382 xpos = pos;
383 for (; xpos; --xpos)
384 if (traits::ne (data () [xpos], c))
385 return xpos;
386 return npos;
387 }
388
389 template <class charT, class traits, class Allocator>
390 int basic_string <charT, traits, Allocator>::
391 compare (const basic_string& str, size_type pos, size_type n) const
392 {
393 OUTOFRANGE (pos > length ());
394
395 size_t rlen = length () - pos;
396 if (rlen > n)
397 rlen = n;
398 if (rlen > str.length ())
399 rlen = str.length ();
400 int r = traits::compare (data () + pos, str.data (), rlen);
401 if (r != 0)
402 return r;
403 if (rlen == n)
404 return 0;
405 return (length () - pos) - str.length ();
406 }
407
408 template <class charT, class traits, class Allocator>
409 int basic_string <charT, traits, Allocator>::
410 compare (const charT* s, size_type pos, size_type n) const
411 {
412 OUTOFRANGE (pos > length ());
413
414 size_t rlen = length () - pos;
415 if (rlen > n)
416 rlen = n;
417 int r = traits::compare (data () + pos, s, rlen);
418 if (r != 0)
419 return r;
420 return (length () - pos) - n;
421 }
422
423 #include <iostream.h>
424
425 template <class charT, class traits, class Allocator>
426 istream &
427 operator>> (istream &is, basic_string <charT, traits, Allocator> &s)
428 {
429 int w = is.width (0);
430 if (is.ipfx0 ())
431 {
432 register streambuf *sb = is.rdbuf ();
433 s.resize (0);
434 while (1)
435 {
436 int ch = sb->sbumpc ();
437 if (ch == EOF)
438 {
439 is.setstate (ios::eofbit);
440 break;
441 }
442 else if (traits::is_del (ch))
443 {
444 sb->sungetc ();
445 break;
446 }
447 s += ch;
448 if (--w == 1)
449 break;
450 }
451 }
452
453 is.isfx ();
454 if (s.length () == 0)
455 is.setstate (ios::failbit);
456
457 return is;
458 }
459
460 template <class charT, class traits, class Allocator>
461 ostream &
462 operator<< (ostream &o, const basic_string <charT, traits, Allocator>& s)
463 {
464 return o.write (s.data (), s.length ());
465 }
466
467 template <class charT, class traits, class Allocator>
468 istream&
469 getline (istream &is, basic_string <charT, traits, Allocator>& s, charT delim)
470 {
471 if (is.ipfx1 ())
472 {
473 _IO_size_t count = 0;
474 streambuf *sb = is.rdbuf ();
475 s.resize (0);
476
477 while (1)
478 {
479 int ch = sb->sbumpc ();
480 if (ch == EOF)
481 {
482 is.setstate (count == 0
483 ? (ios::failbit|ios::eofbit)
484 : ios::eofbit);
485 break;
486 }
487
488 ++count;
489
490 if (ch == delim)
491 break;
492
493 s += ch;
494
495 if (s.length () == s.npos - 1)
496 {
497 is.setstate (ios::failbit);
498 break;
499 }
500 }
501 }
502
503 // We need to be friends with istream to do this.
504 // is._gcount = count;
505 is.isfx ();
506
507 return is;
508 }
509
510 template <class charT, class traits, class Allocator>
511 basic_string <charT, traits, Allocator>::Rep
512 basic_string<charT, traits, Allocator>::nilRep = { 0, 0, 1, false };
513
514 template <class charT, class traits, class Allocator>
515 const basic_string <charT, traits, Allocator>::size_type
516 basic_string <charT, traits, Allocator>::npos;
517
518 } // extern "C++"