diff --git a/include/ss/splitter.hpp b/include/ss/splitter.hpp index 9ad3b1b..917bdcb 100644 --- a/include/ss/splitter.hpp +++ b/include/ss/splitter.hpp @@ -135,11 +135,10 @@ public: split_input& resplit(line_ptr_type new_line, ssize_t new_size, const std::string& delimiter = default_delimiter) { - clear_error(); line_ = new_line; // resplitting, continue from last slice - if (!output_.empty()) { + if (!output_.empty() && unterminated_quote()) { const auto& last = std::prev(output_.end()); const auto [old_line, old_begin] = *last; size_t begin = old_begin - old_line - 1; @@ -152,7 +151,7 @@ public: return output_; } - line_ += begin; + begin_ = line_ + begin; } return split_impl_select_delim(delimiter); @@ -287,6 +286,7 @@ private: split_input& split_impl_select_delim( const std::string& delimiter = default_delimiter) { + clear_error(); switch (delimiter.size()) { case 0: set_error_empty_delimiter(); @@ -301,7 +301,10 @@ private: template split_input& split_impl(const Delim& delim) { state_ = state::begin; - begin_ = line_; + + if (output_.empty()) { + begin_ = line_; + } trim_if_enabled(begin_); diff --git a/test/test_helpers.hpp b/test/test_helpers.hpp index 87abd8a..903cde8 100644 --- a/test/test_helpers.hpp +++ b/test/test_helpers.hpp @@ -17,6 +17,11 @@ public: strcpy(data_, data); return data_; } + + char* append(const char* data) { + strcat(data_, data); + return data_; + } }; [[maybe_unused]] inline buffer buff; diff --git a/test/test_splitter.cpp b/test/test_splitter.cpp index 3411714..c2376ef 100644 --- a/test/test_splitter.cpp +++ b/test/test_splitter.cpp @@ -525,7 +525,7 @@ TEST_CASE("testing unterminated quote") { auto vec = expect_unterminated_quote(s, "\"just"); CHECK(vec.size() == 1); - char new_line[] = R"("just",strings)"; + auto new_line = buff.append(R"(",strings)"); vec = s.resplit(new_line, strlen(new_line)); CHECK(s.valid()); CHECK(!s.unterminated_quote()); @@ -539,7 +539,7 @@ TEST_CASE("testing unterminated quote") { std::vector expected{"just", "some", "just,some,\""}; CHECK(words(vec) == expected); - char new_line[] = R"(just,some,"random",strings)"; + auto new_line = buff.append(R"(",strings)"); vec = s.resplit(new_line, strlen(new_line)); CHECK(s.valid()); CHECK(!s.unterminated_quote()); @@ -547,17 +547,126 @@ TEST_CASE("testing unterminated quote") { CHECK(words(vec) == expected); } + { + ss::splitter> s; + auto vec = expect_unterminated_quote(s, R"("just","some","ran"")"); + std::vector expected{"just", "some", R"("just","some",")"}; + CHECK(words(vec) == expected); + + auto new_line = buff.append(R"(,dom","strings")"); + vec = s.resplit(new_line, strlen(new_line)); + CHECK(s.valid()); + CHECK(!s.unterminated_quote()); + expected = {"just", "some", "ran\",dom", "strings"}; + CHECK(words(vec) == expected); + } + { ss::splitter> s; auto vec = expect_unterminated_quote(s, R"("just","some","ran)"); std::vector expected{"just", "some", R"("just","some",")"}; CHECK(words(vec) == expected); - char new_line[] = R"("just","some","ran,dom","strings")"; - vec = s.resplit(new_line, strlen(new_line)); - CHECK(s.valid()); - CHECK(!s.unterminated_quote()); - expected = {"just", "some", "ran,dom", "strings"}; - CHECK(words(vec) == expected); + { + auto new_line = buff.append(R"(,dom)"); + vec = s.resplit(new_line, strlen(new_line)); + CHECK(!s.valid()); + CHECK(s.unterminated_quote()); + CHECK(words(vec) == expected); + } + + { + auto new_line = buff.append(R"(",strings)"); + vec = s.resplit(new_line, strlen(new_line)); + CHECK(s.valid()); + CHECK(!s.unterminated_quote()); + expected = {"just", "some", "ran,dom", "strings"}; + CHECK(words(vec) == expected); + } + } + + { + ss::splitter, ss::escape<'\\'>> s; + auto vec = expect_unterminated_quote(s, R"("just\"some","ra)"); + std::vector expected{"just\"some"}; + auto w = words(vec); + w.pop_back(); + CHECK(w == expected); + { + auto new_line = buff.append(R"(n,dom",str\"ings)"); + vec = s.resplit(new_line, strlen(new_line)); + CHECK(s.valid()); + CHECK(!s.unterminated_quote()); + expected = {"just\"some", "ran,dom", "str\"ings"}; + CHECK(words(vec) == expected); + } + } + + { + ss::splitter, ss::escape<'\\'>> s; + auto vec = expect_unterminated_quote(s, R"("just\"some","ra"")"); + std::vector expected{"just\"some"}; + auto w = words(vec); + w.pop_back(); + CHECK(w == expected); + { + auto new_line = buff.append(R"(n,dom",str\"ings)"); + vec = s.resplit(new_line, strlen(new_line)); + CHECK(s.valid()); + CHECK(!s.unterminated_quote()); + expected = {"just\"some", "ra\"n,dom", "str\"ings"}; + CHECK(words(vec) == expected); + } + } + + { + ss::splitter, ss::escape<'\\'>> s; + auto vec = expect_unterminated_quote(s, R"("just\"some","ra\")"); + std::vector expected{"just\"some"}; + auto w = words(vec); + w.pop_back(); + CHECK(w == expected); + { + auto new_line = buff.append(R"(n,dom",str\"ings)"); + vec = s.resplit(new_line, strlen(new_line)); + CHECK(s.valid()); + CHECK(!s.unterminated_quote()); + expected = {"just\"some", "ra\"n,dom", "str\"ings"}; + CHECK(words(vec) == expected); + } + } + + { + ss::splitter, ss::trim<' '>> s; + auto vec = expect_unterminated_quote(s, R"( "just" ,some, "ra )"); + std::vector expected{"just", "some"}; + auto w = words(vec); + w.pop_back(); + CHECK(w == expected); + { + auto new_line = buff.append(R"( n,dom" , strings )"); + vec = s.resplit(new_line, strlen(new_line)); + CHECK(s.valid()); + CHECK(!s.unterminated_quote()); + expected = {"just", "some", "ra n,dom", "strings"}; + CHECK(words(vec) == expected); + } + } + + { + ss::splitter, ss::trim<' '>, ss::escape<'\\'>> s; + auto vec = expect_unterminated_quote(s, R"( "ju\"st" ,some, "ra \")"); + std::vector expected{"ju\"st", "some"}; + auto w = words(vec); + w.pop_back(); + CHECK(w == expected); + { + auto new_line = buff.append(R"( n,dom" , strings )"); + vec = s.resplit(new_line, strlen(new_line)); + CHECK(s.valid()); + CHECK(!s.unterminated_quote()); + expected = {"ju\"st", "some", "ra \" n,dom", "strings"}; + CHECK(words(vec) == expected); + } } }