From 8f0bf890b4b15148a149bf9bbeead4eed6675e8a Mon Sep 17 00:00:00 2001 From: Tom Sepez Date: Mon, 17 Apr 2017 14:14:01 -0700 Subject: Add iterators for Byte/WideStringCs. Change-Id: I40ec07c0da54bcf36c83fa26ff457cd4b98a91cf Reviewed-on: https://pdfium-review.googlesource.com/4261 Commit-Queue: Tom Sepez Reviewed-by: Lei Zhang --- core/fxcrt/cfx_bytestring.h | 7 ++ core/fxcrt/cfx_bytestring_unittest.cpp | 130 +++++++++++++++++++++++++++++++++ core/fxcrt/cfx_string_c_template.h | 9 +++ core/fxcrt/cfx_widestring.h | 7 ++ core/fxcrt/cfx_widestring_unittest.cpp | 129 ++++++++++++++++++++++++++++++++ 5 files changed, 282 insertions(+) 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 #include #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::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(m_Ptr); + } + const_iterator end() const { + return m_Ptr ? reinterpret_cast(m_Ptr) + m_Length + : nullptr; + } + bool operator==(const CharType* ptr) const { return FXSYS_len(ptr) == m_Length && FXSYS_cmp(ptr, reinterpret_cast(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 #include #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(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(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(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(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')); +} -- cgit v1.2.3