add ignore_header setup option, add unit tests for parsing by header, add string_view to possible conversion values

This commit is contained in:
ado
2022-03-27 21:04:02 +02:00
parent 45d166f93d
commit a8fa5c753c
69 changed files with 4194 additions and 33 deletions

View File

@@ -273,7 +273,7 @@ private:
}
}
void set_error_number_of_colums(size_t expected_pos, size_t pos) {
void set_error_number_of_columns(size_t expected_pos, size_t pos) {
if constexpr (string_error) {
error_.clear();
error_.append("invalid number of columns, expected: ")
@@ -339,7 +339,7 @@ private:
if (!columns_mapped()) {
if (sizeof...(Ts) != elems.size()) {
set_error_number_of_colums(sizeof...(Ts), elems.size());
set_error_number_of_columns(sizeof...(Ts), elems.size());
return return_type{};
}
} else {
@@ -349,9 +349,8 @@ private:
return return_type{};
}
if (elems.size() != number_of_columnts_) {
set_error_number_of_colums(sizeof...(Ts),
column_mappings_.size());
if (elems.size() != number_of_columns_) {
set_error_number_of_columns(number_of_columns_, elems.size());
return return_type{};
}
}
@@ -382,25 +381,25 @@ private:
}
void set_column_mapping(std::vector<size_t> positions,
size_t number_of_columnts) {
size_t number_of_columns) {
if (positions.empty()) {
set_error_invalid_mapping();
return;
}
auto max_index = *std::max_element(positions.begin(), positions.end());
if (max_index >= number_of_columnts) {
set_error_mapping_out_of_range(max_index, number_of_columnts);
if (max_index >= number_of_columns) {
set_error_mapping_out_of_range(max_index, number_of_columns);
return;
}
column_mappings_ = positions;
number_of_columnts_ = number_of_columnts;
number_of_columns_ = number_of_columns;
}
void clear_column_positions() {
column_mappings_.clear();
number_of_columnts_ = 0;
number_of_columns_ = 0;
}
////////////////
@@ -479,7 +478,7 @@ private:
friend class parser;
std::vector<size_t> column_mappings_;
size_t number_of_columnts_;
size_t number_of_columns_;
};
} /* ss */

View File

@@ -8,6 +8,7 @@
#include <optional>
#include <stdexcept>
#include <string>
#include <string_view>
#include <variant>
namespace ss {
@@ -318,7 +319,14 @@ inline bool extract(const char* begin, const char* end, char& value) {
template <>
inline bool extract(const char* begin, const char* end, std::string& value) {
value = std::string(begin, end);
value = std::string{begin, end};
return true;
}
template <>
inline bool extract(const char* begin, const char* end,
std::string_view& value) {
value = std::string_view{begin, static_cast<size_t>(end - begin)};
return true;
}

View File

@@ -25,15 +25,19 @@ class parser {
constexpr static bool quoted_multiline_enabled =
multiline::enabled && setup<Matchers...>::quote::enabled;
constexpr static bool ignore_header = setup<Matchers...>::ignore_header;
public:
parser(const std::string& file_name,
const std::string& delim = ss::default_delimiter)
: file_name_{file_name}, reader_{file_name_, delim} {
if (reader_.file_) {
read_line();
// TODO if header reading enabled
header_ = reader_.get_next_row();
// TODO if ignore_header defined ignore first line
if constexpr (ignore_header) {
ignore_next();
} else {
header_ = reader_.get_next_row();
}
} else {
set_error_file_not_open();
eof_ = true;
@@ -102,6 +106,11 @@ public:
template <typename... Ts>
void use_fields(const Ts&... fields_args) {
if constexpr (ignore_header) {
set_error_header_ignored();
return;
}
if (!valid()) {
return;
}
@@ -449,6 +458,18 @@ private:
}
}
void set_error_header_ignored() {
if constexpr (string_error) {
error_.append(file_name_)
.append(": \"")
.append("the header row is ignored within the setup, it cannot "
"be used")
.append("\"");
} else {
error_ = true;
}
}
void set_error_invalid_field(const std::string& field) {
if constexpr (string_error) {
error_.append(file_name_)

View File

@@ -167,6 +167,12 @@ using get_multiline_t = typename get_multiline<Ts...>::type;
class string_error;
////////////////
// ignore_header
////////////////
class ignore_header;
////////////////
// setup implementation
////////////////
@@ -185,13 +191,19 @@ private:
template <typename T>
struct is_string_error : std::is_same<T, string_error> {};
template <typename T>
struct is_ignore_header : std::is_same<T, ignore_header> {};
constexpr static auto count_matcher = count_v<is_matcher, Ts...>;
constexpr static auto count_multiline =
count_v<is_instance_of_multiline, Ts...>;
constexpr static auto count_string_error = count_v<is_string_error, Ts...>;
constexpr static auto count_ignore_header =
count_v<is_ignore_header, Ts...>;
constexpr static auto number_of_valid_setup_types =
count_matcher + count_multiline + count_string_error;
count_matcher + count_multiline + count_string_error +
count_ignore_header;
using trim_left_only = get_matcher_t<trim_left, Ts...>;
using trim_right_only = get_matcher_t<trim_right, Ts...>;
@@ -206,6 +218,7 @@ public:
using multiline = get_multiline_t<Ts...>;
constexpr static bool string_error = (count_string_error == 1);
constexpr static bool ignore_header = (count_ignore_header == 1);
private:
#define ASSERT_MSG "cannot have the same match character in multiple matchers"