Index: headers/os/support/String.h
===================================================================
--- headers/os/support/String.h	(Revision 23958)
+++ headers/os/support/String.h	(Arbeitskopie)
@@ -1,7 +1,7 @@
 /*
- * Copyright 2001-2007, Haiku Inc. All Rights Reserved.
- * Distributed under the terms of the MIT License.
- */
+* Copyright 2001-2008, Haiku Inc. All Rights Reserved.
+* Distributed under the terms of the MIT License.
+*/
 #ifndef __BSTRING__
 #define __BSTRING__
 
@@ -11,252 +11,256 @@
 #include <string.h>
 
 
-class BString {
-	public:
-		BString();
-		BString(const char* string);
-		BString(const BString& string);
-		BString(const char* string, int32 maxLength);
-		~BString();
+class BStringRef;
 
-		// Access
-		const char*		String() const;
 
-		int32 			Length() const;
-							// length of corresponding string
-		int32			CountChars() const;
-							// returns number of UTF8 characters in string
+class BString
+{
+public:
+				BString();
+				BString(const char* string);
+				BString(const BString& string);
+				BString(const char* string, int32 maxLength);
+				~BString();
 
-		// Assignment
-		BString&		operator=(const BString& string);
-		BString&		operator=(const char* string);
-		BString&		operator=(char c);
+	// Access
+	const char*	String() const;
+	int32 		Length() const;
+	int32		CountChars() const;
+	int32 		ReferenceCount() const;
 
-		BString&		SetTo(const char* string);
-		BString&		SetTo(const char* string, int32 maxLength);
+	// Assignment
+	BString&	operator=(const BString& string);
+	BString&	operator=(const char* string);
+	BString&	operator=(char c);
 
-		BString&		SetTo(const BString& string);
-		BString&		Adopt(BString& from);
+	BString&	SetTo(const char* string);
+	BString&	SetTo(const char* string, int32 maxLength);
 
-		BString&		SetTo(const BString& string, int32 maxLength);
-		BString&		Adopt(BString& from, int32 maxLength);
+	BString&	SetTo(const BString& string);
+	BString&	Adopt(BString& from);
 
-		BString&		SetTo(char c, int32 count);
+	BString&	SetTo(const BString& string, int32 maxLength);
+	BString&	Adopt(BString& from, int32 maxLength);
 
-		// Substring copying
-		BString&		CopyInto(BString& into, int32 fromOffset,
-							int32 length) const;
-		void			CopyInto(char* into, int32 fromOffset,
-							int32 length) const;
+	BString&	SetTo(char c, int32 count);
 
-		// Appending
-		BString&		operator+=(const BString& string);
-		BString&		operator+=(const char* string);
-		BString&		operator+=(char c);
+	// Substring copying
+	BString&	CopyInto(BString& into, int32 fromOffset, int32 length) const;
+	void		CopyInto(char* into, int32 fromOffset, int32 length) const;
 
-		BString&		Append(const BString& string);
-		BString&		Append(const char* string);
+	// Appending
+	BString&	operator+=(const BString& string);
+	BString&	operator+=(const char* string);
+	BString&	operator+=(char c);
 
-		BString&		Append(const BString& string, int32 length);
-		BString&		Append(const char* string, int32 length);
-		BString&		Append(char c, int32 count);
+	BString&	Append(const BString& string);
+	BString&	Append(const char* string);
 
-		// 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&	Append(const BString& string, int32 length);
+	BString&	Append(const char* string, int32 length);
+	BString&	Append(char c, int32 count);
 
-		// Inserting
-		BString&		Insert(const char* string, int32 pos);
-		BString&		Insert(const char* string, int32 length, int32 pos);
-		BString&		Insert(const char* string, int32 fromOffset,
-							int32 length, int32 pos);
+	// 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&		Insert(const BString& string, int32 pos);
-		BString&		Insert(const BString& string, int32 length, int32 pos);
-		BString&		Insert(const BString& string, int32 fromOffset,
-							int32 length, int32 pos);
-		BString&		Insert(char, int32 count, int32 pos);
+	// 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);
 
-		// Removing
-		BString&		Truncate(int32 newLength, bool lazy = true);
-		BString&		Remove(int32 from, int32 length);
+	// Removing
+	BString&	Truncate(int32 newLength, bool lazy = true);
+	BString&	Remove(int32 from, int32 length);
 
-		BString&		RemoveFirst(const BString& string);
-		BString&		RemoveLast(const BString& string);
-		BString&		RemoveAll(const BString& string);
+	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&	RemoveFirst(const char* string);
+	BString&	RemoveLast(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);
-		void			MoveInto(char* into, int32 from, int32 length);
+	BString& 	MoveInto(BString& into, int32 from, int32 length);
+	void		MoveInto(char* into, int32 from, int32 length);
 
-		// 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;
+	// 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;
+	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
-		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				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;
+	// 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			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;
+	// 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			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		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			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		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;
+	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;
 
-		// 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);
+	// 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&		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&	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* setOfChars, char with);
-		BString&		ReplaceSet(const char* setOfChars, const char *with);
+	BString&	ReplaceSet(const char* setOfChars, char with);
+	BString&	ReplaceSet(const char* setOfChars, const char* with);
 
-		// Unchecked char access
-		char 			operator[](int32 index) const;
-		char& 			operator[](int32 index);
+	// Unchecked char access
+	char	 	operator[](int32 index) const;
 
-		// Checked char access
-		char			ByteAt(int32 index) const;
+#if __GNUC__ > 3
+	BStringRef  operator[](int32 index);
+#else
+	char& 		operator[](int32 index);
+#endif
 
-		// Fast low-level manipulation
-		char*			LockBuffer(int32 maxLength);
-		BString&		UnlockBuffer(int32 length = -1);
+	// Checked char access
+	char		ByteAt(int32 index) const;
 
-		// Upercase <-> Lowercase
-		BString&		ToLower();
-		BString&		ToUpper();
+	// Fast low-level manipulation
+	char*		LockBuffer(int32 maxLength);
+	BString&	UnlockBuffer(int32 length = -1);
 
-		BString&		Capitalize();
-		BString&		CapitalizeEachWord();
+	// Upercase <-> Lowercase
+	BString&	ToLower();
+	BString&	ToUpper();
 
-		// Escaping and De-escaping
-		BString&		CharacterEscape(const char* original,
-							const char* setOfCharsToEscape, char escapeWith);
-		BString&		CharacterEscape(const char* setOfCharsToEscape,
-							char escapeWith);
+	BString&	Capitalize();
+	BString&	CapitalizeEachWord();
 
-		BString&		CharacterDeescape(const char* original, char escapeChar);
-		BString&		CharacterDeescape(char escapeChar);
+	// 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);
 
-		// Slower than sprintf() but type and overflow safe
-		BString&		operator<<(const char* string);
-		BString&		operator<<(const BString& string);
-		BString&		operator<<(char c);
-		BString&		operator<<(int value);
-		BString&		operator<<(unsigned int value);
-		BString&		operator<<(uint32 value);
-		BString&		operator<<(int32 value);
-		BString&		operator<<(uint64 value);
-		BString&		operator<<(int64 value);
-		BString&		operator<<(float value);
-			// float output hardcodes %.2f style formatting
+	// Insert
+	BString&	operator<<(const char* string);
+	BString&	operator<<(const BString& string);
+	BString&	operator<<(char c);
+	BString&	operator<<(int value);
+	BString&	operator<<(unsigned int value);
+	BString&	operator<<(uint32 value);
+	BString&	operator<<(int32 value);
+	BString&	operator<<(uint64 value);
+	BString&	operator<<(int64 value);
+	// float output hardcodes %.2f style formatting
+	BString&	operator<<(float value);
 
-	private:
-		void			_Init(const char *, int32);
-		void			_DoAssign(const char *, int32);
-		void			_DoAppend(const char *, int32);
-		char*			_GrowBy(int32);
-		char*			_OpenAtBy(int32, int32);
-		char*			_ShrinkAtBy(int32, int32);
-		void			_DoPrepend(const char *, int32);
+private:
+	class PosVect;
+	friend class BStringRef;
 
-		int32			_FindAfter(const char *, int32, int32) const;
-		int32			_IFindAfter(const char *, int32, int32) const;
-		int32			_ShortFindAfter(const char *, int32) const;
-		int32			_FindBefore(const char *, int32, int32) const;
-		int32			_IFindBefore(const char *, int32, int32) const;
-		BString&		_DoReplace(const char *, const char *, int32, int32,
-							bool);
-		void 			_SetLength(int32);
+	// Management
+	status_t	_Detach();
+	char*		_Realloc(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);
+	status_t	_DetachWith(const char* string, int32 length);
 
-#if DEBUG
-		void			_SetUsingAsCString(bool);
-		void 			_AssertNotUsingAsCString() const;
-#else
-		void 			_SetUsingAsCString(bool) {}
-		void			_AssertNotUsingAsCString() const {}
-#endif
+	// Data
+	void		_SetLength(int32 length);
+	void		_SetReferenceCount(int32 count);
+	bool		_DoAppend(const char* string, int32 length);
+	bool		_DoPrepend(const char* string, int32 length);
+	bool		_DoInsert(const char* string, int32 offset, int32 length);
 
-		char*			_Alloc(int32 size);
+	// Search
+	int32		_ShortFindAfter(const char* string, int32 len) const;
+	int32		_FindAfter(const char* string, int32 offset, int32 strlen) const;
+	int32		_IFindAfter(const char* string, int32 offset, int32 strlen) const;
 
-		class PosVect;
-		void			_ReplaceAtPositions(const PosVect* positions,
-						   int32 searchLength, const char* with, int32 withLen);
+	int32		_FindBefore(const char* string, int32 offset, int32 strlen) const;
+	int32		_IFindBefore(const char* string, int32 offset, int32 strlen) const;
 
-	protected:
-		char*	fPrivateData;
+	// 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 searchLen,
+					const char* with, int32 withLen);
+
+private:
+	char*	            fPrivateData;
 };
 
+
 // Commutative compare operators
 bool operator<(const char* a, const BString& b);
 bool operator<=(const char* a, const BString& b);
@@ -265,6 +269,7 @@
 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);
@@ -272,16 +277,16 @@
 int ICompare(const BString* a, const BString* b);
 
 
-inline int32 
+inline int32
 BString::Length() const
 {
-	return fPrivateData ? (*((int32 *)fPrivateData - 1) & 0x7fffffff) : 0;
-		/* the most significant bit is reserved; accessing
-		 * it in any way will cause the computer to explode
-		 */
+	// 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 const char *
+
+inline const char*
 BString::String() const
 {
 	if (!fPrivateData)
@@ -289,19 +294,29 @@
 	return fPrivateData;
 }
 
+
+inline int32
+BString::ReferenceCount() const
+{
+	return fPrivateData ? (*(((int32 *)fPrivateData) - 2)) : 1;
+}
+
+
 inline BString &
-BString::SetTo(const char *string)
+BString::SetTo(const char* string)
 {
 	return operator=(string);
 }
 
-inline char 
+
+inline char
 BString::operator[](int32 index) const
 {
 	return fPrivateData[index];
 }
 
-inline char 
+
+inline char
 BString::ByteAt(int32 index) const
 {
 	if (!fPrivateData || index < 0 || index > Length())
@@ -309,6 +324,7 @@
 	return fPrivateData[index];
 }
 
+
 inline BString &
 BString::operator+=(const BString &string)
 {
@@ -316,6 +332,7 @@
 	return *this;
 }
 
+
 inline BString &
 BString::Append(const BString &string)
 {
@@ -323,88 +340,125 @@
 	return *this;
 }
 
+
 inline BString &
-BString::Append(const char *str)
+BString::Append(const char* string)
 {
-	return operator+=(str);
+	return operator+=(string);
 }
 
-inline bool 
+
+inline bool
 BString::operator==(const BString &string) const
 {
 	return strcmp(String(), string.String()) == 0;
 }
 
-inline bool 
+
+inline bool
 BString::operator<(const BString &string) const
 {
 	return strcmp(String(), string.String()) < 0;
 }
 
-inline bool 
+
+inline bool
 BString::operator<=(const BString &string) const
 {
 	return strcmp(String(), string.String()) <= 0;
 }
 
-inline bool 
+
+inline bool
 BString::operator>=(const BString &string) const
 {
 	return strcmp(String(), string.String()) >= 0;
 }
 
-inline bool 
+
+inline bool
 BString::operator>(const BString &string) const
 {
 	return strcmp(String(), string.String()) > 0;
 }
 
-inline bool 
+
+inline bool
 BString::operator!=(const BString &string) const
 {
 	return strcmp(String(), string.String()) != 0;
 }
 
-inline bool 
-BString::operator!=(const char *str) const
+
+inline bool
+BString::operator!=(const char* string) const
 {
-	return !operator==(str);
+	return !operator==(string);
 }
 
-inline bool 
+
+inline bool
 operator<(const char *str, const BString &string)
 {
 	return string > str;
 }
 
-inline bool 
+
+inline bool
 operator<=(const char *str, const BString &string)
 {
 	return string >= str;
 }
 
-inline bool 
+
+inline bool
 operator==(const char *str, const BString &string)
 {
 	return string == str;
 }
 
-inline bool 
+
+inline bool
 operator>(const char *str, const BString &string)
 {
 	return string < str;
 }
 
-inline bool 
+
+inline bool
 operator>=(const char *str, const BString &string)
 {
 	return string <= str;
 }
 
-inline bool 
+
+inline bool
 operator!=(const char *str, const BString &string)
 {
 	return string != str;
 }
 
-#endif /* __BSTRING__ */
+
+//	#pragma mark - BStringRef
+
+
+class BStringRef
+{
+public:
+	BStringRef(BString& string, int32 position);
+	~BStringRef() {}
+	
+	operator char() const;
+
+	char* operator&();
+	const char* operator&() const;
+
+	BStringRef& operator=(char c);
+	BStringRef &operator=(const BStringRef &rc);
+
+private:
+	BString&	fString;
+	int32		fPosition;
+};
+
+#endif	// __BSTRING__
Index: src/kits/support/String.cpp
===================================================================
--- src/kits/support/String.cpp	(Revision 23958)
+++ src/kits/support/String.cpp	(Arbeitskopie)
@@ -1,13 +1,14 @@
 /*
- * Copyright 2001-2007, Haiku, Inc. All Rights Reserved.
- * Distributed under the terms of the MIT License.
- *
- * Authors:
- *		Marc Flerackers (mflerackers@androme.be)
- *		Stefano Ceccherini (burton666@libero.it)
- *		Oliver Tappe (openbeos@hirschkaefer.de)
- *		Axel Dörfler, axeld@pinc-software.de
- */
+* Copyright 2001-2008, Haiku, Inc. All Rights Reserved.
+* Distributed under the terms of the MIT License.
+*
+* Authors:
+*		Marc Flerackers (mflerackers@androme.be)
+*		Stefano Ceccherini (burton666@libero.it)
+*		Oliver Tappe (openbeos@hirschkaefer.de)
+*		Axel D�rfler, axeld@pinc-software.de
+*		Julun <host.haiku@gmx.de>
+*/
 
 /* String class supporting common string operations. */
 
@@ -31,59 +32,13 @@
 #define REPLACE_ALL 0x7FFFFFFF
 
 
-// helper macro that is used to fall into debugger if a given param check fails:
-#ifdef DEBUG
-	#define CHECK_PARAM( expr, msg) \
-	if (!(expr)) \
-		debugger( msg)
-
-	#define CHECK_PARAM_RET( expr, msg, retval) \
-	if (!(expr)) \
-		debugger( msg)
-
-	#define CHECK_PARAM_VOID( expr, msg) \
-	if (!(expr)) \
-		debugger( msg)
-#else
-	#define CHECK_PARAM( expr, msg) \
-	if (!(expr)) \
-		return *this
-
-	#define CHECK_PARAM_RET( expr, msg, retval) \
-	if (!(expr)) \
-		return (retval);
-
-	#define CHECK_PARAM_VOID( expr, msg) 
-#endif
-
-
-//! helper class for BString::_ReplaceAtPositions():
-class BString::PosVect {
-	public:
-		PosVect();
-		~PosVect();
-
-		bool Add(int32 pos);
-
-		inline int32 ItemAt(int32 index) const
-			{ return fBuffer[index]; }
-		inline int32 CountItems() const
-			{ return fSize; }
-
-	private:
-		int32	fSize;
-		int32	fBufferSize;
-		int32*	fBuffer;
-};
-
-
 const char *B_EMPTY_STRING = "";
 
 
 // helper function, returns minimum of two given values (but clamps to 0):
 static inline int32
-min_clamp0(int32 num1, int32 num2) 
-{ 
+min_clamp0(int32 num1, int32 num2)
+{
 	if (num1 < num2)
 		return num1 > 0 ? num1 : 0;
 
@@ -93,7 +48,7 @@
 
 //! helper function, returns length of given string (but clamps to given maximum):
 static inline int32
-strlen_clamp(const char* str, int32 max) 
+strlen_clamp(const char* str, int32 max)
 {
 	// this should yield 0 for max<0:
 	int32 length = 0;
@@ -105,92 +60,151 @@
 
 
 //! helper function, massages given pointer into a legal c-string:
-static inline const char * 
-safestr(const char* str) 
+static inline const char *
+safestr(const char* str)
 {
 	return str ? str : "";
 }
 
 
-//	#pragma mark -
+//	#pragma mark - PosVect
 
 
-BString::PosVect::PosVect()
-	:
-	fSize(0),
-	fBufferSize(20),
-	fBuffer(NULL)
+class BString::PosVect {
+public:
+	PosVect()
+		: fSize(0),
+		fBufferSize(20),
+		fBuffer(NULL)	{ }
+
+	~PosVect()
+	{
+		free(fBuffer);
+	}
+
+	bool Add(int32 pos)
+	{
+		if (fBuffer == NULL || fSize == fBufferSize) {
+			if (fBuffer != NULL)
+				fBufferSize *= 2;
+
+			int32* newBuffer = NULL;
+			newBuffer = (int32 *)realloc(fBuffer, fBufferSize * sizeof(int32));
+			if (newBuffer == NULL)
+				return false;
+
+			fBuffer = newBuffer;
+		}
+
+		fBuffer[fSize++] = pos;
+		return true;
+	}
+
+	inline int32 ItemAt(int32 index) const
+	{ return fBuffer[index]; }
+	inline int32 CountItems() const
+	{ return fSize; }
+
+private:
+	int32	fSize;
+	int32	fBufferSize;
+	int32*	fBuffer;
+};
+
+
+//	#pragma mark - BStringRef
+
+
+BStringRef::BStringRef(BString& string, int32 position)
+	: fString(string), fPosition(position)
 {
 }
 
 
-BString::PosVect::~PosVect()
+BStringRef::operator char() const
 {
-	free(fBuffer);
+	return fPosition < fString.Length() ? fString.fPrivateData[fPosition] : 0;
 }
 
 
-bool
-BString::PosVect::Add(int32 pos)
+BStringRef&
+BStringRef::operator=(char c)
 {
-	if (fBuffer == NULL || fSize == fBufferSize) {
-		if (fBuffer != NULL)
-			fBufferSize *= 2;
+	fString._Detach();
+	fString.fPrivateData[fPosition] = c;
+	return *this;
+}
 
-		int32* newBuffer = (int32 *)realloc(fBuffer, fBufferSize * sizeof(int32));
-		if (newBuffer == NULL)
-			return false;
 
-		fBuffer = newBuffer;
-	}
+BStringRef&
+BStringRef::operator=(const BStringRef &rc)
+{
+	return operator=(rc.fString.fPrivateData[rc.fPosition]);
+}
 
-	fBuffer[fSize++] = pos;
-	return true;
+
+const char*
+BStringRef::operator&() const
+{
+	return &(fString.fPrivateData[fPosition]);
 }
 
 
+char*
+BStringRef::operator&()
+{
+	fString._Detach();
+	fString._SetReferenceCount(-1);
+	return &(fString.fPrivateData[fPosition]);
+}
+
+
 //	#pragma mark - BString
 
 
 BString::BString()
-	: fPrivateData(NULL)	
+	: fPrivateData(NULL)
 {
+	_Init("", 0);
 }
 
 
 BString::BString(const char* string)
 	: fPrivateData(NULL)
 {
-	if (string != NULL)
-		_Init(string, strlen(string));
+	_Init(string, strlen(safestr(string)));
 }
 
 
-BString::BString(const BString &string)
-	: fPrivateData(NULL)			
+BString::BString(const BString& string)
+	: fPrivateData(NULL)
 {
-	_Init(string.String(), string.Length());
+	// check if source is sharable - if so, share else clone
+	if (atomic_get(&(*(((vint32*)string.fPrivateData) - 2))) >= 0) {
+		fPrivateData = string.fPrivateData;
+		atomic_add(&(*(((vint32*)fPrivateData) - 2)), 1);
+	} else
+		fPrivateData = _Clone(string.fPrivateData, string.Length());
 }
 
 
-BString::BString(const char *string, int32 maxLength)
-	: fPrivateData(NULL)		
+BString::BString(const char* string, int32 maxLength)
+	: fPrivateData(NULL)
 {
-	if (string != NULL)
-		_Init(string, strlen_clamp(string, maxLength));
+	_Init(string, strlen_clamp(safestr(string), maxLength));
 }
 
 
 BString::~BString()
 {
-	if (fPrivateData)
-		free(fPrivateData - sizeof(int32));
+	if (atomic_add(&(*(((vint32*)fPrivateData) - 2)), -1) < 1)
+		free(fPrivateData - (2 * sizeof(int32)));
 }
 
 
 //	#pragma mark - Access
 
-		
+
 int32
 BString::CountChars() const
 {
@@ -214,22 +228,17 @@
 
 
 BString&
-BString::operator=(const BString &string)
+BString::operator=(const BString& string)
 {
-	if (&string != this) // Avoid auto-assignment
-		_DoAssign(string.String(), string.Length());
-	return *this;
+	return SetTo(string);
 }
 
 
 BString&
-BString::operator=(const char *str)
+BString::operator=(const char* string)
 {
-	if (str != NULL)
-		_DoAssign(str, strlen(str));	
-	else
-		_Alloc(0);
-
+	if (string)
+		SetTo(string, strlen(string));
 	return *this;
 }
 
@@ -237,80 +246,84 @@
 BString&
 BString::operator=(char c)
 {
-	_DoAssign(&c, 1);
-	return *this;
+	return SetTo(c, 1);
 }
 
 
 BString&
-BString::SetTo(const char *str, int32 maxLength)
+BString::SetTo(const char* string, int32 maxLength)
 {
-	if (str != NULL)
-		_DoAssign(str, strlen_clamp(str, maxLength));
-	else
-		_Alloc(0);
+	maxLength = strlen_clamp(safestr(string), maxLength);
+	if (_DetachWith("", maxLength) == B_OK)
+		memcpy(fPrivateData, string, maxLength);
 
 	return *this;
 }
 
 
 BString&
-BString::SetTo(const BString &from)
+BString::SetTo(const BString& string)
 {
-	if (&from != this) {
-		// Avoid auto-assignment
-		_DoAssign(from.String(), from.Length());
+	// we share the information already
+	if (fPrivateData == string.fPrivateData)
+		return *this;
+
+	// check if we are shared by someone else
+	if (atomic_get(&(*(((vint32*)fPrivateData) - 2))) > 1) {
+		// we share our data with someone else
+		if (atomic_add(&(*((vint32*)fPrivateData - 2)), -1) < 1) {
+			// someone else decrement, we are the last owner
+			free(fPrivateData - (2 * sizeof(int32)));
+		} else {
+			; // there is still someone who shares our data
+		}
+	} else {
+		// we don't share our data with someone else
+		// or we are marked as unsharable, but this will go away
+		free(fPrivateData - (2 * sizeof(int32)));
 	}
+
+	// if source is sharable share, otherwise clone
+	if (atomic_get(&(*(((vint32*)string.fPrivateData) - 2))) >= 0) {
+		fPrivateData = string.fPrivateData;
+		atomic_add(&(*(((vint32*)fPrivateData) - 2)), 1);
+	} else
+		fPrivateData = _Clone(string.fPrivateData, string.Length());
+
 	return *this;
 }
 
 
 BString&
-BString::Adopt(BString &from)
+BString::Adopt(BString& from)
 {
-	if (&from == this) {
-		// Avoid auto-adoption
-		return *this;
-	}
+	SetTo(from);
+	from.SetTo("");
 
-	if (fPrivateData)
-		free(fPrivateData - sizeof(int32));
-
-	/* "steal" the data from the given BString */
-	fPrivateData = from.fPrivateData;
-	from.fPrivateData = NULL;
-
 	return *this;
 }
 
 
 BString&
-BString::SetTo(const BString &string, int32 length)
+BString::SetTo(const BString& string, int32 maxLength)
 {
-	if (&string != this) // Avoid auto-assignment
-		_DoAssign(string.String(), min_clamp0(length, string.Length()));
+	if (fPrivateData != string.fPrivateData
+		// make sure we reassing in case length is different
+		|| (fPrivateData == string.fPrivateData && Length() != maxLength)) {
+			maxLength = min_clamp0(maxLength, string.Length());
+			if (_DetachWith("", maxLength) == B_OK)
+				memcpy(fPrivateData, string.fPrivateData, maxLength);
+	}
 	return *this;
 }
 
 
 BString&
-BString::Adopt(BString &from, int32 length)
+BString::Adopt(BString& from, int32 maxLength)
 {
-	if (&from == this) // Avoid auto-adoption
-		return *this;
+	SetTo(from, maxLength);
+	from.SetTo("");
 
-	int32 len = min_clamp0(length, from.Length());
-
-	if (fPrivateData)
-		free(fPrivateData - sizeof(int32));
-
-	/* "steal" the data from the given BString */
-	fPrivateData = from.fPrivateData;
-	from.fPrivateData = NULL;
-
-	if (len < Length())
-		_Alloc(len);
-
 	return *this;
 }
 
@@ -320,39 +333,32 @@
 {
 	if (count < 0)
 		count = 0;
-	int32 curLen = Length();
-	
-	if (curLen == count || _GrowBy(count - curLen)) 
+
+	if (_DetachWith("", count) == B_OK)
 		memset(fPrivateData, c, count);
-	return *this;	
+	return *this;
 }
 
 
 //	#pragma mark - Substring copying
 
 
-BString &
-BString::CopyInto(BString &into, int32 fromOffset, int32 length) const
+BString&
+BString::CopyInto(BString& into, int32 fromOffset,
+				  int32 length) const
 {
-	if (&into != this) {
-		CHECK_PARAM_RET(fromOffset >= 0, "'fromOffset' must not be negative!", 
-						into);
-		CHECK_PARAM_RET(fromOffset <= Length(), "'fromOffset' exceeds length!", 
-						into);
-		into.SetTo(String() + fromOffset, length);
-	}
+	if (this != &into)
+		into.SetTo(fPrivateData + fromOffset, length);
 	return into;
 }
 
 
 void
-BString::CopyInto(char *into, int32 fromOffset, int32 length) const
+BString::CopyInto(char* into, int32 fromOffset, int32 length) const
 {
-	if (into != NULL) {
-		CHECK_PARAM_VOID(fromOffset >= 0, "'fromOffset' must not be negative!");
-		CHECK_PARAM_VOID(fromOffset <= Length(), "'fromOffset' exceeds length!");
-		int32 len = min_clamp0(length, Length() - fromOffset);
-		memcpy(into, fPrivateData + fromOffset, len);
+	if (into) {
+		length = min_clamp0(length, Length() - fromOffset);
+		memcpy(into, fPrivateData + fromOffset, length);
 	}
 }
 
@@ -361,10 +367,10 @@
 
 
 BString&
-BString::operator+=(const char *str)
+BString::operator+=(const char* string)
 {
-	if (str != NULL)
-		_DoAppend(str, strlen(str));
+	if (string)
+		_DoAppend(string, strlen(string));
 	return *this;
 }
 
@@ -378,20 +384,18 @@
 
 
 BString&
-BString::Append(const BString &string, int32 length)
+BString::Append(const BString& string, int32 length)
 {
-	_DoAppend(string.String(), min_clamp0(length, string.Length()));
+	_DoAppend(string.fPrivateData, min_clamp0(length, string.Length()));
 	return *this;
 }
 
 
 BString&
-BString::Append(const char *str, int32 length)
+BString::Append(const char* string, int32 length)
 {
-	if (str != NULL) {
-		int32 len = strlen_clamp(str, length);
-		_DoAppend(str, len);
-	}	
+	if (string)
+		_DoAppend(string, strlen_clamp(string, length));
 	return *this;
 }
 
@@ -400,9 +404,8 @@
 BString::Append(char c, int32 count)
 {
 	int32 len = Length();
-	if (count > 0 && _GrowBy(count))
+	if (count > 0 && _DoAppend("", count))
 		memset(fPrivateData + len, c, count);
-
 	return *this;
 }
 
@@ -411,53 +414,46 @@
 
 
 BString&
-BString::Prepend(const char *str)
+BString::Prepend(const char* string)
 {
-	if (str != NULL)
-		_DoPrepend(str, strlen(str));
+	if (string)
+		_DoPrepend(string, strlen(string));
 	return *this;
 }
 
 
-// Prepend
 BString&
-BString::Prepend(const BString &string)
+BString::Prepend(const BString& string)
 {
-	if (&string != this)
-		_DoPrepend(string.String(), string.Length());
+	if (fPrivateData != string.fPrivateData)
+		_DoPrepend(string.fPrivateData, string.Length());
 	return *this;
 }
 
 
-// Prepend
 BString&
-BString::Prepend(const char *str, int32 length)
+BString::Prepend(const char* string, int32 length)
 {
-	if (str != NULL) {
-		int32 len = strlen_clamp(str, length);
-		_DoPrepend(str, len);
-	}
+	if (string)
+		_DoPrepend(string, strlen_clamp(string, length));
 	return *this;
 }
 
 
-// Prepend
 BString&
-BString::Prepend(const BString &string, int32 len)
+BString::Prepend(const BString& string, int32 length)
 {
-	if (&string != this)
-		_DoPrepend(string.String(), min_clamp0(len, string.Length()));
+	if (fPrivateData != string.fPrivateData)
+		_DoPrepend(string.fPrivateData, min_clamp0(length, string.Length()));
 	return *this;
 }
 
 
-// Prepend
 BString&
 BString::Prepend(char c, int32 count)
 {
-	if (count > 0 && _OpenAtBy(0, count))
+	if (count > 0 && _DoPrepend("", count))
 		memset(fPrivateData, c, count);
-	
 	return *this;
 }
 
@@ -466,101 +462,94 @@
 
 
 BString&
-BString::Insert(const char *str, int32 pos)
+BString::Insert(const char* string, int32 position)
 {
-	if (str != NULL) {
-		CHECK_PARAM(pos <= Length(), "'pos' exceeds length!");
-		int32 len = (int32)strlen(str);
-		if (pos < 0) {
-			int32 skipLen = min_clamp0(-1 * pos, len);
-			str += skipLen;
+	if (string && position <= Length()) {
+		int32 len = int32(strlen(string));
+		if (position < 0) {
+			int32 skipLen = min_clamp0(-1 * position, len);
+			string += skipLen;
 			len -= skipLen;
-			pos = 0;
-		} else
-			pos = min_clamp0(pos, Length());
-		if (_OpenAtBy(pos, len))
-			memcpy(fPrivateData + pos, str, len);
+			position = 0;
+		} else {
+			position = min_clamp0(position, Length());
+		}
+		_DoInsert(string, position, len);
 	}
 	return *this;
 }
 
 
-// Insert
 BString&
-BString::Insert(const char *str, int32 length, int32 pos)
+BString::Insert(const char* string, int32 length, int32 position)
 {
-	if (str != NULL) {
-		CHECK_PARAM(pos <= Length(), "'pos' exceeds length!");
-		int32 len = strlen_clamp(str, length);
-		if (pos < 0) {
-			int32 skipLen = min_clamp0(-1 * pos, len);
-			str += skipLen;
+	if (string && position <= Length()) {
+		int32 len = strlen_clamp(string, length);
+		if (position < 0) {
+			int32 skipLen = min_clamp0(-1 * position, len);
+			string += skipLen;
 			len -= skipLen;
-			pos = 0;
-		} else
-			pos = min_clamp0(pos, Length());
-		if (_OpenAtBy(pos, len))
-			memcpy(fPrivateData + pos, str, len);
+			position = 0;
+		} else {
+			position = min_clamp0(position, Length());
+		}
+		_DoInsert(string, position, len);
 	}
 	return *this;
 }
 
 
-// Insert
 BString&
-BString::Insert(const char *str, int32 fromOffset, int32 length, int32 pos)
+BString::Insert(const char* string, int32 fromOffset, int32 length,
+				int32 position)
 {
-	CHECK_PARAM(fromOffset >= 0, "'fromOffset' must not be negative!");
-	return Insert(str + fromOffset, length, pos);
+	if (string)
+		Insert(string + fromOffset, length, position);
+	return *this;
 }
 
 
-// Insert
 BString&
-BString::Insert(const BString &string, int32 pos)
+BString::Insert(const BString& string, int32 position)
 {
-	if (&string != this)
-		Insert(string.String(), pos); //TODO: Optimize
-	return *this;				  
+	if ((fPrivateData != string.fPrivateData) && string.Length() > 0)
+		Insert(string.fPrivateData, position);
+	return *this;
 }
 
 
-// Insert
 BString&
-BString::Insert(const BString &string, int32 length, int32 pos)
+BString::Insert(const BString& string, int32 length,
+				int32 position)
 {
-	if (&string != this)
-		Insert(string.String(), length, pos); //TODO: Optimize
+	if ((fPrivateData != string.fPrivateData) && string.Length() > 0)
+		Insert(string.String(), length, position);
 	return *this;
 }
 
 
-// Insert
 BString&
-BString::Insert(const BString &string, int32 fromOffset, int32 length, int32 pos)
+BString::Insert(const BString& string, int32 fromOffset,
+				int32 length, int32 position)
 {
-	if (&string != this) {
-		CHECK_PARAM(fromOffset >= 0, "'fromOffset' must not be negative!");
-		Insert(string.String() + fromOffset, length, pos);
-	}
+	if ((fPrivateData != string.fPrivateData) && string.Length() > 0)
+		Insert(string.String() + fromOffset, length, position);
 	return *this;
 }
 
 
-// Insert
 BString&
-BString::Insert(char c, int32 count, int32 pos)
+BString::Insert(char c, int32 count, int32 position)
 {
-	CHECK_PARAM(pos <= Length(), "'pos' exceeds length!");
-	if (pos < 0) {
-		count = max_c(count + pos, 0);
-		pos = 0;
+	if (position < 0) {
+		count = MAX(count + position, 0);
+		position = 0;
 	} else
-		pos = min_clamp0(pos, Length());
-	
-	if (count > 0 && _OpenAtBy(pos, count))
-		memset(fPrivateData + pos, c, count);
-	
+		position = min_clamp0(position, Length());
+
+	if (count > 0 && _DoInsert("", position, count))
+		memset(fPrivateData + position, c, count);
+
 	return *this;
 }
 
@@ -574,40 +563,25 @@
 	if (newLength < 0)
 		newLength = 0;
 
-	int32 curLen = Length();
+	if (newLength < Length())
+		// ignore lazy, since we might detach
+		_DetachWith(fPrivateData, newLength);
 
-	if (newLength < curLen) {
-		if (lazy) {
-			// don't free memory yet, just set new length
-			_SetLength(newLength);
-			fPrivateData[newLength] = '\0';
-		} else
-			_Alloc(newLength);
-	}
-
 	return *this;
 }
 
 
-// Remove
 BString&
 BString::Remove(int32 from, int32 length)
 {
-	int32 len = Length();
-	if (from < 0) {
-		int32 skipLen = min_clamp0(from, len);
-		len -= skipLen;
-		from = 0;
-	} else
-		from = min_clamp0(from, len);
-	_ShrinkAtBy(from, min_clamp0(length, len - from));
+	if (length > 0 && from < Length())
+		_ShrinkAtBy(from, min_clamp0(length, (Length() - from)));
 	return *this;
 }
 
 
-// Remove
 BString&
-BString::RemoveFirst(const BString &string)
+BString::RemoveFirst(const BString& string)
 {
 	if (string.Length() > 0) {
 		int32 pos = _ShortFindAfter(string.String(), string.Length());
@@ -618,9 +592,8 @@
 }
 
 
-// Remove
 BString&
-BString::RemoveLast(const BString &string)
+BString::RemoveLast(const BString& string)
 {
 	int32 pos = _FindBefore(string.String(), Length(), string.Length());
 	if (pos >= 0)
@@ -630,17 +603,21 @@
 }
 
 
-// Remove
 BString&
-BString::RemoveAll(const BString &string)
+BString::RemoveAll(const BString& string)
 {
+	if (string.Length() == 0 || Length() == 0 || FindFirst(string) < 0)
+		return *this;
+
+	if (_Detach() != B_OK)
+		return *this;
+
 	return _DoReplace(string.String(), "", REPLACE_ALL, 0, KEEP_CASE);
 }
 
 
-// Remove
 BString&
-BString::RemoveFirst(const char *string)
+BString::RemoveFirst(const char* string)
 {
 	int32 length = string ? strlen(string) : 0;
 	if (length > 0) {
@@ -652,9 +629,8 @@
 }
 
 
-// Remove
 BString&
-BString::RemoveLast(const char *string)
+BString::RemoveLast(const char* string)
 {
 	int32 length = string ? strlen(string) : 0;
 	if (length > 0) {
@@ -666,152 +642,141 @@
 }
 
 
-// Remove
 BString&
-BString::RemoveAll(const char *str)
+BString::RemoveAll(const char* string)
 {
-	return _DoReplace(str, "", REPLACE_ALL, 0, KEEP_CASE);
+	if (!string || Length() == 0 || FindFirst(string) < 0)
+		return *this;
+
+	if (_Detach() != B_OK)
+		return *this;
+
+	return _DoReplace(string, "", REPLACE_ALL, 0, KEEP_CASE);
 }
 
 
-// Remove
 BString&
-BString::RemoveSet(const char *setOfCharsToRemove)
+BString::RemoveSet(const char* setOfCharsToRemove)
 {
 	return ReplaceSet(setOfCharsToRemove, "");
 }
 
 
-// MoveInto
 BString&
-BString::MoveInto(BString &into, int32 from, int32 length)
+BString::MoveInto(BString& into, int32 from, int32 length)
 {
-	CHECK_PARAM_RET(from >= 0, "'from' must not be negative!", into);
-	CHECK_PARAM_RET(from <= Length(), "'from' exceeds length!", into);
-	int32 len = min_clamp0(length, Length() - from);
-	if (&into == this) {
-		/* TODO: [zooey]: to be activated later (>R1):
-		// strings are identical, just move the data:
-		if (from>0 && fPrivateData)
-			memmove( fPrivateData, fPrivateData+from, len);
-		Truncate( len);
-		*/
-		return *this;
+	if (length) {
+		CopyInto(into, from, length);
+		Remove(from, length);
 	}
-	into.SetTo(String() + from, len);
-	_ShrinkAtBy(from, len);
-
 	return into;
 }
 
 
-// MoveInto
 void
-BString::MoveInto(char *into, int32 from, int32 length)
+BString::MoveInto(char* into, int32 from, int32 length)
 {
-	if (into != NULL) {
-		CHECK_PARAM_VOID(from >= 0, "'from' must not be negative!");
-		CHECK_PARAM_VOID(from <= Length(), "'from' exceeds length!");
-		int32 len = min_clamp0(length, Length() - from);
-		memcpy(into, String() + from, len);
-		into[len] = '\0';
-		_ShrinkAtBy(from, len);
+	if (into) {
+		CopyInto(into, from, length);
+		Remove(from, length);
 	}
 }
 
 
-/*---- Compare functions ---------------------------------------------------*/
+//	#pragma mark - Compare functions
+
+
 bool
-BString::operator<(const char *string) const
+BString::operator<(const char* string) const
 {
 	return strcmp(String(), safestr(string)) < 0;
 }
 
 
 bool
-BString::operator<=(const char *string) const
+BString::operator<=(const char* string) const
 {
 	return strcmp(String(), safestr(string)) <= 0;
 }
 
 
 bool
-BString::operator==(const char *string) const
+BString::operator==(const char* string) const
 {
 	return strcmp(String(), safestr(string)) == 0;
 }
 
 
 bool
-BString::operator>=(const char *string) const
+BString::operator>=(const char* string) const
 {
 	return strcmp(String(), safestr(string)) >= 0;
 }
 
 
 bool
-BString::operator>(const char *string) const
+BString::operator>(const char* string) const
 {
 	return strcmp(String(), safestr(string)) > 0;
 }
 
 
-//	#pragma mark - Comparison
+//	#pragma mark - strcmp()-style compare functions
 
 
 int
-BString::Compare(const BString &string) const
+BString::Compare(const BString& string) const
 {
 	return strcmp(String(), string.String());
 }
 
 
 int
-BString::Compare(const char *string) const
+BString::Compare(const char* string) const
 {
 	return strcmp(String(), safestr(string));
 }
 
 
 int
-BString::Compare(const BString &string, int32 n) const
+BString::Compare(const BString& string, int32 length) const
 {
-	return strncmp(String(), string.String(), n);
+	return strncmp(String(), string.String(), length);
 }
 
 
 int
-BString::Compare(const char *string, int32 n) const
+BString::Compare(const char* string, int32 length) const
 {
-	return strncmp(String(), safestr(string), n);
+	return strncmp(String(), safestr(string), length);
 }
 
 
 int
-BString::ICompare(const BString &string) const
+BString::ICompare(const BString& string) const
 {
 	return strcasecmp(String(), string.String());
 }
 
 
 int
-BString::ICompare(const char *str) const
+BString::ICompare(const char* string) const
 {
-	return strcasecmp(String(), safestr(str));
+	return strcasecmp(String(), safestr(string));
 }
 
 
 int
-BString::ICompare(const BString &string, int32 n) const
+BString::ICompare(const BString& string, int32 length) const
 {
-	return strncasecmp(String(), string.String(), n);
+	return strncasecmp(String(), string.String(), length);
 }
 
 
 int
-BString::ICompare(const char *str, int32 n) const
+BString::ICompare(const char* string, int32 length) const
 {
-	return strncasecmp(String(), safestr(str), n);
+	return strncasecmp(String(), safestr(string), length);
 }
 
 
@@ -819,15 +784,14 @@
 
 
 int32
-BString::FindFirst(const BString &string) const
+BString::FindFirst(const BString& string) const
 {
 	return _ShortFindAfter(string.String(), string.Length());
 }
 
 
-// FindFirst
 int32
-BString::FindFirst(const char *string) const
+BString::FindFirst(const char* string) const
 {
 	if (string == NULL)
 		return B_BAD_VALUE;
@@ -836,9 +800,8 @@
 }
 
 
-// FindFirst
 int32
-BString::FindFirst(const BString &string, int32 fromOffset) const
+BString::FindFirst(const BString& string, int32 fromOffset) const
 {
 	if (fromOffset < 0)
 		return B_ERROR;
@@ -848,29 +811,28 @@
 }
 
 
-// FindFirst
 int32
-BString::FindFirst(const char *string, int32 fromOffset) const
+BString::FindFirst(const char* string, int32 fromOffset) const
 {
 	if (string == NULL)
 		return B_BAD_VALUE;
+
 	if (fromOffset < 0)
 		return B_ERROR;
 
 	return _FindAfter(string, min_clamp0(fromOffset, Length()),
-		strlen(string));
+		strlen(safestr(string)));
 }
 
 
-// FindFirst
 int32
 BString::FindFirst(char c) const
-{	
+{
 	const char *start = String();
 	const char *end = String() + Length();
 
-	/* Scans the string until we find the character, */
-	/* or we hit the string's end */
+	// Scans the string until we found the
+	// character, or we reach the string's start
 	while (start != end && *start != c) {
 		start++;
 	}
@@ -882,7 +844,6 @@
 }
 
 
-// FindFirst
 int32
 BString::FindFirst(char c, int32 fromOffset) const
 {
@@ -892,8 +853,8 @@
 	const char *start = String() + min_clamp0(fromOffset, Length());
 	const char *end = String() + Length();
 
-	/* Scans the string until we found the character, */
-	/* or we hit the string's end */
+	// Scans the string until we found the
+	// character, or we reach the string's start
 	while (start < end && *start != c) {
 		start++;
 	}
@@ -905,59 +866,56 @@
 }
 
 
-// FindLast
 int32
-BString::FindLast(const BString &string) const
+BString::FindLast(const BString& string) const
 {
 	return _FindBefore(string.String(), Length(), string.Length());
 }
 
 
-// FindLast
 int32
-BString::FindLast(const char *string) const
+BString::FindLast(const char* string) const
 {
 	if (string == NULL)
 		return B_BAD_VALUE;
 
-	return _FindBefore(string, Length(), strlen(string));
+	return _FindBefore(string, Length(), strlen(safestr(string)));
 }
 
 
-// FindLast
 int32
-BString::FindLast(const BString &string, int32 beforeOffset) const
+BString::FindLast(const BString& string, int32 beforeOffset) const
 {
 	if (beforeOffset < 0)
 		return B_ERROR;
 
-	return _FindBefore(string.String(), min_clamp0(beforeOffset, Length()), 
-		string.Length()); 
+	return _FindBefore(string.String(), min_clamp0(beforeOffset, Length()),
+		string.Length());
 }
 
 
-// FindLast
 int32
-BString::FindLast(const char *string, int32 beforeOffset) const
+BString::FindLast(const char* string, int32 beforeOffset) const
 {
 	if (string == NULL)
 		return B_BAD_VALUE;
+
 	if (beforeOffset < 0)
 		return B_ERROR;
 
-	return _FindBefore(string, min_clamp0(beforeOffset, Length()), strlen(string));
+	return _FindBefore(string, min_clamp0(beforeOffset, Length()),
+		strlen(safestr(string)));
 }
 
 
-// FindLast
 int32
 BString::FindLast(char c) const
 {
 	const char *start = String();
 	const char *end = String() + Length();
 
-	/* Scans the string backwards until we found the character, */
-	/* or we reach the string's start */
+	// Scans the string backwards until we found
+	// the character, or we reach the string's start
 	while (end != start && *end != c) {
 		end--;
 	}
@@ -969,7 +927,6 @@
 }
 
 
-// FindLast
 int32
 BString::FindLast(char c, int32 beforeOffset) const
 {
@@ -979,8 +936,8 @@
 	const char *start = String();
 	const char *end = String() + min_clamp0(beforeOffset, Length());
 
-	/* Scans the string backwards until we found the character, */
-	/* or we reach the string's start */
+	// Scans the string backwards until we found
+	// the character, or we reach the string's start
 	while (end > start && *end != c) {
 		end--;
 	}
@@ -993,83 +950,86 @@
 
 
 int32
-BString::IFindFirst(const BString &string) const
+BString::IFindFirst(const BString& string) const
 {
 	return _IFindAfter(string.String(), 0, string.Length());
 }
 
 
 int32
-BString::IFindFirst(const char *string) const
+BString::IFindFirst(const char* string) const
 {
 	if (string == NULL)
 		return B_BAD_VALUE;
 
-	return _IFindAfter(string, 0, strlen(string));
+	return _IFindAfter(string, 0, strlen(safestr(string)));
 }
 
 
 int32
-BString::IFindFirst(const BString &string, int32 fromOffset) const
+BString::IFindFirst(const BString& string, int32 fromOffset) const
 {
 	if (fromOffset < 0)
 		return B_ERROR;
 
-	return _IFindAfter(string.String(), min_clamp0(fromOffset, Length()), 
+	return _IFindAfter(string.String(), min_clamp0(fromOffset, Length()),
 		string.Length());
 }
 
 
 int32
-BString::IFindFirst(const char *string, int32 fromOffset) const
+BString::IFindFirst(const char* string, int32 fromOffset) const
 {
 	if (string == NULL)
 		return B_BAD_VALUE;
+
 	if (fromOffset < 0)
 		return B_ERROR;
 
-	return _IFindAfter(string, min_clamp0(fromOffset,Length()), strlen(string));
+	return _IFindAfter(string, min_clamp0(fromOffset,Length()),
+		strlen(safestr(string)));
 }
 
 
 int32
-BString::IFindLast(const BString &string) const
+BString::IFindLast(const BString& string) const
 {
 	return _IFindBefore(string.String(), Length(), string.Length());
 }
 
 
 int32
-BString::IFindLast(const char *string) const
+BString::IFindLast(const char* string) const
 {
 	if (string == NULL)
 		return B_BAD_VALUE;
 
-	return _IFindBefore(string, Length(), strlen(string));
+	return _IFindBefore(string, Length(), strlen(safestr(string)));
 }
 
 
 int32
-BString::IFindLast(const BString &string, int32 beforeOffset) const
+BString::IFindLast(const BString& string, int32 beforeOffset) const
 {
 	if (beforeOffset < 0)
 		return B_ERROR;
 
-	return _IFindBefore(string.String(), min_clamp0(beforeOffset, Length()), 
+	return _IFindBefore(string.String(), min_clamp0(beforeOffset, Length()),
 		string.Length());
 }
 
 
 int32
-BString::IFindLast(const char *string, int32 beforeOffset) const
+BString::IFindLast(const char* string, int32 beforeOffset) const
 {
 	if (string == NULL)
 		return B_BAD_VALUE;
+
 	if (beforeOffset < 0)
 		return B_ERROR;
 
 	return _IFindBefore(string, min_clamp0(beforeOffset, Length()),
-		strlen(string));
+		strlen(safestr(string)));
 }
 
 
@@ -1080,9 +1040,8 @@
 BString::ReplaceFirst(char replaceThis, char withThis)
 {
 	int32 pos = FindFirst(replaceThis);
-	if (pos >= 0)
+	if (pos >= 0 && _Detach() == B_OK)
 		fPrivateData[pos] = withThis;
-
 	return *this;
 }
 
@@ -1091,9 +1050,8 @@
 BString::ReplaceLast(char replaceThis, char withThis)
 {
 	int32 pos = FindLast(replaceThis);
-	if (pos >= 0)
+	if (pos >= 0 && _Detach() == B_OK)
 		fPrivateData[pos] = withThis;
-
 	return *this;
 }
 
@@ -1101,25 +1059,34 @@
 BString&
 BString::ReplaceAll(char replaceThis, char withThis, int32 fromOffset)
 {
-	CHECK_PARAM(fromOffset >= 0, "'fromOffset' must not be negative!");
-	for (int32 pos = min_clamp0(fromOffset, Length());;) {
-		pos = FindFirst(replaceThis, pos);
-		if (pos < 0)
-			break;
+	fromOffset = min_clamp0(fromOffset, Length());
+	int32 pos = FindFirst(replaceThis, fromOffset);
+
+	// detach and set first match
+	if (pos >= 0 && _Detach() == B_OK) {
 		fPrivateData[pos] = withThis;
+		for (pos = pos;;) {
+			pos = FindFirst(replaceThis, pos);
+			if (pos < 0)
+				break;
+			fPrivateData[pos] = withThis;
+		}
 	}
-
 	return *this;
 }
 
 
 BString&
-BString::Replace(char replaceThis, char withThis, int32 maxReplaceCount, int32 fromOffset)
+BString::Replace(char replaceThis, char withThis, int32 maxReplaceCount,
+				 int32 fromOffset)
 {
-	CHECK_PARAM(fromOffset >= 0, "'fromOffset' must not be negative!");
-	if (maxReplaceCount > 0) {
-		for (int32 pos = min_clamp0(fromOffset, Length()); 
-			  		maxReplaceCount > 0; maxReplaceCount--) {
+	fromOffset = min_clamp0(fromOffset, Length());
+	int32 pos = FindFirst(replaceThis, fromOffset);
+
+	if (maxReplaceCount > 0 && pos >= 0 && _Detach() == B_OK) {
+		maxReplaceCount--;
+		fPrivateData[pos] = withThis;
+		for (pos = pos;  maxReplaceCount > 0; maxReplaceCount--) {
 			pos = FindFirst(replaceThis, pos);
 			if (pos < 0)
 				break;
@@ -1131,54 +1098,76 @@
 
 
 BString&
-BString::ReplaceFirst(const char *replaceThis, const char *withThis)
+BString::ReplaceFirst(const char* replaceThis, const char* withThis)
 {
-	return _DoReplace( replaceThis, withThis, 1, 0, KEEP_CASE);
+	if (!replaceThis || !withThis || FindFirst(replaceThis) < 0)
+		return *this;
+
+	if (_Detach() != B_OK)
+		return *this;
+
+	return _DoReplace(replaceThis, withThis, 1, 0, KEEP_CASE);
 }
 
 
 BString&
-BString::ReplaceLast(const char *replaceThis, const char *withThis)
+BString::ReplaceLast(const char* replaceThis, const char* withThis)
 {
-	if (replaceThis == NULL)
+	if (!replaceThis || !withThis)
 		return *this;
-		
-	int32 firstStringLength = strlen(replaceThis);	
-	int32 pos = _FindBefore(replaceThis, Length(), firstStringLength);
-	
+
+	int32 replaceThisLength = strlen(replaceThis);
+	int32 pos = _FindBefore(replaceThis, Length(), replaceThisLength);
+
 	if (pos >= 0) {
-		int32 len = (withThis ? strlen(withThis) : 0);
-		int32 difference = len - firstStringLength;
-		
+		int32 withThisLength =  strlen(withThis);
+		int32 difference = withThisLength - replaceThisLength;
+
 		if (difference > 0) {
 			if (!_OpenAtBy(pos, difference))
 				return *this;
 		} else if (difference < 0) {
 			if (!_ShrinkAtBy(pos, -difference))
 				return *this;
+		} else {
+			if (_Detach() != B_OK)
+				return *this;
 		}
-		memcpy(fPrivateData + pos, withThis, len);
+		memcpy(fPrivateData + pos, withThis, withThisLength);
 	}
-		
+
 	return *this;
 }
 
 
 BString&
-BString::ReplaceAll(const char *replaceThis, const char *withThis, int32 fromOffset)
+BString::ReplaceAll(const char* replaceThis, const char* withThis,
+					int32 fromOffset)
 {
-	CHECK_PARAM(fromOffset >= 0, "'fromOffset' must not be negative!");
+	if (!replaceThis || !withThis || FindFirst(replaceThis) < 0)
+		return *this;
+
+	if (_Detach() != B_OK)
+		return *this;
+
 	return _DoReplace(replaceThis, withThis, REPLACE_ALL,
-		min_clamp0(fromOffset,Length()), KEEP_CASE);
+		min_clamp0(fromOffset, Length()), KEEP_CASE);
 }
 
 
 BString&
-BString::Replace(const char *replaceThis, const char *withThis, int32 maxReplaceCount, int32 fromOffset)
+BString::Replace(const char* replaceThis, const char* withThis,
+				 int32 maxReplaceCount, int32 fromOffset)
 {
-	CHECK_PARAM(fromOffset >= 0, "'fromOffset' must not be negative!");
+	if (!replaceThis || !withThis || maxReplaceCount <= 0
+		|| FindFirst(replaceThis) < 0)
+		return *this;
+
+	if (_Detach() != B_OK)
+		return *this;
+
 	return _DoReplace(replaceThis, withThis, maxReplaceCount,
-		min_clamp0(fromOffset,Length()), KEEP_CASE);
+		min_clamp0(fromOffset, Length()), KEEP_CASE);
 }
 
 
@@ -1188,9 +1177,8 @@
 	char tmp[2] = { replaceThis, '\0' };
 
 	int32 pos = _IFindAfter(tmp, 0, 1);
-	if (pos >= 0)
+	if (pos >= 0 && _Detach() == B_OK)
 		fPrivateData[pos] = withThis;
-
 	return *this;
 }
 
@@ -1201,9 +1189,8 @@
 	char tmp[2] = { replaceThis, '\0' };
 
 	int32 pos = _IFindBefore(tmp, Length(), 1);
-	if (pos >= 0)
+	if (pos >= 0 && _Detach() == B_OK)
 		fPrivateData[pos] = withThis;
-	
 	return *this;
 }
 
@@ -1211,60 +1198,70 @@
 BString&
 BString::IReplaceAll(char replaceThis, char withThis, int32 fromOffset)
 {
-	CHECK_PARAM(fromOffset >= 0, "'fromOffset' must not be negative!");
-
 	char tmp[2] = { replaceThis, '\0' };
+	fromOffset = min_clamp0(fromOffset, Length());
+	int32 pos = _IFindAfter(tmp, fromOffset, 1);
 
-	for (int32 pos = min_clamp0(fromOffset, Length());;) {
-		pos = _IFindAfter(tmp, pos, 1);
-		if (pos < 0)
-			break;
+	if (pos >= 0 && _Detach() == B_OK) {
 		fPrivateData[pos] = withThis;
+		for (pos = pos;;) {
+			pos = _IFindAfter(tmp, pos, 1);
+			if (pos < 0)
+				break;
+			fPrivateData[pos] = withThis;
+		}
 	}
 	return *this;
 }
 
 
 BString&
-BString::IReplace(char replaceThis, char withThis, int32 maxReplaceCount, int32 fromOffset)
+BString::IReplace(char replaceThis, char withThis, int32 maxReplaceCount,
+				  int32 fromOffset)
 {
-	CHECK_PARAM(fromOffset >= 0, "'fromOffset' must not be negative!");
+	char tmp[2] = { replaceThis, '\0' };
+	fromOffset = min_clamp0(fromOffset, Length());
+	int32 pos = _IFindAfter(tmp, fromOffset, 1);
 
-	char tmp[2] = { replaceThis, '\0' };
-	
-	if (fPrivateData == NULL)
-		return *this;
-		
-	for (int32 pos = min_clamp0(fromOffset,Length()); 
-		  	maxReplaceCount > 0;   maxReplaceCount--) {	
-		pos = _IFindAfter(tmp, pos, 1);
-		if (pos < 0)
-			break;
+	if (maxReplaceCount > 0 && pos >= 0 && _Detach() == B_OK) {
 		fPrivateData[pos] = withThis;
+		maxReplaceCount--;
+		for (pos = pos;  maxReplaceCount > 0; maxReplaceCount--) {
+			pos = _IFindAfter(tmp, pos, 1);
+			if (pos < 0)
+				break;
+			fPrivateData[pos] = withThis;
+		}
 	}
+
 	return *this;
 }
 
 
 BString&
-BString::IReplaceFirst(const char *replaceThis, const char *withThis)
+BString::IReplaceFirst(const char* replaceThis, const char* withThis)
 {
+	if (!replaceThis || !withThis || IFindFirst(replaceThis) < 0)
+		return *this;
+
+	if (_Detach() != B_OK)
+		return *this;
 	return _DoReplace(replaceThis, withThis, 1, 0, IGNORE_CASE);
 }
 
 
 BString&
-BString::IReplaceLast(const char *replaceThis, const char *withThis)
+BString::IReplaceLast(const char* replaceThis, const char* withThis)
 {
-	if (replaceThis == NULL)
+	if (!replaceThis || !withThis)
 		return *this;
 
-	int32 firstStringLength = strlen(replaceThis);		
-	int32 pos = _IFindBefore(replaceThis, Length(), firstStringLength);
+	int32 replaceThisLength = strlen(replaceThis);
+	int32 pos = _IFindBefore(replaceThis, Length(), replaceThisLength);
 
 	if (pos >= 0) {
-		int32 len = (withThis ? strlen(withThis) : 0);
-		int32 difference = len - firstStringLength;
+		int32 withThisLength = strlen(withThis);
+		int32 difference = withThisLength - replaceThisLength;
 
 		if (difference > 0) {
 			if (!_OpenAtBy(pos, difference))
@@ -1272,8 +1269,11 @@
 		} else if (difference < 0) {
 			if (!_ShrinkAtBy(pos, -difference))
 				return *this;
+		} else {
+			if (_Detach() != B_OK)
+				return *this;
 		}
-		memcpy(fPrivateData + pos, withThis, len);
+		memcpy(fPrivateData + pos, withThis, withThisLength);
 	}
 
 	return *this;
@@ -1281,35 +1281,49 @@
 
 
 BString&
-BString::IReplaceAll(const char *replaceThis, const char *withThis, int32 fromOffset)
+BString::IReplaceAll(const char* replaceThis, const char* withThis,
+					 int32 fromOffset)
 {
-	CHECK_PARAM(fromOffset >= 0, "'fromOffset' must not be negative!");
+	if (!replaceThis || !withThis || IFindFirst(replaceThis) < 0)
+		return *this;
+
+	if (_Detach() != B_OK)
+		return *this;
+
 	return _DoReplace(replaceThis, withThis, REPLACE_ALL,
 		min_clamp0(fromOffset, Length()), IGNORE_CASE);
 }
 
 
 BString&
-BString::IReplace(const char *replaceThis, const char *withThis,
-	int32 maxReplaceCount, int32 fromOffset)
+BString::IReplace(const char* replaceThis, const char* withThis,
+				  int32 maxReplaceCount, int32 fromOffset)
 {
-	CHECK_PARAM(fromOffset >= 0, "'fromOffset' must not be negative!");
+	if (!replaceThis || !withThis || maxReplaceCount <= 0
+		|| FindFirst(replaceThis) < 0)
+		return *this;
+
+	if (_Detach() != B_OK)
+		return *this;
+
 	return _DoReplace(replaceThis, withThis, maxReplaceCount,
 		min_clamp0(fromOffset, Length()), IGNORE_CASE);
 }
 
 
 BString&
-BString::ReplaceSet(const char *setOfChars, char with)
+BString::ReplaceSet(const char* setOfChars, char with)
 {
-	if (setOfChars == NULL)
+	if (!setOfChars || strcspn(fPrivateData, setOfChars) >= uint32(Length()))
 		return *this;
 
+	if (_Detach() != B_OK)
+		return *this;
+
 	int32 offset = 0;
 	int32 length = Length();
-
 	for (int32 pos;;) {
-		pos = strcspn(String() + offset, setOfChars);
+		pos = strcspn(fPrivateData + offset, setOfChars);
 
 		offset += pos;
 		if (offset >= length)
@@ -1324,23 +1338,26 @@
 
 
 BString&
-BString::ReplaceSet(const char *setOfChars, const char *with)
+BString::ReplaceSet(const char* setOfChars, const char* with)
 {
-	int32 withLen = with ? strlen(with) : 0;
-	if (withLen == 1) {
-		// delegate simple case:
+	if (!setOfChars || !with
+		|| strcspn(fPrivateData, setOfChars) >= uint32(Length()))
+		return *this;
+
+	// delegate simple case
+	int32 withLen = strlen(with);
+	if (withLen == 1)
 		return ReplaceSet(setOfChars, *with);
-	}
 
-	if (setOfChars == NULL || fPrivateData == NULL)
+	if (_Detach() != B_OK)
 		return *this;
 
-	PosVect positions;
-
+	int32 pos = 0;
 	int32 searchLen = 1;
 	int32 len = Length();
-	int32 pos = 0;
-	for (int32 offset = 0; offset < len; offset += (pos+searchLen)) {
+
+	PosVect positions;
+	for (int32 offset = 0; offset < len; offset += (pos + searchLen)) {
 		pos = strcspn(fPrivateData + offset, setOfChars);
 		if (pos + offset >= len)
 			break;
@@ -1348,41 +1365,43 @@
 			return *this;
 	}
 
-	_ReplaceAtPositions(&positions, searchLen, with, withLen);	
+	_ReplaceAtPositions(&positions, searchLen, with, withLen);
 	return *this;
 }
 
 
-/*---- Unchecked char access -----------------------------------------------*/
+//	#pragma mark - Unchecked char access
 
-// operator[]
-char &
+
+#if __GNUC__ > 3
+BStringRef
 BString::operator[](int32 index)
 {
+	return BStringRef(*this, index);
+}
+#else
+char&
+BString::operator[](int32 index)
+{
+	_Detach();
+	_SetReferenceCount(-1);
+
 	return fPrivateData[index];
 }
+#endif
 
 
-/*---- Fast low-level manipulation -----------------------------------------*/
+//	#pragma mark - Fast low-level manipulation
+
+
 char*
 BString::LockBuffer(int32 maxLength)
 {
-	_SetUsingAsCString(true);
+	int32 length = Length();
+	if (maxLength > length)
+		length += maxLength - length;
 
-	int32 len = Length();
-
-	if (maxLength > len) {
-		if (!_GrowBy(maxLength - len))
-			return NULL;
-		if (!len && fPrivateData)
-			// if string was empty before call to LockBuffer(), we make sure the
-			// buffer represents an empty c-string:
-			*fPrivateData = '\0';
-	} else if (!maxLength && !len) {
-		// special case for unallocated string, we return an empty c-string:
-		return const_cast<char*>(String());
-	}
-
+	_DetachWith(fPrivateData, length);
 	return fPrivateData;
 }
 
@@ -1390,198 +1409,148 @@
 BString&
 BString::UnlockBuffer(int32 length)
 {
-	_SetUsingAsCString(false);
-
-	if (length < 0)
+	if (length > 0) {
+		if (length)
+			length = min_clamp0(length, Length());
+	} else {
 		length = (fPrivateData == NULL) ? 0 : strlen(fPrivateData);
+	}
 
-	if (length != Length())
-		_GrowBy(length - Length());
+	_Realloc(length);
+	fPrivateData[length] = '\0';
 
 	return *this;
 }
 
 
-/*---- Uppercase<->Lowercase ------------------------------------------------*/
-// ToLower
+//	#pragma mark - Uppercase <-> Lowercase
+
+
 BString&
 BString::ToLower()
 {
 	int32 length = Length();
-	for (int32 count = 0; count < length; count++) {
-		fPrivateData[count] = tolower(fPrivateData[count]);
+	if (length > 0 && _Detach() == B_OK) {
+		for (int32 count = 0; count < length; count++)
+			fPrivateData[count] = tolower(fPrivateData[count]);
 	}
-
 	return *this;
 }
 
 
-// ToUpper
 BString&
 BString::ToUpper()
-{			
+{
 	int32 length = Length();
-	for (int32 count = 0; count < length; count++) {
-		fPrivateData[count] = toupper(fPrivateData[count]);
+	if (length > 0 && _Detach() == B_OK) {
+		for (int32 count = 0; count < length; count++)
+			fPrivateData[count] = toupper(fPrivateData[count]);
 	}
-
 	return *this;
 }
 
 
-// Capitalize
 BString&
 BString::Capitalize()
 {
-	if (fPrivateData == NULL)
-		return *this;
-
-	fPrivateData[0] = toupper(fPrivateData[0]);
 	int32 length = Length();
 
-	for (int32 count = 1; count < length; count++) {
-		fPrivateData[count] = tolower(fPrivateData[count]);
+	if (length > 0 && _Detach() == B_OK) {
+		fPrivateData[0] = toupper(fPrivateData[0]);
+		for (int32 count = 1; count < length; count++)
+			fPrivateData[count] = tolower(fPrivateData[count]);
 	}
-
 	return *this;
 }
 
 
-// CapitalizeEachWord
 BString&
 BString::CapitalizeEachWord()
 {
-	if (fPrivateData == NULL)
-		return *this;
-		
-	int32 count = 0;
 	int32 length = Length();
-		
-	do {
-		// Find the first alphabetical character...
-		for (; count < length; count++) {
-			if (isalpha(fPrivateData[count])) {
-				// ...found! Convert it to uppercase.
-				fPrivateData[count] = toupper(fPrivateData[count]);
-				count++;
-				break;
+
+	if (length > 0 && _Detach() == B_OK) {
+		int32 count = 0;
+		do {
+			// Find the first alphabetical character...
+			for (; count < length; count++) {
+				if (isalpha(fPrivateData[count])) {
+					// ...found! Convert it to uppercase.
+					fPrivateData[count] = toupper(fPrivateData[count]);
+					count++;
+					break;
+				}
 			}
-		}
 
-		// Now find the first non-alphabetical character,
-		// and meanwhile, turn to lowercase all the alphabetical ones
-		for (; count < length; count++) {
-			if (isalpha(fPrivateData[count]))
-				fPrivateData[count] = tolower(fPrivateData[count]);
-			else
-				break;
-		}
-	} while (count < length);
-
+			// Now find the first non-alphabetical character,
+			// and meanwhile, turn to lowercase all the alphabetical ones
+			for (; count < length; count++) {
+				if (isalpha(fPrivateData[count]))
+					fPrivateData[count] = tolower(fPrivateData[count]);
+				else
+					break;
+			}
+		} while (count < length);
+	}
 	return *this;
 }
 
 
-/*----- Escaping and Deescaping --------------------------------------------*/
+//	#pragma mark - Escaping and De-escaping
+
+
 BString&
-BString::CharacterEscape(const char *original, const char *setOfCharsToEscape,
-	char escapeWith)
+BString::CharacterEscape(const char* original,
+						 const char* setOfCharsToEscape, char escapeWith)
 {
-	SetTo(original);
-	CharacterEscape(setOfCharsToEscape, escapeWith);
-
+	if (setOfCharsToEscape)
+		_DoCharacterEscape(original, setOfCharsToEscape, escapeWith);
 	return *this;
 }
 
 
 BString&
-BString::CharacterEscape(const char *setOfCharsToEscape, char escapeWith)
+BString::CharacterEscape(const char* setOfCharsToEscape, char escapeWith)
 {
-	if (setOfCharsToEscape == NULL || fPrivateData == NULL)
-		return *this;
-
-	PosVect positions;
-	int32 len = Length();
-	int32 pos = 0;
-	for (int32 offset = 0; offset < len; offset += pos + 1) {
-		if ((pos = strcspn(fPrivateData + offset, setOfCharsToEscape)) < len - offset) {
-			if (!positions.Add(offset + pos))
-				return *this;
-		}
-	}
-
-	uint32 count = positions.CountItems();
-	int32 newLength = len + count;
-	if (!newLength) {
-		_Alloc(0);
-		return *this;
-	}
-
-	int32 lastPos = 0;
-	char* oldAdr = fPrivateData;
-	char* newData = (char*)malloc(newLength + sizeof(int32) + 1);
-	if (newData) {
-		newData += sizeof(int32);
-		char* newAdr = newData;
-		for (uint32 i = 0; i < count; ++i) {
-			pos = positions.ItemAt( i);
-			len = pos-lastPos;
-			if (len > 0) {
-				memcpy(newAdr, oldAdr, len);
-				oldAdr += len;
-				newAdr += len;
-			}
-			*newAdr++ = escapeWith;
-			*newAdr++ = *oldAdr++;
-			lastPos = pos + 1;
-		}
-		len = Length() + 1 - lastPos;
-		if (len > 0)
-			memcpy(newAdr, oldAdr, len);
-
-		free(fPrivateData - sizeof(int32));
-		fPrivateData = newData;
-		fPrivateData[newLength] = 0;
-		_SetLength( newLength);
-	}
-
+	if (setOfCharsToEscape && Length() > 0)
+		_DoCharacterEscape(fPrivateData, setOfCharsToEscape, escapeWith);
 	return *this;
 }
 
 
 BString&
-BString::CharacterDeescape(const char *original, char escapeChar)
+BString::CharacterDeescape(const char* original, char escapeChar)
 {
-	SetTo(original);	
-	CharacterDeescape(escapeChar);
-
-	return *this;
+	return _DoCharacterDeescape(original, escapeChar);
 }
 
 
 BString&
 BString::CharacterDeescape(char escapeChar)
 {
-	const char temp[2] = {escapeChar, 0};
-	return _DoReplace(temp, "", REPLACE_ALL, 0, KEEP_CASE);
+	if (Length() > 0)
+		_DoCharacterDeescape(fPrivateData, escapeChar);
+	return *this;
 }
 
 
-/*---- Simple sprintf replacement calls ------------------------------------*/
-/*---- Slower than sprintf but type and overflow safe ----------------------*/
+//	#pragma mark - Insert
+
+
 BString&
-BString::operator<<(const char *str)
+BString::operator<<(const char* string)
 {
-	if (str != NULL)
-		_DoAppend(str, strlen(str));
-	return *this;	
+	if (string != NULL)
+		_DoAppend(string, strlen(string));
+	return *this;
 }
 
 
 BString&
-BString::operator<<(const BString &string)
+BString::operator<<(const BString& string)
 {
-	_DoAppend(string.String(), string.Length());
+	if (string.Length() > 0)
+		_DoAppend(string.String(), string.Length());
 	return *this;
 }
 
@@ -1589,7 +1558,7 @@
 BString&
 BString::operator<<(char c)
 {
-	_DoAppend(&c, 1);	
+	_DoAppend(&c, 1);
 	return *this;
 }
 
@@ -1674,75 +1643,88 @@
 //	#pragma mark - Private or reserved
 
 
-char *
-BString::_Alloc(int32 dataLength)
+status_t
+BString::_Detach()
 {
-	char *dataPtr = fPrivateData ? fPrivateData - sizeof(int32) : NULL;
-	if (dataLength <= 0) {
-		// release buffer
-#if 0
-		free(dataPtr);
-		fPrivateData = NULL;
-		return NULL;
-#else
-		// TODO: think about removing this work-around again; it lets
-		//	BeOS R5 NetPositive run on Haiku - this is obviously ignoring
-		//	the fact, that fPrivateData could be NULL at one point
-		//	(while building the menus from resources).
-		dataLength = 0;
-#endif
+	char* newData = fPrivateData;
+	if (atomic_get(&(*(((vint32*)fPrivateData - 2)))) > 1) {
+		// we share our data with someone else
+		if (atomic_add(&(*(((vint32*)fPrivateData) - 2)), -1) < 1) {
+			; // someone else decrement, we are the last owner
+		} else {
+			// there is still someone who shares our data
+			newData = _Clone(fPrivateData, Length());
+		}
+	} else {
+		; // we don't share our data with someone else
 	}
 
-	int32 allocLength = dataLength + sizeof(int32) + 1;
-	dataPtr = (char *)realloc(dataPtr, allocLength);
+	if (newData)
+		fPrivateData = newData;
+	return newData != NULL ? B_OK : B_NO_MEMORY;
+}
+
+
+char*
+BString::_Realloc(int32 length)
+{
+	if (length == Length())
+		return fPrivateData;
+
+	int32 offset = 2 * sizeof(int32);
+	char *dataPtr = fPrivateData ? fPrivateData - offset : NULL;
+	if (length < 0)
+		length = 0;
+
+	dataPtr = (char*)realloc(dataPtr, length + offset + 1);
 	if (dataPtr) {
-		dataPtr += sizeof(int32);
+		dataPtr += offset;
+
 		fPrivateData = dataPtr;
+		fPrivateData[length] = '\0';
 
-		_SetLength(dataLength);
-		fPrivateData[dataLength] = '\0';
+		_SetLength(length);
+		_SetReferenceCount(1);
 	}
-
 	return dataPtr;
-}	
-
-void
-BString::_Init(const char *str, int32 len)
-{
-	if (_Alloc(len))
-		memcpy(fPrivateData, str, len);
 }
 
 
-#if ENABLE_INLINES
-inline
-#endif
 void
-BString::_DoAssign(const char *str, int32 len)
+BString::_Init(const char* src, int32 length)
 {
-	int32 curLen = Length();
+	fPrivateData = _Clone(src, length);
+	if (!fPrivateData) {
+		int32 offset = 2 * sizeof(int32);
+		fPrivateData = (char *)realloc(fPrivateData, offset + 1);
 
-	if (len == curLen || _GrowBy(len - curLen))
-		memcpy(fPrivateData, str, len);
+		fPrivateData += offset;
+		fPrivateData[0] = '\0';
+
+		_SetLength(0);
+		_SetReferenceCount(1);
+	}
 }
 
 
-#if ENABLE_INLINES
-inline
-#endif
-void
-BString::_DoAppend(const char *str, int32 len)
+char*
+BString::_Clone(const char* data, int32 length)
 {
-	int32 length = Length();
-	if (_GrowBy(len))
-		memcpy(fPrivateData + length, str, len);
-}
+	char* newData = NULL;
+	int32 offset = 2 * sizeof(int32);
+	newData = (char *)realloc(newData, length + offset + 1);
 
+	if (newData) {
+		newData += offset;
+		newData[length] = '\0';
 
-char*
-BString::_GrowBy(int32 size)
-{
-	return _Alloc(Length() + size);
+		*(((vint32*)newData) - 2) = 1;
+		*(((int32*)newData) - 1) = length & 0x7fffffff;
+
+		if (data && length)
+			memcpy(newData, data, length);
+	}
+	return newData;
 }
 
 
@@ -1751,60 +1733,123 @@
 {
 	int32 oldLength = Length();
 
-	char* newData = _Alloc(oldLength + length);
-	if (newData != NULL) {
-		memmove(fPrivateData + offset + length, fPrivateData + offset,
-			oldLength - offset);
-	}
+	if (_Detach() != B_OK)
+		return NULL;
 
-	return newData;
+	memmove(fPrivateData + offset + length, fPrivateData + offset,
+		oldLength - offset);
+	return _Realloc(oldLength + length);
 }
 
 
 char*
 BString::_ShrinkAtBy(int32 offset, int32 length)
-{	
-	if (!fPrivateData)
+{
+	int32 oldLength = Length();
+	if (_Detach() != B_OK)
 		return NULL;
 
-	int32 oldLength = Length();
-
 	memmove(fPrivateData + offset, fPrivateData + offset + length,
 		oldLength - offset - length);
+	return _Realloc(oldLength - length);
+}
 
-	// the following actually should never fail, since we are reducing the size...
-	return _Alloc(oldLength - length);
+
+status_t
+BString::_DetachWith(const char* string, int32 length)
+{
+	char* newData = NULL;
+	if (atomic_get(&(*(((vint32*)fPrivateData) - 2))) > 1) {
+		// we share our data with someone else
+		if (atomic_add(&(*(((vint32*)fPrivateData) - 2)), -1) < 1) {
+			// someone else decrement, we are the last owner
+			newData = _Realloc(length);
+		} else {
+			// there is still someone who shares our data
+			newData = _Clone(string, length);
+		}
+	} 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;
 }
 
 
-#if ENABLE_INLINES
-inline
-#endif
 void
-BString::_DoPrepend(const char *str, int32 count)
+BString::_SetLength(int32 length)
 {
-	if (_OpenAtBy(0, count))
-		memcpy(fPrivateData, str, count);
+	*(((int32*)fPrivateData) - 1) = length & 0x7fffffff;
 }
 
 
-/* XXX: These could be inlined too, if they are too slow */
+void
+BString::_SetReferenceCount(int32 count)
+{
+	*(((vint32*)fPrivateData) - 2) = count;
+}
+
+
+bool
+BString::_DoAppend(const char* string, int32 length)
+{
+	int32 len = Length();
+	if (_DetachWith(fPrivateData, len + length) == B_OK) {
+		if (string && length)
+			memcpy(fPrivateData + len, string, length);
+		return true;
+	}
+	return false;
+}
+
+
+bool
+BString::_DoPrepend(const char* string, int32 length)
+{
+	int32 len = Length();
+	if (_DetachWith(fPrivateData, len + length) == B_OK) {
+		memmove(fPrivateData + length, fPrivateData, len);
+		if (string && length)
+			memcpy(fPrivateData, string, length);
+		return true;
+	}
+	return false;
+}
+
+
+bool
+BString::_DoInsert(const char* string, int32 offset, int32 length)
+{
+	int32 len = Length();
+	if (_DetachWith(fPrivateData, len + length) == B_OK) {
+		memmove(fPrivateData + offset + length, fPrivateData + offset, len - offset);
+		if (string && length)
+			memcpy(fPrivateData + offset, string, length);
+		return true;
+	}
+	return false;
+}
+
+
 int32
-BString::_FindAfter(const char *str, int32 offset, int32 strlen) const
-{	
-	char *ptr = strstr(String() + offset, str);
+BString::_ShortFindAfter(const char* string, int32 len) const
+{
+	const char *ptr = strstr(String(), string);
 
 	if (ptr != NULL)
 		return ptr - String();
-	
+
 	return B_ERROR;
 }
 
 
 int32
-BString::_IFindAfter(const char *str, int32 offset, int32 strlen) const
+BString::_FindAfter(const char* string, int32 offset, int32 strlen) const
 {
-	char *ptr = strcasestr(String() + offset, str);
+	const char *ptr = strstr(String() + offset, string);
 
 	if (ptr != NULL)
 		return ptr - String();
@@ -1814,26 +1859,26 @@
 
 
 int32
-BString::_ShortFindAfter(const char *str, int32 len) const
+BString::_IFindAfter(const char* string, int32 offset, int32 strlen) const
 {
-	char *ptr = strstr(String(), str);
-	
+	const char *ptr = strcasestr(String() + offset, string);
+
 	if (ptr != NULL)
 		return ptr - String();
-		
+
 	return B_ERROR;
 }
 
 
 int32
-BString::_FindBefore(const char *str, int32 offset, int32 strlen) const
+BString::_FindBefore(const char* string, int32 offset, int32 strlen) const
 {
 	if (fPrivateData) {
 		const char *ptr = fPrivateData + offset - strlen;
-		
-		while (ptr >= fPrivateData) {	
-			if (!memcmp(ptr, str, strlen))
-				return ptr - fPrivateData; 
+
+		while (ptr >= fPrivateData) {
+			if (!memcmp(ptr, string, strlen))
+				return ptr - fPrivateData;
 			ptr--;
 		}
 	}
@@ -1842,14 +1887,14 @@
 
 
 int32
-BString::_IFindBefore(const char *str, int32 offset, int32 strlen) const
+BString::_IFindBefore(const char* string, int32 offset, int32 strlen) const
 {
 	if (fPrivateData) {
 		char *ptr1 = fPrivateData + offset - strlen;
-		
+
 		while (ptr1 >= fPrivateData) {
-			if (!strncasecmp(ptr1, str, strlen))
-				return ptr1 - fPrivateData; 
+			if (!strncasecmp(ptr1, string, strlen))
+				return ptr1 - fPrivateData;
 			ptr1--;
 		}
 	}
@@ -1858,15 +1903,88 @@
 
 
 BString&
-BString::_DoReplace(const char *findThis, const char *replaceWith,
-	int32 maxReplaceCount, int32 fromOffset, bool ignoreCase)
+BString::_DoCharacterEscape(const char* string,
+							const char *setOfCharsToEscape, char escapeChar)
 {
-	if (findThis == NULL || maxReplaceCount <= 0 
+	if (_DetachWith(string, strlen(safestr(string))) != B_OK)
+		return *this;
+
+	memcpy(fPrivateData, string, Length());
+
+	PosVect positions;
+	int32 len = Length();
+	int32 pos = 0;
+	for (int32 offset = 0; offset < len; offset += pos + 1) {
+		if ((pos = strcspn(fPrivateData + offset, setOfCharsToEscape)) < len - offset) {
+			if (!positions.Add(offset + pos))
+				return *this;
+		}
+	}
+
+	uint32 count = positions.CountItems();
+	int32 newLength = len + count;
+	if (!newLength) {
+		_Realloc(0);
+		return *this;
+	}
+
+	int32 lastPos = 0;
+	char* oldAdr = fPrivateData;
+	int32 offset = 2 * sizeof(int32);
+
+	char* newData = (char*)malloc(newLength + offset + 1);
+	if (newData) {
+		newData += offset;
+		char* newAdr = newData;
+		for (uint32 i = 0; i < count; ++i) {
+			pos = positions.ItemAt(i);
+			len = pos - lastPos;
+			if (len > 0) {
+				memcpy(newAdr, oldAdr, len);
+				oldAdr += len;
+				newAdr += len;
+			}
+			*newAdr++ = escapeChar;
+			*newAdr++ = *oldAdr++;
+			lastPos = pos + 1;
+		}
+		len = Length() + 1 - lastPos;
+		if (len > 0)
+			memcpy(newAdr, oldAdr, len);
+
+		free(fPrivateData - offset);
+
+		fPrivateData = newData;
+		_SetLength(newLength);
+		fPrivateData[newLength] = '\0';
+	}
+	return *this;
+}
+
+
+BString&
+BString::_DoCharacterDeescape(const char* string, char escapeChar)
+{
+	if (_DetachWith(string, strlen(safestr(string))) != B_OK)
+		return *this;
+
+	memcpy(fPrivateData, string, Length());
+	const char temp[2] = { escapeChar, '\0' };
+	return _DoReplace(temp, "", REPLACE_ALL, 0, KEEP_CASE);
+}
+
+
+BString&
+BString::_DoReplace(const char* findThis, const char* replaceWith,
+					int32 maxReplaceCount, int32 fromOffset, bool ignoreCase)
+{
+	if (findThis == NULL || maxReplaceCount <= 0
 		|| fromOffset < 0 || fromOffset >= Length())
 		return *this;
 
-	typedef int32 (BString::*TFindMethod)(const char *, int32, int32) const;
-	TFindMethod findMethod = ignoreCase ? &BString::_IFindAfter : &BString::_FindAfter;
+	typedef int32 (BString::*TFindMethod)(const char*, int32, int32) const;
+	TFindMethod findMethod = ignoreCase ? &BString::_IFindAfter
+		: &BString::_FindAfter;
 	int32 findLen = strlen(findThis);
 
 	if (!replaceWith)
@@ -1875,10 +1993,9 @@
 	int32 replaceLen = strlen(replaceWith);
 	int32 lastSrcPos = fromOffset;
 	PosVect positions;
-	for(int32 srcPos = 0; 
-			maxReplaceCount > 0 
-			&& (srcPos = (this->*findMethod)(findThis, lastSrcPos, findLen)) >= 0; 
-			maxReplaceCount-- ) {
+	for (int32 srcPos = 0; maxReplaceCount > 0
+		&& (srcPos = (this->*findMethod)(findThis, lastSrcPos, findLen)) >= 0;
+		maxReplaceCount--) {
 		positions.Add(srcPos);
 		lastSrcPos = srcPos + findLen;
 	}
@@ -1888,25 +2005,27 @@
 
 
 void
-BString::_ReplaceAtPositions(const PosVect* positions,
-	int32 searchLen, const char* with, int32 withLen)
+BString::_ReplaceAtPositions(const PosVect* positions, int32 searchLen,
+							 const char* with, int32 withLen)
 {
 	int32 len = Length();
 	uint32 count = positions->CountItems();
 	int32 newLength = len + count * (withLen - searchLen);
 	if (!newLength) {
-		_Alloc(0);
+		_Realloc(0);
 		return;
 	}
 
 	int32 pos;
 	int32 lastPos = 0;
 	char *oldAdr = fPrivateData;
-	char *newData = (char *)malloc(newLength + sizeof(int32) + 1);
+
+	int32 offset = 2 * sizeof(int32);
+	char *newData = (char *)malloc(newLength + offset + 1);
 	if (newData) {
-		newData += sizeof(int32);
+		newData += offset;
 		char *newAdr = newData;
-		for(uint32 i = 0; i < count; ++i) {
+		for (uint32 i = 0; i < count; ++i) {
 			pos = positions->ItemAt(i);
 			len = pos - lastPos;
 			if (len > 0) {
@@ -1923,42 +2042,15 @@
 		if (len > 0)
 			memcpy(newAdr, oldAdr, len);
 
-		free(fPrivateData - sizeof(int32));
+		free(fPrivateData - offset);
+
 		fPrivateData = newData;
-		fPrivateData[newLength] = 0;
-		_SetLength( newLength);
+		_SetLength(newLength);
+		fPrivateData[newLength] = '\0';
 	}
 }
 
 
-#if ENABLE_INLINES
-inline
-#endif
-void
-BString::_SetLength(int32 length)
-{
-	*((int32*)fPrivateData - 1) = length & 0x7fffffff;
-}
-
-
-#if DEBUG
-// AFAIK, these are not implemented in BeOS R5
-// XXX : Test these puppies
-void
-BString::_SetUsingAsCString(bool state)
-{	
-	//TODO: Implement ?		
-}
-
-
-void
-BString::_AssertNotUsingAsCString() const
-{
-	//TODO: Implement ?
-}
-#endif
-
-
 //	#pragma mark - backwards compatibility
 
 
@@ -2002,4 +2094,3 @@
 {
 	return strcasecmp(string1->String(), string2->String());
 }
-
