mirror of
https://github.com/red0124/ssp.git
synced 2025-01-23 13:05:20 +01:00
refactor splitter
This commit is contained in:
parent
263dba7626
commit
024e5d3810
@ -33,6 +33,7 @@ std::enable_if_t<std::is_floating_point_v<T>, T> pow10(int n) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO not working with large number of digits
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::enable_if_t<std::is_floating_point_v<T>, std::optional<T>> to_num(
|
std::enable_if_t<std::is_floating_point_v<T>, std::optional<T>> to_num(
|
||||||
const char* begin, const char* const end) {
|
const char* begin, const char* const end) {
|
||||||
|
@ -31,22 +31,6 @@ public:
|
|||||||
static bool match(char c) = delete;
|
static bool match(char c) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////
|
|
||||||
// is instance of
|
|
||||||
////////////////
|
|
||||||
|
|
||||||
template <typename T, template <char...> class Template>
|
|
||||||
struct is_instance_of_char {
|
|
||||||
constexpr static bool value = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <char... Ts, template <char...> class Template>
|
|
||||||
struct is_instance_of_char<Template<Ts...>, Template> {
|
|
||||||
constexpr static bool value = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////
|
|
||||||
|
|
||||||
template <char... Cs>
|
template <char... Cs>
|
||||||
struct quote : matcher<Cs...> {};
|
struct quote : matcher<Cs...> {};
|
||||||
|
|
||||||
@ -56,29 +40,23 @@ struct trim : matcher<Cs...> {};
|
|||||||
template <char... Cs>
|
template <char... Cs>
|
||||||
struct escape : matcher<Cs...> {};
|
struct escape : matcher<Cs...> {};
|
||||||
|
|
||||||
/////////////////////////////////////////////////
|
template <typename T, template <char...> class Template>
|
||||||
// -> type traits
|
struct is_instance_of_matcher {
|
||||||
template <bool B, typename T, typename U>
|
constexpr static bool value = false;
|
||||||
struct if_then_else;
|
|
||||||
|
|
||||||
template <typename T, typename U>
|
|
||||||
struct if_then_else<true, T, U> {
|
|
||||||
using type = T;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, typename U>
|
template <char... Ts, template <char...> class Template>
|
||||||
struct if_then_else<false, T, U> {
|
struct is_instance_of_matcher<Template<Ts...>, Template> {
|
||||||
using type = U;
|
constexpr static bool value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
template <template <char...> class Matcher, typename... Ts>
|
template <template <char...> class Matcher, typename... Ts>
|
||||||
struct get_matcher;
|
struct get_matcher;
|
||||||
|
|
||||||
template <template <char...> class Matcher, typename T, typename... Ts>
|
template <template <char...> class Matcher, typename T, typename... Ts>
|
||||||
struct get_matcher<Matcher, T, Ts...> {
|
struct get_matcher<Matcher, T, Ts...> {
|
||||||
using type =
|
using type =
|
||||||
typename if_then_else<is_instance_of_char<T, Matcher>::value, T,
|
typename ternary<is_instance_of_matcher<T, Matcher>::value, T,
|
||||||
typename get_matcher<Matcher, Ts...>::type>::type;
|
typename get_matcher<Matcher, Ts...>::type>::type;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -87,21 +65,21 @@ struct get_matcher<Matcher> {
|
|||||||
using type = Matcher<'\0'>;
|
using type = Matcher<'\0'>;
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////
|
template <template <char...> class Matcher, typename... Ts>
|
||||||
// TODO add restriction
|
using get_matcher_t = typename get_matcher<Matcher, Ts...>::type;
|
||||||
|
|
||||||
|
// TODO add static asserts
|
||||||
template <typename... Ts>
|
template <typename... Ts>
|
||||||
struct setup {
|
struct setup {
|
||||||
using quote = typename get_matcher<quote, Ts...>::type;
|
using quote = get_matcher_t<quote, Ts...>;
|
||||||
using trim = typename get_matcher<trim, Ts...>::type;
|
using trim = get_matcher_t<trim, Ts...>;
|
||||||
using escape = typename get_matcher<escape, Ts...>::type;
|
using escape = get_matcher_t<escape, Ts...>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename... Ts>
|
template <typename... Ts>
|
||||||
struct setup<setup<Ts...>> : setup<Ts...> {};
|
struct setup<setup<Ts...>> : setup<Ts...> {};
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
enum class state { begin, reading, quoting, finished };
|
||||||
|
|
||||||
enum class State { finished, begin, reading, quoting };
|
|
||||||
using range = std::pair<const char*, const char*>;
|
using range = std::pair<const char*, const char*>;
|
||||||
|
|
||||||
using string_range = std::pair<const char*, const char*>;
|
using string_range = std::pair<const char*, const char*>;
|
||||||
@ -109,10 +87,9 @@ using split_input = std::vector<string_range>;
|
|||||||
|
|
||||||
template <typename... Ts>
|
template <typename... Ts>
|
||||||
class splitter {
|
class splitter {
|
||||||
using Setup = setup<Ts...>;
|
using quote = typename setup<Ts...>::quote;
|
||||||
using quote = typename Setup::quote;
|
using trim = typename setup<Ts...>::trim;
|
||||||
using trim = typename Setup::trim;
|
using escape = typename setup<Ts...>::escape;
|
||||||
using escape = typename Setup::escape;
|
|
||||||
|
|
||||||
bool match(const char* end_i, char delim) {
|
bool match(const char* end_i, char delim) {
|
||||||
return *end_i == delim;
|
return *end_i == delim;
|
||||||
@ -187,6 +164,12 @@ class splitter {
|
|||||||
return {end_i - begin, true};
|
return {end_i - begin, true};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void push_and_start_next(size_t n) {
|
||||||
|
output_.emplace_back(begin, curr);
|
||||||
|
begin = end + n;
|
||||||
|
state_ = state::begin;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool valid() {
|
bool valid() {
|
||||||
return error_.empty();
|
return error_.empty();
|
||||||
@ -208,21 +191,21 @@ public:
|
|||||||
|
|
||||||
template <typename Delim>
|
template <typename Delim>
|
||||||
std::vector<range>& split_impl(const Delim& delim) {
|
std::vector<range>& split_impl(const Delim& delim) {
|
||||||
state = State::begin;
|
state_ = state::begin;
|
||||||
begin = line;
|
begin = line;
|
||||||
|
|
||||||
trim_if_enabled(begin);
|
trim_if_enabled(begin);
|
||||||
|
|
||||||
while (state != State::finished) {
|
while (state_ != state::finished) {
|
||||||
curr = end = begin;
|
curr = end = begin;
|
||||||
switch (state) {
|
switch (state_) {
|
||||||
case (State::begin):
|
case (state::begin):
|
||||||
state_begin();
|
state_begin();
|
||||||
break;
|
break;
|
||||||
case (State::reading):
|
case (state::reading):
|
||||||
state_reading(delim);
|
state_reading(delim);
|
||||||
break;
|
break;
|
||||||
case (State::quoting):
|
case (state::quoting):
|
||||||
state_quoting(delim);
|
state_quoting(delim);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -237,11 +220,11 @@ public:
|
|||||||
if constexpr (quote::enabled) {
|
if constexpr (quote::enabled) {
|
||||||
if (quote::match(*begin)) {
|
if (quote::match(*begin)) {
|
||||||
++begin;
|
++begin;
|
||||||
state = State::quoting;
|
state_ = state::quoting;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
state = State::reading;
|
state_ = state::reading;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Delim>
|
template <typename Delim>
|
||||||
@ -254,7 +237,7 @@ public:
|
|||||||
if (width == 0) {
|
if (width == 0) {
|
||||||
// eol
|
// eol
|
||||||
output_.emplace_back(begin, curr);
|
output_.emplace_back(begin, curr);
|
||||||
state = State::finished;
|
state_ = state::finished;
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
shift(width);
|
shift(width);
|
||||||
@ -294,7 +277,7 @@ public:
|
|||||||
// missmatched quote
|
// missmatched quote
|
||||||
// eg: ...,"hel"lo,... -> error
|
// eg: ...,"hel"lo,... -> error
|
||||||
}
|
}
|
||||||
state = State::finished;
|
state_ = state::finished;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,27 +298,21 @@ public:
|
|||||||
// eg: ..."hell\0 -> quote not terminated
|
// eg: ..."hell\0 -> quote not terminated
|
||||||
if (*end == '\0') {
|
if (*end == '\0') {
|
||||||
*curr = '\0';
|
*curr = '\0';
|
||||||
state = State::finished;
|
state_ = state::finished;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
shift();
|
shift();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// set error impossible scenario
|
// set error impossible scenario
|
||||||
state = State::finished;
|
state_ = state::finished;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void push_and_start_next(size_t n) {
|
|
||||||
output_.emplace_back(begin, curr);
|
|
||||||
begin = end + n;
|
|
||||||
state = State::begin;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<range> output_;
|
std::vector<range> output_;
|
||||||
std::string error_ = "";
|
std::string error_ = "";
|
||||||
State state;
|
state state_;
|
||||||
char* curr;
|
char* curr;
|
||||||
char* end;
|
char* end;
|
||||||
char* begin;
|
char* begin;
|
||||||
|
@ -314,6 +314,23 @@ struct is_instance_of<Template<Ts...>, Template> {
|
|||||||
constexpr static bool value = true;
|
constexpr static bool value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
////////////////
|
||||||
|
// ternary
|
||||||
|
////////////////
|
||||||
|
|
||||||
|
template <bool B, typename T, typename U>
|
||||||
|
struct ternary;
|
||||||
|
|
||||||
|
template <typename T, typename U>
|
||||||
|
struct ternary<true, T, U> {
|
||||||
|
using type = T;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename U>
|
||||||
|
struct ternary<false, T, U> {
|
||||||
|
using type = U;
|
||||||
|
};
|
||||||
|
|
||||||
////////////////
|
////////////////
|
||||||
// tuple to struct
|
// tuple to struct
|
||||||
////////////////
|
////////////////
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
CXX=clang++
|
CXX=g++
|
||||||
CXXFLAGS=-Wall -Wextra -std=c++17 -lstdc++fs
|
CXXFLAGS=-Wall -Wextra -std=c++17 -lstdc++fs
|
||||||
TESTS=test_parser test_converter test_extractions test_splitter
|
TESTS=test_parser test_converter test_extractions test_splitter
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user