diff options
-rw-r--r-- | core/fxcrt/cfx_bytestring.h | 7 | ||||
-rw-r--r-- | core/fxcrt/cfx_bytestring_unittest.cpp | 130 | ||||
-rw-r--r-- | core/fxcrt/cfx_string_c_template.h | 9 | ||||
-rw-r--r-- | core/fxcrt/cfx_widestring.h | 7 | ||||
-rw-r--r-- | core/fxcrt/cfx_widestring_unittest.cpp | 129 |
5 files changed, 282 insertions, 0 deletions
diff --git a/core/fxcrt/cfx_bytestring.h b/core/fxcrt/cfx_bytestring.h index b9ebd8a83c..0ffe92936a 100644 --- a/core/fxcrt/cfx_bytestring.h +++ b/core/fxcrt/cfx_bytestring.h @@ -23,6 +23,7 @@ class CFX_WideString; class CFX_ByteString { public: using CharType = char; + using const_iterator = const CharType*; CFX_ByteString(); CFX_ByteString(const CFX_ByteString& other); @@ -65,6 +66,12 @@ class CFX_ByteString { return CFX_ByteStringC(raw_str(), GetLength()); } + // Note: Any subsequent modification of |this| will invalidate iterators. + const_iterator begin() const { return m_pData ? m_pData->m_String : nullptr; } + const_iterator end() const { + return m_pData ? m_pData->m_String + m_pData->m_nDataLength : nullptr; + } + FX_STRSIZE GetLength() const { return m_pData ? m_pData->m_nDataLength : 0; } bool IsEmpty() const { return !GetLength(); } diff --git a/core/fxcrt/cfx_bytestring_unittest.cpp b/core/fxcrt/cfx_bytestring_unittest.cpp index 9cfc773fad..42627c2299 100644 --- a/core/fxcrt/cfx_bytestring_unittest.cpp +++ b/core/fxcrt/cfx_bytestring_unittest.cpp @@ -4,10 +4,12 @@ #include "core/fxcrt/cfx_bytestring.h" +#include <algorithm> #include <vector> #include "testing/fx_string_testhelpers.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/base/stl_util.h" TEST(fxcrt, ByteStringOperatorSubscript) { // CFX_ByteString includes the NUL terminator for non-empty strings. @@ -1031,6 +1033,70 @@ TEST(fxcrt, ByteStringCOperatorNE) { EXPECT_TRUE(c_string3 != byte_string_c); } +TEST(fxcrt, ByteStringCNullIterator) { + CFX_ByteStringC null_str; + int32_t sum = 0; + bool any_present = false; + for (const auto& c : null_str) { + sum += c; // Avoid unused arg warnings. + any_present = true; + } + EXPECT_FALSE(any_present); + EXPECT_EQ(0, sum); +} + +TEST(fxcrt, ByteStringCEmptyIterator) { + CFX_ByteStringC empty_str(""); + int32_t sum = 0; + bool any_present = false; + for (const auto& c : empty_str) { + any_present = true; + sum += c; // Avoid unused arg warnings. + } + EXPECT_FALSE(any_present); + EXPECT_EQ(0, sum); +} + +TEST(fxcrt, ByteStringCOneCharIterator) { + CFX_ByteStringC one_str("a"); + int32_t sum = 0; + bool any_present = false; + for (const auto& c : one_str) { + any_present = true; + sum += c; // Avoid unused arg warnings. + } + EXPECT_TRUE(any_present); + EXPECT_EQ('a', sum); +} + +TEST(fxcrt, ByteStringCMultiCharIterator) { + CFX_ByteStringC one_str("abc"); + int32_t sum = 0; + bool any_present = false; + for (const auto& c : one_str) { + any_present = true; + sum += c; // Avoid unused arg warnings. + } + EXPECT_TRUE(any_present); + EXPECT_EQ('a' + 'b' + 'c', sum); +} + +TEST(fxcrt, ByteStringCAnyAllNoneOf) { + CFX_ByteStringC str("aaaaaaaaaaaaaaaaab"); + EXPECT_FALSE(std::all_of(str.begin(), str.end(), + [](const char& c) { return c == 'a'; })); + + EXPECT_FALSE(std::none_of(str.begin(), str.end(), + [](const char& c) { return c == 'a'; })); + + EXPECT_TRUE(std::any_of(str.begin(), str.end(), + [](const char& c) { return c == 'a'; })); + + EXPECT_TRUE(pdfium::ContainsValue(str, 'a')); + EXPECT_TRUE(pdfium::ContainsValue(str, 'b')); + EXPECT_FALSE(pdfium::ContainsValue(str, 'z')); +} + TEST(fxcrt, ByteStringFormatWidth) { { CFX_ByteString str; @@ -1109,3 +1175,67 @@ TEST(fxcrt, ByteStringInitializerList) { many_str = {"fish", " and ", "chips", " and ", "soda"}; EXPECT_EQ("fish and chips and soda", many_str); } + +TEST(fxcrt, ByteStringNullIterator) { + CFX_ByteString null_str; + int32_t sum = 0; + bool any_present = false; + for (const auto& c : null_str) { + sum += c; // Avoid unused arg warnings. + any_present = true; + } + EXPECT_FALSE(any_present); + EXPECT_EQ(0, sum); +} + +TEST(fxcrt, ByteStringEmptyIterator) { + CFX_ByteString empty_str(""); + int32_t sum = 0; + bool any_present = false; + for (const auto& c : empty_str) { + any_present = true; + sum += c; // Avoid unused arg warnings. + } + EXPECT_FALSE(any_present); + EXPECT_EQ(0, sum); +} + +TEST(fxcrt, ByteStringOneCharIterator) { + CFX_ByteString one_str("a"); + int32_t sum = 0; + bool any_present = false; + for (const auto& c : one_str) { + any_present = true; + sum += c; // Avoid unused arg warnings. + } + EXPECT_TRUE(any_present); + EXPECT_EQ('a', sum); +} + +TEST(fxcrt, ByteStringMultiCharIterator) { + CFX_ByteString one_str("abc"); + int32_t sum = 0; + bool any_present = false; + for (const auto& c : one_str) { + any_present = true; + sum += c; // Avoid unused arg warnings. + } + EXPECT_TRUE(any_present); + EXPECT_EQ('a' + 'b' + 'c', sum); +} + +TEST(fxcrt, ByteStringAnyAllNoneOf) { + CFX_ByteString str("aaaaaaaaaaaaaaaaab"); + EXPECT_FALSE(std::all_of(str.begin(), str.end(), + [](const char& c) { return c == 'a'; })); + + EXPECT_FALSE(std::none_of(str.begin(), str.end(), + [](const char& c) { return c == 'a'; })); + + EXPECT_TRUE(std::any_of(str.begin(), str.end(), + [](const char& c) { return c == 'a'; })); + + EXPECT_TRUE(pdfium::ContainsValue(str, 'a')); + EXPECT_TRUE(pdfium::ContainsValue(str, 'b')); + EXPECT_FALSE(pdfium::ContainsValue(str, 'z')); +} diff --git a/core/fxcrt/cfx_string_c_template.h b/core/fxcrt/cfx_string_c_template.h index 4aba2cd4b9..75c2be0efc 100644 --- a/core/fxcrt/cfx_string_c_template.h +++ b/core/fxcrt/cfx_string_c_template.h @@ -22,6 +22,7 @@ class CFX_StringCTemplate { public: using CharType = T; using UnsignedType = typename std::make_unsigned<CharType>::type; + using const_iterator = const CharType*; CFX_StringCTemplate() : m_Ptr(nullptr), m_Length(0) {} @@ -73,6 +74,14 @@ class CFX_StringCTemplate { return *this; } + const_iterator begin() const { + return reinterpret_cast<const CharType*>(m_Ptr); + } + const_iterator end() const { + return m_Ptr ? reinterpret_cast<const CharType*>(m_Ptr) + m_Length + : nullptr; + } + bool operator==(const CharType* ptr) const { return FXSYS_len(ptr) == m_Length && FXSYS_cmp(ptr, reinterpret_cast<const CharType*>(m_Ptr), m_Length) == diff --git a/core/fxcrt/cfx_widestring.h b/core/fxcrt/cfx_widestring.h index 52cd65a2b7..fd3c92a15e 100644 --- a/core/fxcrt/cfx_widestring.h +++ b/core/fxcrt/cfx_widestring.h @@ -23,6 +23,7 @@ class CFX_ByteString; class CFX_WideString { public: using CharType = wchar_t; + using const_iterator = const CharType*; CFX_WideString(); CFX_WideString(const CFX_WideString& other); @@ -61,6 +62,12 @@ class CFX_WideString { return CFX_WideStringC(c_str(), GetLength()); } + // Note: Any subsequent modification of |this| will invalidate iterators. + const_iterator begin() const { return m_pData ? m_pData->m_String : nullptr; } + const_iterator end() const { + return m_pData ? m_pData->m_String + m_pData->m_nDataLength : nullptr; + } + void clear() { m_pData.Reset(); } FX_STRSIZE GetLength() const { return m_pData ? m_pData->m_nDataLength : 0; } diff --git a/core/fxcrt/cfx_widestring_unittest.cpp b/core/fxcrt/cfx_widestring_unittest.cpp index 498b4f0b6a..a9cb2d34cd 100644 --- a/core/fxcrt/cfx_widestring_unittest.cpp +++ b/core/fxcrt/cfx_widestring_unittest.cpp @@ -4,6 +4,7 @@ #include "core/fxcrt/cfx_widestring.h" +#include <algorithm> #include <vector> #include "testing/fx_string_testhelpers.h" @@ -871,6 +872,70 @@ TEST(fxcrt, WideStringCFind) { EXPECT_EQ(2, hibyte_string.Find(L'\xff08')); } +TEST(fxcrt, WideStringCNullIterator) { + CFX_WideStringC null_str; + int32_t sum = 0; + bool any_present = false; + for (const auto& c : null_str) { + sum += c; // Avoid unused arg warnings. + any_present = true; + } + EXPECT_FALSE(any_present); + EXPECT_EQ(0, sum); +} + +TEST(fxcrt, WideStringCEmptyIterator) { + CFX_WideStringC empty_str(L""); + int32_t sum = 0; + bool any_present = false; + for (const auto& c : empty_str) { + any_present = true; + sum += c; // Avoid unused arg warnings. + } + EXPECT_FALSE(any_present); + EXPECT_EQ(0, sum); +} + +TEST(fxcrt, WideStringCOneCharIterator) { + CFX_WideStringC one_str(L"a"); + int32_t sum = 0; + bool any_present = false; + for (const auto& c : one_str) { + any_present = true; + sum += c; // Avoid unused arg warnings. + } + EXPECT_TRUE(any_present); + EXPECT_EQ(static_cast<int32_t>(L'a'), sum); +} + +TEST(fxcrt, WideStringCMultiCharIterator) { + CFX_WideStringC one_str(L"abc"); + int32_t sum = 0; + bool any_present = false; + for (const auto& c : one_str) { + any_present = true; + sum += c; // Avoid unused arg warnings. + } + EXPECT_TRUE(any_present); + EXPECT_EQ(static_cast<int32_t>(L'a' + L'b' + L'c'), sum); +} + +TEST(fxcrt, WideStringCAnyAllNoneOf) { + CFX_WideStringC str(L"aaaaaaaaaaaaaaaaab"); + EXPECT_FALSE(std::all_of(str.begin(), str.end(), + [](const wchar_t& c) { return c == L'a'; })); + + EXPECT_FALSE(std::none_of(str.begin(), str.end(), + [](const wchar_t& c) { return c == L'a'; })); + + EXPECT_TRUE(std::any_of(str.begin(), str.end(), + [](const wchar_t& c) { return c == L'a'; })); + + EXPECT_TRUE(pdfium::ContainsValue(str, L'a')); + EXPECT_TRUE(pdfium::ContainsValue(str, L'b')); + EXPECT_FALSE(pdfium::ContainsValue(str, L'z')); +} + TEST(fxcrt, WideStringFormatWidth) { { CFX_WideString str; @@ -966,3 +1031,67 @@ TEST(fxcrt, WidStringInitializerList) { many_str = {L"fish", L" and ", L"chips", L" and ", L"soda"}; EXPECT_EQ(L"fish and chips and soda", many_str); } + +TEST(fxcrt, WideStringNullIterator) { + CFX_WideString null_str; + int32_t sum = 0; + bool any_present = false; + for (const auto& c : null_str) { + sum += c; // Avoid unused arg warnings. + any_present = true; + } + EXPECT_FALSE(any_present); + EXPECT_EQ(0, sum); +} + +TEST(fxcrt, WideStringEmptyIterator) { + CFX_WideString empty_str(L""); + int32_t sum = 0; + bool any_present = false; + for (const auto& c : empty_str) { + any_present = true; + sum += c; // Avoid unused arg warnings. + } + EXPECT_FALSE(any_present); + EXPECT_EQ(0, sum); +} + +TEST(fxcrt, WideStringOneCharIterator) { + CFX_WideString one_str(L"a"); + int32_t sum = 0; + bool any_present = false; + for (const auto& c : one_str) { + any_present = true; + sum += c; // Avoid unused arg warnings. + } + EXPECT_TRUE(any_present); + EXPECT_EQ(static_cast<int32_t>(L'a'), sum); +} + +TEST(fxcrt, WideStringMultiCharIterator) { + CFX_WideString one_str(L"abc"); + int32_t sum = 0; + bool any_present = false; + for (const auto& c : one_str) { + any_present = true; + sum += c; // Avoid unused arg warnings. + } + EXPECT_TRUE(any_present); + EXPECT_EQ(static_cast<int32_t>(L'a' + L'b' + L'c'), sum); +} + +TEST(fxcrt, WideStringAnyAllNoneOf) { + CFX_WideString str(L"aaaaaaaaaaaaaaaaab"); + EXPECT_FALSE(std::all_of(str.begin(), str.end(), + [](const wchar_t& c) { return c == L'a'; })); + + EXPECT_FALSE(std::none_of(str.begin(), str.end(), + [](const wchar_t& c) { return c == L'a'; })); + + EXPECT_TRUE(std::any_of(str.begin(), str.end(), + [](const wchar_t& c) { return c == L'a'; })); + + EXPECT_TRUE(pdfium::ContainsValue(str, L'a')); + EXPECT_TRUE(pdfium::ContainsValue(str, L'b')); + EXPECT_FALSE(pdfium::ContainsValue(str, L'z')); +} |