From ad7645f8e9eb7c45a0ccb7f47eabfdde3728083e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathias=20Panzenb=C3=B6ck?= Date: Mon, 1 Aug 2011 04:13:55 +0200 Subject: [PATCH 1/3] ByteVector::replace performance improvements --- taglib/toolkit/tbytevector.cpp | 70 ++++++++++++++++++++++++---------- 1 file changed, 50 insertions(+), 20 deletions(-) diff --git a/taglib/toolkit/tbytevector.cpp b/taglib/toolkit/tbytevector.cpp index 9fb77b12..d90f464f 100644 --- a/taglib/toolkit/tbytevector.cpp +++ b/taglib/toolkit/tbytevector.cpp @@ -431,29 +431,59 @@ 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(); + const uint withSize = with.size(); + const uint patternSize = pattern.size(); + int offset = 0; - 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); - - ::memcpy(data() + offset, with.data(), withSize); - - offset = find(pattern, offset + withSize); + 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; } + // 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; + } + + // 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; } From 3b14dc3e94d9dbade686563ceda5429e3ff84628 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathias=20Panzenb=C3=B6ck?= Date: Mon, 1 Aug 2011 15:14:58 +0200 Subject: [PATCH 2/3] ByteVector::replace: forgot detach() and opt. when pattern not found --- taglib/toolkit/tbytevector.cpp | 36 +++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/taglib/toolkit/tbytevector.cpp b/taglib/toolkit/tbytevector.cpp index d90f464f..623a8c37 100644 --- a/taglib/toolkit/tbytevector.cpp +++ b/taglib/toolkit/tbytevector.cpp @@ -436,25 +436,29 @@ ByteVector &ByteVector::replace(const ByteVector &pattern, const ByteVector &wit 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; + // I think this case might be common enough to optimize it + detach(); + offset = find(pattern); + while(offset >= 0) { + ::memcpy(data() + offset, with.data(), withSize); + offset = find(pattern, offset + withSize); + } + return *this; } // 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; + int next = find(pattern, offset); + if(next < 0) { + if(offset == 0) + // pattern not found, do nothing: + return *this; + newSize += size() - offset; + break; + } + newSize += (next - offset) + withSize; + offset = next + patternSize; } // new private data of appropriate size: @@ -467,8 +471,8 @@ ByteVector &ByteVector::replace(const ByteVector &pattern, const ByteVector &wit for(;;) { int next = find(pattern, offset); if(next < 0) { - ::memcpy(target, source + offset, size() - offset); - break; + ::memcpy(target, source + offset, size() - offset); + break; } int chunkSize = next - offset; ::memcpy(target, source + offset, chunkSize); From 11c993e9f0b29c5f3bf9df68d9f27b3dd1a21afe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathias=20Panzenb=C3=B6ck?= Date: Mon, 1 Aug 2011 15:33:27 +0200 Subject: [PATCH 3/3] use DATA() macro --- taglib/toolkit/tbytevector.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/taglib/toolkit/tbytevector.cpp b/taglib/toolkit/tbytevector.cpp index 623a8c37..5edbfbfe 100644 --- a/taglib/toolkit/tbytevector.cpp +++ b/taglib/toolkit/tbytevector.cpp @@ -463,7 +463,7 @@ ByteVector &ByteVector::replace(const ByteVector &pattern, const ByteVector &wit // new private data of appropriate size: ByteVectorPrivate *newData = new ByteVectorPrivate(newSize, 0); - char *target = &newData->data[0]; + char *target = DATA(newData); const char *source = data(); // copy modified data into new private data: