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(volatile __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((volatile __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  int compare (const basic_string& str, size_type pos = 0, size_type n = npos) const;
412  // There is no 'strncmp' equivalent for charT pointers.
413
414  // BeOS bogus version
415  int compare (const charT* s, size_type pos, size_type n) const;
416
417  // Correct std C++ prototype
418  int compare (size_type pos, size_type n, const charT* s) const
419    { return compare(s, pos, n); }
420  int compare (const charT* s, size_type pos = 0) const
421    { return compare (s, pos, traits::length (s)); }
422
423  iterator begin () { selfish (); return &(*this)[0]; }
424  iterator end () { selfish (); return &(*this)[length ()]; }
425
426private:
427  iterator ibegin () const { return &(*rep ())[0]; }
428  iterator iend () const { return &(*rep ())[length ()]; }
429
430public:
431  const_iterator begin () const { return ibegin (); }
432  const_iterator end () const { return iend (); }
433
434  reverse_iterator       rbegin() { return reverse_iterator (end ()); }
435  const_reverse_iterator rbegin() const
436    { return const_reverse_iterator (end ()); }
437  reverse_iterator       rend() { return reverse_iterator (begin ()); }
438  const_reverse_iterator rend() const
439    { return const_reverse_iterator (begin ()); }
440
441private:
442  void alloc (size_type size, bool save);
443  static size_type _find (const charT* ptr, charT c, size_type xpos, size_type len);
444  inline bool check_realloc (size_type s) const;
445
446  static Rep nilRep;
447  charT *dat;
448};
449
450#ifdef __STL_MEMBER_TEMPLATES
451template <class charT, class traits, class Allocator> template <class InputIterator>
452basic_string <charT, traits, Allocator>& basic_string <charT, traits, Allocator>::
453replace (iterator i1, iterator i2, InputIterator j1, InputIterator j2)
454#else
455template <class charT, class traits, class Allocator>
456basic_string <charT, traits, Allocator>& basic_string <charT, traits, Allocator>::
457replace (iterator i1, iterator i2, const_iterator j1, const_iterator j2)
458#endif
459{
460  const size_type len = length ();
461  size_type pos = i1 - ibegin ();
462  size_type n1 = i2 - i1;
463  size_type n2 = j2 - j1;
464
465  OUTOFRANGE (pos > len);
466  if (n1 > len - pos)
467    n1 = len - pos;
468  LENGTHERROR (len - n1 > max_size () - n2);
469  size_t newlen = len - n1 + n2;
470
471  if (check_realloc (newlen))
472    {
473      Rep *p = Rep::create (newlen);
474      p->copy (0, data (), pos);
475      p->copy (pos + n2, data () + pos + n1, len - (pos + n1));
476      for (; j1 != j2; ++j1, ++pos)
477	traits::assign ((*p)[pos], *j1);
478      repup (p);
479    }
480  else
481    {
482      rep ()->move (pos + n2, data () + pos + n1, len - (pos + n1));
483      for (; j1 != j2; ++j1, ++pos)
484	traits::assign ((*rep ())[pos], *j1);
485    }
486  rep ()->len = newlen;
487
488  return *this;
489}
490
491template <class charT, class traits, class Allocator>
492inline basic_string <charT, traits, Allocator>
493operator+ (const basic_string <charT, traits, Allocator>& lhs,
494	   const basic_string <charT, traits, Allocator>& rhs)
495{
496  basic_string <charT, traits, Allocator> _str (lhs);
497  _str.append (rhs);
498  return _str;
499}
500
501template <class charT, class traits, class Allocator>
502inline basic_string <charT, traits, Allocator>
503operator+ (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs)
504{
505  basic_string <charT, traits, Allocator> _str (lhs);
506  _str.append (rhs);
507  return _str;
508}
509
510template <class charT, class traits, class Allocator>
511inline basic_string <charT, traits, Allocator>
512operator+ (charT lhs, const basic_string <charT, traits, Allocator>& rhs)
513{
514  basic_string <charT, traits, Allocator> _str (1, lhs);
515  _str.append (rhs);
516  return _str;
517}
518
519template <class charT, class traits, class Allocator>
520inline basic_string <charT, traits, Allocator>
521operator+ (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs)
522{
523  basic_string <charT, traits, Allocator> _str (lhs);
524  _str.append (rhs);
525  return _str;
526}
527
528template <class charT, class traits, class Allocator>
529inline basic_string <charT, traits, Allocator>
530operator+ (const basic_string <charT, traits, Allocator>& lhs, charT rhs)
531{
532  basic_string <charT, traits, Allocator> str (lhs);
533  str.append (1, rhs);
534  return str;
535}
536
537template <class charT, class traits, class Allocator>
538inline bool
539operator== (const basic_string <charT, traits, Allocator>& lhs,
540	    const basic_string <charT, traits, Allocator>& rhs)
541{
542  return (lhs.compare (rhs) == 0);
543}
544
545template <class charT, class traits, class Allocator>
546inline bool
547operator== (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs)
548{
549  return (rhs.compare (lhs) == 0);
550}
551
552template <class charT, class traits, class Allocator>
553inline bool
554operator== (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs)
555{
556  return (lhs.compare (rhs) == 0);
557}
558
559template <class charT, class traits, class Allocator>
560inline bool
561operator!= (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs)
562{
563  return (rhs.compare (lhs) != 0);
564}
565
566template <class charT, class traits, class Allocator>
567inline bool
568operator!= (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs)
569{
570  return (lhs.compare (rhs) != 0);
571}
572
573template <class charT, class traits, class Allocator>
574inline bool
575operator< (const basic_string <charT, traits, Allocator>& lhs,
576	    const basic_string <charT, traits, Allocator>& rhs)
577{
578  return (lhs.compare (rhs) < 0);
579}
580
581template <class charT, class traits, class Allocator>
582inline bool
583operator< (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs)
584{
585  return (rhs.compare (lhs) > 0);
586}
587
588template <class charT, class traits, class Allocator>
589inline bool
590operator< (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs)
591{
592  return (lhs.compare (rhs) < 0);
593}
594
595template <class charT, class traits, class Allocator>
596inline bool
597operator> (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs)
598{
599  return (rhs.compare (lhs) < 0);
600}
601
602template <class charT, class traits, class Allocator>
603inline bool
604operator> (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs)
605{
606  return (lhs.compare (rhs) > 0);
607}
608
609template <class charT, class traits, class Allocator>
610inline bool
611operator<= (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs)
612{
613  return (rhs.compare (lhs) >= 0);
614}
615
616template <class charT, class traits, class Allocator>
617inline bool
618operator<= (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs)
619{
620  return (lhs.compare (rhs) <= 0);
621}
622
623template <class charT, class traits, class Allocator>
624inline bool
625operator>= (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs)
626{
627  return (rhs.compare (lhs) <= 0);
628}
629
630template <class charT, class traits, class Allocator>
631inline bool
632operator>= (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs)
633{
634  return (lhs.compare (rhs) >= 0);
635}
636
637template <class charT, class traits, class Allocator>
638inline bool
639operator!= (const basic_string <charT, traits, Allocator>& lhs,
640	    const basic_string <charT, traits, Allocator>& rhs)
641{
642  return (lhs.compare (rhs) != 0);
643}
644
645template <class charT, class traits, class Allocator>
646inline bool
647operator> (const basic_string <charT, traits, Allocator>& lhs,
648	   const basic_string <charT, traits, Allocator>& rhs)
649{
650  return (lhs.compare (rhs) > 0);
651}
652
653template <class charT, class traits, class Allocator>
654inline bool
655operator<= (const basic_string <charT, traits, Allocator>& lhs,
656	    const basic_string <charT, traits, Allocator>& rhs)
657{
658  return (lhs.compare (rhs) <= 0);
659}
660
661template <class charT, class traits, class Allocator>
662inline bool
663operator>= (const basic_string <charT, traits, Allocator>& lhs,
664	    const basic_string <charT, traits, Allocator>& rhs)
665{
666  return (lhs.compare (rhs) >= 0);
667}
668
669class istream; class ostream;
670template <class charT, class traits, class Allocator> istream&
671operator>> (istream&, basic_string <charT, traits, Allocator>&);
672template <class charT, class traits, class Allocator> ostream&
673operator<< (ostream&, const basic_string <charT, traits, Allocator>&);
674template <class charT, class traits, class Allocator> istream&
675getline (istream&, basic_string <charT, traits, Allocator>&, charT delim = '\n');
676
677} // extern "C++"
678
679#include <std/bastring.cc>
680
681#endif
682