Move containers utils to containers.hh and add filtered/transformed utils
This commit is contained in:
parent
bf980eba04
commit
064fb81b8d
|
@ -3,6 +3,7 @@
|
||||||
#include "assert.hh"
|
#include "assert.hh"
|
||||||
#include "buffer_manager.hh"
|
#include "buffer_manager.hh"
|
||||||
#include "client.hh"
|
#include "client.hh"
|
||||||
|
#include "containers.hh"
|
||||||
#include "context.hh"
|
#include "context.hh"
|
||||||
#include "file.hh"
|
#include "file.hh"
|
||||||
#include "interned_string.hh"
|
#include "interned_string.hh"
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "client_manager.hh"
|
#include "client_manager.hh"
|
||||||
#include "command_manager.hh"
|
#include "command_manager.hh"
|
||||||
#include "completion.hh"
|
#include "completion.hh"
|
||||||
|
#include "containers.hh"
|
||||||
#include "context.hh"
|
#include "context.hh"
|
||||||
#include "debug.hh"
|
#include "debug.hh"
|
||||||
#include "event_manager.hh"
|
#include "event_manager.hh"
|
||||||
|
|
172
src/containers.hh
Normal file
172
src/containers.hh
Normal file
|
@ -0,0 +1,172 @@
|
||||||
|
#ifndef containers_hh_INCLUDED
|
||||||
|
#define containers_hh_INCLUDED
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <utility>
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
|
namespace Kakoune
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename Container>
|
||||||
|
struct ReversedContainer
|
||||||
|
{
|
||||||
|
using iterator = decltype(std::declval<Container>().rbegin());
|
||||||
|
ReversedContainer(Container& container) : m_container(container) {}
|
||||||
|
|
||||||
|
iterator begin() { return m_container.rbegin(); }
|
||||||
|
iterator end() { return m_container.rend(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Container& m_container;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Container>
|
||||||
|
ReversedContainer<Container> reversed(Container&& container)
|
||||||
|
{
|
||||||
|
return ReversedContainer<Container>(container);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Iterator, typename Filter>
|
||||||
|
struct FilteredIterator : std::iterator<std::forward_iterator_tag,
|
||||||
|
typename Iterator::value_type>
|
||||||
|
{
|
||||||
|
FilteredIterator(Filter filter, Iterator it, Iterator end)
|
||||||
|
: m_it(std::move(it)), m_end(std::move(end)), m_filter(std::move(filter))
|
||||||
|
{
|
||||||
|
do_filter();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto operator*() -> decltype(*std::declval<Iterator>()) { return *m_it; }
|
||||||
|
FilteredIterator& operator++() { ++m_it; do_filter(); return *this; }
|
||||||
|
FilteredIterator operator++(int) { auto copy = *this; ++(*this); return copy; }
|
||||||
|
|
||||||
|
friend bool operator==(const FilteredIterator& lhs, const FilteredIterator& rhs)
|
||||||
|
{
|
||||||
|
return lhs.m_it == rhs.m_it;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool operator!=(const FilteredIterator& lhs, const FilteredIterator& rhs)
|
||||||
|
{
|
||||||
|
return not (lhs == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void do_filter()
|
||||||
|
{
|
||||||
|
while (m_it != m_end and not m_filter(*m_it))
|
||||||
|
++m_it;
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator m_it;
|
||||||
|
Iterator m_end;
|
||||||
|
Filter m_filter;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Container, typename Filter>
|
||||||
|
struct FilteredContainer
|
||||||
|
{
|
||||||
|
using iterator = FilteredIterator<decltype(begin(std::declval<Container>())), Filter>;
|
||||||
|
FilteredContainer(Container& container, Filter filter)
|
||||||
|
: m_container(container), m_filter(std::move(filter)) {}
|
||||||
|
|
||||||
|
iterator begin() const { return iterator(m_filter, m_container.begin(), m_container.end()); }
|
||||||
|
iterator end() const { return iterator(m_filter, m_container.end(), m_container.end()); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Container& m_container;
|
||||||
|
Filter m_filter;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Container, typename Filter>
|
||||||
|
FilteredContainer<Container, Filter> filtered(Container&& container, Filter filter)
|
||||||
|
{
|
||||||
|
return FilteredContainer<Container, Filter>(container, std::move(filter));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Iterator, typename Transform>
|
||||||
|
struct TransformedIterator : std::iterator<std::forward_iterator_tag,
|
||||||
|
typename std::remove_reference<decltype(std::declval<Transform>()(*std::declval<Iterator>()))>::type>
|
||||||
|
{
|
||||||
|
TransformedIterator(Transform transform, Iterator it)
|
||||||
|
: m_it(std::move(it)), m_transform(std::move(transform)) {}
|
||||||
|
|
||||||
|
auto operator*() -> decltype(std::declval<Transform>()(*std::declval<Iterator>())) { return m_transform(*m_it); }
|
||||||
|
TransformedIterator& operator++() { ++m_it; return *this; }
|
||||||
|
TransformedIterator operator++(int) { auto copy = *this; ++m_it; return copy; }
|
||||||
|
|
||||||
|
friend bool operator==(const TransformedIterator& lhs, const TransformedIterator& rhs)
|
||||||
|
{
|
||||||
|
return lhs.m_it == rhs.m_it;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool operator!=(const TransformedIterator& lhs, const TransformedIterator& rhs)
|
||||||
|
{
|
||||||
|
return not (lhs == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Iterator m_it;
|
||||||
|
Transform m_transform;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<typename Container, typename Transform>
|
||||||
|
struct TransformedContainer
|
||||||
|
{
|
||||||
|
using iterator = TransformedIterator<decltype(begin(std::declval<Container>())), Transform>;
|
||||||
|
TransformedContainer(Container& container, Transform transform)
|
||||||
|
: m_container(container), m_transform(std::move(transform)) {}
|
||||||
|
|
||||||
|
iterator begin() const { return iterator(m_transform, m_container.begin()); }
|
||||||
|
iterator end() const { return iterator(m_transform, m_container.end()); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Container& m_container;
|
||||||
|
Transform m_transform;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Container, typename Transform>
|
||||||
|
TransformedContainer<Container, Transform> transformed(Container&& container, Transform transform)
|
||||||
|
{
|
||||||
|
return TransformedContainer<Container, Transform>(container, std::move(transform));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Todo: move that into the following functions once we can remove the decltype
|
||||||
|
// return type.
|
||||||
|
using std::begin;
|
||||||
|
using std::end;
|
||||||
|
|
||||||
|
template<typename Container, typename T>
|
||||||
|
auto find(Container&& container, const T& value) -> decltype(begin(container))
|
||||||
|
{
|
||||||
|
return std::find(begin(container), end(container), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Container, typename T>
|
||||||
|
auto find_if(Container&& container, T op) -> decltype(begin(container))
|
||||||
|
{
|
||||||
|
return std::find_if(begin(container), end(container), op);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Container, typename T>
|
||||||
|
bool contains(Container&& container, const T& value)
|
||||||
|
{
|
||||||
|
return find(container, value) != end(container);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Container, typename U>
|
||||||
|
void unordered_erase(Container&& vec, U&& value)
|
||||||
|
{
|
||||||
|
auto it = find(vec, std::forward<U>(value));
|
||||||
|
if (it != vec.end())
|
||||||
|
{
|
||||||
|
using std::swap;
|
||||||
|
swap(vec.back(), *it);
|
||||||
|
vec.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // containers_hh_INCLUDED
|
|
@ -1,5 +1,7 @@
|
||||||
#include "event_manager.hh"
|
#include "event_manager.hh"
|
||||||
|
|
||||||
|
#include "containers.hh"
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "face_registry.hh"
|
#include "face_registry.hh"
|
||||||
|
|
||||||
|
#include "containers.hh"
|
||||||
#include "exception.hh"
|
#include "exception.hh"
|
||||||
|
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
|
@ -7,8 +8,8 @@ namespace Kakoune
|
||||||
|
|
||||||
static Face parse_face(StringView facedesc)
|
static Face parse_face(StringView facedesc)
|
||||||
{
|
{
|
||||||
auto bg_it = std::find(facedesc.begin(), facedesc.end(), ',');
|
auto bg_it = find(facedesc, ',');
|
||||||
auto attr_it = std::find(facedesc.begin(), facedesc.end(), '+');
|
auto attr_it = find(facedesc, '+');
|
||||||
if (bg_it != facedesc.end() and attr_it < bg_it)
|
if (bg_it != facedesc.end() and attr_it < bg_it)
|
||||||
throw runtime_error("invalid face description, expected <fg>[,<bg>][+<attr>]");
|
throw runtime_error("invalid face description, expected <fg>[,<bg>][+<attr>]");
|
||||||
Face res;
|
Face res;
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#include "highlighter_group.hh"
|
#include "highlighter_group.hh"
|
||||||
|
|
||||||
|
#include "containers.hh"
|
||||||
|
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
#ifndef id_map_hh_INCLUDED
|
#ifndef id_map_hh_INCLUDED
|
||||||
#define id_map_hh_INCLUDED
|
#define id_map_hh_INCLUDED
|
||||||
|
|
||||||
|
#include "containers.hh"
|
||||||
#include "completion.hh"
|
#include "completion.hh"
|
||||||
#include "string.hh"
|
#include "string.hh"
|
||||||
#include "utils.hh"
|
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
#include "keys.hh"
|
#include "keys.hh"
|
||||||
|
|
||||||
|
#include "containers.hh"
|
||||||
|
#include "exception.hh"
|
||||||
|
#include "string.hh"
|
||||||
#include "utils.hh"
|
#include "utils.hh"
|
||||||
#include "utf8_iterator.hh"
|
#include "utf8_iterator.hh"
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#include "units.hh"
|
#include "units.hh"
|
||||||
#include "utils.hh"
|
#include "utils.hh"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "client_manager.hh"
|
#include "client_manager.hh"
|
||||||
#include "command_manager.hh"
|
#include "command_manager.hh"
|
||||||
#include "commands.hh"
|
#include "commands.hh"
|
||||||
|
#include "containers.hh"
|
||||||
#include "context.hh"
|
#include "context.hh"
|
||||||
#include "debug.hh"
|
#include "debug.hh"
|
||||||
#include "event_manager.hh"
|
#include "event_manager.hh"
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "utf8_iterator.hh"
|
#include "utf8_iterator.hh"
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#define NCURSES_OPAQUE 0
|
#define NCURSES_OPAQUE 0
|
||||||
#define NCURSES_INTERNALS
|
#define NCURSES_INTERNALS
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "client_manager.hh"
|
#include "client_manager.hh"
|
||||||
#include "command_manager.hh"
|
#include "command_manager.hh"
|
||||||
#include "commands.hh"
|
#include "commands.hh"
|
||||||
|
#include "containers.hh"
|
||||||
#include "context.hh"
|
#include "context.hh"
|
||||||
#include "debug.hh"
|
#include "debug.hh"
|
||||||
#include "face_registry.hh"
|
#include "face_registry.hh"
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define option_manager_hh_INCLUDED
|
#define option_manager_hh_INCLUDED
|
||||||
|
|
||||||
#include "completion.hh"
|
#include "completion.hh"
|
||||||
|
#include "containers.hh"
|
||||||
#include "exception.hh"
|
#include "exception.hh"
|
||||||
#include "flags.hh"
|
#include "flags.hh"
|
||||||
#include "option_types.hh"
|
#include "option_types.hh"
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include "assert.hh"
|
#include "assert.hh"
|
||||||
#include "id_map.hh"
|
#include "id_map.hh"
|
||||||
#include "utils.hh"
|
#include "exception.hh"
|
||||||
|
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#include "string.hh"
|
#include "string.hh"
|
||||||
|
|
||||||
#include "exception.hh"
|
#include "exception.hh"
|
||||||
#include "utils.hh"
|
#include "containers.hh"
|
||||||
#include "utf8_iterator.hh"
|
#include "utf8_iterator.hh"
|
||||||
|
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
|
|
67
src/utils.hh
67
src/utils.hh
|
@ -2,11 +2,8 @@
|
||||||
#define utils_hh_INCLUDED
|
#define utils_hh_INCLUDED
|
||||||
|
|
||||||
#include "assert.hh"
|
#include "assert.hh"
|
||||||
#include "exception.hh"
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
@ -59,70 +56,6 @@ private:
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T* Singleton<T>::ms_instance = nullptr;
|
T* Singleton<T>::ms_instance = nullptr;
|
||||||
|
|
||||||
// *** Containers helpers ***
|
|
||||||
|
|
||||||
template<typename Container>
|
|
||||||
struct ReversedContainer
|
|
||||||
{
|
|
||||||
ReversedContainer(Container& container) : container(container) {}
|
|
||||||
Container& container;
|
|
||||||
|
|
||||||
decltype(container.rbegin()) begin() { return container.rbegin(); }
|
|
||||||
decltype(container.rend()) end() { return container.rend(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Container>
|
|
||||||
auto begin(ReversedContainer<Container>& c) -> decltype(c.begin())
|
|
||||||
{
|
|
||||||
return c.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Container>
|
|
||||||
auto end(ReversedContainer<Container>& c) -> decltype(c.end())
|
|
||||||
{
|
|
||||||
return c.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Container>
|
|
||||||
ReversedContainer<Container> reversed(Container&& container)
|
|
||||||
{
|
|
||||||
return ReversedContainer<Container>(container);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Todo: move that into the following functions once we can remove the decltype
|
|
||||||
// return type.
|
|
||||||
using std::begin;
|
|
||||||
using std::end;
|
|
||||||
|
|
||||||
template<typename Container, typename T>
|
|
||||||
auto find(Container&& container, const T& value) -> decltype(begin(container))
|
|
||||||
{
|
|
||||||
return std::find(begin(container), end(container), value);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Container, typename T>
|
|
||||||
auto find_if(Container&& container, T op) -> decltype(begin(container))
|
|
||||||
{
|
|
||||||
return std::find_if(begin(container), end(container), op);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Container, typename T>
|
|
||||||
bool contains(Container&& container, const T& value)
|
|
||||||
{
|
|
||||||
return find(container, value) != end(container);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, typename U>
|
|
||||||
void unordered_erase(std::vector<T>& vec, U&& value)
|
|
||||||
{
|
|
||||||
auto it = find(vec, std::forward<U>(value));
|
|
||||||
if (it != vec.end())
|
|
||||||
{
|
|
||||||
std::swap(vec.back(), *it);
|
|
||||||
vec.pop_back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Iterator, typename EndIterator, typename T>
|
template<typename Iterator, typename EndIterator, typename T>
|
||||||
void skip_while(Iterator& it, const EndIterator& end, T condition)
|
void skip_while(Iterator& it, const EndIterator& end, T condition)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue
Block a user