Added get_token_list to string_utilities to retrieve multiple tokens

This commit is contained in:
John Wellbelove 2025-05-21 09:56:17 +01:00
parent 95a4b107c7
commit f33c40001f
4 changed files with 196 additions and 5 deletions

View File

@ -46,6 +46,36 @@ SOFTWARE.
namespace etl
{
namespace detail
{
//Helper: only performs the v < F check when has_lower == true ––
template <bool has_lower, typename U, U F>
struct lower_bound_impl;
// Specialisation for First != 0: enforce v >= First
template <typename U, U F>
struct lower_bound_impl<true, U, F>
{
static ETL_CONSTEXPR auto apply(U& v) ETL_NOEXCEPT -> void
{
if (v < F)
{
v = F;
}
}
};
// Specialisation for First == 0: no-op
template <typename U, U F>
struct lower_bound_impl<false, U, F>
{
static ETL_CONSTEXPR auto apply(U&) ETL_NOEXCEPT -> void
{
// nothing
}
};
} // namespace detail
//***************************************************************************
/// Provides a value that cycles between two limits.
//***************************************************************************
@ -113,10 +143,9 @@ namespace etl
{
value_ = Last;
}
else if (value_ < First)
{
value_ = First;
}
// lower-bound clamp only if First != 0
detail::lower_bound_impl<(First != 0), T, First>::apply(value_);
value = value_;
}
@ -351,7 +380,7 @@ namespace etl
cyclic_value(T first_, T last_)
: value(first_)
, first_value(first_)
, last_value(last_)
, last_value(last_)
{
}

View File

@ -756,6 +756,45 @@ namespace etl
return etl::optional<TStringView>(view);
}
//***************************************************************************
/// get_token_list
///\brief Splits a string of tokens to a set of views, according to a set of delimiters.
/// The tokenisation stops if:
/// 1. The end of the input text is reached.
/// 2. The max_size() of the output container is reached.
/// 3. The number of tokens found reaches max_n_tokens.
/// The input container must define <code>const_pointer</code>.
/// The output container must define <code>value_type</code>.
/// The output container must define the member function <code>max_size</code> that returns the maximum size of the container.
/// The output container must define the member function <code>push_back</code> that pushes the view on to the back of the container.
///\param input The input string.
///\param output A reference to an output container of string views.
///\param delimiters A pointer to a string of valid delimiters.
///\param ignore_empty_tokens If <b>true</b> then empty tokens are ignored.
///\param max_n_tokens The maximum number of tokens to collect. Default tokenise everything.
///\return Returns <b>true</b> if all tokens were added to the list, otherwise <b>false</b>.
//***************************************************************************
template <typename TInput, typename TOutput>
bool get_token_list(const TInput& input, TOutput& output, typename TInput::const_pointer delimiters, bool ignore_empty_tokens, size_t max_n_tokens = etl::integral_limits<size_t>::max)
{
typedef typename TOutput::value_type string_view_t;
etl::optional<string_view_t> token;
size_t count = 0;
while ((count != output.max_size()) &&
(count != max_n_tokens) &&
(token = etl::get_token(input, delimiters, token, ignore_empty_tokens)))
{
output.push_back(token.value());
++count;
}
bool all_tokens_found = (token.has_value() == false);
return all_tokens_found;
}
//***************************************************************************
/// pad_left
//***************************************************************************

View File

@ -3,6 +3,7 @@
Updates:
Added etl::tuple
Added get_token_list to string_utilities to retrieve multiple tokens
#757 Add etl::chrono time/date classes
#1085 Add The Remaining Math Operators To ETL_TYPEDEF
#1084 Add 'type' Alias to Strong Types
@ -29,6 +30,7 @@ Fixes:
#1041 Incorrect rounding of scaled natural numbers in scaled_rounding #1041
Pull Requests:
#1088 Fix numeric overflow in bip buffer's get_write_reserve
#1090 Fix copy_s() for C++03
#1089 Cleanup fixes for C++03
#1083 Add take() to etl::span

View File

@ -34,6 +34,9 @@ SOFTWARE.
#include "etl/vector.h"
#include <string>
#include <string_view>
#include <vector>
#include <list>
#undef STR
#define STR(x) x
@ -54,6 +57,9 @@ namespace
using Vector = etl::vector<String, 15>;
using SizeType = etl::istring::size_type;
using VectorOfViews7 = etl::vector<StringView, 7>;
using VectorOfViews5 = etl::vector<StringView, 5>;
#if ETL_USING_CPP17
constexpr auto Whitespace = etl::whitespace_v<String::value_type>;
#else
@ -1085,6 +1091,121 @@ namespace
CHECK_EQUAL(0U, tokens.size());
}
//*************************************************************************
TEST(test_split_to_vector_of_string_view_all_tokens_captured_ignore_empty_tokens)
{
String text(STR(",,,The,cat,sat,,on,the,mat"));
VectorOfViews7 views;
bool all_views_found = etl::get_token_list(text, views, STR(","), true);
CHECK_TRUE(all_views_found);
CHECK_EQUAL(6, views.size());
CHECK_EQUAL(std::string("The"), std::string(views[0].begin(), views[0].end()));
CHECK_EQUAL(std::string("cat"), std::string(views[1].begin(), views[1].end()));
CHECK_EQUAL(std::string("sat"), std::string(views[2].begin(), views[2].end()));
CHECK_EQUAL(std::string("on"), std::string(views[3].begin(), views[3].end()));
CHECK_EQUAL(std::string("the"), std::string(views[4].begin(), views[4].end()));
CHECK_EQUAL(std::string("mat"), std::string(views[5].begin(), views[5].end()));
}
//*************************************************************************
TEST(test_get_token_list_to_vector_of_string_view_all_but_1_tokens_captured_ignore_empty_tokens)
{
String text(STR(",,,The,cat,sat,,on,the,mat"));
VectorOfViews5 views;
bool all_views_found = etl::get_token_list(text, views, STR(","), true);
CHECK_FALSE(all_views_found);
CHECK_EQUAL(5, views.size());
CHECK_EQUAL(std::string("The"), std::string(views[0].begin(), views[0].end()));
CHECK_EQUAL(std::string("cat"), std::string(views[1].begin(), views[1].end()));
CHECK_EQUAL(std::string("sat"), std::string(views[2].begin(), views[2].end()));
CHECK_EQUAL(std::string("on"), std::string(views[3].begin(), views[3].end()));
CHECK_EQUAL(std::string("the"), std::string(views[4].begin(), views[4].end()));
}
#if ETL_USING_CPP17
//*************************************************************************
TEST(test_get_token_list_to_std_vector_of_std_string_view_all_tokens_captured_ignore_empty_tokens)
{
std::string text(STR(",,,The,cat,sat,,on,the,mat"));
std::vector<std::string_view> views;
bool all_views_found = etl::get_token_list(text, views, STR(","), true);
CHECK_TRUE(all_views_found);
CHECK_EQUAL(6, views.size());
CHECK_EQUAL(std::string("The"), std::string(views[0].begin(), views[0].end()));
CHECK_EQUAL(std::string("cat"), std::string(views[1].begin(), views[1].end()));
CHECK_EQUAL(std::string("sat"), std::string(views[2].begin(), views[2].end()));
CHECK_EQUAL(std::string("on"), std::string(views[3].begin(), views[3].end()));
CHECK_EQUAL(std::string("the"), std::string(views[4].begin(), views[4].end()));
CHECK_EQUAL(std::string("mat"), std::string(views[5].begin(), views[5].end()));
}
#endif
//*************************************************************************
TEST(test_get_token_list_to_vector_of_string_view_all_tokens_captured_ignore_empty_tokens_maximum_of_3_tokens)
{
String text(STR(",,,The,cat,sat,,on,the,mat"));
VectorOfViews7 views;
bool all_views_found = etl::get_token_list(text, views, STR(","), true, 3);
CHECK_FALSE(all_views_found);
CHECK_EQUAL(3, views.size());
CHECK_EQUAL(std::string("The"), std::string(views[0].begin(), views[0].end()));
CHECK_EQUAL(std::string("cat"), std::string(views[1].begin(), views[1].end()));
CHECK_EQUAL(std::string("sat"), std::string(views[2].begin(), views[2].end()));
}
#if ETL_USING_CPP17
//*************************************************************************
TEST(test_get_token_list_to_std_vector_of_std_string_view_all_tokens_captured_ignore_empty_tokens_maximum_of_3_tokens)
{
std::string text(STR(",,,The,cat,sat,,on,the,mat"));
std::vector<std::string_view> views;
bool all_views_found = etl::get_token_list(text, views, STR(","), true, 3);
CHECK_FALSE(all_views_found);
CHECK_EQUAL(3, views.size());
CHECK_EQUAL(std::string("The"), std::string(views[0].begin(), views[0].end()));
CHECK_EQUAL(std::string("cat"), std::string(views[1].begin(), views[1].end()));
CHECK_EQUAL(std::string("sat"), std::string(views[2].begin(), views[2].end()));
}
#endif
#if ETL_USING_CPP17
//*************************************************************************
TEST(test_get_token_list_to_std_list_of_std_string_view_all_tokens_captured_ignore_empty_tokens)
{
std::string text(STR(",,,The,cat,sat,,on,the,mat"));
std::list<std::string_view> views;
bool all_views_found = etl::get_token_list(text, views, STR(","), true);
CHECK_TRUE(all_views_found);
CHECK_EQUAL(6, views.size());
auto itr = views.begin();
CHECK_EQUAL(std::string("The"), std::string(itr->begin(), itr->end()));
++itr;
CHECK_EQUAL(std::string("cat"), std::string(itr->begin(), itr->end()));
++itr;
CHECK_EQUAL(std::string("sat"), std::string(itr->begin(), itr->end()));
++itr;
CHECK_EQUAL(std::string("on"), std::string(itr->begin(), itr->end()));
++itr;
CHECK_EQUAL(std::string("the"), std::string(itr->begin(), itr->end()));
++itr;
CHECK_EQUAL(std::string("mat"), std::string(itr->begin(), itr->end()));
}
#endif
//*************************************************************************
TEST(test_pad_left)
{