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