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