string: move tokeniser into the header
This allows more varied template parameters to be used.
This commit is contained in:
parent
32a4aa23e5
commit
c4e0cd31f9
143
string.cpp
143
string.cpp
@ -51,146 +51,3 @@ strbegins (const char *restrict str,
|
|||||||
const char *restrict prefix) {
|
const char *restrict prefix) {
|
||||||
return 0 == strncmp (prefix, str, strlen (prefix));
|
return 0 == strncmp (prefix, str, strlen (prefix));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <typename Iterator>
|
|
||||||
tokeniser<Iterator>::tokeniser (Iterator _first,
|
|
||||||
Iterator _last,
|
|
||||||
value_type _separator):
|
|
||||||
m_range (_first, _last),
|
|
||||||
m_separator (_separator)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <typename Iterator>
|
|
||||||
typename tokeniser<Iterator>::iterator
|
|
||||||
tokeniser<Iterator>::cbegin (void) const
|
|
||||||
{
|
|
||||||
return iterator (
|
|
||||||
m_range,
|
|
||||||
m_separator
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <typename Iterator>
|
|
||||||
typename tokeniser<Iterator>::iterator
|
|
||||||
tokeniser<Iterator>::cend (void) const
|
|
||||||
{
|
|
||||||
return iterator (
|
|
||||||
{m_range.cend (), m_range.cend ()},
|
|
||||||
m_separator
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <typename Iterator>
|
|
||||||
typename tokeniser<Iterator>::iterator
|
|
||||||
tokeniser<Iterator>::begin (void) const
|
|
||||||
{
|
|
||||||
return cbegin ();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <typename Iterator>
|
|
||||||
typename tokeniser<Iterator>::iterator
|
|
||||||
tokeniser<Iterator>::end (void) const
|
|
||||||
{
|
|
||||||
return cend ();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <typename Iterator>
|
|
||||||
tokeniser<Iterator>::iterator::iterator (range_type _range, value_type _separator):
|
|
||||||
m_separator (_separator),
|
|
||||||
m_range (_range.cbegin (),
|
|
||||||
std::find (_range.cbegin (),
|
|
||||||
_range.cend (),
|
|
||||||
_separator)),
|
|
||||||
m_end (_range.cend ())
|
|
||||||
{ }
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <typename Iterator>
|
|
||||||
typename tokeniser<Iterator>::iterator
|
|
||||||
tokeniser<Iterator>::iterator::operator++ (int)
|
|
||||||
{
|
|
||||||
iterator res(*this);
|
|
||||||
++*this;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <typename Iterator>
|
|
||||||
typename tokeniser<Iterator>::iterator&
|
|
||||||
tokeniser<Iterator>::iterator::operator++ (void)&
|
|
||||||
{
|
|
||||||
auto newend = m_range.cend ();
|
|
||||||
if (newend != m_end) {
|
|
||||||
CHECK_EQ (*m_range.cend (), m_separator);
|
|
||||||
newend++;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_range = {
|
|
||||||
newend,
|
|
||||||
std::find (newend, m_end, m_separator)
|
|
||||||
};
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <typename Iterator>
|
|
||||||
typename tokeniser<Iterator>::range_type
|
|
||||||
tokeniser<Iterator>::iterator::operator* (void) const
|
|
||||||
{
|
|
||||||
return m_range;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <typename Iterator>
|
|
||||||
bool
|
|
||||||
tokeniser<Iterator>::iterator::operator== (const iterator &rhs) const
|
|
||||||
{
|
|
||||||
return m_range == rhs.m_range && m_separator == rhs.m_separator;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <typename Iterator>
|
|
||||||
bool
|
|
||||||
tokeniser<Iterator>::iterator::operator!= (const iterator &rhs) const
|
|
||||||
{
|
|
||||||
return !(*this == rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
tokeniser<std::string::const_iterator>
|
|
||||||
util::make_tokeniser (const std::string &value, std::string::value_type separator)
|
|
||||||
{
|
|
||||||
return tokeniser<std::string::const_iterator> (value.cbegin (), value.cend (), separator);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
tokeniser<const char*>
|
|
||||||
util::make_tokeniser (const char *str, char separator)
|
|
||||||
{
|
|
||||||
return tokeniser<const char*> (str, str + strlen (str), separator);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template struct util::tokeniser<std::string::const_iterator>;
|
|
||||||
template struct util::tokeniser<const char*>;
|
|
||||||
|
99
string.hpp
99
string.hpp
@ -14,9 +14,10 @@
|
|||||||
* Copyright 2011-2016 Danny Robson <danny@nerdcruft.net>
|
* Copyright 2011-2016 Danny Robson <danny@nerdcruft.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __UTIL_STRING_HPP
|
#ifndef CRUFT_UTIL_STRING_HPP
|
||||||
#define __UTIL_STRING_HPP
|
#define CRUFT_UTIL_STRING_HPP
|
||||||
|
|
||||||
|
#include "debug.hpp"
|
||||||
#include "view.hpp"
|
#include "view.hpp"
|
||||||
|
|
||||||
|
|
||||||
@ -38,15 +39,14 @@ namespace util {
|
|||||||
using value_type = typename std::iterator_traits<Iterator>::value_type;
|
using value_type = typename std::iterator_traits<Iterator>::value_type;
|
||||||
using range_type = view<Iterator>;
|
using range_type = view<Iterator>;
|
||||||
|
|
||||||
tokeniser (Iterator first, Iterator last, value_type separator);
|
tokeniser (util::view<Iterator,Iterator> _range, value_type _separator):
|
||||||
|
m_range (_range),
|
||||||
|
m_separator (_separator)
|
||||||
|
{ ; }
|
||||||
|
|
||||||
template <typename ContainerT>
|
tokeniser (const char *_range, char _separator):
|
||||||
tokeniser (ContainerT &container, typename ContainerT::value_type _separator):
|
m_range (_range),
|
||||||
tokeniser (
|
m_separator (_separator)
|
||||||
std::begin (container),
|
|
||||||
std::end (container),
|
|
||||||
_separator
|
|
||||||
)
|
|
||||||
{ ; }
|
{ ; }
|
||||||
|
|
||||||
struct iterator : public std::iterator<
|
struct iterator : public std::iterator<
|
||||||
@ -55,16 +55,54 @@ namespace util {
|
|||||||
std::size_t
|
std::size_t
|
||||||
> {
|
> {
|
||||||
public:
|
public:
|
||||||
iterator operator++ (int);
|
iterator operator++ (int)
|
||||||
iterator& operator++ (void)&;
|
{
|
||||||
|
iterator res(*this);
|
||||||
|
++*this;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
range_type operator* (void) const;
|
iterator& operator++ (void)&
|
||||||
|
{
|
||||||
|
auto newend = m_range.cend ();
|
||||||
|
if (newend != m_end) {
|
||||||
|
CHECK_EQ (*m_range.cend (), m_separator);
|
||||||
|
newend++;
|
||||||
|
}
|
||||||
|
|
||||||
bool operator== (const iterator&) const;
|
m_range = {
|
||||||
bool operator!= (const iterator&) const;
|
newend,
|
||||||
|
std::find (newend, m_end, m_separator)
|
||||||
|
};
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
range_type operator* (void) const
|
||||||
|
{
|
||||||
|
return m_range;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator== (const iterator &rhs) const
|
||||||
|
{
|
||||||
|
return m_range == rhs.m_range && m_separator == rhs.m_separator;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!= (const iterator &rhs) const
|
||||||
|
{
|
||||||
|
return !(*this == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
iterator (range_type range, value_type separator);
|
iterator (range_type _range, value_type _separator):
|
||||||
|
m_separator (_separator),
|
||||||
|
m_range (_range.cbegin (),
|
||||||
|
std::find (_range.cbegin (),
|
||||||
|
_range.cend (),
|
||||||
|
_separator)
|
||||||
|
),
|
||||||
|
m_end (_range.cend ())
|
||||||
|
{ ; }
|
||||||
|
|
||||||
const value_type m_separator;
|
const value_type m_separator;
|
||||||
range_type m_range;
|
range_type m_range;
|
||||||
@ -73,11 +111,11 @@ namespace util {
|
|||||||
friend tokeniser;
|
friend tokeniser;
|
||||||
};
|
};
|
||||||
|
|
||||||
iterator cbegin (void) const;
|
iterator cbegin (void) const { return { m_range, m_separator }; }
|
||||||
iterator begin (void) const;
|
iterator begin (void) const { return { m_range, m_separator }; }
|
||||||
|
|
||||||
iterator cend (void) const;
|
iterator cend (void) const { return { { m_range.cend (), m_range.cend () }, m_separator }; }
|
||||||
iterator end (void) const;
|
iterator end (void) const { return { { m_range.cend (), m_range.cend () }, m_separator }; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const range_type m_range;
|
const range_type m_range;
|
||||||
@ -85,6 +123,11 @@ namespace util {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename ContainerT>
|
||||||
|
tokeniser (ContainerT&, typename ContainerT::value_type) -> tokeniser<typename ContainerT::iterator>;
|
||||||
|
|
||||||
|
tokeniser (const char*,char) -> tokeniser<const char*>;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
template <typename CharT, std::size_t LengthV>
|
template <typename CharT, std::size_t LengthV>
|
||||||
auto
|
auto
|
||||||
@ -92,22 +135,6 @@ namespace util {
|
|||||||
{
|
{
|
||||||
return tokeniser { std::begin (data), std::end (data), 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);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // __UTIL_STRING_HPP
|
#endif // __UTIL_STRING_HPP
|
||||||
|
2
term.cpp
2
term.cpp
@ -71,7 +71,7 @@ find_terminfo_path [[gnu::unused]] (const std::string &key)
|
|||||||
|
|
||||||
// check colon seperated list in TERMINFO_DIRS
|
// check colon seperated list in TERMINFO_DIRS
|
||||||
if (const char *dirs = getenv ("TERMINFO_DIRS")) {
|
if (const char *dirs = getenv ("TERMINFO_DIRS")) {
|
||||||
auto tok = util::make_tokeniser (dirs, ':');
|
auto tok = util::tokeniser (dirs, ':');
|
||||||
|
|
||||||
for (auto i: tok) {
|
for (auto i: tok) {
|
||||||
try {
|
try {
|
||||||
|
@ -29,8 +29,11 @@ main (int, char**)
|
|||||||
{ "", "trailing empty" }
|
{ "", "trailing empty" }
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const auto &[tok, expected]: util::zip (util::make_tokeniser (csv, ','), TESTS))
|
for (const auto tok: util::tokeniser (csv.c_str (), ','))
|
||||||
|
std::cout << '"' << tok << "\"\n";
|
||||||
|
|
||||||
|
for (const auto &[tok, expected]: util::zip (util::tokeniser (csv.c_str (), ','), TESTS))
|
||||||
tap.expect_eq (tok, expected.value, "%s", expected.message);
|
tap.expect_eq (tok, expected.value, "%s", expected.message);
|
||||||
|
|
||||||
return tap.status ();
|
return tap.status ();
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user