From b847699b5e5f67b45f291b94e739c3f9fdc3df0a Mon Sep 17 00:00:00 2001 From: ado Date: Sun, 7 Feb 2021 21:12:13 +0100 Subject: [PATCH 1/4] add/delete constructors and assign operators for the parser, refactor some code, update unit tests --- include/ss/parser.hpp | 376 ++++++++++++++++++++++------------------ include/ss/splitter.hpp | 4 +- test/test_parser.cpp | 3 + 3 files changed, 216 insertions(+), 167 deletions(-) diff --git a/include/ss/parser.hpp b/include/ss/parser.hpp index 11c78d6..c6783f3 100644 --- a/include/ss/parser.hpp +++ b/include/ss/parser.hpp @@ -17,10 +17,10 @@ class parser { struct none {}; public: - parser(const std::string& file_name, const std::string& delimiter) - : file_name_{file_name}, delim_{delimiter}, - file_{fopen(file_name_.c_str(), "rb")} { - if (file_) { + 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(); } else { set_error_file_not_open(); @@ -28,11 +28,12 @@ public: } } - ~parser() { - if (file_) { - fclose(file_); - } - } + parser(parser&& other) = default; + parser& operator=(parser&& other) = default; + + parser() = delete; + parser(const parser& other) = delete; + parser& operator=(const parser& other) = delete; bool valid() const { return (error_mode_ == error_mode::error_string) ? string_error_.empty() @@ -53,7 +54,7 @@ public: } bool ignore_next() { - return reader_.read(file_); + return reader_.read_next(); } template @@ -70,9 +71,9 @@ public: return {}; } - auto value = reader_.get_converter().template convert(); + auto value = reader_.converter_.template convert(); - if (!reader_.get_converter().valid()) { + if (!reader_.converter_.valid()) { set_error_invalid_conversion(); } @@ -161,8 +162,8 @@ public: no_void_validator_tup_t try_same() { parser_.clear_error(); auto value = - parser_.reader_.get_converter().template convert(); - if (!parser_.reader_.get_converter().valid()) { + parser_.reader_.converter_.template convert(); + if (!parser_.reader_.converter_.valid()) { parser_.set_error_invalid_conversion(); } return value; @@ -241,151 +242,6 @@ private: return {valid() ? std::move(value) : std::nullopt, *this}; } - //////////////// - // line reading - //////////////// - - class reader { - char* buffer_{nullptr}; - char* next_line_buffer_{nullptr}; - char* helper_buffer_{nullptr}; - - converter converter_; - converter next_line_converter_; - - size_t size_{0}; - size_t helper_size_{0}; - const std::string& delim_; - - bool crlf; - - bool escaped_eol(size_t size) { - const char* curr; - for (curr = next_line_buffer_ + size - 1; - curr >= next_line_buffer_ && - setup::escape::match(*curr); - --curr) { - } - return (next_line_buffer_ - curr + size) % 2 == 0; - } - - bool unterminated_quote() { - if (next_line_converter_.unterminated_quote()) { - return true; - } - return false; - } - - void undo_remove_eol(size_t& string_end) { - if (crlf) { - std::copy_n("\r\n\0", 3, next_line_buffer_ + string_end); - string_end += 2; - } else { - std::copy_n("\n\0", 2, next_line_buffer_ + string_end); - string_end += 1; - } - } - - size_t remove_eol(char*& buffer, size_t size) { - size_t new_size = size - 1; - if (size >= 2 && buffer[size - 2] == '\r') { - crlf = true; - new_size--; - } else { - crlf = false; - } - - buffer[new_size] = '\0'; - return new_size; - } - - void realloc_concat(char*& first, size_t& first_size, - const char* const second, size_t second_size) { - first = static_cast(realloc(static_cast(first), - first_size + second_size + 2)); - - std::copy_n(second, second_size + 1, first + first_size); - first_size += second_size; - } - - bool append_line(FILE* file, char*& dst_buffer, size_t& dst_size) { - undo_remove_eol(dst_size); - - ssize_t ssize = getline(&helper_buffer_, &helper_size_, file); - if (ssize == -1) { - return false; - } - - size_t size = remove_eol(helper_buffer_, ssize); - realloc_concat(dst_buffer, dst_size, helper_buffer_, size); - return true; - } - - public: - reader(const std::string& delimiter) : delim_{delimiter} { - } - - ~reader() { - free(buffer_); - free(next_line_buffer_); - free(helper_buffer_); - } - - bool read(FILE* file) { - ssize_t ssize = getline(&next_line_buffer_, &size_, file); - - if (ssize == -1) { - return false; - } - - size_t size = remove_eol(next_line_buffer_, ssize); - - if constexpr (setup::escape::enabled) { - while (escaped_eol(size)) { - if (!append_line(file, next_line_buffer_, size)) { - return false; - } - } - } - - next_line_converter_.split(next_line_buffer_, delim_); - - if constexpr (setup::quote::enabled) { - while (unterminated_quote()) { - if (!append_line(file, next_line_buffer_, size)) { - return false; - } - next_line_converter_.resplit(next_line_buffer_, size); - } - } - - return true; - } - - void set_error_mode(error_mode mode) { - converter_.set_error_mode(mode); - next_line_converter_.set_error_mode(mode); - } - - converter& get_converter() { - return converter_; - } - - const char* get_buffer() const { - return buffer_; - } - - void update() { - std::swap(buffer_, next_line_buffer_); - std::swap(converter_, next_line_converter_); - } - }; - - void read_line() { - eof_ = !reader_.read(file_); - ++line_number_; - } - //////////////// // error //////////////// @@ -422,26 +278,216 @@ private: .append(" ") .append(std::to_string(line_number_)) .append(": ") - .append(reader_.get_converter().error_msg()) + .append(reader_.converter_.error_msg()) .append(": \"") - .append(reader_.get_buffer()) + .append(reader_.buffer_) .append("\""); } else { bool_error_ = true; } } + //////////////// + // line reading + //////////////// + + void read_line() { + eof_ = !reader_.read_next(); + ++line_number_; + } + + class reader { + public: + reader(const std::string& file_name_, const std::string& delim) + : delim_{delim}, file_{fopen(file_name_.c_str(), "rb")} { + } + + 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_}, + helper_size_{other.helper_size_}, + delim_{std::move(other.delim_)}, + file_{other.file_}, + crlf_{other.crlf_} { + other.buffer_ = nullptr; + other.next_line_buffer_ = nullptr; + other.helper_buffer_ = nullptr; + other.file_ = nullptr; + } + + reader& operator=(reader&& other) { + if (this != &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_; + helper_size_ = other.helper_size_; + delim_ = std::move(other.delim_); + file_ = other.file_; + crlf_ = other.crlf_; + + other.buffer_ = nullptr; + other.next_line_buffer_ = nullptr; + other.helper_buffer_ = nullptr; + other.file_ = nullptr; + } + + return *this; + } + + ~reader() { + free(buffer_); + free(next_line_buffer_); + free(helper_buffer_); + + if (file_) { + fclose(file_); + } + } + + reader() = delete; + reader(const reader& other) = delete; + reader& operator=(const reader& other) = delete; + + bool read_next() { + ssize_t ssize = getline(&next_line_buffer_, &size_, file_); + + if (ssize == -1) { + return false; + } + + size_t size = remove_eol(next_line_buffer_, ssize); + + if constexpr (setup::escape::enabled) { + while (escaped_eol(size)) { + if (!append_line(next_line_buffer_, size)) { + return false; + } + } + } + + next_line_converter_.split(next_line_buffer_, delim_); + + if constexpr (setup::quote::enabled) { + while (unterminated_quote()) { + if (!append_line(next_line_buffer_, size)) { + return false; + } + next_line_converter_.resplit(next_line_buffer_, size); + } + } + + return true; + } + + void set_error_mode(error_mode mode) { + converter_.set_error_mode(mode); + next_line_converter_.set_error_mode(mode); + } + + void update() { + std::swap(buffer_, next_line_buffer_); + std::swap(converter_, next_line_converter_); + } + + private: + bool escaped_eol(size_t size) { + const char* curr; + for (curr = next_line_buffer_ + size - 1; + curr >= next_line_buffer_ && + setup::escape::match(*curr); + --curr) { + } + return (next_line_buffer_ - curr + size) % 2 == 0; + } + + bool unterminated_quote() { + if (next_line_converter_.unterminated_quote()) { + return true; + } + return false; + } + + void undo_remove_eol(size_t& string_end) { + if (crlf_) { + std::copy_n("\r\n\0", 3, next_line_buffer_ + string_end); + string_end += 2; + } else { + std::copy_n("\n\0", 2, next_line_buffer_ + string_end); + string_end += 1; + } + } + + size_t remove_eol(char*& buffer, size_t size) { + size_t new_size = size - 1; + if (size >= 2 && buffer[size - 2] == '\r') { + crlf_ = true; + new_size--; + } else { + crlf_ = false; + } + + buffer[new_size] = '\0'; + return new_size; + } + + void realloc_concat(char*& first, size_t& first_size, + const char* const second, size_t second_size) { + first = static_cast(realloc(static_cast(first), + first_size + second_size + 2)); + + std::copy_n(second, second_size + 1, first + first_size); + first_size += second_size; + } + + bool append_line(char*& dst_buffer, size_t& dst_size) { + undo_remove_eol(dst_size); + + ssize_t ssize = getline(&helper_buffer_, &helper_size_, file_); + if (ssize == -1) { + return false; + } + + size_t size = remove_eol(helper_buffer_, ssize); + realloc_concat(dst_buffer, dst_size, helper_buffer_, size); + return true; + } + + //////////////// + // members + //////////////// + public: + char* buffer_{nullptr}; + char* next_line_buffer_{nullptr}; + char* helper_buffer_{nullptr}; + + converter converter_; + converter next_line_converter_; + + size_t size_{0}; + size_t helper_size_{0}; + + std::string delim_; + FILE* file_{nullptr}; + + bool crlf_; + }; + //////////////// // members //////////////// - const std::string file_name_; - const std::string delim_; + std::string file_name_; std::string string_error_; bool bool_error_{false}; error_mode error_mode_{error_mode::error_bool}; - FILE* file_{nullptr}; - reader reader_{delim_}; + reader reader_; size_t line_number_{0}; bool eof_{false}; }; diff --git a/include/ss/splitter.hpp b/include/ss/splitter.hpp index 5794cd4..f72b1e8 100644 --- a/include/ss/splitter.hpp +++ b/include/ss/splitter.hpp @@ -10,8 +10,10 @@ namespace ss { +// TODO move to common using string_range = std::pair; using split_input = std::vector; +constexpr static auto default_delimiter = ","; // the error can be set inside a string, or a bool enum class error_mode { error_string, error_bool }; @@ -19,8 +21,6 @@ enum class error_mode { error_string, error_bool }; template class splitter { private: - constexpr static auto default_delimiter = ","; - using quote = typename setup::quote; using trim = typename setup::trim; using escape = typename setup::escape; diff --git a/test/test_parser.cpp b/test/test_parser.cpp index 896f0b9..ad1b844 100644 --- a/test/test_parser.cpp +++ b/test/test_parser.cpp @@ -56,6 +56,9 @@ TEST_CASE("testing parser") { make_and_write(f.name, data); { ss::parser p{f.name, ","}; + ss::parser p0{std::move(p)}; + p = std::move(p0); + p.set_error_mode(ss::error_mode::error_string); std::vector i; From c094ede5884a5d0d81501c4749b6300667ff77bb Mon Sep 17 00:00:00 2001 From: ado Date: Sun, 7 Feb 2021 21:24:41 +0100 Subject: [PATCH 2/4] update test names --- include/ss/parser.hpp | 1 - test/test_converter.cpp | 25 +++++++++++++------------ test/test_extractions.cpp | 14 +++++++------- test/test_parser.cpp | 14 +++++++------- test/test_splitter.cpp | 24 ++++++++++++------------ 5 files changed, 39 insertions(+), 39 deletions(-) diff --git a/include/ss/parser.hpp b/include/ss/parser.hpp index c6783f3..9f2d78d 100644 --- a/include/ss/parser.hpp +++ b/include/ss/parser.hpp @@ -9,7 +9,6 @@ #include #include -// TODO rule of 5-3-1 namespace ss { template diff --git a/test/test_converter.cpp b/test/test_converter.cpp index e8eec52..c33c25b 100644 --- a/test/test_converter.cpp +++ b/test/test_converter.cpp @@ -2,7 +2,7 @@ #include #include -TEST_CASE("testing split") { +TEST_CASE("converter test split") { ss::converter c; for (const auto& [s, expected, delim] : // clang-format off @@ -22,7 +22,7 @@ TEST_CASE("testing split") { } } -TEST_CASE("testing valid conversions") { +TEST_CASE("converter test valid conversions") { ss::converter c; { @@ -109,7 +109,7 @@ TEST_CASE("testing valid conversions") { } } -TEST_CASE("testing invalid conversions") { +TEST_CASE("converter test invalid conversions") { ss::converter c; c.convert(""); @@ -143,7 +143,7 @@ TEST_CASE("testing invalid conversions") { REQUIRE(!c.valid()); } -TEST_CASE("testing ss:ax restriction (all except)") { +TEST_CASE("converter test ss:ax restriction (all except)") { ss::converter c; c.convert>("0"); @@ -174,7 +174,7 @@ TEST_CASE("testing ss:ax restriction (all except)") { } } -TEST_CASE("testing ss:nx restriction (none except)") { +TEST_CASE("converter test ss:nx restriction (none except)") { ss::converter c; c.convert>("3"); @@ -208,7 +208,7 @@ TEST_CASE("testing ss:nx restriction (none except)") { } } -TEST_CASE("testing ss:ir restriction (in range)") { +TEST_CASE("converter test ss:ir restriction (in range)") { ss::converter c; c.convert>("3"); @@ -242,7 +242,7 @@ TEST_CASE("testing ss:ir restriction (in range)") { } } -TEST_CASE("testing ss:oor restriction (out of range)") { +TEST_CASE("converter test ss:oor restriction (out of range)") { ss::converter c; c.convert>("3"); @@ -289,7 +289,7 @@ inline bool ss::extract(const char* begin, const char* end, return true; } -TEST_CASE("testing ss:ne restriction (not empty)") { +TEST_CASE("converter test ss:ne restriction (not empty)") { ss::converter c; c.convert>(""); @@ -324,7 +324,8 @@ TEST_CASE("testing ss:ne restriction (not empty)") { } } -TEST_CASE("testing ss:lt ss::lte ss::gt ss::gte restriction (in range)") { +TEST_CASE( + "converter test ss:lt ss::lte ss::gt ss::gte restriction (in range)") { ss::converter c; c.convert>("3"); @@ -382,7 +383,7 @@ TEST_CASE("testing ss:lt ss::lte ss::gt ss::gte restriction (in range)") { } } -TEST_CASE("testing error mode") { +TEST_CASE("converter test error mode") { ss::converter c; c.convert("junk"); @@ -395,7 +396,7 @@ TEST_CASE("testing error mode") { CHECK(!c.error_msg().empty()); } -TEST_CASE("testing converter with quotes spacing and escaping") { +TEST_CASE("converter test converter with quotes spacing and escaping") { { ss::converter c; @@ -442,7 +443,7 @@ TEST_CASE("testing converter with quotes spacing and escaping") { } } -TEST_CASE("testing invalid split conversions") { +TEST_CASE("converter test invalid split conversions") { ss::converter, ss::trim<' '>, ss::quote<'"'>> c; c.set_error_mode(ss::error_mode::error_string); diff --git a/test/test_extractions.cpp b/test/test_extractions.cpp index 244b368..118a1a7 100644 --- a/test/test_extractions.cpp +++ b/test/test_extractions.cpp @@ -59,7 +59,7 @@ using ul = unsigned long; using ll = long long; using ull = unsigned long long; -TEST_CASE("testing extract functions for decimal values") { +TEST_CASE("extract test functions for decimal values") { CHECK_DECIMAL_CONVERSION(1234, short); CHECK_DECIMAL_CONVERSION(1234, us); CHECK_DECIMAL_CONVERSION(1234, int); @@ -77,7 +77,7 @@ TEST_CASE("testing extract functions for decimal values") { CHECK(!t.has_value()); \ } -TEST_CASE("testing extract functions for numbers with invalid inputs") { +TEST_CASE("extract test functions for numbers with invalid inputs") { // negative unsigned value CHECK_INVALID_CONVERSION("-1234", ul); @@ -125,7 +125,7 @@ TEST_CASE("testing extract functions for numbers with invalid inputs") { CHECK(!t.has_value()); \ } -TEST_CASE("testing extract functions for numbers with out of range inputs") { +TEST_CASE("extract test functions for numbers with out of range inputs") { CHECK_OUT_OF_RANGE_CONVERSION(short); CHECK_OUT_OF_RANGE_CONVERSION(us); CHECK_OUT_OF_RANGE_CONVERSION(int); @@ -136,7 +136,7 @@ TEST_CASE("testing extract functions for numbers with out of range inputs") { CHECK_OUT_OF_RANGE_CONVERSION(ull); } -TEST_CASE("testing extract functions for boolean values") { +TEST_CASE("extract test functions for boolean values") { for (const auto& [b, s] : {std::pair{true, "1"}, {false, "0"}, {true, "true"}, @@ -152,7 +152,7 @@ TEST_CASE("testing extract functions for boolean values") { } } -TEST_CASE("testing extract functions for char values") { +TEST_CASE("extract test functions for char values") { for (const auto& [c, s] : {std::pair{'a', "a"}, {'x', "x"}, {' ', " "}}) { char v; @@ -166,7 +166,7 @@ TEST_CASE("testing extract functions for char values") { } } -TEST_CASE("testing extract functions for std::optional") { +TEST_CASE("extract test functions for std::optional") { for (const auto& [i, s] : {std::pair, std::string>{1, "1"}, {69, "69"}, @@ -209,7 +209,7 @@ TEST_CASE("testing extract functions for std::optional") { #define CHECK_NOT_VARIANT(var, type) CHECK(!std::holds_alternative(var)); -TEST_CASE("testing extract functions for std::variant") { +TEST_CASE("extract test functions for std::variant") { { std::string s = "22"; { diff --git a/test/test_parser.cpp b/test/test_parser.cpp index ad1b844..5b040e6 100644 --- a/test/test_parser.cpp +++ b/test/test_parser.cpp @@ -49,7 +49,7 @@ static void make_and_write(const std::string& file_name, } } -TEST_CASE("testing parser") { +TEST_CASE("parser test various cases") { unique_file_name f; std::vector data = {{1, 2, "x"}, {3, 4, "y"}, {5, 6, "z"}, {7, 8, "u"}, {9, 10, "v"}, {11, 12, "w"}}; @@ -179,7 +179,7 @@ void expect_test_struct(const test_struct&) { } // various scenarios -TEST_CASE("testing composite conversion") { +TEST_CASE("parser test composite conversion") { unique_file_name f; { std::ofstream out{f.name}; @@ -436,7 +436,7 @@ struct xyz { } }; -TEST_CASE("testing the moving of parsed values") { +TEST_CASE("parser test the moving of parsed values") { size_t move_called_one_col; { @@ -482,7 +482,7 @@ TEST_CASE("testing the moving of parsed values") { } } -TEST_CASE("testing the moving of parsed composite values") { +TEST_CASE("parser test the moving of parsed composite values") { // to compile is enough return; ss::parser p{"", ""}; @@ -495,7 +495,7 @@ TEST_CASE("testing the moving of parsed composite values") { [](auto&, auto&, auto&) {}); } -TEST_CASE("testing error mode") { +TEST_CASE("parser test error mode") { unique_file_name f; { std::ofstream out{f.name}; @@ -525,7 +525,7 @@ std::string no_quote(const std::string& s) { return s; } -TEST_CASE("testing csv on multiple lines with quotes") { +TEST_CASE("parser test csv on multiple lines with quotes") { unique_file_name f; std::vector data = {{1, 2, "\"x\nx\nx\""}, {3, 4, "\"y\ny\ny\""}, {5, 6, "\"z\nz\""}, {7, 8, "\"u\"\"\""}, @@ -555,7 +555,7 @@ std::string no_escape(std::string& s) { return s; } -TEST_CASE("testing csv on multiple lines with escapes") { +TEST_CASE("parser test csv on multiple lines with escapes") { unique_file_name f; std::vector data = {{1, 2, "x\\\nx\\\nx"}, {3, 4, "y\\\ny\\\ny"}, {5, 6, "z\\\nz"}, {7, 8, "u"}, diff --git a/test/test_splitter.cpp b/test/test_splitter.cpp index 50ea6af..8054461 100644 --- a/test/test_splitter.cpp +++ b/test/test_splitter.cpp @@ -174,7 +174,7 @@ void test_combinations(matches_type& matches, std::vector delims) { } } -TEST_CASE("testing splitter no setup") { +TEST_CASE("splitter test with no setup") { { matches_type p{{{"x"}, "x"}, {{"\""}, "\""}, {{""}, ""}, {{"\n"}, "\n"}, @@ -184,7 +184,7 @@ TEST_CASE("testing splitter no setup") { } } -TEST_CASE("testing splitter quote") { +TEST_CASE("splitter test with quote") { case_type case1 = {R"("""")"}; case_type case2 = {R"("x""x")", R"(x"x)"}; case_type case3 = {R"("")", R"()"}; @@ -228,7 +228,7 @@ TEST_CASE("testing splitter quote") { } } -TEST_CASE("testing splitter trim") { +TEST_CASE("splitter test with trim") { auto guard = set_combinations_size(3); case_type case1 = spaced({R"(x)"}, " "); case_type case2 = spaced({R"(yy)"}, " "); @@ -258,7 +258,7 @@ TEST_CASE("testing splitter trim") { } } -TEST_CASE("testing splitter escape") { +TEST_CASE("splitter test with escape") { case_type case1 = {R"(x)", R"(\x)"}; case_type case2 = {R"(xx)", R"(\xx)", R"(x\x)", R"(\x\x)"}; case_type case3 = {R"(\\)"}; @@ -295,7 +295,7 @@ TEST_CASE("testing splitter escape") { } } -TEST_CASE("testing splitter quote and trim") { +TEST_CASE("splitter test with quote and trim") { auto guard = set_combinations_size(3); case_type case1 = spaced({R"("""")"}, " "); case_type case2 = spaced({R"("x""x")", R"(x"x)"}, " "); @@ -328,7 +328,7 @@ TEST_CASE("testing splitter quote and trim") { } } -TEST_CASE("testing splitter quote and escape") { +TEST_CASE("splitter test with quote and escape") { case_type case1 = {R"("\"")", R"(\")", R"("""")"}; case_type case2 = {R"("x\"x")", R"(x\"x)", R"(x"x)", R"("x""x")"}; case_type case3 = {R"("")", R"()"}; @@ -376,7 +376,7 @@ TEST_CASE("testing splitter quote and escape") { } } -TEST_CASE("testing splitter escape and trim") { +TEST_CASE("splitter test with escape and trim") { case_type case0 = spaced({R"(\ x\ )", R"(\ \x\ )"}, " "); case_type case1 = spaced({R"(x)", R"(\x)"}, " "); case_type case3 = spaced({R"(\\)"}, " "); @@ -413,7 +413,7 @@ TEST_CASE("testing splitter escape and trim") { } } -TEST_CASE("testing splitter quote and escape and trim") { +TEST_CASE("splitter test with quote and escape and trim") { auto guard = set_combinations_size(3); case_type case1 = spaced({R"("\"")", R"(\")", R"("""")"}, " "); case_type case2 = @@ -466,7 +466,7 @@ TEST_CASE("testing splitter quote and escape and trim") { } } -TEST_CASE("testing splitter constnes if quoting and escaping are disabled") { +TEST_CASE("splitter test constnes if quoting and escaping are disabled") { // to compile is enough return; const char* const line{}; @@ -476,7 +476,7 @@ TEST_CASE("testing splitter constnes if quoting and escaping are disabled") { s2.split(line); } -TEST_CASE("testing error mode") { +TEST_CASE("splitter test error mode") { { // empty delimiter @@ -529,7 +529,7 @@ public: }; } /* ss */ -TEST_CASE("testing unterminated quote") { +TEST_CASE("splitter test unterminated quote") { { ss::converter> c; auto& s = c.splitter; @@ -690,7 +690,7 @@ TEST_CASE("testing unterminated quote") { } } -TEST_CASE("testing invalid splits") { +TEST_CASE("splitter test invalid splits") { ss::converter, ss::trim<' '>, ss::escape<'\\'>> c; auto& s = c.splitter; From b626f78a7110630caaa59b558fbe419afb99a603 Mon Sep 17 00:00:00 2001 From: ado Date: Sun, 7 Feb 2021 21:29:12 +0100 Subject: [PATCH 3/4] make reader a struct --- include/ss/parser.hpp | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/include/ss/parser.hpp b/include/ss/parser.hpp index 9f2d78d..21811a1 100644 --- a/include/ss/parser.hpp +++ b/include/ss/parser.hpp @@ -295,8 +295,7 @@ private: ++line_number_; } - class reader { - public: + struct reader { reader(const std::string& file_name_, const std::string& delim) : delim_{delim}, file_{fopen(file_name_.c_str(), "rb")} { } @@ -304,14 +303,12 @@ private: reader(reader&& other) : buffer_{other.buffer_}, next_line_buffer_{other.next_line_buffer_}, - helper_buffer_{other.helper_buffer_}, - converter_{std::move(other.converter_)}, + helper_buffer_{other.helper_buffer_}, converter_{std::move( + other.converter_)}, next_line_converter_{std::move(other.next_line_converter_)}, size_{other.size_}, - helper_size_{other.helper_size_}, - delim_{std::move(other.delim_)}, - file_{other.file_}, - crlf_{other.crlf_} { + helper_size_{other.helper_size_}, delim_{std::move(other.delim_)}, + file_{other.file_}, crlf_{other.crlf_} { other.buffer_ = nullptr; other.next_line_buffer_ = nullptr; other.helper_buffer_ = nullptr; @@ -395,7 +392,6 @@ private: std::swap(converter_, next_line_converter_); } - private: bool escaped_eol(size_t size) { const char* curr; for (curr = next_line_buffer_ + size - 1; @@ -461,7 +457,6 @@ private: //////////////// // members //////////////// - public: char* buffer_{nullptr}; char* next_line_buffer_{nullptr}; char* helper_buffer_{nullptr}; From 6f2f4d91712b2cea54ba9c09f668c65aec6d6bf0 Mon Sep 17 00:00:00 2001 From: ado Date: Sun, 7 Feb 2021 22:12:23 +0100 Subject: [PATCH 4/4] fix out of range copy_n within the splitter --- include/ss/splitter.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/ss/splitter.hpp b/include/ss/splitter.hpp index f72b1e8..beafa4c 100644 --- a/include/ss/splitter.hpp +++ b/include/ss/splitter.hpp @@ -201,7 +201,7 @@ private: void shift_and_set_current() { if constexpr (!is_const_line) { if (escaped_ > 0) { - std::copy_n(curr_ + escaped_, end_ - curr_, curr_); + std::copy_n(curr_ + escaped_, end_ - curr_ - escaped_, curr_); curr_ = end_ - escaped_; return; }