forked from boostorg/algorithm
More tests for string_ref
[SVN r81884]
This commit is contained in:
@ -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_;
|
||||||
};
|
};
|
||||||
|
@ -22,10 +22,12 @@ typedef boost::string_ref string_ref;
|
|||||||
void interop ( const std::string &str, string_ref ref ) {
|
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++;
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
Reference in New Issue
Block a user