diff --git a/include/utl/parser/csv.h b/include/utl/parser/csv.h index 4558e0f..a24c66a 100644 --- a/include/utl/parser/csv.h +++ b/include/utl/parser/csv.h @@ -53,6 +53,17 @@ inline void parse_column(cstr& s, T& arg) { adjust_for_quote + adjust_for_cr)); } +inline void unescape_quoted_string(std::string& arg) { + auto found_at = 0; + while ((found_at = arg.find('"', found_at)) != -1) { + if (found_at < static_cast(arg.size()) - 1 && + arg[found_at + 1] == '"') { + arg.erase(found_at, 1); + ++found_at; // Skip following character + } + } +} + template ::value, int> = 0> inline void parse_value(cstr& s, IntType& arg) { @@ -71,8 +82,13 @@ inline void parse_value(cstr& s, bool& arg) { s = s.skip_whitespace_front(); parse_arg(s, arg); } -inline void parse_value(cstr& s, std::string& arg) { parse_arg(s, arg); } -inline void parse_value(cstr& s, cstr& arg) { parse_arg(s, arg); } +inline void parse_value(cstr& s, std::string& arg) { + parse_arg(s, arg); + unescape_quoted_string(arg); +} +inline void parse_value(cstr& s, cstr& arg) { + parse_arg(s, arg); +} template typename std::enable_if::type read( diff --git a/include/utl/parser/csv_range.h b/include/utl/parser/csv_range.h index 8714990..1d25042 100644 --- a/include/utl/parser/csv_range.h +++ b/include/utl/parser/csv_range.h @@ -94,7 +94,7 @@ struct csv_range : public LineRange { T t{}; cista::for_each_field(t, [&, i = 0u](auto& f) mutable { if (row[i]) { - parse_arg(row[i], f.val()); + parse_value(row[i], f.val()); } ++i; }); diff --git a/test/parser/pipe_csv_test.cc b/test/parser/pipe_csv_test.cc index b0d3509..beb0ffd 100644 --- a/test/parser/pipe_csv_test.cc +++ b/test/parser/pipe_csv_test.cc @@ -101,7 +101,7 @@ TEST(pipe_csv, csv_escaped_string) { | vec(); ASSERT_TRUE(result.size() == 1); - EXPECT_TRUE(result[0].foo_.val() == R"([""asd"", ""bsd""])"); + EXPECT_TRUE(result[0].foo_.val() == R"(["asd", "bsd"])"); EXPECT_TRUE(result[0].bar_.val() == "asd"); EXPECT_TRUE(result[0].baz_.val() == "xxx"); }