From b24538eb05caa533d4153789eb1b488d134c8db1 Mon Sep 17 00:00:00 2001 From: Shane Carr Date: Wed, 11 Dec 2019 20:46:08 -0800 Subject: [PATCH] ICU-20921 Adding find and compare to StringPiece --- icu4c/source/common/stringpiece.cpp | 41 +++++++++++++ icu4c/source/common/unicode/stringpiece.h | 20 ++++++ icu4c/source/test/intltest/strtest.cpp | 75 +++++++++++++++++++++++ icu4c/source/test/intltest/strtest.h | 1 + 4 files changed, 137 insertions(+) diff --git a/icu4c/source/common/stringpiece.cpp b/icu4c/source/common/stringpiece.cpp index d4f7f310baf..99089e08ef9 100644 --- a/icu4c/source/common/stringpiece.cpp +++ b/icu4c/source/common/stringpiece.cpp @@ -51,6 +51,47 @@ void StringPiece::set(const char* str) { length_ = 0; } +int32_t StringPiece::find(StringPiece needle, int32_t offset) { + if (length() == 0 && needle.length() == 0) { + return 0; + } + // TODO: Improve to be better than O(N^2)? + for (int32_t i = offset; i < length(); i++) { + int32_t j = 0; + for (; j < needle.length(); i++, j++) { + if (data()[i] != needle.data()[j]) { + i -= j; + goto outer_end; + } + } + return i - j; + outer_end: void(); + } + return -1; +} + +int32_t StringPiece::compare(StringPiece other) { + int32_t i = 0; + for (; i < length(); i++) { + if (i == other.length()) { + // this is longer + return 1; + } + char a = data()[i]; + char b = other.data()[i]; + if (a < b) { + return -1; + } else if (a > b) { + return 1; + } + } + if (i < other.length()) { + // other is longer + return -1; + } + return 0; +} + U_EXPORT UBool U_EXPORT2 operator==(const StringPiece& x, const StringPiece& y) { int32_t len = x.size(); diff --git a/icu4c/source/common/unicode/stringpiece.h b/icu4c/source/common/unicode/stringpiece.h index f581091f872..ba2240e6ac0 100644 --- a/icu4c/source/common/unicode/stringpiece.h +++ b/icu4c/source/common/unicode/stringpiece.h @@ -212,6 +212,26 @@ class U_COMMON_API StringPiece : public UMemory { } } +#ifndef U_HIDE_DRAFT_API + /** + * Searches the StringPiece for the given search string (needle); + * @param needle The string for which to search. + * @param offset Where to start searching within this string (haystack). + * @return The offset of needle in haystack, or -1 if not found. + * @draft ICU 67 + */ + int32_t find(StringPiece needle, int32_t offset); + + /** + * Compares this StringPiece with the other StringPiece, with semantics + * similar to std::string::compare(). + * @param other The string to compare to. + * @return below zero if this < other; above zero if this > other; 0 if this == other. + * @draft ICU 67 + */ + int32_t compare(StringPiece other); +#endif // U_HIDE_DRAFT_API + /** * Maximum integer, used as a default value for substring methods. * @stable ICU 4.2 diff --git a/icu4c/source/test/intltest/strtest.cpp b/icu4c/source/test/intltest/strtest.cpp index 7bb9662c36c..1665a03cdb8 100644 --- a/icu4c/source/test/intltest/strtest.cpp +++ b/icu4c/source/test/intltest/strtest.cpp @@ -243,6 +243,7 @@ void StringTest::runIndexedTest(int32_t index, UBool exec, const char *&name, ch TESTCASE_AUTO(TestSTLCompatibility); TESTCASE_AUTO(TestStringPiece); TESTCASE_AUTO(TestStringPieceComparisons); + TESTCASE_AUTO(TestStringPieceFind); TESTCASE_AUTO(TestStringPieceOther); #ifdef U_HAVE_STRING_VIEW TESTCASE_AUTO(TestStringPieceStringView); @@ -407,6 +408,35 @@ StringTest::TestStringPieceComparisons() { if(abc==abcd) { errln("abc==abcd"); } + + assertTrue("nullnull", abc.compare(null) > 0); + assertTrue("abcabc", abcd.compare(abc) > 0); + assertTrue("abcabc", abx.compare(abc) > 0); + assertTrue("abx>abcd", abx.compare(abcd) > 0); + assertTrue("abcdnull", abc.compare(null) > 0); + assertTrue("std: abcabc", abcd.compare(abc) > 0); + assertTrue("std: abcabc", abx.compare(abc) > 0); + assertTrue("std: abx>abcd", abx.compare(abcd) > 0); + assertTrue("std: abcd