Initial import from FreeBSD RELENG_4:
[dragonfly.git] / contrib / libstdc++ / std / bastring.cc
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::
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   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>::
342 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>::
354 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>::
366 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>::
382 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>::
397 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>::
416 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 &
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 &
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&
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++"