1// Main templates for the -*- C++ -*- string classes.
2// Copyright (C) 1994, 1995, 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#ifndef __BASTRING__
29#define __BASTRING__
30
31#ifdef __GNUG__
32#pragma interface
33#endif
34
35#include <cstddef>
36#include <std/straits.h>
37
38// NOTE : This does NOT conform to the draft standard and is likely to change
39#include <alloc.h>
40
41#ifdef __HAIKU__
42#	include <config/types.h>
43#endif
44
45extern "C++" {
46class istream; class ostream;
47
48#include <iterator>
49
50#ifdef __STL_USE_EXCEPTIONS
51
52extern void __out_of_range (const char *);
53extern void __length_error (const char *);
54
55#define OUTOFRANGE(cond) \
56  do { if (cond) __out_of_range (#cond); } while (0)
57#define LENGTHERROR(cond) \
58  do { if (cond) __length_error (#cond); } while (0)
59
60#else
61
62#include <cassert>
63#define OUTOFRANGE(cond) assert (!(cond))
64#define LENGTHERROR(cond) assert (!(cond))
65
66#endif
67
68#ifdef __HAIKU__
69#ifndef atomic_add
70extern "C" __haiku_int32 atomic_add(__haiku_int32* value,
71	__haiku_int32 addvalue);
72#endif
73#endif	/* __HAIKU__ */
74
75template <class charT, class traits = string_char_traits<charT>,
76	  class Allocator = alloc >
77class basic_string
78{
79private:
80  struct Rep {
81    size_t len, res, ref;
82    bool selfish;
83
84    charT* data () { return reinterpret_cast<charT *>(this + 1); }
85    charT& operator[] (size_t s) { return data () [s]; }
86#ifdef __HAIKU__
87    charT* grab () { if (selfish) return clone (); atomic_add((__haiku_int32*) &ref, 1); return data (); }
88    void release() { if (atomic_add((__haiku_int32*) &ref, -1) == 1) delete this; }
89#else
90    charT* grab () { if (selfish) return clone (); ++ref; return data (); }
91#if defined __i486__ || defined __i586__ || defined __i686__
92    void release ()
93      {
94	size_t __val;
95	// This opcode exists as a .byte instead of as a mnemonic for the
96	// benefit of SCO OpenServer 5.  The system assembler (which is
97	// essentially required on this target) can't assemble xaddl in
98	//COFF mode.
99	asm (".byte 0xf0, 0x0f, 0xc1, 0x02" // lock; xaddl %eax, (%edx)
100	    : "=a" (__val)
101	    : "0" (-1), "m" (ref), "d" (&ref)
102	    : "memory");
103
104	if (__val == 1)
105	  delete this;
106      }
107#elif defined __sparcv9__
108    void release ()
109      {
110	size_t __newval, __oldval = ref;
111	do
112	  {
113	    __newval = __oldval - 1;
114	    __asm__ ("cas	[%4], %2, %0"
115		     : "=r" (__oldval), "=m" (ref)
116		     : "r" (__oldval), "m" (ref), "r"(&(ref)), "0" (__newval));
117	  }
118	while (__newval != __oldval);
119
120	if (__oldval == 0)
121	  delete this;
122      }
123#else
124    void release () { if (--ref == 0) delete this; }
125#endif
126#endif /* __HAIKU__ */
127    inline static void * operator new (size_t, size_t);
128    inline static void operator delete (void *);
129    inline static Rep* create (size_t);
130    charT* clone ();
131
132    inline void copy (size_t, const charT *, size_t);
133    inline void move (size_t, const charT *, size_t);
134    inline void set  (size_t, const charT,   size_t);
135
136    inline static bool excess_slop (size_t, size_t);
137    inline static size_t frob_size (size_t);
138
139  private:
140    Rep &operator= (const Rep &);
141  };
142
143public:
144// types:
145  typedef	   traits		traits_type;
146  typedef typename traits::char_type	value_type;
147  typedef	   Allocator		allocator_type;
148
149  typedef size_t size_type;
150  typedef ptrdiff_t difference_type;
151  typedef charT& reference;
152  typedef const charT& const_reference;
153  typedef charT* pointer;
154  typedef const charT* const_pointer;
155  typedef pointer iterator;
156  typedef const_pointer const_iterator;
157  typedef ::reverse_iterator<iterator> reverse_iterator;
158  typedef ::reverse_iterator<const_iterator> const_reverse_iterator;
159  static const size_type npos = static_cast<size_type>(-1);
160
161private:
162  Rep *rep () const { return reinterpret_cast<Rep *>(dat) - 1; }
163  void repup (Rep *p) { rep ()->release (); dat = p->data (); }
164
165public:
166  const charT* data () const
167    { return rep ()->data(); }
168  size_type length () const
169    { return rep ()->len; }
170  size_type size () const
171    { return rep ()->len; }
172  size_type capacity () const
173    { return rep ()->res; }
174  size_type max_size () const
175    { return (npos - 1)/sizeof (charT); }		// XXX
176  bool empty () const
177    { return size () == 0; }
178
179// _lib.string.cons_ construct/copy/destroy:
180  basic_string& operator= (const basic_string& str)
181    {
182      if (&str != this) { rep ()->release (); dat = str.rep ()->grab (); }
183      return *this;
184    }
185
186  explicit basic_string (): dat (nilRep.grab ()) { }
187  basic_string (const basic_string& _str): dat (_str.rep ()->grab ()) { }
188  basic_string (const basic_string& _str, size_type pos, size_type n = npos)
189    : dat (nilRep.grab ()) { assign (_str, pos, n); }
190  basic_string (const charT* s, size_type n)
191    : dat (nilRep.grab ()) { assign (s, n); }
192  basic_string (const charT* s)
193    : dat (nilRep.grab ()) { assign (s); }
194  basic_string (size_type n, charT c)
195    : dat (nilRep.grab ()) { assign (n, c); }
196#ifdef __STL_MEMBER_TEMPLATES
197  template<class InputIterator>
198    basic_string(InputIterator __begin, InputIterator __end)
199#else
200  basic_string(const_iterator __begin, const_iterator __end)
201#endif
202    : dat (nilRep.grab ()) { assign (__begin, __end); }
203
204  ~basic_string ()
205    { rep ()->release (); }
206
207  void swap (basic_string &s) { charT *d = dat; dat = s.dat; s.dat = d; }
208
209  basic_string& append (const basic_string& _str, size_type pos = 0,
210			size_type n = npos)
211    { return replace (length (), 0, _str, pos, n); }
212  basic_string& append (const charT* s, size_type n)
213    { return replace (length (), 0, s, n); }
214  basic_string& append (const charT* s)
215    { return append (s, traits::length (s)); }
216  basic_string& append (size_type n, charT c)
217    { return replace (length (), 0, n, c); }
218#ifdef __STL_MEMBER_TEMPLATES
219  template<class InputIterator>
220    basic_string& append(InputIterator first, InputIterator last)
221#else
222  basic_string& append(const_iterator first, const_iterator last)
223#endif
224    { return replace (iend (), iend (), first, last); }
225
226  void push_back(charT __c)
227  { append(1, __c); }
228
229  basic_string& assign (const basic_string& str, size_type pos = 0,
230			size_type n = npos)
231    { return replace (0, npos, str, pos, n); }
232  basic_string& assign (const charT* s, size_type n)
233    { return replace (0, npos, s, n); }
234  basic_string& assign (const charT* s)
235    { return assign (s, traits::length (s)); }
236  basic_string& assign (size_type n, charT c)
237    { return replace (0, npos, n, c); }
238#ifdef __STL_MEMBER_TEMPLATES
239  template<class InputIterator>
240    basic_string& assign(InputIterator first, InputIterator last)
241#else
242  basic_string& assign(const_iterator first, const_iterator last)
243#endif
244    { return replace (ibegin (), iend (), first, last); }
245
246  basic_string& operator= (const charT* s)
247    { return assign (s); }
248  basic_string& operator= (charT c)
249    { return assign (1, c); }
250
251  basic_string& operator+= (const basic_string& rhs)
252    { return append (rhs); }
253  basic_string& operator+= (const charT* s)
254    { return append (s); }
255  basic_string& operator+= (charT c)
256    { return append (1, c); }
257
258  basic_string& insert (size_type pos1, const basic_string& str,
259			size_type pos2 = 0, size_type n = npos)
260    { return replace (pos1, 0, str, pos2, n); }
261  basic_string& insert (size_type pos, const charT* s, size_type n)
262    { return replace (pos, 0, s, n); }
263  basic_string& insert (size_type pos, const charT* s)
264    { return insert (pos, s, traits::length (s)); }
265  basic_string& insert (size_type pos, size_type n, charT c)
266    { return replace (pos, 0, n, c); }
267  iterator insert(iterator p, charT c)
268    { size_type __o = p - ibegin ();
269      insert (p - ibegin (), 1, c); selfish ();
270      return ibegin () + __o; }
271  iterator insert(iterator p, size_type n, charT c)
272    { size_type __o = p - ibegin ();
273      insert (p - ibegin (), n, c); selfish ();
274      return ibegin () + __o; }
275#ifdef __STL_MEMBER_TEMPLATES
276  template<class InputIterator>
277    void insert(iterator p, InputIterator first, InputIterator last)
278#else
279  void insert(iterator p, const_iterator first, const_iterator last)
280#endif
281    { replace (p, p, first, last); }
282
283  basic_string& erase (size_type pos = 0, size_type n = npos)
284    { return replace (pos, n, (size_type)0, (charT)0); }
285  iterator erase(iterator p)
286    { size_type __o = p - begin();
287      replace (__o, 1, (size_type)0, (charT)0); selfish ();
288      return ibegin() + __o; }
289  iterator erase(iterator f, iterator l)
290    { size_type __o = f - ibegin();
291      replace (__o, l-f, (size_type)0, (charT)0);selfish ();
292      return ibegin() + __o; }
293
294  void clear()
295    { erase(begin(), end()); }
296  basic_string& replace (size_type pos1, size_type n1, const basic_string& str,
297			 size_type pos2 = 0, size_type n2 = npos);
298  basic_string& replace (size_type pos, size_type n1, const charT* s,
299			 size_type n2);
300  basic_string& replace (size_type pos, size_type n1, const charT* s)
301    { return replace (pos, n1, s, traits::length (s)); }
302  basic_string& replace (size_type pos, size_type n1, size_type n2, charT c);
303  basic_string& replace (size_type pos, size_type n, charT c)
304    { return replace (pos, n, 1, c); }
305  basic_string& replace (iterator i1, iterator i2, const basic_string& str)
306    { return replace (i1 - ibegin (), i2 - i1, str); }
307  basic_string& replace (iterator i1, iterator i2, const charT* s, size_type n)
308    { return replace (i1 - ibegin (), i2 - i1, s, n); }
309  basic_string& replace (iterator i1, iterator i2, const charT* s)
310    { return replace (i1 - ibegin (), i2 - i1, s); }
311  basic_string& replace (iterator i1, iterator i2, size_type n, charT c)
312    { return replace (i1 - ibegin (), i2 - i1, n, c); }
313#ifdef __STL_MEMBER_TEMPLATES
314  template<class InputIterator>
315    basic_string& replace(iterator i1, iterator i2,
316			  InputIterator j1, InputIterator j2);
317#else
318  basic_string& replace(iterator i1, iterator i2,
319			const_iterator j1, const_iterator j2);
320#endif
321
322private:
323  static charT eos () { return traits::eos (); }
324  void unique () { if (rep ()->ref > 1) alloc (length (), true); }
325  void selfish () { unique (); rep ()->selfish = true; }
326
327public:
328  charT operator[] (size_type pos) const
329    {
330      if (pos == length ())
331	return eos ();
332      return data ()[pos];
333    }
334
335  reference operator[] (size_type pos)
336    { selfish (); return (*rep ())[pos]; }
337
338  reference at (size_type pos)
339    {
340      OUTOFRANGE (pos >= length ());
341      return (*this)[pos];
342    }
343  const_reference at (size_type pos) const
344    {
345      OUTOFRANGE (pos >= length ());
346      return data ()[pos];
347    }
348
349private:
350  void terminate () const
351    { traits::assign ((*rep ())[length ()], eos ()); }
352
353public:
354  const charT* c_str () const
355    {
356	  static const charT null_str[1] = {0};
357	  if (length () == 0) return null_str; terminate (); return data ();
358	}
359  void resize (size_type n, charT c);
360  void resize (size_type n)
361    { resize (n, eos ()); }
362  void reserve (size_type) { }
363
364  size_type copy (charT* s, size_type n, size_type pos = 0) const;
365
366  size_type find (const basic_string& str, size_type pos = 0) const
367    { return find (str.data(), pos, str.length()); }
368  size_type find (const charT* s, size_type pos, size_type n) const;
369  size_type find (const charT* _s, size_type pos = 0) const
370    { return find (_s, pos, traits::length (_s)); }
371  size_type find (charT c, size_type pos = 0) const;
372
373  size_type rfind (const basic_string& str, size_type pos = npos) const
374    { return rfind (str.data(), pos, str.length()); }
375  size_type rfind (const charT* s, size_type pos, size_type n) const;
376  size_type rfind (const charT* s, size_type pos = npos) const
377    { return rfind (s, pos, traits::length (s)); }
378  size_type rfind (charT c, size_type pos = npos) const;
379
380  size_type find_first_of (const basic_string& str, size_type pos = 0) const
381    { return find_first_of (str.data(), pos, str.length()); }
382  size_type find_first_of (const charT* s, size_type pos, size_type n) const;
383  size_type find_first_of (const charT* s, size_type pos = 0) const
384    { return find_first_of (s, pos, traits::length (s)); }
385  size_type find_first_of (charT c, size_type pos = 0) const
386    { return find (c, pos); }
387
388  size_type find_last_of (const basic_string& str, size_type pos = npos) const
389    { return find_last_of (str.data(), pos, str.length()); }
390  size_type find_last_of (const charT* s, size_type pos, size_type n) const;
391  size_type find_last_of (const charT* s, size_type pos = npos) const
392    { return find_last_of (s, pos, traits::length (s)); }
393  size_type find_last_of (charT c, size_type pos = npos) const
394    { return rfind (c, pos); }
395
396  size_type find_first_not_of (const basic_string& str, size_type pos = 0) const
397    { return find_first_not_of (str.data(), pos, str.length()); }
398  size_type find_first_not_of (const charT* s, size_type pos, size_type n) const;
399  size_type find_first_not_of (const charT* s, size_type pos = 0) const
400    { return find_first_not_of (s, pos, traits::length (s)); }
401  size_type find_first_not_of (charT c, size_type pos = 0) const;
402
403  size_type find_last_not_of (const basic_string& str, size_type pos = npos) const
404    { return find_last_not_of (str.data(), pos, str.length()); }
405  size_type find_last_not_of (const charT* s, size_type pos, size_type n) const;
406  size_type find_last_not_of (const charT* s, size_type pos = npos) const
407    { return find_last_not_of (s, pos, traits::length (s)); }
408  size_type find_last_not_of (charT c, size_type pos = npos) const;
409
410  basic_string substr (size_type pos = 0, size_type n = npos) const
411    { return basic_string (*this, pos, n); }
412
413
414  // BeOS bogus versions
415  int compare (const charT* s, size_type pos, size_type n) const;
416  int compare (const basic_string& str, size_type pos = 0, size_type n = npos) const;
417  // There is no 'strncmp' equivalent for charT pointers.
418
419  // Correct std C++ prototypes
420  int compare (size_type pos, size_type n, const basic_string& str) const
421	{ return compare(str, pos, n); }
422  int compare (size_type pos, size_type n, const charT* s) const
423    { return compare(s, pos, n); }
424  int compare (size_type pos, size_type n, const charT* s, size_type n2) const
425    { if (n > n2) n = n2; return compare(s, pos, n); }
426  int compare (const charT* s, size_type pos = 0) const
427    { return compare (s, pos, traits::length (s)); }
428
429  iterator begin () { selfish (); return &(*this)[0]; }
430  iterator end () { selfish (); return &(*this)[length ()]; }
431
432private:
433  iterator ibegin () const { return &(*rep ())[0]; }
434  iterator iend () const { return &(*rep ())[length ()]; }
435
436public:
437  const_iterator begin () const { return ibegin (); }
438  const_iterator end () const { return iend (); }
439
440  reverse_iterator       rbegin() { return reverse_iterator (end ()); }
441  const_reverse_iterator rbegin() const
442    { return const_reverse_iterator (end ()); }
443  reverse_iterator       rend() { return reverse_iterator (begin ()); }
444  const_reverse_iterator rend() const
445    { return const_reverse_iterator (begin ()); }
446
447private:
448  void alloc (size_type size, bool save);
449  static size_type _find (const charT* ptr, charT c, size_type xpos, size_type len);
450  inline bool check_realloc (size_type s) const;
451
452  static Rep nilRep;
453  charT *dat;
454};
455
456#ifdef __STL_MEMBER_TEMPLATES
457template <class charT, class traits, class Allocator> template <class InputIterator>
458basic_string <charT, traits, Allocator>& basic_string <charT, traits, Allocator>::
459replace (iterator i1, iterator i2, InputIterator j1, InputIterator j2)
460#else
461template <class charT, class traits, class Allocator>
462basic_string <charT, traits, Allocator>& basic_string <charT, traits, Allocator>::
463replace (iterator i1, iterator i2, const_iterator j1, const_iterator j2)
464#endif
465{
466  const size_type len = length ();
467  size_type pos = i1 - ibegin ();
468  size_type n1 = i2 - i1;
469  size_type n2 = j2 - j1;
470
471  OUTOFRANGE (pos > len);
472  if (n1 > len - pos)
473    n1 = len - pos;
474  LENGTHERROR (len - n1 > max_size () - n2);
475  size_t newlen = len - n1 + n2;
476
477  if (check_realloc (newlen))
478    {
479      Rep *p = Rep::create (newlen);
480      p->copy (0, data (), pos);
481      p->copy (pos + n2, data () + pos + n1, len - (pos + n1));
482      for (; j1 != j2; ++j1, ++pos)
483	traits::assign ((*p)[pos], *j1);
484      repup (p);
485    }
486  else
487    {
488      rep ()->move (pos + n2, data () + pos + n1, len - (pos + n1));
489      for (; j1 != j2; ++j1, ++pos)
490	traits::assign ((*rep ())[pos], *j1);
491    }
492  rep ()->len = newlen;
493
494  return *this;
495}
496
497template <class charT, class traits, class Allocator>
498inline basic_string <charT, traits, Allocator>
499operator+ (const basic_string <charT, traits, Allocator>& lhs,
500	   const basic_string <charT, traits, Allocator>& rhs)
501{
502  basic_string <charT, traits, Allocator> _str (lhs);
503  _str.append (rhs);
504  return _str;
505}
506
507template <class charT, class traits, class Allocator>
508inline basic_string <charT, traits, Allocator>
509operator+ (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs)
510{
511  basic_string <charT, traits, Allocator> _str (lhs);
512  _str.append (rhs);
513  return _str;
514}
515
516template <class charT, class traits, class Allocator>
517inline basic_string <charT, traits, Allocator>
518operator+ (charT lhs, const basic_string <charT, traits, Allocator>& rhs)
519{
520  basic_string <charT, traits, Allocator> _str (1, lhs);
521  _str.append (rhs);
522  return _str;
523}
524
525template <class charT, class traits, class Allocator>
526inline basic_string <charT, traits, Allocator>
527operator+ (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs)
528{
529  basic_string <charT, traits, Allocator> _str (lhs);
530  _str.append (rhs);
531  return _str;
532}
533
534template <class charT, class traits, class Allocator>
535inline basic_string <charT, traits, Allocator>
536operator+ (const basic_string <charT, traits, Allocator>& lhs, charT rhs)
537{
538  basic_string <charT, traits, Allocator> str (lhs);
539  str.append (1, rhs);
540  return str;
541}
542
543template <class charT, class traits, class Allocator>
544inline bool
545operator== (const basic_string <charT, traits, Allocator>& lhs,
546	    const basic_string <charT, traits, Allocator>& rhs)
547{
548  return (lhs.compare (rhs) == 0);
549}
550
551template <class charT, class traits, class Allocator>
552inline bool
553operator== (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs)
554{
555  return (rhs.compare (lhs) == 0);
556}
557
558template <class charT, class traits, class Allocator>
559inline bool
560operator== (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs)
561{
562  return (lhs.compare (rhs) == 0);
563}
564
565template <class charT, class traits, class Allocator>
566inline bool
567operator!= (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs)
568{
569  return (rhs.compare (lhs) != 0);
570}
571
572template <class charT, class traits, class Allocator>
573inline bool
574operator!= (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs)
575{
576  return (lhs.compare (rhs) != 0);
577}
578
579template <class charT, class traits, class Allocator>
580inline bool
581operator< (const basic_string <charT, traits, Allocator>& lhs,
582	    const basic_string <charT, traits, Allocator>& rhs)
583{
584  return (lhs.compare (rhs) < 0);
585}
586
587template <class charT, class traits, class Allocator>
588inline bool
589operator< (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs)
590{
591  return (rhs.compare (lhs) > 0);
592}
593
594template <class charT, class traits, class Allocator>
595inline bool
596operator< (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs)
597{
598  return (lhs.compare (rhs) < 0);
599}
600
601template <class charT, class traits, class Allocator>
602inline bool
603operator> (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs)
604{
605  return (rhs.compare (lhs) < 0);
606}
607
608template <class charT, class traits, class Allocator>
609inline bool
610operator> (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs)
611{
612  return (lhs.compare (rhs) > 0);
613}
614
615template <class charT, class traits, class Allocator>
616inline bool
617operator<= (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs)
618{
619  return (rhs.compare (lhs) >= 0);
620}
621
622template <class charT, class traits, class Allocator>
623inline bool
624operator<= (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs)
625{
626  return (lhs.compare (rhs) <= 0);
627}
628
629template <class charT, class traits, class Allocator>
630inline bool
631operator>= (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs)
632{
633  return (rhs.compare (lhs) <= 0);
634}
635
636template <class charT, class traits, class Allocator>
637inline bool
638operator>= (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs)
639{
640  return (lhs.compare (rhs) >= 0);
641}
642
643template <class charT, class traits, class Allocator>
644inline bool
645operator!= (const basic_string <charT, traits, Allocator>& lhs,
646	    const basic_string <charT, traits, Allocator>& rhs)
647{
648  return (lhs.compare (rhs) != 0);
649}
650
651template <class charT, class traits, class Allocator>
652inline bool
653operator> (const basic_string <charT, traits, Allocator>& lhs,
654	   const basic_string <charT, traits, Allocator>& rhs)
655{
656  return (lhs.compare (rhs) > 0);
657}
658
659template <class charT, class traits, class Allocator>
660inline bool
661operator<= (const basic_string <charT, traits, Allocator>& lhs,
662	    const basic_string <charT, traits, Allocator>& rhs)
663{
664  return (lhs.compare (rhs) <= 0);
665}
666
667template <class charT, class traits, class Allocator>
668inline bool
669operator>= (const basic_string <charT, traits, Allocator>& lhs,
670	    const basic_string <charT, traits, Allocator>& rhs)
671{
672  return (lhs.compare (rhs) >= 0);
673}
674
675class istream; class ostream;
676template <class charT, class traits, class Allocator> istream&
677operator>> (istream&, basic_string <charT, traits, Allocator>&);
678template <class charT, class traits, class Allocator> ostream&
679operator<< (ostream&, const basic_string <charT, traits, Allocator>&);
680template <class charT, class traits, class Allocator> istream&
681getline (istream&, basic_string <charT, traits, Allocator>&, charT delim = '\n');
682
683} // extern "C++"
684
685#include <std/bastring.cc>
686
687#endif
688