1 // Member templates for the -*- C++ -*- string classes. 2 // Copyright (C) 1994, 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 extern "C++" { 29 template <class charT, class traits, class Allocator> 30 inline void * basic_string <charT, traits, Allocator>::Rep:: 31 operator new (size_t s, size_t extra) 32 { 33 return Allocator::allocate(s + extra * sizeof (charT)); 34 } 35 36 template <class charT, class traits, class Allocator> 37 inline void basic_string <charT, traits, Allocator>::Rep:: 38 operator delete (void * ptr) 39 { 40 Allocator::deallocate(ptr, sizeof(Rep) + 41 reinterpret_cast<Rep *>(ptr)->res * 42 sizeof (charT)); 43 } 44 45 template <class charT, class traits, class Allocator> 46 inline size_t basic_string <charT, traits, Allocator>::Rep:: 47 frob_size (size_t s) 48 { 49 size_t i = 16; 50 while (i < s) i *= 2; 51 return i; 52 } 53 54 template <class charT, class traits, class Allocator> 55 inline basic_string <charT, traits, Allocator>::Rep * 56 basic_string <charT, traits, Allocator>::Rep:: 57 create (size_t extra) 58 { 59 extra = frob_size (extra + 1); 60 Rep *p = new (extra) Rep; 61 p->res = extra; 62 p->ref = 1; 63 p->selfish = false; 64 return p; 65 } 66 67 template <class charT, class traits, class Allocator> 68 charT * basic_string <charT, traits, Allocator>::Rep:: 69 clone () 70 { 71 Rep *p = Rep::create (len); 72 p->copy (0, data (), len); 73 p->len = len; 74 return p->data (); 75 } 76 77 template <class charT, class traits, class Allocator> 78 inline bool basic_string <charT, traits, Allocator>::Rep:: 79 excess_slop (size_t s, size_t r) 80 { 81 return 2 * (s <= 16 ? 16 : s) < r; 82 } 83 84 template <class charT, class traits, class Allocator> 85 inline bool basic_string <charT, traits, Allocator>:: 86 check_realloc (basic_string::size_type s) const 87 { 88 s += sizeof (charT); 89 rep ()->selfish = false; 90 return (rep ()->ref > 1 91 || s > capacity () 92 || Rep::excess_slop (s, capacity ())); 93 } 94 95 template <class charT, class traits, class Allocator> 96 void basic_string <charT, traits, Allocator>:: 97 alloc (basic_string::size_type __size, bool __save) 98 { 99 if (! check_realloc (__size)) 100 return; 101 102 Rep *p = Rep::create (__size); 103 104 if (__save) 105 { 106 p->copy (0, data (), length ()); 107 p->len = length (); 108 } 109 else 110 p->len = 0; 111 112 repup (p); 113 } 114 115 template <class charT, class traits, class Allocator> 116 basic_string <charT, traits, Allocator>& 117 basic_string <charT, traits, Allocator>:: 118 replace (size_type pos1, size_type n1, 119 const basic_string& _str, size_type pos2, size_type n2) 120 { 121 const size_t len2 = _str.length (); 122 123 if (pos1 == 0 && n1 >= length () && pos2 == 0 && n2 >= len2) 124 return operator= (_str); 125 126 OUTOFRANGE (pos2 > len2); 127 128 if (n2 > len2 - pos2) 129 n2 = len2 - pos2; 130 131 return replace (pos1, n1, _str.data () + pos2, n2); 132 } 133 134 template <class charT, class traits, class Allocator> 135 inline void basic_string <charT, traits, Allocator>::Rep:: 136 copy (size_t pos, const charT *s, size_t n) 137 { 138 if (n) 139 traits::copy (data () + pos, s, n); 140 } 141 142 template <class charT, class traits, class Allocator> 143 inline void basic_string <charT, traits, Allocator>::Rep:: 144 move (size_t pos, const charT *s, size_t n) 145 { 146 if (n) 147 traits::move (data () + pos, s, n); 148 } 149 150 template <class charT, class traits, class Allocator> 151 basic_string <charT, traits, Allocator>& 152 basic_string <charT, traits, Allocator>:: 153 replace (size_type pos, size_type n1, const charT* s, size_type n2) 154 { 155 const size_type len = length (); 156 OUTOFRANGE (pos > len); 157 if (n1 > len - pos) 158 n1 = len - pos; 159 LENGTHERROR (len - n1 > max_size () - n2); 160 size_t newlen = len - n1 + n2; 161 162 if (check_realloc (newlen)) 163 { 164 Rep *p = Rep::create (newlen); 165 p->copy (0, data (), pos); 166 p->copy (pos + n2, data () + pos + n1, len - (pos + n1)); 167 p->copy (pos, s, n2); 168 repup (p); 169 } 170 else 171 { 172 rep ()->move (pos + n2, data () + pos + n1, len - (pos + n1)); 173 rep ()->copy (pos, s, n2); 174 } 175 rep ()->len = newlen; 176 177 return *this; 178 } 179 180 template <class charT, class traits, class Allocator> 181 inline void basic_string <charT, traits, Allocator>::Rep:: 182 set (size_t pos, const charT c, size_t n) 183 { 184 traits::set (data () + pos, c, n); 185 } 186 187 template <class charT, class traits, class Allocator> 188 basic_string <charT, traits, Allocator>& basic_string <charT, traits, Allocator>:: 189 replace (size_type pos, size_type n1, size_type n2, charT c) 190 { 191 const size_t len = length (); 192 OUTOFRANGE (pos > len); 193 if (n1 > len - pos) 194 n1 = len - pos; 195 LENGTHERROR (len - n1 > max_size () - n2); 196 size_t newlen = len - n1 + n2; 197 198 if (check_realloc (newlen)) 199 { 200 Rep *p = Rep::create (newlen); 201 p->copy (0, data (), pos); 202 p->copy (pos + n2, data () + pos + n1, len - (pos + n1)); 203 p->set (pos, c, n2); 204 repup (p); 205 } 206 else 207 { 208 rep ()->move (pos + n2, data () + pos + n1, len - (pos + n1)); 209 rep ()->set (pos, c, n2); 210 } 211 rep ()->len = newlen; 212 213 return *this; 214 } 215 216 template <class charT, class traits, class Allocator> 217 void basic_string <charT, traits, Allocator>:: 218 resize (size_type n, charT c) 219 { 220 LENGTHERROR (n > max_size ()); 221 222 if (n > length ()) 223 append (n - length (), c); 224 else 225 erase (n); 226 } 227 228 template <class charT, class traits, class Allocator> 229 basic_string <charT, traits, Allocator>::size_type 230 basic_string <charT, traits, Allocator>:: 231 copy (charT* s, size_type n, size_type pos) const 232 { 233 OUTOFRANGE (pos > length ()); 234 235 if (n > length () - pos) 236 n = length () - pos; 237 238 traits::copy (s, data () + pos, n); 239 return n; 240 } 241 242 template <class charT, class traits, class Allocator> 243 basic_string <charT, traits, Allocator>::size_type 244 basic_string <charT, traits, Allocator>:: 245 find (const charT* s, size_type pos, size_type n) const 246 { 247 size_t xpos = pos; 248 for (; xpos + n <= length (); ++xpos) 249 if (traits::eq (data () [xpos], *s) 250 && traits::compare (data () + xpos, s, n) == 0) 251 return xpos; 252 return npos; 253 } 254 255 template <class charT, class traits, class Allocator> 256 inline basic_string <charT, traits, Allocator>::size_type 257 basic_string <charT, traits, Allocator>:: 258 _find (const charT* ptr, charT c, size_type xpos, size_type len) 259 { 260 for (; xpos < len; ++xpos) 261 if (traits::eq (ptr [xpos], c)) 262 return xpos; 263 return npos; 264 } 265 266 template <class charT, class traits, class Allocator> 267 basic_string <charT, traits, Allocator>::size_type 268 basic_string <charT, traits, Allocator>:: 269 find (charT c, size_type pos) const 270 { 271 return _find (data (), c, pos, length ()); 272 } 273 274 template <class charT, class traits, class Allocator> 275 basic_string <charT, traits, Allocator>::size_type 276 basic_string <charT, traits, Allocator>:: 277 rfind (const charT* s, size_type pos, size_type n) const 278 { 279 if (n > length ()) 280 return npos; 281 282 size_t xpos = length () - n; 283 if (xpos > pos) 284 xpos = pos; 285 286 for (++xpos; xpos-- > 0; ) 287 if (traits::eq (data () [xpos], *s) 288 && traits::compare (data () + xpos, s, n) == 0) 289 return xpos; 290 return npos; 291 } 292 293 template <class charT, class traits, class Allocator> 294 basic_string <charT, traits, Allocator>::size_type 295 basic_string <charT, traits, Allocator>:: 296 rfind (charT c, size_type pos) const 297 { 298 if (1 > length ()) 299 return npos; 300 301 size_t xpos = length () - 1; 302 if (xpos > pos) 303 xpos = pos; 304 305 for (++xpos; xpos-- > 0; ) 306 if (traits::eq (data () [xpos], c)) 307 return xpos; 308 return npos; 309 } 310 311 template <class charT, class traits, class Allocator> 312 basic_string <charT, traits, Allocator>::size_type 313 basic_string <charT, traits, Allocator>:: 314 find_first_of (const charT* s, size_type pos, size_type n) const 315 { 316 size_t xpos = pos; 317 for (; xpos < length (); ++xpos) 318 if (_find (s, data () [xpos], 0, n) != npos) 319 return xpos; 320 return npos; 321 } 322 323 template <class charT, class traits, class Allocator> 324 basic_string <charT, traits, Allocator>::size_type 325 basic_string <charT, traits, Allocator>:: 326 find_last_of (const charT* s, size_type pos, size_type n) const 327 { 328 if (length() == 0) 329 return npos; 330 size_t xpos = length () - 1; 331 if (xpos > pos) 332 xpos = pos; 333 for (++xpos; xpos-- > 0;) 334 if (_find (s, data () [xpos], 0, n) != npos) 335 return xpos; 336 return npos; 337 } 338 339 template <class charT, class traits, class Allocator> 340 basic_string <charT, traits, Allocator>::size_type 341 basic_string <charT, traits, Allocator>:: 342 find_first_not_of (const charT* s, size_type pos, size_type n) const 343 { 344 size_t xpos = pos; 345 for (; xpos < length (); ++xpos) 346 if (_find (s, data () [xpos], 0, n) == npos) 347 return xpos; 348 return npos; 349 } 350 351 template <class charT, class traits, class Allocator> 352 basic_string <charT, traits, Allocator>::size_type 353 basic_string <charT, traits, Allocator>:: 354 find_first_not_of (charT c, size_type pos) const 355 { 356 size_t xpos = pos; 357 for (; xpos < length (); ++xpos) 358 if (traits::ne (data () [xpos], c)) 359 return xpos; 360 return npos; 361 } 362 363 template <class charT, class traits, class Allocator> 364 basic_string <charT, traits, Allocator>::size_type 365 basic_string <charT, traits, Allocator>:: 366 find_last_not_of (const charT* s, size_type pos, size_type n) const 367 { 368 if (length() == 0) 369 return npos; 370 size_t xpos = length () - 1; 371 if (xpos > pos) 372 xpos = pos; 373 for (++xpos; xpos-- > 0;) 374 if (_find (s, data () [xpos], 0, n) == npos) 375 return xpos; 376 return npos; 377 } 378 379 template <class charT, class traits, class Allocator> 380 basic_string <charT, traits, Allocator>::size_type 381 basic_string <charT, traits, Allocator>:: 382 find_last_not_of (charT c, size_type pos) const 383 { 384 if (length() == 0) 385 return npos; 386 size_t xpos = length () - 1; 387 if (xpos > pos) 388 xpos = pos; 389 for (++xpos; xpos-- > 0;) 390 if (traits::ne (data () [xpos], c)) 391 return xpos; 392 return npos; 393 } 394 395 template <class charT, class traits, class Allocator> 396 int basic_string <charT, traits, Allocator>:: 397 compare (const basic_string& _str, size_type pos, size_type n) const 398 { 399 OUTOFRANGE (pos > length ()); 400 401 size_t rlen = length () - pos; 402 if (rlen > n) 403 rlen = n; 404 if (rlen > _str.length ()) 405 rlen = _str.length (); 406 int r = traits::compare (data () + pos, _str.data (), rlen); 407 if (r != 0) 408 return r; 409 if (rlen == n) 410 return 0; 411 return (length () - pos) - _str.length (); 412 } 413 414 template <class charT, class traits, class Allocator> 415 int basic_string <charT, traits, Allocator>:: 416 compare (const charT* s, size_type pos, size_type n) const 417 { 418 OUTOFRANGE (pos > length ()); 419 420 size_t rlen = length () - pos; 421 if (rlen > n) 422 rlen = n; 423 int r = traits::compare (data () + pos, s, rlen); 424 if (r != 0) 425 return r; 426 return (length () - pos) - n; 427 } 428 429 #include <iostream.h> 430 431 template <class charT, class traits, class Allocator> 432 istream & 433 operator>> (istream &is, basic_string <charT, traits, Allocator> &s) 434 { 435 int w = is.width (0); 436 if (is.ipfx0 ()) 437 { 438 register streambuf *sb = is.rdbuf (); 439 s.resize (0); 440 while (1) 441 { 442 int ch = sb->sbumpc (); 443 if (ch == EOF) 444 { 445 is.setstate (ios::eofbit); 446 break; 447 } 448 else if (traits::is_del (ch)) 449 { 450 sb->sungetc (); 451 break; 452 } 453 s += static_cast<charT> (ch); 454 if (--w == 1) 455 break; 456 } 457 } 458 459 is.isfx (); 460 if (s.length () == 0) 461 is.setstate (ios::failbit); 462 463 return is; 464 } 465 466 template <class charT, class traits, class Allocator> 467 ostream & 468 operator<< (ostream &o, const basic_string <charT, traits, Allocator>& s) 469 { 470 return o.write (s.data (), s.length ()); 471 } 472 473 template <class charT, class traits, class Allocator> 474 istream& 475 getline (istream &is, basic_string <charT, traits, Allocator>& s, charT delim) 476 { 477 if (is.ipfx1 ()) 478 { 479 _IO_size_t _count = 0; 480 streambuf *sb = is.rdbuf (); 481 s.resize (0); 482 483 while (1) 484 { 485 int ch = sb->sbumpc (); 486 if (ch == EOF) 487 { 488 is.setstate (_count == 0 489 ? (ios::failbit|ios::eofbit) 490 : ios::eofbit); 491 break; 492 } 493 494 ++_count; 495 496 if (ch == delim) 497 break; 498 499 s += static_cast<charT> (ch); 500 501 if (s.length () == s.npos - 1) 502 { 503 is.setstate (ios::failbit); 504 break; 505 } 506 } 507 } 508 509 // We need to be friends with istream to do this. 510 // is._gcount = _count; 511 is.isfx (); 512 513 return is; 514 } 515 516 template <class charT, class traits, class Allocator> 517 basic_string <charT, traits, Allocator>::Rep 518 basic_string<charT, traits, Allocator>::nilRep = { 0, 0, 1, false }; 519 520 template <class charT, class traits, class Allocator> 521 const basic_string <charT, traits, Allocator>::size_type 522 basic_string <charT, traits, Allocator>::npos; 523 524 } // extern "C++" 525