1// -*- Mode: C++; tab-width: 2; -*- 2// vi: set ts=2: 3// 4 5BALL_INLINE 6String::String() 7 : string() 8{ 9} 10 11BALL_INLINE String::String(const String& s) 12 : string(s) 13{ 14} 15 16#ifdef BALL_STD_STRING_HAS_RVALUE_REFERENCES 17BALL_INLINE 18String::String(String&& s) 19 : string(std::move(s)) 20{ 21} 22 23BALL_INLINE 24String::String(string&& s) 25 : string(std::move(s)) 26{ 27} 28 29BALL_INLINE 30String& String::operator=(String&& s) 31{ 32 if (this != &s) 33 { 34 string::operator=(std::move(s)); 35 } 36 37 return *this; 38} 39 40BALL_INLINE 41String& String::operator=(string&& s) 42{ 43 if (this != &s) 44 { 45 string::operator=(std::move(s)); 46 } 47 48 return *this; 49} 50#endif 51 52BALL_INLINE 53String::String(const unsigned char c) 54 : string(1, (char)c) 55{ 56} 57 58BALL_INLINE 59String::String(const char c, Size len) 60 : string(len, c) 61{ 62} 63 64BALL_INLINE 65String::String(const string& s) 66 : string(s) 67{ 68} 69 70BALL_INLINE 71String::String(const String& s, Index from, Size len) 72 : string("") 73{ 74 s.validateRange_(from, len); 75 if (len > 0) 76 { 77 assign(s.c_str() + from, len); 78 } 79} 80 81BALL_INLINE 82#ifdef BALL_HAS_SSTREAM 83void String::set(std::stringstream& s) 84#else 85void String::set(std::strstream& s) 86#endif 87{ 88 s >> (*this); 89} 90 91BALL_INLINE 92void String::set(char c, Size len) 93{ 94 assign(len, c); 95} 96 97BALL_INLINE 98void String::set(unsigned char c) 99{ 100 assign(1, (char)c); 101} 102 103BALL_INLINE 104bool String::operator == (const char* char_ptr) const 105{ 106 return (compare(char_ptr) == 0); 107} 108 109BALL_INLINE 110bool String::operator != (const char* char_ptr) const 111{ 112 return (compare(char_ptr) != 0); 113} 114 115BALL_INLINE 116bool Substring::operator == (const String& s) const 117{ 118 if (bound_ == 0) 119 { 120 throw UnboundSubstring(__FILE__, __LINE__); 121 } 122 123 return (s.compare(bound_->c_str() + from_, 0, to_ - from_ + 1) == 0); 124} 125 126BALL_INLINE 127bool Substring::operator != (const String& s) const 128{ 129 if (bound_ == 0) 130 { 131 throw UnboundSubstring(__FILE__, __LINE__); 132 } 133 134 return (s.compare(bound_->c_str() + from_, 0, to_ - from_ + 1) != 0); 135} 136 137BALL_INLINE 138Size Substring::size() const 139{ 140 if (bound_ == 0) 141 { 142 return 0; 143 } 144 145 return (to_ - from_ + 1); 146} 147 148BALL_INLINE 149Substring::operator String() const 150{ 151 if (bound_ == 0) 152 { 153 throw UnboundSubstring(__FILE__, __LINE__); 154 } 155 156 return String(bound_->c_str(), from_, to_ - from_ + 1); 157} 158 159BALL_INLINE 160void Substring::unbind() 161{ 162 bound_ = 0; 163 from_ = to_ = (Index)String::EndPos; 164} 165 166BALL_INLINE 167void Substring::destroy() 168{ 169 if (bound_ != 0) 170 { 171 bound_->erase(from_, to_ - from_ + 1); 172 } 173 174 unbind(); 175} 176 177BALL_INLINE 178void Substring::clear() 179{ 180 destroy(); 181} 182 183BALL_INLINE 184String Substring::toString() const 185{ 186 if (bound_ == 0) 187 { 188 throw UnboundSubstring(__FILE__, __LINE__); 189 } 190 191 return String(bound_->c_str(), from_, to_ - from_ + 1); 192} 193 194BALL_INLINE 195Substring& Substring::bind(const String& s, Index from, Size len) 196{ 197 s.validateRange_(from, len); 198 199 bound_ = (String *)&s; 200 from_ = from; 201 to_ = from + (Index)len - 1; 202 203 return *this; 204} 205 206BALL_INLINE 207void Substring::set(const String& s) 208{ 209 if (bound_ == 0) 210 { 211 throw Substring::UnboundSubstring(__FILE__, __LINE__); 212 } 213 214 bound_->replace(from_, to_ - from_ + 1, s); 215} 216 217BALL_INLINE 218void Substring::set(const Substring& s) 219{ 220 if (bound_ == 0 || s.bound_ == 0) 221 { 222 throw Substring::UnboundSubstring(__FILE__, __LINE__); 223 } 224 225 bound_->replace(from_, to_ - from_ + 1, s.bound_->c_str() + s.from_, s.size()); 226} 227 228BALL_INLINE 229const Substring& Substring::operator = (const String& s) 230{ 231 set(s); 232 return *this; 233} 234 235BALL_INLINE 236const Substring& Substring::operator = (const Substring& s) 237{ 238 set(s); 239 return *this; 240} 241 242BALL_INLINE 243const Substring& Substring::operator = (const char* char_ptr) 244{ 245 set(char_ptr); 246 return *this; 247} 248 249BALL_INLINE 250String* Substring::getBoundString() 251{ 252 return bound_; 253} 254 255BALL_INLINE 256const String* Substring::getBoundString() const 257{ 258 return bound_; 259} 260 261BALL_INLINE 262char* Substring::c_str() 263{ 264 if (bound_ == 0) 265 { 266 throw UnboundSubstring(__FILE__, __LINE__); 267 } 268 269 return (char*)&(bound_->c_str()[from_]); 270} 271 272BALL_INLINE 273const char* Substring::c_str() const 274{ 275 if (bound_ == 0) 276 { 277 throw UnboundSubstring(__FILE__, __LINE__); 278 } 279 280 return &(bound_->c_str()[from_]); 281} 282 283BALL_INLINE 284Index Substring::getFirstIndex() const 285{ 286 if (bound_ == 0) 287 { 288 throw UnboundSubstring(__FILE__, __LINE__); 289 } 290 291 return from_; 292} 293 294BALL_INLINE 295Index Substring::getLastIndex() const 296{ 297 if (bound_ == 0) 298 { 299 throw UnboundSubstring(__FILE__, __LINE__); 300 } 301 302 return to_; 303} 304 305BALL_INLINE 306char& Substring::operator [] (Index index) 307{ 308 if (bound_ == 0) 309 { 310 throw UnboundSubstring(__FILE__, __LINE__); 311 } 312 313 Size len = String::EndPos; 314 validateRange_(index, len); 315 316 return (*bound_)[from_ + index]; 317} 318 319BALL_INLINE 320char Substring::operator [] (Index index) const 321{ 322 if (bound_ == 0) 323 { 324 throw UnboundSubstring(__FILE__, __LINE__); 325 } 326 327 Size len = String::EndPos; 328 validateRange_(index, len); 329 330 return (*bound_)[from_ + index]; 331} 332 333BALL_INLINE 334bool Substring::isBound() const 335{ 336 return (bound_ != 0); 337} 338 339BALL_INLINE 340bool Substring::isEmpty() const 341{ 342 return (bound_ == 0); 343} 344 345BALL_INLINE 346int String::compare(char c, Index from) const 347{ 348 validateIndex_(from); 349 return (c_str()[from] - c); 350} 351 352 353BALL_INLINE 354bool Substring::operator == (char c) const 355{ 356 if (bound_ == 0) 357 { 358 throw UnboundSubstring(__FILE__, __LINE__); 359 } 360 return (bound_->compare(c, from_, to_ - from_ + 1) == 0); 361} 362 363BALL_INLINE 364bool Substring::operator != (char c) const 365{ 366 if (bound_ == 0) 367 { 368 throw UnboundSubstring(__FILE__, __LINE__); 369 } 370 371 return (bound_->compare(c, from_, to_ - from_ + 1) != 0); 372} 373 374BALL_INLINE 375bool Substring::isValid() const 376{ 377 return (bound_ != 0 && from_ >= 0 && from_ <= to_ && to_ < (Index)bound_->size()) ; 378} 379 380BALL_INLINE 381Substring& Substring::toLower() 382{ 383 if (bound_ == 0) 384 { 385 throw UnboundSubstring(__FILE__, __LINE__); 386 } 387 (*bound_).toLower(from_, to_ - from_); 388 return *this; 389} 390 391BALL_INLINE 392Substring& Substring::toUpper() 393{ 394 if (bound_ == 0) 395 { 396 throw UnboundSubstring(__FILE__, __LINE__); 397 } 398 (*bound_).toUpper(from_, to_ - from_); 399 return *this; 400} 401 402BALL_INLINE 403const String& String::operator = (const String& s) 404{ 405 set(s); 406 return *this; 407} 408 409BALL_INLINE 410const String& String::operator = (const char* char_ptr) 411{ 412 set(char_ptr, 0); 413 return *this; 414} 415 416BALL_INLINE 417 418#ifdef BALL_HAS_SSTREAM 419const String& String::operator = (std::stringstream& s) 420#else 421const String& String::operator = (std::strstream& s) 422#endif 423{ 424 set(s); 425 return *this; 426} 427 428#define BALL_STRING_DEFINE_ASSIGNMENT_METHOD(Type) \ 429BALL_INLINE \ 430const String& String::operator = (Type t) \ 431{ \ 432 set(t); \ 433\ 434 return *this; \ 435} 436 437BALL_STRING_DEFINE_ASSIGNMENT_METHOD(char) 438BALL_STRING_DEFINE_ASSIGNMENT_METHOD(unsigned char) 439BALL_STRING_DEFINE_ASSIGNMENT_METHOD(short) 440BALL_STRING_DEFINE_ASSIGNMENT_METHOD(unsigned short) 441BALL_STRING_DEFINE_ASSIGNMENT_METHOD(int) 442BALL_STRING_DEFINE_ASSIGNMENT_METHOD(unsigned int) 443BALL_STRING_DEFINE_ASSIGNMENT_METHOD(long) 444BALL_STRING_DEFINE_ASSIGNMENT_METHOD(unsigned long) 445#ifdef BALL_ALLOW_LONG64_TYPE_OVERLOADS 446BALL_STRING_DEFINE_ASSIGNMENT_METHOD(LongIndex) 447BALL_STRING_DEFINE_ASSIGNMENT_METHOD(LongSize) 448#endif 449BALL_STRING_DEFINE_ASSIGNMENT_METHOD(float) 450BALL_STRING_DEFINE_ASSIGNMENT_METHOD(double) 451#undef BALL_STRING_DEFINE_ASSIGNMENT_METHOD 452 453BALL_INLINE 454void String::setCompareMode(CompareMode mode) 455{ 456 compare_mode_ = mode; 457} 458 459BALL_INLINE 460String::CompareMode String::getCompareMode() 461{ 462 return compare_mode_; 463} 464 465BALL_INLINE 466char String::toChar() const 467{ 468 return *c_str(); 469} 470 471BALL_INLINE 472unsigned char String::toUnsignedChar() const 473{ 474 return (unsigned char)*c_str(); 475} 476 477BALL_INLINE 478Substring String::getSubstring(Index from, Size len) const 479{ 480 validateRange_(from, len); 481 return Substring(*this, from, len); 482} 483 484BALL_INLINE 485Substring String::operator () (Index from, Size len) const 486{ 487 return getSubstring(from, len); 488} 489 490BALL_INLINE 491String& String::trim(const char* trimmed) 492{ 493 return trimRight(trimmed).trimLeft(trimmed); 494} 495 496BALL_INLINE 497String String::trim(const char* trimmed) const 498{ 499 String tmp(*this); 500 tmp.trimRight(trimmed); 501 tmp.trimLeft(trimmed); 502 return tmp; 503} 504 505BALL_INLINE 506String& String::truncate(Size max_size) 507{ 508 if (max_size < (Size) size()) 509 { 510 resize(max_size); 511 } 512 513 return *this; 514} 515 516BALL_INLINE 517Substring String::left(Size len) const 518{ 519 if (len > (Size)size()) 520 { 521 len = (Size)size(); 522 } 523 524 return Substring(*this, 0, len); 525} 526 527BALL_INLINE 528Substring String::instr(const String& patterns, Index from) const 529{ 530 string::size_type found = find(patterns, from); 531 532 return (found == string::npos) 533 ? Substring(*this, 0, 0) 534 : Substring(*this, (Index)found, (Size)patterns.size()); 535} 536 537BALL_INLINE 538String operator + (const String& s1, const string& s2) 539{ 540 String result(s1); 541 result.append(s2); 542 return result; 543} 544 545BALL_INLINE 546String operator + (const string& s1, const String& s2) 547{ 548 String result(s1); 549 result.append(s2); 550 return result; 551} 552 553BALL_INLINE 554String operator + (const String& s1, const String& s2) 555{ 556 String result(s1); 557 result.append(s2); 558 return result; 559} 560 561BALL_INLINE 562String operator +(const String& s1, const char* char_ptr) 563{ 564 String result(s1); 565 result.append(char_ptr); 566 return result; 567} 568 569BALL_INLINE 570String operator + (const String& s1, char c) 571{ 572 String result(s1); 573 result.append(1, c); 574 return result; 575} 576 577#ifdef BALL_STD_STRING_HAS_RVALUE_REFERENCES 578/// Concatenates two strings 579BALL_INLINE 580String operator + (String&& s1, const string& s2) 581{ 582 s1.append(s2); 583 return std::move(s1); 584} 585 586BALL_INLINE 587String operator + (String&& s1, const String& s2) 588{ 589 s1.append(s2); 590 return std::move(s1); 591} 592 593BALL_INLINE 594String operator + (String&& s1, String&& s2) 595{ 596 s1.append(s2); 597 return std::move(s1); 598} 599 600BALL_INLINE 601String operator + (const String& s1, string&& s2) 602{ 603 return std::move(std::operator+(s1, std::move(s2))); 604} 605 606BALL_INLINE 607String operator + (const String& s1, String&& s2) 608{ 609 return std::move(std::operator+(s1, std::move(s2))); 610} 611 612BALL_INLINE 613String operator + (string&& s1, const String& s2) 614{ 615 s1.append(s2); 616 return std::move(s1); 617} 618 619BALL_INLINE 620String operator + (const string& s1, String&& s2) 621{ 622 return std::move(std::operator+(s1, std::move(s2))); 623} 624 625/// Concatenates a string and a C type string 626BALL_INLINE 627String operator + (String&& s1, const char* char_ptr) 628{ 629 s1 += char_ptr; 630 return std::move(s1); 631} 632 633/// Concatenates a C type string and a string 634BALL_INLINE 635String operator + (const char* char_ptr, String&& s) 636{ 637 return std::move(std::operator+(char_ptr,std::move(s))); 638} 639 640/// Concatenates a string and a character 641BALL_INLINE 642String operator + (String&& s, char c) 643{ 644 s += c; 645 return std::move(s); 646} 647 648/// Concatenates a character and a string 649BALL_INLINE 650String operator + (char c, String&& s) 651{ 652 return std::move(std::operator+(c, std::move(s))); 653} 654 655#endif 656 657BALL_INLINE 658void String::destroy() 659{ 660 assign(""); 661} 662 663BALL_INLINE 664void String::clear() 665{ 666 assign(""); 667} 668 669BALL_INLINE 670bool String::has(char c) const 671{ 672 return ((c != (char)0) && (find(c, 0) != string::npos)); 673} 674 675BALL_INLINE 676bool String::hasSubstring(const String& s, Index from) const 677{ 678 if (s.size() == 0) 679 { 680 return true; 681 } 682 683 return (find(s, from) != string::npos); 684} 685 686BALL_INLINE 687bool String::isEmpty() const 688{ 689 return (size() == 0); 690} 691 692BALL_INLINE 693bool String::isAlpha(char c) 694{ 695 return ((c != 0) && ((char*)strchr(CHARACTER_CLASS__ASCII_ALPHA, c) != 0)); 696} 697 698BALL_INLINE 699bool String::isAlnum(char c) 700{ 701 return ((c != 0) && ((char*)strchr(CHARACTER_CLASS__ASCII_ALPHANUMERIC, c) != 0)); 702} 703 704BALL_INLINE 705bool String::isDigit(char c) 706{ 707 return ((c != 0) && ((char*)strchr(CHARACTER_CLASS__ASCII_NUMERIC, c) != 0)); 708} 709 710BALL_INLINE 711bool String::isFloat() const 712{ 713 char* test; 714 char* str = const_cast<char*>(c_str()); 715 errno = 0; 716 717//Get rid of those friggin warnings 718#if defined BALL_COMPILER_GXX && ((BALL_COMPILER_VERSION_MAJOR == 4 && BALL_COMPILER_VERSION_MINOR < 6) || BALL_COMPILER_VERSION_MAJOR < 4) 719 double d = 0; 720 d = strtod(str, &test); 721#else 722 strtod(str, &test); 723#endif 724 return (errno == 0 && *test == '\0'); 725} 726 727BALL_INLINE 728bool String::isSpace(char c) 729{ 730 return (c == ' '); 731} 732 733BALL_INLINE 734bool String::isWhitespace(char c) 735{ 736 return ((c != 0) && ((char*)strchr(CHARACTER_CLASS__WHITESPACE, c) != 0)); 737} 738 739BALL_INLINE 740bool String::operator != (const String& s) const 741{ 742 return (compare(s) != 0); 743} 744 745BALL_INLINE 746bool String::operator < (const String& s) const 747{ 748 return (compare(s) < 0); 749} 750 751BALL_INLINE 752bool String::operator <= (const String& s) const 753{ 754 return (compare(s) <= 0); 755} 756 757BALL_INLINE 758bool String::operator >= (const String& s) const 759{ 760 return (compare(s) >= 0); 761} 762 763BALL_INLINE 764bool String::operator > (const String& s) const 765{ 766 return (compare(s) > 0); 767} 768 769BALL_INLINE 770bool String::operator == (const String& string) const 771{ 772 return (compare(string.c_str()) == 0); 773} 774 775BALL_INLINE 776bool String::operator < (const char* char_ptr) const 777{ 778 return (compare(char_ptr) < 0); 779} 780 781BALL_INLINE 782bool String::operator <= (const char* char_ptr) const 783{ 784 return (compare(char_ptr) <= 0); 785} 786 787BALL_INLINE 788bool String::operator >= (const char* char_ptr) const 789{ 790 return (compare(char_ptr) >= 0); 791} 792 793BALL_INLINE 794bool String::operator > (const char* char_ptr) const 795{ 796 return (compare(char_ptr) > 0); 797} 798 799BALL_INLINE 800bool String::operator == (char c) const 801{ 802 return (compare(c) == 0); 803} 804 805BALL_INLINE 806bool String::operator != (char c) const 807{ 808 return (compare(c) != 0); 809} 810 811BALL_INLINE 812bool String::operator < (char c) const 813{ 814 return (compare(c) < 0); 815} 816 817BALL_INLINE 818bool String::operator <= (char c) const 819{ 820 return (compare(c) <= 0); 821} 822 823BALL_INLINE 824bool String::operator >= (char c) const 825{ 826 return (compare(c) >= 0); 827} 828 829BALL_INLINE 830bool String::operator > (char c) const 831{ 832 return (compare(c) > 0); 833} 834 835BALL_INLINE 836bool String::isValid() const 837{ 838 return (c_str() != 0 && size() <= capacity()); 839} 840 841BALL_INLINE 842std::istream& String::getline(std::istream& s, char delimiter) 843{ 844 static vector<char> line_buffer(8192); 845 s.getline(&(line_buffer[0]), 8191, delimiter); 846 set(&(line_buffer[0])); 847 848 return s; 849} 850 851BALL_INLINE 852bool operator != (const String& s, const Substring& substring) 853{ 854 return (substring != s); 855} 856 857BALL_INLINE 858bool operator == (const String& s, const Substring& substring) 859{ 860 return (substring == s); 861} 862 863BALL_INLINE 864void String::swap(String& s) 865{ 866 string::swap(s); 867} 868 869BALL_INLINE 870bool operator == (const char* char_ptr, const String &s) 871{ 872 return (s.compare(char_ptr) == 0); 873} 874 875BALL_INLINE 876bool operator != (const char* char_ptr, const String &s) 877{ 878 return (s.compare(char_ptr) != 0); 879} 880 881BALL_INLINE 882bool operator < (const char* char_ptr, const String& s) 883{ 884 return (s.compare(char_ptr) > 0); 885} 886 887BALL_INLINE 888bool operator <= (const char* char_ptr, const String &s) 889{ 890 return (s.compare(char_ptr) >= 0); 891} 892 893BALL_INLINE 894bool operator >= (const char* char_ptr, const String& s) 895{ 896 return (s.compare(char_ptr) <= 0); 897} 898 899BALL_INLINE 900bool operator > (const char* char_ptr, const String& s) 901{ 902 return (s.compare(char_ptr) < 0); 903} 904 905BALL_INLINE 906bool operator == (char c, const String& s) 907{ 908 return (s.compare(c) == 0); 909} 910 911BALL_INLINE 912bool operator != (char c, const String &s) 913{ 914 return (s.compare(c) != 0); 915} 916 917BALL_INLINE 918bool operator < (char c, const String& s) 919{ 920 return (s.compare(c) > 0); 921} 922 923BALL_INLINE 924bool operator <= (char c, const String &s) 925{ 926 return (s.compare(c) >= 0); 927} 928 929BALL_INLINE 930bool operator >= (char c, const String &s) 931{ 932 return (s.compare(c) <= 0); 933} 934 935BALL_INLINE 936bool operator > (char c, const String &s) 937{ 938 return (s.compare(c) < 0); 939} 940