* As found by Karsten, the reference count was not initialized in

_ReplaceAtPositions(), and _DoCharacterEscape() (we don't need to preserve
  it, though, as it must be 1).
* Factored out an _Alloc() method which is now always called when the private
  data is allocated. It also takes care of correct initialization (and thus
  fixes the above problem).
* This fix finally allows turning on reference counting again, thanks Karsten!
* Minor cleanup, renamed "oldAdr"/"newAdr" to "oldString", resp. "newString".


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24348 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2008-03-10 19:14:05 +00:00
parent 7c58a46830
commit bf4ddb61e1
2 changed files with 78 additions and 69 deletions
+1
View File
@@ -221,6 +221,7 @@ private:
// Management // Management
status_t _Detach(); status_t _Detach();
char* _Alloc(int32 length);
char* _Realloc(int32 length); char* _Realloc(int32 length);
void _Init(const char* src, int32 length); void _Init(const char* src, int32 length);
char* _Clone(const char* data, int32 length); char* _Clone(const char* data, int32 length);
+77 -69
View File
@@ -1678,6 +1678,27 @@ BString::_Detach()
} }
char*
BString::_Alloc(int32 length)
{
if (length < 0)
return NULL;
char* newData = (char *)malloc(length + kPrivateDataOffset + 1);
if (newData == NULL)
return NULL;
newData += kPrivateDataOffset;
newData[length] = '\0';
// initialize reference count & length
*(((vint32*)newData) - 2) = 1;
*(((int32*)newData) - 1) = length & 0x7fffffff;
return newData;
}
char* char*
BString::_Realloc(int32 length) BString::_Realloc(int32 length)
{ {
@@ -1713,18 +1734,11 @@ BString::_Init(const char* src, int32 length)
char* char*
BString::_Clone(const char* data, int32 length) BString::_Clone(const char* data, int32 length)
{ {
char* newData = (char *)malloc(length + kPrivateDataOffset + 1); char* newData = _Alloc(length);
if (newData == NULL) if (newData == NULL)
return NULL; return NULL;
newData += kPrivateDataOffset; if (data != NULL && length > 0) {
newData[length] = '\0';
// initialize reference count & length
*(((vint32*)newData) - 2) = 1;
*(((int32*)newData) - 1) = length & 0x7fffffff;
if (data && length) {
// "data" may not span over the whole length // "data" may not span over the whole length
strncpy(newData, data, length); strncpy(newData, data, length);
} }
@@ -1808,8 +1822,7 @@ BString::_ReferenceCount() const
inline bool inline bool
BString::_IsShareable() const BString::_IsShareable() const
{ {
return false; return fPrivateData != NULL && _ReferenceCount() >= 0;
// return fPrivateData != NULL && _ReferenceCount() >= 0;
} }
@@ -1934,7 +1947,7 @@ BString::_IFindBefore(const char* string, int32 offset, int32 strlen) const
BString& BString&
BString::_DoCharacterEscape(const char* string, const char *setOfCharsToEscape, BString::_DoCharacterEscape(const char* string, const char* setOfCharsToEscape,
char escapeChar) char escapeChar)
{ {
if (_DetachWith(string, strlen(safestr(string))) != B_OK) if (_DetachWith(string, strlen(safestr(string))) != B_OK)
@@ -1943,50 +1956,48 @@ BString::_DoCharacterEscape(const char* string, const char *setOfCharsToEscape,
memcpy(fPrivateData, string, Length()); memcpy(fPrivateData, string, Length());
PosVect positions; PosVect positions;
int32 len = Length(); int32 length = Length();
int32 pos = 0; int32 pos = 0;
for (int32 offset = 0; offset < len; offset += pos + 1) { for (int32 offset = 0; offset < length; offset += pos + 1) {
if ((pos = strcspn(fPrivateData + offset, setOfCharsToEscape)) < len - offset) { if ((pos = strcspn(fPrivateData + offset, setOfCharsToEscape))
< length - offset) {
if (!positions.Add(offset + pos)) if (!positions.Add(offset + pos))
return *this; return *this;
} }
} }
uint32 count = positions.CountItems(); uint32 count = positions.CountItems();
int32 newLength = len + count; int32 newLength = length + count;
if (!newLength) { if (!newLength) {
_Realloc(0); _Realloc(0);
return *this; return *this;
} }
int32 lastPos = 0; char* newData = _Alloc(newLength);
char* oldAdr = fPrivateData;
char* newData = (char*)malloc(newLength + kPrivateDataOffset + 1);
if (newData) { if (newData) {
newData += kPrivateDataOffset; char* oldString = fPrivateData;
char* newAdr = newData; char* newString = newData;
int32 lastPos = 0;
for (uint32 i = 0; i < count; ++i) { for (uint32 i = 0; i < count; ++i) {
pos = positions.ItemAt(i); pos = positions.ItemAt(i);
len = pos - lastPos; length = pos - lastPos;
if (len > 0) { if (length > 0) {
memcpy(newAdr, oldAdr, len); memcpy(newString, oldString, length);
oldAdr += len; oldString += length;
newAdr += len; newString += length;
} }
*newAdr++ = escapeChar; *newString++ = escapeChar;
*newAdr++ = *oldAdr++; *newString++ = *oldString++;
lastPos = pos + 1; lastPos = pos + 1;
} }
len = Length() + 1 - lastPos;
if (len > 0) length = Length() + 1 - lastPos;
memcpy(newAdr, oldAdr, len); if (length > 0)
memcpy(newString, oldString, length);
_FreePrivateData(); _FreePrivateData();
fPrivateData = newData; fPrivateData = newData;
_SetLength(newLength);
fPrivateData[newLength] = '\0';
} }
return *this; return *this;
} }
@@ -1999,8 +2010,8 @@ BString::_DoCharacterDeescape(const char* string, char escapeChar)
return *this; return *this;
memcpy(fPrivateData, string, Length()); memcpy(fPrivateData, string, Length());
const char temp[2] = { escapeChar, '\0' }; const char escape[2] = { escapeChar, '\0' };
return _DoReplace(temp, "", REPLACE_ALL, 0, KEEP_CASE); return _DoReplace(escape, "", REPLACE_ALL, 0, KEEP_CASE);
} }
@@ -2025,7 +2036,7 @@ BString::_DoReplace(const char* findThis, const char* replaceWith,
PosVect positions; PosVect positions;
for (int32 srcPos = 0; maxReplaceCount > 0 for (int32 srcPos = 0; maxReplaceCount > 0
&& (srcPos = (this->*findMethod)(findThis, lastSrcPos, findLen)) >= 0; && (srcPos = (this->*findMethod)(findThis, lastSrcPos, findLen)) >= 0;
maxReplaceCount--) { maxReplaceCount--) {
positions.Add(srcPos); positions.Add(srcPos);
lastSrcPos = srcPos + findLen; lastSrcPos = srcPos + findLen;
} }
@@ -2035,48 +2046,45 @@ BString::_DoReplace(const char* findThis, const char* replaceWith,
void void
BString::_ReplaceAtPositions(const PosVect* positions, int32 searchLen, BString::_ReplaceAtPositions(const PosVect* positions, int32 searchLength,
const char* with, int32 withLen) const char* with, int32 withLength)
{ {
int32 len = Length(); int32 length = Length();
uint32 count = positions->CountItems(); uint32 count = positions->CountItems();
int32 newLength = len + count * (withLen - searchLen); int32 newLength = length + count * (withLength - searchLength);
if (!newLength) { if (!newLength) {
_Realloc(0); _Realloc(0);
return; return;
} }
int32 pos; char *newData = _Alloc(newLength);
if (newData == NULL)
return;
char *oldString = fPrivateData;
char *newString = newData;
int32 lastPos = 0; int32 lastPos = 0;
char *oldAdr = fPrivateData;
char *newData = (char *)malloc(newLength + kPrivateDataOffset + 1); for (uint32 i = 0; i < count; ++i) {
if (newData) { int32 pos = positions->ItemAt(i);
newData += kPrivateDataOffset; length = pos - lastPos;
char *newAdr = newData; if (length > 0) {
for (uint32 i = 0; i < count; ++i) { memcpy(newString, oldString, length);
pos = positions->ItemAt(i); oldString += length;
len = pos - lastPos; newString += length;
if (len > 0) {
memcpy(newAdr, oldAdr, len);
oldAdr += len;
newAdr += len;
}
memcpy(newAdr, with, withLen);
oldAdr += searchLen;
newAdr += withLen;
lastPos = pos+searchLen;
} }
len = Length() + 1 - lastPos; memcpy(newString, with, withLength);
if (len > 0) oldString += searchLength;
memcpy(newAdr, oldAdr, len); newString += withLength;
lastPos = pos + searchLength;
_FreePrivateData();
fPrivateData = newData;
_SetLength(newLength);
fPrivateData[newLength] = '\0';
} }
length = Length() + 1 - lastPos;
if (length > 0)
memcpy(newString, oldString, length);
_FreePrivateData();
fPrivateData = newData;
} }