* Fixed a race condition in the former _Detach*() functions: since atomic_get()
was used, two different threads could decide to share the same mutable string. * Renamed some functions to make clearer what they do, ie. _Detach() is now called _MakeWritable(). * Cleaned up some questionable semantics, like the const char* parameter in _DetachWith() - you can now choose to copy the original string or not with a boolean. This also makes sure that the string is actually copied when it has to, which wasn't the case before (but that was no problem with the way that function was used). * Made the header compliant with our style guide. * Further cleanup. * All BString related unit tests are passed, so I guess I didn't break too much :-) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30980 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
+227
-197
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2001-2008, Haiku Inc. All Rights Reserved.
|
* Copyright 2001-2009, Haiku Inc. All Rights Reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef __BSTRING__
|
#ifndef __BSTRING__
|
||||||
@@ -16,251 +16,281 @@ class BStringRef;
|
|||||||
|
|
||||||
class BString {
|
class BString {
|
||||||
public:
|
public:
|
||||||
BString();
|
BString();
|
||||||
BString(const char* string);
|
BString(const char* string);
|
||||||
BString(const BString& string);
|
BString(const BString& string);
|
||||||
BString(const char* string, int32 maxLength);
|
BString(const char* string, int32 maxLength);
|
||||||
~BString();
|
~BString();
|
||||||
|
|
||||||
// Access
|
// Access
|
||||||
const char* String() const;
|
const char* String() const;
|
||||||
int32 Length() const;
|
int32 Length() const;
|
||||||
int32 CountChars() const;
|
int32 CountChars() const;
|
||||||
|
|
||||||
// Assignment
|
// Assignment
|
||||||
BString& operator=(const BString& string);
|
BString& operator=(const BString& string);
|
||||||
BString& operator=(const char* string);
|
BString& operator=(const char* string);
|
||||||
BString& operator=(char c);
|
BString& operator=(char c);
|
||||||
|
|
||||||
BString& SetTo(const char* string);
|
BString& SetTo(const char* string);
|
||||||
BString& SetTo(const char* string, int32 maxLength);
|
BString& SetTo(const char* string, int32 maxLength);
|
||||||
|
|
||||||
BString& SetTo(const BString& string);
|
BString& SetTo(const BString& string);
|
||||||
BString& Adopt(BString& from);
|
BString& Adopt(BString& from);
|
||||||
|
|
||||||
BString& SetTo(const BString& string, int32 maxLength);
|
BString& SetTo(const BString& string, int32 maxLength);
|
||||||
BString& Adopt(BString& from, int32 maxLength);
|
BString& Adopt(BString& from, int32 maxLength);
|
||||||
|
|
||||||
BString& SetTo(char c, int32 count);
|
BString& SetTo(char c, int32 count);
|
||||||
|
|
||||||
// Substring copying
|
// Substring copying
|
||||||
BString& CopyInto(BString& into, int32 fromOffset, int32 length) const;
|
BString& CopyInto(BString& into, int32 fromOffset,
|
||||||
void CopyInto(char* into, int32 fromOffset, int32 length) const;
|
int32 length) const;
|
||||||
|
void CopyInto(char* into, int32 fromOffset,
|
||||||
|
int32 length) const;
|
||||||
|
|
||||||
// Appending
|
// Appending
|
||||||
BString& operator+=(const BString& string);
|
BString& operator+=(const BString& string);
|
||||||
BString& operator+=(const char* string);
|
BString& operator+=(const char* string);
|
||||||
BString& operator+=(char c);
|
BString& operator+=(char c);
|
||||||
|
|
||||||
BString& Append(const BString& string);
|
BString& Append(const BString& string);
|
||||||
BString& Append(const char* string);
|
BString& Append(const char* string);
|
||||||
|
|
||||||
BString& Append(const BString& string, int32 length);
|
BString& Append(const BString& string, int32 length);
|
||||||
BString& Append(const char* string, int32 length);
|
BString& Append(const char* string, int32 length);
|
||||||
BString& Append(char c, int32 count);
|
BString& Append(char c, int32 count);
|
||||||
|
|
||||||
// Prepending
|
// Prepending
|
||||||
BString& Prepend(const char* string);
|
BString& Prepend(const char* string);
|
||||||
BString& Prepend(const BString& string);
|
BString& Prepend(const BString& string);
|
||||||
BString& Prepend(const char* string, int32 length);
|
BString& Prepend(const char* string, int32 length);
|
||||||
BString& Prepend(const BString& string, int32 length);
|
BString& Prepend(const BString& string, int32 length);
|
||||||
BString& Prepend(char c, int32 count);
|
BString& Prepend(char c, int32 count);
|
||||||
|
|
||||||
// Inserting
|
// Inserting
|
||||||
BString& Insert(const char* string, int32 position);
|
BString& Insert(const char* string, int32 position);
|
||||||
BString& Insert(const char* string, int32 length, int32 position);
|
BString& Insert(const char* string, int32 length,
|
||||||
BString& Insert(const char* string, int32 fromOffset, int32 length,
|
int32 position);
|
||||||
int32 position);
|
BString& Insert(const char* string, int32 fromOffset,
|
||||||
BString& Insert(const BString& string, int32 position);
|
int32 length, int32 position);
|
||||||
BString& Insert(const BString& string, int32 length, int32 position);
|
BString& Insert(const BString& string, int32 position);
|
||||||
BString& Insert(const BString& string, int32 fromOffset, int32 length,
|
BString& Insert(const BString& string, int32 length,
|
||||||
int32 position);
|
int32 position);
|
||||||
BString& Insert(char c, int32 count, int32 position);
|
BString& Insert(const BString& string, int32 fromOffset,
|
||||||
|
int32 length, int32 position);
|
||||||
|
BString& Insert(char c, int32 count, int32 position);
|
||||||
|
|
||||||
// Removing
|
// Removing
|
||||||
BString& Truncate(int32 newLength, bool lazy = true);
|
BString& Truncate(int32 newLength, bool lazy = true);
|
||||||
BString& Remove(int32 from, int32 length);
|
BString& Remove(int32 from, int32 length);
|
||||||
|
|
||||||
BString& RemoveFirst(const BString& string);
|
BString& RemoveFirst(const BString& string);
|
||||||
BString& RemoveLast(const BString& string);
|
BString& RemoveLast(const BString& string);
|
||||||
BString& RemoveAll(const BString& string);
|
BString& RemoveAll(const BString& string);
|
||||||
|
|
||||||
BString& RemoveFirst(const char* string);
|
BString& RemoveFirst(const char* string);
|
||||||
BString& RemoveLast(const char* string);
|
BString& RemoveLast(const char* string);
|
||||||
BString& RemoveAll(const char* string);
|
BString& RemoveAll(const char* string);
|
||||||
|
|
||||||
BString& RemoveSet(const char* setOfCharsToRemove);
|
BString& RemoveSet(const char* setOfCharsToRemove);
|
||||||
|
|
||||||
BString& MoveInto(BString& into, int32 from, int32 length);
|
BString& MoveInto(BString& into, int32 from, int32 length);
|
||||||
void MoveInto(char* into, int32 from, int32 length);
|
void MoveInto(char* into, int32 from, int32 length);
|
||||||
|
|
||||||
// Compare functions
|
// 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 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;
|
||||||
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;
|
||||||
|
|
||||||
// strcmp()-style compare functions
|
// strcmp()-style compare functions
|
||||||
int Compare(const BString& string) const;
|
int Compare(const BString& string) const;
|
||||||
int Compare(const char* string) const;
|
int Compare(const char* string) const;
|
||||||
int Compare(const BString& string, int32 length) const;
|
int Compare(const BString& string, int32 length) const;
|
||||||
int Compare(const char* string, int32 length) const;
|
int Compare(const char* string, int32 length) const;
|
||||||
int ICompare(const BString& string) const;
|
int ICompare(const BString& string) const;
|
||||||
int ICompare(const char* string) const;
|
int ICompare(const char* string) const;
|
||||||
int ICompare(const BString& string, int32 length) const;
|
int ICompare(const BString& string, int32 length) const;
|
||||||
int ICompare(const char* string, int32 length) const;
|
int ICompare(const char* string, int32 length) const;
|
||||||
|
|
||||||
// Searching
|
// Searching
|
||||||
int32 FindFirst(const BString& string) const;
|
int32 FindFirst(const BString& string) const;
|
||||||
int32 FindFirst(const char* string) const;
|
int32 FindFirst(const char* string) const;
|
||||||
int32 FindFirst(const BString& string, int32 fromOffset) const;
|
int32 FindFirst(const BString& string,
|
||||||
int32 FindFirst(const char* string, int32 fromOffset) const;
|
int32 fromOffset) const;
|
||||||
int32 FindFirst(char c) const;
|
int32 FindFirst(const char* string,
|
||||||
int32 FindFirst(char c, int32 fromOffset) const;
|
int32 fromOffset) const;
|
||||||
|
int32 FindFirst(char c) const;
|
||||||
|
int32 FindFirst(char c, int32 fromOffset) const;
|
||||||
|
|
||||||
int32 FindLast(const BString& string) const;
|
int32 FindLast(const BString& string) const;
|
||||||
int32 FindLast(const char* string) const;
|
int32 FindLast(const char* string) const;
|
||||||
int32 FindLast(const BString& string, int32 beforeOffset) const;
|
int32 FindLast(const BString& string,
|
||||||
int32 FindLast(const char* string, int32 beforeOffset) const;
|
int32 beforeOffset) const;
|
||||||
int32 FindLast(char c) const;
|
int32 FindLast(const char* string,
|
||||||
int32 FindLast(char c, int32 beforeOffset) const;
|
int32 beforeOffset) const;
|
||||||
|
int32 FindLast(char c) const;
|
||||||
|
int32 FindLast(char c, int32 beforeOffset) const;
|
||||||
|
|
||||||
int32 IFindFirst(const BString& string) const;
|
int32 IFindFirst(const BString& string) const;
|
||||||
int32 IFindFirst(const char* string) const;
|
int32 IFindFirst(const char* string) const;
|
||||||
int32 IFindFirst(const BString& string, int32 fromOffset) const;
|
int32 IFindFirst(const BString& string,
|
||||||
int32 IFindFirst(const char* string, int32 fromOffset) const;
|
int32 fromOffset) const;
|
||||||
|
int32 IFindFirst(const char* string,
|
||||||
|
int32 fromOffset) const;
|
||||||
|
|
||||||
int32 IFindLast(const BString& string) const;
|
int32 IFindLast(const BString& string) const;
|
||||||
int32 IFindLast(const char* string) const;
|
int32 IFindLast(const char* string) const;
|
||||||
int32 IFindLast(const BString& string, int32 beforeOffset) const;
|
int32 IFindLast(const BString& string,
|
||||||
int32 IFindLast(const char* string, int32 beforeOffset) const;
|
int32 beforeOffset) const;
|
||||||
|
int32 IFindLast(const char* string,
|
||||||
|
int32 beforeOffset) const;
|
||||||
|
|
||||||
// Replacing
|
// Replacing
|
||||||
BString& ReplaceFirst(char replaceThis, char withThis);
|
BString& ReplaceFirst(char replaceThis, char withThis);
|
||||||
BString& ReplaceLast(char replaceThis, char withThis);
|
BString& ReplaceLast(char replaceThis, char withThis);
|
||||||
BString& ReplaceAll(char replaceThis, char withThis, int32 fromOffset = 0);
|
BString& ReplaceAll(char replaceThis, char withThis,
|
||||||
BString& Replace(char replaceThis, char withThis, int32 maxReplaceCount,
|
int32 fromOffset = 0);
|
||||||
int32 fromOffset = 0);
|
BString& Replace(char replaceThis, char withThis,
|
||||||
BString& ReplaceFirst(const char* replaceThis, const char* withThis);
|
int32 maxReplaceCount, int32 fromOffset = 0);
|
||||||
BString& ReplaceLast(const char* replaceThis, const char* withThis);
|
BString& ReplaceFirst(const char* replaceThis,
|
||||||
BString& ReplaceAll(const char* replaceThis, const char* withThis,
|
const char* withThis);
|
||||||
int32 fromOffset = 0);
|
BString& ReplaceLast(const char* replaceThis,
|
||||||
BString& Replace(const char* replaceThis, const char* withThis,
|
const char* withThis);
|
||||||
int32 maxReplaceCount, int32 fromOffset = 0);
|
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& IReplaceFirst(char replaceThis, char withThis);
|
BString& IReplaceFirst(char replaceThis, char withThis);
|
||||||
BString& IReplaceLast(char replaceThis, char withThis);
|
BString& IReplaceLast(char replaceThis, char withThis);
|
||||||
BString& IReplaceAll(char replaceThis, char withThis, int32 fromOffset = 0);
|
BString& IReplaceAll(char replaceThis, char withThis,
|
||||||
BString& IReplace(char replaceThis, char withThis, int32 maxReplaceCount,
|
int32 fromOffset = 0);
|
||||||
int32 fromOffset = 0);
|
BString& IReplace(char replaceThis, char withThis,
|
||||||
BString& IReplaceFirst(const char* replaceThis, const char* withThis);
|
int32 maxReplaceCount, int32 fromOffset = 0);
|
||||||
BString& IReplaceLast(const char* replaceThis, const char* withThis);
|
BString& IReplaceFirst(const char* replaceThis,
|
||||||
BString& IReplaceAll(const char* replaceThis, const char* withThis,
|
const char* withThis);
|
||||||
int32 fromOffset = 0);
|
BString& IReplaceLast(const char* replaceThis,
|
||||||
BString& IReplace(const char* replaceThis, const char* withThis,
|
const char* withThis);
|
||||||
int32 maxReplaceCount, int32 fromOffset = 0);
|
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* setOfChars, char with);
|
BString& ReplaceSet(const char* setOfChars, char with);
|
||||||
BString& ReplaceSet(const char* setOfChars, const char* with);
|
BString& ReplaceSet(const char* setOfChars, const char* with);
|
||||||
|
|
||||||
// Unchecked char access
|
// Unchecked char access
|
||||||
char operator[](int32 index) const;
|
char operator[](int32 index) const;
|
||||||
|
|
||||||
#if __GNUC__ > 3
|
#if __GNUC__ > 3
|
||||||
BStringRef operator[](int32 index);
|
BStringRef operator[](int32 index);
|
||||||
#else
|
#else
|
||||||
char& operator[](int32 index);
|
char& operator[](int32 index);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Checked char access
|
// Checked char access
|
||||||
char ByteAt(int32 index) const;
|
char ByteAt(int32 index) const;
|
||||||
|
|
||||||
// Fast low-level manipulation
|
// Fast low-level manipulation
|
||||||
char* LockBuffer(int32 maxLength);
|
char* LockBuffer(int32 maxLength);
|
||||||
BString& UnlockBuffer(int32 length = -1);
|
BString& UnlockBuffer(int32 length = -1);
|
||||||
|
|
||||||
// Upercase <-> Lowercase
|
// Upercase <-> Lowercase
|
||||||
BString& ToLower();
|
BString& ToLower();
|
||||||
BString& ToUpper();
|
BString& ToUpper();
|
||||||
|
|
||||||
BString& Capitalize();
|
BString& Capitalize();
|
||||||
BString& CapitalizeEachWord();
|
BString& CapitalizeEachWord();
|
||||||
|
|
||||||
// Escaping and De-escaping
|
// Escaping and De-escaping
|
||||||
BString& CharacterEscape(const char* original, const char* setOfCharsToEscape,
|
BString& CharacterEscape(const char* original,
|
||||||
char escapeWith);
|
const char* setOfCharsToEscape, char escapeWith);
|
||||||
BString& CharacterEscape(const char* setOfCharsToEscape, char escapeWith);
|
BString& CharacterEscape(const char* setOfCharsToEscape,
|
||||||
BString& CharacterDeescape(const char* original, char escapeChar);
|
char escapeWith);
|
||||||
BString& CharacterDeescape(char escapeChar);
|
BString& CharacterDeescape(const char* original,
|
||||||
|
char escapeChar);
|
||||||
|
BString& CharacterDeescape(char escapeChar);
|
||||||
|
|
||||||
// Insert
|
// Insert
|
||||||
BString& operator<<(const char* string);
|
BString& operator<<(const char* string);
|
||||||
BString& operator<<(const BString& string);
|
BString& operator<<(const BString& string);
|
||||||
BString& operator<<(char c);
|
BString& operator<<(char c);
|
||||||
BString& operator<<(int value);
|
BString& operator<<(int value);
|
||||||
BString& operator<<(unsigned int value);
|
BString& operator<<(unsigned int value);
|
||||||
BString& operator<<(uint32 value);
|
BString& operator<<(uint32 value);
|
||||||
BString& operator<<(int32 value);
|
BString& operator<<(int32 value);
|
||||||
BString& operator<<(uint64 value);
|
BString& operator<<(uint64 value);
|
||||||
BString& operator<<(int64 value);
|
BString& operator<<(int64 value);
|
||||||
// float output hardcodes %.2f style formatting
|
// float output hardcodes %.2f style formatting
|
||||||
BString& operator<<(float value);
|
BString& operator<<(float value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class PosVect;
|
class PosVect;
|
||||||
friend class BStringRef;
|
friend class BStringRef;
|
||||||
|
|
||||||
// Management
|
// Management
|
||||||
status_t _Detach();
|
status_t _MakeWritable();
|
||||||
char* _Alloc(int32 length, bool adoptReferenceCount = true);
|
status_t _MakeWritable(int32 length, bool copy);
|
||||||
char* _Realloc(int32 length);
|
char* _Allocate(int32 length);
|
||||||
void _Init(const char* src, int32 length);
|
char* _Resize(int32 length);
|
||||||
char* _Clone(const char* data, int32 length);
|
void _Init(const char* src, int32 length);
|
||||||
char* _OpenAtBy(int32 offset, int32 length);
|
char* _Clone(const char* data, int32 length);
|
||||||
char* _ShrinkAtBy(int32 offset, int32 length);
|
char* _OpenAtBy(int32 offset, int32 length);
|
||||||
status_t _DetachWith(const char* string, int32 length);
|
char* _ShrinkAtBy(int32 offset, int32 length);
|
||||||
|
|
||||||
// Data
|
// Data
|
||||||
void _SetLength(int32 length);
|
void _SetLength(int32 length);
|
||||||
bool _DoAppend(const char* string, int32 length);
|
bool _DoAppend(const char* string, int32 length);
|
||||||
bool _DoPrepend(const char* string, int32 length);
|
bool _DoPrepend(const char* string, int32 length);
|
||||||
bool _DoInsert(const char* string, int32 offset, int32 length);
|
bool _DoInsert(const char* string, int32 offset,
|
||||||
|
int32 length);
|
||||||
|
|
||||||
// Search
|
// Search
|
||||||
int32 _ShortFindAfter(const char* string, int32 len) const;
|
int32 _ShortFindAfter(const char* string,
|
||||||
int32 _FindAfter(const char* string, int32 offset, int32 strlen) const;
|
int32 length) const;
|
||||||
int32 _IFindAfter(const char* string, int32 offset, int32 strlen) 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;
|
||||||
|
|
||||||
int32 _FindBefore(const char* string, int32 offset, int32 strlen) const;
|
// Escape
|
||||||
int32 _IFindBefore(const char* string, int32 offset, int32 strlen) const;
|
BString& _DoCharacterEscape(const char* string,
|
||||||
|
const char *setOfCharsToEscape, char escapeChar);
|
||||||
|
BString& _DoCharacterDeescape(const char* string,
|
||||||
|
char escapeChar);
|
||||||
|
|
||||||
// Escape
|
// Replace
|
||||||
BString& _DoCharacterEscape(const char* string,
|
BString& _DoReplace(const char* findThis,
|
||||||
const char *setOfCharsToEscape, char escapeChar);
|
const char* replaceWith, int32 maxReplaceCount,
|
||||||
BString& _DoCharacterDeescape(const char* string, char escapeChar);
|
int32 fromOffset, bool ignoreCase);
|
||||||
|
void _ReplaceAtPositions(const PosVect* positions,
|
||||||
// Replace
|
int32 searchLength, const char* with,
|
||||||
BString& _DoReplace(const char* findThis, const char* replaceWith,
|
int32 withLength);
|
||||||
int32 maxReplaceCount, int32 fromOffset, bool ignoreCase);
|
|
||||||
void _ReplaceAtPositions(const PosVect* positions, int32 searchLen,
|
|
||||||
const char* with, int32 withLen);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int32& _ReferenceCount();
|
vint32& _ReferenceCount();
|
||||||
const int32& _ReferenceCount() const;
|
const vint32& _ReferenceCount() const;
|
||||||
bool _IsShareable() const;
|
bool _IsShareable() const;
|
||||||
void _FreePrivateData();
|
void _FreePrivateData();
|
||||||
|
|
||||||
char* fPrivateData;
|
char* fPrivateData;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -442,7 +472,7 @@ class BStringRef {
|
|||||||
public:
|
public:
|
||||||
BStringRef(BString& string, int32 position);
|
BStringRef(BString& string, int32 position);
|
||||||
~BStringRef() {}
|
~BStringRef() {}
|
||||||
|
|
||||||
operator char() const;
|
operator char() const;
|
||||||
|
|
||||||
char* operator&();
|
char* operator&();
|
||||||
|
|||||||
+222
-174
@@ -1,19 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2001-2008, Haiku, Inc. All Rights Reserved.
|
* Copyright 2001-2009, Haiku, Inc. All Rights Reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
* Marc Flerackers ([email protected])
|
* Marc Flerackers ([email protected])
|
||||||
* Stefano Ceccherini ([email protected])
|
* Stefano Ceccherini ([email protected])
|
||||||
* Oliver Tappe ([email protected])
|
* Oliver Tappe ([email protected])
|
||||||
* Axel Dörfler, [email protected]
|
* Axel Dörfler, [email protected]
|
||||||
* Julun <[email protected]>
|
* Julun <[email protected]>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*! String class supporting common string operations. */
|
/*! String class supporting common string operations. */
|
||||||
|
|
||||||
|
|
||||||
#include <Debug.h>
|
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@@ -21,9 +20,8 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <Debug.h>
|
||||||
|
|
||||||
// Set this to 1 to make some private methods inline
|
|
||||||
#define ENABLE_INLINES 0
|
|
||||||
|
|
||||||
// define proper names for case-option of _DoReplace()
|
// define proper names for case-option of _DoReplace()
|
||||||
#define KEEP_CASE false
|
#define KEEP_CASE false
|
||||||
@@ -35,7 +33,7 @@
|
|||||||
|
|
||||||
const uint32 kPrivateDataOffset = 2 * sizeof(int32);
|
const uint32 kPrivateDataOffset = 2 * sizeof(int32);
|
||||||
|
|
||||||
const char *B_EMPTY_STRING = "";
|
const char* B_EMPTY_STRING = "";
|
||||||
|
|
||||||
|
|
||||||
// helper function, returns minimum of two given values (but clamps to 0):
|
// helper function, returns minimum of two given values (but clamps to 0):
|
||||||
@@ -49,7 +47,7 @@ min_clamp0(int32 num1, int32 num2)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//! helper function, returns length of given string (but clamps to given maximum):
|
//! Returns length of given string (but clamps to given maximum).
|
||||||
static inline int32
|
static inline int32
|
||||||
strlen_clamp(const char* str, int32 max)
|
strlen_clamp(const char* str, int32 max)
|
||||||
{
|
{
|
||||||
@@ -62,23 +60,48 @@ strlen_clamp(const char* str, int32 max)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//! Helper function for strlen() that can handle NULL strings.
|
||||||
|
static inline size_t
|
||||||
|
string_length(const char* string)
|
||||||
|
{
|
||||||
|
return string != NULL ? strlen(string) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//! helper function, massages given pointer into a legal c-string:
|
//! helper function, massages given pointer into a legal c-string:
|
||||||
static inline const char *
|
static inline const char*
|
||||||
safestr(const char* str)
|
safestr(const char* str)
|
||||||
{
|
{
|
||||||
return str ? str : "";
|
return str ? str : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline vint32&
|
||||||
|
data_reference_count(char* data)
|
||||||
|
{
|
||||||
|
return *(((int32 *)data) - 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline int32&
|
||||||
|
data_length(char* data)
|
||||||
|
{
|
||||||
|
return *(((int32*)data) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - PosVect
|
// #pragma mark - PosVect
|
||||||
|
|
||||||
|
|
||||||
class BString::PosVect {
|
class BString::PosVect {
|
||||||
public:
|
public:
|
||||||
PosVect()
|
PosVect()
|
||||||
: fSize(0),
|
:
|
||||||
|
fSize(0),
|
||||||
fBufferSize(20),
|
fBufferSize(20),
|
||||||
fBuffer(NULL) { }
|
fBuffer(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
~PosVect()
|
~PosVect()
|
||||||
{
|
{
|
||||||
@@ -92,7 +115,7 @@ public:
|
|||||||
fBufferSize *= 2;
|
fBufferSize *= 2;
|
||||||
|
|
||||||
int32* newBuffer = NULL;
|
int32* newBuffer = NULL;
|
||||||
newBuffer = (int32 *)realloc(fBuffer, fBufferSize * sizeof(int32));
|
newBuffer = (int32*)realloc(fBuffer, fBufferSize * sizeof(int32));
|
||||||
if (newBuffer == NULL)
|
if (newBuffer == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -104,9 +127,14 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline int32 ItemAt(int32 index) const
|
inline int32 ItemAt(int32 index) const
|
||||||
{ return fBuffer[index]; }
|
{
|
||||||
|
return fBuffer[index];
|
||||||
|
}
|
||||||
|
|
||||||
inline int32 CountItems() const
|
inline int32 CountItems() const
|
||||||
{ return fSize; }
|
{
|
||||||
|
return fSize;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int32 fSize;
|
int32 fSize;
|
||||||
@@ -133,7 +161,7 @@ BStringRef::operator char() const
|
|||||||
BStringRef&
|
BStringRef&
|
||||||
BStringRef::operator=(char c)
|
BStringRef::operator=(char c)
|
||||||
{
|
{
|
||||||
fString._Detach();
|
fString._MakeWritable();
|
||||||
fString.fPrivateData[fPosition] = c;
|
fString.fPrivateData[fPosition] = c;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -156,7 +184,7 @@ BStringRef::operator&() const
|
|||||||
char*
|
char*
|
||||||
BStringRef::operator&()
|
BStringRef::operator&()
|
||||||
{
|
{
|
||||||
if (fString._Detach() != B_OK)
|
if (fString._MakeWritable() != B_OK)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
fString._ReferenceCount() = -1;
|
fString._ReferenceCount() = -1;
|
||||||
@@ -169,21 +197,24 @@ BStringRef::operator&()
|
|||||||
|
|
||||||
|
|
||||||
BString::BString()
|
BString::BString()
|
||||||
: fPrivateData(NULL)
|
:
|
||||||
|
fPrivateData(NULL)
|
||||||
{
|
{
|
||||||
_Init("", 0);
|
_Init("", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BString::BString(const char* string)
|
BString::BString(const char* string)
|
||||||
: fPrivateData(NULL)
|
:
|
||||||
|
fPrivateData(NULL)
|
||||||
{
|
{
|
||||||
_Init(string, strlen(safestr(string)));
|
_Init(string, strlen(safestr(string)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BString::BString(const BString& string)
|
BString::BString(const BString& string)
|
||||||
: fPrivateData(NULL)
|
:
|
||||||
|
fPrivateData(NULL)
|
||||||
{
|
{
|
||||||
// check if source is sharable - if so, share else clone
|
// check if source is sharable - if so, share else clone
|
||||||
if (string._IsShareable()) {
|
if (string._IsShareable()) {
|
||||||
@@ -217,8 +248,8 @@ BString::CountChars() const
|
|||||||
{
|
{
|
||||||
int32 count = 0;
|
int32 count = 0;
|
||||||
|
|
||||||
const char *start = fPrivateData;
|
const char* start = fPrivateData;
|
||||||
const char *end = fPrivateData + Length();
|
const char* end = fPrivateData + Length();
|
||||||
|
|
||||||
while (start++ != end) {
|
while (start++ != end) {
|
||||||
count++;
|
count++;
|
||||||
@@ -262,8 +293,10 @@ BString::SetTo(const char* string, int32 maxLength)
|
|||||||
{
|
{
|
||||||
if (maxLength < 0)
|
if (maxLength < 0)
|
||||||
maxLength = INT32_MAX;
|
maxLength = INT32_MAX;
|
||||||
|
|
||||||
maxLength = strlen_clamp(safestr(string), maxLength);
|
maxLength = strlen_clamp(safestr(string), maxLength);
|
||||||
if (_DetachWith("", maxLength) == B_OK)
|
|
||||||
|
if (_MakeWritable(maxLength, false) == B_OK)
|
||||||
memcpy(fPrivateData, string, maxLength);
|
memcpy(fPrivateData, string, maxLength);
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
@@ -318,7 +351,7 @@ BString::SetTo(const BString& string, int32 maxLength)
|
|||||||
// make sure we reassing in case length is different
|
// make sure we reassing in case length is different
|
||||||
|| (fPrivateData == string.fPrivateData && Length() > maxLength)) {
|
|| (fPrivateData == string.fPrivateData && Length() > maxLength)) {
|
||||||
maxLength = min_clamp0(maxLength, string.Length());
|
maxLength = min_clamp0(maxLength, string.Length());
|
||||||
if (_DetachWith("", maxLength) == B_OK)
|
if (_MakeWritable(maxLength, false) == B_OK)
|
||||||
memcpy(fPrivateData, string.String(), maxLength);
|
memcpy(fPrivateData, string.String(), maxLength);
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
@@ -341,7 +374,7 @@ BString::SetTo(char c, int32 count)
|
|||||||
if (count < 0)
|
if (count < 0)
|
||||||
count = 0;
|
count = 0;
|
||||||
|
|
||||||
if (_DetachWith("", count) == B_OK)
|
if (_MakeWritable(count, false) == B_OK)
|
||||||
memset(fPrivateData, c, count);
|
memset(fPrivateData, c, count);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -480,7 +513,7 @@ BString::Prepend(char c, int32 count)
|
|||||||
BString&
|
BString&
|
||||||
BString::Insert(const char* string, int32 position)
|
BString::Insert(const char* string, int32 position)
|
||||||
{
|
{
|
||||||
if (string && position <= Length()) {
|
if (string != NULL && position <= Length()) {
|
||||||
int32 len = int32(strlen(string));
|
int32 len = int32(strlen(string));
|
||||||
if (position < 0) {
|
if (position < 0) {
|
||||||
int32 skipLen = min_clamp0(-1 * position, len);
|
int32 skipLen = min_clamp0(-1 * position, len);
|
||||||
@@ -499,7 +532,7 @@ BString::Insert(const char* string, int32 position)
|
|||||||
BString&
|
BString&
|
||||||
BString::Insert(const char* string, int32 length, int32 position)
|
BString::Insert(const char* string, int32 length, int32 position)
|
||||||
{
|
{
|
||||||
if (string && position <= Length()) {
|
if (string != NULL && position <= Length()) {
|
||||||
int32 len = strlen_clamp(string, length);
|
int32 len = strlen_clamp(string, length);
|
||||||
if (position < 0) {
|
if (position < 0) {
|
||||||
int32 skipLen = min_clamp0(-1 * position, len);
|
int32 skipLen = min_clamp0(-1 * position, len);
|
||||||
@@ -578,9 +611,10 @@ BString::Truncate(int32 newLength, bool lazy)
|
|||||||
if (newLength < 0)
|
if (newLength < 0)
|
||||||
newLength = 0;
|
newLength = 0;
|
||||||
|
|
||||||
if (newLength < Length())
|
if (newLength < Length()) {
|
||||||
// ignore lazy, since we might detach
|
// ignore lazy, since we might detach
|
||||||
_DetachWith(fPrivateData, newLength);
|
_MakeWritable(newLength, true);
|
||||||
|
}
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -624,7 +658,7 @@ BString::RemoveAll(const BString& string)
|
|||||||
if (string.Length() == 0 || Length() == 0 || FindFirst(string) < 0)
|
if (string.Length() == 0 || Length() == 0 || FindFirst(string) < 0)
|
||||||
return *this;
|
return *this;
|
||||||
|
|
||||||
if (_Detach() != B_OK)
|
if (_MakeWritable() != B_OK)
|
||||||
return *this;
|
return *this;
|
||||||
|
|
||||||
return _DoReplace(string.String(), "", REPLACE_ALL, 0, KEEP_CASE);
|
return _DoReplace(string.String(), "", REPLACE_ALL, 0, KEEP_CASE);
|
||||||
@@ -663,7 +697,7 @@ BString::RemoveAll(const char* string)
|
|||||||
if (!string || Length() == 0 || FindFirst(string) < 0)
|
if (!string || Length() == 0 || FindFirst(string) < 0)
|
||||||
return *this;
|
return *this;
|
||||||
|
|
||||||
if (_Detach() != B_OK)
|
if (_MakeWritable() != B_OK)
|
||||||
return *this;
|
return *this;
|
||||||
|
|
||||||
return _DoReplace(string, "", REPLACE_ALL, 0, KEEP_CASE);
|
return _DoReplace(string, "", REPLACE_ALL, 0, KEEP_CASE);
|
||||||
@@ -843,8 +877,8 @@ BString::FindFirst(const char* string, int32 fromOffset) const
|
|||||||
int32
|
int32
|
||||||
BString::FindFirst(char c) const
|
BString::FindFirst(char c) const
|
||||||
{
|
{
|
||||||
const char *start = String();
|
const char* start = String();
|
||||||
const char *end = String() + Length();
|
const char* end = String() + Length();
|
||||||
|
|
||||||
// Scans the string until we found the
|
// Scans the string until we found the
|
||||||
// character, or we reach the string's start
|
// character, or we reach the string's start
|
||||||
@@ -865,8 +899,8 @@ BString::FindFirst(char c, int32 fromOffset) const
|
|||||||
if (fromOffset < 0)
|
if (fromOffset < 0)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
const char *start = String() + min_clamp0(fromOffset, Length());
|
const char* start = String() + min_clamp0(fromOffset, Length());
|
||||||
const char *end = String() + Length();
|
const char* end = String() + Length();
|
||||||
|
|
||||||
// Scans the string until we found the
|
// Scans the string until we found the
|
||||||
// character, or we reach the string's start
|
// character, or we reach the string's start
|
||||||
@@ -926,8 +960,8 @@ BString::FindLast(const char* string, int32 beforeOffset) const
|
|||||||
int32
|
int32
|
||||||
BString::FindLast(char c) const
|
BString::FindLast(char c) const
|
||||||
{
|
{
|
||||||
const char *start = String();
|
const char* start = String();
|
||||||
const char *end = String() + Length();
|
const char* end = String() + Length();
|
||||||
|
|
||||||
// Scans the string backwards until we found
|
// Scans the string backwards until we found
|
||||||
// the character, or we reach the string's start
|
// the character, or we reach the string's start
|
||||||
@@ -948,8 +982,8 @@ BString::FindLast(char c, int32 beforeOffset) const
|
|||||||
if (beforeOffset < 0)
|
if (beforeOffset < 0)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
const char *start = String();
|
const char* start = String();
|
||||||
const char *end = String() + min_clamp0(beforeOffset, Length());
|
const char* end = String() + min_clamp0(beforeOffset, Length());
|
||||||
|
|
||||||
// Scans the string backwards until we found
|
// Scans the string backwards until we found
|
||||||
// the character, or we reach the string's start
|
// the character, or we reach the string's start
|
||||||
@@ -1055,7 +1089,7 @@ BString&
|
|||||||
BString::ReplaceFirst(char replaceThis, char withThis)
|
BString::ReplaceFirst(char replaceThis, char withThis)
|
||||||
{
|
{
|
||||||
int32 pos = FindFirst(replaceThis);
|
int32 pos = FindFirst(replaceThis);
|
||||||
if (pos >= 0 && _Detach() == B_OK)
|
if (pos >= 0 && _MakeWritable() == B_OK)
|
||||||
fPrivateData[pos] = withThis;
|
fPrivateData[pos] = withThis;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -1065,7 +1099,7 @@ BString&
|
|||||||
BString::ReplaceLast(char replaceThis, char withThis)
|
BString::ReplaceLast(char replaceThis, char withThis)
|
||||||
{
|
{
|
||||||
int32 pos = FindLast(replaceThis);
|
int32 pos = FindLast(replaceThis);
|
||||||
if (pos >= 0 && _Detach() == B_OK)
|
if (pos >= 0 && _MakeWritable() == B_OK)
|
||||||
fPrivateData[pos] = withThis;
|
fPrivateData[pos] = withThis;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -1078,7 +1112,7 @@ BString::ReplaceAll(char replaceThis, char withThis, int32 fromOffset)
|
|||||||
int32 pos = FindFirst(replaceThis, fromOffset);
|
int32 pos = FindFirst(replaceThis, fromOffset);
|
||||||
|
|
||||||
// detach and set first match
|
// detach and set first match
|
||||||
if (pos >= 0 && _Detach() == B_OK) {
|
if (pos >= 0 && _MakeWritable() == B_OK) {
|
||||||
fPrivateData[pos] = withThis;
|
fPrivateData[pos] = withThis;
|
||||||
for (pos = pos;;) {
|
for (pos = pos;;) {
|
||||||
pos = FindFirst(replaceThis, pos);
|
pos = FindFirst(replaceThis, pos);
|
||||||
@@ -1098,7 +1132,7 @@ BString::Replace(char replaceThis, char withThis, int32 maxReplaceCount,
|
|||||||
fromOffset = min_clamp0(fromOffset, Length());
|
fromOffset = min_clamp0(fromOffset, Length());
|
||||||
int32 pos = FindFirst(replaceThis, fromOffset);
|
int32 pos = FindFirst(replaceThis, fromOffset);
|
||||||
|
|
||||||
if (maxReplaceCount > 0 && pos >= 0 && _Detach() == B_OK) {
|
if (maxReplaceCount > 0 && pos >= 0 && _MakeWritable() == B_OK) {
|
||||||
maxReplaceCount--;
|
maxReplaceCount--;
|
||||||
fPrivateData[pos] = withThis;
|
fPrivateData[pos] = withThis;
|
||||||
for (pos = pos; maxReplaceCount > 0; maxReplaceCount--) {
|
for (pos = pos; maxReplaceCount > 0; maxReplaceCount--) {
|
||||||
@@ -1118,7 +1152,7 @@ BString::ReplaceFirst(const char* replaceThis, const char* withThis)
|
|||||||
if (!replaceThis || !withThis || FindFirst(replaceThis) < 0)
|
if (!replaceThis || !withThis || FindFirst(replaceThis) < 0)
|
||||||
return *this;
|
return *this;
|
||||||
|
|
||||||
if (_Detach() != B_OK)
|
if (_MakeWritable() != B_OK)
|
||||||
return *this;
|
return *this;
|
||||||
|
|
||||||
return _DoReplace(replaceThis, withThis, 1, 0, KEEP_CASE);
|
return _DoReplace(replaceThis, withThis, 1, 0, KEEP_CASE);
|
||||||
@@ -1145,7 +1179,7 @@ BString::ReplaceLast(const char* replaceThis, const char* withThis)
|
|||||||
if (!_ShrinkAtBy(pos, -difference))
|
if (!_ShrinkAtBy(pos, -difference))
|
||||||
return *this;
|
return *this;
|
||||||
} else {
|
} else {
|
||||||
if (_Detach() != B_OK)
|
if (_MakeWritable() != B_OK)
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
memcpy(fPrivateData + pos, withThis, withThisLength);
|
memcpy(fPrivateData + pos, withThis, withThisLength);
|
||||||
@@ -1162,7 +1196,7 @@ BString::ReplaceAll(const char* replaceThis, const char* withThis,
|
|||||||
if (!replaceThis || !withThis || FindFirst(replaceThis) < 0)
|
if (!replaceThis || !withThis || FindFirst(replaceThis) < 0)
|
||||||
return *this;
|
return *this;
|
||||||
|
|
||||||
if (_Detach() != B_OK)
|
if (_MakeWritable() != B_OK)
|
||||||
return *this;
|
return *this;
|
||||||
|
|
||||||
return _DoReplace(replaceThis, withThis, REPLACE_ALL,
|
return _DoReplace(replaceThis, withThis, REPLACE_ALL,
|
||||||
@@ -1178,7 +1212,7 @@ BString::Replace(const char* replaceThis, const char* withThis,
|
|||||||
|| FindFirst(replaceThis) < 0)
|
|| FindFirst(replaceThis) < 0)
|
||||||
return *this;
|
return *this;
|
||||||
|
|
||||||
if (_Detach() != B_OK)
|
if (_MakeWritable() != B_OK)
|
||||||
return *this;
|
return *this;
|
||||||
|
|
||||||
return _DoReplace(replaceThis, withThis, maxReplaceCount,
|
return _DoReplace(replaceThis, withThis, maxReplaceCount,
|
||||||
@@ -1192,7 +1226,7 @@ BString::IReplaceFirst(char replaceThis, char withThis)
|
|||||||
char tmp[2] = { replaceThis, '\0' };
|
char tmp[2] = { replaceThis, '\0' };
|
||||||
|
|
||||||
int32 pos = _IFindAfter(tmp, 0, 1);
|
int32 pos = _IFindAfter(tmp, 0, 1);
|
||||||
if (pos >= 0 && _Detach() == B_OK)
|
if (pos >= 0 && _MakeWritable() == B_OK)
|
||||||
fPrivateData[pos] = withThis;
|
fPrivateData[pos] = withThis;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -1204,7 +1238,7 @@ BString::IReplaceLast(char replaceThis, char withThis)
|
|||||||
char tmp[2] = { replaceThis, '\0' };
|
char tmp[2] = { replaceThis, '\0' };
|
||||||
|
|
||||||
int32 pos = _IFindBefore(tmp, Length(), 1);
|
int32 pos = _IFindBefore(tmp, Length(), 1);
|
||||||
if (pos >= 0 && _Detach() == B_OK)
|
if (pos >= 0 && _MakeWritable() == B_OK)
|
||||||
fPrivateData[pos] = withThis;
|
fPrivateData[pos] = withThis;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -1217,7 +1251,7 @@ BString::IReplaceAll(char replaceThis, char withThis, int32 fromOffset)
|
|||||||
fromOffset = min_clamp0(fromOffset, Length());
|
fromOffset = min_clamp0(fromOffset, Length());
|
||||||
int32 pos = _IFindAfter(tmp, fromOffset, 1);
|
int32 pos = _IFindAfter(tmp, fromOffset, 1);
|
||||||
|
|
||||||
if (pos >= 0 && _Detach() == B_OK) {
|
if (pos >= 0 && _MakeWritable() == B_OK) {
|
||||||
fPrivateData[pos] = withThis;
|
fPrivateData[pos] = withThis;
|
||||||
for (pos = pos;;) {
|
for (pos = pos;;) {
|
||||||
pos = _IFindAfter(tmp, pos, 1);
|
pos = _IFindAfter(tmp, pos, 1);
|
||||||
@@ -1238,7 +1272,7 @@ BString::IReplace(char replaceThis, char withThis, int32 maxReplaceCount,
|
|||||||
fromOffset = min_clamp0(fromOffset, Length());
|
fromOffset = min_clamp0(fromOffset, Length());
|
||||||
int32 pos = _IFindAfter(tmp, fromOffset, 1);
|
int32 pos = _IFindAfter(tmp, fromOffset, 1);
|
||||||
|
|
||||||
if (maxReplaceCount > 0 && pos >= 0 && _Detach() == B_OK) {
|
if (maxReplaceCount > 0 && pos >= 0 && _MakeWritable() == B_OK) {
|
||||||
fPrivateData[pos] = withThis;
|
fPrivateData[pos] = withThis;
|
||||||
maxReplaceCount--;
|
maxReplaceCount--;
|
||||||
for (pos = pos; maxReplaceCount > 0; maxReplaceCount--) {
|
for (pos = pos; maxReplaceCount > 0; maxReplaceCount--) {
|
||||||
@@ -1259,7 +1293,7 @@ BString::IReplaceFirst(const char* replaceThis, const char* withThis)
|
|||||||
if (!replaceThis || !withThis || IFindFirst(replaceThis) < 0)
|
if (!replaceThis || !withThis || IFindFirst(replaceThis) < 0)
|
||||||
return *this;
|
return *this;
|
||||||
|
|
||||||
if (_Detach() != B_OK)
|
if (_MakeWritable() != B_OK)
|
||||||
return *this;
|
return *this;
|
||||||
return _DoReplace(replaceThis, withThis, 1, 0, IGNORE_CASE);
|
return _DoReplace(replaceThis, withThis, 1, 0, IGNORE_CASE);
|
||||||
}
|
}
|
||||||
@@ -1285,7 +1319,7 @@ BString::IReplaceLast(const char* replaceThis, const char* withThis)
|
|||||||
if (!_ShrinkAtBy(pos, -difference))
|
if (!_ShrinkAtBy(pos, -difference))
|
||||||
return *this;
|
return *this;
|
||||||
} else {
|
} else {
|
||||||
if (_Detach() != B_OK)
|
if (_MakeWritable() != B_OK)
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
memcpy(fPrivateData + pos, withThis, withThisLength);
|
memcpy(fPrivateData + pos, withThis, withThisLength);
|
||||||
@@ -1302,7 +1336,7 @@ BString::IReplaceAll(const char* replaceThis, const char* withThis,
|
|||||||
if (!replaceThis || !withThis || IFindFirst(replaceThis) < 0)
|
if (!replaceThis || !withThis || IFindFirst(replaceThis) < 0)
|
||||||
return *this;
|
return *this;
|
||||||
|
|
||||||
if (_Detach() != B_OK)
|
if (_MakeWritable() != B_OK)
|
||||||
return *this;
|
return *this;
|
||||||
|
|
||||||
return _DoReplace(replaceThis, withThis, REPLACE_ALL,
|
return _DoReplace(replaceThis, withThis, REPLACE_ALL,
|
||||||
@@ -1318,7 +1352,7 @@ BString::IReplace(const char* replaceThis, const char* withThis,
|
|||||||
|| FindFirst(replaceThis) < 0)
|
|| FindFirst(replaceThis) < 0)
|
||||||
return *this;
|
return *this;
|
||||||
|
|
||||||
if (_Detach() != B_OK)
|
if (_MakeWritable() != B_OK)
|
||||||
return *this;
|
return *this;
|
||||||
|
|
||||||
return _DoReplace(replaceThis, withThis, maxReplaceCount,
|
return _DoReplace(replaceThis, withThis, maxReplaceCount,
|
||||||
@@ -1332,7 +1366,7 @@ BString::ReplaceSet(const char* setOfChars, char with)
|
|||||||
if (!setOfChars || strcspn(fPrivateData, setOfChars) >= uint32(Length()))
|
if (!setOfChars || strcspn(fPrivateData, setOfChars) >= uint32(Length()))
|
||||||
return *this;
|
return *this;
|
||||||
|
|
||||||
if (_Detach() != B_OK)
|
if (_MakeWritable() != B_OK)
|
||||||
return *this;
|
return *this;
|
||||||
|
|
||||||
int32 offset = 0;
|
int32 offset = 0;
|
||||||
@@ -1364,7 +1398,7 @@ BString::ReplaceSet(const char* setOfChars, const char* with)
|
|||||||
if (withLen == 1)
|
if (withLen == 1)
|
||||||
return ReplaceSet(setOfChars, *with);
|
return ReplaceSet(setOfChars, *with);
|
||||||
|
|
||||||
if (_Detach() != B_OK)
|
if (_MakeWritable() != B_OK)
|
||||||
return *this;
|
return *this;
|
||||||
|
|
||||||
int32 pos = 0;
|
int32 pos = 0;
|
||||||
@@ -1398,7 +1432,7 @@ BString::operator[](int32 index)
|
|||||||
char&
|
char&
|
||||||
BString::operator[](int32 index)
|
BString::operator[](int32 index)
|
||||||
{
|
{
|
||||||
if (_Detach() != B_OK) {
|
if (_MakeWritable() != B_OK) {
|
||||||
static char invalid;
|
static char invalid;
|
||||||
return invalid;
|
return invalid;
|
||||||
}
|
}
|
||||||
@@ -1421,7 +1455,7 @@ BString::LockBuffer(int32 maxLength)
|
|||||||
if (maxLength > length)
|
if (maxLength > length)
|
||||||
length = maxLength;
|
length = maxLength;
|
||||||
|
|
||||||
if (_DetachWith(fPrivateData, length) == B_OK) {
|
if (_MakeWritable(length, true) == B_OK) {
|
||||||
_ReferenceCount() = -1;
|
_ReferenceCount() = -1;
|
||||||
// mark unshareable
|
// mark unshareable
|
||||||
}
|
}
|
||||||
@@ -1436,10 +1470,10 @@ BString::UnlockBuffer(int32 length)
|
|||||||
if (length)
|
if (length)
|
||||||
length = min_clamp0(length, Length());
|
length = min_clamp0(length, Length());
|
||||||
} else {
|
} else {
|
||||||
length = (fPrivateData == NULL) ? 0 : strlen(fPrivateData);
|
length = fPrivateData == NULL ? 0 : strlen(fPrivateData);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_Realloc(length) != NULL) {
|
if (_Resize(length) != NULL) {
|
||||||
fPrivateData[length] = '\0';
|
fPrivateData[length] = '\0';
|
||||||
_ReferenceCount() = 1;
|
_ReferenceCount() = 1;
|
||||||
// mark shareable again
|
// mark shareable again
|
||||||
@@ -1456,7 +1490,7 @@ BString&
|
|||||||
BString::ToLower()
|
BString::ToLower()
|
||||||
{
|
{
|
||||||
int32 length = Length();
|
int32 length = Length();
|
||||||
if (length > 0 && _Detach() == B_OK) {
|
if (length > 0 && _MakeWritable() == B_OK) {
|
||||||
for (int32 count = 0; count < length; count++)
|
for (int32 count = 0; count < length; count++)
|
||||||
fPrivateData[count] = tolower(fPrivateData[count]);
|
fPrivateData[count] = tolower(fPrivateData[count]);
|
||||||
}
|
}
|
||||||
@@ -1468,7 +1502,7 @@ BString&
|
|||||||
BString::ToUpper()
|
BString::ToUpper()
|
||||||
{
|
{
|
||||||
int32 length = Length();
|
int32 length = Length();
|
||||||
if (length > 0 && _Detach() == B_OK) {
|
if (length > 0 && _MakeWritable() == B_OK) {
|
||||||
for (int32 count = 0; count < length; count++)
|
for (int32 count = 0; count < length; count++)
|
||||||
fPrivateData[count] = toupper(fPrivateData[count]);
|
fPrivateData[count] = toupper(fPrivateData[count]);
|
||||||
}
|
}
|
||||||
@@ -1481,7 +1515,7 @@ BString::Capitalize()
|
|||||||
{
|
{
|
||||||
int32 length = Length();
|
int32 length = Length();
|
||||||
|
|
||||||
if (length > 0 && _Detach() == B_OK) {
|
if (length > 0 && _MakeWritable() == B_OK) {
|
||||||
fPrivateData[0] = toupper(fPrivateData[0]);
|
fPrivateData[0] = toupper(fPrivateData[0]);
|
||||||
for (int32 count = 1; count < length; count++)
|
for (int32 count = 1; count < length; count++)
|
||||||
fPrivateData[count] = tolower(fPrivateData[count]);
|
fPrivateData[count] = tolower(fPrivateData[count]);
|
||||||
@@ -1495,7 +1529,7 @@ BString::CapitalizeEachWord()
|
|||||||
{
|
{
|
||||||
int32 length = Length();
|
int32 length = Length();
|
||||||
|
|
||||||
if (length > 0 && _Detach() == B_OK) {
|
if (length > 0 && _MakeWritable() == B_OK) {
|
||||||
int32 count = 0;
|
int32 count = 0;
|
||||||
do {
|
do {
|
||||||
// Find the first alphabetical character...
|
// Find the first alphabetical character...
|
||||||
@@ -1672,36 +1706,75 @@ BString::operator<<(float f)
|
|||||||
// #pragma mark - Private or reserved
|
// #pragma mark - Private or reserved
|
||||||
|
|
||||||
|
|
||||||
/*! Detaches this string from an eventually shared fPrivateData.
|
/*! Detaches this string from an eventually shared fPrivateData, ie. this makes
|
||||||
|
this string writable.
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
BString::_Detach()
|
BString::_MakeWritable()
|
||||||
{
|
{
|
||||||
char* newData = fPrivateData;
|
if (atomic_add(&_ReferenceCount(), 1) > 1) {
|
||||||
|
|
||||||
if (atomic_get(&_ReferenceCount()) > 1) {
|
|
||||||
// It might be shared, and this requires special treatment
|
// It might be shared, and this requires special treatment
|
||||||
newData = _Clone(fPrivateData, Length());
|
char* newData = _Clone(fPrivateData, Length());
|
||||||
if (atomic_add(&_ReferenceCount(), -1) == 1) {
|
if (atomic_add(&_ReferenceCount(), -2) == 1) {
|
||||||
// someone else left, we were the last owner
|
// someone else left, we were the last owner
|
||||||
_FreePrivateData();
|
_FreePrivateData();
|
||||||
}
|
}
|
||||||
}
|
if (newData == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
if (newData)
|
|
||||||
fPrivateData = newData;
|
fPrivateData = newData;
|
||||||
|
} else
|
||||||
|
atomic_add(&_ReferenceCount(), -1);
|
||||||
|
|
||||||
return newData != NULL ? B_OK : B_NO_MEMORY;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! Makes this string writable, and resizes the buffer to \a length bytes.
|
||||||
|
|
||||||
|
@param length The length of the new buffer in bytes.
|
||||||
|
@param copy If true, the current string will be copied into the new string.
|
||||||
|
*/
|
||||||
|
status_t
|
||||||
|
BString::_MakeWritable(int32 length, bool copy)
|
||||||
|
{
|
||||||
|
char* newData = NULL;
|
||||||
|
|
||||||
|
if (atomic_add(&_ReferenceCount(), 1) > 1) {
|
||||||
|
// we might share our data with someone else
|
||||||
|
if (copy)
|
||||||
|
newData = _Clone(fPrivateData, length);
|
||||||
|
else
|
||||||
|
newData = _Allocate(length);
|
||||||
|
|
||||||
|
if (atomic_add(&_ReferenceCount(), -2) == 1) {
|
||||||
|
// someone else left, we were the last owner
|
||||||
|
_FreePrivateData();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// we don't share our data with someone else
|
||||||
|
atomic_add(&_ReferenceCount(), -1);
|
||||||
|
newData = _Resize(length);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newData == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
fPrivateData = newData;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! Allocates a new private data buffer with the space to store \a length bytes,
|
||||||
|
but does not change the current one.
|
||||||
|
*/
|
||||||
char*
|
char*
|
||||||
BString::_Alloc(int32 length, bool adoptReferenceCount)
|
BString::_Allocate(int32 length)
|
||||||
{
|
{
|
||||||
if (length < 0)
|
if (length < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
char* newData = (char *)malloc(length + kPrivateDataOffset + 1);
|
char* newData = (char*)malloc(length + kPrivateDataOffset + 1);
|
||||||
if (newData == NULL)
|
if (newData == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@@ -1709,40 +1782,41 @@ BString::_Alloc(int32 length, bool adoptReferenceCount)
|
|||||||
newData[length] = '\0';
|
newData[length] = '\0';
|
||||||
|
|
||||||
// initialize reference count & length
|
// initialize reference count & length
|
||||||
int32 referenceCount = 1;
|
data_reference_count(newData) = 1;
|
||||||
if (adoptReferenceCount && fPrivateData != NULL)
|
data_length(newData) = length & 0x7fffffff;
|
||||||
referenceCount = _ReferenceCount();
|
|
||||||
|
|
||||||
*(((vint32*)newData) - 2) = referenceCount;
|
|
||||||
*(((int32*)newData) - 1) = length & 0x7fffffff;
|
|
||||||
|
|
||||||
return newData;
|
return newData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! Resizes the private data buffer. You must already have a writable buffer
|
||||||
|
when you call this method.
|
||||||
|
*/
|
||||||
char*
|
char*
|
||||||
BString::_Realloc(int32 length)
|
BString::_Resize(int32 length)
|
||||||
{
|
{
|
||||||
|
ASSERT(_ReferenceCount() == 1);
|
||||||
|
|
||||||
if (length == Length())
|
if (length == Length())
|
||||||
return fPrivateData;
|
return fPrivateData;
|
||||||
|
|
||||||
char *dataPtr = fPrivateData ? fPrivateData - kPrivateDataOffset : NULL;
|
char* data = fPrivateData ? fPrivateData - kPrivateDataOffset : NULL;
|
||||||
if (length < 0)
|
if (length < 0)
|
||||||
length = 0;
|
length = 0;
|
||||||
|
|
||||||
dataPtr = (char*)realloc(dataPtr, length + kPrivateDataOffset + 1);
|
data = (char*)realloc(data, length + kPrivateDataOffset + 1);
|
||||||
if (dataPtr) {
|
if (data == NULL)
|
||||||
int32 oldReferenceCount = _ReferenceCount();
|
return NULL;
|
||||||
|
|
||||||
dataPtr += kPrivateDataOffset;
|
data += kPrivateDataOffset;
|
||||||
|
|
||||||
fPrivateData = dataPtr;
|
fPrivateData = data;
|
||||||
fPrivateData[length] = '\0';
|
fPrivateData[length] = '\0';
|
||||||
|
|
||||||
_SetLength(length);
|
_SetLength(length);
|
||||||
_ReferenceCount() = oldReferenceCount;
|
_ReferenceCount() = 1;
|
||||||
}
|
|
||||||
return dataPtr;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1758,7 +1832,7 @@ BString::_Init(const char* src, int32 length)
|
|||||||
char*
|
char*
|
||||||
BString::_Clone(const char* data, int32 length)
|
BString::_Clone(const char* data, int32 length)
|
||||||
{
|
{
|
||||||
char* newData = _Alloc(length, false);
|
char* newData = _Allocate(length);
|
||||||
if (newData == NULL)
|
if (newData == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@@ -1776,12 +1850,12 @@ BString::_OpenAtBy(int32 offset, int32 length)
|
|||||||
{
|
{
|
||||||
int32 oldLength = Length();
|
int32 oldLength = Length();
|
||||||
|
|
||||||
if (_Detach() != B_OK)
|
if (_MakeWritable() != B_OK)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
memmove(fPrivateData + offset + length, fPrivateData + offset,
|
memmove(fPrivateData + offset + length, fPrivateData + offset,
|
||||||
oldLength - offset);
|
oldLength - offset);
|
||||||
return _Realloc(oldLength + length);
|
return _Resize(oldLength + length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1789,57 +1863,33 @@ char*
|
|||||||
BString::_ShrinkAtBy(int32 offset, int32 length)
|
BString::_ShrinkAtBy(int32 offset, int32 length)
|
||||||
{
|
{
|
||||||
int32 oldLength = Length();
|
int32 oldLength = Length();
|
||||||
if (_Detach() != B_OK)
|
if (_MakeWritable() != B_OK)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
memmove(fPrivateData + offset, fPrivateData + offset + length,
|
memmove(fPrivateData + offset, fPrivateData + offset + length,
|
||||||
oldLength - offset - length);
|
oldLength - offset - length);
|
||||||
return _Realloc(oldLength - length);
|
return _Resize(oldLength - length);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
BString::_DetachWith(const char* string, int32 length)
|
|
||||||
{
|
|
||||||
char* newData = NULL;
|
|
||||||
|
|
||||||
if (atomic_get(&_ReferenceCount()) > 1) {
|
|
||||||
// we might share our data with someone else
|
|
||||||
newData = _Clone(string, length);
|
|
||||||
if (atomic_add(&_ReferenceCount(), -1) == 1) {
|
|
||||||
// someone else left, we were the last owner
|
|
||||||
_FreePrivateData();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// we don't share our data with someone else
|
|
||||||
newData = _Realloc(length);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newData)
|
|
||||||
fPrivateData = newData;
|
|
||||||
|
|
||||||
return newData != NULL ? B_OK : B_NO_MEMORY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BString::_SetLength(int32 length)
|
BString::_SetLength(int32 length)
|
||||||
{
|
{
|
||||||
*(((int32*)fPrivateData) - 1) = length & 0x7fffffff;
|
data_length(fPrivateData) = length & 0x7fffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline int32&
|
inline vint32&
|
||||||
BString::_ReferenceCount()
|
BString::_ReferenceCount()
|
||||||
{
|
{
|
||||||
return *(((int32 *)fPrivateData) - 2);
|
return data_reference_count(fPrivateData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline const int32&
|
inline const vint32&
|
||||||
BString::_ReferenceCount() const
|
BString::_ReferenceCount() const
|
||||||
{
|
{
|
||||||
return *(((int32 *)fPrivateData) - 2);
|
return data_reference_count(fPrivateData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1864,7 +1914,7 @@ bool
|
|||||||
BString::_DoAppend(const char* string, int32 length)
|
BString::_DoAppend(const char* string, int32 length)
|
||||||
{
|
{
|
||||||
int32 oldLength = Length();
|
int32 oldLength = Length();
|
||||||
if (_DetachWith(fPrivateData, oldLength + length) == B_OK) {
|
if (_MakeWritable(oldLength + length, true) == B_OK) {
|
||||||
strncpy(fPrivateData + oldLength, string, length);
|
strncpy(fPrivateData + oldLength, string, length);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1875,8 +1925,9 @@ BString::_DoAppend(const char* string, int32 length)
|
|||||||
bool
|
bool
|
||||||
BString::_DoPrepend(const char* string, int32 length)
|
BString::_DoPrepend(const char* string, int32 length)
|
||||||
{
|
{
|
||||||
|
// TODO: this could be optimized (allocate a new buffer, use memcpy())
|
||||||
int32 oldLength = Length();
|
int32 oldLength = Length();
|
||||||
if (_DetachWith(fPrivateData, oldLength + length) == B_OK) {
|
if (_MakeWritable(oldLength + length, true) == B_OK) {
|
||||||
memmove(fPrivateData + length, fPrivateData, oldLength);
|
memmove(fPrivateData + length, fPrivateData, oldLength);
|
||||||
if (string && length)
|
if (string && length)
|
||||||
strncpy(fPrivateData, string, length);
|
strncpy(fPrivateData, string, length);
|
||||||
@@ -1890,10 +1941,10 @@ bool
|
|||||||
BString::_DoInsert(const char* string, int32 offset, int32 length)
|
BString::_DoInsert(const char* string, int32 offset, int32 length)
|
||||||
{
|
{
|
||||||
int32 oldLength = Length();
|
int32 oldLength = Length();
|
||||||
if (_DetachWith(fPrivateData, oldLength + length) == B_OK) {
|
if (_MakeWritable(oldLength + length, true) == B_OK) {
|
||||||
memmove(fPrivateData + offset + length, fPrivateData + offset,
|
memmove(fPrivateData + offset + length, fPrivateData + offset,
|
||||||
oldLength - offset);
|
oldLength - offset);
|
||||||
if (string && length)
|
if (string != NULL && length)
|
||||||
strncpy(fPrivateData + offset, string, length);
|
strncpy(fPrivateData + offset, string, length);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1904,7 +1955,7 @@ BString::_DoInsert(const char* string, int32 offset, int32 length)
|
|||||||
int32
|
int32
|
||||||
BString::_ShortFindAfter(const char* string, int32 len) const
|
BString::_ShortFindAfter(const char* string, int32 len) const
|
||||||
{
|
{
|
||||||
const char *ptr = strstr(String(), string);
|
const char* ptr = strstr(String(), string);
|
||||||
|
|
||||||
if (ptr != NULL)
|
if (ptr != NULL)
|
||||||
return ptr - String();
|
return ptr - String();
|
||||||
@@ -1914,9 +1965,9 @@ BString::_ShortFindAfter(const char* string, int32 len) const
|
|||||||
|
|
||||||
|
|
||||||
int32
|
int32
|
||||||
BString::_FindAfter(const char* string, int32 offset, int32 strlen) const
|
BString::_FindAfter(const char* string, int32 offset, int32 length) const
|
||||||
{
|
{
|
||||||
const char *ptr = strstr(String() + offset, string);
|
const char* ptr = strstr(String() + offset, string);
|
||||||
|
|
||||||
if (ptr != NULL)
|
if (ptr != NULL)
|
||||||
return ptr - String();
|
return ptr - String();
|
||||||
@@ -1926,9 +1977,9 @@ BString::_FindAfter(const char* string, int32 offset, int32 strlen) const
|
|||||||
|
|
||||||
|
|
||||||
int32
|
int32
|
||||||
BString::_IFindAfter(const char* string, int32 offset, int32 strlen) const
|
BString::_IFindAfter(const char* string, int32 offset, int32 length) const
|
||||||
{
|
{
|
||||||
const char *ptr = strcasestr(String() + offset, string);
|
const char* ptr = strcasestr(String() + offset, string);
|
||||||
|
|
||||||
if (ptr != NULL)
|
if (ptr != NULL)
|
||||||
return ptr - String();
|
return ptr - String();
|
||||||
@@ -1938,13 +1989,13 @@ BString::_IFindAfter(const char* string, int32 offset, int32 strlen) const
|
|||||||
|
|
||||||
|
|
||||||
int32
|
int32
|
||||||
BString::_FindBefore(const char* string, int32 offset, int32 strlen) const
|
BString::_FindBefore(const char* string, int32 offset, int32 length) const
|
||||||
{
|
{
|
||||||
if (fPrivateData) {
|
if (fPrivateData != NULL) {
|
||||||
const char *ptr = fPrivateData + offset - strlen;
|
const char* ptr = fPrivateData + offset - length;
|
||||||
|
|
||||||
while (ptr >= fPrivateData) {
|
while (ptr >= fPrivateData) {
|
||||||
if (!memcmp(ptr, string, strlen))
|
if (!memcmp(ptr, string, length))
|
||||||
return ptr - fPrivateData;
|
return ptr - fPrivateData;
|
||||||
ptr--;
|
ptr--;
|
||||||
}
|
}
|
||||||
@@ -1954,13 +2005,13 @@ BString::_FindBefore(const char* string, int32 offset, int32 strlen) const
|
|||||||
|
|
||||||
|
|
||||||
int32
|
int32
|
||||||
BString::_IFindBefore(const char* string, int32 offset, int32 strlen) const
|
BString::_IFindBefore(const char* string, int32 offset, int32 length) const
|
||||||
{
|
{
|
||||||
if (fPrivateData) {
|
if (fPrivateData != NULL) {
|
||||||
char *ptr1 = fPrivateData + offset - strlen;
|
char* ptr1 = fPrivateData + offset - length;
|
||||||
|
|
||||||
while (ptr1 >= fPrivateData) {
|
while (ptr1 >= fPrivateData) {
|
||||||
if (!strncasecmp(ptr1, string, strlen))
|
if (!strncasecmp(ptr1, string, length))
|
||||||
return ptr1 - fPrivateData;
|
return ptr1 - fPrivateData;
|
||||||
ptr1--;
|
ptr1--;
|
||||||
}
|
}
|
||||||
@@ -1973,30 +2024,28 @@ BString&
|
|||||||
BString::_DoCharacterEscape(const char* string, const char* setOfCharsToEscape,
|
BString::_DoCharacterEscape(const char* string, const char* setOfCharsToEscape,
|
||||||
char escapeChar)
|
char escapeChar)
|
||||||
{
|
{
|
||||||
if (_DetachWith(string, strlen(safestr(string))) != B_OK)
|
if (_MakeWritable(string_length(string), false) != B_OK)
|
||||||
return *this;
|
return *this;
|
||||||
|
|
||||||
memcpy(fPrivateData, string, Length());
|
memcpy(fPrivateData, string, Length());
|
||||||
|
|
||||||
PosVect positions;
|
PosVect positions;
|
||||||
int32 length = Length();
|
int32 length = Length();
|
||||||
int32 pos = 0;
|
int32 pos;
|
||||||
for (int32 offset = 0; offset < length; offset += pos + 1) {
|
for (int32 offset = 0; offset < length; offset += pos + 1) {
|
||||||
if ((pos = strcspn(fPrivateData + offset, setOfCharsToEscape))
|
pos = strcspn(fPrivateData + offset, setOfCharsToEscape);
|
||||||
< length - offset) {
|
if (pos < length - offset && !positions.Add(offset + pos))
|
||||||
if (!positions.Add(offset + pos))
|
return *this;
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 count = positions.CountItems();
|
uint32 count = positions.CountItems();
|
||||||
int32 newLength = length + count;
|
int32 newLength = length + count;
|
||||||
if (!newLength) {
|
if (!newLength) {
|
||||||
_Realloc(0);
|
_Resize(0);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* newData = _Alloc(newLength);
|
char* newData = _Allocate(newLength);
|
||||||
if (newData) {
|
if (newData) {
|
||||||
char* oldString = fPrivateData;
|
char* oldString = fPrivateData;
|
||||||
char* newString = newData;
|
char* newString = newData;
|
||||||
@@ -2029,7 +2078,7 @@ BString::_DoCharacterEscape(const char* string, const char* setOfCharsToEscape,
|
|||||||
BString&
|
BString&
|
||||||
BString::_DoCharacterDeescape(const char* string, char escapeChar)
|
BString::_DoCharacterDeescape(const char* string, char escapeChar)
|
||||||
{
|
{
|
||||||
if (_DetachWith(string, strlen(safestr(string))) != B_OK)
|
if (_MakeWritable(string_length(string), false) != B_OK)
|
||||||
return *this;
|
return *this;
|
||||||
|
|
||||||
memcpy(fPrivateData, string, Length());
|
memcpy(fPrivateData, string, Length());
|
||||||
@@ -2047,8 +2096,8 @@ BString::_DoReplace(const char* findThis, const char* replaceWith,
|
|||||||
return *this;
|
return *this;
|
||||||
|
|
||||||
typedef int32 (BString::*TFindMethod)(const char*, int32, int32) const;
|
typedef int32 (BString::*TFindMethod)(const char*, int32, int32) const;
|
||||||
TFindMethod findMethod = ignoreCase ? &BString::_IFindAfter
|
TFindMethod findMethod = ignoreCase
|
||||||
: &BString::_FindAfter;
|
? &BString::_IFindAfter : &BString::_FindAfter;
|
||||||
int32 findLen = strlen(findThis);
|
int32 findLen = strlen(findThis);
|
||||||
|
|
||||||
if (!replaceWith)
|
if (!replaceWith)
|
||||||
@@ -2076,16 +2125,16 @@ BString::_ReplaceAtPositions(const PosVect* positions, int32 searchLength,
|
|||||||
uint32 count = positions->CountItems();
|
uint32 count = positions->CountItems();
|
||||||
int32 newLength = length + count * (withLength - searchLength);
|
int32 newLength = length + count * (withLength - searchLength);
|
||||||
if (!newLength) {
|
if (!newLength) {
|
||||||
_Realloc(0);
|
_Resize(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *newData = _Alloc(newLength);
|
char* newData = _Allocate(newLength);
|
||||||
if (newData == NULL)
|
if (newData == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
char *oldString = fPrivateData;
|
char* oldString = fPrivateData;
|
||||||
char *newString = newData;
|
char* newString = newData;
|
||||||
int32 lastPos = 0;
|
int32 lastPos = 0;
|
||||||
|
|
||||||
for (uint32 i = 0; i < count; ++i) {
|
for (uint32 i = 0; i < count; ++i) {
|
||||||
@@ -2114,8 +2163,7 @@ BString::_ReplaceAtPositions(const PosVect* positions, int32 searchLength,
|
|||||||
// #pragma mark - backwards compatibility
|
// #pragma mark - backwards compatibility
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*! Translates to (missing const):
|
||||||
Translates to (missing const):
|
|
||||||
BString& BString::operator<<(BString& string)
|
BString& BString::operator<<(BString& string)
|
||||||
*/
|
*/
|
||||||
extern "C" BString&
|
extern "C" BString&
|
||||||
@@ -2129,28 +2177,28 @@ __ls__7BStringR7BString(BString* self, BString& string)
|
|||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
Compare(const BString &string1, const BString &string2)
|
Compare(const BString& string1, const BString& string2)
|
||||||
{
|
{
|
||||||
return strcmp(string1.String(), string2.String());
|
return strcmp(string1.String(), string2.String());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
ICompare(const BString &string1, const BString &string2)
|
ICompare(const BString& string1, const BString& string2)
|
||||||
{
|
{
|
||||||
return strcasecmp(string1.String(), string2.String());
|
return strcasecmp(string1.String(), string2.String());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
Compare(const BString *string1, const BString *string2)
|
Compare(const BString* string1, const BString* string2)
|
||||||
{
|
{
|
||||||
return strcmp(string1->String(), string2->String());
|
return strcmp(string1->String(), string2->String());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
ICompare(const BString *string1, const BString *string2)
|
ICompare(const BString* string1, const BString* string2)
|
||||||
{
|
{
|
||||||
return strcasecmp(string1->String(), string2->String());
|
return strcasecmp(string1->String(), string2->String());
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user