Browse Source

More cleanup

master
Jessica James 3 years ago
parent
commit
bdebc6fba2
  1. 83
      src/include/split.hpp

83
src/include/split.hpp

@ -29,24 +29,23 @@
#include <vector> #include <vector>
namespace jessilib { namespace jessilib {
namespace impl {
template<template<typename...> typename ContainerT, typename FallbackArg, typename... ArgsT> template<template<typename...> typename ContainerT, typename ElementT, typename...>
struct split_container_helper { struct split_defaults {
using type = ContainerT<FallbackArg>; using member_type = std::basic_string<ElementT>;
using container_type = ContainerT<member_type>;
}; };
template<template<typename...> typename ContainerT, typename FallbackArg, typename FirstOptional, typename... ArgsT> template<template<typename...> typename ContainerT, typename ElementT, typename FirstOptional, typename... ContainerArgsT>
struct split_container_helper<ContainerT, FallbackArg, FirstOptional, ArgsT...> { struct split_defaults<ContainerT, ElementT, FirstOptional, ContainerArgsT...> {
using type = ContainerT<FirstOptional, ArgsT...>; using member_type = FirstOptional;
using container_type = ContainerT<FirstOptional, ContainerArgsT...>;
}; };
template<template<typename...> typename ContainerT, typename... ArgsT> // Can probably be specialized for types which don't take in iterators _or_
using split_container_helper_t = typename split_container_helper<ContainerT, ArgsT...>::type;
template<typename MemberT, typename ItrT, typename EndT, typename std::enable_if<!std::is_constructible<MemberT, ItrT, EndT>::value>::type* = nullptr> template<typename MemberT, typename ItrT, typename EndT, typename std::enable_if<!std::is_constructible<MemberT, ItrT, EndT>::value>::type* = nullptr>
MemberT member_from_range(ItrT in_itr, EndT in_end) { MemberT make_split_member(ItrT in_itr, EndT in_end) {
// Workaround due to C++20 iterator constructor being inconsistently available // Intended for string_view
if constexpr (std::is_pointer_v<MemberT>) { if constexpr (std::is_pointer_v<MemberT>) {
return { in_itr, static_cast<size_t>(in_end - in_itr) }; return { in_itr, static_cast<size_t>(in_end - in_itr) };
} }
@ -59,13 +58,11 @@ MemberT member_from_range(ItrT in_itr, EndT in_end) {
} }
template<typename MemberT, typename ItrT, typename EndT, typename std::enable_if<std::is_constructible<MemberT, ItrT, EndT>::value>::type* = nullptr> template<typename MemberT, typename ItrT, typename EndT, typename std::enable_if<std::is_constructible<MemberT, ItrT, EndT>::value>::type* = nullptr>
MemberT member_from_range(ItrT in_itr, EndT in_end) { MemberT make_split_member(ItrT in_itr, EndT in_end) {
// Workaround due to C++20 iterator constructor being inconsistently available // Can construct with iterators, so construct with iterators
return { in_itr, in_end }; return { in_itr, in_end };
} }
} // namespace impl
/** /**
* Splits an input string into substrings * Splits an input string into substrings
* *
@ -78,8 +75,9 @@ MemberT member_from_range(ItrT in_itr, EndT in_end) {
*/ */
template<template<typename...> typename ContainerT = std::vector, typename... ContainerArgsT, typename ItrT, typename EndT, typename ElementT> template<template<typename...> typename ContainerT = std::vector, typename... ContainerArgsT, typename ItrT, typename EndT, typename ElementT>
constexpr auto split(ItrT begin, EndT end, ElementT in_delim) { constexpr auto split(ItrT begin, EndT end, ElementT in_delim) {
using MemberT = std::tuple_element_t<0, std::tuple<ContainerArgsT..., std::basic_string<ElementT>>>; using split_defaults_type = split_defaults<ContainerT, ElementT, ContainerArgsT...>;
using container_type = impl::split_container_helper_t<ContainerT, MemberT, ContainerArgsT...>; using member_type = typename split_defaults_type::member_type;
using container_type = typename split_defaults_type::container_type;
container_type result; container_type result;
if (begin >= end) { if (begin >= end) {
@ -90,13 +88,13 @@ constexpr auto split(ItrT begin, EndT end, ElementT in_delim) {
for (auto itr = begin; itr != end; ++itr) { for (auto itr = begin; itr != end; ++itr) {
if (*itr == in_delim) { if (*itr == in_delim) {
// Push token to result // Push token to result
result.push_back(impl::member_from_range<MemberT>(begin, itr)); result.push_back(make_split_member<member_type>(begin, itr));
begin = itr + 1; begin = itr + 1;
} }
} }
// Push final token to the end; may be empty // Push final token to the end; may be empty
result.push_back(impl::member_from_range<MemberT>(begin, end)); result.push_back(make_split_member<member_type>(begin, end));
return result; return result;
} }
@ -115,8 +113,9 @@ constexpr auto split(ItrT begin, EndT end, ElementT in_delim) {
template<template<typename...> typename ContainerT = std::vector, typename... ContainerArgsT, typename ItrT, typename EndT, typename DelimItrT, typename DelimEndT> template<template<typename...> typename ContainerT = std::vector, typename... ContainerArgsT, typename ItrT, typename EndT, typename DelimItrT, typename DelimEndT>
constexpr auto split(ItrT begin, EndT end, DelimItrT in_delim_begin, DelimEndT in_delim_end) { constexpr auto split(ItrT begin, EndT end, DelimItrT in_delim_begin, DelimEndT in_delim_end) {
using ElementT = std::remove_cvref_t<decltype(*begin)>; using ElementT = std::remove_cvref_t<decltype(*begin)>;
using MemberT = std::tuple_element_t<0, std::tuple<ContainerArgsT..., std::basic_string<ElementT>>>; using split_defaults_type = split_defaults<ContainerT, ElementT, ContainerArgsT...>;
using container_type = impl::split_container_helper_t<ContainerT, MemberT, ContainerArgsT...>; using member_type = typename split_defaults_type::member_type;
using container_type = typename split_defaults_type::container_type;
auto delim_length = std::distance(in_delim_begin, in_delim_end); auto delim_length = std::distance(in_delim_begin, in_delim_end);
if (delim_length == 1) { if (delim_length == 1) {
@ -132,7 +131,7 @@ constexpr auto split(ItrT begin, EndT end, DelimItrT in_delim_begin, DelimEndT i
if (in_delim_begin >= in_delim_end if (in_delim_begin >= in_delim_end
|| (end - begin) < delim_length) { || (end - begin) < delim_length) {
// Absent or impossible to match delimiter, therefore no match, therefore return input as single token // Absent or impossible to match delimiter, therefore no match, therefore return input as single token
result.push_back(impl::member_from_range<MemberT>(begin, end)); result.push_back(make_split_member<member_type>(begin, end));
return result; return result;
} }
@ -140,7 +139,7 @@ constexpr auto split(ItrT begin, EndT end, DelimItrT in_delim_begin, DelimEndT i
for (auto itr = begin; itr < itr_end;) { for (auto itr = begin; itr < itr_end;) {
if (std::equal(in_delim_begin, in_delim_end, itr)) { if (std::equal(in_delim_begin, in_delim_end, itr)) {
// Push token to result // Push token to result
result.push_back(impl::member_from_range<MemberT>(begin, itr)); result.push_back(make_split_member<member_type>(begin, itr));
itr += delim_length; itr += delim_length;
begin = itr; begin = itr;
continue; continue;
@ -150,7 +149,7 @@ constexpr auto split(ItrT begin, EndT end, DelimItrT in_delim_begin, DelimEndT i
} }
// Push final token to the end; may be empty // Push final token to the end; may be empty
result.push_back(impl::member_from_range<MemberT>(begin, end)); result.push_back(make_split_member<member_type>(begin, end));
return result; return result;
} }
@ -201,14 +200,14 @@ constexpr auto split_once(ItrT begin, EndT end, ElementT in_delim) {
for (auto itr = begin; itr != end; ++itr) { for (auto itr = begin; itr != end; ++itr) {
if (*itr == in_delim) { if (*itr == in_delim) {
// in_delim found; split upon it // in_delim found; split upon it
result.first = impl::member_from_range<MemberT>(begin, itr); result.first = make_split_member<MemberT>(begin, itr);
result.second = impl::member_from_range<MemberT>(itr + 1, end); result.second = make_split_member<MemberT>(itr + 1, end);
return result; return result;
} }
} }
// in_delim not found // in_delim not found
result.first = impl::member_from_range<MemberT>(begin, end); result.first = make_split_member<MemberT>(begin, end);
return result; return result;
} }
@ -245,7 +244,7 @@ constexpr auto split_once(ItrT begin, EndT end, DelimItrT in_delim_begin, DelimE
if (in_delim_begin >= in_delim_end if (in_delim_begin >= in_delim_end
|| (end - begin) < delim_length) { || (end - begin) < delim_length) {
// Absent or impossible to match delimiter, therefore no match, therefore return input as single token // Absent or impossible to match delimiter, therefore no match, therefore return input as single token
result.first = impl::member_from_range<MemberT>(begin, end); result.first = make_split_member<MemberT>(begin, end);
return result; return result;
} }
@ -253,14 +252,14 @@ constexpr auto split_once(ItrT begin, EndT end, DelimItrT in_delim_begin, DelimE
for (auto itr = begin; itr < itr_end;) { for (auto itr = begin; itr < itr_end;) {
if (std::equal(in_delim_begin, in_delim_end, itr)) { if (std::equal(in_delim_begin, in_delim_end, itr)) {
// in_delim found; split upon it // in_delim found; split upon it
result.first = impl::member_from_range<MemberT>(begin, itr); result.first = make_split_member<MemberT>(begin, itr);
result.second = impl::member_from_range<MemberT>(itr + delim_length, end); result.second = make_split_member<MemberT>(itr + delim_length, end);
return result; return result;
} }
} }
// in_delim not found // in_delim not found
result.first = impl::member_from_range<MemberT>(begin, end); result.first = make_split_member<MemberT>(begin, end);
return result; return result;
} }
@ -305,8 +304,9 @@ constexpr auto split_once(const InputT& in_string, const DelimT& in_delim) {
*/ */
template<template<typename...> typename ContainerT = std::vector, typename... ContainerArgsT, typename ItrT, typename EndT, typename ElementT> template<template<typename...> typename ContainerT = std::vector, typename... ContainerArgsT, typename ItrT, typename EndT, typename ElementT>
constexpr auto split_n(ItrT begin, EndT end, ElementT in_delim, size_t in_limit) { constexpr auto split_n(ItrT begin, EndT end, ElementT in_delim, size_t in_limit) {
using MemberT = std::tuple_element_t<0, std::tuple<ContainerArgsT..., std::basic_string<ElementT>>>; using split_defaults_type = split_defaults<ContainerT, ElementT, ContainerArgsT...>;
using container_type = impl::split_container_helper_t<ContainerT, MemberT, ContainerArgsT...>; using member_type = typename split_defaults_type::member_type;
using container_type = typename split_defaults_type::container_type;
container_type result; container_type result;
if (begin >= end) { if (begin >= end) {
@ -317,14 +317,14 @@ constexpr auto split_n(ItrT begin, EndT end, ElementT in_delim, size_t in_limit)
for (auto itr = begin; itr != end && in_limit != 0; ++itr) { for (auto itr = begin; itr != end && in_limit != 0; ++itr) {
if (*itr == in_delim) { if (*itr == in_delim) {
// Push token to result // Push token to result
result.push_back(impl::member_from_range<MemberT>(begin, itr)); result.push_back(make_split_member<member_type>(begin, itr));
begin = itr + 1; begin = itr + 1;
--in_limit; --in_limit;
} }
} }
// Push final token to the end; may be empty // Push final token to the end; may be empty
result.push_back(impl::member_from_range<MemberT>(begin, end)); result.push_back(make_split_member<member_type>(begin, end));
return result; return result;
} }
@ -344,8 +344,9 @@ constexpr auto split_n(ItrT begin, EndT end, ElementT in_delim, size_t in_limit)
template<template<typename...> typename ContainerT = std::vector, typename... ContainerArgsT, typename ItrT, typename EndT, typename DelimItrT, typename DelimEndT> template<template<typename...> typename ContainerT = std::vector, typename... ContainerArgsT, typename ItrT, typename EndT, typename DelimItrT, typename DelimEndT>
constexpr auto split_n(ItrT begin, EndT end, DelimItrT in_delim_begin, DelimEndT in_delim_end, size_t in_limit) { constexpr auto split_n(ItrT begin, EndT end, DelimItrT in_delim_begin, DelimEndT in_delim_end, size_t in_limit) {
using ElementT = std::remove_cvref_t<decltype(*begin)>; using ElementT = std::remove_cvref_t<decltype(*begin)>;
using MemberT = std::tuple_element_t<0, std::tuple<ContainerArgsT..., std::basic_string<ElementT>>>; using split_defaults_type = split_defaults<ContainerT, ElementT, ContainerArgsT...>;
using container_type = impl::split_container_helper_t<ContainerT, MemberT, ContainerArgsT...>; using member_type = typename split_defaults_type::member_type;
using container_type = typename split_defaults_type::container_type;
auto delim_length = std::distance(in_delim_begin, in_delim_end); auto delim_length = std::distance(in_delim_begin, in_delim_end);
if (delim_length == 1) { if (delim_length == 1) {
@ -361,7 +362,7 @@ constexpr auto split_n(ItrT begin, EndT end, DelimItrT in_delim_begin, DelimEndT
if (in_delim_begin >= in_delim_end if (in_delim_begin >= in_delim_end
|| (end - begin) < delim_length) { || (end - begin) < delim_length) {
// Absent or impossible to match delimiter, therefore no match, therefore return input as single token // Absent or impossible to match delimiter, therefore no match, therefore return input as single token
result.push_back(impl::member_from_range<MemberT>(begin, end)); result.push_back(make_split_member<member_type>(begin, end));
return result; return result;
} }
@ -369,7 +370,7 @@ constexpr auto split_n(ItrT begin, EndT end, DelimItrT in_delim_begin, DelimEndT
for (auto itr = begin; itr < itr_end && in_limit != 0;) { for (auto itr = begin; itr < itr_end && in_limit != 0;) {
if (std::equal(in_delim_begin, in_delim_end, itr)) { if (std::equal(in_delim_begin, in_delim_end, itr)) {
// Push token to result // Push token to result
result.push_back(impl::member_from_range<MemberT>(begin, itr)); result.push_back(make_split_member<member_type>(begin, itr));
itr += delim_length; itr += delim_length;
begin = itr; begin = itr;
--in_limit; --in_limit;
@ -380,7 +381,7 @@ constexpr auto split_n(ItrT begin, EndT end, DelimItrT in_delim_begin, DelimEndT
} }
// Push final token to the end; may be empty // Push final token to the end; may be empty
result.push_back(impl::member_from_range<MemberT>(begin, end)); result.push_back(make_split_member<member_type>(begin, end));
return result; return result;
} }

Loading…
Cancel
Save