зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 2 changesets (bug 1101337) because of ASAN bustage landed on a CLOSED TREE
Backed out changeset ffef93ec94aa (bug 1101337) Backed out changeset 2954a37bc2df (bug 1101337)
This commit is contained in:
Родитель
169d700dd5
Коммит
eb2d17cdf6
|
@ -106,7 +106,7 @@ static nsStringStats gStringStats;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
void
|
inline void
|
||||||
ReleaseData(void* aData, uint32_t aFlags)
|
ReleaseData(void* aData, uint32_t aFlags)
|
||||||
{
|
{
|
||||||
if (aFlags & nsSubstring::F_SHARED) {
|
if (aFlags & nsSubstring::F_SHARED) {
|
||||||
|
|
|
@ -386,11 +386,6 @@ public:
|
||||||
#ifdef CharT_is_PRUnichar
|
#ifdef CharT_is_PRUnichar
|
||||||
void ReplaceChar(const char16_t* aSet, char16_t aNewChar);
|
void ReplaceChar(const char16_t* aSet, char16_t aNewChar);
|
||||||
#endif
|
#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 self_type& aTarget, const self_type& aNewValue);
|
||||||
void ReplaceSubstring(const char_type* aTarget, const char_type* aNewValue);
|
void ReplaceSubstring(const char_type* aTarget, const char_type* aNewValue);
|
||||||
|
|
||||||
|
@ -463,14 +458,6 @@ protected:
|
||||||
: substring_type(aData, aLength, aFlags)
|
: substring_type(aData, aLength, aFlags)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Segment {
|
|
||||||
uint32_t mBegin, mLength;
|
|
||||||
Segment(uint32_t aBegin, uint32_t aLength)
|
|
||||||
: mBegin(aBegin)
|
|
||||||
, mLength(aLength)
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "nsTArray.h"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nsTString::Find
|
* nsTString::Find
|
||||||
|
@ -451,8 +451,6 @@ nsTString_CharT::ReplaceChar( const char* aSet, char_type aNewChar )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReleaseData(void* aData, uint32_t aFlags);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
nsTString_CharT::ReplaceSubstring( const char_type* aTarget, const char_type* aNewValue )
|
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)
|
if (aTarget.Length() == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Remember all of the non-matching parts.
|
|
||||||
nsAutoTArray<Segment, 16> nonMatching;
|
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
uint32_t newLength = 0;
|
while (i < mLength)
|
||||||
while (true)
|
|
||||||
{
|
{
|
||||||
int32_t r = FindSubstring(mData + i, mLength - i, static_cast<const char_type*>(aTarget.Data()), aTarget.Length(), false);
|
int32_t r = FindSubstring(mData + i, mLength - i, static_cast<const char_type*>(aTarget.Data()), aTarget.Length(), false);
|
||||||
int32_t until = (r == kNotFound) ? mLength - i : r;
|
if (r == kNotFound)
|
||||||
nonMatching.AppendElement(Segment(i, until));
|
|
||||||
newLength += until;
|
|
||||||
if (r == kNotFound) {
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
newLength += aNewValue.Length();
|
Replace(i + r, aTarget.Length(), aNewValue);
|
||||||
i += r + aTarget.Length();
|
i += r + aNewValue.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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
* nsTString::Trim
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -451,156 +451,6 @@ bool test_replace_substr_2()
|
||||||
return true;
|
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()
|
bool test_strip_ws()
|
||||||
{
|
{
|
||||||
const char text[] = " a $ ";
|
const char text[] = " a $ ";
|
||||||
|
@ -1351,7 +1201,6 @@ tests[] =
|
||||||
{ "test_trim", test_trim },
|
{ "test_trim", test_trim },
|
||||||
{ "test_replace_substr", test_replace_substr },
|
{ "test_replace_substr", test_replace_substr },
|
||||||
{ "test_replace_substr_2", test_replace_substr_2 },
|
{ "test_replace_substr_2", test_replace_substr_2 },
|
||||||
{ "test_replace_substr_3", test_replace_substr_3 },
|
|
||||||
{ "test_strip_ws", test_strip_ws },
|
{ "test_strip_ws", test_strip_ws },
|
||||||
{ "test_equals_ic", test_equals_ic },
|
{ "test_equals_ic", test_equals_ic },
|
||||||
{ "test_fixed_string", test_fixed_string },
|
{ "test_fixed_string", test_fixed_string },
|
||||||
|
|
Загрузка…
Ссылка в новой задаче