diff options
Diffstat (limited to 'coding')
-rw-r--r-- | coding/CMakeLists.txt | 2 | ||||
-rw-r--r-- | coding/coding.pro | 2 | ||||
-rw-r--r-- | coding/coding_tests/CMakeLists.txt | 3 | ||||
-rw-r--r-- | coding/coding_tests/coding_tests.pro | 11 | ||||
-rw-r--r-- | coding/coding_tests/csv_reader_test.cpp | 73 | ||||
-rw-r--r-- | coding/csv_file_reader.cpp | 45 | ||||
-rw-r--r-- | coding/csv_file_reader.hpp | 28 |
7 files changed, 162 insertions, 2 deletions
diff --git a/coding/CMakeLists.txt b/coding/CMakeLists.txt index 246bb52086..4bf68cbf1f 100644 --- a/coding/CMakeLists.txt +++ b/coding/CMakeLists.txt @@ -24,6 +24,8 @@ set( compressed_bit_vector.cpp compressed_bit_vector.hpp constants.hpp + csv_file_reader.cpp + csv_file_reader.hpp dd_vector.hpp diff.hpp diff_patch_common.hpp diff --git a/coding/coding.pro b/coding/coding.pro index 6acb942504..3efe6e381b 100644 --- a/coding/coding.pro +++ b/coding/coding.pro @@ -13,6 +13,7 @@ include($$ROOT_DIR/common.pri) SOURCES += \ base64.cpp \ compressed_bit_vector.cpp \ + csv_file_reader.cpp \ file_container.cpp \ file_name_utils.cpp \ file_reader.cpp \ @@ -46,6 +47,7 @@ HEADERS += \ coder_util.hpp \ compressed_bit_vector.hpp \ constants.hpp \ + csv_file_reader.hpp \ dd_vector.hpp \ diff.hpp \ diff_patch_common.hpp \ diff --git a/coding/coding_tests/CMakeLists.txt b/coding/coding_tests/CMakeLists.txt index 5171fd00cf..7c4589c2c8 100644 --- a/coding/coding_tests/CMakeLists.txt +++ b/coding/coding_tests/CMakeLists.txt @@ -10,6 +10,7 @@ set( coder_test.hpp coder_util_test.cpp compressed_bit_vector_test.cpp + csv_reader_test.cpp dd_vector_test.cpp diff_test.cpp elias_coder_test.cpp @@ -49,4 +50,4 @@ set( omim_add_test(${PROJECT_NAME} ${SRC}) -omim_link_libraries(${PROJECT_NAME} coding base geometry minizip succinct ${LIBZ}) +omim_link_libraries(${PROJECT_NAME} platform_tests_support platform coding base geometry minizip succinct stats_client ${Qt5Widgets_LIBRARIES} ${LIBZ}) diff --git a/coding/coding_tests/coding_tests.pro b/coding/coding_tests/coding_tests.pro index 5e4ad89056..90b45fc6cf 100644 --- a/coding/coding_tests/coding_tests.pro +++ b/coding/coding_tests/coding_tests.pro @@ -6,7 +6,15 @@ TEMPLATE = app ROOT_DIR = ../.. -DEPENDENCIES = coding base geometry minizip succinct +DEPENDENCIES = platform_tests_support platform coding base geometry minizip succinct stats_client + +macx-* { + QT *= gui widgets # needed for QApplication with event loop, to test async events (downloader, etc.) + LIBS *= "-framework IOKit" "-framework QuartzCore" "-framework Cocoa" "-framework SystemConfiguration" +} +win32*|linux* { + QT *= network +} include($$ROOT_DIR/common.pri) @@ -18,6 +26,7 @@ SOURCES += ../../testing/testingmain.cpp \ bwt_coder_tests.cpp \ coder_util_test.cpp \ compressed_bit_vector_test.cpp \ + csv_reader_test.cpp \ dd_vector_test.cpp \ diff_test.cpp \ elias_coder_test.cpp \ diff --git a/coding/coding_tests/csv_reader_test.cpp b/coding/coding_tests/csv_reader_test.cpp new file mode 100644 index 0000000000..92a92ffd18 --- /dev/null +++ b/coding/coding_tests/csv_reader_test.cpp @@ -0,0 +1,73 @@ +#include "testing/testing.hpp" + +#include "coding/csv_file_reader.hpp" + +#include "platform/platform_tests_support/scoped_file.hpp" + +#include <string> +#include <vector> + +namespace +{ +std::string const kCSV1 = "a,b,c,d\ne,f,g h"; +std::string const kCSV2 = "a,b,cd a b, c"; +std::string const kCSV3 = ""; +} // namespace + +using coding::CSVReader; +using Row = std::vector<std::string>; +using File = std::vector<Row>; + +UNIT_TEST(CSVReaderSmoke) +{ + auto const fileName = "test.csv"; + platform::tests_support::ScopedFile sf(fileName, kCSV1); + auto const & filePath = sf.GetFullPath(); + + CSVReader reader; + reader.ReadFullFile(filePath, [](File const & file) { + TEST_EQUAL(file.size(), 1, ()); + TEST_EQUAL(file[0].size(), 3, ()); + Row const firstRow = {"e", "f", "g h"}; + TEST_EQUAL(file[0], firstRow, ()); + }); + + CSVReader::Params p; + p.m_shouldReadHeader = true; + reader.ReadFullFile(filePath, + [](File const & file) { + TEST_EQUAL(file.size(), 2, ()); + Row const headerRow = {"a", "b", "c", "d"}; + TEST_EQUAL(file[0], headerRow, ()); + }, + p); +} + +UNIT_TEST(CSVReaderCustomDelimiter) +{ + auto const fileName = "test.csv"; + platform::tests_support::ScopedFile sf(fileName, kCSV2); + auto const & filePath = sf.GetFullPath(); + + CSVReader reader; + CSVReader::Params p; + p.m_shouldReadHeader = true; + p.m_delimiter = ' '; + + reader.ReadLineByLine(filePath, + [](Row const & row) { + Row const firstRow = {"a,b,cd", "a", "b,", "c"}; + TEST_EQUAL(row, firstRow, ()); + }, + p); +} + +UNIT_TEST(CSVReaderEmptyFile) +{ + auto const fileName = "test.csv"; + platform::tests_support::ScopedFile sf(fileName, kCSV2); + auto const & filePath = sf.GetFullPath(); + + CSVReader reader; + reader.ReadFullFile(filePath, [](File const & file) { TEST_EQUAL(file.size(), 0, ()); }); +} diff --git a/coding/csv_file_reader.cpp b/coding/csv_file_reader.cpp new file mode 100644 index 0000000000..d5984d424b --- /dev/null +++ b/coding/csv_file_reader.cpp @@ -0,0 +1,45 @@ +#include "coding/csv_file_reader.hpp" + +#include "base/logging.hpp" +#include "base/string_utils.hpp" + +#include <fstream> +#include <sstream> + +namespace coding +{ +using namespace std; + +void CSVReader::ReadLineByLine(string const & filePath, LineByLineCallback const & fn, + Params const & params) const +{ + ifstream file(filePath); + if (!file) + { + LOG(LERROR, ("File not found at path: ", filePath)); + return; + } + + string line; + bool readFirstLine = params.m_shouldReadHeader; + while (getline(file, line)) + { + vector<string> splitLine; + strings::ParseCSVRow(line, params.m_delimiter, splitLine); + if (!readFirstLine) + { + readFirstLine = true; + continue; + } + fn(splitLine); + } +} + +void CSVReader::ReadFullFile(string const & filePath, FullFileCallback const & fn, + Params const & params) const +{ + vector<vector<string>> file; + ReadLineByLine(filePath, [&file](vector<string> const & row) { file.emplace_back(row); }, params); + fn(file); +} +} // namespace coding diff --git a/coding/csv_file_reader.hpp b/coding/csv_file_reader.hpp new file mode 100644 index 0000000000..f225942ad5 --- /dev/null +++ b/coding/csv_file_reader.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include <functional> +#include <string> +#include <vector> + +namespace coding +{ +class CSVReader +{ +public: + struct Params + { + Params(){}; + bool m_shouldReadHeader = false; + char m_delimiter = ','; + }; + + using LineByLineCallback = std::function<void(std::vector<std::string> const & line)>; + using FullFileCallback = std::function<void(std::vector<std::vector<std::string>> const & file)>; + + void ReadLineByLine(std::string const & filePath, LineByLineCallback const & fn, + Params const & params = {}) const; + + void ReadFullFile(std::string const & filePath, FullFileCallback const & fn, + Params const & params = {}) const; +}; +} // namespace coding |