1 /* 2 * Copyright 2001-2010 Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 #ifndef _B_STRING_H 6 #define _B_STRING_H 7 8 9 #include <stdarg.h> 10 #include <string.h> 11 12 #include <SupportDefs.h> 13 14 15 class BStringList; 16 class BStringRef; 17 18 19 class BString { 20 public: 21 BString(); 22 BString(const char* string); 23 BString(const BString& string); 24 BString(const char* string, int32 maxLength); 25 ~BString(); 26 27 // Access 28 const char* String() const; 29 int32 Length() const; 30 int32 CountChars() const; 31 int32 CountBytes(int32 fromCharOffset, 32 int32 charCount) const; 33 bool IsEmpty() const; 34 35 uint32 HashValue() const; 36 static uint32 HashValue(const char* string); 37 38 // Assignment 39 BString& operator=(const BString& string); 40 BString& operator=(const char* string); 41 BString& operator=(char c); 42 43 BString& SetTo(const char* string); 44 BString& SetTo(const char* string, int32 maxLength); 45 46 BString& SetTo(const BString& string); 47 BString& Adopt(BString& from); 48 49 BString& SetTo(const BString& string, int32 maxLength); 50 BString& Adopt(BString& from, int32 maxLength); 51 52 BString& SetTo(char c, int32 count); 53 54 BString& SetToChars(const char* string, int32 charCount); 55 BString& SetToChars(const BString& string, int32 charCount); 56 BString& AdoptChars(BString& from, int32 charCount); 57 58 BString& SetToFormat(const char* format, ...) 59 __attribute__((__format__(__printf__, 2, 3))); 60 BString& SetToFormatVarArgs(const char* format, 61 va_list args) 62 __attribute__((__format__(__printf__, 2, 0))); 63 64 int ScanWithFormat(const char* format, ...) 65 __attribute__((__format__(__scanf__, 2, 3))); 66 int ScanWithFormatVarArgs(const char* format, 67 va_list args) 68 __attribute__((__format__(__scanf__, 2, 0))); 69 70 // Substring copying 71 BString& CopyInto(BString& into, int32 fromOffset, 72 int32 length) const; 73 void CopyInto(char* into, int32 fromOffset, 74 int32 length) const; 75 76 BString& CopyCharsInto(BString& into, int32 fromCharOffset, 77 int32 charCount) const; 78 bool CopyCharsInto(char* into, int32* intoLength, 79 int32 fromCharOffset, int32 charCount) const; 80 81 bool Split(const char* separator, bool noEmptyStrings, 82 BStringList& _list) const; 83 84 // Appending 85 BString& operator+=(const BString& string); 86 BString& operator+=(const char* string); 87 BString& operator+=(char c); 88 89 BString& Append(const BString& string); 90 BString& Append(const char* string); 91 92 BString& Append(const BString& string, int32 length); 93 BString& Append(const char* string, int32 length); 94 BString& Append(char c, int32 count); 95 96 BString& AppendChars(const BString& string, int32 charCount); 97 BString& AppendChars(const char* string, int32 charCount); 98 99 // Prepending 100 BString& Prepend(const char* string); 101 BString& Prepend(const BString& string); 102 BString& Prepend(const char* string, int32 length); 103 BString& Prepend(const BString& string, int32 length); 104 BString& Prepend(char c, int32 count); 105 106 BString& PrependChars(const char* string, int32 charCount); 107 BString& PrependChars(const BString& string, 108 int32 charCount); 109 110 // Inserting 111 BString& Insert(const char* string, int32 position); 112 BString& Insert(const char* string, int32 length, 113 int32 position); 114 BString& Insert(const char* string, int32 fromOffset, 115 int32 length, int32 position); 116 BString& Insert(const BString& string, int32 position); 117 BString& Insert(const BString& string, int32 length, 118 int32 position); 119 BString& Insert(const BString& string, int32 fromOffset, 120 int32 length, int32 position); 121 BString& Insert(char c, int32 count, int32 position); 122 123 BString& InsertChars(const char* string, int32 charPosition); 124 BString& InsertChars(const char* string, int32 charCount, 125 int32 charPosition); 126 BString& InsertChars(const char* string, 127 int32 fromCharOffset, int32 charCount, 128 int32 charPosition); 129 BString& InsertChars(const BString& string, 130 int32 charPosition); 131 BString& InsertChars(const BString& string, int32 charCount, 132 int32 charPosition); 133 BString& InsertChars(const BString& string, 134 int32 fromCharOffset, int32 charCount, 135 int32 charPosition); 136 137 // Removing 138 BString& Truncate(int32 newLength, bool lazy = true); 139 BString& TruncateChars(int32 newCharCount, bool lazy = true); 140 141 BString& Remove(int32 from, int32 length); 142 BString& RemoveChars(int32 fromCharOffset, int32 charCount); 143 144 BString& RemoveFirst(const BString& string); 145 BString& RemoveLast(const BString& string); 146 BString& RemoveAll(const BString& string); 147 148 BString& RemoveFirst(const char* string); 149 BString& RemoveLast(const char* string); 150 BString& RemoveAll(const char* string); 151 152 BString& RemoveSet(const char* setOfBytesToRemove); 153 BString& RemoveCharsSet(const char* setOfCharsToRemove); 154 155 BString& MoveInto(BString& into, int32 from, int32 length); 156 void MoveInto(char* into, int32 from, int32 length); 157 158 BString& MoveCharsInto(BString& into, int32 fromCharOffset, 159 int32 charCount); 160 bool MoveCharsInto(char* into, int32* intoLength, 161 int32 fromCharOffset, int32 charCount); 162 163 // Compare functions 164 bool operator<(const BString& string) const; 165 bool operator<=(const BString& string) const; 166 bool operator==(const BString& string) const; 167 bool operator>=(const BString& string) const; 168 bool operator>(const BString& string) const; 169 bool operator!=(const BString& string) const; 170 171 bool operator<(const char* string) const; 172 bool operator<=(const char* string) const; 173 bool operator==(const char* string) const; 174 bool operator>=(const char* string) const; 175 bool operator>(const char* string) const; 176 bool operator!=(const char* string) const; 177 178 operator const char*() const; 179 180 // strcmp()-style compare functions 181 int Compare(const BString& string) const; 182 int Compare(const char* string) const; 183 int Compare(const BString& string, int32 length) const; 184 int Compare(const char* string, int32 length) const; 185 186 int CompareAt(size_t offset, const BString& string, 187 int32 length) const; 188 189 int CompareChars(const BString& string, 190 int32 charCount) const; 191 int CompareChars(const char* string, 192 int32 charCount) const; 193 194 int ICompare(const BString& string) const; 195 int ICompare(const char* string) const; 196 int ICompare(const BString& string, int32 length) const; 197 int ICompare(const char* string, int32 length) const; 198 199 // Searching 200 int32 FindFirst(const BString& string) const; 201 int32 FindFirst(const char* string) const; 202 int32 FindFirst(const BString& string, 203 int32 fromOffset) const; 204 int32 FindFirst(const char* string, 205 int32 fromOffset) const; 206 int32 FindFirst(char c) const; 207 int32 FindFirst(char c, int32 fromOffset) const; 208 209 int32 FindFirstChars(const BString& string, 210 int32 fromCharOffset) const; 211 int32 FindFirstChars(const char* string, 212 int32 fromCharOffset) const; 213 214 int32 FindLast(const BString& string) const; 215 int32 FindLast(const char* string) const; 216 int32 FindLast(const BString& string, 217 int32 beforeOffset) const; 218 int32 FindLast(const char* string, 219 int32 beforeOffset) const; 220 int32 FindLast(char c) const; 221 int32 FindLast(char c, int32 beforeOffset) const; 222 223 int32 FindLastChars(const BString& string, 224 int32 beforeCharOffset) const; 225 int32 FindLastChars(const char* string, 226 int32 beforeCharOffset) const; 227 228 int32 IFindFirst(const BString& string) const; 229 int32 IFindFirst(const char* string) const; 230 int32 IFindFirst(const BString& string, 231 int32 fromOffset) const; 232 int32 IFindFirst(const char* string, 233 int32 fromOffset) const; 234 235 int32 IFindLast(const BString& string) const; 236 int32 IFindLast(const char* string) const; 237 int32 IFindLast(const BString& string, 238 int32 beforeOffset) const; 239 int32 IFindLast(const char* string, 240 int32 beforeOffset) const; 241 242 bool StartsWith(const BString& string) const; 243 bool StartsWith(const char* string) const; 244 bool StartsWith(const char* string, int32 length) const; 245 246 bool IStartsWith(const BString& string) const; 247 bool IStartsWith(const char* string) const; 248 bool IStartsWith(const char* string, int32 length) const; 249 250 bool EndsWith(const BString& string) const; 251 bool EndsWith(const char* string) const; 252 bool EndsWith(const char* string, int32 length) const; 253 254 bool IEndsWith(const BString& string) const; 255 bool IEndsWith(const char* string) const; 256 bool IEndsWith(const char* string, int32 length) const; 257 258 // Replacing 259 BString& ReplaceFirst(char replaceThis, char withThis); 260 BString& ReplaceLast(char replaceThis, char withThis); 261 BString& ReplaceAll(char replaceThis, char withThis, 262 int32 fromOffset = 0); 263 BString& Replace(char replaceThis, char withThis, 264 int32 maxReplaceCount, int32 fromOffset = 0); 265 BString& ReplaceFirst(const char* replaceThis, 266 const char* withThis); 267 BString& ReplaceLast(const char* replaceThis, 268 const char* withThis); 269 BString& ReplaceAll(const char* replaceThis, 270 const char* withThis, int32 fromOffset = 0); 271 BString& Replace(const char* replaceThis, 272 const char* withThis, int32 maxReplaceCount, 273 int32 fromOffset = 0); 274 275 BString& ReplaceAllChars(const char* replaceThis, 276 const char* withThis, int32 fromCharOffset); 277 BString& ReplaceChars(const char* replaceThis, 278 const char* withThis, int32 maxReplaceCount, 279 int32 fromCharOffset); 280 281 BString& IReplaceFirst(char replaceThis, char withThis); 282 BString& IReplaceLast(char replaceThis, char withThis); 283 BString& IReplaceAll(char replaceThis, char withThis, 284 int32 fromOffset = 0); 285 BString& IReplace(char replaceThis, char withThis, 286 int32 maxReplaceCount, int32 fromOffset = 0); 287 BString& IReplaceFirst(const char* replaceThis, 288 const char* withThis); 289 BString& IReplaceLast(const char* replaceThis, 290 const char* withThis); 291 BString& IReplaceAll(const char* replaceThis, 292 const char* withThis, int32 fromOffset = 0); 293 BString& IReplace(const char* replaceThis, 294 const char* withThis, int32 maxReplaceCount, 295 int32 fromOffset = 0); 296 297 BString& ReplaceSet(const char* setOfBytes, char with); 298 BString& ReplaceSet(const char* setOfBytes, 299 const char* with); 300 301 BString& ReplaceCharsSet(const char* setOfChars, 302 const char* with); 303 304 // Unchecked char access 305 char operator[](int32 index) const; 306 307 #if __GNUC__ == 2 308 char& operator[](int32 index); 309 #endif 310 311 // Checked char access 312 char ByteAt(int32 index) const; 313 const char* CharAt(int32 charIndex, int32* bytes = NULL) const; 314 bool CharAt(int32 charIndex, char* buffer, 315 int32* bytes) const; 316 317 // Fast low-level manipulation 318 char* LockBuffer(int32 maxLength); 319 BString& UnlockBuffer(int32 length = -1); 320 BString& SetByteAt(int32 pos, char to); 321 322 // Upercase <-> Lowercase 323 BString& ToLower(); 324 BString& ToUpper(); 325 326 BString& Capitalize(); 327 BString& CapitalizeEachWord(); 328 329 // Escaping and De-escaping 330 BString& CharacterEscape(const char* original, 331 const char* setOfCharsToEscape, 332 char escapeWith); 333 BString& CharacterEscape(const char* setOfCharsToEscape, 334 char escapeWith); 335 BString& CharacterDeescape(const char* original, 336 char escapeChar); 337 BString& CharacterDeescape(char escapeChar); 338 339 // Trimming 340 BString& Trim(); 341 342 // Insert 343 BString& operator<<(const char* string); 344 BString& operator<<(const BString& string); 345 BString& operator<<(char c); 346 BString& operator<<(bool value); 347 BString& operator<<(int value); 348 BString& operator<<(unsigned int value); 349 BString& operator<<(unsigned long value); 350 BString& operator<<(long value); 351 BString& operator<<(unsigned long long value); 352 BString& operator<<(long long value); 353 // float/double output hardcodes %.2f style formatting 354 BString& operator<<(float value); 355 BString& operator<<(double value); 356 357 public: 358 class Private; 359 friend class Private; 360 361 private: 362 class PosVect; 363 friend class BStringRef; 364 365 enum PrivateDataTag { 366 PRIVATE_DATA 367 }; 368 369 private: 370 BString(char* privateData, PrivateDataTag tag); 371 372 // Management 373 status_t _MakeWritable(); 374 status_t _MakeWritable(int32 length, bool copy); 375 static char* _Allocate(int32 length); 376 char* _Resize(int32 length); 377 void _Init(const char* src, int32 length); 378 char* _Clone(const char* data, int32 length); 379 char* _OpenAtBy(int32 offset, int32 length); 380 char* _ShrinkAtBy(int32 offset, int32 length); 381 382 // Data 383 void _SetLength(int32 length); 384 bool _DoAppend(const char* string, int32 length); 385 bool _DoPrepend(const char* string, int32 length); 386 bool _DoInsert(const char* string, int32 offset, 387 int32 length); 388 389 // Search 390 int32 _ShortFindAfter(const char* string, 391 int32 length) const; 392 int32 _FindAfter(const char* string, int32 offset, 393 int32 length) const; 394 int32 _IFindAfter(const char* string, int32 offset, 395 int32 length) const; 396 int32 _FindBefore(const char* string, int32 offset, 397 int32 length) const; 398 int32 _IFindBefore(const char* string, int32 offset, 399 int32 length) const; 400 401 // Escape 402 BString& _DoCharacterEscape(const char* string, 403 const char* setOfCharsToEscape, char escapeChar); 404 BString& _DoCharacterDeescape(const char* string, 405 char escapeChar); 406 407 // Replace 408 BString& _DoReplace(const char* findThis, 409 const char* replaceWith, int32 maxReplaceCount, 410 int32 fromOffset, bool ignoreCase); 411 void _ReplaceAtPositions(const PosVect* positions, 412 int32 searchLength, const char* with, 413 int32 withLength); 414 415 private: 416 int32& _ReferenceCount(); 417 const int32& _ReferenceCount() const; 418 bool _IsShareable() const; 419 void _FreePrivateData(); 420 421 char* fPrivateData; 422 }; 423 424 425 // Commutative compare operators 426 bool operator<(const char* a, const BString& b); 427 bool operator<=(const char* a, const BString& b); 428 bool operator==(const char* a, const BString& b); 429 bool operator>(const char* a, const BString& b); 430 bool operator>=(const char* a, const BString& b); 431 bool operator!=(const char* a, const BString& b); 432 433 434 // Non-member compare for sorting, etc. 435 int Compare(const BString& a, const BString& b); 436 int ICompare(const BString& a, const BString& b); 437 int Compare(const BString* a, const BString* b); 438 int ICompare(const BString* a, const BString* b); 439 440 441 inline int32 442 BString::Length() const 443 { 444 // the most significant bit is reserved; accessing 445 // it in any way will cause the computer to explode 446 return fPrivateData ? (*(((int32*)fPrivateData) - 1) & 0x7fffffff) : 0; 447 } 448 449 450 inline bool 451 BString::IsEmpty() const 452 { 453 return !Length(); 454 } 455 456 457 inline const char* 458 BString::String() const 459 { 460 if (!fPrivateData) 461 return ""; 462 return fPrivateData; 463 } 464 465 466 inline uint32 467 BString::HashValue() const 468 { 469 return HashValue(String()); 470 } 471 472 473 inline BString& 474 BString::SetTo(const char* string) 475 { 476 return operator=(string); 477 } 478 479 480 inline char 481 BString::operator[](int32 index) const 482 { 483 return fPrivateData[index]; 484 } 485 486 487 inline char 488 BString::ByteAt(int32 index) const 489 { 490 if (!fPrivateData || index < 0 || index >= Length()) 491 return 0; 492 return fPrivateData[index]; 493 } 494 495 496 inline BString& 497 BString::operator+=(const BString& string) 498 { 499 _DoAppend(string.String(), string.Length()); 500 return *this; 501 } 502 503 504 inline BString& 505 BString::Append(const BString& string) 506 { 507 _DoAppend(string.String(), string.Length()); 508 return *this; 509 } 510 511 512 inline BString& 513 BString::Append(const char* string) 514 { 515 return operator+=(string); 516 } 517 518 519 inline bool 520 BString::operator==(const BString& string) const 521 { 522 return strcmp(String(), string.String()) == 0; 523 } 524 525 526 inline bool 527 BString::operator<(const BString& string) const 528 { 529 return strcmp(String(), string.String()) < 0; 530 } 531 532 533 inline bool 534 BString::operator<=(const BString& string) const 535 { 536 return strcmp(String(), string.String()) <= 0; 537 } 538 539 540 inline bool 541 BString::operator>=(const BString& string) const 542 { 543 return strcmp(String(), string.String()) >= 0; 544 } 545 546 547 inline bool 548 BString::operator>(const BString& string) const 549 { 550 return strcmp(String(), string.String()) > 0; 551 } 552 553 554 inline bool 555 BString::operator!=(const BString& string) const 556 { 557 return strcmp(String(), string.String()) != 0; 558 } 559 560 561 inline bool 562 BString::operator!=(const char* string) const 563 { 564 return !operator==(string); 565 } 566 567 568 inline 569 BString::operator const char*() const 570 { 571 return String(); 572 } 573 574 575 inline bool 576 operator<(const char* str, const BString& string) 577 { 578 return string > str; 579 } 580 581 582 inline bool 583 operator<=(const char* str, const BString& string) 584 { 585 return string >= str; 586 } 587 588 589 inline bool 590 operator==(const char* str, const BString& string) 591 { 592 return string == str; 593 } 594 595 596 inline bool 597 operator>(const char* str, const BString& string) 598 { 599 return string < str; 600 } 601 602 603 inline bool 604 operator>=(const char* str, const BString& string) 605 { 606 return string <= str; 607 } 608 609 610 inline bool 611 operator!=(const char* str, const BString& string) 612 { 613 return string != str; 614 } 615 616 617 #endif // _B_STRING_H 618