mirror of
https://github.com/red0124/ssp.git
synced 2025-02-02 16:51:12 +01:00
move setup to seperate header, add static asserts
This commit is contained in:
parent
6da0cb3544
commit
7640c038f3
111
include/ss/setup.hpp
Normal file
111
include/ss/setup.hpp
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "type_traits.hpp"
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
namespace ss {
|
||||||
|
|
||||||
|
template <char... Cs>
|
||||||
|
struct matcher {
|
||||||
|
private:
|
||||||
|
template <char X, char... Xs>
|
||||||
|
static bool match_impl(char c) {
|
||||||
|
if constexpr (sizeof...(Xs) != 0) {
|
||||||
|
return (c == X) || match_impl<Xs...>(c);
|
||||||
|
}
|
||||||
|
return (c == X);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr static bool contains_string_terminator() {
|
||||||
|
for (const auto& match : matches) {
|
||||||
|
if (match == '\0') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
static bool match(char c) {
|
||||||
|
return match_impl<Cs...>(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr static bool enabled = true;
|
||||||
|
constexpr static std::array<char, sizeof...(Cs)> matches{Cs...};
|
||||||
|
static_assert(contains_string_terminator(),
|
||||||
|
"string terminator cannot be used as a match character");
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename FirstMatcher, typename SecondMatcher>
|
||||||
|
constexpr bool matches_intersect() {
|
||||||
|
for (const auto& first_match : FirstMatcher::matches) {
|
||||||
|
for (const auto& second_match : SecondMatcher::matches) {
|
||||||
|
if (first_match != '\0' && first_match == second_match) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
class matcher<'\0'> {
|
||||||
|
public:
|
||||||
|
constexpr static bool enabled = false;
|
||||||
|
constexpr static std::array<char, 1> matches{'\0'};
|
||||||
|
static bool match(char c) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <char C>
|
||||||
|
struct quote : matcher<C> {};
|
||||||
|
|
||||||
|
template <char... Cs>
|
||||||
|
struct trim : matcher<Cs...> {};
|
||||||
|
|
||||||
|
template <char... Cs>
|
||||||
|
struct escape : matcher<Cs...> {};
|
||||||
|
|
||||||
|
template <typename T, template <char...> class Template>
|
||||||
|
struct is_instance_of_matcher {
|
||||||
|
constexpr static bool value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <char... Ts, template <char...> class Template>
|
||||||
|
struct is_instance_of_matcher<Template<Ts...>, Template> {
|
||||||
|
constexpr static bool value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <template <char...> class Matcher, typename... Ts>
|
||||||
|
struct get_matcher;
|
||||||
|
|
||||||
|
template <template <char...> class Matcher, typename T, typename... Ts>
|
||||||
|
struct get_matcher<Matcher, T, Ts...> {
|
||||||
|
using type =
|
||||||
|
typename ternary<is_instance_of_matcher<T, Matcher>::value, T,
|
||||||
|
typename get_matcher<Matcher, Ts...>::type>::type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <template <char...> class Matcher>
|
||||||
|
struct get_matcher<Matcher> {
|
||||||
|
using type = Matcher<'\0'>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <template <char...> class Matcher, typename... Ts>
|
||||||
|
using get_matcher_t = typename get_matcher<Matcher, Ts...>::type;
|
||||||
|
|
||||||
|
template <typename... Ts>
|
||||||
|
struct setup {
|
||||||
|
using quote = get_matcher_t<quote, Ts...>;
|
||||||
|
using trim = get_matcher_t<trim, Ts...>;
|
||||||
|
using escape = get_matcher_t<escape, Ts...>;
|
||||||
|
|
||||||
|
#define ASSERT_MSG "cannot have the same character in multiple matchers"
|
||||||
|
static_assert(!matches_intersect<quote, trim>(), ASSERT_MSG);
|
||||||
|
static_assert(!matches_intersect<trim, escape>(), ASSERT_MSG);
|
||||||
|
static_assert(!matches_intersect<escape, quote>(), ASSERT_MSG);
|
||||||
|
#undef ASSERT_MSG
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename... Ts>
|
||||||
|
struct setup<setup<Ts...>> : setup<Ts...> {};
|
||||||
|
|
||||||
|
} /* ss */
|
@ -1,4 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "setup.hpp"
|
||||||
#include "type_traits.hpp"
|
#include "type_traits.hpp"
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@ -6,78 +7,6 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace ss {
|
namespace ss {
|
||||||
template <char... Cs>
|
|
||||||
struct matcher {
|
|
||||||
private:
|
|
||||||
template <char X, char... Xs>
|
|
||||||
static bool match_impl(char c) {
|
|
||||||
if constexpr (sizeof...(Xs) != 0) {
|
|
||||||
return (c == X) || match_impl<Xs...>(c);
|
|
||||||
}
|
|
||||||
return (c == X);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
static bool match(char c) {
|
|
||||||
return match_impl<Cs...>(c);
|
|
||||||
}
|
|
||||||
constexpr static bool enabled = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
class matcher<'\0'> {
|
|
||||||
public:
|
|
||||||
constexpr static bool enabled = false;
|
|
||||||
static bool match(char c) = delete;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <char C>
|
|
||||||
struct quote : matcher<C> {};
|
|
||||||
|
|
||||||
template <char... Cs>
|
|
||||||
struct trim : matcher<Cs...> {};
|
|
||||||
|
|
||||||
template <char... Cs>
|
|
||||||
struct escape : matcher<Cs...> {};
|
|
||||||
|
|
||||||
template <typename T, template <char...> class Template>
|
|
||||||
struct is_instance_of_matcher {
|
|
||||||
constexpr static bool value = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <char... Ts, template <char...> class Template>
|
|
||||||
struct is_instance_of_matcher<Template<Ts...>, Template> {
|
|
||||||
constexpr static bool value = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <template <char...> class Matcher, typename... Ts>
|
|
||||||
struct get_matcher;
|
|
||||||
|
|
||||||
template <template <char...> class Matcher, typename T, typename... Ts>
|
|
||||||
struct get_matcher<Matcher, T, Ts...> {
|
|
||||||
using type =
|
|
||||||
typename ternary<is_instance_of_matcher<T, Matcher>::value, T,
|
|
||||||
typename get_matcher<Matcher, Ts...>::type>::type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <template <char...> class Matcher>
|
|
||||||
struct get_matcher<Matcher> {
|
|
||||||
using type = Matcher<'\0'>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <template <char...> class Matcher, typename... Ts>
|
|
||||||
using get_matcher_t = typename get_matcher<Matcher, Ts...>::type;
|
|
||||||
|
|
||||||
// TODO add static asserts
|
|
||||||
template <typename... Ts>
|
|
||||||
struct setup {
|
|
||||||
using quote = get_matcher_t<quote, Ts...>;
|
|
||||||
using trim = get_matcher_t<trim, Ts...>;
|
|
||||||
using escape = get_matcher_t<escape, Ts...>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename... Ts>
|
|
||||||
struct setup<setup<Ts...>> : setup<Ts...> {};
|
|
||||||
|
|
||||||
using string_range = std::pair<const char*, const char*>;
|
using string_range = std::pair<const char*, const char*>;
|
||||||
using split_input = std::vector<string_range>;
|
using split_input = std::vector<string_range>;
|
||||||
|
Loading…
Reference in New Issue
Block a user