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