diff --git a/include/ss/common.hpp b/include/ss/common.hpp new file mode 100644 index 0000000..d2d34bd --- /dev/null +++ b/include/ss/common.hpp @@ -0,0 +1,19 @@ +#pragma once +#include + +namespace ss { + +struct none {}; + +using string_range = std::pair; +using split_data = std::vector; + +constexpr inline auto default_delimiter = ","; + +template +inline void assert_string_error_defined() { + static_assert(StringError, + "'string_error' needs to be enabled to use 'error_msg'"); +} + +} /* ss */ diff --git a/include/ss/converter.hpp b/include/ss/converter.hpp index 0a0b837..74546d8 100644 --- a/include/ss/converter.hpp +++ b/include/ss/converter.hpp @@ -40,19 +40,13 @@ template using no_validator_t = typename no_validator::type; template -struct no_validator_tup { - using type = typename apply_trait>::type; -}; +struct no_validator_tup : apply_trait> {}; template -struct no_validator_tup> { - using type = typename no_validator_tup::type; -}; +struct no_validator_tup> : no_validator_tup {}; template -struct no_validator_tup> { - using type = no_validator_t; -}; +struct no_validator_tup> : no_validator {}; template using no_validator_tup_t = typename no_validator_tup::type; @@ -62,10 +56,7 @@ using no_validator_tup_t = typename no_validator_tup::type; //////////////// template -struct no_void_tup { - using type = - typename filter_not>::type; -}; +struct no_void_tup : filter_not> {}; template using no_void_tup_t = filter_not_t; @@ -76,14 +67,11 @@ using no_void_tup_t = filter_not_t; // replace 'validators' and remove void from tuple template -struct no_void_validator_tup { - using type = no_validator_tup_t>; -}; +struct no_void_validator_tup : no_validator_tup> {}; template -struct no_void_validator_tup> { - using type = no_validator_tup_t>; -}; +struct no_void_validator_tup> + : no_validator_tup> {}; template using no_void_validator_tup_t = typename no_void_validator_tup::type; @@ -131,12 +119,12 @@ public: no_void_validator_tup_t convert( line_ptr_type line, const std::string& delim = default_delimiter) { split(line, delim); - return convert(splitter_.split_input_); + return convert(splitter_.split_data_); } // parses already split line, returns 'T' object with extracted values template - T convert_object(const split_input& elems) { + T convert_object(const split_data& elems) { return to_object(convert(elems)); } @@ -151,17 +139,12 @@ public: // one argument is given which is a class which has a tied // method which returns a tuple, returns that type template - no_void_validator_tup_t convert(const split_input& elems) { - if constexpr (sizeof...(Ts) == 0 && - is_instance_of::value) { + no_void_validator_tup_t convert(const split_data& elems) { + if constexpr (sizeof...(Ts) == 0 && is_instance_of_v) { return convert_impl(elems, static_cast(nullptr)); - } else if constexpr (tied_class_v) { - using arg_ref_tuple = - typename std::result_of_t; - - using arg_tuple = - typename apply_trait::type; + using arg_ref_tuple = std::result_of_t; + using arg_tuple = apply_trait_t; return to_object( convert_impl(elems, static_cast(nullptr))); @@ -173,7 +156,7 @@ public: // same as above, but uses cached split line template no_void_validator_tup_t convert() { - return convert(splitter_.split_input_); + return convert(splitter_.split_data_); } bool valid() const { @@ -185,8 +168,7 @@ public: } const std::string& error_msg() const { - static_assert(string_error, - "'string_error' needs to be enabled to use 'error_msg'"); + assert_string_error_defined(); return error_; } @@ -196,11 +178,11 @@ public: // 'splits' string by given delimiter, returns vector of pairs which // contain the beginnings and the ends of each column of the string - const split_input& split(line_ptr_type line, - const std::string& delim = default_delimiter) { - splitter_.split_input_.clear(); + const split_data& split(line_ptr_type line, + const std::string& delim = default_delimiter) { + splitter_.split_data_.clear(); if (line[0] == '\0') { - return splitter_.split_input_; + return splitter_.split_data_; } return splitter_.split(line, delim); @@ -211,8 +193,8 @@ private: // resplit //////////////// - const split_input& resplit(line_ptr_type new_line, ssize_t new_size, - const std::string& delim = default_delimiter) { + const split_data& resplit(line_ptr_type new_line, ssize_t new_size, + const std::string& delim = default_delimiter) { return splitter_.resplit(new_line, new_size, delim); } @@ -285,7 +267,7 @@ private: //////////////// template - no_void_validator_tup_t convert_impl(const split_input& elems) { + no_void_validator_tup_t convert_impl(const split_data& elems) { clear_error(); if (!splitter_.valid()) { @@ -306,7 +288,7 @@ private: // do not know how to specialize by return type :( template no_void_validator_tup_t> convert_impl( - const split_input& elems, const std::tuple*) { + const split_data& elems, const std::tuple*) { return convert_impl(elems); } @@ -345,11 +327,11 @@ private: template void extract_multiple(no_void_validator_tup_t& tup, - const split_input& elems) { + const split_data& elems) { using elem_t = std::tuple_element_t>; constexpr bool not_void = !std::is_void_v; - constexpr bool one_element = count_not::size == 1; + constexpr bool one_element = count_not_v == 1; if constexpr (not_void) { if constexpr (one_element) { @@ -367,8 +349,8 @@ private: } template - no_void_validator_tup_t extract_tuple(const split_input& elems) { - static_assert(!all_of::value, + no_void_validator_tup_t extract_tuple(const split_data& elems) { + static_assert(!all_of_v, "at least one parameter must be non void"); no_void_validator_tup_t ret{}; extract_multiple<0, 0, Ts...>(ret, elems); @@ -379,7 +361,7 @@ private: // members //////////////// - error_type error_; + error_type error_{}; splitter splitter_; template diff --git a/include/ss/extract.hpp b/include/ss/extract.hpp index 60d3fdb..ebf7ef8 100644 --- a/include/ss/extract.hpp +++ b/include/ss/extract.hpp @@ -225,8 +225,8 @@ struct unsupported_type { template std::enable_if_t && !std::is_floating_point_v && - !is_instance_of::value && - !is_instance_of::value, + !is_instance_of_v && + !is_instance_of_v, bool> extract(const char*, const char*, T&) { static_assert(error::unsupported_type::value, @@ -246,7 +246,7 @@ extract(const char* begin, const char* end, T& value) { } template -std::enable_if_t::value, bool> extract( +std::enable_if_t, bool> extract( const char* begin, const char* end, T& value) { typename T::value_type raw_value; if (extract(begin, end, raw_value)) { @@ -271,7 +271,7 @@ bool extract_variant(const char* begin, const char* end, T& value) { } template -std::enable_if_t::value, bool> extract( +std::enable_if_t, bool> extract( const char* begin, const char* end, T& value) { return extract_variant(begin, end, value); } diff --git a/include/ss/parser.hpp b/include/ss/parser.hpp index af740b1..7054e7c 100644 --- a/include/ss/parser.hpp +++ b/include/ss/parser.hpp @@ -13,8 +13,6 @@ namespace ss { template class parser { - struct none {}; - constexpr static auto string_error = setup::string_error; constexpr static auto multiline = setup::multiline; @@ -48,8 +46,7 @@ public: } const std::string& error_msg() const { - static_assert(string_error, - "'string_error' needs to be enabled to use 'error_msg'"); + assert_string_error_defined(); return error_; } @@ -157,11 +154,13 @@ public: if (!parser_.valid()) { return; } + if constexpr (!std::is_same_v) { value = to_object(std::move(tuple_output)); } else { value = std::move(tuple_output); } + parser_.try_invoke(*value, std::forward(fun)); } } @@ -177,6 +176,10 @@ public: return value; } + //////////////// + // members + //////////////// + std::tuple values_; parser& parser_; }; @@ -488,7 +491,7 @@ private: //////////////// std::string file_name_; - error_type error_; + error_type error_{}; reader reader_; size_t line_number_{0}; bool eof_{false}; diff --git a/include/ss/setup.hpp b/include/ss/setup.hpp index c773fca..228cb1e 100644 --- a/include/ss/setup.hpp +++ b/include/ss/setup.hpp @@ -4,6 +4,10 @@ namespace ss { +//////////////// +// matcher +//////////////// + template struct matcher { private: @@ -36,7 +40,7 @@ public: }; template -constexpr bool matches_intersect() { +inline 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) { @@ -47,6 +51,13 @@ constexpr bool matches_intersect() { return false; } +template +inline constexpr bool matches_intersect_union() { + return matches_intersect() || + matches_intersect(); +} + template <> class matcher<'\0'> { public: @@ -55,31 +66,57 @@ public: static bool match(char c) = delete; }; +//////////////// +// setup parameters +//////////////// + template struct quote : matcher {}; template struct trim : matcher {}; +template +struct trim_left : matcher {}; + +template +struct trim_right : matcher {}; + template struct escape : matcher {}; +// TODO add limit +class multiline; + +class string_error; + +//////////////// +// setup implementation +//////////////// + template class Template> -struct is_instance_of_matcher { - constexpr static bool value = false; -}; +struct is_instance_of_matcher : std::false_type {}; template class Template> -struct is_instance_of_matcher, Template> { - constexpr static bool value = true; -}; +struct is_instance_of_matcher, Template> : std::true_type {}; + +template class Template> +using is_instance_of_matcher_t = + typename is_instance_of_matcher::type; template