* After my last change, _IsShareable() was called on the wrong string in the

copy constructors, effectively turning of references completely.
* Since that caused troubles (NetPositive now crashes when started), I
  temporarily disabled references by letting _IsShareable() always return
  false until the issue is resolved.
* _FreePrivateData() now sets the fPrivateData member to NULL, and is also
  safe to be called when fPrivateData is NULL.
* Removed my comment about the threading problem in _Detach() and _DetachWith()
  as that just couldn't happen.
* _Clone() must not use memcpy() as the string pointed to by "data" might not
  be as long as "length".
* LockBuffer() now marks a string as unshareable.
* Minor cleanup.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24345 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2008-03-10 14:14:44 +00:00
parent 417889ced8
commit 688c14266c
2 changed files with 40 additions and 27 deletions
+3 -2
View File
@@ -254,8 +254,9 @@ private:
const char* with, int32 withLen); const char* with, int32 withLen);
private: private:
inline int32& _ReferenceCount(); int32& _ReferenceCount();
bool _IsShareable(); const int32& _ReferenceCount() const;
bool _IsShareable() const;
void _FreePrivateData(); void _FreePrivateData();
char* fPrivateData; char* fPrivateData;
+37 -25
View File
@@ -183,7 +183,7 @@ 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 (_IsShareable()) { if (string._IsShareable()) {
fPrivateData = string.fPrivateData; fPrivateData = string.fPrivateData;
atomic_add(&_ReferenceCount(), 1); atomic_add(&_ReferenceCount(), 1);
// string cannot go away right now // string cannot go away right now
@@ -283,7 +283,7 @@ BString::SetTo(const BString& string)
_FreePrivateData(); _FreePrivateData();
// if source is sharable share, otherwise clone // if source is sharable share, otherwise clone
if (_IsShareable()) { if (string._IsShareable()) {
fPrivateData = string.fPrivateData; fPrivateData = string.fPrivateData;
atomic_add(&_ReferenceCount(), 1); atomic_add(&_ReferenceCount(), 1);
// the string cannot go away right now // the string cannot go away right now
@@ -344,8 +344,7 @@ BString::SetTo(char c, int32 count)
BString& BString&
BString::CopyInto(BString& into, int32 fromOffset, BString::CopyInto(BString& into, int32 fromOffset, int32 length) const
int32 length) const
{ {
if (this != &into) if (this != &into)
into.SetTo(fPrivateData + fromOffset, length); into.SetTo(fPrivateData + fromOffset, length);
@@ -501,7 +500,7 @@ BString::Insert(const char* string, int32 length, int32 position)
BString& BString&
BString::Insert(const char* string, int32 fromOffset, int32 length, BString::Insert(const char* string, int32 fromOffset, int32 length,
int32 position) int32 position)
{ {
if (string) if (string)
Insert(string + fromOffset, length, position); Insert(string + fromOffset, length, position);
@@ -519,8 +518,7 @@ BString::Insert(const BString& string, int32 position)
BString& BString&
BString::Insert(const BString& string, int32 length, BString::Insert(const BString& string, int32 length, int32 position)
int32 position)
{ {
if ((fPrivateData != string.fPrivateData) && string.Length() > 0) if ((fPrivateData != string.fPrivateData) && string.Length() > 0)
Insert(string.String(), length, position); Insert(string.String(), length, position);
@@ -529,8 +527,8 @@ BString::Insert(const BString& string, int32 length,
BString& BString&
BString::Insert(const BString& string, int32 fromOffset, BString::Insert(const BString& string, int32 fromOffset, int32 length,
int32 length, int32 position) int32 position)
{ {
if ((fPrivateData != string.fPrivateData) && string.Length() > 0) if ((fPrivateData != string.fPrivateData) && string.Length() > 0)
Insert(string.String() + fromOffset, length, position); Insert(string.String() + fromOffset, length, position);
@@ -1078,7 +1076,7 @@ BString::ReplaceAll(char replaceThis, char withThis, int32 fromOffset)
BString& BString&
BString::Replace(char replaceThis, char withThis, int32 maxReplaceCount, BString::Replace(char replaceThis, char withThis, int32 maxReplaceCount,
int32 fromOffset) int32 fromOffset)
{ {
fromOffset = min_clamp0(fromOffset, Length()); fromOffset = min_clamp0(fromOffset, Length());
int32 pos = FindFirst(replaceThis, fromOffset); int32 pos = FindFirst(replaceThis, fromOffset);
@@ -1142,7 +1140,7 @@ BString::ReplaceLast(const char* replaceThis, const char* withThis)
BString& BString&
BString::ReplaceAll(const char* replaceThis, const char* withThis, BString::ReplaceAll(const char* replaceThis, const char* withThis,
int32 fromOffset) int32 fromOffset)
{ {
if (!replaceThis || !withThis || FindFirst(replaceThis) < 0) if (!replaceThis || !withThis || FindFirst(replaceThis) < 0)
return *this; return *this;
@@ -1157,7 +1155,7 @@ BString::ReplaceAll(const char* replaceThis, const char* withThis,
BString& BString&
BString::Replace(const char* replaceThis, const char* withThis, BString::Replace(const char* replaceThis, const char* withThis,
int32 maxReplaceCount, int32 fromOffset) int32 maxReplaceCount, int32 fromOffset)
{ {
if (!replaceThis || !withThis || maxReplaceCount <= 0 if (!replaceThis || !withThis || maxReplaceCount <= 0
|| FindFirst(replaceThis) < 0) || FindFirst(replaceThis) < 0)
@@ -1217,7 +1215,7 @@ BString::IReplaceAll(char replaceThis, char withThis, int32 fromOffset)
BString& BString&
BString::IReplace(char replaceThis, char withThis, int32 maxReplaceCount, BString::IReplace(char replaceThis, char withThis, int32 maxReplaceCount,
int32 fromOffset) int32 fromOffset)
{ {
char tmp[2] = { replaceThis, '\0' }; char tmp[2] = { replaceThis, '\0' };
fromOffset = min_clamp0(fromOffset, Length()); fromOffset = min_clamp0(fromOffset, Length());
@@ -1282,7 +1280,7 @@ BString::IReplaceLast(const char* replaceThis, const char* withThis)
BString& BString&
BString::IReplaceAll(const char* replaceThis, const char* withThis, BString::IReplaceAll(const char* replaceThis, const char* withThis,
int32 fromOffset) int32 fromOffset)
{ {
if (!replaceThis || !withThis || IFindFirst(replaceThis) < 0) if (!replaceThis || !withThis || IFindFirst(replaceThis) < 0)
return *this; return *this;
@@ -1297,7 +1295,7 @@ BString::IReplaceAll(const char* replaceThis, const char* withThis,
BString& BString&
BString::IReplace(const char* replaceThis, const char* withThis, BString::IReplace(const char* replaceThis, const char* withThis,
int32 maxReplaceCount, int32 fromOffset) int32 maxReplaceCount, int32 fromOffset)
{ {
if (!replaceThis || !withThis || maxReplaceCount <= 0 if (!replaceThis || !withThis || maxReplaceCount <= 0
|| FindFirst(replaceThis) < 0) || FindFirst(replaceThis) < 0)
@@ -1402,6 +1400,8 @@ BString::LockBuffer(int32 maxLength)
length += maxLength - length; length += maxLength - length;
_DetachWith(fPrivateData, length); _DetachWith(fPrivateData, length);
_ReferenceCount() = -1;
// mark unshareable
return fPrivateData; return fPrivateData;
} }
@@ -1418,6 +1418,8 @@ BString::UnlockBuffer(int32 length)
_Realloc(length); _Realloc(length);
fPrivateData[length] = '\0'; fPrivateData[length] = '\0';
_ReferenceCount() = 1;
// mark shareable again
return *this; return *this;
} }
@@ -1650,8 +1652,6 @@ BString::_Detach()
{ {
char* newData = fPrivateData; char* newData = fPrivateData;
// TODO: this is not thread safe! A string could be used in than one
// thread at a time (and one of those threads could create a ref)
if (atomic_get(&_ReferenceCount()) > 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()); newData = _Clone(fPrivateData, Length());
@@ -1714,8 +1714,10 @@ BString::_Clone(const char* data, int32 length)
*(((vint32*)newData) - 2) = 1; *(((vint32*)newData) - 2) = 1;
*(((int32*)newData) - 1) = length & 0x7fffffff; *(((int32*)newData) - 1) = length & 0x7fffffff;
if (data && length) if (data && length) {
memcpy(newData, data, length); // "data" may not span over the whole length
strncpy(newData, data, length);
}
return newData; return newData;
} }
@@ -1752,8 +1754,7 @@ status_t
BString::_DetachWith(const char* string, int32 length) BString::_DetachWith(const char* string, int32 length)
{ {
char* newData = NULL; char* newData = NULL;
// TODO: this is not thread safe! A string could be used in than one
// thread at a time (and one of those threads could create a ref)
if (atomic_get(&_ReferenceCount()) > 1) { if (atomic_get(&_ReferenceCount()) > 1) {
// we might share our data with someone else // we might share our data with someone else
newData = _Clone(string, length); newData = _Clone(string, length);
@@ -1787,17 +1788,28 @@ BString::_ReferenceCount()
} }
inline bool inline const int32&
BString::_IsShareable() BString::_ReferenceCount() const
{ {
return fPrivateData != NULL && _ReferenceCount() >= 0; return *(((int32 *)fPrivateData) - 2);
}
inline bool
BString::_IsShareable() const
{
return false;
// return fPrivateData != NULL && _ReferenceCount() >= 0;
} }
void void
BString::_FreePrivateData() BString::_FreePrivateData()
{ {
free(fPrivateData - kPrivateDataOffset); if (fPrivateData != NULL) {
free(fPrivateData - kPrivateDataOffset);
fPrivateData = NULL;
}
} }