From 7275a13d9f3cc8eaeb9d8be2a14db1ec67317f02 Mon Sep 17 00:00:00 2001 From: Darrell Wright Date: Sat, 4 Jan 2025 18:20:12 -0500 Subject: [PATCH] Refine `rfind` implementations and add related test. Improved the `rfind` function for better performance and correctness, including enhanced handling of character and substring searches. Updated `rfind` to include optimized logic for specific cases, such as using `memrchr` when applicable. Added a new test case to validate the updated `rfind` functionality. --- include/daw/daw_string_view.h | 41 +++++++++++++++++++++++++-------- tests/daw_string_view2_test.cpp | 7 ++++++ 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/include/daw/daw_string_view.h b/include/daw/daw_string_view.h index 1ed8bece..b5427541 100644 --- a/include/daw/daw_string_view.h +++ b/include/daw/daw_string_view.h @@ -1743,8 +1743,9 @@ namespace daw { return static_cast( static_cast( r ) - first ); } else if constexpr( sizeof( CharT ) == 2 ) { - void const *r = std::wmemchr( const_cast( first ), - static_cast( c ), sz ); + void const *r = + std::wmemchr( reinterpet_cast( first ), + static_cast( c ), sz ); if( r == nullptr ) { return npos; } @@ -1852,10 +1853,11 @@ namespace daw { if( v.empty( ) ) { return pos; } + do { - if( sv2_details::compare( m_first + - static_cast( pos ), - v.begin( ), v.size( ) ) == 0 ) { + if( sv2_details::compare( + std::next( m_first, static_cast( pos ) ), + v.begin( ), v.size( ) ) == 0 ) { return pos; } } while( pos-- > 0 ); @@ -1868,8 +1870,8 @@ namespace daw { /// @param pos starting position /// @param count size of substring /// @returns starting position of substring or npos if not found - [[nodiscard]] constexpr size_type rfind( const_pointer s, size_type pos, - size_type count ) const { + [[nodiscard]] DAW_ATTRIB_FLATTEN constexpr size_type + rfind( const_pointer s, size_type pos, size_type count ) const { return rfind( basic_string_view( s, count ), pos ); } @@ -1880,8 +1882,29 @@ namespace daw { /// @returns position of found character or npos [[nodiscard]] constexpr size_type rfind( CharT c, size_type pos = npos ) const { - return rfind( - basic_string_view( std::addressof( c ), 1 ), pos ); + if( empty( ) ) { + return npos; + } + pos = ( std::min )( { pos, size( ) - 1 } ); +#if defined( _GNU_SOURCE ) and defined( DAW_HAS_CONSTEVAL ) + if constexpr( sizeof( CharT ) == 1 ) { + if( not DAW_IS_CONSTANT_EVALUATED( ) ) { + void const *r = memrchr( m_first, static_cast( c ), pos ); + if( r == nullptr ) { + return npos; + } + return static_cast( static_cast( r ) - + m_first ); + } + } +#endif + + do { + if( m_first[static_cast( pos )] == c ) { + return pos; + } + } while( pos-- > 0 ); + return npos; } /// @brief find the last position of character in [data( ) + pos, data( ) diff --git a/tests/daw_string_view2_test.cpp b/tests/daw_string_view2_test.cpp index 56bf4060..34c1a378 100644 --- a/tests/daw_string_view2_test.cpp +++ b/tests/daw_string_view2_test.cpp @@ -1344,6 +1344,12 @@ namespace daw { daw_expecting( 16U, pos_sv ); } + void daw_rfind_test_004( ) { + daw::sv2::string_view const sv = "This is a string"; + auto pos_sv = sv.rfind( 's' ); + daw_expecting( 10U, pos_sv ); + } + void daw_find_test_001( ) { daw::sv2::string_view const sv = "This is a string"; auto pos_sv = sv.find( "is" ); @@ -1787,6 +1793,7 @@ int main( ) daw::daw_rfind_test_001( ); daw::daw_rfind_test_002( ); daw::daw_rfind_test_003( ); + daw::daw_rfind_test_004( ); daw::daw_find_test_001( ); daw::daw_find_test_002( ); daw::daw_find_test_003( );