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