diff --git a/include/daw/daw_string_view.h b/include/daw/daw_string_view.h index 63ee56304..286b19147 100644 --- a/include/daw/daw_string_view.h +++ b/include/daw/daw_string_view.h @@ -2324,6 +2324,14 @@ namespace daw { return static_cast( std::distance( begin( ), iter ) ); } + template + DAW_REQ_UNARY_PRED_REQ( UnaryPredicate, CharT ) + [[nodiscard]] constexpr bool all_of_if( UnaryPredicate pred, + size_type pos = 0 ) const { + return find_first_not_of_if( std::move( pred ), pos ) == npos; + } + [[nodiscard]] constexpr size_type find_first_of( CharT c, size_type pos = 0 ) const { // Searching for a single character is exactly what find( ) does, @@ -2524,6 +2532,45 @@ namespace daw { return find_first_not_of( basic_string_view( s, N - 1 ), 0 ); } + [[nodiscard]] constexpr bool + all_of( basic_string_view v, size_type pos = 0 ) const { + return find_first_not_of( v, pos ) == npos; + } + + [[nodiscard]] constexpr bool all_of( CharT c, + size_type pos = 0 ) const { + return find_first_not_of( c, pos ) == npos; + } + + [[nodiscard]] constexpr bool all_of( const_pointer s, size_type pos, + size_type count ) const { + return find_first_not_of( s, pos, count ) == npos; + } + + [[nodiscard]] constexpr bool all_of( const_pointer s, + size_type pos ) const { + return find_first_not_of( s, pos ) == npos; + } + + template + [[nodiscard]] constexpr bool all_of( CharT const ( &&s )[N], + size_type pos ) const { + daw_dbg_ensure( s[N - 1] == CharT{ } ); + return find_first_not_of( basic_string_view( s, N - 1 ), pos ) == + npos; + } + + [[nodiscard]] constexpr bool all_of( const_pointer s ) const { + return find_first_not_of( s ) == npos; + } + + template + [[nodiscard]] constexpr bool all_of( CharT const ( &&s )[N] ) const { + daw_dbg_ensure( s[N - 1] == CharT{ } ); + return find_first_not_of( basic_string_view( s, N - 1 ), 0 ) == + npos; + } + template DAW_REQ_UNARY_PRED_REQ( UnaryPredicate, CharT ) diff --git a/tests/daw_string_view2_test.cpp b/tests/daw_string_view2_test.cpp index bac4d75b6..82cb79833 100644 --- a/tests/daw_string_view2_test.cpp +++ b/tests/daw_string_view2_test.cpp @@ -286,6 +286,45 @@ namespace daw { daw_expecting( daw::sv2::string_view::npos, pos ); } + constexpr bool daw_string_view_all_of_tests( ) { + using daw::sv2::string_view; + + constexpr string_view empty{ }; + constexpr string_view repeated = "aaaa"; + constexpr string_view mixed = "abca"; + + return empty.all_of( 'a' ) and repeated.all_of( 'a' ) and + not mixed.all_of( 'a' ) and mixed.all_of( 'a', mixed.size( ) ) and + mixed.all_of( string_view{ "abc" } ) and + not mixed.all_of( string_view{ "ab" } ) and + mixed.all_of( "abc" ) and not mixed.all_of( "ab" ) and + mixed.all_of( "a", 3 ) and mixed.all_of( "a", 3, 1 ) and + not mixed.all_of( "a", 2, 1 ) and empty.all_of( "" ) and + not repeated.all_of( "" ); + } + + constexpr bool daw_string_view_all_of_if_tests( ) { + using daw::sv2::string_view; + auto const is_lower = []( char c ) { + return c >= 'a' and c <= 'z'; + }; + + return string_view{ }.all_of_if( is_lower ) and + string_view{ "lower" }.all_of_if( is_lower ) and + not string_view{ "lower1" }.all_of_if( is_lower ) and + string_view{ "1lower" }.all_of_if( is_lower, 1 ) and + string_view{ "1" }.all_of_if( is_lower, 1 ); + } + + static_assert( daw_string_view_all_of_tests( ) ); + static_assert( daw_string_view_all_of_if_tests( ) ); + + static_assert( [] { + daw::sv2::string_view const sv = "abca"; + char const chars[] = "ab"; + return sv.find_first_not_of( std::move( chars ) ) == 2; + }( ) ); + void daw_string_view_find_first_of_001( ) { daw::sv2::string_view const a = "abcdefghijklm"; auto pos = a.find_first_of( "def" );