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 45 extern "C++" { 46 class istream; class ostream; 47 48 #include <iterator> 49 50 #ifdef __STL_USE_EXCEPTIONS 51 52 extern void __out_of_range (const char *); 53 extern 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 extern "C" __haiku_int32 atomic_add(volatile __haiku_int32* value, 70 __haiku_int32 addvalue); 71 #endif /* __HAIKU__ */ 72 73 template <class charT, class traits = string_char_traits<charT>, 74 class Allocator = alloc > 75 class basic_string 76 { 77 private: 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 141 public: 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 159 private: 160 Rep *rep () const { return reinterpret_cast<Rep *>(dat) - 1; } 161 void repup (Rep *p) { rep ()->release (); dat = p->data (); } 162 163 public: 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 320 private: 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 325 public: 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 347 private: 348 void terminate () const 349 { traits::assign ((*rep ())[length ()], eos ()); } 350 351 public: 352 const charT* c_str () const 353 { if (length () == 0) return ""; terminate (); return data (); } 354 void resize (size_type n, charT c); 355 void resize (size_type n) 356 { resize (n, eos ()); } 357 void reserve (size_type) { } 358 359 size_type copy (charT* s, size_type n, size_type pos = 0) const; 360 361 size_type find (const basic_string& str, size_type pos = 0) const 362 { return find (str.data(), pos, str.length()); } 363 size_type find (const charT* s, size_type pos, size_type n) const; 364 size_type find (const charT* _s, size_type pos = 0) const 365 { return find (_s, pos, traits::length (_s)); } 366 size_type find (charT c, size_type pos = 0) const; 367 368 size_type rfind (const basic_string& str, size_type pos = npos) const 369 { return rfind (str.data(), pos, str.length()); } 370 size_type rfind (const charT* s, size_type pos, size_type n) const; 371 size_type rfind (const charT* s, size_type pos = npos) const 372 { return rfind (s, pos, traits::length (s)); } 373 size_type rfind (charT c, size_type pos = npos) const; 374 375 size_type find_first_of (const basic_string& str, size_type pos = 0) const 376 { return find_first_of (str.data(), pos, str.length()); } 377 size_type find_first_of (const charT* s, size_type pos, size_type n) const; 378 size_type find_first_of (const charT* s, size_type pos = 0) const 379 { return find_first_of (s, pos, traits::length (s)); } 380 size_type find_first_of (charT c, size_type pos = 0) const 381 { return find (c, pos); } 382 383 size_type find_last_of (const basic_string& str, size_type pos = npos) const 384 { return find_last_of (str.data(), pos, str.length()); } 385 size_type find_last_of (const charT* s, size_type pos, size_type n) const; 386 size_type find_last_of (const charT* s, size_type pos = npos) const 387 { return find_last_of (s, pos, traits::length (s)); } 388 size_type find_last_of (charT c, size_type pos = npos) const 389 { return rfind (c, pos); } 390 391 size_type find_first_not_of (const basic_string& str, size_type pos = 0) const 392 { return find_first_not_of (str.data(), pos, str.length()); } 393 size_type find_first_not_of (const charT* s, size_type pos, size_type n) const; 394 size_type find_first_not_of (const charT* s, size_type pos = 0) const 395 { return find_first_not_of (s, pos, traits::length (s)); } 396 size_type find_first_not_of (charT c, size_type pos = 0) const; 397 398 size_type find_last_not_of (const basic_string& str, size_type pos = npos) const 399 { return find_last_not_of (str.data(), pos, str.length()); } 400 size_type find_last_not_of (const charT* s, size_type pos, size_type n) const; 401 size_type find_last_not_of (const charT* s, size_type pos = npos) const 402 { return find_last_not_of (s, pos, traits::length (s)); } 403 size_type find_last_not_of (charT c, size_type pos = npos) const; 404 405 basic_string substr (size_type pos = 0, size_type n = npos) const 406 { return basic_string (*this, pos, n); } 407 408 int compare (const basic_string& str, size_type pos = 0, size_type n = npos) const; 409 // There is no 'strncmp' equivalent for charT pointers. 410 411 // BeOS bogus version 412 int compare (const charT* s, size_type pos, size_type n) const; 413 414 // Correct std C++ prototype 415 int compare (size_type pos, size_type n, const charT* s) const 416 { return compare(s, pos, n); } 417 int compare (const charT* s, size_type pos = 0) const 418 { return compare (s, pos, traits::length (s)); } 419 420 iterator begin () { selfish (); return &(*this)[0]; } 421 iterator end () { selfish (); return &(*this)[length ()]; } 422 423 private: 424 iterator ibegin () const { return &(*rep ())[0]; } 425 iterator iend () const { return &(*rep ())[length ()]; } 426 427 public: 428 const_iterator begin () const { return ibegin (); } 429 const_iterator end () const { return iend (); } 430 431 reverse_iterator rbegin() { return reverse_iterator (end ()); } 432 const_reverse_iterator rbegin() const 433 { return const_reverse_iterator (end ()); } 434 reverse_iterator rend() { return reverse_iterator (begin ()); } 435 const_reverse_iterator rend() const 436 { return const_reverse_iterator (begin ()); } 437 438 private: 439 void alloc (size_type size, bool save); 440 static size_type _find (const charT* ptr, charT c, size_type xpos, size_type len); 441 inline bool check_realloc (size_type s) const; 442 443 static Rep nilRep; 444 charT *dat; 445 }; 446 447 #ifdef __STL_MEMBER_TEMPLATES 448 template <class charT, class traits, class Allocator> template <class InputIterator> 449 basic_string <charT, traits, Allocator>& basic_string <charT, traits, Allocator>:: 450 replace (iterator i1, iterator i2, InputIterator j1, InputIterator j2) 451 #else 452 template <class charT, class traits, class Allocator> 453 basic_string <charT, traits, Allocator>& basic_string <charT, traits, Allocator>:: 454 replace (iterator i1, iterator i2, const_iterator j1, const_iterator j2) 455 #endif 456 { 457 const size_type len = length (); 458 size_type pos = i1 - ibegin (); 459 size_type n1 = i2 - i1; 460 size_type n2 = j2 - j1; 461 462 OUTOFRANGE (pos > len); 463 if (n1 > len - pos) 464 n1 = len - pos; 465 LENGTHERROR (len - n1 > max_size () - n2); 466 size_t newlen = len - n1 + n2; 467 468 if (check_realloc (newlen)) 469 { 470 Rep *p = Rep::create (newlen); 471 p->copy (0, data (), pos); 472 p->copy (pos + n2, data () + pos + n1, len - (pos + n1)); 473 for (; j1 != j2; ++j1, ++pos) 474 traits::assign ((*p)[pos], *j1); 475 repup (p); 476 } 477 else 478 { 479 rep ()->move (pos + n2, data () + pos + n1, len - (pos + n1)); 480 for (; j1 != j2; ++j1, ++pos) 481 traits::assign ((*rep ())[pos], *j1); 482 } 483 rep ()->len = newlen; 484 485 return *this; 486 } 487 488 template <class charT, class traits, class Allocator> 489 inline basic_string <charT, traits, Allocator> 490 operator+ (const basic_string <charT, traits, Allocator>& lhs, 491 const basic_string <charT, traits, Allocator>& rhs) 492 { 493 basic_string <charT, traits, Allocator> _str (lhs); 494 _str.append (rhs); 495 return _str; 496 } 497 498 template <class charT, class traits, class Allocator> 499 inline basic_string <charT, traits, Allocator> 500 operator+ (const charT* lhs, 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 507 template <class charT, class traits, class Allocator> 508 inline basic_string <charT, traits, Allocator> 509 operator+ (charT lhs, const basic_string <charT, traits, Allocator>& rhs) 510 { 511 basic_string <charT, traits, Allocator> _str (1, lhs); 512 _str.append (rhs); 513 return _str; 514 } 515 516 template <class charT, class traits, class Allocator> 517 inline basic_string <charT, traits, Allocator> 518 operator+ (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs) 519 { 520 basic_string <charT, traits, Allocator> _str (lhs); 521 _str.append (rhs); 522 return _str; 523 } 524 525 template <class charT, class traits, class Allocator> 526 inline basic_string <charT, traits, Allocator> 527 operator+ (const basic_string <charT, traits, Allocator>& lhs, charT rhs) 528 { 529 basic_string <charT, traits, Allocator> str (lhs); 530 str.append (1, rhs); 531 return str; 532 } 533 534 template <class charT, class traits, class Allocator> 535 inline bool 536 operator== (const basic_string <charT, traits, Allocator>& lhs, 537 const basic_string <charT, traits, Allocator>& rhs) 538 { 539 return (lhs.compare (rhs) == 0); 540 } 541 542 template <class charT, class traits, class Allocator> 543 inline bool 544 operator== (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs) 545 { 546 return (rhs.compare (lhs) == 0); 547 } 548 549 template <class charT, class traits, class Allocator> 550 inline bool 551 operator== (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs) 552 { 553 return (lhs.compare (rhs) == 0); 554 } 555 556 template <class charT, class traits, class Allocator> 557 inline bool 558 operator!= (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs) 559 { 560 return (rhs.compare (lhs) != 0); 561 } 562 563 template <class charT, class traits, class Allocator> 564 inline bool 565 operator!= (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs) 566 { 567 return (lhs.compare (rhs) != 0); 568 } 569 570 template <class charT, class traits, class Allocator> 571 inline bool 572 operator< (const basic_string <charT, traits, Allocator>& lhs, 573 const basic_string <charT, traits, Allocator>& rhs) 574 { 575 return (lhs.compare (rhs) < 0); 576 } 577 578 template <class charT, class traits, class Allocator> 579 inline bool 580 operator< (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs) 581 { 582 return (rhs.compare (lhs) > 0); 583 } 584 585 template <class charT, class traits, class Allocator> 586 inline bool 587 operator< (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs) 588 { 589 return (lhs.compare (rhs) < 0); 590 } 591 592 template <class charT, class traits, class Allocator> 593 inline bool 594 operator> (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs) 595 { 596 return (rhs.compare (lhs) < 0); 597 } 598 599 template <class charT, class traits, class Allocator> 600 inline bool 601 operator> (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs) 602 { 603 return (lhs.compare (rhs) > 0); 604 } 605 606 template <class charT, class traits, class Allocator> 607 inline bool 608 operator<= (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs) 609 { 610 return (rhs.compare (lhs) >= 0); 611 } 612 613 template <class charT, class traits, class Allocator> 614 inline bool 615 operator<= (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs) 616 { 617 return (lhs.compare (rhs) <= 0); 618 } 619 620 template <class charT, class traits, class Allocator> 621 inline bool 622 operator>= (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs) 623 { 624 return (rhs.compare (lhs) <= 0); 625 } 626 627 template <class charT, class traits, class Allocator> 628 inline bool 629 operator>= (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs) 630 { 631 return (lhs.compare (rhs) >= 0); 632 } 633 634 template <class charT, class traits, class Allocator> 635 inline bool 636 operator!= (const basic_string <charT, traits, Allocator>& lhs, 637 const basic_string <charT, traits, Allocator>& rhs) 638 { 639 return (lhs.compare (rhs) != 0); 640 } 641 642 template <class charT, class traits, class Allocator> 643 inline bool 644 operator> (const basic_string <charT, traits, Allocator>& lhs, 645 const basic_string <charT, traits, Allocator>& rhs) 646 { 647 return (lhs.compare (rhs) > 0); 648 } 649 650 template <class charT, class traits, class Allocator> 651 inline bool 652 operator<= (const basic_string <charT, traits, Allocator>& lhs, 653 const basic_string <charT, traits, Allocator>& rhs) 654 { 655 return (lhs.compare (rhs) <= 0); 656 } 657 658 template <class charT, class traits, class Allocator> 659 inline bool 660 operator>= (const basic_string <charT, traits, Allocator>& lhs, 661 const basic_string <charT, traits, Allocator>& rhs) 662 { 663 return (lhs.compare (rhs) >= 0); 664 } 665 666 class istream; class ostream; 667 template <class charT, class traits, class Allocator> istream& 668 operator>> (istream&, basic_string <charT, traits, Allocator>&); 669 template <class charT, class traits, class Allocator> ostream& 670 operator<< (ostream&, const basic_string <charT, traits, Allocator>&); 671 template <class charT, class traits, class Allocator> istream& 672 getline (istream&, basic_string <charT, traits, Allocator>&, charT delim = '\n'); 673 674 } // extern "C++" 675 676 #include <std/bastring.cc> 677 678 #endif 679