More tests for string_ref

[SVN r81884]
This commit is contained in:
Marshall Clow
2012-12-13 02:17:49 +00:00
parent b7d4f04a8b
commit 9e130e7b4e
3 changed files with 181 additions and 35 deletions

View File

@ -63,7 +63,7 @@ namespace boost {
typedef const_iterator iterator; typedef const_iterator iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator; typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef const_reverse_iterator reverse_iterator; typedef const_reverse_iterator reverse_iterator;
typedef size_t size_type; typedef std::size_t size_type;
typedef ptrdiff_t difference_type; typedef ptrdiff_t difference_type;
static BOOST_CONSTEXPR_OR_CONST size_type npos = size_type(-1); static BOOST_CONSTEXPR_OR_CONST size_type npos = size_type(-1);
@ -162,18 +162,16 @@ namespace boost {
return cmp != 0 ? cmp : ( len_ == x.len_ ? 0 : len_ < x.len_ ? -1 : 1 ); return cmp != 0 ? cmp : ( len_ == x.len_ ? 0 : len_ < x.len_ ? -1 : 1 );
} }
bool starts_with(charT c) const { return !empty() && front() == c; } bool starts_with(charT c) const { return !empty() && traits::eq ( c, front()); }
bool starts_with(basic_string_ref x) const { bool starts_with(basic_string_ref x) const {
return len_ >= x.len_ && traits::compare ( ptr_, x.ptr_, x.len_ ) == 0; return len_ >= x.len_ && traits::compare ( ptr_, x.ptr_, x.len_ ) == 0;
} }
bool ends_with(charT c) const { return !empty() && back() == c; } bool ends_with(charT c) const { return !empty() && traits::eq ( c, back()); }
bool ends_with(basic_string_ref x) const { bool ends_with(basic_string_ref x) const {
return len_ >= x.len_ && traits::compare ( ptr_ + len_ - x.len_, x.ptr_, x.len_ ) == 0; return len_ >= x.len_ && traits::compare ( ptr_ + len_ - x.len_, x.ptr_, x.len_ ) == 0;
} }
// Have to use traits here
size_type find(basic_string_ref s) const { size_type find(basic_string_ref s) const {
const_iterator iter = std::search ( this->cbegin (), this->cend (), const_iterator iter = std::search ( this->cbegin (), this->cend (),
s.cbegin (), s.cend (), traits::eq ); s.cbegin (), s.cend (), traits::eq );
@ -187,7 +185,7 @@ namespace boost {
} }
size_type rfind(basic_string_ref s) const { size_type rfind(basic_string_ref s) const {
const_iterator iter = std::search ( this->crbegin (), this->crend (), const_reverse_iterator iter = std::search ( this->crbegin (), this->crend (),
s.crbegin (), s.crend (), traits::eq ); s.crbegin (), s.crend (), traits::eq );
return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter ); return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter );
} }
@ -198,27 +196,24 @@ namespace boost {
return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter ); return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter );
} }
size_type find_first_of(basic_string_ref s) const {
const_iterator iter = std::find_first_of ( this->cbegin (), this->cend (),
s.cbegin (), s.cend (), traits::eq );
return iter = this->cend () ? npos : std::distance ( this->cbegin (), iter );
}
size_type find_first_of(charT c) const { return find (c); } size_type find_first_of(charT c) const { return find (c); }
size_type find_last_of (charT c) const { return rfind (c); } size_type find_last_of (charT c) const { return rfind (c); }
size_type find_first_of(basic_string_ref s) const {
const_iterator iter = std::find_first_of
( this->cbegin (), this->cend (), s.cbegin (), s.cend (), traits::eq );
return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
}
size_type find_last_of(basic_string_ref s) const { size_type find_last_of(basic_string_ref s) const {
const_reverse_iterator iter = std::find_first_of ( this->crbegin (), this->crend (), const_reverse_iterator iter = std::find_first_of
s.crbegin (), s.crend (), traits::eq ); ( this->crbegin (), this->crend (), s.cbegin (), s.cend (), traits::eq );
return iter = this->cend () ? npos : reverse_distance ( this->crbegin (), iter); return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter);
} }
size_type find_first_not_of(basic_string_ref s) const { size_type find_first_not_of(basic_string_ref s) const {
for ( const_reverse_iterator iter = this->cbegin (); iter != this->cend (); ++iter ) const_iterator iter = find_not_of ( this->cbegin (), this->cend (), s );
if ( 0 == traits::find ( s->ptr_, s.len_, *iter )) return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
return std::distance ( this->cbegin (), iter );
return npos;
} }
size_type find_first_not_of(charT c) const { size_type find_first_not_of(charT c) const {
@ -229,10 +224,8 @@ namespace boost {
} }
size_type find_last_not_of(basic_string_ref s) const { size_type find_last_not_of(basic_string_ref s) const {
for ( const_reverse_iterator iter = this->crbegin (); iter != this->crend (); ++iter ) const_reverse_iterator iter = find_not_of ( this->crbegin (), this->crend (), s );
if ( 0 == traits::find ( s.ptr_, s.len_, *iter )) return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter );
return reverse_distance ( this->crbegin (), iter );
return npos;
} }
size_type find_last_not_of(charT c) const { size_type find_last_not_of(charT c) const {
@ -243,10 +236,21 @@ namespace boost {
} }
private: private:
size_type reverse_distance ( reverse_iterator first, reverse_iterator last ) const { template <typename r_iter>
return len_ - 1 + std::distance ( first, last ); size_type reverse_distance ( r_iter first, r_iter last ) const {
return len_ - 1 - std::distance ( first, last );
} }
template <typename Iterator>
Iterator find_not_of ( Iterator first, Iterator last, basic_string_ref s ) const {
for ( ; first != last ; ++first )
if ( 0 == traits::find ( s.ptr_, s.len_, *first ))
return first;
return last;
}
const charT *ptr_; const charT *ptr_;
std::size_t len_; std::size_t len_;
}; };

View File

@ -23,9 +23,11 @@ void interop ( const std::string &str, string_ref ref ) {
// BOOST_CHECK ( str == ref ); // BOOST_CHECK ( str == ref );
BOOST_CHECK ( str.size () == ref.size ()); BOOST_CHECK ( str.size () == ref.size ());
BOOST_CHECK ( std::equal ( str.begin (), str.end (), ref.begin ())); BOOST_CHECK ( std::equal ( str.begin (), str.end (), ref.begin ()));
BOOST_CHECK ( std::equal ( str.rbegin (), str.rend (), ref.rbegin ()));
} }
void substr ( const std::string &str ) { // make sure that substrings work just like strings
void test_substr ( const std::string &str ) {
const size_t sz = str.size (); const size_t sz = str.size ();
string_ref ref ( str ); string_ref ref ( str );
@ -43,6 +45,33 @@ void substr ( const std::string &str ) {
interop ( str.substr ( i, j ), ref.substr ( i, j )); interop ( str.substr ( i, j ), ref.substr ( i, j ));
} }
// make sure that removing prefixes and suffixes work just like strings
void test_remove ( const std::string &str ) {
const size_t sz = str.size ();
std::string work;
string_ref ref;
for ( size_t i = 1; i <= sz; ++i ) {
work = str;
ref = str;
while ( ref.size () >= i ) {
interop ( work, ref );
work.erase ( 0, i );
ref.remove_prefix (i);
}
}
for ( size_t i = 1; i < sz; ++ i ) {
work = str;
ref = str;
while ( ref.size () >= i ) {
interop ( work, ref );
work.erase ( work.size () - i, i );
ref.remove_suffix (i);
}
}
}
const char *test_strings [] = { const char *test_strings [] = {
"", "",
"1", "1",
@ -57,7 +86,8 @@ int test_main( int , char* [] ) {
while ( *p != NULL ) { while ( *p != NULL ) {
interop ( *p, *p ); interop ( *p, *p );
substr ( *p ); test_substr ( *p );
test_remove ( *p );
p++; p++;
} }

View File

@ -8,6 +8,7 @@
*/ */
#include <iostream> #include <iostream>
#include <cstring> // for std::strchr
#include <boost/algorithm/string_ref.hpp> #include <boost/algorithm/string_ref.hpp>
@ -16,6 +17,7 @@
typedef boost::string_ref string_ref; typedef boost::string_ref string_ref;
void ends_with ( const char *arg ) { void ends_with ( const char *arg ) {
const size_t sz = strlen ( arg );
string_ref sr ( arg ); string_ref sr ( arg );
string_ref sr2 ( arg ); string_ref sr2 ( arg );
const char *p = arg; const char *p = arg;
@ -36,10 +38,16 @@ void ends_with ( const char *arg ) {
sr2.remove_prefix (1); sr2.remove_prefix (1);
} }
BOOST_CHECK ( sr.ends_with ( string_ref ())); char ch = sz == 0 ? '\0' : arg [ sz - 1 ];
sr2 = arg;
if ( sz > 0 )
BOOST_CHECK ( sr2.ends_with ( ch ));
BOOST_CHECK ( !sr2.ends_with ( ++ch ));
BOOST_CHECK ( sr2.ends_with ( string_ref ()));
} }
void starts_with ( const char *arg ) { void starts_with ( const char *arg ) {
const size_t sz = strlen ( arg );
string_ref sr ( arg ); string_ref sr ( arg );
string_ref sr2 ( arg ); string_ref sr2 ( arg );
const char *p = arg + std::strlen ( arg ) - 1; const char *p = arg + std::strlen ( arg ) - 1;
@ -54,7 +62,12 @@ void starts_with ( const char *arg ) {
sr2.remove_suffix (1); sr2.remove_suffix (1);
} }
BOOST_CHECK ( sr.starts_with ( string_ref ())); char ch = *arg;
sr2 = arg;
if ( sz > 0 )
BOOST_CHECK ( sr2.starts_with ( ch ));
BOOST_CHECK ( !sr2.starts_with ( ++ch ));
BOOST_CHECK ( sr2.starts_with ( string_ref ()));
} }
void reverse ( const char *arg ) { void reverse ( const char *arg ) {
@ -71,10 +84,56 @@ void reverse ( const char *arg ) {
void find ( const char *arg ) { void find ( const char *arg ) {
string_ref sr1 ( arg ); string_ref sr1;
const char *p = arg; string_ref sr2;
const char *p;
// Look for each character in the string(searching from the start)
p = arg;
sr1 = arg;
while ( *p ) {
string_ref::size_type pos = sr1.find(*p);
BOOST_CHECK ( pos != string_ref::npos && ( pos <= p - arg ));
++p;
}
// Look for each character in the string (searching from the end)
p = arg;
sr1 = arg;
while ( *p ) {
string_ref::size_type pos = sr1.rfind(*p);
BOOST_CHECK ( pos != string_ref::npos && pos < sr1.size () && ( pos >= p - arg ));
++p;
}
sr1 = arg;
p = arg;
// for all possible chars, see if we find them in the right place.
// Note that strchr will/might do the _wrong_ thing if we search for NULL
for ( int ch = 1; ch < 256; ++ch ) {
string_ref::size_type pos = sr1.find(ch);
const char *strp = std::strchr ( arg, ch );
BOOST_CHECK (( strp == NULL ) == ( pos == string_ref::npos ));
if ( strp != NULL )
BOOST_CHECK (( strp - arg ) == pos );
}
sr1 = arg;
p = arg;
// for all possible chars, see if we find them in the right place.
// Note that strchr will/might do the _wrong_ thing if we search for NULL
for ( int ch = 1; ch < 256; ++ch ) {
string_ref::size_type pos = sr1.rfind(ch);
const char *strp = std::strrchr ( arg, ch );
BOOST_CHECK (( strp == NULL ) == ( pos == string_ref::npos ));
if ( strp != NULL )
BOOST_CHECK (( strp - arg ) == pos );
}
// Find everything at the start // Find everything at the start
p = arg;
sr1 = arg;
while ( !sr1.empty ()) { while ( !sr1.empty ()) {
string_ref::size_type pos = sr1.find(*p); string_ref::size_type pos = sr1.find(*p);
BOOST_CHECK ( pos == 0 ); BOOST_CHECK ( pos == 0 );
@ -112,12 +171,65 @@ void find ( const char *arg ) {
sr1.remove_suffix (1); sr1.remove_suffix (1);
--p; --p;
} }
// Basic sanity checking for "find_first_of / find_first_not_of"
sr1 = arg;
sr2 = arg;
while ( !sr1.empty() ) {
BOOST_CHECK ( sr1.find_first_of ( sr2 ) == 0 );
BOOST_CHECK ( sr1.find_first_not_of ( sr2 ) == string_ref::npos );
sr1.remove_prefix ( 1 );
}
p = arg;
sr1 = arg;
while ( *p ) {
string_ref::size_type pos1 = sr1.find_first_of(*p);
string_ref::size_type pos2 = sr1.find_first_not_of(*p);
BOOST_CHECK ( pos1 != string_ref::npos && pos1 < sr1.size () && pos1 <= ( p - arg ));
if ( pos2 != string_ref::npos ) {
for ( size_t i = 0 ; i < pos2; ++i )
BOOST_CHECK ( sr1[i] == *p );
BOOST_CHECK ( sr1 [ pos2 ] != *p );
}
BOOST_CHECK ( pos2 != pos1 );
++p;
}
// Basic sanity checking for "find_last_of / find_last_not_of"
sr1 = arg;
sr2 = arg;
while ( !sr1.empty() ) {
BOOST_CHECK ( sr1.find_last_of ( sr2 ) == ( sr1.size () - 1 ));
BOOST_CHECK ( sr1.find_last_not_of ( sr2 ) == string_ref::npos );
sr1.remove_suffix ( 1 );
}
p = arg;
sr1 = arg;
while ( *p ) {
string_ref::size_type pos1 = sr1.find_last_of(*p);
string_ref::size_type pos2 = sr1.find_last_not_of(*p);
BOOST_CHECK ( pos1 != string_ref::npos && pos1 < sr1.size () && pos1 >= ( p - arg ));
BOOST_CHECK ( pos2 == string_ref::npos || pos1 < sr1.size ());
if ( pos2 != string_ref::npos ) {
for ( size_t i = sr1.size () -1 ; i > pos2; --i )
BOOST_CHECK ( sr1[i] == *p );
BOOST_CHECK ( sr1 [ pos2 ] != *p );
}
BOOST_CHECK ( pos2 != pos1 );
++p;
}
} }
const char *test_strings [] = { const char *test_strings [] = {
"", "",
"0", "0",
"abc", "abc",
"AAA", // all the same
"adsfadadiaef;alkdg;aljt;j agl;sjrl;tjs;lga;lretj;srg[w349u5209dsfadfasdfasdfadsf", "adsfadadiaef;alkdg;aljt;j agl;sjrl;tjs;lga;lretj;srg[w349u5209dsfadfasdfasdfadsf",
"abc\0asdfadsfasf", "abc\0asdfadsfasf",
NULL NULL