530f89aa6d
This removes the use of the destructor in the move assignment operator, as it may rely on undefined behaviour from the compiler. Additionally, some duplicate logic to dereference and free a shared string has been unified under _ReleasePrivateData(). Change-Id: Ie9f51d598c734f83cd0fba49b651315c6e9c8aac Reviewed-on: https://review.haiku-os.org/c/haiku/+/4440 Reviewed-by: waddlesplash <waddlesplash@gmail.com> Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org>
625 lines
17 KiB
C++
625 lines
17 KiB
C++
/*
|
|
* Copyright 2001-2010 Haiku, Inc. All rights reserved.
|
|
* Distributed under the terms of the MIT License.
|
|
*/
|
|
#ifndef _B_STRING_H
|
|
#define _B_STRING_H
|
|
|
|
|
|
#include <stdarg.h>
|
|
#include <string.h>
|
|
|
|
#include <SupportDefs.h>
|
|
|
|
|
|
class BStringList;
|
|
class BStringRef;
|
|
|
|
|
|
class BString {
|
|
public:
|
|
BString();
|
|
BString(const char* string);
|
|
BString(const BString& string);
|
|
BString(const char* string, int32 maxLength);
|
|
#if __cplusplus >= 201103L
|
|
BString(BString&& string);
|
|
#endif
|
|
~BString();
|
|
|
|
// Access
|
|
const char* String() const;
|
|
int32 Length() const;
|
|
int32 CountChars() const;
|
|
int32 CountBytes(int32 fromCharOffset,
|
|
int32 charCount) const;
|
|
bool IsEmpty() const;
|
|
|
|
uint32 HashValue() const;
|
|
static uint32 HashValue(const char* string);
|
|
|
|
// Assignment
|
|
BString& operator=(const BString& string);
|
|
BString& operator=(const char* string);
|
|
BString& operator=(char c);
|
|
#if __cplusplus >= 201103L
|
|
BString& operator=(BString&& string);
|
|
#endif
|
|
|
|
BString& SetTo(const char* string);
|
|
BString& SetTo(const char* string, int32 maxLength);
|
|
|
|
BString& SetTo(const BString& string);
|
|
BString& Adopt(BString& from);
|
|
|
|
BString& SetTo(const BString& string, int32 maxLength);
|
|
BString& Adopt(BString& from, int32 maxLength);
|
|
|
|
BString& SetTo(char c, int32 count);
|
|
|
|
BString& SetToChars(const char* string, int32 charCount);
|
|
BString& SetToChars(const BString& string, int32 charCount);
|
|
BString& AdoptChars(BString& from, int32 charCount);
|
|
|
|
BString& SetToFormat(const char* format, ...)
|
|
__attribute__((__format__(__printf__, 2, 3)));
|
|
BString& SetToFormatVarArgs(const char* format,
|
|
va_list args)
|
|
__attribute__((__format__(__printf__, 2, 0)));
|
|
|
|
int ScanWithFormat(const char* format, ...)
|
|
__attribute__((__format__(__scanf__, 2, 3)));
|
|
int ScanWithFormatVarArgs(const char* format,
|
|
va_list args)
|
|
__attribute__((__format__(__scanf__, 2, 0)));
|
|
|
|
// Substring copying
|
|
BString& CopyInto(BString& into, int32 fromOffset,
|
|
int32 length) const;
|
|
void CopyInto(char* into, int32 fromOffset,
|
|
int32 length) const;
|
|
|
|
BString& CopyCharsInto(BString& into, int32 fromCharOffset,
|
|
int32 charCount) const;
|
|
bool CopyCharsInto(char* into, int32* intoLength,
|
|
int32 fromCharOffset, int32 charCount) const;
|
|
|
|
bool Split(const char* separator, bool noEmptyStrings,
|
|
BStringList& _list) const;
|
|
|
|
// Appending
|
|
BString& operator+=(const BString& string);
|
|
BString& operator+=(const char* string);
|
|
BString& operator+=(char c);
|
|
|
|
BString& Append(const BString& string);
|
|
BString& Append(const char* string);
|
|
|
|
BString& Append(const BString& string, int32 length);
|
|
BString& Append(const char* string, int32 length);
|
|
BString& Append(char c, int32 count);
|
|
|
|
BString& AppendChars(const BString& string, int32 charCount);
|
|
BString& AppendChars(const char* string, int32 charCount);
|
|
|
|
// Prepending
|
|
BString& Prepend(const char* string);
|
|
BString& Prepend(const BString& string);
|
|
BString& Prepend(const char* string, int32 length);
|
|
BString& Prepend(const BString& string, int32 length);
|
|
BString& Prepend(char c, int32 count);
|
|
|
|
BString& PrependChars(const char* string, int32 charCount);
|
|
BString& PrependChars(const BString& string,
|
|
int32 charCount);
|
|
|
|
// Inserting
|
|
BString& Insert(const char* string, int32 position);
|
|
BString& Insert(const char* string, int32 length,
|
|
int32 position);
|
|
BString& Insert(const char* string, int32 fromOffset,
|
|
int32 length, int32 position);
|
|
BString& Insert(const BString& string, int32 position);
|
|
BString& Insert(const BString& string, int32 length,
|
|
int32 position);
|
|
BString& Insert(const BString& string, int32 fromOffset,
|
|
int32 length, int32 position);
|
|
BString& Insert(char c, int32 count, int32 position);
|
|
|
|
BString& InsertChars(const char* string, int32 charPosition);
|
|
BString& InsertChars(const char* string, int32 charCount,
|
|
int32 charPosition);
|
|
BString& InsertChars(const char* string,
|
|
int32 fromCharOffset, int32 charCount,
|
|
int32 charPosition);
|
|
BString& InsertChars(const BString& string,
|
|
int32 charPosition);
|
|
BString& InsertChars(const BString& string, int32 charCount,
|
|
int32 charPosition);
|
|
BString& InsertChars(const BString& string,
|
|
int32 fromCharOffset, int32 charCount,
|
|
int32 charPosition);
|
|
|
|
// Removing
|
|
BString& Truncate(int32 newLength, bool lazy = true);
|
|
BString& TruncateChars(int32 newCharCount, bool lazy = true);
|
|
|
|
BString& Remove(int32 from, int32 length);
|
|
BString& RemoveChars(int32 fromCharOffset, int32 charCount);
|
|
|
|
BString& RemoveFirst(const BString& string);
|
|
BString& RemoveLast(const BString& string);
|
|
BString& RemoveAll(const BString& string);
|
|
|
|
BString& RemoveFirst(const char* string);
|
|
BString& RemoveLast(const char* string);
|
|
BString& RemoveAll(const char* string);
|
|
|
|
BString& RemoveSet(const char* setOfBytesToRemove);
|
|
BString& RemoveCharsSet(const char* setOfCharsToRemove);
|
|
|
|
BString& MoveInto(BString& into, int32 from, int32 length);
|
|
void MoveInto(char* into, int32 from, int32 length);
|
|
|
|
BString& MoveCharsInto(BString& into, int32 fromCharOffset,
|
|
int32 charCount);
|
|
bool MoveCharsInto(char* into, int32* intoLength,
|
|
int32 fromCharOffset, int32 charCount);
|
|
|
|
// Compare functions
|
|
bool operator<(const BString& string) const;
|
|
bool operator<=(const BString& string) const;
|
|
bool operator==(const BString& string) const;
|
|
bool operator>=(const BString& string) const;
|
|
bool operator>(const BString& string) const;
|
|
bool operator!=(const BString& string) const;
|
|
|
|
bool operator<(const char* string) const;
|
|
bool operator<=(const char* string) const;
|
|
bool operator==(const char* string) const;
|
|
bool operator>=(const char* string) const;
|
|
bool operator>(const char* string) const;
|
|
bool operator!=(const char* string) const;
|
|
|
|
operator const char*() const;
|
|
|
|
// strcmp()-style compare functions
|
|
int Compare(const BString& string) const;
|
|
int Compare(const char* string) const;
|
|
int Compare(const BString& string, int32 length) const;
|
|
int Compare(const char* string, int32 length) const;
|
|
|
|
int CompareAt(size_t offset, const BString& string,
|
|
int32 length) const;
|
|
|
|
int CompareChars(const BString& string,
|
|
int32 charCount) const;
|
|
int CompareChars(const char* string,
|
|
int32 charCount) const;
|
|
|
|
int ICompare(const BString& string) const;
|
|
int ICompare(const char* string) const;
|
|
int ICompare(const BString& string, int32 length) const;
|
|
int ICompare(const char* string, int32 length) const;
|
|
|
|
// Searching
|
|
int32 FindFirst(const BString& string) const;
|
|
int32 FindFirst(const char* string) const;
|
|
int32 FindFirst(const BString& string,
|
|
int32 fromOffset) const;
|
|
int32 FindFirst(const char* string,
|
|
int32 fromOffset) const;
|
|
int32 FindFirst(char c) const;
|
|
int32 FindFirst(char c, int32 fromOffset) const;
|
|
|
|
int32 FindFirstChars(const BString& string,
|
|
int32 fromCharOffset) const;
|
|
int32 FindFirstChars(const char* string,
|
|
int32 fromCharOffset) const;
|
|
|
|
int32 FindLast(const BString& string) const;
|
|
int32 FindLast(const char* string) const;
|
|
int32 FindLast(const BString& string,
|
|
int32 beforeOffset) const;
|
|
int32 FindLast(const char* string,
|
|
int32 beforeOffset) const;
|
|
int32 FindLast(char c) const;
|
|
int32 FindLast(char c, int32 beforeOffset) const;
|
|
|
|
int32 FindLastChars(const BString& string,
|
|
int32 beforeCharOffset) const;
|
|
int32 FindLastChars(const char* string,
|
|
int32 beforeCharOffset) const;
|
|
|
|
int32 IFindFirst(const BString& string) const;
|
|
int32 IFindFirst(const char* string) const;
|
|
int32 IFindFirst(const BString& string,
|
|
int32 fromOffset) const;
|
|
int32 IFindFirst(const char* string,
|
|
int32 fromOffset) const;
|
|
|
|
int32 IFindLast(const BString& string) const;
|
|
int32 IFindLast(const char* string) const;
|
|
int32 IFindLast(const BString& string,
|
|
int32 beforeOffset) const;
|
|
int32 IFindLast(const char* string,
|
|
int32 beforeOffset) const;
|
|
|
|
bool StartsWith(const BString& string) const;
|
|
bool StartsWith(const char* string) const;
|
|
bool StartsWith(const char* string, int32 length) const;
|
|
|
|
bool IStartsWith(const BString& string) const;
|
|
bool IStartsWith(const char* string) const;
|
|
bool IStartsWith(const char* string, int32 length) const;
|
|
|
|
bool EndsWith(const BString& string) const;
|
|
bool EndsWith(const char* string) const;
|
|
bool EndsWith(const char* string, int32 length) const;
|
|
|
|
bool IEndsWith(const BString& string) const;
|
|
bool IEndsWith(const char* string) const;
|
|
bool IEndsWith(const char* string, int32 length) const;
|
|
|
|
// Replacing
|
|
BString& ReplaceFirst(char replaceThis, char withThis);
|
|
BString& ReplaceLast(char replaceThis, char withThis);
|
|
BString& ReplaceAll(char replaceThis, char withThis,
|
|
int32 fromOffset = 0);
|
|
BString& Replace(char replaceThis, char withThis,
|
|
int32 maxReplaceCount, int32 fromOffset = 0);
|
|
BString& ReplaceFirst(const char* replaceThis,
|
|
const char* withThis);
|
|
BString& ReplaceLast(const char* replaceThis,
|
|
const char* withThis);
|
|
BString& ReplaceAll(const char* replaceThis,
|
|
const char* withThis, int32 fromOffset = 0);
|
|
BString& Replace(const char* replaceThis,
|
|
const char* withThis, int32 maxReplaceCount,
|
|
int32 fromOffset = 0);
|
|
|
|
BString& ReplaceAllChars(const char* replaceThis,
|
|
const char* withThis, int32 fromCharOffset);
|
|
BString& ReplaceChars(const char* replaceThis,
|
|
const char* withThis, int32 maxReplaceCount,
|
|
int32 fromCharOffset);
|
|
|
|
BString& IReplaceFirst(char replaceThis, char withThis);
|
|
BString& IReplaceLast(char replaceThis, char withThis);
|
|
BString& IReplaceAll(char replaceThis, char withThis,
|
|
int32 fromOffset = 0);
|
|
BString& IReplace(char replaceThis, char withThis,
|
|
int32 maxReplaceCount, int32 fromOffset = 0);
|
|
BString& IReplaceFirst(const char* replaceThis,
|
|
const char* withThis);
|
|
BString& IReplaceLast(const char* replaceThis,
|
|
const char* withThis);
|
|
BString& IReplaceAll(const char* replaceThis,
|
|
const char* withThis, int32 fromOffset = 0);
|
|
BString& IReplace(const char* replaceThis,
|
|
const char* withThis, int32 maxReplaceCount,
|
|
int32 fromOffset = 0);
|
|
|
|
BString& ReplaceSet(const char* setOfBytes, char with);
|
|
BString& ReplaceSet(const char* setOfBytes,
|
|
const char* with);
|
|
|
|
BString& ReplaceCharsSet(const char* setOfChars,
|
|
const char* with);
|
|
|
|
// Unchecked char access
|
|
char operator[](int32 index) const;
|
|
|
|
#if __GNUC__ == 2
|
|
char& operator[](int32 index);
|
|
#endif
|
|
|
|
// Checked char access
|
|
char ByteAt(int32 index) const;
|
|
const char* CharAt(int32 charIndex, int32* bytes = NULL) const;
|
|
bool CharAt(int32 charIndex, char* buffer,
|
|
int32* bytes) const;
|
|
|
|
// Fast low-level manipulation
|
|
char* LockBuffer(int32 maxLength);
|
|
BString& UnlockBuffer(int32 length = -1);
|
|
BString& SetByteAt(int32 pos, char to);
|
|
|
|
// Upercase <-> Lowercase
|
|
BString& ToLower();
|
|
BString& ToUpper();
|
|
|
|
BString& Capitalize();
|
|
BString& CapitalizeEachWord();
|
|
|
|
// Escaping and De-escaping
|
|
BString& CharacterEscape(const char* original,
|
|
const char* setOfCharsToEscape,
|
|
char escapeWith);
|
|
BString& CharacterEscape(const char* setOfCharsToEscape,
|
|
char escapeWith);
|
|
BString& CharacterDeescape(const char* original,
|
|
char escapeChar);
|
|
BString& CharacterDeescape(char escapeChar);
|
|
|
|
// Trimming
|
|
BString& Trim();
|
|
|
|
// Insert
|
|
BString& operator<<(const char* string);
|
|
BString& operator<<(const BString& string);
|
|
BString& operator<<(char c);
|
|
BString& operator<<(bool value);
|
|
BString& operator<<(int value);
|
|
BString& operator<<(unsigned int value);
|
|
BString& operator<<(unsigned long value);
|
|
BString& operator<<(long value);
|
|
BString& operator<<(unsigned long long value);
|
|
BString& operator<<(long long value);
|
|
// float/double output hardcodes %.2f style formatting
|
|
BString& operator<<(float value);
|
|
BString& operator<<(double value);
|
|
|
|
public:
|
|
class Private;
|
|
friend class Private;
|
|
|
|
private:
|
|
class PosVect;
|
|
friend class BStringRef;
|
|
|
|
enum PrivateDataTag {
|
|
PRIVATE_DATA
|
|
};
|
|
|
|
private:
|
|
BString(char* privateData, PrivateDataTag tag);
|
|
|
|
// Management
|
|
status_t _MakeWritable();
|
|
status_t _MakeWritable(int32 length, bool copy);
|
|
static char* _Allocate(int32 length);
|
|
char* _Resize(int32 length);
|
|
void _Init(const char* src, int32 length);
|
|
char* _Clone(const char* data, int32 length);
|
|
char* _OpenAtBy(int32 offset, int32 length);
|
|
char* _ShrinkAtBy(int32 offset, int32 length);
|
|
|
|
// Data
|
|
void _SetLength(int32 length);
|
|
bool _DoAppend(const char* string, int32 length);
|
|
bool _DoPrepend(const char* string, int32 length);
|
|
bool _DoInsert(const char* string, int32 offset,
|
|
int32 length);
|
|
|
|
// Search
|
|
int32 _ShortFindAfter(const char* string,
|
|
int32 length) const;
|
|
int32 _FindAfter(const char* string, int32 offset,
|
|
int32 length) const;
|
|
int32 _IFindAfter(const char* string, int32 offset,
|
|
int32 length) const;
|
|
int32 _FindBefore(const char* string, int32 offset,
|
|
int32 length) const;
|
|
int32 _IFindBefore(const char* string, int32 offset,
|
|
int32 length) const;
|
|
|
|
// Escape
|
|
BString& _DoCharacterEscape(const char* string,
|
|
const char* setOfCharsToEscape, char escapeChar);
|
|
BString& _DoCharacterDeescape(const char* string,
|
|
char escapeChar);
|
|
|
|
// Replace
|
|
BString& _DoReplace(const char* findThis,
|
|
const char* replaceWith, int32 maxReplaceCount,
|
|
int32 fromOffset, bool ignoreCase);
|
|
void _ReplaceAtPositions(const PosVect* positions,
|
|
int32 searchLength, const char* with,
|
|
int32 withLength);
|
|
|
|
private:
|
|
int32& _ReferenceCount();
|
|
const int32& _ReferenceCount() const;
|
|
bool _IsShareable() const;
|
|
void _FreePrivateData();
|
|
void _ReleasePrivateData();
|
|
|
|
char* fPrivateData;
|
|
};
|
|
|
|
|
|
// Commutative compare operators
|
|
bool operator<(const char* a, const BString& b);
|
|
bool operator<=(const char* a, const BString& b);
|
|
bool operator==(const char* a, const BString& b);
|
|
bool operator>(const char* a, const BString& b);
|
|
bool operator>=(const char* a, const BString& b);
|
|
bool operator!=(const char* a, const BString& b);
|
|
|
|
|
|
// Non-member compare for sorting, etc.
|
|
int Compare(const BString& a, const BString& b);
|
|
int ICompare(const BString& a, const BString& b);
|
|
int Compare(const BString* a, const BString* b);
|
|
int ICompare(const BString* a, const BString* b);
|
|
|
|
|
|
inline int32
|
|
BString::Length() const
|
|
{
|
|
// the most significant bit is reserved; accessing
|
|
// it in any way will cause the computer to explode
|
|
return fPrivateData ? (*(((int32*)fPrivateData) - 1) & 0x7fffffff) : 0;
|
|
}
|
|
|
|
|
|
inline bool
|
|
BString::IsEmpty() const
|
|
{
|
|
return !Length();
|
|
}
|
|
|
|
|
|
inline const char*
|
|
BString::String() const
|
|
{
|
|
if (!fPrivateData)
|
|
return "";
|
|
return fPrivateData;
|
|
}
|
|
|
|
|
|
inline uint32
|
|
BString::HashValue() const
|
|
{
|
|
return HashValue(String());
|
|
}
|
|
|
|
|
|
inline BString&
|
|
BString::SetTo(const char* string)
|
|
{
|
|
return operator=(string);
|
|
}
|
|
|
|
|
|
inline char
|
|
BString::operator[](int32 index) const
|
|
{
|
|
return fPrivateData[index];
|
|
}
|
|
|
|
|
|
inline char
|
|
BString::ByteAt(int32 index) const
|
|
{
|
|
if (!fPrivateData || index < 0 || index >= Length())
|
|
return 0;
|
|
return fPrivateData[index];
|
|
}
|
|
|
|
|
|
inline BString&
|
|
BString::operator+=(const BString& string)
|
|
{
|
|
_DoAppend(string.String(), string.Length());
|
|
return *this;
|
|
}
|
|
|
|
|
|
inline BString&
|
|
BString::Append(const BString& string)
|
|
{
|
|
_DoAppend(string.String(), string.Length());
|
|
return *this;
|
|
}
|
|
|
|
|
|
inline BString&
|
|
BString::Append(const char* string)
|
|
{
|
|
return operator+=(string);
|
|
}
|
|
|
|
|
|
inline bool
|
|
BString::operator==(const BString& string) const
|
|
{
|
|
return strcmp(String(), string.String()) == 0;
|
|
}
|
|
|
|
|
|
inline bool
|
|
BString::operator<(const BString& string) const
|
|
{
|
|
return strcmp(String(), string.String()) < 0;
|
|
}
|
|
|
|
|
|
inline bool
|
|
BString::operator<=(const BString& string) const
|
|
{
|
|
return strcmp(String(), string.String()) <= 0;
|
|
}
|
|
|
|
|
|
inline bool
|
|
BString::operator>=(const BString& string) const
|
|
{
|
|
return strcmp(String(), string.String()) >= 0;
|
|
}
|
|
|
|
|
|
inline bool
|
|
BString::operator>(const BString& string) const
|
|
{
|
|
return strcmp(String(), string.String()) > 0;
|
|
}
|
|
|
|
|
|
inline bool
|
|
BString::operator!=(const BString& string) const
|
|
{
|
|
return strcmp(String(), string.String()) != 0;
|
|
}
|
|
|
|
|
|
inline bool
|
|
BString::operator!=(const char* string) const
|
|
{
|
|
return !operator==(string);
|
|
}
|
|
|
|
|
|
inline
|
|
BString::operator const char*() const
|
|
{
|
|
return String();
|
|
}
|
|
|
|
|
|
inline bool
|
|
operator<(const char* str, const BString& string)
|
|
{
|
|
return string > str;
|
|
}
|
|
|
|
|
|
inline bool
|
|
operator<=(const char* str, const BString& string)
|
|
{
|
|
return string >= str;
|
|
}
|
|
|
|
|
|
inline bool
|
|
operator==(const char* str, const BString& string)
|
|
{
|
|
return string == str;
|
|
}
|
|
|
|
|
|
inline bool
|
|
operator>(const char* str, const BString& string)
|
|
{
|
|
return string < str;
|
|
}
|
|
|
|
|
|
inline bool
|
|
operator>=(const char* str, const BString& string)
|
|
{
|
|
return string <= str;
|
|
}
|
|
|
|
|
|
inline bool
|
|
operator!=(const char* str, const BString& string)
|
|
{
|
|
return string != str;
|
|
}
|
|
|
|
|
|
#endif // _B_STRING_H
|