mirror of
https://github.com/red0124/ssp.git
synced 2025-02-02 16:51:12 +01:00
Implement throw_on_error functionality, rename some template parameters
This commit is contained in:
parent
3eefac93b1
commit
eeac30651a
@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#include "exception.hpp"
|
||||
#include "extract.hpp"
|
||||
#include "function_traits.hpp"
|
||||
#include "restrictions.hpp"
|
||||
@ -95,11 +96,12 @@ constexpr bool tied_class_v = tied_class<Ts...>::value;
|
||||
// converter
|
||||
////////////////
|
||||
|
||||
template <typename... Matchers>
|
||||
template <typename... Options>
|
||||
class converter {
|
||||
using line_ptr_type = typename splitter<Matchers...>::line_ptr_type;
|
||||
using line_ptr_type = typename splitter<Options...>::line_ptr_type;
|
||||
|
||||
constexpr static auto string_error = setup<Matchers...>::string_error;
|
||||
constexpr static auto string_error = setup<Options...>::string_error;
|
||||
constexpr static auto throw_on_error = setup<Options...>::throw_on_error;
|
||||
constexpr static auto default_delimiter = ",";
|
||||
|
||||
using error_type = std::conditional_t<string_error, std::string, bool>;
|
||||
@ -229,6 +231,7 @@ private:
|
||||
if constexpr (string_error) {
|
||||
error_.clear();
|
||||
error_.append(splitter_.error_msg());
|
||||
throw_if_throw_on_error<throw_on_error>(error_);
|
||||
} else {
|
||||
error_ = true;
|
||||
}
|
||||
@ -239,6 +242,7 @@ private:
|
||||
error_.clear();
|
||||
splitter_.set_error_unterminated_escape();
|
||||
error_.append(splitter_.error_msg());
|
||||
throw_if_throw_on_error<throw_on_error>(error_);
|
||||
} else {
|
||||
error_ = true;
|
||||
}
|
||||
@ -247,7 +251,8 @@ private:
|
||||
void set_error_multiline_limit_reached() {
|
||||
if constexpr (string_error) {
|
||||
error_.clear();
|
||||
error_.append("multiline limit reached.");
|
||||
error_.append("multiline limit reached");
|
||||
throw_if_throw_on_error<throw_on_error>(error_);
|
||||
} else {
|
||||
error_ = true;
|
||||
}
|
||||
@ -258,6 +263,7 @@ private:
|
||||
error_.clear();
|
||||
error_.append("invalid conversion for parameter ")
|
||||
.append(error_sufix(msg, pos));
|
||||
throw_if_throw_on_error<throw_on_error>(error_);
|
||||
} else {
|
||||
error_ = true;
|
||||
}
|
||||
@ -268,6 +274,7 @@ private:
|
||||
if constexpr (string_error) {
|
||||
error_.clear();
|
||||
error_.append(error).append(" ").append(error_sufix(msg, pos));
|
||||
throw_if_throw_on_error<throw_on_error>(error_);
|
||||
} else {
|
||||
error_ = true;
|
||||
}
|
||||
@ -280,6 +287,7 @@ private:
|
||||
.append(std::to_string(expected_pos))
|
||||
.append(", got: ")
|
||||
.append(std::to_string(pos));
|
||||
throw_if_throw_on_error<throw_on_error>(error_);
|
||||
} else {
|
||||
error_ = true;
|
||||
}
|
||||
@ -295,6 +303,7 @@ private:
|
||||
.append(std::to_string(mapping_size))
|
||||
.append(", got: ")
|
||||
.append(std::to_string(argument_size));
|
||||
throw_if_throw_on_error<throw_on_error>(error_);
|
||||
} else {
|
||||
error_ = true;
|
||||
}
|
||||
@ -304,6 +313,7 @@ private:
|
||||
if constexpr (string_error) {
|
||||
error_.clear();
|
||||
error_.append("received empty mapping");
|
||||
throw_if_throw_on_error<throw_on_error>(error_);
|
||||
} else {
|
||||
error_ = true;
|
||||
}
|
||||
@ -317,6 +327,7 @@ private:
|
||||
.append(std::to_string(maximum_index))
|
||||
.append(", greater then number of columns: ")
|
||||
.append(std::to_string(number_of_columnts));
|
||||
throw_if_throw_on_error<throw_on_error>(error_);
|
||||
} else {
|
||||
error_ = true;
|
||||
}
|
||||
@ -472,7 +483,7 @@ private:
|
||||
////////////////
|
||||
|
||||
error_type error_{};
|
||||
splitter<Matchers...> splitter_;
|
||||
splitter<Options...> splitter_;
|
||||
|
||||
template <typename...>
|
||||
friend class parser;
|
||||
|
30
include/ss/exception.hpp
Normal file
30
include/ss/exception.hpp
Normal file
@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
#include <exception>
|
||||
#include <string>
|
||||
|
||||
namespace ss {
|
||||
|
||||
////////////////
|
||||
// exception
|
||||
////////////////
|
||||
|
||||
class exception : public std::exception {
|
||||
std::string msg_;
|
||||
|
||||
public:
|
||||
exception(const std::string& msg): msg_{msg} {
|
||||
}
|
||||
|
||||
virtual char const* what() const noexcept {
|
||||
return msg_.c_str();
|
||||
}
|
||||
};
|
||||
|
||||
template <bool throw_on_error>
|
||||
void throw_if_throw_on_error(const std::string& msg) {
|
||||
if constexpr (throw_on_error) {
|
||||
throw ss::exception(msg);
|
||||
}
|
||||
}
|
||||
|
||||
} /* ss */
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include "common.hpp"
|
||||
#include "converter.hpp"
|
||||
#include "exception.hpp"
|
||||
#include "extract.hpp"
|
||||
#include "restrictions.hpp"
|
||||
#include <cstdlib>
|
||||
@ -12,22 +13,23 @@
|
||||
|
||||
namespace ss {
|
||||
|
||||
template <typename... Matchers>
|
||||
template <typename... Options>
|
||||
class parser {
|
||||
constexpr static auto string_error = setup<Matchers...>::string_error;
|
||||
constexpr static auto string_error = setup<Options...>::string_error;
|
||||
constexpr static auto throw_on_error = setup<Options...>::throw_on_error;
|
||||
|
||||
using multiline = typename setup<Matchers...>::multiline;
|
||||
using multiline = typename setup<Options...>::multiline;
|
||||
using error_type = std::conditional_t<string_error, std::string, bool>;
|
||||
|
||||
constexpr static bool escaped_multiline_enabled =
|
||||
multiline::enabled && setup<Matchers...>::escape::enabled;
|
||||
multiline::enabled && setup<Options...>::escape::enabled;
|
||||
|
||||
constexpr static bool quoted_multiline_enabled =
|
||||
multiline::enabled && setup<Matchers...>::quote::enabled;
|
||||
multiline::enabled && setup<Options...>::quote::enabled;
|
||||
|
||||
constexpr static bool ignore_header = setup<Matchers...>::ignore_header;
|
||||
constexpr static bool ignore_header = setup<Options...>::ignore_header;
|
||||
|
||||
constexpr static bool ignore_empty = setup<Matchers...>::ignore_empty;
|
||||
constexpr static bool ignore_empty = setup<Options...>::ignore_empty;
|
||||
|
||||
public:
|
||||
parser(const std::string& file_name,
|
||||
@ -152,11 +154,11 @@ public:
|
||||
struct iterable {
|
||||
struct iterator {
|
||||
using value = std::conditional_t<get_object, T,
|
||||
no_void_validator_tup_t<T, Ts...>>;
|
||||
no_void_validator_tup_t<T, Ts...>>;
|
||||
|
||||
iterator() : parser_{nullptr} {
|
||||
}
|
||||
iterator(parser<Matchers...>* parser) : parser_{parser} {
|
||||
iterator(parser<Options...>* parser) : parser_{parser} {
|
||||
}
|
||||
|
||||
value& operator*() {
|
||||
@ -197,10 +199,10 @@ public:
|
||||
|
||||
private:
|
||||
value value_;
|
||||
parser<Matchers...>* parser_;
|
||||
parser<Options...>* parser_;
|
||||
};
|
||||
|
||||
iterable(parser<Matchers...>* parser) : parser_{parser} {
|
||||
iterable(parser<Options...>* parser) : parser_{parser} {
|
||||
}
|
||||
|
||||
iterator begin() {
|
||||
@ -211,7 +213,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
parser<Matchers...>* parser_;
|
||||
parser<Options...>* parser_;
|
||||
};
|
||||
|
||||
template <typename... Ts>
|
||||
@ -423,7 +425,8 @@ private:
|
||||
|
||||
void set_error_failed_check() {
|
||||
if constexpr (string_error) {
|
||||
error_.append(file_name_).append(" failed check.");
|
||||
error_.append(file_name_).append(" failed check");
|
||||
throw_if_throw_on_error<throw_on_error>(error_);
|
||||
} else {
|
||||
error_ = true;
|
||||
}
|
||||
@ -431,7 +434,8 @@ private:
|
||||
|
||||
void set_error_file_not_open() {
|
||||
if constexpr (string_error) {
|
||||
error_.append(file_name_).append(" could not be opened.");
|
||||
error_.append(file_name_).append(" could not be opened");
|
||||
throw_if_throw_on_error<throw_on_error>(error_);
|
||||
} else {
|
||||
error_ = true;
|
||||
}
|
||||
@ -439,7 +443,8 @@ private:
|
||||
|
||||
void set_error_eof_reached() {
|
||||
if constexpr (string_error) {
|
||||
error_.append(file_name_).append(" reached end of file.");
|
||||
error_.append(file_name_).append(" reached end of file");
|
||||
throw_if_throw_on_error<throw_on_error>(error_);
|
||||
} else {
|
||||
error_ = true;
|
||||
}
|
||||
@ -455,6 +460,7 @@ private:
|
||||
.append(": \"")
|
||||
.append(reader_.buffer_)
|
||||
.append("\"");
|
||||
throw_if_throw_on_error<throw_on_error>(error_);
|
||||
} else {
|
||||
error_ = true;
|
||||
}
|
||||
@ -467,6 +473,7 @@ private:
|
||||
.append("the header row is ignored within the setup, it cannot "
|
||||
"be used")
|
||||
.append("\"");
|
||||
throw_if_throw_on_error<throw_on_error>(error_);
|
||||
} else {
|
||||
error_ = true;
|
||||
}
|
||||
@ -477,6 +484,7 @@ private:
|
||||
error_.append(file_name_)
|
||||
.append(": header does not contain given field: ")
|
||||
.append(field);
|
||||
throw_if_throw_on_error<throw_on_error>(error_);
|
||||
} else {
|
||||
error_ = true;
|
||||
}
|
||||
@ -487,6 +495,7 @@ private:
|
||||
error_.append(file_name_)
|
||||
.append(": given field used multiple times: ")
|
||||
.append(field);
|
||||
throw_if_throw_on_error<throw_on_error>(error_);
|
||||
} else {
|
||||
error_ = true;
|
||||
}
|
||||
@ -650,7 +659,7 @@ private:
|
||||
const char* curr;
|
||||
for (curr = next_line_buffer_ + size - 1;
|
||||
curr >= next_line_buffer_ &&
|
||||
setup<Matchers...>::escape::match(*curr);
|
||||
setup<Options...>::escape::match(*curr);
|
||||
--curr) {
|
||||
}
|
||||
return (next_line_buffer_ - curr + size) % 2 == 0;
|
||||
@ -729,8 +738,8 @@ private:
|
||||
char* next_line_buffer_{nullptr};
|
||||
char* helper_buffer_{nullptr};
|
||||
|
||||
converter<Matchers...> converter_;
|
||||
converter<Matchers...> next_line_converter_;
|
||||
converter<Options...> converter_;
|
||||
converter<Options...> next_line_converter_;
|
||||
|
||||
size_t size_{0};
|
||||
size_t next_line_size_{0};
|
||||
|
@ -179,20 +179,26 @@ class ignore_header;
|
||||
|
||||
class ignore_empty;
|
||||
|
||||
////////////////
|
||||
// throw_on_error
|
||||
////////////////
|
||||
|
||||
class throw_on_error;
|
||||
|
||||
////////////////
|
||||
// setup implementation
|
||||
////////////////
|
||||
|
||||
template <typename... Ts>
|
||||
template <typename... Options>
|
||||
struct setup {
|
||||
private:
|
||||
template <typename T>
|
||||
template <typename Option>
|
||||
struct is_matcher
|
||||
: std::disjunction<is_instance_of_matcher_t<T, quote>,
|
||||
is_instance_of_matcher_t<T, escape>,
|
||||
is_instance_of_matcher_t<T, trim>,
|
||||
is_instance_of_matcher_t<T, trim_left>,
|
||||
is_instance_of_matcher_t<T, trim_right>> {};
|
||||
: std::disjunction<is_instance_of_matcher_t<Option, quote>,
|
||||
is_instance_of_matcher_t<Option, escape>,
|
||||
is_instance_of_matcher_t<Option, trim>,
|
||||
is_instance_of_matcher_t<Option, trim_left>,
|
||||
is_instance_of_matcher_t<Option, trim_right>> {};
|
||||
|
||||
template <typename T>
|
||||
struct is_string_error : std::is_same<T, string_error> {};
|
||||
@ -203,39 +209,47 @@ private:
|
||||
template <typename T>
|
||||
struct is_ignore_empty : std::is_same<T, ignore_empty> {};
|
||||
|
||||
constexpr static auto count_matcher = count_v<is_matcher, Ts...>;
|
||||
template <typename T>
|
||||
struct is_throw_on_error : std::is_same<T, throw_on_error> {};
|
||||
|
||||
constexpr static auto count_matcher = count_v<is_matcher, Options...>;
|
||||
|
||||
constexpr static auto count_multiline =
|
||||
count_v<is_instance_of_multiline, Ts...>;
|
||||
count_v<is_instance_of_multiline, Options...>;
|
||||
|
||||
constexpr static auto count_string_error = count_v<is_string_error, Ts...>;
|
||||
constexpr static auto count_string_error = count_v<is_string_error, Options...>;
|
||||
|
||||
constexpr static auto count_ignore_header =
|
||||
count_v<is_ignore_header, Ts...>;
|
||||
count_v<is_ignore_header, Options...>;
|
||||
|
||||
constexpr static auto count_ignore_empty = count_v<is_ignore_empty, Ts...>;
|
||||
constexpr static auto count_throw_on_error =
|
||||
count_v<is_throw_on_error, Options...>;
|
||||
|
||||
constexpr static auto count_ignore_empty = count_v<is_ignore_empty, Options...>;
|
||||
|
||||
constexpr static auto number_of_valid_setup_types =
|
||||
count_matcher + count_multiline + count_string_error +
|
||||
count_ignore_header + count_ignore_empty;
|
||||
count_ignore_header + count_ignore_empty + count_throw_on_error;
|
||||
|
||||
using trim_left_only = get_matcher_t<trim_left, Ts...>;
|
||||
using trim_right_only = get_matcher_t<trim_right, Ts...>;
|
||||
using trim_all = get_matcher_t<trim, Ts...>;
|
||||
using trim_left_only = get_matcher_t<trim_left, Options...>;
|
||||
using trim_right_only = get_matcher_t<trim_right, Options...>;
|
||||
using trim_all = get_matcher_t<trim, Options...>;
|
||||
|
||||
public:
|
||||
using quote = get_matcher_t<quote, Ts...>;
|
||||
using escape = get_matcher_t<escape, Ts...>;
|
||||
using quote = get_matcher_t<quote, Options...>;
|
||||
using escape = get_matcher_t<escape, Options...>;
|
||||
|
||||
using trim_left =
|
||||
std::conditional_t<trim_all::enabled, trim_all, trim_left_only>;
|
||||
using trim_right =
|
||||
std::conditional_t<trim_all::enabled, trim_all, trim_right_only>;
|
||||
|
||||
using multiline = get_multiline_t<Ts...>;
|
||||
using multiline = get_multiline_t<Options...>;
|
||||
constexpr static bool string_error = (count_string_error == 1);
|
||||
constexpr static bool ignore_header = (count_ignore_header == 1);
|
||||
constexpr static bool ignore_empty = (count_ignore_empty == 1);
|
||||
constexpr static bool throw_on_error = (count_throw_on_error == 1);
|
||||
// TODO set string_error if throw_on_error is defined
|
||||
|
||||
private:
|
||||
#define ASSERT_MSG "cannot have the same match character in multiple matchers"
|
||||
@ -264,11 +278,11 @@ private:
|
||||
static_assert(count_string_error <= 1,
|
||||
"string_error defined multiple times");
|
||||
|
||||
static_assert(number_of_valid_setup_types == sizeof...(Ts),
|
||||
static_assert(number_of_valid_setup_types == sizeof...(Options),
|
||||
"one or multiple invalid setup parameters defined");
|
||||
};
|
||||
|
||||
template <typename... Ts>
|
||||
struct setup<setup<Ts...>> : setup<Ts...> {};
|
||||
template <typename... Options>
|
||||
struct setup<setup<Options...>> : setup<Options...> {};
|
||||
|
||||
} /* ss */
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include "common.hpp"
|
||||
#include "exception.hpp"
|
||||
#include "setup.hpp"
|
||||
#include "type_traits.hpp"
|
||||
#include <algorithm>
|
||||
@ -11,16 +12,17 @@
|
||||
|
||||
namespace ss {
|
||||
|
||||
template <typename... Ts>
|
||||
template <typename... Options>
|
||||
class splitter {
|
||||
private:
|
||||
using quote = typename setup<Ts...>::quote;
|
||||
using trim_left = typename setup<Ts...>::trim_left;
|
||||
using trim_right = typename setup<Ts...>::trim_right;
|
||||
using escape = typename setup<Ts...>::escape;
|
||||
using multiline = typename setup<Ts...>::multiline;
|
||||
using quote = typename setup<Options...>::quote;
|
||||
using trim_left = typename setup<Options...>::trim_left;
|
||||
using trim_right = typename setup<Options...>::trim_right;
|
||||
using escape = typename setup<Options...>::escape;
|
||||
using multiline = typename setup<Options...>::multiline;
|
||||
|
||||
constexpr static auto string_error = setup<Ts...>::string_error;
|
||||
constexpr static auto string_error = setup<Options...>::string_error;
|
||||
constexpr static auto throw_on_error = setup<Options...>::throw_on_error;
|
||||
constexpr static auto is_const_line = !quote::enabled && !escape::enabled;
|
||||
|
||||
using error_type = std::conditional_t<string_error, std::string, bool>;
|
||||
@ -121,7 +123,8 @@ private:
|
||||
void set_error_empty_delimiter() {
|
||||
if constexpr (string_error) {
|
||||
error_.clear();
|
||||
error_.append("empt delimiter");
|
||||
error_.append("empty delimiter");
|
||||
throw_if_throw_on_error<throw_on_error>(error_);
|
||||
} else {
|
||||
error_ = true;
|
||||
}
|
||||
@ -131,6 +134,7 @@ private:
|
||||
if constexpr (string_error) {
|
||||
error_.clear();
|
||||
error_.append("mismatched quote at position: " + std::to_string(n));
|
||||
throw_if_throw_on_error<throw_on_error>(error_);
|
||||
} else {
|
||||
error_ = true;
|
||||
}
|
||||
@ -140,6 +144,7 @@ private:
|
||||
if constexpr (string_error) {
|
||||
error_.clear();
|
||||
error_.append("unterminated escape at the end of the line");
|
||||
throw_if_throw_on_error<throw_on_error>(error_);
|
||||
} else {
|
||||
error_ = true;
|
||||
}
|
||||
@ -150,6 +155,7 @@ private:
|
||||
if constexpr (string_error) {
|
||||
error_.clear();
|
||||
error_.append("unterminated quote");
|
||||
throw_if_throw_on_error<throw_on_error>(error_);
|
||||
} else {
|
||||
error_ = true;
|
||||
}
|
||||
@ -161,6 +167,7 @@ private:
|
||||
error_.clear();
|
||||
error_.append("invalid resplit, new line must be longer"
|
||||
"than the end of the last slice");
|
||||
throw_if_throw_on_error<throw_on_error>(error_);
|
||||
} else {
|
||||
error_ = true;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user