string: allow tokenisation of c arrays
This commit is contained in:
parent
9c5b471b24
commit
cfa272a80a
42
string.hpp
42
string.hpp
@ -40,7 +40,20 @@ namespace util {
|
||||
|
||||
tokeniser (Iterator first, Iterator last, value_type separator);
|
||||
|
||||
struct iterator {
|
||||
template <typename ContainerT>
|
||||
tokeniser (ContainerT &container, typename ContainerT::value_type _separator):
|
||||
tokeniser (
|
||||
std::begin (container),
|
||||
std::end (container),
|
||||
_separator
|
||||
)
|
||||
{ ; }
|
||||
|
||||
struct iterator : public std::iterator<
|
||||
std::forward_iterator_tag,
|
||||
range_type,
|
||||
std::size_t
|
||||
> {
|
||||
public:
|
||||
iterator operator++ (int);
|
||||
iterator& operator++ (void)&;
|
||||
@ -71,10 +84,29 @@ namespace util {
|
||||
const value_type m_separator;
|
||||
};
|
||||
|
||||
|
||||
tokeniser<std::string::const_iterator> make_tokeniser (const std::string&, std::string::value_type);
|
||||
tokeniser<std::string::const_iterator> make_tokeniser (std::string&&, std::string::value_type) = delete;
|
||||
tokeniser<const char*> make_tokeniser (const char*, char);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename CharT, std::size_t LengthV>
|
||||
auto
|
||||
make_tokeniser (CharT (&data)[LengthV], CharT separator)
|
||||
{
|
||||
return tokeniser { std::begin (data), std::end (data), separator };
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
tokeniser<std::string::const_iterator>
|
||||
make_tokeniser (const std::string&, std::string::value_type);
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
tokeniser<std::string::const_iterator>
|
||||
make_tokeniser (std::string&&, std::string::value_type) = delete;
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
tokeniser<const char*>
|
||||
make_tokeniser (const char*, char);
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,9 @@
|
||||
#include "tap.hpp"
|
||||
#include "string.hpp"
|
||||
#include "types.hpp"
|
||||
#include "iterator.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
int
|
||||
main (int, char**)
|
||||
@ -8,28 +11,23 @@ main (int, char**)
|
||||
util::TAP::logger tap;
|
||||
|
||||
const char csv[] = "\0,a,123,,this is a test,";
|
||||
const std::string values[] = {
|
||||
{ "\0", 1 },
|
||||
{ "a" },
|
||||
{ "123" },
|
||||
{ "" },
|
||||
{ "this is a test" },
|
||||
{ "" }
|
||||
|
||||
// expected test data must be a std::string so we can check embedded
|
||||
// nulls (which are ambiguous when using a cstr).
|
||||
struct foo {
|
||||
const std::string value;
|
||||
const char *message;
|
||||
} TESTS[] = {
|
||||
{ "\0", "null" },
|
||||
{ "a", "single letter" },
|
||||
{ "123", "three digits" },
|
||||
{ "", "empty string" },
|
||||
{ "this is a test", "string with spaces" },
|
||||
{ "", "trailing empty" }
|
||||
};
|
||||
|
||||
std::string str (std::cbegin (csv), std::cbegin (csv) + std::size (csv));
|
||||
auto tok = util::make_tokeniser (str, ',');
|
||||
auto t_cursor = tok.cbegin ();
|
||||
auto v_cursor = std::cbegin (values);
|
||||
|
||||
tap.expect_eq (*t_cursor++, *v_cursor++, "tokeniser, single letter");
|
||||
tap.expect_eq (*t_cursor++, *v_cursor++, "tokeniser, three digits");
|
||||
tap.expect_eq (*t_cursor++, *v_cursor++, "tokeniser, embedded null");
|
||||
tap.expect_eq (*t_cursor++, *v_cursor++, "tokeniser, empty string");
|
||||
tap.expect_eq (*t_cursor++, *v_cursor++, "tokeniser, string with spaces");
|
||||
tap.expect_eq (*t_cursor++, *v_cursor++, "tokeniser, trailing empty");
|
||||
|
||||
tap.expect_eq (t_cursor, tok.cend (), "tokeniser iterator at end");
|
||||
for (const auto &[tok, expected]: util::zip (util::make_tokeniser (csv, ','), TESTS))
|
||||
tap.expect (equal (tok, expected.value), "%s", expected.message);
|
||||
|
||||
return tap.status ();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user