summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/fxcrt/cfx_bytestring.h10
-rw-r--r--core/fxcrt/cfx_bytestring_unittest.cpp134
-rw-r--r--core/fxcrt/cfx_string_c_template.h9
-rw-r--r--core/fxcrt/cfx_widestring.h10
-rw-r--r--core/fxcrt/cfx_widestring_unittest.cpp134
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(),