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
Length()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
IsEmpty()458 BString::IsEmpty() const
459 {
460 return !Length();
461 }
462
463
464 inline const char*
String()465 BString::String() const
466 {
467 if (!fPrivateData)
468 return "";
469 return fPrivateData;
470 }
471
472
473 inline uint32
HashValue()474 BString::HashValue() const
475 {
476 return HashValue(String());
477 }
478
479
480 inline BString&
SetTo(const char * string)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
ByteAt(int32 index)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&
Append(const BString & string)512 BString::Append(const BString& string)
513 {
514 _DoAppend(string.String(), string.Length());
515 return *this;
516 }
517
518
519 inline BString&
Append(const char * string)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