diff options
-rw-r--r-- | core/fxcrt/cfx_bytestring.h | 10 | ||||
-rw-r--r-- | core/fxcrt/cfx_bytestring_unittest.cpp | 134 | ||||
-rw-r--r-- | core/fxcrt/cfx_string_c_template.h | 9 | ||||
-rw-r--r-- | core/fxcrt/cfx_widestring.h | 10 | ||||
-rw-r--r-- | core/fxcrt/cfx_widestring_unittest.cpp | 134 |
5 files changed, 297 insertions, 0 deletions
diff --git a/core/fxcrt/cfx_bytestring.h b/core/fxcrt/cfx_bytestring.h index 432f28a06d..b976287617 100644 --- a/core/fxcrt/cfx_bytestring.h +++ b/core/fxcrt/cfx_bytestring.h @@ -8,6 +8,7 @@ #define CORE_FXCRT_CFX_BYTESTRING_H_ #include <functional> +#include <iterator> #include <sstream> #include <utility> @@ -25,6 +26,7 @@ class CFX_ByteString { public: using CharType = char; using const_iterator = const CharType*; + using const_reverse_iterator = std::reverse_iterator<const_iterator>; CFX_ByteString(); CFX_ByteString(const CFX_ByteString& other); @@ -77,6 +79,14 @@ class CFX_ByteString { return m_pData ? m_pData->m_String + m_pData->m_nDataLength : nullptr; } + // Note: Any subsequent modification of |this| will invalidate iterators. + const_reverse_iterator rbegin() const { + return const_reverse_iterator(end()); + } + const_reverse_iterator rend() const { + return const_reverse_iterator(begin()); + } + FX_STRSIZE GetLength() const { return m_pData ? m_pData->m_nDataLength : 0; } FX_STRSIZE GetStringLength() const { return m_pData ? FXSYS_strlen(m_pData->m_String) : 0; diff --git a/core/fxcrt/cfx_bytestring_unittest.cpp b/core/fxcrt/cfx_bytestring_unittest.cpp index a4c5187c11..6bbe305268 100644 --- a/core/fxcrt/cfx_bytestring_unittest.cpp +++ b/core/fxcrt/cfx_bytestring_unittest.cpp @@ -833,6 +833,73 @@ TEST(fxcrt, ByteStringReleaseBuffer) { } } +TEST(fxcrt, ByteStringEmptyReverseIterator) { + CFX_ByteString empty; + auto iter = empty.rbegin(); + EXPECT_TRUE(iter == empty.rend()); + EXPECT_FALSE(iter != empty.rend()); + EXPECT_FALSE(iter < empty.rend()); +} + +TEST(fxcrt, ByteStringOneCharReverseIterator) { + CFX_ByteString one_str("a"); + auto iter = one_str.rbegin(); + EXPECT_FALSE(iter == one_str.rend()); + EXPECT_TRUE(iter != one_str.rend()); + EXPECT_TRUE(iter < one_str.rend()); + + char ch = *iter++; + EXPECT_EQ('a', ch); + EXPECT_TRUE(iter == one_str.rend()); + EXPECT_FALSE(iter != one_str.rend()); + EXPECT_FALSE(iter < one_str.rend()); +} + +TEST(fxcrt, ByteStringMultiCharReverseIterator) { + CFX_ByteString multi_str("abcd"); + auto iter = multi_str.rbegin(); + EXPECT_FALSE(iter == multi_str.rend()); + + char ch = *iter++; + EXPECT_EQ('d', ch); + EXPECT_EQ('c', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *(++iter); + EXPECT_EQ('b', ch); + EXPECT_EQ('b', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter++; + EXPECT_EQ('b', ch); + EXPECT_EQ('a', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter++; + EXPECT_EQ('a', ch); + EXPECT_TRUE(iter == multi_str.rend()); + + ch = *(--iter); + EXPECT_EQ('a', ch); + EXPECT_EQ('a', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter--; + EXPECT_EQ('a', ch); + EXPECT_EQ('b', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter--; + EXPECT_EQ('b', ch); + EXPECT_EQ('c', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *(--iter); + EXPECT_EQ('d', ch); + EXPECT_EQ('d', *iter); + EXPECT_TRUE(iter == multi_str.rbegin()); +} + TEST(fxcrt, ByteStringCNotNull) { CFX_ByteStringC string3("abc"); CFX_ByteStringC string6("abcdef"); @@ -1200,6 +1267,73 @@ TEST(fxcrt, ByteStringCMultiCharIterator) { EXPECT_EQ('a' + 'b' + 'c', sum); } +TEST(fxcrt, ByteStringCEmptyReverseIterator) { + CFX_ByteStringC empty; + auto iter = empty.rbegin(); + EXPECT_TRUE(iter == empty.rend()); + EXPECT_FALSE(iter != empty.rend()); + EXPECT_FALSE(iter < empty.rend()); +} + +TEST(fxcrt, ByteStringCOneCharReverseIterator) { + CFX_ByteStringC one_str("a"); + auto iter = one_str.rbegin(); + EXPECT_FALSE(iter == one_str.rend()); + EXPECT_TRUE(iter != one_str.rend()); + EXPECT_TRUE(iter < one_str.rend()); + + char ch = *iter++; + EXPECT_EQ('a', ch); + EXPECT_TRUE(iter == one_str.rend()); + EXPECT_FALSE(iter != one_str.rend()); + EXPECT_FALSE(iter < one_str.rend()); +} + +TEST(fxcrt, ByteStringCMultiCharReverseIterator) { + CFX_ByteStringC multi_str("abcd"); + auto iter = multi_str.rbegin(); + EXPECT_FALSE(iter == multi_str.rend()); + + char ch = *iter++; + EXPECT_EQ('d', ch); + EXPECT_EQ('c', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *(++iter); + EXPECT_EQ('b', ch); + EXPECT_EQ('b', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter++; + EXPECT_EQ('b', ch); + EXPECT_EQ('a', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter++; + EXPECT_EQ('a', ch); + EXPECT_TRUE(iter == multi_str.rend()); + + ch = *(--iter); + EXPECT_EQ('a', ch); + EXPECT_EQ('a', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter--; + EXPECT_EQ('a', ch); + EXPECT_EQ('b', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter--; + EXPECT_EQ('b', ch); + EXPECT_EQ('c', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *(--iter); + EXPECT_EQ('d', ch); + EXPECT_EQ('d', *iter); + EXPECT_TRUE(iter == multi_str.rbegin()); +} + TEST(fxcrt, ByteStringCAnyAllNoneOf) { CFX_ByteStringC str("aaaaaaaaaaaaaaaaab"); EXPECT_FALSE(std::all_of(str.begin(), str.end(), diff --git a/core/fxcrt/cfx_string_c_template.h b/core/fxcrt/cfx_string_c_template.h index b0e17a1222..9123fc234b 100644 --- a/core/fxcrt/cfx_string_c_template.h +++ b/core/fxcrt/cfx_string_c_template.h @@ -8,6 +8,7 @@ #define CORE_FXCRT_CFX_STRING_C_TEMPLATE_H_ #include <algorithm> +#include <iterator> #include <type_traits> #include <utility> #include <vector> @@ -26,6 +27,7 @@ class CFX_StringCTemplate { using CharType = T; using UnsignedType = typename std::make_unsigned<CharType>::type; using const_iterator = const CharType*; + using const_reverse_iterator = std::reverse_iterator<const_iterator>; CFX_StringCTemplate() : m_Ptr(nullptr), m_Length(0) {} @@ -84,6 +86,13 @@ class CFX_StringCTemplate { : nullptr; } + const_reverse_iterator rbegin() const { + return const_reverse_iterator(end()); + } + const_reverse_iterator rend() const { + return const_reverse_iterator(begin()); + } + bool operator==(const CharType* ptr) const { return FXSYS_len(ptr) == m_Length && FXSYS_cmp(ptr, reinterpret_cast<const CharType*>(m_Ptr.Get()), diff --git a/core/fxcrt/cfx_widestring.h b/core/fxcrt/cfx_widestring.h index 9922e4277a..595615a0b2 100644 --- a/core/fxcrt/cfx_widestring.h +++ b/core/fxcrt/cfx_widestring.h @@ -8,6 +8,7 @@ #define CORE_FXCRT_CFX_WIDESTRING_H_ #include <functional> +#include <iterator> #include <utility> #include "core/fxcrt/cfx_retain_ptr.h" @@ -25,6 +26,7 @@ class CFX_WideString { public: using CharType = wchar_t; using const_iterator = const CharType*; + using const_reverse_iterator = std::reverse_iterator<const_iterator>; CFX_WideString(); CFX_WideString(const CFX_WideString& other); @@ -73,6 +75,14 @@ class CFX_WideString { return m_pData ? m_pData->m_String + m_pData->m_nDataLength : nullptr; } + // Note: Any subsequent modification of |this| will invalidate iterators. + const_reverse_iterator rbegin() const { + return const_reverse_iterator(end()); + } + const_reverse_iterator rend() const { + return const_reverse_iterator(begin()); + } + 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 1c8aca9aca..6f3bc0837f 100644 --- a/core/fxcrt/cfx_widestring_unittest.cpp +++ b/core/fxcrt/cfx_widestring_unittest.cpp @@ -756,6 +756,73 @@ TEST(fxcrt, WideStringReleaseBuffer) { } } +TEST(fxcrt, WideStringEmptyReverseIterator) { + CFX_WideString empty; + auto iter = empty.rbegin(); + EXPECT_TRUE(iter == empty.rend()); + EXPECT_FALSE(iter != empty.rend()); + EXPECT_FALSE(iter < empty.rend()); +} + +TEST(fxcrt, WideStringOneCharReverseIterator) { + CFX_WideString one_str(L"a"); + auto iter = one_str.rbegin(); + EXPECT_FALSE(iter == one_str.rend()); + EXPECT_TRUE(iter != one_str.rend()); + EXPECT_TRUE(iter < one_str.rend()); + + char ch = *iter++; + EXPECT_EQ('a', ch); + EXPECT_TRUE(iter == one_str.rend()); + EXPECT_FALSE(iter != one_str.rend()); + EXPECT_FALSE(iter < one_str.rend()); +} + +TEST(fxcrt, WideStringMultiCharReverseIterator) { + CFX_WideString multi_str(L"abcd"); + auto iter = multi_str.rbegin(); + EXPECT_FALSE(iter == multi_str.rend()); + + char ch = *iter++; + EXPECT_EQ('d', ch); + EXPECT_EQ('c', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *(++iter); + EXPECT_EQ('b', ch); + EXPECT_EQ('b', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter++; + EXPECT_EQ('b', ch); + EXPECT_EQ('a', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter++; + EXPECT_EQ('a', ch); + EXPECT_TRUE(iter == multi_str.rend()); + + ch = *(--iter); + EXPECT_EQ('a', ch); + EXPECT_EQ('a', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter--; + EXPECT_EQ('a', ch); + EXPECT_EQ('b', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter--; + EXPECT_EQ('b', ch); + EXPECT_EQ('c', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *(--iter); + EXPECT_EQ('d', ch); + EXPECT_EQ('d', *iter); + EXPECT_TRUE(iter == multi_str.rbegin()); +} + TEST(fxcrt, WideStringUTF16LE_Encode) { struct UTF16LEEncodeCase { CFX_WideString ws; @@ -1022,6 +1089,73 @@ TEST(fxcrt, WideStringCMultiCharIterator) { EXPECT_EQ(static_cast<int32_t>(L'a' + L'b' + L'c'), sum); } +TEST(fxcrt, WideStringCEmptyReverseIterator) { + CFX_WideStringC empty; + auto iter = empty.rbegin(); + EXPECT_TRUE(iter == empty.rend()); + EXPECT_FALSE(iter != empty.rend()); + EXPECT_FALSE(iter < empty.rend()); +} + +TEST(fxcrt, WideStringCOneCharReverseIterator) { + CFX_WideStringC one_str(L"a"); + auto iter = one_str.rbegin(); + EXPECT_FALSE(iter == one_str.rend()); + EXPECT_TRUE(iter != one_str.rend()); + EXPECT_TRUE(iter < one_str.rend()); + + char ch = *iter++; + EXPECT_EQ('a', ch); + EXPECT_TRUE(iter == one_str.rend()); + EXPECT_FALSE(iter != one_str.rend()); + EXPECT_FALSE(iter < one_str.rend()); +} + +TEST(fxcrt, WideStringCMultiCharReverseIterator) { + CFX_WideStringC multi_str(L"abcd"); + auto iter = multi_str.rbegin(); + EXPECT_FALSE(iter == multi_str.rend()); + + char ch = *iter++; + EXPECT_EQ('d', ch); + EXPECT_EQ('c', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *(++iter); + EXPECT_EQ('b', ch); + EXPECT_EQ('b', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter++; + EXPECT_EQ('b', ch); + EXPECT_EQ('a', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter++; + EXPECT_EQ('a', ch); + EXPECT_TRUE(iter == multi_str.rend()); + + ch = *(--iter); + EXPECT_EQ('a', ch); + EXPECT_EQ('a', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter--; + EXPECT_EQ('a', ch); + EXPECT_EQ('b', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter--; + EXPECT_EQ('b', ch); + EXPECT_EQ('c', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *(--iter); + EXPECT_EQ('d', ch); + EXPECT_EQ('d', *iter); + EXPECT_TRUE(iter == multi_str.rbegin()); +} + TEST(fxcrt, WideStringCAnyAllNoneOf) { CFX_WideStringC str(L"aaaaaaaaaaaaaaaaab"); EXPECT_FALSE(std::all_of(str.begin(), str.end(), |