aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Catania <niko@google.com>2010-02-07 20:21:04 -0800
committerNicolas Catania <niko@google.com>2010-02-08 13:39:07 -0800
commitcb8eb8e1390d1343563a55c117b5c39cfa87fe1d (patch)
tree0ff37f0e023f29bc7b584a273cfe2440011623e7
parent40d9e34c926f59cae26c4bae4ab55377cf3cdd40 (diff)
downloadastl-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/string22
-rw-r--r--src/string.cpp53
-rw-r--r--tests/Android.mk3
-rw-r--r--tests/test_string.cpp84
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;
}