Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 144 additions & 4 deletions include/daw/daw_string_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -1379,6 +1379,45 @@ namespace daw {
return result;
}

/// @brief Searches backwards for the first non-match of where, returns
/// the matching suffix, then removes it from the string_view
/// @param where The character to extract
/// @return substring after the last non-matching character
[[nodiscard]] constexpr basic_string_view pop_back_while( CharT where ) {
auto const pos = find_last_not_of( where );
auto const count =
pos == npos ? size( ) : static_cast<size_type>( size( ) - pos - 1U );
return pop_back( count );
}

/// @brief Searches backwards for the first character not in where,
/// returns the matching suffix, then removes it from the string_view
/// @param where The characters to extract
/// @return substring after the last non-matching character
[[nodiscard]] constexpr basic_string_view
pop_back_while( basic_string_view where ) {
auto const pos = find_last_not_of( where );
auto const count =
pos == npos ? size( ) : static_cast<size_type>( size( ) - pos - 1U );
return pop_back( count );
}

/// @brief Searches backwards until pred is false, returns the matching
/// suffix, then removes it from the string_view
/// @tparam UnaryPredicate A predicate taking a single CharT
/// @param pred Predicate identifying characters to extract
/// @return substring after the last character where pred is false
template<typename UnaryPredicate DAW_REQ_UNARY_PRED( UnaryPredicate,
CharT )>
DAW_REQ_UNARY_PRED_REQ( UnaryPredicate, CharT )
[[nodiscard]] constexpr basic_string_view
pop_back_while( UnaryPredicate pred ) {
auto const pos = find_last_not_of_if( std::move( pred ) );
auto const count =
pos == npos ? size( ) : static_cast<size_type>( size( ) - pos - 1U );
return pop_back( count );
}

/// @brief searches for last where, returns substring between
/// where and end, then pops off the substring
/// @param where string to split on and remove from back
Expand Down Expand Up @@ -1798,6 +1837,80 @@ namespace daw {
return *this;
}

/// @brief Searches backwards for where and removes it and everything
/// after it
/// @param where Character to find and consume
/// @return A reference to the current string_view object
DAW_ATTRIB_INLINE constexpr basic_string_view &
remove_suffix_until( CharT where ) {
auto const pos = rfind( where );
resize( pos == npos ? 0U : pos );
return *this;
}

/// @brief Searches backwards for where and removes everything after it
/// @param where Character to find and retain
/// @return A reference to the current string_view object
DAW_ATTRIB_INLINE constexpr basic_string_view &
remove_suffix_until( CharT where, nodiscard_t ) {
auto const pos = rfind( where );
resize( pos == npos ? 0U : pos + 1U );
return *this;
}

/// @brief Searches backwards for where and removes it and everything
/// after it
/// @param where String to find and consume
/// @return A reference to the current string_view object
DAW_ATTRIB_INLINE constexpr basic_string_view &
remove_suffix_until( basic_string_view where ) {
auto const pos = rfind( where );
resize( pos == npos ? 0U : pos );
return *this;
}

/// @brief Searches backwards for where and removes everything after it
/// @param where String to find and retain
/// @return A reference to the current string_view object
DAW_ATTRIB_INLINE constexpr basic_string_view &
remove_suffix_until( basic_string_view where, nodiscard_t ) {
auto const pos = rfind( where );
resize( pos == npos ? 0U : pos + where.size( ) );
return *this;
}

/// @brief Removes the suffix starting at the last position where pred is
/// true
/// @tparam UnaryPredicate A predicate taking a single CharT
/// @param pred Predicate identifying where to stop
/// @return A reference to the current string_view object
template<typename UnaryPredicate DAW_REQ_UNARY_PRED( UnaryPredicate,
CharT )>
DAW_REQ_UNARY_PRED_REQ( UnaryPredicate, CharT )
DAW_ATTRIB_INLINE constexpr basic_string_view &remove_suffix_until(
UnaryPredicate pred ) {
auto const pos = find_last_of_if( pred );
resize( pos == npos ? 0U : pos );
return *this;
}

/// @brief Removes the suffix after the last position where pred is true
/// @tparam UnaryPredicate A predicate taking a single CharT
/// @param pred Predicate identifying where to stop
/// @return A reference to the current string_view object
template<typename UnaryPredicate DAW_REQ_UNARY_PRED( UnaryPredicate,
CharT )>
DAW_REQ_UNARY_PRED_REQ( UnaryPredicate, CharT )
DAW_ATTRIB_INLINE
constexpr basic_string_view &remove_suffix_until( UnaryPredicate pred,
nodiscard_t ) {
auto const pos = find_last_of_if( pred );
resize( pos == npos
? 0U
: pos + sv2_details::find_predicate_result_size( pred ) );
return *this;
}

/// @brief Set the size of the range
/// @param new_size New size of range
/// @pre size( ) >= new_size
Expand Down Expand Up @@ -2532,13 +2645,12 @@ namespace daw {
return find_first_not_of( basic_string_view<CharT>( s, N - 1 ), 0 );
}

[[nodiscard]] constexpr bool
all_of( basic_string_view v, size_type pos = 0 ) const {
[[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 {
[[nodiscard]] constexpr bool all_of( CharT c, size_type pos = 0 ) const {
return find_first_not_of( c, pos ) == npos;
}

Expand Down Expand Up @@ -2858,6 +2970,13 @@ namespace daw {
return *this;
}

DAW_ATTRIB_INLINE constexpr basic_string_view &
remove_prefix_while( basic_string_view characters ) noexcept {
auto const pos = find_first_not_of( characters );
remove_prefix( pos );
return *this;
}

constexpr basic_string_view &trim_prefix( ) noexcept {
remove_prefix_while( is_space{ } );
return *this;
Expand Down Expand Up @@ -2886,6 +3005,13 @@ namespace daw {
return *this;
}

DAW_ATTRIB_INLINE constexpr basic_string_view &
remove_suffix_while( basic_string_view characters ) noexcept {
auto const pos = find_last_not_of( characters );
resize( pos + 1U );
return *this;
}

constexpr basic_string_view &trim_suffix( ) noexcept {
remove_suffix_while( is_space{ } );
return *this;
Expand All @@ -2909,6 +3035,20 @@ namespace daw {
return result;
}

constexpr basic_string_view &
trim( basic_string_view while_this ) noexcept {
(void)remove_prefix_while( while_this );
(void)remove_suffix_while( while_this );
return *this;
}

[[nodiscard]] constexpr basic_string_view
trim_copy( basic_string_view while_this ) const noexcept {
auto result = *this;
result.trim( while_this );
return result;
}

/// @brief Decrement the data( ) pointer by 1.
/// @pre data( ) != null and data( ) - 1 is a valid object
constexpr void expand_prefix( ) noexcept {
Expand Down
126 changes: 126 additions & 0 deletions tests/daw_string_view2_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1368,6 +1368,36 @@ namespace daw {
daw_expecting( result, " "_sv );
}

void daw_pop_back_while_sv_test_001( ) {
daw::sv2::string_view sv = "This is a test ";
auto result = sv.pop_back_while( ' ' );
daw_expecting( sv, "This is a test"_sv );
daw_expecting( result, " "_sv );
}

void daw_pop_back_while_sv_test_002( ) {
daw::sv2::string_view sv = "This is a test \t\n";
auto result = sv.pop_back_while( " \t\n" );
daw_expecting( sv, "This is a test"_sv );
daw_expecting( result, " \t\n"_sv );
}

void daw_pop_back_while_pred_test_001( ) {
daw::sv2::string_view sv = "test123";
auto result = sv.pop_back_while( []( char c ) {
return c >= '0' and c <= '9';
} );
daw_expecting( sv, "test"_sv );
daw_expecting( result, "123"_sv );

daw::sv2::string_view all = "123";
daw_expecting( all.pop_back_while( []( char c ) {
return c >= '0' and c <= '9';
} ),
"123"_sv );
daw_expecting( all.empty( ), true );
}

void daw_pop_front_test_001( ) {
daw::sv2::string_view sv = "This is a test";
auto result = sv.pop_front( );
Expand Down Expand Up @@ -1716,6 +1746,50 @@ namespace daw {
daw_expecting( sz, 5 );
}

void daw_remove_suffix_until_test_001( ) {
daw::sv2::string_view sv = "0123456789";
sv.remove_suffix_until( '5' );
daw_expecting( sv, "01234"_sv );
}

void daw_remove_suffix_until_test_002( ) {
daw::sv2::string_view sv = "0123456789";
sv.remove_suffix_until( '5', daw::nodiscard );
daw_expecting( sv, "012345"_sv );
}

void daw_remove_suffix_until_test_003( ) {
daw::sv2::string_view sv = "left::middle::right";
sv.remove_suffix_until( "::" );
daw_expecting( sv, "left::middle"_sv );

daw::sv2::string_view retained = "left::middle::right";
retained.remove_suffix_until( "::", daw::nodiscard );
daw_expecting( retained, "left::middle::"_sv );
}

void daw_remove_suffix_until_test_004( ) {
daw::sv2::string_view sv = "abc1def2ghi";
sv.remove_suffix_until( []( char c ) {
return c >= '0' and c <= '9';
} );
daw_expecting( sv, "abc1def"_sv );

daw::sv2::string_view retained = "abc1def2ghi";
retained.remove_suffix_until(
[]( char c ) {
return c >= '0' and c <= '9';
},
daw::nodiscard );
daw_expecting( retained, "abc1def2"_sv );
}

void daw_remove_suffix_until_test_005( ) {
daw::sv2::string_view sv = "test";
sv.remove_suffix_until( 'x' );
daw_expecting( sv.empty( ), true );
}

struct FooSV {
using iterator = char const *;
using size_type = std::size_t;
Expand Down Expand Up @@ -1835,6 +1909,47 @@ namespace daw {
daw_expecting( sv2, "Hello" );
}

void daw_trim_characters( ) {
daw::sv2::string_view sv = " \t,;Hello, world;\n ";
auto const *const original_data = sv.data( );
auto &result = sv.trim( " \t\n,;" );
daw_expecting( std::addressof( result ), std::addressof( sv ) );
daw_expecting( sv, "Hello, world" );
daw_expecting( sv.data( ), original_data + 4 );
}

void daw_trim_characters_copy( ) {
daw::sv2::string_view sv = "...Hello!?";
auto const result = sv.trim_copy( ".!?" );
daw_expecting( result, "Hello" );
daw_expecting( sv, "...Hello!?" );
}

void daw_trim_characters_edge_cases( ) {
daw::sv2::string_view no_matches = "Hello";
no_matches.trim( ".!?" );
daw_expecting( no_matches, "Hello" );

daw::sv2::string_view all_matches = ".!?..!";
all_matches.trim( ".!?" );
daw_expecting( all_matches.empty( ), true );

daw::sv2::string_view empty_set = "Hello";
empty_set.trim( "" );
daw_expecting( empty_set, "Hello" );

daw::sv2::string_view empty = "";
empty.trim( ".!?" );
daw_expecting( empty.empty( ), true );
}

constexpr bool daw_trim_characters_constexpr( ) {
daw::sv2::string_view sv = "--value++";
return sv.trim_copy( "+-" ) == "value" and
sv.trim( "+-" ) == "value";
}
static_assert( daw_trim_characters_constexpr( ) );

namespace daw_array_ctad_impl {
template<typename S>
constexpr auto foo( S &&s ) {
Expand Down Expand Up @@ -2172,6 +2287,9 @@ int main( )
daw::daw_pop_front_until_sv_test_001( );
daw::daw_pop_front_while_sv_test_001( );
daw::daw_pop_front_while_sv_test_002( );
daw::daw_pop_back_while_sv_test_001( );
daw::daw_pop_back_while_sv_test_002( );
daw::daw_pop_back_while_pred_test_001( );
daw::daw_pop_back_count_test_001( );
daw::daw_pop_back_until_sv_test_001( );
daw::daw_pop_back_until_sv_test_002( );
Expand Down Expand Up @@ -2201,6 +2319,11 @@ int main( )
daw::daw_remove_prefix_until_test_004( );
daw::daw_remove_suffix_while_test_001( );
daw::daw_remove_suffix_while_test_002( );
daw::daw_remove_suffix_until_test_001( );
daw::daw_remove_suffix_until_test_002( );
daw::daw_remove_suffix_until_test_003( );
daw::daw_remove_suffix_until_test_004( );
daw::daw_remove_suffix_until_test_005( );
daw::daw_arbutrary_string_view_list_001( );
daw::daw_trim_prefix_test_001( );
daw::daw_trim_prefix_test_002( );
Expand All @@ -2220,6 +2343,9 @@ int main( )
#endif
daw::daw_trim( );
daw::daw_trim_copy( );
daw::daw_trim_characters( );
daw::daw_trim_characters_copy( );
daw::daw_trim_characters_edge_cases( );
daw::daw_array_ctad( );
daw::daw_find_first_match( );
#if defined( DAW_HAS_CPP20_3WAY_COMPARE )
Expand Down
Loading