diff --git a/include/ss/converter.hpp b/include/ss/converter.hpp index ea911fd..ca12fc4 100644 --- a/include/ss/converter.hpp +++ b/include/ss/converter.hpp @@ -236,8 +236,7 @@ private: if constexpr (string_error) { error_.clear(); error_.append(splitter_.error_msg()); - throw_if_throw_on_error(error_); - } else { + } else if constexpr (!throw_on_error) { error_ = true; } } @@ -247,28 +246,46 @@ private: error_.clear(); splitter_.set_error_unterminated_escape(); error_.append(splitter_.error_msg()); - throw_if_throw_on_error(error_); + } else if constexpr (throw_on_error) { + splitter_.set_error_unterminated_escape(); + } else { + error_ = true; + } + } + + void set_error_unterminated_quote() { + if constexpr (string_error) { + error_.clear(); + splitter_.set_error_unterminated_quote(); + error_.append(splitter_.error_msg()); + } else if constexpr (throw_on_error) { + splitter_.set_error_unterminated_quote(); } else { error_ = true; } } void set_error_multiline_limit_reached() { + constexpr static auto error_msg = "multiline limit reached"; + if constexpr (string_error) { error_.clear(); - error_.append("multiline limit reached"); - throw_if_throw_on_error(error_); + error_.append(error_msg); + } else if constexpr (throw_on_error) { + throw ss::exception{error_msg}; } else { error_ = true; } } void set_error_invalid_conversion(const string_range msg, size_t pos) { + constexpr static auto error_msg = "invalid conversion for parameter "; + if constexpr (string_error) { error_.clear(); - error_.append("invalid conversion for parameter ") - .append(error_sufix(msg, pos)); - throw_if_throw_on_error(error_); + error_.append(error_msg).append(error_sufix(msg, pos)); + } else if constexpr (throw_on_error) { + throw ss::exception{error_msg + error_sufix(msg, pos)}; } else { error_ = true; } @@ -279,20 +296,27 @@ private: if constexpr (string_error) { error_.clear(); error_.append(error).append(" ").append(error_sufix(msg, pos)); - throw_if_throw_on_error(error_); + } else if constexpr (throw_on_error) { + throw ss::exception{error + (" " + error_sufix(msg, pos))}; } else { error_ = true; } } void set_error_number_of_columns(size_t expected_pos, size_t pos) { + constexpr static auto error_msg1 = + "invalid number of columns, expected: "; + constexpr static auto error_msg2 = ", got: "; + if constexpr (string_error) { error_.clear(); - error_.append("invalid number of columns, expected: ") + error_.append(error_msg1) .append(std::to_string(expected_pos)) - .append(", got: ") + .append(error_msg2) .append(std::to_string(pos)); - throw_if_throw_on_error(error_); + } else if constexpr (throw_on_error) { + throw ss::exception{error_msg1 + std::to_string(expected_pos) + + error_msg2 + std::to_string(pos)}; } else { error_ = true; } @@ -300,25 +324,32 @@ private: void set_error_incompatible_mapping(size_t argument_size, size_t mapping_size) { + constexpr static auto error_msg1 = + "number of arguments does not match mapping, expected: "; + constexpr static auto error_msg2 = ", got: "; + if constexpr (string_error) { error_.clear(); - error_ - .append( - "number of arguments does not match mapping, expected: ") + error_.append(error_msg1) .append(std::to_string(mapping_size)) - .append(", got: ") + .append(error_msg2) .append(std::to_string(argument_size)); - throw_if_throw_on_error(error_); + } else if constexpr (throw_on_error) { + throw ss::exception{error_msg1 + std::to_string(mapping_size) + + error_msg2 + std::to_string(argument_size)}; } else { error_ = true; } } void set_error_invalid_mapping() { + constexpr static auto error_msg = "received empty mapping"; + if constexpr (string_error) { error_.clear(); - error_.append("received empty mapping"); - throw_if_throw_on_error(error_); + error_.append(error_msg); + } else if constexpr (throw_on_error) { + throw ss::exception{error_msg}; } else { error_ = true; } @@ -326,13 +357,19 @@ private: void set_error_mapping_out_of_range(size_t maximum_index, size_t number_of_columnts) { + constexpr static auto error_msg1 = "maximum index: "; + constexpr static auto error_msg2 = ", greater than number of columns: "; + if constexpr (string_error) { error_.clear(); - error_.append("maximum index: ") + error_.append(error_msg1) .append(std::to_string(maximum_index)) - .append(", greater then number of columns: ") + .append(error_msg2) .append(std::to_string(number_of_columnts)); - throw_if_throw_on_error(error_); + } else if constexpr (throw_on_error) { + throw ss::exception{error_msg1 + std::to_string(maximum_index) + + error_msg2 + + std::to_string(number_of_columnts)}; } else { error_ = true; } diff --git a/include/ss/exception.hpp b/include/ss/exception.hpp index 4122a1f..97c714a 100644 --- a/include/ss/exception.hpp +++ b/include/ss/exception.hpp @@ -20,11 +20,4 @@ public: } }; -template -void throw_if_throw_on_error(const std::string& msg) { - if constexpr (throw_on_error) { - throw ss::exception(msg); - } -} - } /* ss */ diff --git a/include/ss/parser.hpp b/include/ss/parser.hpp index 28062ef..1485324 100644 --- a/include/ss/parser.hpp +++ b/include/ss/parser.hpp @@ -87,8 +87,19 @@ public: template no_void_validator_tup_t get_next() { + if (!eof_) { + reader_.parse(); + } + reader_.update(); + if (!reader_.converter_.valid()) { + set_error_invalid_conversion(); + read_line(); + return {}; + } + clear_error(); + if (eof_) { set_error_eof_reached(); return {}; @@ -424,27 +435,36 @@ private: } void set_error_failed_check() { + constexpr static auto error_msg = " failed check"; + if constexpr (string_error) { - error_.append(file_name_).append(" failed check"); - throw_if_throw_on_error(error_); + error_.append(file_name_).append(error_msg); + } else if constexpr (throw_on_error) { + throw ss::exception{file_name_ + error_msg}; } else { error_ = true; } } void set_error_file_not_open() { + constexpr static auto error_msg = " could not be opened"; + if constexpr (string_error) { error_.append(file_name_).append(" could not be opened"); - throw_if_throw_on_error(error_); + } else if constexpr (throw_on_error) { + throw ss::exception{file_name_ + error_msg}; } else { error_ = true; } } void set_error_eof_reached() { + constexpr static auto error_msg = " reached end of file"; + if constexpr (string_error) { error_.append(file_name_).append(" reached end of file"); - throw_if_throw_on_error(error_); + } else if constexpr (throw_on_error) { + throw ss::exception{file_name_ + error_msg}; } else { error_ = true; } @@ -460,42 +480,45 @@ private: .append(": \"") .append(reader_.buffer_) .append("\""); - throw_if_throw_on_error(error_); - } else { + } else if constexpr (!throw_on_error) { error_ = true; } } void set_error_header_ignored() { + constexpr static auto error_msg = + ": \"the header row is ignored within the setup it cannot be " + "used\""; + if constexpr (string_error) { - error_.append(file_name_) - .append(": \"") - .append("the header row is ignored within the setup, it cannot " - "be used") - .append("\""); - throw_if_throw_on_error(error_); + error_.append(file_name_).append(error_msg); + } else if constexpr (throw_on_error) { + throw ss::exception{file_name_ + error_msg}; } else { error_ = true; } } void set_error_invalid_field(const std::string& field) { + constexpr static auto error_msg = + ": header does not contain given field: "; + if constexpr (string_error) { - error_.append(file_name_) - .append(": header does not contain given field: ") - .append(field); - throw_if_throw_on_error(error_); + error_.append(file_name_).append(error_msg).append(field); + } else if constexpr (throw_on_error) { + throw ss::exception{file_name_ + error_msg + field}; } else { error_ = true; } } void set_error_field_used_multiple_times(const std::string& field) { + constexpr static auto error_msg = ": given field used multiple times: "; + if constexpr (string_error) { - error_.append(file_name_) - .append(": given field used multiple times: ") - .append(field); - throw_if_throw_on_error(error_); + error_.append(file_name_).append(error_msg).append(field); + } else if constexpr (throw_on_error) { + throw ss::exception{file_name_ + error_msg + field}; } else { error_ = true; } @@ -514,13 +537,15 @@ private: : delim_{delim}, file_{fopen(file_name_.c_str(), "rb")} { } + // TODO update for size_ and ssize_ reader(reader&& other) : buffer_{other.buffer_}, next_line_buffer_{other.next_line_buffer_}, helper_buffer_{other.helper_buffer_}, converter_{std::move( other.converter_)}, next_line_converter_{std::move(other.next_line_converter_)}, - size_{other.size_}, next_line_size_{other.next_line_size_}, + buffer_size_{other.size_}, + next_line_buffer_size_{other.next_line_buffer_size_}, helper_size_{other.helper_size_}, delim_{std::move(other.delim_)}, file_{other.file_}, crlf_{other.crlf_}, line_number_{ other.line_number_} { @@ -537,8 +562,8 @@ private: helper_buffer_ = other.helper_buffer_; converter_ = std::move(other.converter_); next_line_converter_ = std::move(other.next_line_converter_); - size_ = other.size_; - next_line_size_ = other.next_line_size_; + buffer_size_ = other.size_; + next_line_buffer_size_ = other.next_line_buffer_size_; helper_size_ = other.helper_size_; delim_ = std::move(other.delim_); file_ = other.file_; @@ -568,16 +593,18 @@ private: reader(const reader& other) = delete; reader& operator=(const reader& other) = delete; + // read next line each time in order to set eof_ bool read_next() { - - ssize_t ssize; + next_line_converter_.clear_error(); + ssize_t ssize = 0; size_t size = 0; while (size == 0) { ++line_number_; - if (next_line_size_ > 0) { + if (next_line_buffer_size_ > 0) { next_line_buffer_[0] = '\0'; } - ssize = get_line(&next_line_buffer_, &next_line_size_, file_); + ssize = get_line(&next_line_buffer_, &next_line_buffer_size_, + file_); if (ssize == -1) { return false; @@ -590,17 +617,24 @@ private: } } + size_ = size; + ssize_ = ssize; + return true; + } + + void parse() { size_t limit = 0; if constexpr (escaped_multiline_enabled) { - while (escaped_eol(size)) { + while (escaped_eol(size_)) { if (multiline_limit_reached(limit)) { - return true; + return; } - if (!append_next_line_to_buffer(next_line_buffer_, size)) { - remove_eol(next_line_buffer_, ssize); + + if (!append_next_line_to_buffer(next_line_buffer_, size_)) { + // remove_eol(next_line_buffer_, ssize_); next_line_converter_.set_error_unterminated_escape(); - return true; + return; } } } @@ -610,38 +644,40 @@ private: if constexpr (quoted_multiline_enabled) { while (unterminated_quote()) { if (multiline_limit_reached(limit)) { - return true; + return; } - if (!append_next_line_to_buffer(next_line_buffer_, size)) { - remove_eol(next_line_buffer_, ssize); - return true; + + if (!append_next_line_to_buffer(next_line_buffer_, size_)) { + // remove_eol(next_line_buffer_, ssize_); + next_line_converter_.set_error_unterminated_quote(); + return; } if constexpr (escaped_multiline_enabled) { - while (escaped_eol(size)) { + while (escaped_eol(size_)) { if (multiline_limit_reached(limit)) { - return true; + return; } + if (!append_next_line_to_buffer(next_line_buffer_, - size)) { - remove_eol(next_line_buffer_, ssize); + size_)) { + // TODO not needed + // remove_eol(next_line_buffer_, ssize_); next_line_converter_ .set_error_unterminated_escape(); - return true; + return; } } } - next_line_converter_.resplit(next_line_buffer_, size); + next_line_converter_.resplit(next_line_buffer_, size_); } } - - return true; } void update() { std::swap(buffer_, next_line_buffer_); - std::swap(size_, next_line_size_); + std::swap(buffer_size_, next_line_buffer_size_); std::swap(converter_, next_line_converter_); } @@ -666,10 +702,7 @@ private: } bool unterminated_quote() { - if (next_line_converter_.unterminated_quote()) { - return true; - } - return false; + return next_line_converter_.unterminated_quote(); } void undo_remove_eol(char* buffer, size_t& string_end) { @@ -685,24 +718,29 @@ private: } } - size_t remove_eol(char*& buffer, size_t size) { - size_t new_size = size - 1; - if (size >= 2 && buffer[size - 2] == '\r') { + size_t remove_eol(char*& buffer, size_t ssize) { + size_t size = ssize - 1; + if (ssize >= 2 && buffer[ssize - 2] == '\r') { crlf_ = true; - new_size--; + size--; } else { crlf_ = false; } - buffer[new_size] = '\0'; - return new_size; + buffer[size] = '\0'; + return size; } void realloc_concat(char*& first, size_t& first_size, const char* const second, size_t second_size) { - next_line_size_ = first_size + second_size + 3; + // TODO make buffer_size an argument !!!!!! + next_line_buffer_size_ = first_size + second_size + 3; first = static_cast( - realloc(static_cast(first), next_line_size_)); + realloc(static_cast(first), next_line_buffer_size_)); + // TODO handle realloc + if (!first) { + exit(EXIT_FAILURE); + } std::copy_n(second, second_size + 1, first + first_size); first_size += second_size; } @@ -722,8 +760,9 @@ private: return true; } - std::vector get_next_row() const { + std::vector get_next_row() { std::vector next_row; + next_line_converter_.split(next_line_buffer_, delim_); auto& next_row_raw = next_line_converter_.splitter_.split_data_; for (const auto& [begin, end] : next_row_raw) { next_row.emplace_back(begin, end); @@ -741,8 +780,8 @@ private: converter converter_; converter next_line_converter_; - size_t size_{0}; - size_t next_line_size_{0}; + size_t buffer_size_{0}; + size_t next_line_buffer_size_{0}; size_t helper_size_{0}; std::string delim_; @@ -750,6 +789,10 @@ private: bool crlf_; size_t line_number_{0}; + + // TODO check if needed + size_t size_{0}; + ssize_t ssize_{0}; }; //////////////// diff --git a/include/ss/setup.hpp b/include/ss/setup.hpp index e80da45..ae2fc7f 100644 --- a/include/ss/setup.hpp +++ b/include/ss/setup.hpp @@ -112,7 +112,7 @@ struct get_matcher { "the same matcher is cannot" "be defined multiple times"); using type = std::conditional_t::value, T, - typename get_matcher::type>; + typename get_matcher::type>; }; template