diff options
-rw-r--r-- | core/fxcrt/fx_basic_bstring.cpp | 11 | ||||
-rw-r--r-- | core/fxcrt/fx_basic_bstring_unittest.cpp | 77 | ||||
-rw-r--r-- | core/fxcrt/fx_basic_wstring.cpp | 11 | ||||
-rw-r--r-- | core/fxcrt/fx_basic_wstring_unittest.cpp | 77 |
4 files changed, 170 insertions, 6 deletions
diff --git a/core/fxcrt/fx_basic_bstring.cpp b/core/fxcrt/fx_basic_bstring.cpp index 1622c4bc55..e098d8fe50 100644 --- a/core/fxcrt/fx_basic_bstring.cpp +++ b/core/fxcrt/fx_basic_bstring.cpp @@ -276,20 +276,25 @@ void CFX_ByteString::ReleaseBuffer(FX_STRSIZE nNewLength) { if (nNewLength == -1) nNewLength = FXSYS_strlen(m_pData->m_String); + nNewLength = std::min(nNewLength, m_pData->m_nAllocLength); if (nNewLength == 0) { clear(); return; } - FXSYS_assert(nNewLength <= m_pData->m_nAllocLength); - ReallocBeforeWrite(nNewLength); + FXSYS_assert(m_pData->m_nRefs == 1); m_pData->m_nDataLength = nNewLength; m_pData->m_String[nNewLength] = 0; + if (m_pData->m_nAllocLength - nNewLength >= 32) { + // Over arbitrary threshold, so pay the price to relocate. Force copy to + // always occur by holding a second reference to the string. + CFX_ByteString preserve(*this); + ReallocBeforeWrite(nNewLength); + } } void CFX_ByteString::Reserve(FX_STRSIZE len) { GetBuffer(len); - ReleaseBuffer(GetLength()); } FX_CHAR* CFX_ByteString::GetBuffer(FX_STRSIZE nMinBufLength) { diff --git a/core/fxcrt/fx_basic_bstring_unittest.cpp b/core/fxcrt/fx_basic_bstring_unittest.cpp index ea7e17f1f1..087c264940 100644 --- a/core/fxcrt/fx_basic_bstring_unittest.cpp +++ b/core/fxcrt/fx_basic_bstring_unittest.cpp @@ -624,6 +624,83 @@ TEST(fxcrt, ByteStringTrimLeftCopies) { } } +TEST(fxcrt, ByteStringReserve) { + { + CFX_ByteString str; + str.Reserve(6); + const FX_CHAR* old_buffer = str.c_str(); + str += "ABCDEF"; + EXPECT_EQ(old_buffer, str.c_str()); + str += "Blah Blah Blah Blah Blah Blah"; + EXPECT_NE(old_buffer, str.c_str()); + } + { + CFX_ByteString str("A"); + str.Reserve(6); + const FX_CHAR* old_buffer = str.c_str(); + str += "BCDEF"; + EXPECT_EQ(old_buffer, str.c_str()); + str += "Blah Blah Blah Blah Blah Blah"; + EXPECT_NE(old_buffer, str.c_str()); + } +} + +TEST(fxcrt, ByteStringGetBuffer) { + { + CFX_ByteString str; + FX_CHAR* buffer = str.GetBuffer(12); + strcpy(buffer, "clams"); + str.ReleaseBuffer(); + EXPECT_EQ("clams", str); + } + { + CFX_ByteString str("cl"); + FX_CHAR* buffer = str.GetBuffer(12); + strcpy(buffer + 2, "ams"); + str.ReleaseBuffer(); + EXPECT_EQ("clams", str); + } +} + +TEST(fxcrt, ByteStringReleaseBuffer) { + { + CFX_ByteString str; + str.Reserve(12); + str += "clams"; + const FX_CHAR* old_buffer = str.c_str(); + str.ReleaseBuffer(4); + EXPECT_EQ(old_buffer, str.c_str()); + EXPECT_EQ("clam", str); + } + { + CFX_ByteString str("c"); + str.Reserve(12); + str += "lams"; + const FX_CHAR* old_buffer = str.c_str(); + str.ReleaseBuffer(4); + EXPECT_EQ(old_buffer, str.c_str()); + EXPECT_EQ("clam", str); + } + { + CFX_ByteString str; + str.Reserve(200); + str += "clams"; + const FX_CHAR* old_buffer = str.c_str(); + str.ReleaseBuffer(4); + EXPECT_NE(old_buffer, str.c_str()); + EXPECT_EQ("clam", str); + } + { + CFX_ByteString str("c"); + str.Reserve(200); + str += "lams"; + const FX_CHAR* old_buffer = str.c_str(); + str.ReleaseBuffer(4); + EXPECT_NE(old_buffer, str.c_str()); + EXPECT_EQ("clam", str); + } +} + TEST(fxcrt, ByteStringCNotNull) { CFX_ByteStringC string3("abc"); CFX_ByteStringC string6("abcdef"); diff --git a/core/fxcrt/fx_basic_wstring.cpp b/core/fxcrt/fx_basic_wstring.cpp index f3b430c7bf..38fd15e13f 100644 --- a/core/fxcrt/fx_basic_wstring.cpp +++ b/core/fxcrt/fx_basic_wstring.cpp @@ -224,20 +224,25 @@ void CFX_WideString::ReleaseBuffer(FX_STRSIZE nNewLength) { if (nNewLength == -1) nNewLength = FXSYS_wcslen(m_pData->m_String); + nNewLength = std::min(nNewLength, m_pData->m_nAllocLength); if (nNewLength == 0) { clear(); return; } - FXSYS_assert(nNewLength <= m_pData->m_nAllocLength); - ReallocBeforeWrite(nNewLength); + FXSYS_assert(m_pData->m_nRefs == 1); m_pData->m_nDataLength = nNewLength; m_pData->m_String[nNewLength] = 0; + if (m_pData->m_nAllocLength - nNewLength >= 32) { + // Over arbitrary threshold, so pay the price to relocate. Force copy to + // always occur by holding a second reference to the string. + CFX_WideString preserve(*this); + ReallocBeforeWrite(nNewLength); + } } void CFX_WideString::Reserve(FX_STRSIZE len) { GetBuffer(len); - ReleaseBuffer(GetLength()); } FX_WCHAR* CFX_WideString::GetBuffer(FX_STRSIZE nMinBufLength) { diff --git a/core/fxcrt/fx_basic_wstring_unittest.cpp b/core/fxcrt/fx_basic_wstring_unittest.cpp index 708556af1d..02281afd36 100644 --- a/core/fxcrt/fx_basic_wstring_unittest.cpp +++ b/core/fxcrt/fx_basic_wstring_unittest.cpp @@ -591,6 +591,83 @@ TEST(fxcrt, WideStringTrimLeftCopies) { } } +TEST(fxcrt, WideStringReserve) { + { + CFX_WideString str; + str.Reserve(6); + const FX_WCHAR* old_buffer = str.c_str(); + str += L"ABCDEF"; + EXPECT_EQ(old_buffer, str.c_str()); + str += L"Blah Blah Blah Blah Blah Blah"; + EXPECT_NE(old_buffer, str.c_str()); + } + { + CFX_WideString str(L"A"); + str.Reserve(6); + const FX_WCHAR* old_buffer = str.c_str(); + str += L"BCDEF"; + EXPECT_EQ(old_buffer, str.c_str()); + str += L"Blah Blah Blah Blah Blah Blah"; + EXPECT_NE(old_buffer, str.c_str()); + } +} + +TEST(fxcrt, WideStringGetBuffer) { + { + CFX_WideString str; + FX_WCHAR* buffer = str.GetBuffer(12); + wcscpy(buffer, L"clams"); + str.ReleaseBuffer(); + EXPECT_EQ(L"clams", str); + } + { + CFX_WideString str(L"cl"); + FX_WCHAR* buffer = str.GetBuffer(12); + wcscpy(buffer + 2, L"ams"); + str.ReleaseBuffer(); + EXPECT_EQ(L"clams", str); + } +} + +TEST(fxcrt, WideStringReleaseBuffer) { + { + CFX_WideString str; + str.Reserve(12); + str += L"clams"; + const FX_WCHAR* old_buffer = str.c_str(); + str.ReleaseBuffer(4); + EXPECT_EQ(old_buffer, str.c_str()); + EXPECT_EQ(L"clam", str); + } + { + CFX_WideString str(L"c"); + str.Reserve(12); + str += L"lams"; + const FX_WCHAR* old_buffer = str.c_str(); + str.ReleaseBuffer(4); + EXPECT_EQ(old_buffer, str.c_str()); + EXPECT_EQ(L"clam", str); + } + { + CFX_WideString str; + str.Reserve(200); + str += L"clams"; + const FX_WCHAR* old_buffer = str.c_str(); + str.ReleaseBuffer(4); + EXPECT_NE(old_buffer, str.c_str()); + EXPECT_EQ(L"clam", str); + } + { + CFX_WideString str(L"c"); + str.Reserve(200); + str += L"lams"; + const FX_WCHAR* old_buffer = str.c_str(); + str.ReleaseBuffer(4); + EXPECT_NE(old_buffer, str.c_str()); + EXPECT_EQ(L"clam", str); + } +} + TEST(fxcrt, WideStringUTF16LE_Encode) { struct UTF16LEEncodeCase { CFX_WideString ws; |