* fix problem in TextGapBuffer which could lead to data loss at end of buffer
  when deleting large chunks of text
 

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@37987 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Oliver Tappe 2010-08-09 16:30:28 +00:00
parent d91215d3f1
commit 7e31a05ca5
2 changed files with 74 additions and 60 deletions

View File

@ -59,10 +59,10 @@ TextGapBuffer::InsertText(const char* inText, int32 inNumItems, int32 inAtIndex)
inAtIndex = (inAtIndex < 0) ? 0 : inAtIndex;
if (inAtIndex != fGapIndex)
MoveGapTo(inAtIndex);
_MoveGapTo(inAtIndex);
if (fGapCount < inNumItems)
SizeGapTo(inNumItems + kTextGapBufferBlockSize);
_EnlargeGapTo(inNumItems + kTextGapBufferBlockSize);
memcpy(fBuffer + fGapIndex, inText, inNumItems);
@ -95,10 +95,10 @@ TextGapBuffer::InsertText(BFile* file, int32 fileOffset, int32 inNumItems,
inAtIndex = (inAtIndex < 0) ? 0 : inAtIndex;
if (inAtIndex != fGapIndex)
MoveGapTo(inAtIndex);
_MoveGapTo(inAtIndex);
if (fGapCount < inNumItems)
SizeGapTo(inNumItems + kTextGapBufferBlockSize);
_EnlargeGapTo(inNumItems + kTextGapBufferBlockSize);
// Finally, read the data and put it into the buffer
if (file->ReadAt(fileOffset, fBuffer + fGapIndex, inNumItems) > 0) {
@ -121,59 +121,13 @@ TextGapBuffer::RemoveRange(int32 start, int32 end)
inAtIndex = (inAtIndex > fItemCount - 1) ? (fItemCount - 1) : inAtIndex;
inAtIndex = (inAtIndex < 0) ? 0 : inAtIndex;
MoveGapTo(inAtIndex);
_MoveGapTo(inAtIndex);
fGapCount += inNumItems;
fItemCount -= inNumItems;
if (fGapCount > kTextGapBufferBlockSize)
SizeGapTo(kTextGapBufferBlockSize);
}
void
TextGapBuffer::MoveGapTo(int32 toIndex)
{
if (toIndex == fGapIndex)
return;
if (toIndex > fItemCount) {
debugger("MoveGapTo: invalid toIndex supplied");
return;
}
int32 srcIndex = 0;
int32 dstIndex = 0;
int32 count = 0;
if (toIndex > fGapIndex) {
srcIndex = fGapIndex + fGapCount;
dstIndex = fGapIndex;
count = toIndex - fGapIndex;
} else {
srcIndex = toIndex;
dstIndex = toIndex + fGapCount;
count = fGapIndex- toIndex;
}
if (count > 0)
memmove(fBuffer + dstIndex, fBuffer + srcIndex, count);
fGapIndex = toIndex;
}
void
TextGapBuffer::SizeGapTo(long inCount)
{
if (inCount == fGapCount)
return;
fBuffer = (char*)realloc(fBuffer, fItemCount + inCount);
memmove(fBuffer + fGapIndex + inCount,
fBuffer + fGapIndex + fGapCount,
fBufferCount - (fGapIndex + fGapCount));
fGapCount = inCount;
fBufferCount = fItemCount + fGapCount;
_ShrinkGapTo(kTextGapBufferBlockSize);
}
@ -195,7 +149,6 @@ TextGapBuffer::GetString(int32 fromOffset, int32* _numBytes)
result = fBuffer + fromOffset;
if (!isStartBeforeGap)
result += fGapCount;
} else {
if (fScratchSize < numBytes) {
fScratchBuffer = (char*)realloc(fScratchBuffer, numBytes);
@ -284,10 +237,10 @@ TextGapBuffer::Text()
const char*
TextGapBuffer::RealText()
{
MoveGapTo(fItemCount);
_MoveGapTo(fItemCount);
if (fGapCount == 0)
SizeGapTo(kTextGapBufferBlockSize);
_EnlargeGapTo(kTextGapBufferBlockSize);
fBuffer[fItemCount] = '\0';
return fBuffer;
@ -348,5 +301,65 @@ TextGapBuffer::SetPasswordMode(bool state)
fPasswordMode = state;
}
} // namespace BPrivate
void
TextGapBuffer::_MoveGapTo(int32 toIndex)
{
if (toIndex == fGapIndex)
return;
if (toIndex > fItemCount) {
debugger("MoveGapTo: invalid toIndex supplied");
return;
}
int32 srcIndex = 0;
int32 dstIndex = 0;
int32 count = 0;
if (toIndex > fGapIndex) {
srcIndex = fGapIndex + fGapCount;
dstIndex = fGapIndex;
count = toIndex - fGapIndex;
} else {
srcIndex = toIndex;
dstIndex = toIndex + fGapCount;
count = fGapIndex- toIndex;
}
if (count > 0)
memmove(fBuffer + dstIndex, fBuffer + srcIndex, count);
fGapIndex = toIndex;
}
void
TextGapBuffer::_EnlargeGapTo(long inCount)
{
if (inCount == fGapCount)
return;
fBuffer = (char*)realloc(fBuffer, fItemCount + inCount);
memmove(fBuffer + fGapIndex + inCount, fBuffer + fGapIndex + fGapCount,
fBufferCount - (fGapIndex + fGapCount));
fGapCount = inCount;
fBufferCount = fItemCount + fGapCount;
}
void
TextGapBuffer::_ShrinkGapTo(long inCount)
{
if (inCount == fGapCount)
return;
memmove(fBuffer + fGapIndex + inCount, fBuffer + fGapIndex + fGapCount,
fBufferCount - (fGapIndex + fGapCount));
fBuffer = (char*)realloc(fBuffer, fItemCount + inCount);
fGapCount = inCount;
fBufferCount = fItemCount + fGapCount;
}
} // namespace BPrivate

View File

@ -30,9 +30,6 @@ public:
int32 amount, int32 atIndex);
void RemoveRange(int32 start, int32 end);
void MoveGapTo(int32 toIndex);
void SizeGapTo(int32 inCount);
bool FindChar(char inChar, int32 fromIndex,
int32* ioDelta);
@ -49,7 +46,11 @@ public:
bool PasswordMode() const;
void SetPasswordMode(bool);
protected:
private:
void _MoveGapTo(int32 toIndex);
void _EnlargeGapTo(int32 inCount);
void _ShrinkGapTo(int32 inCount);
int32 fItemCount; // logical count
char* fBuffer; // allocated memory
int32 fBufferCount; // physical count