diff --git a/src/csv_reporter.cc b/src/csv_reporter.cc index ed0f4fa0..08dad199 100644 --- a/src/csv_reporter.cc +++ b/src/csv_reporter.cc @@ -22,6 +22,8 @@ #include "string_util.h" #include "walltime.h" +// File format reference: http://edoceo.com/utilitas/csv-file-format. + namespace benchmark { bool CSVReporter::ReportContext(const Context& context) { @@ -71,7 +73,8 @@ void CSVReporter::PrintRunData(Run const& run) { cpu_time = cpu_time / static_cast(run.iterations); } - std::cout << run.benchmark_name << ","; + // Field with embedded commas must be delimited with double-quotes. + std::cout << "\"" << run.benchmark_name << "\","; std::cout << run.iterations << ","; std::cout << real_time << ","; std::cout << cpu_time << ","; @@ -85,7 +88,12 @@ void CSVReporter::PrintRunData(Run const& run) { } std::cout << ","; if (!run.report_label.empty()) { - std::cout << run.report_label; + // Field with embedded double-quote characters must be doubled and the field + // delimited with double-quotes. + std::string label = run.report_label; + ReplaceAll(&label, "\"", "\"\""); + + std::cout << "\"" << label << "\""; } std::cout << '\n'; } diff --git a/src/string_util.cc b/src/string_util.cc index ee1badc8..aeb9bc8a 100644 --- a/src/string_util.cc +++ b/src/string_util.cc @@ -154,4 +154,13 @@ std::string StringPrintF(const char* format, ...) return tmp; } +void ReplaceAll(std::string* str, const std::string& from, + const std::string& to) { + std::size_t start = 0; + while((start = str->find(from, start)) != std::string::npos) { + str->replace(start, from.length(), to); + start += to.length(); + } +} + } // end namespace benchmark diff --git a/src/string_util.h b/src/string_util.h index 6d35da2d..e83abbce 100644 --- a/src/string_util.h +++ b/src/string_util.h @@ -35,6 +35,9 @@ inline std::string StrCat(Args&&... args) return ss.str(); } +void ReplaceAll(std::string* str, const std::string& from, + const std::string& to); + } // end namespace benchmark #endif // BENCHMARK_STRING_UTIL_H_