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
15class BStringList;
16class BStringRef;
17
18
19class BString {
20public:
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
363public:
364			class Private;
365			friend class Private;
366
367private:
368			class PosVect;
369			friend class BStringRef;
370
371			enum PrivateDataTag {
372				PRIVATE_DATA
373			};
374
375private:
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
421private:
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
433bool operator<(const char* a, const BString& b);
434bool operator<=(const char* a, const BString& b);
435bool operator==(const char* a, const BString& b);
436bool operator>(const char* a, const BString& b);
437bool operator>=(const char* a, const BString& b);
438bool operator!=(const char* a, const BString& b);
439
440
441// Non-member compare for sorting, etc.
442int Compare(const BString& a, const BString& b);
443int ICompare(const BString& a, const BString& b);
444int Compare(const BString* a, const BString* b);
445int ICompare(const BString* a, const BString* b);
446
447
448inline int32
449BString::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
457inline bool
458BString::IsEmpty() const
459{
460	return !Length();
461}
462
463
464inline const char*
465BString::String() const
466{
467	if (!fPrivateData)
468		return "";
469	return fPrivateData;
470}
471
472
473inline uint32
474BString::HashValue() const
475{
476	return HashValue(String());
477}
478
479
480inline BString&
481BString::SetTo(const char* string)
482{
483	return operator=(string);
484}
485
486
487inline char
488BString::operator[](int32 index) const
489{
490	return fPrivateData[index];
491}
492
493
494inline char
495BString::ByteAt(int32 index) const
496{
497	if (!fPrivateData || index < 0 || index >= Length())
498		return 0;
499	return fPrivateData[index];
500}
501
502
503inline BString&
504BString::operator+=(const BString& string)
505{
506	_DoAppend(string.String(), string.Length());
507	return *this;
508}
509
510
511inline BString&
512BString::Append(const BString& string)
513{
514	_DoAppend(string.String(), string.Length());
515	return *this;
516}
517
518
519inline BString&
520BString::Append(const char* string)
521{
522	return operator+=(string);
523}
524
525
526inline bool
527BString::operator==(const BString& string) const
528{
529	return strcmp(String(), string.String()) == 0;
530}
531
532
533inline bool
534BString::operator<(const BString& string) const
535{
536	return strcmp(String(), string.String()) < 0;
537}
538
539
540inline bool
541BString::operator<=(const BString& string) const
542{
543	return strcmp(String(), string.String()) <= 0;
544}
545
546
547inline bool
548BString::operator>=(const BString& string) const
549{
550	return strcmp(String(), string.String()) >= 0;
551}
552
553
554inline bool
555BString::operator>(const BString& string) const
556{
557	return strcmp(String(), string.String()) > 0;
558}
559
560
561inline bool
562BString::operator!=(const BString& string) const
563{
564	return strcmp(String(), string.String()) != 0;
565}
566
567
568inline bool
569BString::operator!=(const char* string) const
570{
571	return !operator==(string);
572}
573
574
575inline
576BString::operator const char*() const
577{
578	return String();
579}
580
581
582inline bool
583operator<(const char* str, const BString& string)
584{
585	return string > str;
586}
587
588
589inline bool
590operator<=(const char* str, const BString& string)
591{
592	return string >= str;
593}
594
595
596inline bool
597operator==(const char* str, const BString& string)
598{
599	return string == str;
600}
601
602
603inline bool
604operator>(const char* str, const BString& string)
605{
606	return string < str;
607}
608
609
610inline bool
611operator>=(const char* str, const BString& string)
612{
613	return string <= str;
614}
615
616
617inline bool
618operator!=(const char* str, const BString& string)
619{
620	return string != str;
621}
622
623
624#endif	// _B_STRING_H
625