Skip to content

Commit

Permalink
ByteVector::replace performance improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
panzi committed Aug 1, 2011
1 parent fb2decb commit ad7645f
Showing 1 changed file with 49 additions and 19 deletions.
68 changes: 49 additions & 19 deletions taglib/toolkit/tbytevector.cpp
Expand Up @@ -431,28 +431,58 @@ ByteVector &ByteVector::replace(const ByteVector &pattern, const ByteVector &wit
if(pattern.size() == 0 || pattern.size() > size())
return *this;

const int patternSize = pattern.size();
const int withSize = with.size();

int offset = find(pattern);

while(offset >= 0) {

const int originalSize = size();

if(withSize > patternSize)
resize(originalSize + withSize - patternSize);

if(patternSize != withSize)
::memcpy(data() + offset + withSize, mid(offset + patternSize).data(), originalSize - offset - patternSize);

if(withSize < patternSize)
resize(originalSize + withSize - patternSize);
const uint withSize = with.size();
const uint patternSize = pattern.size();
int offset = 0;

if(withSize == patternSize) {
// I think this case might be common enough to optimize it
offset = find(pattern);
while(offset >= 0) {
::memcpy(data() + offset, with.data(), withSize);
offset = find(pattern, offset + withSize);
}
return *this;
}

::memcpy(data() + offset, with.data(), withSize);
// calculate new size:
uint newSize = 0;
for(;;) {
int next = find(pattern, offset);
if(next < 0) {
newSize += size() - offset;
break;
}
newSize += (next - offset) + withSize;
offset = next + patternSize;
}

offset = find(pattern, offset + withSize);
// new private data of appropriate size:
ByteVectorPrivate *newData = new ByteVectorPrivate(newSize, 0);
char *target = &newData->data[0];
const char *source = data();

// copy modified data into new private data:
offset = 0;
for(;;) {
int next = find(pattern, offset);
if(next < 0) {
::memcpy(target, source + offset, size() - offset);
break;
}
int chunkSize = next - offset;
::memcpy(target, source + offset, chunkSize);
target += chunkSize;
::memcpy(target, with.data(), withSize);
target += withSize;
offset += chunkSize + patternSize;
}

// replace private data:
if(d->deref())
delete d;

d = newData;

return *this;
}
Expand Down

0 comments on commit ad7645f

Please sign in to comment.