Skip to main content

Utility functions

Utility functions for handling strings in tests. More...

Functions Index​

const char *extract_file_name (const char *path) noexcept

Extracts the file name component from a full path. More...

boolis_match (std::string_view input, std::string_view pattern)

Checks whether a string matches a pattern with * and ? wildcards. More...

std::vector< std::string_view >split (std::string_view input, std::string_view delimiters)

Splits a string view into a vector of string views. More...

template <class T, class Delim_T>
auto split (T input, Delim_T delim) -> std::vector< T >

Splits a string into a vector of sub-strings. More...

Description​

Utility functions for handling strings in tests.

The utility namespace has three functions for the strings that the tests often check:

  • utility::is_match (input, pattern) checks whether a string matches a pattern, in which * matches any sequence of characters, including an empty one, and ? matches any single character;
  • utility::split (input, delimiters) splits a string into a vector of the non-empty sub-strings separated by any of the delimiter characters; for a std::string it returns std::string copies, and for a std::string_view, a string literal, or a const char* it returns views into the input, which must outlive them;
  • utility::extract_file_name (path) returns the file name part of a path, after the last / or backslash.
Example
 
 ts.test ("Check the strings", [] (auto& t) {
  t.expect (mt::utility::is_match ("main.cpp", "*.cpp"));
  t.expect (mt::eq (mt::utility::split ("a, b,,c", ", ").size (), 3u));
  t.expect (mt::eq (mt::utility::extract_file_name ("src/main.cpp"),
  "main.cpp"));
 });

Functions​

extract_file_name()​

const char * micro_os_plus::micro_test_plus::utility::extract_file_name (const char * path)
nodiscard noexcept

Extracts the file name component from a full path.

Parameters
path

A null-terminated file path string, or nullptr.

Returns

A pointer to the first character of the file name within path, or path itself if no path separator (/ or the backslash) is found; an empty string if path is nullptr.

The extract_file_name function extracts the file name from a given file path, handling both Unix-style (/) and Windows-style (the backslash) path separators. It returns a pointer to the start of the file name within the input string, or the original string if no separators are found.

The reports use it to display concise file names without full paths.

A nullptr path, which a default-constructed source location may provide, is accepted and yields an empty string, instead of reaching the std::string_view constructor, which does not allow it.

Example
 
 const char* path = "/home/user/project/test.cpp";
 const char* filename = mt::utility::extract_file_name (path);
 // filename now points to "test.cpp"

Definition at line 95 of file utility.cpp.

95 extract_file_name (const char* path) noexcept
96 {
97 if (path == nullptr)
98 {
99 return ""; // No path, return an empty string.
100 }
101
102 const std::string_view sv{ path };
103 const auto pos = sv.find_last_of ("/\\");
104 if (pos == std::string_view::npos)
105 {
106 return path; // No separators found, return original string.
107 }
108 return sv.substr (pos + 1).data ();
109 }

Reference micro_os_plus::micro_test_plus::utility::extract_file_name.

Referenced by micro_os_plus::micro_test_plus::runner::abort, micro_os_plus::micro_test_plus::detail::reporter_human::abort_session, micro_os_plus::micro_test_plus::detail::reporter_tap::abort_session, micro_os_plus::micro_test_plus::runner::add_top_suite, micro_os_plus::micro_test_plus::utility::extract_file_name, micro_os_plus::micro_test_plus::runner::initialise, micro_os_plus::micro_test_plus::detail::reporter_human::output_fail_prefix, micro_os_plus::micro_test_plus::detail::reporter_tap::output_fail_suffix, micro_os_plus::micro_test_plus::reflection::short_name and micro_os_plus::micro_test_plus::detail::reporter::write_info.

is_match()​

bool micro_os_plus::micro_test_plus::utility::is_match (std::string_view input, std::string_view pattern)
nodiscard

Checks whether a string matches a pattern with * and ? wildcards.

Parameters
input

The string view to be checked.

pattern

The string view containing the pattern to match.

Returns

true if the input string matches the pattern; otherwise, false.

This function enables pattern-based string comparison for tests, supporting both exact matches and wildcard patterns. The pattern may include * to match any sequence of characters (including an empty one) and ? to match any single character. This allows for flexible validation of string content in test checks, accommodating variable or partially known values.

The match is iterative, with no recursion, so the stack usage is constant, which matters on embedded targets. When a mismatch occurs after a *, only the most recent * is retried, one character further in the input; the earlier ones never need to be, since any match they could produce is also found by the most recent one. The worst-case complexity is O(n * m), for an input of length n and a pattern of length m.

The function is also used by the runner to select the suites and the test cases matching the --filter patterns, for each of the alternatives separated by |.

Examples

Both checks pass:

 
 t.expect (mt::utility::is_match ("abc", "a?c")) << "abc matches a?c";
 t.expect (mt::utility::is_match ("abc", "a*c")) << "abc matches a*c";

Definition at line 147 of file utility.cpp.

147 is_match (std::string_view input, std::string_view pattern)
148 {
149 constexpr auto npos = std::string_view::npos;
150
151 std::size_t i = 0; // Index in the input.
152 std::size_t p = 0; // Index in the pattern.
153
154 // The position of the most recent `*` in the pattern, and the input
155 // index where its match ends.
156 std::size_t star_p = npos;
157 std::size_t star_i = 0;
158
159 while (i < input.size ())
160 {
161 if (p < pattern.size ()
162 && (pattern[p] == '?' || pattern[p] == input[i]))
163 {
164 ++i;
165 ++p;
166 }
167 else if (p < pattern.size () && pattern[p] == '*')
168 {
169 // Start by matching an empty sequence.
170 star_p = p++;
171 star_i = i;
172 }
173 else if (star_p != npos)
174 {
175 // Extend the match of the most recent `*` by one character.
176 p = star_p + 1;
177 i = ++star_i;
178 }
179 else
180 {
181 return false;
182 }
183 }
184
185 // The input is exhausted; the rest of the pattern must be only `*`.
186 while (p < pattern.size () && pattern[p] == '*')
187 {
188 ++p;
189 }
190
191 return p == pattern.size ();
192 }

Reference micro_os_plus::micro_test_plus::utility::is_match.

Referenced by micro_os_plus::micro_test_plus::utility::is_match and micro_os_plus::micro_test_plus::runner::is_selected.

split()​

std::vector< std::string_view > micro_os_plus::micro_test_plus::utility::split (std::string_view input, std::string_view delimiters)
nodiscard

Splits a string view into a vector of string views.

This overload accepts string literals and const char* arguments, which the template cannot handle, and also any other type convertible to std::string_view. The returned views refer to the characters of the input, which must outlive them.

Parameters
input

Input string to split.

delimiters

Delimiter characters; any of them separates sub-strings.

Returns

A vector containing the resulting sub-strings; empty sub-strings (e.g. between consecutive delimiters) are omitted.

The function iterates through the input, identifying the positions of any of the delimiter characters (via find_first_of()) and extracting the views between them. Empty views, such as those between consecutive delimiters, are omitted. It is the overload selected for string literals and const char* arguments, which the template cannot handle.

Example

The check passes:

 
 t.expect (std::vector<std::string_view>{ "a", "b" }
  == mt::utility::split ("a.b", "."))
  << "a.b splits into [a,b]";

Definition at line 215 of file utility.cpp.

215 split (std::string_view input, std::string_view delimiters)
216 {
217 std::vector<std::string_view> output{};
218 std::size_t first{};
219 while (first < input.size ())
220 {
221 const auto second = input.find_first_of (delimiters, first);
222 if (first != second)
223 {
224 output.emplace_back (input.substr (first, second - first));
225 }
226 if (second == std::string_view::npos)
227 {
228 break;
229 }
230 first = second + 1;
231 }
232 return output;
233 }

Reference micro_os_plus::micro_test_plus::utility::split.

split()​

template <class T, class Delim_T>
std::vector< T > micro_os_plus::micro_test_plus::utility::split (T input, Delim_T delim)
nodiscard

Splits a string into a vector of sub-strings.

This function template splits a string into a vector of sub-strings, using the specified delimiter characters.

The function iterates through the input string, identifying the positions of any of the delimiter characters (via find_first_of()) and extracting the sub-strings between them. Each non-empty sub-string is added to the output vector; empty sub-strings, such as those between consecutive delimiters, are omitted. This approach supports flexible parsing of delimited data, which is useful for validating string processing logic in test cases.

Example
 
 t.expect (std::vector<std::string_view>{ "a", "b" }
  == mt::utility::split<std::string_view> ("a.b", "."))
  << "a.b splits into [a,b]";

This template preserves the type of the argument: for a std::string_view it returns views into the input, for a std::string it returns copies. It takes part in overload resolution only for the string-like types, i.e. those having npos, find_first_of(), and substr(); for string literals and const char* arguments the non-template overload is selected.

Template Parameters
T

Type of the input string.

Delim_T

Type of the delimiter.

Parameters
input

Input string to split.

delim

Delimiter characters; any of them separates sub-strings.

Returns

A vector containing the resulting sub-strings; empty sub-strings (e.g. between consecutive delimiters) are omitted.

Definition at line 91 of file utility-inlines.h.

91 split (T input, Delim_T delim) -> std::vector<T>
92 {
93 std::vector<T> output{};
94 std::size_t first{};
95 while (first < std::size (input))
96 {
97 const auto second = input.find_first_of (delim, first);
98 if (first != second)
99 {
100 output.emplace_back (input.substr (first, second - first));
101 }
102 if (second == T::npos)
103 {
104 break;
105 }
106 first = second + 1;
107 }
108 return output;
109 }

Reference micro_os_plus::micro_test_plus::utility::split.

Referenced by micro_os_plus::micro_test_plus::utility::split and micro_os_plus::micro_test_plus::utility::split.


Generated via doxygen2docusaurus 2.2.8 by Doxygen 1.18.0.