add mismatched quote error, update error handling for splitter, add unit tests, update test_helpers buffer

This commit is contained in:
ado 2021-02-02 02:17:31 +01:00
parent d887dff82a
commit 6da0cb3544
6 changed files with 104 additions and 18 deletions

View File

@ -127,11 +127,6 @@ public:
no_void_validator_tup_t<Ts...> convert( no_void_validator_tup_t<Ts...> convert(
line_ptr_type line, const std::string& delim = default_delimiter) { line_ptr_type line, const std::string& delim = default_delimiter) {
input_ = split(line, delim); input_ = split(line, delim);
if (!splitter_.valid()) {
set_error_line_not_split();
no_void_validator_tup_t<Ts...> ret{};
return ret;
}
return convert<Ts...>(input_); return convert<Ts...>(input_);
} }
@ -191,6 +186,7 @@ public:
} }
void set_error_mode(error_mode mode) { void set_error_mode(error_mode mode) {
splitter_.set_error_mode(mode);
error_mode_ = mode; error_mode_ = mode;
} }
@ -234,10 +230,10 @@ private:
return error; return error;
} }
void set_error_line_not_split() { void set_error_unterminated_quote() {
if (error_mode_ == error_mode::error_string) { if (error_mode_ == error_mode::error_string) {
string_error_.clear(); string_error_.clear();
string_error_.append("line not split correctly"); string_error_.append(splitter_.error_msg());
} else { } else {
bool_error_ = true; bool_error_ = true;
} }
@ -283,11 +279,19 @@ private:
template <typename... Ts> template <typename... Ts>
no_void_validator_tup_t<Ts...> convert_impl(const split_input& elems) { no_void_validator_tup_t<Ts...> convert_impl(const split_input& elems) {
clear_error(); clear_error();
if (!splitter_.valid()) {
set_error_unterminated_quote();
no_void_validator_tup_t<Ts...> ret{};
return ret;
}
if (sizeof...(Ts) != elems.size()) { if (sizeof...(Ts) != elems.size()) {
set_error_number_of_colums(sizeof...(Ts), elems.size()); set_error_number_of_colums(sizeof...(Ts), elems.size());
no_void_validator_tup_t<Ts...> ret{}; no_void_validator_tup_t<Ts...> ret{};
return ret; return ret;
} }
return extract_tuple<Ts...>(elems); return extract_tuple<Ts...>(elems);
} }

View File

@ -9,6 +9,8 @@
#include <string> #include <string>
#include <vector> #include <vector>
// TODO rule of 5-3-1
// TODO threads
namespace ss { namespace ss {
template <typename... Matchers> template <typename... Matchers>

View File

@ -119,7 +119,7 @@ public:
} }
const split_input& split(line_ptr_type new_line, const split_input& split(line_ptr_type new_line,
const std::string& delimiter = default_delimiter) { const std::string& delimiter = default_delimiter) {
output_.clear(); output_.clear();
return resplit(new_line, -1, delimiter); return resplit(new_line, -1, delimiter);
} }
@ -131,8 +131,9 @@ public:
} }
} }
const split_input& resplit(line_ptr_type new_line, ssize_t new_size, const split_input& resplit(
const std::string& delimiter = default_delimiter) { line_ptr_type new_line, ssize_t new_size,
const std::string& delimiter = default_delimiter) {
line_ = new_line; line_ = new_line;
// resplitting, continue from last slice // resplitting, continue from last slice
@ -175,6 +176,16 @@ private:
} }
} }
void set_error_mismatched_quote(size_t n) {
if (error_mode_ == error_mode::error_string) {
string_error_.clear();
string_error_.append("mismatched quote at position: " +
std::to_string(n));
} else {
bool_error_ = true;
}
}
void set_error_unterminated_quote() { void set_error_unterminated_quote() {
unterminated_quote_ = true; unterminated_quote_ = true;
if (error_mode_ == error_mode::error_string) { if (error_mode_ == error_mode::error_string) {
@ -186,9 +197,11 @@ private:
} }
void set_error_invalid_resplit() { void set_error_invalid_resplit() {
unterminated_quote_ = false;
if (error_mode_ == error_mode::error_string) { if (error_mode_ == error_mode::error_string) {
string_error_.clear(); string_error_.clear();
string_error_.append("invalid_resplit"); string_error_.append("invalid resplit, new line must be longer"
"than the end of the last slice");
} else { } else {
bool_error_ = true; bool_error_ = true;
} }
@ -388,9 +401,10 @@ private:
// eg no trim: ...,"hello"\0 -> hello // eg no trim: ...,"hello"\0 -> hello
output_.emplace_back(begin_, curr_); output_.emplace_back(begin_, curr_);
} else { } else {
// missmatched quote // mismatched quote
// eg: ...,"hel"lo,... -> error // eg: ...,"hel"lo,... -> error
// or not set_error_mismatched_quote(end_ - line_);
output_.emplace_back(line_, begin_);
} }
state_ = state::finished; state_ = state::finished;
break; break;

View File

@ -115,6 +115,9 @@ TEST_CASE("testing invalid conversions") {
c.convert<int>(""); c.convert<int>("");
REQUIRE(!c.valid()); REQUIRE(!c.valid());
c.convert<int>("10", "");
REQUIRE(!c.valid());
c.convert<int, void>(""); c.convert<int, void>("");
REQUIRE(!c.valid()); REQUIRE(!c.valid());
@ -438,3 +441,24 @@ TEST_CASE("testing converter with quotes spacing and escaping") {
CHECK(tup == std::make_tuple("ju,st", "so,me", 12.34, "str\"ings")); CHECK(tup == std::make_tuple("ju,st", "so,me", 12.34, "str\"ings"));
} }
} }
TEST_CASE("testing invalid split conversions") {
ss::converter<ss::escape<'\\'>, ss::trim<' '>, ss::quote<'"'>> c;
c.set_error_mode(ss::error_mode::error_string);
{
// mismatched quote
auto tup = c.convert<std::string, std::string, double, char>(
buff(R"( "just , some , "12.3","a" )"));
CHECK(!c.valid());
CHECK(!c.unterminated_quote());
}
{
// unterminated quote
auto tup = c.convert<std::string, std::string, double, std::string>(
buff(R"( ju\,st , "so,me" , 12.34 , "str""ings)"));
CHECK(!c.valid());
CHECK(c.unterminated_quote());
}
}

View File

@ -1,4 +1,5 @@
#pragma once #pragma once
#include <cstdlib>
#include <cstring> #include <cstring>
#ifdef CMAKE_GITHUB_CI #ifdef CMAKE_GITHUB_CI
@ -8,19 +9,35 @@
#endif #endif
class buffer { class buffer {
constexpr static auto buff_size = 1024; char* data_{nullptr};
char data_[buff_size];
public: public:
char* operator()(const char* data) { char* operator()(const char* data) {
memset(data_, '\0', buff_size); if (data_) {
delete[] data_;
}
data_ = new char[strlen(data) + 1];
strcpy(data_, data); strcpy(data_, data);
return data_; return data_;
} }
char* append(const char* data) { char* append(const char* data) {
strcat(data_, data); if (data_) {
return data_; char* new_data_ = new char[strlen(data_) + strlen(data) + 1];
strcpy(new_data_, data_);
strcat(new_data_, data);
delete[] data_;
data_ = new_data_;
return data_;
} else {
return operator()(data);
}
}
~buffer() {
if (data_) {
delete[] data_;
}
} }
}; };

View File

@ -668,3 +668,28 @@ TEST_CASE("testing unterminated quote") {
} }
} }
} }
TEST_CASE("testing invalid splits") {
ss::splitter<ss::quote<'"'>, ss::trim<' '>, ss::escape<'\\'>> s;
// empty delimiter
s.split(buff("some,random,strings"), "");
CHECK(!s.valid());
CHECK(!s.unterminated_quote());
// mismatched delimiter
s.split(buff(R"(some,"random,"strings")"));
CHECK(!s.valid());
CHECK(!s.unterminated_quote());
// unterminated quote
s.split(buff("some,random,\"strings"));
CHECK(!s.valid());
CHECK(s.unterminated_quote());
// invalid resplit
char new_line[] = "some";
auto a = s.resplit(new_line, strlen(new_line));
CHECK(!s.valid());
CHECK(!s.unterminated_quote());
}