diff --git a/xpcom/string/nsSubstring.cpp b/xpcom/string/nsSubstring.cpp index a13e6d979121..052e6399ec8d 100644 --- a/xpcom/string/nsSubstring.cpp +++ b/xpcom/string/nsSubstring.cpp @@ -106,7 +106,7 @@ static nsStringStats gStringStats; // --------------------------------------------------------------------------- -void +inline void ReleaseData(void* aData, uint32_t aFlags) { if (aFlags & nsSubstring::F_SHARED) { diff --git a/xpcom/string/nsTString.h b/xpcom/string/nsTString.h index 75dafef42349..6871937d9a25 100644 --- a/xpcom/string/nsTString.h +++ b/xpcom/string/nsTString.h @@ -386,11 +386,6 @@ public: #ifdef CharT_is_PRUnichar void ReplaceChar(const char16_t* aSet, char16_t aNewChar); #endif - /** - * Replace all occurrences of aTarget with aNewValue. - * The complexity of this function is O(n+m), n being the length of the string - * and m being the length of aNewValue. - */ void ReplaceSubstring(const self_type& aTarget, const self_type& aNewValue); void ReplaceSubstring(const char_type* aTarget, const char_type* aNewValue); @@ -463,14 +458,6 @@ protected: : substring_type(aData, aLength, aFlags) { } - - struct Segment { - uint32_t mBegin, mLength; - Segment(uint32_t aBegin, uint32_t aLength) - : mBegin(aBegin) - , mLength(aLength) - {} - }; }; diff --git a/xpcom/string/nsTStringObsolete.cpp b/xpcom/string/nsTStringObsolete.cpp index d88612f2f0c5..edfac983f4f0 100644 --- a/xpcom/string/nsTStringObsolete.cpp +++ b/xpcom/string/nsTStringObsolete.cpp @@ -4,7 +4,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "nsTArray.h" + /** * nsTString::Find @@ -451,8 +451,6 @@ nsTString_CharT::ReplaceChar( const char* aSet, char_type aNewChar ) } } -void ReleaseData(void* aData, uint32_t aFlags); - void nsTString_CharT::ReplaceSubstring( const char_type* aTarget, const char_type* aNewValue ) { @@ -466,91 +464,19 @@ nsTString_CharT::ReplaceSubstring( const self_type& aTarget, const self_type& aN if (aTarget.Length() == 0) return; - // Remember all of the non-matching parts. - nsAutoTArray nonMatching; uint32_t i = 0; - uint32_t newLength = 0; - while (true) + while (i < mLength) { int32_t r = FindSubstring(mData + i, mLength - i, static_cast(aTarget.Data()), aTarget.Length(), false); - int32_t until = (r == kNotFound) ? mLength - i : r; - nonMatching.AppendElement(Segment(i, until)); - newLength += until; - if (r == kNotFound) { + if (r == kNotFound) break; - } - newLength += aNewValue.Length(); - i += r + aTarget.Length(); - if (i >= mLength) { - // Add an auxiliary entry at the end of the list to help as an edge case - // for the algorithms below. - nonMatching.AppendElement(Segment(mLength, 0)); - break; - } + Replace(i + r, aTarget.Length(), aNewValue); + i += r + aNewValue.Length(); } - - // If there's only one non-matching segment, then the target string was not - // found, and there's nothing to do. - if (nonMatching.Length() == 1) { - MOZ_ASSERT(nonMatching[0].mBegin == 0 && nonMatching[0].mLength == mLength, - "We should have the correct non-matching segment."); - return; - } - - // Make sure that we can mutate our buffer. - char_type* oldData; - uint32_t oldFlags; - if (!MutatePrep(newLength, &oldData, &oldFlags)) - return; - if (oldData) { - // Copy all of the old data to the new buffer. - char_traits::copy(mData, oldData, mLength); - ::ReleaseData(oldData, oldFlags); - } - - if (aTarget.Length() >= aNewValue.Length()) { - // In the shrinking case, start filling the buffer from the beginning. - const uint32_t delta = (aTarget.Length() - aNewValue.Length()); - for (i = 1; i < nonMatching.Length(); ++i) { - // When we move the i'th non-matching segment into position, we need to - // account for the characters deleted by the previous |i| replacements by - // subtracting |i * delta|. - const char_type* sourceSegmentPtr = mData + nonMatching[i].mBegin; - char_type* destinationSegmentPtr = mData + nonMatching[i].mBegin - i * delta; - memmove(destinationSegmentPtr, sourceSegmentPtr, - sizeof(char_type) * nonMatching[i].mLength); - // Write the i'th replacement immediately before the new i'th non-matching - // segment. - char_traits::copy(destinationSegmentPtr - aNewValue.Length(), - aNewValue.Data(), aNewValue.Length()); - } - } else { - // In the growing case, start filling the buffer from the end. - const uint32_t delta = (aNewValue.Length() - aTarget.Length()); - const uint32_t numNonMatching = nonMatching.Length(); - if (numNonMatching > 1) { - for (i = numNonMatching - 1; i > 0; --i) { - // When we move the i'th non-matching segment into position, we need to - // account for the characters added by the previous |i| replacements - // by adding |i * delta|. - const char_type* sourceSegmentPtr = mData + nonMatching[i].mBegin; - char_type* destinationSegmentPtr = mData + nonMatching[i].mBegin + i * delta; - memmove(destinationSegmentPtr, sourceSegmentPtr, - sizeof(char_type) * nonMatching[i].mLength); - // Write the i'th replacement immediately before the new i'th - // non-matching segment. - char_traits::copy(destinationSegmentPtr - aNewValue.Length(), - aNewValue.Data(), aNewValue.Length()); - } - } - } - - // Adjust the length and make sure the string is null terminated. - mLength = newLength; - mData[mLength] = char_type(0); } + /** * nsTString::Trim */ diff --git a/xpcom/tests/TestStrings.cpp b/xpcom/tests/TestStrings.cpp index 65865352e9e0..bf9325f89e75 100644 --- a/xpcom/tests/TestStrings.cpp +++ b/xpcom/tests/TestStrings.cpp @@ -451,156 +451,6 @@ bool test_replace_substr_2() return true; } -bool test_replace_substr_3() - { - nsCString s; - s.Assign("abcabcabc"); - s.ReplaceSubstring("ca", "X"); - bool r = strcmp(s.get(), "abXbXbc") == 0; - if (!r) - { - printf("[s=%s]\n", s.get()); - return false; - } - - s.Assign("abcabcabc"); - s.ReplaceSubstring("ca", "XYZ"); - r = strcmp(s.get(), "abXYZbXYZbc") == 0; - if (!r) - { - printf("[s=%s]\n", s.get()); - return false; - } - - s.Assign("abcabcabc"); - s.ReplaceSubstring("ca", "XY"); - r = strcmp(s.get(), "abXYbXYbc") == 0; - if (!r) - { - printf("[s=%s]\n", s.get()); - return false; - } - - s.Assign("abcabcabc"); - s.ReplaceSubstring("ca", "XYZ!"); - r = strcmp(s.get(), "abXYZ!bXYZ!bc") == 0; - if (!r) - { - printf("[s=%s]\n", s.get()); - return false; - } - - s.Assign("abcdabcdabcd"); - s.ReplaceSubstring("bcd", "X"); - r = strcmp(s.get(), "aXaXaX") == 0; - if (!r) - { - printf("[s=%s]\n", s.get()); - return false; - } - - s.Assign("abcdabcdabcd"); - s.ReplaceSubstring("bcd", "XYZ!"); - r = strcmp(s.get(), "aXYZ!aXYZ!aXYZ!") == 0; - if (!r) - { - printf("[s=%s]\n", s.get()); - return false; - } - - s.Assign("abcdabcdabcd"); - s.ReplaceSubstring("bcd", "XY"); - r = strcmp(s.get(), "aXYaXYaXY") == 0; - if (!r) - { - printf("[s=%s]\n", s.get()); - return false; - } - - s.Assign("abcdabcdabcd"); - s.ReplaceSubstring("bcd", "XYZABC"); - r = strcmp(s.get(), "aXYZABCaXYZABCaXYZABC") == 0; - if (!r) - { - printf("[s=%s]\n", s.get()); - return false; - } - - s.Assign("abcdabcdabcd"); - s.ReplaceSubstring("bcd", "XYZ"); - r = strcmp(s.get(), "aXYZaXYZaXYZ") == 0; - if (!r) - { - printf("[s=%s]\n", s.get()); - return false; - } - - s.Assign("abcdabcdabcd"); - s.ReplaceSubstring("bcd", "XYZ!"); - r = strcmp(s.get(), "aXYZ!aXYZ!aXYZ!") == 0; - if (!r) - { - printf("[s=%s]\n", s.get()); - return false; - } - - s.Assign("abcdabcdabcd"); - s.ReplaceSubstring("ab", "X"); - r = strcmp(s.get(), "XcdXcdXcd") == 0; - if (!r) - { - printf("[s=%s]\n", s.get()); - return false; - } - - s.Assign("abcdabcdabcd"); - s.ReplaceSubstring("ab", "XYZABC"); - r = strcmp(s.get(), "XYZABCcdXYZABCcdXYZABCcd") == 0; - if (!r) - { - printf("[s=%s]\n", s.get()); - return false; - } - - s.Assign("abcdabcdabcd"); - s.ReplaceSubstring("ab", "XY"); - r = strcmp(s.get(), "XYcdXYcdXYcd") == 0; - if (!r) - { - printf("[s=%s]\n", s.get()); - return false; - } - - s.Assign("abcdabcdabcd"); - s.ReplaceSubstring("ab", "XYZ!"); - r = strcmp(s.get(), "XYZ!cdXYZ!cdXYZ!cd") == 0; - if (!r) - { - printf("[s=%s]\n", s.get()); - return false; - } - - s.Assign("abcdabcdabcd"); - s.ReplaceSubstring("notfound", "X"); - r = strcmp(s.get(), "abcdabcdabcd") == 0; - if (!r) - { - printf("[s=%s]\n", s.get()); - return false; - } - - s.Assign("abcdabcdabcd"); - s.ReplaceSubstring("notfound", "longlongstring"); - r = strcmp(s.get(), "abcdabcdabcd") == 0; - if (!r) - { - printf("[s=%s]\n", s.get()); - return false; - } - - return true; - } - bool test_strip_ws() { const char text[] = " a $ "; @@ -1351,7 +1201,6 @@ tests[] = { "test_trim", test_trim }, { "test_replace_substr", test_replace_substr }, { "test_replace_substr_2", test_replace_substr_2 }, - { "test_replace_substr_3", test_replace_substr_3 }, { "test_strip_ws", test_strip_ws }, { "test_equals_ic", test_equals_ic }, { "test_fixed_string", test_fixed_string },