diff options
author | Nicolas Catania <niko@google.com> | 2010-02-07 20:21:04 -0800 |
---|---|---|
committer | Nicolas Catania <niko@google.com> | 2010-02-08 13:39:07 -0800 |
commit | cb8eb8e1390d1343563a55c117b5c39cfa87fe1d (patch) | |
tree | 0ff37f0e023f29bc7b584a273cfe2440011623e7 | |
parent | 40d9e34c926f59cae26c4bae4ab55377cf3cdd40 (diff) | |
download | astl-cb8eb8e1390d1343563a55c117b5c39cfa87fe1d.tar.gz |
Added the methods to find a char in a string:
find_first_of, find_first_not_of
find_last_of, find_last_not_of.
Added rfind and find for char (equivalent to find_last_of and find_first_of when
a char is used instead of a set of char (string)).
-rw-r--r-- | include/string | 22 | ||||
-rw-r--r-- | src/string.cpp | 53 | ||||
-rw-r--r-- | tests/Android.mk | 3 | ||||
-rw-r--r-- | tests/test_string.cpp | 84 |
4 files changed, 157 insertions, 5 deletions
diff --git a/include/string b/include/string index bcf13d8..e7fe904 100644 --- a/include/string +++ b/include/string @@ -257,6 +257,22 @@ class string // starting position. size_type find(const value_type *str, size_type pos = 0) const; + // Find the lowest position xpos, if possible, such that: + // pos <= xpos && xpos < size() + // at(xpos) == c + // @return xpos if it exists, npos otherwise. + size_type find(const value_type c, size_type pos = 0) const { + return find_first_of(c, pos); + } + + // Find the highest position xpos, if possible, such that: + // xpos <= pos && xpos < size() + // at(xpos) == c + // @return xpos if it exists, npos otherwise. + size_type rfind(const value_type c, size_type pos = npos) const { + return find_last_of(c, pos); + } + // Iterators iterator begin() {return iterator(mData);} const_iterator begin() const {return const_iterator(mData);} @@ -267,6 +283,12 @@ class string // Requires pos <= size(). If n > size() - pos, size() - pos is used. string substr(size_type pos = 0, size_type n = npos) const; + // Find char methods. Return the position or npos if the char was not found. + size_type find_first_of(value_type c, size_type pos = 0) const; + size_type find_last_of(value_type c, size_type pos = npos) const; + size_type find_first_not_of(value_type c, size_type pos = 0) const; + size_type find_last_not_of(value_type c, size_type pos = npos) const; + private: bool SafeMalloc(size_type n); void SafeRealloc(size_type n); diff --git a/src/string.cpp b/src/string.cpp index b67e732..4e763e6 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -560,6 +560,59 @@ string string::substr(size_type pos, size_type n) const { return string(*this, pos, n); } +string::size_type string::find_first_of(value_type c, size_type pos) const { + if (pos >= mLength) { + return npos; + } + const char *res; + // The last parameter represents a number of chars, not a index. + res = static_cast<const char *>(std::memchr(mData + pos, c, mLength - pos)); + return res != NULL ? res - mData : npos; +} + +string::size_type string::find_last_of(value_type c, size_type pos) const { + if (mLength == 0) { + return npos; + } else if (pos >= mLength) { + pos = mLength - 1; // >= 0 + } + + const char *res; + // Note:memrchr is not in the std namepace. + // The last parameter represents a number of chars, not a index. + res = static_cast<const char *>(memrchr(mData, c, pos + 1)); + return res != NULL ? res - mData : npos; +} + +string::size_type string::find_first_not_of(value_type c, size_type pos) const { + char *curr = mData + pos; + for (size_type i = pos; i < mLength; ++i, ++curr) { + if (c != *curr) { + return i; + } + } + return npos; +} + +string::size_type string::find_last_not_of(value_type c, size_type pos) const { + if (mLength == 0) { + return npos; + } else if (pos >= mLength) { + pos = mLength - 1; // >= 0 + } + + char *curr = mData + pos; + size_type i = pos; + + for (;; --i, --curr) { + if (c != *curr) { + return i; + } else if (i == 0) { + return npos; + } + } +} + ostream& operator<<(ostream& os, const string& str) { return os.write_formatted(str.data(), str.size()); } diff --git a/tests/Android.mk b/tests/Android.mk index 3233619..dab455a 100644 --- a/tests/Android.mk +++ b/tests/Android.mk @@ -12,9 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # -# Build control file for Bionic's test programs -# define the BIONIC_TESTS environment variable to build the test programs -# # define the ASTL_TESTS environment variable to build the test programs ifdef ASTL_TESTS diff --git a/tests/test_string.cpp b/tests/test_string.cpp index 100b23b..412f065 100644 --- a/tests/test_string.cpp +++ b/tests/test_string.cpp @@ -714,8 +714,8 @@ bool testFind() string haystack("one two three one two three"); // Don't die on null strings - EXPECT_TRUE(haystack.find(NULL) == string::npos); - EXPECT_TRUE(haystack.find(NULL, 10) == string::npos); + EXPECT_TRUE(haystack.find((char*)NULL) == string::npos); + EXPECT_TRUE(haystack.find((char*)NULL, 10) == string::npos); // C strings. EXPECT_TRUE(haystack.find("one") == 0); @@ -943,6 +943,85 @@ bool testSubstr() { return true; } +bool testCharSearch() { + { + string s; + EXPECT_TRUE(s.find_first_of('a') == string::npos); + s = "abracadabra"; + EXPECT_TRUE(s.find_first_of('a') == 0); + EXPECT_TRUE(s.find_first_of('a', 0) == 0); + EXPECT_TRUE(s.find_first_of('a', 1) == 3); + EXPECT_TRUE(s.find_first_of('a', 8) == 10); + s = "zzzzzzza"; + EXPECT_TRUE(s.find_first_of('a') == 7); + EXPECT_TRUE(s.find_first_of('a', 8) == string::npos); // out of bound + } + // For char (set of size 1) find_first_of is equive to find(char, pos) + { + string s; + EXPECT_TRUE(s.find('a') == string::npos); + s = "abracadabra"; + EXPECT_TRUE(s.find('a') == 0); + EXPECT_TRUE(s.find('a', 0) == 0); + EXPECT_TRUE(s.find('a', 1) == 3); + EXPECT_TRUE(s.find('a', 8) == 10); + s = "zzzzzzza"; + EXPECT_TRUE(s.find('a') == 7); + EXPECT_TRUE(s.find('a', 8) == string::npos); // out of bound + } + { + string s; + EXPECT_TRUE(s.find_last_of('a') == string::npos); + EXPECT_TRUE(s.find_last_of('a', 0) == string::npos); + EXPECT_TRUE(s.find_last_of('a', 10) == string::npos); + s = "abracadabra"; + EXPECT_TRUE(s.find_last_of('a', 10) == 10); + EXPECT_TRUE(s.find_last_of('a', 9) == 7); + EXPECT_TRUE(s.find_last_of('a', 0) == 0); + s = "azzzzzzz"; + EXPECT_TRUE(s.find_last_of('a') == 0); + } + // For char (set of size 1) find_last_of is equiv to rfind(char, pos). + { + string s; + EXPECT_TRUE(s.rfind('a') == string::npos); + EXPECT_TRUE(s.rfind('a', 0) == string::npos); + EXPECT_TRUE(s.rfind('a', 10) == string::npos); + s = "abracadabra"; + EXPECT_TRUE(s.rfind('a', 10) == 10); + EXPECT_TRUE(s.rfind('a', 9) == 7); + EXPECT_TRUE(s.rfind('a', 0) == 0); + s = "azzzzzzz"; + EXPECT_TRUE(s.rfind('a') == 0); + } + { + string s; + EXPECT_TRUE(s.find_first_not_of('a') == string::npos); + s = "abracadabra"; + EXPECT_TRUE(s.find_first_not_of('a') == 1); + EXPECT_TRUE(s.find_first_not_of('a', 0) == 1); + EXPECT_TRUE(s.find_first_not_of('a', 1) == 1); + EXPECT_TRUE(s.find_first_not_of('a', 7) == 8); + s = "zzzzzzza"; + EXPECT_TRUE(s.find_first_not_of('a') == 0); + EXPECT_TRUE(s.find_first_not_of('a', 8) == string::npos); // out of bound + } + { + string s; + EXPECT_TRUE(s.find_last_not_of('a') == string::npos); + EXPECT_TRUE(s.find_last_not_of('a', 0) == string::npos); + EXPECT_TRUE(s.find_last_not_of('a', 10) == string::npos); + s = "abracadabra"; + EXPECT_TRUE(s.find_last_not_of('a') == 9); + EXPECT_TRUE(s.find_last_not_of('a', 10) == 9); + EXPECT_TRUE(s.find_last_not_of('a', 9) == 9); + EXPECT_TRUE(s.find_last_not_of('a', 0) == string::npos); + s = "azzzzzzz"; + EXPECT_TRUE(s.find_last_not_of('a') == 7); + } + return true; +} + } // namespace android int main(int argc, char **argv) @@ -971,5 +1050,6 @@ int main(int argc, char **argv) FAIL_UNLESS(testConstIterator); FAIL_UNLESS(testForwardIterator); FAIL_UNLESS(testSubstr); + FAIL_UNLESS(testCharSearch); return kPassed; } |