From bfd4a908dc4cc3f92dda031bbd3572e653019483 Mon Sep 17 00:00:00 2001 From: Antony Cherepanov Date: Fri, 23 Apr 2021 08:46:38 +0300 Subject: [PATCH] Switch to Qt6 (#69) * Now library supports only Qt6. We've updated interface of the main classes in compliance with Qt6: * QList instead of QStringList * QStringConverter::Encoding instead of QTextCodec * qsizetype instead of int * Simplification - no more PIMPL classes * Switch to C++11/14/17 * Minor code style changes * Move all CI jobs to Appveyor New contributors: Bogdan Cristea (https://github.com/cristeab), Markus Krause (https://github.com/markusdd) --- .travis.yml | 94 ------- CMakeLists.txt | 15 +- README.md | 175 ++++++------ appveyor.yml | 76 ++++-- include/qtcsv/abstractdata.h | 16 +- include/qtcsv/qtcsv_global.h | 12 +- include/qtcsv/reader.h | 51 ++-- include/qtcsv/stringdata.h | 57 ++-- include/qtcsv/variantdata.h | 64 +++-- include/qtcsv/writer.h | 34 ++- qtcsv.pro | 5 +- sources/contentiterator.cpp | 62 ++--- sources/contentiterator.h | 32 ++- sources/filechecker.h | 19 +- sources/reader.cpp | 353 ++++++++++--------------- sources/stringdata.cpp | 121 +++------ sources/symbols.h | 3 +- sources/variantdata.cpp | 178 +++++-------- sources/writer.cpp | 122 ++++----- tests/CMakeLists.txt | 13 +- tests/testreader.cpp | 496 +++++++++++++++-------------------- tests/testreader.h | 5 +- tests/teststringdata.cpp | 120 ++++----- tests/teststringdata.h | 5 +- tests/testvariantdata.cpp | 91 +++---- tests/testvariantdata.h | 5 +- tests/testwriter.cpp | 356 +++++++++++-------------- tests/testwriter.h | 7 +- tests/tst_testmain.cpp | 10 +- 29 files changed, 1055 insertions(+), 1542 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 00e2092..0000000 --- a/.travis.yml +++ /dev/null @@ -1,94 +0,0 @@ -language: cpp - -jobs: - include: - - os: linux - dist: xenial - compiler: gcc - env: - - QT_BASE=56 - - os: linux - dist: xenial - compiler: gcc - env: - - QT_BASE=56 USE_CMAKE=true - - os: linux - dist: xenial - compiler: gcc - env: - - QT_BASE=59 USE_CMAKE=true - - os: linux - dist: focal - compiler: gcc - env: - - QT_BASE=512 USE_CMAKE=true - - os: linux - dist: focal - compiler: gcc - env: - - QT_BASE=515 - - os: linux - dist: focal - compiler: gcc - env: - - QT_BASE=515 USE_CMAKE=true - -before_install: - - if [ "$QT_BASE" = "56" ]; then sudo add-apt-repository ppa:beineri/opt-qt563-xenial -y; fi - - if [ "$QT_BASE" = "59" ]; then sudo add-apt-repository ppa:beineri/opt-qt597-xenial -y; fi - - if [ "$QT_BASE" = "512" ]; then sudo add-apt-repository ppa:beineri/opt-qt-5.12.10-focal -y; fi - - if [ "$QT_BASE" = "515" ]; then sudo add-apt-repository ppa:beineri/opt-qt-5.15.2-focal -y; fi - - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get update -qq; fi - -install: - - if [ "$QT_BASE" = "56" ]; then sudo apt-get install -qq qt56base; source /opt/qt56/bin/qt56-env.sh; fi - - if [ "$QT_BASE" = "59" ]; then sudo apt-get install -qq qt59base; source /opt/qt59/bin/qt59-env.sh; fi - - if [ "$QT_BASE" = "512" ]; then sudo apt-get install -qq qt512base; source /opt/qt512/bin/qt512-env.sh; fi - - if [ "$QT_BASE" = "515" ]; then sudo apt-get install -qq qt515base; source /opt/qt515/bin/qt515-env.sh; fi - -script: - # build library and tests, install library - - mkdir ./build && cd ./build - - if [ "$USE_CMAKE" = "true" ]; then - cmake --version; - cmake -DCMAKE_BUILD_TYPE=Release ..; - make; - sudo make install; - - cd ./tests; - else - qmake -v; - qmake ../qtcsv.pro CONFIG+=release; - make; - sudo make install; - - mkdir ./tests && cd ./tests; - qmake ../../tests/tests.pro CONFIG+=release LIBS+=-L../; - make; - fi - - # run tests - - export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/../ - - chmod 777 qtcsv_tests - - ./qtcsv_tests - - # check if library was properly installed - - if [ "$TRAVIS_OS_NAME" = "linux" ]; then - echo "Check installation"; - if [ -f /usr/local/lib/libqtcsv.so ]; then - ls -la /usr/local/lib | grep qtcsv; - else - echo "File '/usr/local/lib/libqtcsv.so' do not exist"; - exit 1; - fi - - if [ -d /usr/local/include/qtcsv ]; then - ls -la /usr/local/include/qtcsv; - else - echo "Dir '/usr/local/include/qtcsv' do not exist"; - exit 1; - fi - fi - -notifications: - email: true diff --git a/CMakeLists.txt b/CMakeLists.txt index 04037fd..866f6d0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,23 +1,14 @@ cmake_minimum_required (VERSION 3.0) -project (qtcsv VERSION 1.6.0 LANGUAGES CXX) +project (qtcsv VERSION 1.7.0 LANGUAGES CXX) # set options option(STATIC_LIB "build as static lib if ON, otherwise build shared lib" OFF) -option(USE_QT4 "builds against Qt4 if ON, otherwise builds against Qt5" OFF) option(BUILD_TESTS "build tests" ON) # find qt package -if(USE_QT4) - find_package(Qt4 REQUIRED) - set(QT_CORE_TARGET Qt4::QtCore) -else() - # if cmake failed to find Qt5Core configuration file, set path manually: - #list(APPEND CMAKE_PREFIX_PATH "/path/to/Qt/lib/cmake/Qt5Core/") - - find_package(Qt5Core REQUIRED) - set(QT_CORE_TARGET Qt5::Core) -endif(USE_QT4) +find_package(Qt6 COMPONENTS Core REQUIRED) +set(QT_CORE_TARGET Qt6::Core) # instruct CMake to run moc automatically when needed. set(CMAKE_AUTOMOC ON) diff --git a/README.md b/README.md index 9011fbc..5dbac9f 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,17 @@ # qtcsv -[![Build Status](https://travis-ci.org/iamantony/qtcsv.svg?branch=master)](https://travis-ci.org/iamantony/qtcsv) [![Build status](https://ci.appveyor.com/api/projects/status/7uv7ghs9uexf08bv/branch/master?svg=true)](https://ci.appveyor.com/project/iamantony/qtcsv/branch/master) +[![Build status](https://ci.appveyor.com/api/projects/status/7uv7ghs9uexf08bv/branch/master?svg=true)](https://ci.appveyor.com/project/iamantony/qtcsv/branch/master) -Small easy-to-use library for reading and writing [csv-files][csvwiki] -in Qt. +Small easy-to-use library for reading and writing [csv-files][csvwiki] in Qt. + +Qt suppport: +- Qt6: branch `master` (you're here) +- Qt4 and Qt5: branch `qt4_qt5` Tested on: -- Ubuntu with gcc, Qt 4.8 - 5.15 -- Windows with MinGW, Qt 5.3 - 5.15 -- OS X with clang, Qt 4.8 - 5.15 +- Ubuntu with gcc, Qt6 +- Windows with MinGW, Qt6 +- OS X with clang, Qt6 ## Table of contents * [1. Quick Example](#1-quick-example) @@ -42,7 +45,7 @@ Tested on: ```cpp #include -#include +#include #include #include @@ -53,7 +56,7 @@ Tested on: int main() { // prepare data that you want to save to csv-file - QStringList strList; + QList strList; strList << "one" << "two" << "three"; QtCSV::StringData strData; @@ -62,12 +65,12 @@ int main() strData << strList << "this is the last row"; // write to file - QString filePath = QDir::currentPath() + "/test.csv"; + const auto filePath = QDir::currentPath() + "/test.csv"; QtCSV::Writer::write(filePath, strData); // read data from file - QList readData = QtCSV::Reader::readToList(filePath); - for (int i = 0; i < readData.size(); ++i) + const auto readData = QtCSV::Reader::readToList(filePath); + for (auto i = 0; i < readData.size(); ++i) { qDebug() << readData.at(i).join(","); } @@ -83,8 +86,7 @@ Library could be separated into three parts: **_Reader_**, ### 2.1 Containers -*qtcsv* library can work with standard Qt containers (like QList and -QStringList) and special data containers. +*qtcsv* library can work with standard Qt containers (like QList) and special data containers. #### 2.1.1 AbstractData @@ -92,18 +94,16 @@ QStringList) and special data containers. interface for a class of special data containers. ```cpp -class AbstractData -{ +class AbstractData { public: - explicit AbstractData() {} - virtual ~AbstractData() {} + virtual ~AbstractData() = default; virtual void addEmptyRow() = 0; - virtual void addRow(const QStringList& values) = 0; + virtual void addRow(const QList& values) = 0; virtual void clear() = 0; virtual bool isEmpty() const = 0; - virtual int rowCount() const = 0; - virtual QStringList rowValues(const int& row) const = 0; + virtual qsizetype rowCount() const = 0; + virtual QList rowValues(qsizetype row) const = 0; }; ``` @@ -132,17 +132,19 @@ Use **[_Reader_][reader]** class to read csv-files / csv-data. Let's see it's fu #### 2.2.1 Reader functions -1. Read data to **_QList\_** +1. Read data to **_QList\\>_** ```cpp - QList readToList(const QString& filePath, - const QString& separator, - const QString& textDelimiter, - QTextCodec* codec); + QList> readToList( + const QString& filePath, + const QString& separator = QString(","), + const QString& textDelimiter = QString("\""), + QStringConverter::Encoding codec = QStringConverter::Utf8); - QList readToList(QIODevice& ioDevice, - const QString& separator, - const QString& textDelimiter, - QTextCodec* codec); + QList> readToList( + QIODevice& ioDevice, + const QString& separator = QString(","), + const QString& textDelimiter = QString("\""), + QStringConverter::Encoding codec = QStringConverter::Utf8); ``` - *filePath* - string with absolute path to existent csv-file @@ -152,40 +154,42 @@ Use **[_Reader_][reader]** class to read csv-files / csv-data. Let's see it's fu in a row (by default it is comma - ","); - *textDelimiter* (optional) - text delimiter symbol that encloses each element in a row (by default it is double quoute - "); - - *codec* (optional) - pointer to the codec object that will be used + - *codec* (optional) - codec type that will be used to read data from the file (by default it is UTF-8 codec). - As a result function will return **_QList\_** that holds content + As a result function will return **_QList\\>_** that holds content of the file / IO Device. Size of it will be equal to the number of rows - in csv-data source. Each **_QStringList_** will contain elements of the + in csv-data source. Each **_QList\_** will contain elements of the corresponding row. On error these functions will return empty list. 2. Read data to **_AbstractData_**-based container ```cpp - bool readToData(const QString& filePath, - AbstractData& data, - const QString& separator, - const QString& textDelimiter, - QTextCodec* codec); + bool readToData( + const QString& filePath, + AbstractData& data, + const QString& separator = QString(","), + const QString& textDelimiter = QString("\""), + QStringConverter::Encoding codec = QStringConverter::Utf8); - bool readToData(QIODevice& ioDevice, - AbstractData& data, - const QString& separator, - const QString& textDelimiter, - QTextCodec* codec); + bool readToData( + QIODevice& ioDevice, + AbstractData& data, + const QString& separator = QString(","), + const QString& textDelimiter = QString("\""), + QStringConverter::Encoding codec = QStringConverter::Utf8); ``` - Second function is a little more advanced and, I hope, a little more useful. + These functions are little more advanced and, I hope, a little more useful. - *filePath* - string with absolute path to existent csv-file; - *ioDevice* - IO Device that contains csv-formatted data; - *data* - reference to **_AbstractData_**-based class object; - *separator* (optional) - delimiter symbol; - *textDelimiter* (optional) - text delimiter symbol; - - *codec* (optional) - pointer to the codec object. + - *codec* (optional) - codec type. - Function will save content of the file / IO Device in *data* object using virtual - function **_AbstractData::addRow(QStringList)_**. Elements of csv-data will be + Functions will save content of the file / IO Device in *data* object using virtual + function **_AbstractData::addRow(QList\)_**. Elements of csv-data will be saved as strings in objects of **_StringData_** / **_VariantData_**. If you would like to convert row elements to the target types on-the-fly during @@ -193,17 +197,19 @@ Use **[_Reader_][reader]** class to read csv-files / csv-data. Let's see it's fu 3. Read data and process it line-by-line by **_AbstractProcessor_**-based processor ```cpp - bool readToProcessor(const QString& filePath, - AbstractProcessor& processor, - const QString& separator, - const QString& textDelimiter, - QTextCodec* codec); + bool readToProcessor( + const QString& filePath, + AbstractProcessor& processor, + const QString& separator = QString(","), + const QString& textDelimiter = QString("\""), + QStringConverter::Encoding codec = QStringConverter::Utf8); - bool readToProcessor(QIODevice& ioDevice, - AbstractProcessor& processor, - const QString& separator, - const QString& textDelimiter, - QTextCodec* codec); + bool readToProcessor( + QIODevice& ioDevice, + AbstractProcessor& processor, + const QString& separator = QString(","), + const QString& textDelimiter = QString("\""), + QStringConverter::Encoding codec = QStringConverter::Utf8); ``` - *filePath* - string with absolute path to existent csv-file; @@ -211,7 +217,7 @@ Use **[_Reader_][reader]** class to read csv-files / csv-data. Let's see it's fu - *processor* - reference to **_AbstractProcessor_**-based class object; - *separator* (optional) - delimiter symbol; - *textDelimiter* (optional) - text delimiter symbol; - - *codec* (optional) - pointer to the codec object. + - *codec* (optional) - codec type. This function will read csv-data from file / IO Device line-by-line and pass data to *processor* object. @@ -224,11 +230,9 @@ Use **[_Reader_][reader]** class to read csv-files / csv-data. Let's see it's fu class AbstractProcessor { public: - explicit AbstractProcessor() {} - virtual ~AbstractProcessor() {} - - virtual void preProcessRawLine(QString& line) { } - virtual bool processRowElements(const QStringList& elements) = 0; + virtual ~AbstractProcessor() = default; + virtual void preProcessRawLine(QString& /*editable_line*/) {} + virtual bool processRowElements(const QList& elements) = 0; }; ``` @@ -238,7 +242,7 @@ new line to processor's method **_preProcessRawLine(QString&)_**. In this method you can edit the line - replace values, remove sensitive information and so on. After that **_Reader_** parses elements of the row and passes them to processor's -method **_processRowElements(QStringList)_**. At that step you can do whatever +method **_processRowElements(QList\)_**. At that step you can do whatever you want with row elements - convert/edit/save/filter the elements. Please check out **_ReadToListProcessor_** class (defined in [reader.cpp][reader-cpp]) as an example of such processor. @@ -248,22 +252,24 @@ such processor. Use **[_Writer_][writer]** class to write csv-data to files / IO Devices. ```cpp -bool write(const QString& filePath, - const AbstractData& data, - const QString& separator, - const QString& textDelimiter, - const WriteMode& mode, - const QStringList& header, - const QStringList& footer, - QTextCodec* codec); +bool write( + const QString& filePath, + const AbstractData& data, + const QString& separator = QString(","), + const QString& textDelimiter = QString("\""), + WriteMode mode = WriteMode::REWRITE, + const QList& header = {}, + const QList& footer = {}, + QStringConverter::Encoding codec = QStringConverter::Utf8); -bool write(QIODevice& ioDevice, - const AbstractData& data, - const QString& separator, - const QString& textDelimiter, - const QStringList& header, - const QStringList& footer, - QTextCodec* codec); +bool write( + QIODevice& ioDevice, + const AbstractData& data, + const QString& separator = QString(","), + const QString& textDelimiter = QString("\""), + const QList& header = {}, + const QList& footer = {}, + QStringConverter::Encoding codec = QStringConverter::Utf8); ``` - *filePath* - string with absolute path to csv-file (new or existent); @@ -280,7 +286,7 @@ information will be appended to the end of the file. By default mode is set to **_WriteMode::REWRITE_**. - *header* (optional) - strings that will be written as the first row; - *footer* (optional) - strings that will be written at the last row; -- *codec* (optional) - pointer to the codec object that will be used +- *codec* (optional) - codec type that will be used in write operations (by default it is UTF-8 codec). **_Writer_** uses *CRLF* as line ending symbols in accordance with [standard][rfc]. @@ -290,8 +296,7 @@ empty string as text delimiter symbol). ## 3. Requirements -Qt 4.8 - 5.15, only core/base modules. -It is quite possible that library would work with older Qt versions. +Qt6, only core/base modules. ## 4. Build @@ -337,7 +342,7 @@ make #### 4.2.1 Prebuild step on Windows -If you going to build *qtcsv* library on Windows with MinGW, first of all [check that your PATH variable][path_var] contains paths to _Qt_ and _MinGW_ toolsets. For example, you have installed Qt 5.3 into _C:\Qt_. Then Qt binaries and libraries will be in folder _C:\Qt\5.3\mingw482_32\bin_ and MinGW binaries will be in _C:\Qt\Tools\mingw482_32\bin_. Add these paths to the PATH variable so that Windows would know where to look for _qmake_ and _make_ binaries. +If you going to build *qtcsv* library on Windows with MinGW, first of all [check that your PATH variable][path_var] contains paths to _Qt_ and _MinGW_ toolsets. #### 4.2.2 Using qmake @@ -440,7 +445,7 @@ proper csv-file. ## 9. Creators Author: [Antony Cherepanov][mypage] (antony.cherepanov@gmail.com) -Contributors: [Patrizio "pbek" Bekerle][pbek], [Furkan "Furkanzmc" Üzümcü][Furkanzmc], [Martin "schulmar" Schulze][schulmar], [cguentherTUChemnitz][cguentherTUChemnitz], [David Jung][David_Jung], [Nicu Tofan][TNick], [Florian Apolloner][apollo13], [Michael Pollind][pollend], [Kuba Ober][KubaO], [Akram Abdeslem Chaima][gakramx] +Contributors: [Patrizio "pbek" Bekerle][pbek], [Furkan "Furkanzmc" Üzümcü][Furkanzmc], [Martin "schulmar" Schulze][schulmar], [cguentherTUChemnitz][cguentherTUChemnitz], [David Jung][David_Jung], [Nicu Tofan][TNick], [Florian Apolloner][apollo13], [Michael Pollind][pollend], [Kuba Ober][KubaO], [Akram Abdeslem Chaima][gakramx], [Bogdan Cristea][cristeab], [Markus Krause][markusdd] [csvwiki]: http://en.wikipedia.org/wiki/Comma-separated_values [reader]: https://github.com/iamantony/qtcsv/blob/master/include/qtcsv/reader.h @@ -450,7 +455,7 @@ Contributors: [Patrizio "pbek" Bekerle][pbek], [Furkan "Furkanzmc" Üzümcü][Fu [strdata]: https://github.com/iamantony/qtcsv/blob/master/include/qtcsv/stringdata.h [vardata]: https://github.com/iamantony/qtcsv/blob/master/include/qtcsv/variantdata.h [qtcsv-pro]: https://github.com/iamantony/qtcsv/blob/master/qtcsv.pro -[install-files]: http://doc.qt.io/qt-5/qmake-advanced-usage.html#installing-files +[install-files]: https://doc.qt.io/qt-6/qmake-advanced-usage.html#installing-files [qtcsv-example]: https://github.com/iamantony/qtcsv-example [rfc]: http://tools.ietf.org/pdf/rfc4180.pdf [path_var]: http://superuser.com/questions/284342/what-are-path-and-other-environment-variables-and-how-can-i-set-or-use-them @@ -466,3 +471,5 @@ Contributors: [Patrizio "pbek" Bekerle][pbek], [Furkan "Furkanzmc" Üzümcü][Fu [pollend]: https://github.com/pollend [KubaO]: https://github.com/KubaO [gakramx]: https://github.com/gakramx +[cristeab]: https://github.com/cristeab +[markusdd]: https://github.com/markusdd diff --git a/appveyor.yml b/appveyor.yml index 7d7dfe5..f9a42d5 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,40 +1,58 @@ version: "{build}" init: -- git config --global core.autocrlf input + - git config --global core.autocrlf input environment: matrix: - - QT5: C:\Qt\5.6.3\mingw49_32 - MINGW: C:\Qt\Tools\mingw530_32 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 - - QT5: C:\Qt\5.9\mingw53_32 - MINGW: C:\Qt\Tools\mingw530_32 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 - - QT5: C:\Qt\5.12\mingw73_32 - MINGW: C:\Qt\Tools\mingw730_32 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + - QT6: /Users/appveyor/Qt/6.0.0/clang_64 + APPVEYOR_BUILD_WORKER_IMAGE: macos + - QT6: /home/appveyor/Qt/6.0.0/gcc_64 + APPVEYOR_BUILD_WORKER_IMAGE: Ubuntu2004 + - QT6: C:\Qt\6.0.1\mingw81_64 + MINGW: C:\Qt\Tools\mingw810_64 + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 matrix: - fast_finish: true + fast_finish: false -before_build: -- set PATH=%MINGW%\bin;%QT5%\bin;%PATH% +for: + - matrix: + only: + - APPVEYOR_BUILD_WORKER_IMAGE: Ubuntu2004 + - APPVEYOR_BUILD_WORKER_IMAGE: macos -build_script: -- mkdir .\build -- cd .\build + build_script: + - echo $APPVEYOR_BUILD_WORKER_IMAGE build script + - "echo Shell: $SHELL" + - "echo Home: $HOME" + - export PATH=$QT6/bin:$PATH + - export CMAKE_PREFIX_PATH=$QT6 + - ls -lah $QT6 + - ls -lah $QT6/bin + - mkdir build + - cd build + - cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release --build .. + - make + - cd tests + - ./qtcsv_tests -# build library and tests -- qmake -v -- qmake ..\qtcsv.pro CONFIG+=release DESTDIR=%cd% -- mingw32-make -- dir /s -- mkdir .\tests -- copy .\*qtcsv.dll .\tests -- qmake ..\tests\tests.pro CONFIG+=release DESTDIR=%cd%\tests -- mingw32-make - -# run tests -- dir /s -- .\tests\qtcsv_tests.exe + - matrix: + only: + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 + build_script: + - ps: echo Windows build script + - ps: echo $env:PATH + - ps: (dir env:) + - ps: $env:PATH="$env:MINGW\bin;$env:QT6\bin;$env:PATH" + - ps: $env:QT_LOGGING_RULES="*.debug=true" + - ps: mkdir build + - ps: cd build + # build library and tests + - ps: cmake --version + # IGNORE_PATH is a workaround for CMake not wanting sh.exe on PATH for MinGW + - ps: cmake -G "MinGW Makefiles" -DCMAKE_IGNORE_PATH="C:/Program Files/Git/usr/bin" -DCMAKE_BUILD_TYPE=Release .. + - ps: ls -s + - ps: mingw32-make + - ps: cd tests + - ps: bash.exe -c "cp ../libqtcsv.dll .; ./qtcsv_tests.exe" diff --git a/include/qtcsv/abstractdata.h b/include/qtcsv/abstractdata.h index 27dd6b2..132d5c3 100644 --- a/include/qtcsv/abstractdata.h +++ b/include/qtcsv/abstractdata.h @@ -3,10 +3,8 @@ #include "qtcsv_global.h" -class QStringList; +namespace QtCSV { -namespace QtCSV -{ // AbstractData is a pure abstract container class. Its main purpouse is to // provide common interface for concrete container classes that could be // used in processing of csv-files. @@ -21,24 +19,22 @@ namespace QtCSV // Note, that AbstractData is just an interface for container class, not a // container class. So you are free to decide how to store // information in derived classes. - class QTCSVSHARED_EXPORT AbstractData - { + class QTCSVSHARED_EXPORT AbstractData { public: - explicit AbstractData() {} - virtual ~AbstractData() {} + virtual ~AbstractData() = default; // Add new empty row virtual void addEmptyRow() = 0; // Add new row with specified values - virtual void addRow(const QStringList& values) = 0; + virtual void addRow(const QList& values) = 0; // Clear all data virtual void clear() = 0; // Check if there are any rows virtual bool isEmpty() const = 0; // Get number of rows - virtual int rowCount() const = 0; + virtual qsizetype rowCount() const = 0; // Get values of specified row as list of strings - virtual QStringList rowValues(const int& row) const = 0; + virtual QList rowValues(qsizetype row) const = 0; }; } diff --git a/include/qtcsv/qtcsv_global.h b/include/qtcsv/qtcsv_global.h index 0c44ca3..47cf536 100644 --- a/include/qtcsv/qtcsv_global.h +++ b/include/qtcsv/qtcsv_global.h @@ -4,13 +4,13 @@ #include #ifdef QTCSV_STATIC_LIB -# define QTCSVSHARED_EXPORT +#define QTCSVSHARED_EXPORT #else -# if defined(QTCSV_LIBRARY) -# define QTCSVSHARED_EXPORT Q_DECL_EXPORT -# else -# define QTCSVSHARED_EXPORT Q_DECL_IMPORT -# endif +#if defined(QTCSV_LIBRARY) +#define QTCSVSHARED_EXPORT Q_DECL_EXPORT +#else +#define QTCSVSHARED_EXPORT Q_DECL_IMPORT +#endif #endif #endif // QTCSV_GLOBAL_H diff --git a/include/qtcsv/reader.h b/include/qtcsv/reader.h index 6f4b957..66d659b 100644 --- a/include/qtcsv/reader.h +++ b/include/qtcsv/reader.h @@ -2,15 +2,13 @@ #define QTCSVREADER_H #include "qtcsv/qtcsv_global.h" +#include "abstractdata.h" +#include #include -#include +#include +#include -class QIODevice; -class QStringList; - -namespace QtCSV -{ - class AbstractData; +namespace QtCSV { // Reader class is a file reader that work with csv-files. It needs an // absolute path to the csv-file that you are going to read or @@ -25,28 +23,23 @@ namespace QtCSV // - text codec. // // Reader can save (or transfer) information to: - // - QList, where each QStringList contains values of one row; + // - QList>, where each QList contains values + // of one row; // - AbstractData-based container class; // - AbstractProcessor-based object. - class QTCSVSHARED_EXPORT Reader - { + class QTCSVSHARED_EXPORT Reader { public: // AbstractProcessor is a class that could be used to process csv-data // line by line class QTCSVSHARED_EXPORT AbstractProcessor { public: - explicit AbstractProcessor() {} - virtual ~AbstractProcessor() {} + virtual ~AbstractProcessor() = default; // Preprocess one raw line from a file // @input: - // line - raw line from a file - virtual void preProcessRawLine(QString& line) - { - // Here you can edit line - Q_UNUSED(line); - } + // editable_line - raw line from a file + virtual void preProcessRawLine(QString& /*editable_line*/) {} // Process one row worth of elements // @input: @@ -55,23 +48,23 @@ namespace QtCSV // bool - True if elements was processed successfully, False in case // of error. If process() return False, the csv-file will be stopped // reading - virtual bool processRowElements(const QStringList& elements) = 0; + virtual bool processRowElements(const QList& elements) = 0; }; - // Read csv-file and save it's data as strings to QList - static QList readToList( + // Read csv-file and save it's data as strings to QList> + static QList> readToList( const QString& filePath, const QString& separator = QString(","), const QString& textDelimiter = QString("\""), - QTextCodec* codec = QTextCodec::codecForName("UTF-8")); + QStringConverter::Encoding codec = QStringConverter::Utf8); // Read csv-formatted data from IO Device and save it - // as strings to QList - static QList readToList( + // as strings to QList> + static QList> readToList( QIODevice& ioDevice, const QString& separator = QString(","), const QString& textDelimiter = QString("\""), - QTextCodec* codec = QTextCodec::codecForName("UTF-8")); + QStringConverter::Encoding codec = QStringConverter::Utf8); // Read csv-file and save it's data to AbstractData-based container // class @@ -80,7 +73,7 @@ namespace QtCSV AbstractData& data, const QString& separator = QString(","), const QString& textDelimiter = QString("\""), - QTextCodec* codec = QTextCodec::codecForName("UTF-8")); + QStringConverter::Encoding codec = QStringConverter::Utf8); // Read csv-formatted data from IO Device and save it // to AbstractData-based container class @@ -89,7 +82,7 @@ namespace QtCSV AbstractData& data, const QString& separator = QString(","), const QString& textDelimiter = QString("\""), - QTextCodec* codec = QTextCodec::codecForName("UTF-8")); + QStringConverter::Encoding codec = QStringConverter::Utf8); // Read csv-file and process it line-by-line static bool readToProcessor( @@ -97,7 +90,7 @@ namespace QtCSV AbstractProcessor& processor, const QString& separator = QString(","), const QString& textDelimiter = QString("\""), - QTextCodec* codec = QTextCodec::codecForName("UTF-8")); + QStringConverter::Encoding codec = QStringConverter::Utf8); // Read csv-formatted data from IO Device and process it line-by-line static bool readToProcessor( @@ -105,7 +98,7 @@ namespace QtCSV AbstractProcessor& processor, const QString& separator = QString(","), const QString& textDelimiter = QString("\""), - QTextCodec* codec = QTextCodec::codecForName("UTF-8")); + QStringConverter::Encoding codec = QStringConverter::Utf8); }; } diff --git a/include/qtcsv/stringdata.h b/include/qtcsv/stringdata.h index 4d7dbfe..e72c66b 100644 --- a/include/qtcsv/stringdata.h +++ b/include/qtcsv/stringdata.h @@ -1,66 +1,63 @@ #ifndef QTCSVSTRINGDATA_H #define QTCSVSTRINGDATA_H -#include "qtcsv/qtcsv_global.h" #include "qtcsv/abstractdata.h" +#include "qtcsv/qtcsv_global.h" +#include +#include -class QString; -class QStringList; +namespace QtCSV { -namespace QtCSV -{ // StringData is a simple container class. It implements interface of // AbstractData class and uses strings to store information. Also it // provides basic functions for working with rows. - class QTCSVSHARED_EXPORT StringData : public AbstractData - { - class StringDataPrivate; - StringDataPrivate* d_ptr; + class QTCSVSHARED_EXPORT StringData : public AbstractData { + QList> m_values; public: - explicit StringData(); + StringData() = default; StringData(const StringData& other); StringData& operator=(const StringData& other); - virtual ~StringData(); + ~StringData() override = default; + + bool operator==(const StringData& other) const; // Add new empty row - virtual void addEmptyRow(); + void addEmptyRow() override; // Add new row with one value void addRow(const QString& value); // Add new row with specified values (as strings) - virtual void addRow(const QStringList& values); + void addRow(const QList& values) override; // Clear all data - virtual void clear(); + void clear() override; // Insert new row at index position 'row' - void insertRow(const int& row, const QString& value); - void insertRow(const int& row, const QStringList& values); + void insertRow(qsizetype row, const QString& value); + void insertRow(qsizetype row, const QList& values); // Check if there are any data - virtual bool isEmpty() const; + bool isEmpty() const override; // Remove the row at index position 'row' - void removeRow(const int& row); + void removeRow(qsizetype row); // Replace the row at index position 'row' with new row - void replaceRow(const int& row, const QString& value); - void replaceRow(const int& row, const QStringList& values); + void replaceRow(qsizetype row, const QString& value); + void replaceRow(qsizetype row, const QList& values); // Reserve space for 'size' rows - void reserve(const int& size); + void reserve(qsizetype size); // Get number of rows - virtual int rowCount() const; + qsizetype rowCount() const override; // Get values (as list of strings) of specified row - virtual QStringList rowValues(const int& row) const; + QList rowValues(qsizetype row) const override; // Add new row that would contain one value StringData& operator<<(const QString& value); // Add new row with specified values - StringData& operator<<(const QStringList& values); - - bool operator==(const StringData& other) const; - friend bool operator!=(const StringData& left, const StringData& right) - { - return !(left == right); - } + StringData& operator<<(const QList& values); }; + + inline bool operator!=(const StringData& left, const StringData& right) { + return !(left == right); + } } #endif // QTCSVSTRINGDATA_H diff --git a/include/qtcsv/variantdata.h b/include/qtcsv/variantdata.h index f3d9f91..1d52c24 100644 --- a/include/qtcsv/variantdata.h +++ b/include/qtcsv/variantdata.h @@ -4,12 +4,11 @@ #include "qtcsv/abstractdata.h" #include "qtcsv/qtcsv_global.h" #include +#include +#include -class QVariant; -class QStringList; +namespace QtCSV { -namespace QtCSV -{ // VariantData is a simple container class. It implements interface of // AbstractData class. It uses QVariant to hold information, so data could // be of almost any type - integral, strings and so on. There is only one @@ -17,61 +16,58 @@ namespace QtCSV // obviously, if we want to save information to CSV file, we would need to // convert it to plain-text form). So don't forget to see docs of QVariant // before you start using this class. - class QTCSVSHARED_EXPORT VariantData : public AbstractData - { - class VariantDataPrivate; - VariantDataPrivate* d_ptr; + class QTCSVSHARED_EXPORT VariantData : public AbstractData { + QList< QList > m_values; public: - explicit VariantData(); + VariantData() = default; VariantData(const VariantData& other); VariantData& operator=(const VariantData& other); - virtual ~VariantData(); + ~VariantData() override = default; + + bool operator==(const VariantData& other) const; // Add new empty row - virtual void addEmptyRow(); + void addEmptyRow() override; // Add new row with one value bool addRow(const QVariant& value); // Add new row with specified values bool addRow(const QList& values); // Add new row with specified values (as strings) - virtual void addRow(const QStringList& values); + void addRow(const QList& values) override; // Clear all data - virtual void clear(); + void clear() override; // Insert new row at index position 'row' - bool insertRow(const int& row, const QVariant& value); - bool insertRow(const int& row, const QStringList& values); - bool insertRow(const int& row, const QList& values); + bool insertRow(qsizetype row, const QVariant& value); + bool insertRow(qsizetype row, const QList& values); + bool insertRow(qsizetype row, const QList& values); // Check if there are any data - virtual bool isEmpty() const; + bool isEmpty() const override; // Remove the row at index position 'row' - void removeRow(const int& row); + void removeRow(qsizetype row); // Replace the row at index position 'row' with new row - bool replaceRow(const int& row, const QVariant& value); - bool replaceRow(const int& row, const QStringList& values); - bool replaceRow(const int& row, const QList& values); + bool replaceRow(qsizetype row, const QVariant& value); + bool replaceRow(qsizetype row, const QList& values); + bool replaceRow(qsizetype row, const QList& values); // Reserve space for 'size' rows - void reserve(const int& size); + void reserve(qsizetype size); // Get number of rows - virtual int rowCount() const; + qsizetype rowCount() const override; // Get values (as list of strings) of specified row - virtual QStringList rowValues(const int& row) const; + QList rowValues(qsizetype row) const override; // Add new row that would contain one value - VariantData& operator<<(const QVariant &value); + VariantData& operator<<(const QVariant& value); // Add new row with specified values - VariantData& operator<<(const QList &values); - VariantData& operator<<(const QStringList &values); - - bool operator==(const VariantData& other) const; - friend bool operator!=( - const VariantData& left, const VariantData& right) - { - return !(left == right); - } + VariantData& operator<<(const QList& values); + VariantData& operator<<(const QList& values); }; + + inline bool operator!=(const VariantData& left, const VariantData& right) { + return !(left == right); + } } #endif // QTCSVVARIANTDATA_H diff --git a/include/qtcsv/writer.h b/include/qtcsv/writer.h index ebc9405..50c44ce 100644 --- a/include/qtcsv/writer.h +++ b/include/qtcsv/writer.h @@ -2,15 +2,14 @@ #define QTCSVWRITER_H #include "qtcsv/qtcsv_global.h" +#include "abstractdata.h" +#include +#include #include -#include -#include +#include -class QIODevice; +namespace QtCSV { -namespace QtCSV -{ - class AbstractData; class ContentIterator; // Writer is a data-writer class that works with csv-files and IO Devices. @@ -23,11 +22,9 @@ namespace QtCSV // to the end of the file. // // Also you can specify header and footer for your data. - class QTCSVSHARED_EXPORT Writer - { + class QTCSVSHARED_EXPORT Writer { public: - enum WriteMode - { + enum class WriteMode { REWRITE = 0, APPEND }; @@ -38,19 +35,20 @@ namespace QtCSV const AbstractData& data, const QString& separator = QString(","), const QString& textDelimiter = QString("\""), - const WriteMode& mode = REWRITE, - const QStringList& header = QStringList(), - const QStringList& footer = QStringList(), - QTextCodec* codec = QTextCodec::codecForName("UTF-8")); + WriteMode mode = WriteMode::REWRITE, + const QList& header = {}, + const QList& footer = {}, + QStringConverter::Encoding codec = QStringConverter::Utf8); // Write data to IO Device - static bool write(QIODevice& ioDevice, + static bool write( + QIODevice& ioDevice, const AbstractData& data, const QString& separator = QString(","), const QString& textDelimiter = QString("\""), - const QStringList& header = QStringList(), - const QStringList& footer = QStringList(), - QTextCodec* codec = QTextCodec::codecForName("UTF-8")); + const QList& header = {}, + const QList& footer = {}, + QStringConverter::Encoding codec = QStringConverter::Utf8); }; } diff --git a/qtcsv.pro b/qtcsv.pro index e281264..0bab085 100644 --- a/qtcsv.pro +++ b/qtcsv.pro @@ -1,7 +1,7 @@ QT = core TARGET = qtcsv TEMPLATE = lib -VERSION = 1.6.0 +VERSION = 1.7.0 win32:TARGET_EXT = .dll # Uncomment this setting if you want to build static library @@ -29,8 +29,7 @@ DISTFILES += \ CMakeLists.txt OTHER_FILES += \ - appveyor.yml \ - .travis.yml + appveyor.yml message(=== Configuration of qtcsv ===) message(Qt version: $$[QT_VERSION]) diff --git a/sources/contentiterator.cpp b/sources/contentiterator.cpp index 0399dd7..7ff882f 100644 --- a/sources/contentiterator.cpp +++ b/sources/contentiterator.cpp @@ -1,8 +1,5 @@ #include "sources/contentiterator.h" -#include "include/qtcsv/abstractdata.h" #include "sources/symbols.h" -#include -#include using namespace QtCSV; @@ -18,50 +15,45 @@ ContentIterator::ContentIterator( const AbstractData& data, const QString& separator, const QString& textDelimiter, - const QStringList& header, - const QStringList& footer, - const int chunkSize) : + const QList& header, + const QList& footer, + const qsizetype chunkSize) : m_data(data), m_separator(separator), m_textDelimiter(textDelimiter), m_header(header), m_footer(footer), m_chunkSize(chunkSize), m_dataRow(-1), - atEnd(false) + m_atEnd(false) {} // Check if content contains information // @output: // - bool - True if content is empty, False otherwise -bool ContentIterator::isEmpty() const -{ +bool ContentIterator::isEmpty() const { return m_data.isEmpty() && m_header.isEmpty() && m_footer.isEmpty(); } // Check if content still has chunks of information to return // @output: // - bool - True if class can return next chunk of information, False otherwise -bool ContentIterator::hasNext() const -{ - return !atEnd; +bool ContentIterator::hasNext() const { + return !m_atEnd; } // Get next chunk of information // @output: // - QString - next chunk of information. If there is no more information to // return, function will return empty string -QString ContentIterator::getNext() -{ +QString ContentIterator::getNext() { // Check if we have already get to the end of the content - if (atEnd) { return QString(); } + if (m_atEnd) { return {}; } QString content; - int rowsNumber = 0; + qsizetype rowsNumber = 0; // Initially m_dataRow have negative value. Negative value indicates that // client have called this function first time. In this case at the // beginning of the chunk we should place header information. And then // set m_dataRow to the index of the first row in main data container. - if (m_dataRow < 0) - { - if (false == m_header.isEmpty()) - { + if (m_dataRow < 0) { + if (!m_header.isEmpty()) { content.append(composeRow(m_header)); ++rowsNumber; } @@ -72,28 +64,24 @@ QString ContentIterator::getNext() // Check if m_dataRow is less than number of rows in m_data. If this is // true, add information from the m_data to the chunk. Otherwise, this means // that we already have passed all information from the m_data. - if (m_dataRow < m_data.rowCount()) - { - int endRow = + if (m_dataRow < m_data.rowCount()) { + const auto endRow = qMin(m_dataRow + m_chunkSize - rowsNumber, m_data.rowCount()); - for (int i = m_dataRow; i < endRow; ++i, ++m_dataRow, ++rowsNumber) - { + for (auto i = m_dataRow; i < endRow; ++i, ++m_dataRow, ++rowsNumber) { content.append(composeRow(m_data.rowValues(i))); } } // If we still have place in chunk, try to add footer information to it. - if (rowsNumber < m_chunkSize) - { - if (false == m_footer.isEmpty()) - { + if (rowsNumber < m_chunkSize) { + if (!m_footer.isEmpty()) { content.append(composeRow(m_footer)); ++rowsNumber; } // At this point chunk contains the last row - footer. That // means that we get to the end of content. - atEnd = true; + m_atEnd = true; } return content; @@ -104,19 +92,16 @@ QString ContentIterator::getNext() // - values - list of values in rows // @output: // - QString - result row string -QString ContentIterator::composeRow(const QStringList& values) const -{ - QStringList rowValues = values; +QString ContentIterator::composeRow(const QList& values) const { + QList rowValues = values; const QString twoDelimiters = m_textDelimiter + m_textDelimiter; - for (int i = 0; i < rowValues.size(); ++i) - { + for (auto i = 0; i < rowValues.size(); ++i) { rowValues[i].replace(m_textDelimiter, twoDelimiters); QString delimiter = m_textDelimiter; if (delimiter.isEmpty() && - (rowValues.at(i).contains(m_separator) || - rowValues.at(i).contains(CR) || - rowValues.at(i).contains(LF))) + (rowValues.at(i).contains(m_separator) || + rowValues.at(i).contains(CR) || rowValues.at(i).contains(LF))) { delimiter = DOUBLE_QUOTE; } @@ -127,6 +112,5 @@ QString ContentIterator::composeRow(const QStringList& values) const QString result = rowValues.join(m_separator); result.append(LF); - return result; } diff --git a/sources/contentiterator.h b/sources/contentiterator.h index 213bb40..a177cb6 100644 --- a/sources/contentiterator.h +++ b/sources/contentiterator.h @@ -1,12 +1,11 @@ #ifndef QTCSVCONTENTITERATOR_H #define QTCSVCONTENTITERATOR_H -class QString; -class QStringList; +#include "include/qtcsv/abstractdata.h" +#include +#include -namespace QtCSV -{ - class AbstractData; +namespace QtCSV { // ContentIterator is a class that holds references to containers with // information. Its main purpose: @@ -17,28 +16,27 @@ namespace QtCSV // You can use this class with csv-writer class. ContentIterator will join // elements of one row with separator symbol and then join rows with // new line symbol. - class ContentIterator - { + class ContentIterator { const AbstractData& m_data; const QString& m_separator; const QString& m_textDelimiter; - const QStringList& m_header; - const QStringList& m_footer; - const int m_chunkSize; - int m_dataRow; - bool atEnd; + const QList& m_header; + const QList& m_footer; + const qsizetype m_chunkSize; + qsizetype m_dataRow; + bool m_atEnd; // Compose row string from values - QString composeRow(const QStringList& values) const; + QString composeRow(const QList& values) const; public: - explicit ContentIterator( + ContentIterator( const AbstractData& data, const QString& separator, const QString& textDelimiter, - const QStringList& header, - const QStringList& footer, - int chunkSize = 1000); + const QList& header, + const QList& footer, + qsizetype chunkSize = 1000); // Check if content contains information bool isEmpty() const; diff --git a/sources/filechecker.h b/sources/filechecker.h index dd36b5e..0cb851b 100644 --- a/sources/filechecker.h +++ b/sources/filechecker.h @@ -1,33 +1,28 @@ #ifndef QTCSVFILECHECKER_H #define QTCSVFILECHECKER_H -#include -#include #include +#include +#include -namespace QtCSV -{ +namespace QtCSV { // Check if path to csv file is valid // @input: // - filePath - string with absolute path to file // - mustExist - True if file must exist, False if this is not important // @output: // - bool - True if file is OK, else False - inline bool CheckFile( - const QString& filePath, const bool mustExist = false) + inline bool CheckFile(const QString& filePath, const bool mustExist = false) { - if (filePath.isEmpty()) - { + if (filePath.isEmpty()) { qDebug() << __FUNCTION__ << "Error - file path is empty"; return false; } QFileInfo fileInfo(filePath); - if (fileInfo.isAbsolute() && false == fileInfo.isDir()) - { + if (fileInfo.isAbsolute() && false == fileInfo.isDir()) { if (mustExist && false == fileInfo.exists()) { return false; } - if ("csv" != fileInfo.suffix()) - { + if ("csv" != fileInfo.suffix()) { qDebug() << __FUNCTION__ << "Warning - file suffix is not .csv"; } diff --git a/sources/reader.cpp b/sources/reader.cpp index 505d5f7..ef7fba9 100644 --- a/sources/reader.cpp +++ b/sources/reader.cpp @@ -2,27 +2,22 @@ #include "include/qtcsv/abstractdata.h" #include "sources/filechecker.h" #include "sources/symbols.h" +#include #include -#include -#include -#include +#include #include -#include using namespace QtCSV; -inline bool openFile(const QString& filePath, QFile& file) -{ - if (false == CheckFile(filePath, true)) - { +bool openFile(const QString& filePath, QFile& file) { + if (!CheckFile(filePath, true)) { qDebug() << __FUNCTION__ << "Error - wrong file path:" << filePath; return false; } file.setFileName(filePath); - bool result = file.open(QIODevice::ReadOnly); - if (false == result) - { + const auto result = file.open(QIODevice::ReadOnly); + if (!result) { qDebug() << __FUNCTION__ << "Error - can't open file:" << filePath; } @@ -30,53 +25,48 @@ inline bool openFile(const QString& filePath, QFile& file) } // ElementInfo is a helper struct that is used as indicator of row end -struct ElementInfo -{ -public: - ElementInfo() : isEnded(true) {} - bool isEnded; +struct ElementInfo { + bool isEnded = true; }; -class ReaderPrivate -{ -public: - // Function that really reads csv-data and transfer it's data to - // AbstractProcessor-based processor - static bool read( - QIODevice& ioDevice, - Reader::AbstractProcessor& processor, - const QString& separator, - const QString& textDelimiter, - QTextCodec* codec); - -private: +class ReaderPrivate { // Check if file path and separator are valid static bool checkParams(const QString& separator); // Split string to elements - static QStringList splitElements( + static QList splitElements( const QString& line, const QString& separator, const QString& textDelimiter, ElementInfo& elemInfo); // Try to find end position of first or middle element - static int findMiddleElementPosition( + static qsizetype findMiddleElementPosition( const QString& str, - const int& startPos, + const qsizetype& startPos, const QString& separator, const QString& txtDelim); // Check if current element is the last element static bool isElementLast( const QString& str, - const int& startPos, + const qsizetype startPos, const QString& separator, const QString& txtDelim); // Remove extra symbols (spaces, text delimeters...) static void removeExtraSymbols( - QStringList& elements, const QString& textDelimiter); + QList& elements, const QString& textDelimiter); + +public: + // Function that really reads csv-data and transfer it's data to + // AbstractProcessor-based processor + static bool read( + QIODevice& ioDevice, + Reader::AbstractProcessor& processor, + const QString& separator, + const QString& textDelimiter, + QStringConverter::Encoding codec); }; // Function that really reads csv-data and transfer it's data to @@ -94,57 +84,48 @@ bool ReaderPrivate::read( Reader::AbstractProcessor& processor, const QString& separator, const QString& textDelimiter, - QTextCodec* codec) + const QStringConverter::Encoding codec) { - if (false == checkParams(separator)) { return false; } + if (!checkParams(separator)) { return false; } // Open IO Device if it was not opened - if (false == ioDevice.isOpen() && - false == ioDevice.open(QIODevice::ReadOnly)) - { + if (!ioDevice.isOpen() && !ioDevice.open(QIODevice::ReadOnly)) { qDebug() << __FUNCTION__ << "Error - failed to open IO Device"; return false; } QTextStream stream(&ioDevice); - stream.setCodec(codec); + stream.setEncoding(codec); // This list will contain elements of the row if its elements // are located on several lines - QStringList row; + QList row; ElementInfo elemInfo; - bool result = true; - while (false == stream.atEnd()) - { - QString line = stream.readLine(); + auto result = true; + while (!stream.atEnd()) { + auto line = stream.readLine(); processor.preProcessRawLine(line); - QStringList elements = ReaderPrivate::splitElements( - line, separator, textDelimiter, elemInfo); - if (elemInfo.isEnded) - { + auto elements = ReaderPrivate::splitElements( + line, separator, textDelimiter, elemInfo); + if (elemInfo.isEnded) { // Current row ends on this line. Check if these elements are // end elements of the long row - if (row.isEmpty()) - { + if (row.isEmpty()) { // No, these elements constitute the entire row - if (false == processor.processRowElements(elements)) - { + if (!processor.processRowElements(elements)) { result = false; break; } } - else - { + else { // Yes, these elements should be added to the row - if (false == elements.isEmpty()) - { + if (!elements.isEmpty()) { row.last().append(elements.takeFirst()); row << elements; } - if (false == processor.processRowElements(row)) - { + if (!processor.processRowElements(row)) { result = false; break; } @@ -152,13 +133,10 @@ bool ReaderPrivate::read( row.clear(); } } - else - { + else { // These elements constitute long row that lasts on several lines - if (false == elements.isEmpty()) - { - if (false == row.isEmpty()) - { + if (!elements.isEmpty()) { + if (!row.isEmpty()) { row.last().append(elements.takeFirst()); } @@ -167,8 +145,7 @@ bool ReaderPrivate::read( } } - if (false == elemInfo.isEnded && false == row.isEmpty()) - { + if (!elemInfo.isEnded && !row.isEmpty()) { result = processor.processRowElements(row); } @@ -180,10 +157,8 @@ bool ReaderPrivate::read( // - separator - string or character that separate values in a row // @output: // - bool - True if file path and separator are valid, otherwise False -bool ReaderPrivate::checkParams(const QString& separator) -{ - if (separator.isEmpty()) - { +bool ReaderPrivate::checkParams(const QString& separator) { + if (separator.isEmpty()) { qDebug() << __FUNCTION__ << "Error - separator could not be empty"; return false; } @@ -197,8 +172,8 @@ bool ReaderPrivate::checkParams(const QString& separator) // - separator - string or character that separate elements // - textDelimiter - string that is used as text delimiter // @output: -// - QStringList - list of elements -QStringList ReaderPrivate::splitElements( +// - QList - list of elements +QList ReaderPrivate::splitElements( const QString& line, const QString& separator, const QString& textDelimiter, @@ -206,31 +181,26 @@ QStringList ReaderPrivate::splitElements( { // If separator is empty, return whole line. Can't work in this // conditions! - if (separator.isEmpty()) - { + if (separator.isEmpty()) { elemInfo.isEnded = true; - return (QStringList() << line); + return (QList() << line); } - if (line.isEmpty()) - { - // If previous row was ended, then return empty QStringList. + if (line.isEmpty()) { + // If previous row was ended, then return empty QList. // Otherwise return list that contains one element - new line symbols - return elemInfo.isEnded ? QStringList() : (QStringList() << LF); + return elemInfo.isEnded ? QList() : (QList() << LF); } - QStringList result; - int pos = 0; - while (pos < line.size()) - { - if (elemInfo.isEnded) - { + QList result; + qsizetype pos = 0; + while (pos < line.size()) { + if (elemInfo.isEnded) { // This line is a new line, not a continuation of the previous // line. // Check if element starts with the delimiter symbol - int delimiterPos = line.indexOf(textDelimiter, pos); - if (delimiterPos == pos) - { + const auto delimiterPos = line.indexOf(textDelimiter, pos); + if (delimiterPos == pos) { pos = delimiterPos + textDelimiter.size(); // Element starts with the delimiter symbol. It means that @@ -239,41 +209,37 @@ QStringList ReaderPrivate::splitElements( // 1. Be the first or the middle element. Then it should end // with delimiter and the seprator symbols standing next to each // other. - int midElemEndPos = findMiddleElementPosition( + const auto midElemEndPos = findMiddleElementPosition( line, pos, separator, textDelimiter); - if (midElemEndPos > 0) - { - int length = midElemEndPos - pos; + if (midElemEndPos > 0) { + const auto length = midElemEndPos - pos; result << line.mid(pos, length); - pos = midElemEndPos + - textDelimiter.size() + separator.size(); + pos = + midElemEndPos + textDelimiter.size() + separator.size(); continue; } // 2. Be The last element on the line. Then it should end with // delimiter symbol. - if (isElementLast(line, pos, separator, textDelimiter)) - { - int length = line.size() - textDelimiter.size() - pos; + if (isElementLast(line, pos, separator, textDelimiter)) { + const auto length = line.size() - textDelimiter.size() - pos; result << line.mid(pos, length); break; } // 3. Not ends on this line - int length = line.size() - pos; + const auto length = line.size() - pos; result << line.mid(pos, length); elemInfo.isEnded = false; break; } - else - { + else { // Element do not starts with the delimiter symbol. It means // that this element do not contain double delimiters and it // ends at the next separator symbol. // Check if line contains separator symbol. - int separatorPos = line.indexOf(separator, pos); - if (separatorPos >= 0) - { + const auto separatorPos = line.indexOf(separator, pos); + if (separatorPos >= 0) { // If line contains separator symbol, then our element // located between current position and separator // position. Copy it into result list and move @@ -282,16 +248,14 @@ QStringList ReaderPrivate::splitElements( // Special case: if line ends with separator symbol, // then at the end of the line we have empty element. - if (separatorPos == line.size() - separator.size()) - { + if (separatorPos == line.size() - separator.size()) { result << QString(); } // Move the current position on to the next element pos = separatorPos + separator.size(); } - else - { + else { // If line do not contains separator symbol, then // this element ends at the end of the string. // Copy it into result list and exit the loop. @@ -309,10 +273,9 @@ QStringList ReaderPrivate::splitElements( // 1. Ends somewhere in the middle of the line. Then it should ends // with delimiter and the seprator symbols standing next to each // other. - int midElemEndPos = findMiddleElementPosition( + const auto midElemEndPos = findMiddleElementPosition( line, pos, separator, textDelimiter); - if (midElemEndPos >= 0) - { + if (midElemEndPos >= 0) { result << (LF + line.mid(pos, midElemEndPos - pos)); pos = midElemEndPos + textDelimiter.size() + separator.size(); elemInfo.isEnded = true; @@ -321,9 +284,8 @@ QStringList ReaderPrivate::splitElements( // 2. Ends at the end of the line. Then it should ends with // delimiter symbol. - if (isElementLast(line, pos, separator, textDelimiter)) - { - int length = line.size() - textDelimiter.size() - pos; + if (isElementLast(line, pos, separator, textDelimiter)) { + const auto length = line.size() - textDelimiter.size() - pos; result << (LF + line.mid(pos, length)); elemInfo.isEnded = true; break; @@ -346,15 +308,15 @@ QStringList ReaderPrivate::splitElements( // - separator - string or character that separate elements // - textDelimiter - string that is used as text delimiter // @output: -// - int - end position of the element or -1 if this element is not first +// - qsizetype - end position of the element or -1 if this element is not first // or middle -int ReaderPrivate::findMiddleElementPosition( +qsizetype ReaderPrivate::findMiddleElementPosition( const QString& str, - const int& startPos, + const qsizetype& startPos, const QString& separator, const QString& txtDelim) { - const int ERROR = -1; + const qsizetype ERROR = -1; if (str.isEmpty() || startPos < 0 || separator.isEmpty() || @@ -363,14 +325,12 @@ int ReaderPrivate::findMiddleElementPosition( return ERROR; } - const QString elemEndSymbols = txtDelim + separator; - int elemEndPos = startPos; - while (elemEndPos < str.size()) - { + const auto elemEndSymbols = txtDelim + separator; + auto elemEndPos = startPos; + while (elemEndPos < str.size()) { // Find position of element end symbol elemEndPos = str.indexOf(elemEndSymbols, elemEndPos); - if (elemEndPos < 0) - { + if (elemEndPos < 0) { // This element could not be the middle element, becaise string // do not contains any end symbols return ERROR; @@ -380,26 +340,20 @@ int ReaderPrivate::findMiddleElementPosition( // element and we don't mix up it with double delimiter // and separator. Calc number of delimiter symbols from elemEndPos // to startPos that stands together. - int numOfDelimiters = 0; - for (int pos = elemEndPos; startPos <= pos; --pos, ++numOfDelimiters) - { - QStringRef strRef = str.midRef(pos, txtDelim.size()); - if (QStringRef::compare(strRef, txtDelim) != 0) - { - break; - } + qsizetype numOfDelimiters = 0; + for (auto pos = elemEndPos; startPos <= pos; --pos, ++numOfDelimiters) { + const auto strRef = str.mid(pos, txtDelim.size()); + if (QString::compare(strRef, txtDelim) != 0) { break; } } // If we have odd number of delimiter symbols that stand together, // then this is the even number of double delimiter symbols + last // delimiter symbol. That means that we have found end position of // the middle element. - if (numOfDelimiters % 2 == 1) - { + if (numOfDelimiters % 2 == 1) { return elemEndPos; } - else - { + else { // Otherwise this is not the end of the middle element and we // should try again elemEndPos += elemEndSymbols.size(); @@ -420,7 +374,7 @@ int ReaderPrivate::findMiddleElementPosition( // False otherwise bool ReaderPrivate::isElementLast( const QString& str, - const int& startPos, + const qsizetype startPos, const QString& separator, const QString& txtDelim) { @@ -434,31 +388,22 @@ bool ReaderPrivate::isElementLast( // Check if string ends with text delimiter. If not, then this element // do not ends on this line - if (false == str.endsWith(txtDelim)) { return false; } + if (!str.endsWith(txtDelim)) { return false; } // Check that this is really the end symbols of the // element and we don't mix up it with double delimiter. // Calc number of delimiter symbols from end // to startPos that stands together. - int numOfDelimiters = 0; - for (int pos = str.size() - 1; startPos <= pos; --pos, ++numOfDelimiters) - { - QStringRef strRef = str.midRef(pos, txtDelim.size()); - if (QStringRef::compare(strRef, txtDelim) != 0) - { - break; - } + qsizetype numOfDelimiters = 0; + for (auto pos = str.size() - 1; startPos <= pos; --pos, ++numOfDelimiters) { + const auto strRef = str.mid(pos, txtDelim.size()); + if (QString::compare(strRef, txtDelim) != 0) { break; } } // If we have odd number of delimiter symbols that stand together, // then this is the even number of double delimiter symbols + last // delimiter symbol. That means that this element is the last on the line. - if (numOfDelimiters % 2 == 1) - { - return true; - } - - return false; + return numOfDelimiters % 2 == 1; } // Remove extra symbols (spaces, text delimeters...) @@ -466,53 +411,44 @@ bool ReaderPrivate::isElementLast( // - elements - list of row elements // - textDelimiter - string that is used as text delimiter void ReaderPrivate::removeExtraSymbols( - QStringList& elements, const QString& textDelimiter) + QList& elements, const QString& textDelimiter) { if (elements.isEmpty()) { return; } - const QString doubleTextDelim = textDelimiter + textDelimiter; - for (int i = 0; i < elements.size(); ++i) - { - QStringRef str(&elements.at(i)); + const auto doubleTextDelim = textDelimiter + textDelimiter; + for (auto i = 0; i < elements.size(); ++i) { + const auto str = QStringView{elements.at(i)}; if (str.isEmpty()) { continue; } - int startPos = 0, endPos = str.size() - 1; + qsizetype startPos = 0, endPos = str.size() - 1; // Find first non-space char - for (; - startPos < str.size() && - str.at(startPos).category() == QChar::Separator_Space; + for (; startPos < str.size() && + str.at(startPos).category() == QChar::Separator_Space; ++startPos); // Find last non-space char for (; - endPos >= 0 && - str.at(endPos).category() == QChar::Separator_Space; + endPos >= 0 && str.at(endPos).category() == QChar::Separator_Space; --endPos); - if (false == textDelimiter.isEmpty()) - { + if (!textDelimiter.isEmpty()) { // Skip text delimiter symbol if element starts with it - QStringRef strStart(&elements.at(i), startPos, textDelimiter.size()); - if (strStart == textDelimiter) - { + const auto strStart = str.mid(startPos, textDelimiter.size()); + if (strStart == textDelimiter) { startPos += textDelimiter.size(); } // Skip text delimiter symbol if element ends with it - QStringRef strEnd( - &elements.at(i), - endPos - textDelimiter.size() + 1, - textDelimiter.size()); - if (strEnd == textDelimiter) - { + const auto strEnd = str.mid( + endPos - textDelimiter.size() + 1, textDelimiter.size()); + if (strEnd == textDelimiter) { endPos -= textDelimiter.size(); } } if ((0 < startPos || endPos < str.size() - 1) && - startPos <= endPos) - { + startPos <= endPos) { elements[i] = elements[i].mid(startPos, endPos - startPos + 1); } @@ -522,45 +458,43 @@ void ReaderPrivate::removeExtraSymbols( } // ReadToListProcessor - processor that saves rows of elements to list. -class ReadToListProcessor : public Reader::AbstractProcessor -{ +class ReadToListProcessor : public Reader::AbstractProcessor { public: - QList data; - virtual bool processRowElements(const QStringList& elements) - { + QList> data; + + bool processRowElements(const QList& elements) override { data << elements; return true; } }; -// Read csv-file and save it's data as strings to QList +// Read csv-file and save it's data as strings to QList> // @input: // - filePath - string with absolute path to csv-file // - separator - string or character that separate elements in a row // - textDelimiter - string or character that enclose each element in a row // - codec - pointer to codec object that would be used for file reading // @output: -// - QList - list of values (as strings) from csv-file. In case of -// error will return empty QList. -QList Reader::readToList( +// - QList> - list of values (as strings) from csv-file. In case of +// error will return empty QList>. +QList> Reader::readToList( const QString& filePath, const QString& separator, const QString& textDelimiter, - QTextCodec* codec) + const QStringConverter::Encoding codec) { QFile file; - if (false == openFile(filePath, file)) { return QList(); } - - return readToList(file, separator, textDelimiter, codec); + return openFile(filePath, file) ? + readToList(file, separator, textDelimiter, codec) : QList>(); } // Read csv-formatted data from IO Device and save it -// as strings to QList -QList Reader::readToList( +// as strings to QList> +QList> Reader::readToList( QIODevice &ioDevice, const QString &separator, const QString &textDelimiter, - QTextCodec *codec) + const QStringConverter::Encoding codec) { ReadToListProcessor processor; ReaderPrivate::read(ioDevice, processor, separator, textDelimiter, codec); @@ -581,12 +515,11 @@ bool Reader::readToData( AbstractData& data, const QString& separator, const QString& textDelimiter, - QTextCodec* codec) + const QStringConverter::Encoding codec) { QFile file; - if (false == openFile(filePath, file)) { return false; } - - return readToData(file, data, separator, textDelimiter, codec); + return openFile(filePath, file) ? + readToData(file, data, separator, textDelimiter, codec) : false; } // Read csv-formatted data from IO Device and save it @@ -596,15 +529,13 @@ bool Reader::readToData( AbstractData& data, const QString& separator, const QString& textDelimiter, - QTextCodec* codec) + const QStringConverter::Encoding codec) { ReadToListProcessor processor; - const bool result = ReaderPrivate::read( + const auto result = ReaderPrivate::read( ioDevice, processor, separator, textDelimiter, codec); - if (result) - { - for (int i = 0; i < processor.data.size(); ++i) - { + if (result) { + for (auto i = 0; i < processor.data.size(); ++i) { data.addRow(processor.data.at(i)); } } @@ -627,20 +558,20 @@ bool Reader::readToProcessor( Reader::AbstractProcessor& processor, const QString& separator, const QString& textDelimiter, - QTextCodec* codec) + const QStringConverter::Encoding codec) { QFile file; - if (false == openFile(filePath, file)) { return false; } - - return readToProcessor(file, processor, separator, textDelimiter, codec); + return openFile(filePath, file) ? + readToProcessor(file, processor, separator, textDelimiter, codec) : false; } // Read csv-formatted data from IO Device and process it line-by-line -bool Reader::readToProcessor(QIODevice& ioDevice, - Reader::AbstractProcessor& processor, - const QString& separator, - const QString& textDelimiter, - QTextCodec* codec) +bool Reader::readToProcessor( + QIODevice& ioDevice, + Reader::AbstractProcessor& processor, + const QString& separator, + const QString& textDelimiter, + const QStringConverter::Encoding codec) { return ReaderPrivate::read( ioDevice, processor, separator, textDelimiter, codec); diff --git a/sources/stringdata.cpp b/sources/stringdata.cpp index f4f27dd..efb1ee0 100644 --- a/sources/stringdata.cpp +++ b/sources/stringdata.cpp @@ -1,54 +1,41 @@ #include "include/qtcsv/stringdata.h" -#include -#include using namespace QtCSV; -class StringData::StringDataPrivate -{ -public: - QList m_values; -}; +StringData::StringData(const StringData& other) : m_values(other.m_values) {} -StringData::StringData() : d_ptr(new StringDataPrivate) {} - -StringData::StringData(const StringData& other) : d_ptr(new StringDataPrivate) -{ - d_ptr->m_values = other.d_ptr->m_values; +StringData& StringData::operator=(const StringData& other) { + m_values = other.m_values; + return *this; } -StringData::~StringData() -{ - delete d_ptr; +bool StringData::operator==(const StringData& other) const { + return m_values == other.m_values; } // Add new empty row -void StringData::addEmptyRow() -{ - d_ptr->m_values << QStringList(); +void StringData::addEmptyRow() { + m_values << QList(); } // Add new row with one value // @input: // - value - value that is supposed to be written to the new row -void StringData::addRow(const QString& value) -{ - d_ptr->m_values << (QStringList() << value); +void StringData::addRow(const QString& value) { + m_values << (QList() << value); } // Add new row with specified values (as strings) // @input: // - values - list of strings. If list is empty, it will be interpreted // as empty line -void StringData::addRow(const QStringList& values) -{ - d_ptr->m_values << values; +void StringData::addRow(const QList& values) { + m_values << values; } // Clear all data -void StringData::clear() -{ - d_ptr->m_values.clear(); +void StringData::clear() { + m_values.clear(); } // Insert new row at index position 'row'. @@ -56,9 +43,8 @@ void StringData::clear() // - row - index of row. If 'row' is 0, the value will be set as first row. // If 'row' is >= rowCount(), the value will be added as new last row. // - value - value that is supposed to be written to the new row -void StringData::insertRow(const int& row, const QString& value) -{ - insertRow(row, (QStringList() << value)); +void StringData::insertRow(const qsizetype row, const QString& value) { + insertRow(row, (QList() << value)); } // Insert new row at index position 'row'. @@ -66,26 +52,25 @@ void StringData::insertRow(const int& row, const QString& value) // - row - index of row. If 'row' is 0, the values will be set as first row. // If 'row' is >= rowCount(), the values will be added as new last row. // - values - list of strings -void StringData::insertRow(const int& row, const QStringList& values) -{ - d_ptr->m_values.insert(row, values); +void StringData::insertRow(const qsizetype row, const QList& values) { + m_values.insert(qBound(0, row, m_values.size()), values); } // Check if there are any rows // @output: // - bool - True if there are any rows, else False -bool StringData::isEmpty() const -{ - return d_ptr->m_values.isEmpty(); +bool StringData::isEmpty() const { + return m_values.isEmpty(); } // Remove the row at index position 'row'. // @input: // - row - index of row to remove. 'row' must be a valid index position // (i.e., 0 <= row < rowCount()). Otherwise function will do nothing. -void StringData::removeRow(const int& row) -{ - d_ptr->m_values.removeAt(row); +void StringData::removeRow(const qsizetype row) { + if (row >= 0 && row < m_values.size()) { + m_values.removeAt(row); + } } // Replace the row at index position 'row' with new row. @@ -93,9 +78,8 @@ void StringData::removeRow(const int& row) // - row - index of row that should be replaced. 'row' must be // a valid index position (i.e., 0 <= row < rowCount()). // - value - value that is supposed to be written instead of the 'old' values -void StringData::replaceRow(const int& row, const QString& value) -{ - replaceRow(row, (QStringList() << value)); +void StringData::replaceRow(const qsizetype row, const QString& value) { + replaceRow(row, (QList() << value)); } // Replace the row at index position 'row' with new row. @@ -104,66 +88,45 @@ void StringData::replaceRow(const int& row, const QString& value) // a valid index position (i.e., 0 <= row < rowCount()). // - values - list of strings that is supposed to be written instead of the // 'old' values -void StringData::replaceRow(const int& row, const QStringList& values) -{ - d_ptr->m_values.replace(row, values); +void StringData::replaceRow(const qsizetype row, const QList& values) { + m_values.replace(row, values); } // Reserve space for 'size' rows. // @input: // - size - number of rows to reserve in memory. If 'size' is smaller than the // current number of rows, function will do nothing. -void StringData::reserve(const int& size) -{ - d_ptr->m_values.reserve(size); +void StringData::reserve(const qsizetype size) { + m_values.reserve(size); } // Get number of rows // @output: -// - int - current number of rows -int StringData::rowCount() const -{ - return d_ptr->m_values.size(); +// - qsizetype - current number of rows +qsizetype StringData::rowCount() const { + return m_values.size(); } // Get values (as list of strings) of specified row // @input: // - row - valid number of row // @output: -// - QStringList - values of row. If row is invalid number, function will -// return empty QStringList. -QStringList StringData::rowValues(const int& row) const -{ - if (row < 0 || rowCount() <= row) - { - return QStringList(); - } +// - QList - values of row. If row is invalid number, function will +// return empty list. +QList StringData::rowValues(const qsizetype row) const { + if (row < 0 || rowCount() <= row) { return {}; } - return d_ptr->m_values.at(row); -} - -bool StringData::operator==(const StringData& other) const -{ - return d_ptr->m_values == other.d_ptr->m_values; -} - -StringData& StringData::operator=(const StringData& other) -{ - StringData tmp(other); - std::swap(d_ptr, tmp.d_ptr); - return *this; + return m_values.at(row); } // Add new row that would contain one value -StringData& StringData::operator<<(const QString& value) -{ - this->addRow(value); +StringData& StringData::operator<<(const QString& value) { + addRow(value); return *this; } // Add new row with specified values -StringData& StringData::operator<<(const QStringList& values) -{ - this->addRow(values); +StringData& StringData::operator<<(const QList& values) { + addRow(values); return *this; } diff --git a/sources/symbols.h b/sources/symbols.h index 578c344..b908ba3 100644 --- a/sources/symbols.h +++ b/sources/symbols.h @@ -3,8 +3,7 @@ #include -namespace QtCSV -{ +namespace QtCSV { const QString DOUBLE_QUOTE("\""); const QString CR("\r"); const QString LF("\n"); diff --git a/sources/variantdata.cpp b/sources/variantdata.cpp index 206e74e..14e3476 100644 --- a/sources/variantdata.cpp +++ b/sources/variantdata.cpp @@ -1,74 +1,48 @@ #include "include/qtcsv/variantdata.h" -#include -#include using namespace QtCSV; -class VariantData::VariantDataPrivate -{ -public: - QList< QList > m_values; - - // Check if all values are convertable to strings - bool isConvertableToString(const QList& values) const; - // Transform QStringList to QList - QList toListOfVariants(const QStringList& values) const; -}; - // Check if all values are convertable to strings // @input: // - values - list of values // @output: // - bool - True if all values are convertable to strings, False otherwise -bool VariantData::VariantDataPrivate::isConvertableToString( - const QList& values) const -{ - for (QList::const_iterator iter = values.constBegin(); - iter != values.constEnd(); - ++iter) - { - if (false == (*iter).canConvert()) { return false; } +bool isConvertableToString(const QList& values) { + for (auto iter = values.constBegin(); iter != values.constEnd(); ++iter) { + if (!(*iter).canConvert()) { return false; } } return true; } -// Transform QStringList to QList +// Transform QList to QList // @input: // - values - list of strings // @output: // - QList - list of the same strings, but converted to QVariants -QList VariantData::VariantDataPrivate::toListOfVariants( - const QStringList& values) const -{ +QList toListOfVariants(const QList& values) { QList list; - for (QStringList::const_iterator iter = values.constBegin(); - iter != values.constEnd(); - ++iter) - { + for (auto iter = values.constBegin(); iter != values.constEnd(); ++iter) { list << QVariant(*iter); } return list; } -VariantData::VariantData() : d_ptr(new VariantDataPrivate) {} +VariantData::VariantData(const VariantData& other) : m_values(other.m_values) {} -VariantData::VariantData(const VariantData& other) : - d_ptr(new VariantDataPrivate) -{ - d_ptr->m_values = other.d_ptr->m_values; +VariantData& VariantData::operator=(const VariantData& other) { + m_values = other.m_values; + return *this; } -VariantData::~VariantData() -{ - delete d_ptr; +bool VariantData::operator==(const VariantData& other) const { + return m_values == other.m_values; } // Add new empty row -void VariantData::addEmptyRow() -{ - d_ptr->m_values << QList(); +void VariantData::addEmptyRow() { + m_values << QList(); } // Add new row with one value @@ -78,11 +52,10 @@ void VariantData::addEmptyRow() // QString! // @output: // - bool - True if new row was successfully added, else False -bool VariantData::addRow(const QVariant& value) -{ - if (false == value.canConvert()) { return false; } +bool VariantData::addRow(const QVariant& value) { + if (!value.canConvert()) { return false; } - d_ptr->m_values << (QList() << value); + m_values << (QList() << value); return true; } @@ -92,26 +65,23 @@ bool VariantData::addRow(const QVariant& value) // Values must be convertable to a QString! // @output: // - bool - True if new row was successfully added, else False -bool VariantData::addRow(const QList& values) -{ - if (false == d_ptr->isConvertableToString(values)) { return false; } +bool VariantData::addRow(const QList& values) { + if (!isConvertableToString(values)) { return false; } - d_ptr->m_values << values; + m_values << values; return true; } // Add new row with specified values (as strings) // @input: // - values - list of strings. If list is empty, empty row will be added. -void VariantData::addRow(const QStringList& values) -{ - d_ptr->m_values << d_ptr->toListOfVariants(values); +void VariantData::addRow(const QList& values) { + m_values << toListOfVariants(values); } // Clear all data -void VariantData::clear() -{ - d_ptr->m_values.clear(); +void VariantData::clear() { + m_values.clear(); } // Insert new row at index position 'row'. @@ -122,8 +92,7 @@ void VariantData::clear() // convertable to a QString! // @output: // - bool - True if row was inserted, False otherwise -bool VariantData::insertRow(const int& row, const QVariant& value) -{ +bool VariantData::insertRow(const qsizetype row, const QVariant& value) { return insertRow(row, (QList() << value)); } @@ -134,9 +103,8 @@ bool VariantData::insertRow(const int& row, const QVariant& value) // - values - list of strings that are supposed to be written to the new row // @output: // - bool - True if row was inserted, False otherwise -bool VariantData::insertRow(const int& row, const QStringList& values) -{ - return insertRow(row, d_ptr->toListOfVariants(values)); +bool VariantData::insertRow(const qsizetype row, const QList& values) { + return insertRow(row, toListOfVariants(values)); } // Insert new row at index position 'row'. @@ -147,29 +115,28 @@ bool VariantData::insertRow(const int& row, const QStringList& values) // Values must be convertable to a QString! // @output: // - bool - True if row was inserted, False otherwise -bool VariantData::insertRow(const int& row, const QList& values) -{ - if (false == d_ptr->isConvertableToString(values)) { return false; } +bool VariantData::insertRow(const qsizetype row, const QList& values) { + if (!isConvertableToString(values)) { return false; } - d_ptr->m_values.insert(row, values); + m_values.insert(qBound(0, row, m_values.size()), values); return true; } // Check if there are any rows // @output: // - bool - True if there are any rows, else False -bool VariantData::isEmpty() const -{ - return d_ptr->m_values.isEmpty(); +bool VariantData::isEmpty() const { + return m_values.isEmpty(); } // Remove the row at index position 'row' // @input: // - row - index of row to remove. 'row' must be a valid index position // (i.e., 0 <= row < rowCount()). Otherwise function will do nothing. -void VariantData::removeRow(const int& row) -{ - d_ptr->m_values.removeAt(row); +void VariantData::removeRow(const qsizetype row) { + if (row >= 0 && row < m_values.size()) { + m_values.removeAt(row); + } } // Replace the row at index position 'row' with new row. @@ -180,8 +147,7 @@ void VariantData::removeRow(const int& row) // Value must be convertable to QString! // @output: // - bool - True if row was replaced, else False -bool VariantData::replaceRow(const int& row, const QVariant& value) -{ +bool VariantData::replaceRow(const qsizetype row, const QVariant& value) { return replaceRow(row, (QList() << value)); } @@ -193,9 +159,8 @@ bool VariantData::replaceRow(const int& row, const QVariant& value) // values. // @output: // - bool - True if row was replaced, else False -bool VariantData::replaceRow(const int& row, const QStringList& values) -{ - return replaceRow(row, d_ptr->toListOfVariants(values)); +bool VariantData::replaceRow(const qsizetype row, const QList& values) { + return replaceRow(row, toListOfVariants(values)); } // Replace the row at index position 'row' with new row. @@ -206,11 +171,11 @@ bool VariantData::replaceRow(const int& row, const QStringList& values) // values. Values must be convertable to a QString! // @output: // - bool - True if row was replaced, else False -bool VariantData::replaceRow(const int& row, const QList& values) -{ - if (false == d_ptr->isConvertableToString(values)) { return false; } +bool VariantData::replaceRow( + const qsizetype row, const QList& values) { + if (!isConvertableToString(values)) { return false; } - d_ptr->m_values.replace(row, values); + m_values.replace(row, values); return true; } @@ -218,67 +183,48 @@ bool VariantData::replaceRow(const int& row, const QList& values) // @input: // - size - number of rows to reserve in memory. If 'size' is smaller than the // current number of rows, function will do nothing. -void VariantData::reserve(const int& size) -{ - d_ptr->m_values.reserve(size); +void VariantData::reserve(const qsizetype size) { + m_values.reserve(size); } // Get number of rows // @output: -// - int - current number of rows -int VariantData::rowCount() const -{ - return d_ptr->m_values.size(); +// - qsizetype - current number of rows +qsizetype VariantData::rowCount() const { + return m_values.size(); } // Get values (as list of strings) of specified row // @input: // - row - valid number of the row // @output: -// - QStringList - values of the row. If row have invalid value, function will -// return empty QStringList. -QStringList VariantData::rowValues(const int& row) const -{ - if (row < 0 || rowCount() <= row) { return QStringList(); } - - QStringList values; - for (int i = 0; i < d_ptr->m_values.at(row).size(); ++i) - { - values << d_ptr->m_values.at(row).at(i).toString(); +// - QList - values of the row. If row have invalid value, function will +// return empty QList. +QList VariantData::rowValues(const qsizetype row) const { + if (row < 0 || rowCount() <= row) { return {}; } + + QList values; + for (int i = 0; i < m_values.at(row).size(); ++i) { + values << m_values.at(row).at(i).toString(); } return values; } -bool VariantData::operator==(const VariantData& other) const -{ - return d_ptr->m_values == other.d_ptr->m_values; -} - -VariantData& VariantData::operator=(const VariantData& other) -{ - VariantData tmp(other); - std::swap(d_ptr, tmp.d_ptr); - return *this; -} - // Add new row that would contain one value -VariantData& VariantData::operator<<(const QVariant& value) -{ - this->addRow(value); +VariantData& VariantData::operator<<(const QVariant& value) { + addRow(value); return *this; } // Add new row with specified values -VariantData& VariantData::operator<<(const QList& values) -{ - this->addRow(values); +VariantData& VariantData::operator<<(const QList& values) { + addRow(values); return *this; } // Add new row with specified values -VariantData& VariantData::operator<<(const QStringList& values) -{ - this->addRow(values); +VariantData& VariantData::operator<<(const QList& values) { + addRow(values); return *this; } diff --git a/sources/writer.cpp b/sources/writer.cpp index 23040b4..1c1fbf5 100644 --- a/sources/writer.cpp +++ b/sources/writer.cpp @@ -1,15 +1,12 @@ #include "include/qtcsv/writer.h" -#include "include/qtcsv/abstractdata.h" -#include "sources/filechecker.h" #include "sources/contentiterator.h" -#include -#include -#include +#include "sources/filechecker.h" #include #include -#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)) - #include -#endif +#include +#include +#include +#include #include using namespace QtCSV; @@ -19,38 +16,35 @@ using namespace QtCSV; // create object of class TempFileHandler, you must specify absolute path // to the (temp) file (as a string). When object will be about to destroy, it // will try to remove specified file. -class TempFileHandler -{ +class TempFileHandler { QString m_filePath; public: explicit TempFileHandler(const QString& filePath) : m_filePath(filePath) {} - ~TempFileHandler() - { + ~TempFileHandler() { QFile::remove(m_filePath); } }; -class WriterPrivate -{ +class WriterPrivate { public: // Append information to the file static bool appendToFile( const QString& filePath, ContentIterator& content, - QTextCodec* codec); + QStringConverter::Encoding codec); // Overwrite file with new information static bool overwriteFile( const QString& filePath, ContentIterator& content, - QTextCodec* codec); + QStringConverter::Encoding codec); // Write to IO Device static bool writeToIODevice( QIODevice& ioDevice, ContentIterator& content, - QTextCodec* codec); + QStringConverter::Encoding codec); // Create unique name for the temporary file static QString getTempFileName(); @@ -66,23 +60,21 @@ class WriterPrivate bool WriterPrivate::appendToFile( const QString& filePath, ContentIterator& content, - QTextCodec* codec) + const QStringConverter::Encoding codec) { - if (filePath.isEmpty() || content.isEmpty()) - { + if (filePath.isEmpty() || content.isEmpty()) { qDebug() << __FUNCTION__ << "Error - invalid arguments"; return false; } QFile csvFile(filePath); - if (false == csvFile.open(QIODevice::Append | QIODevice::Text)) - { + if (!csvFile.open(QIODevice::Append | QIODevice::Text)) { qDebug() << __FUNCTION__ << "Error - can't open file:" << csvFile.fileName(); return false; } - bool result = writeToIODevice(csvFile, content, codec); + const auto result = writeToIODevice(csvFile, content, codec); csvFile.close(); return result; @@ -98,12 +90,11 @@ bool WriterPrivate::appendToFile( bool WriterPrivate::overwriteFile( const QString& filePath, ContentIterator& content, - QTextCodec* codec) + const QStringConverter::Encoding codec) { // Create path to the unique temporary file - QString tempFileName = getTempFileName(); - if (tempFileName.isEmpty()) - { + const auto tempFileName = getTempFileName(); + if (tempFileName.isEmpty()) { qDebug() << __FUNCTION__ << "Error - failed to create unique name for temp file"; return false; @@ -112,19 +103,17 @@ bool WriterPrivate::overwriteFile( TempFileHandler handler(tempFileName); // Write information to the temporary file - if (false == appendToFile(tempFileName, content, codec)) { return false; } + if (!appendToFile(tempFileName, content, codec)) { return false; } // Remove "old" file if it exists - if (QFile::exists(filePath) && false == QFile::remove(filePath)) - { + if (QFile::exists(filePath) && !QFile::remove(filePath)) { qDebug() << __FUNCTION__ << "Error - failed to remove file" << filePath; return false; } // Copy "new" file (temporary file) to the destination path (replace // "old" file) - if (false == QFile::copy(tempFileName, filePath)) - { + if (!QFile::copy(tempFileName, filePath)) { qDebug() << __FUNCTION__ << "Error - failed to copy temp file to" << filePath; return false; @@ -143,31 +132,26 @@ bool WriterPrivate::overwriteFile( bool WriterPrivate::writeToIODevice( QIODevice& ioDevice, ContentIterator& content, - QTextCodec* codec) + const QStringConverter::Encoding codec) { - if (content.isEmpty()) - { + if (content.isEmpty()) { qDebug() << __FUNCTION__ << "Error - invalid arguments"; return false; } // Open IO Device if it was not opened - if (false == ioDevice.isOpen() && - false == ioDevice.open(QIODevice::Append | QIODevice::Text)) + if (!ioDevice.isOpen() && + !ioDevice.open(QIODevice::Append | QIODevice::Text)) { qDebug() << __FUNCTION__ << "Error - failed to open IO Device"; return false; } QTextStream stream(&ioDevice); - stream.setCodec(codec); - while(content.hasNext()) - { - stream << content.getNext(); - } + stream.setEncoding(codec); + while (content.hasNext()) { stream << content.getNext(); } stream.flush(); - return stream.status() == QTextStream::Ok; } @@ -178,18 +162,15 @@ bool WriterPrivate::writeToIODevice( // string. QString WriterPrivate::getTempFileName() { - QString nameTemplate = QDir::tempPath() + "/qtcsv_" + + const auto nameTemplate = QDir::tempPath() + "/qtcsv_" + QString::number(QCoreApplication::applicationPid()) + "_%1.csv"; - for (int counter = 0; counter < std::numeric_limits::max(); ++counter) + for (auto counter = 0; counter < std::numeric_limits::max(); ++counter) { -#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)) QString name = nameTemplate.arg( QString::number(QRandomGenerator::global()->generate())); -#else - QString name = nameTemplate.arg(QString::number(qrand())); -#endif - if (false == QFile::exists(name)) { return name; } + + if (!QFile::exists(name)) { return name; } } return QString(); @@ -216,42 +197,38 @@ bool Writer::write( const AbstractData& data, const QString& separator, const QString& textDelimiter, - const WriteMode& mode, - const QStringList& header, - const QStringList& footer, - QTextCodec* codec) + const WriteMode mode, + const QList& header, + const QList& footer, + const QStringConverter::Encoding codec) { - if (filePath.isEmpty()) - { + if (filePath.isEmpty()) { qDebug() << __FUNCTION__ << "Error - empty path to file"; return false; } - if (data.isEmpty()) - { + if (data.isEmpty()) { qDebug() << __FUNCTION__ << "Error - empty data"; return false; } - if (false == CheckFile(filePath)) - { + if (false == CheckFile(filePath)) { qDebug() << __FUNCTION__ << "Error - wrong file path/name:" << filePath; return false; } ContentIterator content(data, separator, textDelimiter, header, footer); - bool result = false; switch (mode) { - case APPEND: - result = WriterPrivate::appendToFile(filePath, content, codec); - break; - case REWRITE: - default: - result = WriterPrivate::overwriteFile(filePath, content, codec); + case WriteMode::APPEND: + return WriterPrivate::appendToFile(filePath, content, codec); + break; + case WriteMode::REWRITE: + default: + return WriterPrivate::overwriteFile(filePath, content, codec); } - return result; + return false; } // Write data to IO Device @@ -273,12 +250,11 @@ bool Writer::write( const AbstractData& data, const QString& separator, const QString& textDelimiter, - const QStringList& header, - const QStringList& footer, - QTextCodec* codec) + const QList& header, + const QList& footer, + const QStringConverter::Encoding codec) { - if (data.isEmpty()) - { + if (data.isEmpty()) { qDebug() << __FUNCTION__ << "Error - empty data"; return false; } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 20d65a2..7d587fa 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,13 +1,6 @@ -if(USE_QT4) - find_package(Qt4 REQUIRED) - set(QT_TEST_TARGET Qt4::QtTest) -else() - # if cmake failed to find Qt5Test configuration file, set path manually: - #list(APPEND CMAKE_PREFIX_PATH "/path/to/Qt/lib/cmake/Qt5Test/") - - find_package(Qt5Test REQUIRED) - set(QT_TEST_TARGET Qt5::Test) -endif(USE_QT4) + +find_package(Qt6 COMPONENTS Test REQUIRED) +set(QT_TEST_TARGET Qt6::Test) # define names set(BINARY_NAME qtcsv_tests) diff --git a/tests/testreader.cpp b/tests/testreader.cpp index ae0e3bc..a7a4434 100644 --- a/tests/testreader.cpp +++ b/tests/testreader.cpp @@ -6,10 +6,7 @@ #include #include -TestReader::TestReader() {} - -void TestReader::testReadToListInvalidArgs() -{ +void TestReader::testReadToListInvalidArgs() { QVERIFY2(QtCSV::Reader::readToList(QString(), QString()).empty(), "Invalid arguments was accepted"); @@ -28,345 +25,314 @@ void TestReader::testReadToListInvalidArgs() "Invalid arguments was accepted"); } -void TestReader::testReadToDataInvalidArgs() -{ +void TestReader::testReadToDataInvalidArgs() { QtCSV::StringData data; - QVERIFY2(false == QtCSV::Reader::readToData(QString(), data, QString()), + QVERIFY2(!QtCSV::Reader::readToData(QString(), data, QString()), "Invalid arguments was accepted"); - QVERIFY2(false == QtCSV::Reader::readToData( + QVERIFY2(!QtCSV::Reader::readToData( getPathToFileTestComma(), data, QString()), "Invalid arguments was accepted"); - QVERIFY2(false == QtCSV::Reader::readToData(QString(), data, ","), + QVERIFY2(!QtCSV::Reader::readToData(QString(), data, ","), "Invalid arguments was accepted"); - QVERIFY2(false == QtCSV::Reader::readToData("./some/path.csv", data,","), + QVERIFY2(!QtCSV::Reader::readToData("./some/path.csv", data, ","), "Invalid arguments was accepted"); - QVERIFY2(false == QtCSV::Reader::readToData( - getPathToFileTestComma() + ".md5", data,","), + QVERIFY2(!QtCSV::Reader::readToData( + getPathToFileTestComma() + ".md5", data, ","), "Invalid arguments was accepted"); } -void TestReader::testReadFileWithCommas() -{ - const QString path = getPathToFileTestComma(); - QList data = QtCSV::Reader::readToList(path); +void TestReader::testReadFileWithCommas() { + const auto path = getPathToFileTestComma(); + const auto data = QtCSV::Reader::readToList(path); - QVERIFY2(false == data.isEmpty(), "Failed to read file content"); + QVERIFY2(!data.isEmpty(), "Failed to read file content"); - QList expected; - expected << (QStringList() << "one" << "two" << "three"); - expected << (QStringList() << "one_element"); - expected << (QStringList() << "1" << "2" << "3"); - expected << (QStringList()); - expected << (QStringList() << "3.14"); + QList> expected; + expected << (QList() << "one" << "two" << "three"); + expected << (QList() << "one_element"); + expected << (QList() << "1" << "2" << "3"); + expected << (QList()); + expected << (QList() << "3.14"); QVERIFY2(expected.size() == data.size(), "Wrong number of rows"); - for (int i = 0; i < data.size(); ++i) - { + for (auto i = 0; i < data.size(); ++i) { QVERIFY2(expected.at(i) == data.at(i), "Wrong row data"); } } -void TestReader::testReadFileWithDotsInName() -{ - const QString path = getPathToFileTestDotsInName(); - QList data = QtCSV::Reader::readToList(path); +void TestReader::testReadFileWithDotsInName() { + const auto path = getPathToFileTestDotsInName(); + const auto data = QtCSV::Reader::readToList(path); - QVERIFY2(false == data.isEmpty(), "Failed to read file content"); + QVERIFY2(!data.isEmpty(), "Failed to read file content"); - QList expected; - expected << (QStringList() << "one" << "two" << "three"); - expected << (QStringList() << "one_element"); + QList> expected; + expected << (QList() << "one" << "two" << "three"); + expected << (QList() << "one_element"); QVERIFY2(expected.size() == data.size(), "Wrong number of rows"); - for (int i = 0; i < data.size(); ++i) - { + for (auto i = 0; i < data.size(); ++i) { QVERIFY2(expected.at(i) == data.at(i), "Wrong row data"); } } -void TestReader::testReadFileWithCommasToStringData() -{ - const QString path = getPathToFileTestComma(); +void TestReader::testReadFileWithCommasToStringData() { + const auto path = getPathToFileTestComma(); QtCSV::StringData strData; - bool readResult = QtCSV::Reader::readToData(path, strData); - QVERIFY2(true == readResult, "Failed to read file content"); - QVERIFY2(false == strData.isEmpty(), "StringData is empty"); + const auto readResult = QtCSV::Reader::readToData(path, strData); + QVERIFY2(readResult, "Failed to read file content"); + QVERIFY2(!strData.isEmpty(), "StringData is empty"); - QList expected; - expected << (QStringList() << "one" << "two" << "three"); - expected << (QStringList() << "one_element"); - expected << (QStringList() << "1" << "2" << "3"); - expected << (QStringList()); - expected << (QStringList() << "3.14"); + QList> expected; + expected << (QList() << "one" << "two" << "three"); + expected << (QList() << "one_element"); + expected << (QList() << "1" << "2" << "3"); + expected << (QList()); + expected << (QList() << "3.14"); QVERIFY2(expected.size() == strData.rowCount(), "Wrong number of rows"); - for (int i = 0; i < strData.rowCount(); ++i) - { + for (auto i = 0; i < strData.rowCount(); ++i) { QVERIFY2(expected.at(i) == strData.rowValues(i), "Wrong row data"); } } -void TestReader::testReadFileWithCommasToVariantData() -{ - const QString path = getPathToFileTestComma(); +void TestReader::testReadFileWithCommasToVariantData() { + const auto path = getPathToFileTestComma(); QtCSV::VariantData varData; - bool readResult = QtCSV::Reader::readToData(path, varData); - QVERIFY2(true == readResult, "Failed to read file content"); - QVERIFY2(false == varData.isEmpty(), "StringData is empty"); + const auto readResult = QtCSV::Reader::readToData(path, varData); + QVERIFY2(readResult, "Failed to read file content"); + QVERIFY2(!varData.isEmpty(), "StringData is empty"); - QList expected; - expected << (QStringList() << "one" << "two" << "three"); - expected << (QStringList() << "one_element"); - expected << (QStringList() << "1" << "2" << "3"); - expected << (QStringList()); - expected << (QStringList() << "3.14"); + QList> expected; + expected << (QList() << "one" << "two" << "three"); + expected << (QList() << "one_element"); + expected << (QList() << "1" << "2" << "3"); + expected << (QList()); + expected << (QList() << "3.14"); QVERIFY2(expected.size() == varData.rowCount(), "Wrong number of rows"); - for (int i = 0; i < varData.rowCount(); ++i) - { + for (auto i = 0; i < varData.rowCount(); ++i) { QVERIFY2(expected.at(i) == varData.rowValues(i), "Wrong row data"); } } -void TestReader::testReadFileWithSemicolons() -{ - const QString path = getPathToFileTestSemicolon(); - QList data = QtCSV::Reader::readToList(path, ";"); +void TestReader::testReadFileWithSemicolons() { + const auto path = getPathToFileTestSemicolon(); + const auto data = QtCSV::Reader::readToList(path, ";"); - QVERIFY2(false == data.isEmpty(), "Failed to read file content"); + QVERIFY2(!data.isEmpty(), "Failed to read file content"); QVERIFY2(2 == data.size(), "Wrong number of rows"); - QStringList expectedFirstRow; + QList expectedFirstRow; expectedFirstRow << "1" << "2" << "3"; - QStringList expectedSecondRow; + QList expectedSecondRow; expectedSecondRow << "j" << "io" << "pp"; QVERIFY2(expectedFirstRow == data.at(0), "Wrong first row"); QVERIFY2(expectedSecondRow == data.at(1), "Wrong second row"); } -void TestReader::testReadFileWithSemicolonsToStringData() -{ - const QString path = getPathToFileTestSemicolon(); +void TestReader::testReadFileWithSemicolonsToStringData() { + const auto path = getPathToFileTestSemicolon(); QtCSV::StringData strData; - bool readResult = QtCSV::Reader::readToData(path, strData, ";"); - QVERIFY2(true == readResult, "Failed to read file content"); + const auto readResult = QtCSV::Reader::readToData(path, strData, ";"); + QVERIFY2(readResult, "Failed to read file content"); - QVERIFY2(false == strData.isEmpty(), "Failed to read file content"); + QVERIFY2(!strData.isEmpty(), "Failed to read file content"); QVERIFY2(2 == strData.rowCount(), "Wrong number of rows"); - QStringList expectedFirstRow; + QList expectedFirstRow; expectedFirstRow << "1" << "2" << "3"; - QStringList expectedSecondRow; + QList expectedSecondRow; expectedSecondRow << "j" << "io" << "pp"; QVERIFY2(expectedFirstRow == strData.rowValues(0), "Wrong first row"); QVERIFY2(expectedSecondRow == strData.rowValues(1), "Wrong second row"); } -void TestReader::testReadFileWithSemicolonsToVariantData() -{ - const QString path = getPathToFileTestSemicolon(); +void TestReader::testReadFileWithSemicolonsToVariantData() { + const auto path = getPathToFileTestSemicolon(); QtCSV::VariantData varData; - bool readResult = QtCSV::Reader::readToData(path, varData, ";"); - QVERIFY2(true == readResult, "Failed to read file content"); + const auto readResult = QtCSV::Reader::readToData(path, varData, ";"); + QVERIFY2(readResult, "Failed to read file content"); - QVERIFY2(false == varData.isEmpty(), "Failed to read file content"); + QVERIFY2(!varData.isEmpty(), "Failed to read file content"); QVERIFY2(2 == varData.rowCount(), "Wrong number of rows"); - QStringList expectedFirstRow; + QList expectedFirstRow; expectedFirstRow << "1" << "2" << "3"; - QStringList expectedSecondRow; + QList expectedSecondRow; expectedSecondRow << "j" << "io" << "pp"; QVERIFY2(expectedFirstRow == varData.rowValues(0), "Wrong first row"); QVERIFY2(expectedSecondRow == varData.rowValues(1), "Wrong second row"); } -void TestReader::testReadFileWithTextDelimDQoutes() -{ - const QString path = getPathToFileTestDataTextDelimDQuotes(); - QList data = QtCSV::Reader::readToList(path, ",", "\""); +void TestReader::testReadFileWithTextDelimDQoutes() { + const auto path = getPathToFileTestDataTextDelimDQuotes(); + const auto data = QtCSV::Reader::readToList(path, ",", "\""); - QVERIFY2(false == data.isEmpty(), "Failed to read file content"); + QVERIFY2(!data.isEmpty(), "Failed to read file content"); - QList expected; - expected << (QStringList() << "one" << "two" << "three, four" << "five"); - expected << (QStringList() << "this, is, one, element"); - expected << (QStringList() << "six" << "seven" << "eight"); + QList> expected; + expected << (QList() << "one" << "two" << "three, four" << "five"); + expected << (QList() << "this, is, one, element"); + expected << (QList() << "six" << "seven" << "eight"); QVERIFY2(expected.size() == data.size(), "Wrong number of rows"); - for (int i = 0; i < data.size(); ++i) - { + for (auto i = 0; i < data.size(); ++i) { QVERIFY2(expected.at(i) == data.at(i), "Wrong row data"); } } -void TestReader::testReadFileWithTextDelimQoutes() -{ - const QString path = getPathToFileTestDataTextDelimQuotes(); - QList data = QtCSV::Reader::readToList(path, ",", "'"); - QVERIFY2(false == data.isEmpty(), "Failed to read file content"); +void TestReader::testReadFileWithTextDelimQoutes() { + const auto path = getPathToFileTestDataTextDelimQuotes(); + const auto data = QtCSV::Reader::readToList(path, ",", "'"); + QVERIFY2(!data.isEmpty(), "Failed to read file content"); - QList expected; - expected << (QStringList() << "one" << "two" << "three, four" << "five"); - expected << (QStringList() << "this, is, one, element"); - expected << (QStringList() << "six" << "seven" << "eight"); + QList> expected; + expected << (QList() << "one" << "two" << "three, four" << "five"); + expected << (QList() << "this, is, one, element"); + expected << (QList() << "six" << "seven" << "eight"); QVERIFY2(expected.size() == data.size(), "Wrong number of rows"); - for (int i = 0; i < data.size(); ++i) - { + for (auto i = 0; i < data.size(); ++i) { QVERIFY2(expected.at(i) == data.at(i), "Wrong row data"); } } -void TestReader::testReadFileWithTextDelimDQToStringData() -{ - const QString path = getPathToFileTestDataTextDelimDQuotes(); +void TestReader::testReadFileWithTextDelimDQToStringData() { + const auto path = getPathToFileTestDataTextDelimDQuotes(); QtCSV::StringData strData; - bool readResult = QtCSV::Reader::readToData(path, strData, ",", "\""); - QVERIFY2(true == readResult, "Failed to read file content"); - QVERIFY2(false == strData.isEmpty(), "Failed to read file content"); + const auto readResult = QtCSV::Reader::readToData(path, strData, ",", "\""); + QVERIFY2(readResult, "Failed to read file content"); + QVERIFY2(!strData.isEmpty(), "Failed to read file content"); - QList expected; - expected << (QStringList() << "one" << "two" << "three, four" << "five"); - expected << (QStringList() << "this, is, one, element"); - expected << (QStringList() << "six" << "seven" << "eight"); + QList> expected; + expected << (QList() << "one" << "two" << "three, four" << "five"); + expected << (QList() << "this, is, one, element"); + expected << (QList() << "six" << "seven" << "eight"); QVERIFY2(expected.size() == strData.rowCount(), "Wrong number of rows"); - for (int i = 0; i < strData.rowCount(); ++i) - { + for (auto i = 0; i < strData.rowCount(); ++i) { QVERIFY2(expected.at(i) == strData.rowValues(i), "Wrong row data"); } } -void TestReader::testReadLongWithDQuotes() -{ - const QString path = getPathToFileTestFieldWithDQuotes(); - QList data = QtCSV::Reader::readToList(path, ",", "\""); - QVERIFY2(false == data.isEmpty(), "Failed to read file content"); +void TestReader::testReadLongWithDQuotes() { + const auto path = getPathToFileTestFieldWithDQuotes(); + const auto data = QtCSV::Reader::readToList(path, ",", "\""); + QVERIFY2(!data.isEmpty(), "Failed to read file content"); - QList expected; - expected << (QStringList() << "one" << "two" << "three"); - expected << (QStringList() << "four" << "very \"long\" field" << "five"); - expected << (QStringList() << "six" << "seven"); + QList> expected; + expected << (QList() << "one" << "two" << "three"); + expected << (QList() << "four" << "very \"long\" field" << "five"); + expected << (QList() << "six" << "seven"); QVERIFY2(expected.size() == data.size(), "Wrong number of rows"); - for (int i = 0; i < data.size(); ++i) - { + for (auto i = 0; i < data.size(); ++i) { QVERIFY2(expected.at(i) == data.at(i), "Wrong row data"); } } -void TestReader::testReadFieldWithCR() -{ - const QString path = getPathToFileTestFieldWithCR(); - QList data = QtCSV::Reader::readToList(path, ";", "\""); - QVERIFY2(false == data.isEmpty(), "Failed to read file content"); +void TestReader::testReadFieldWithCR() { + const auto path = getPathToFileTestFieldWithCR(); + const auto data = QtCSV::Reader::readToList(path, ";", "\""); + QVERIFY2(!data.isEmpty(), "Failed to read file content"); - QList expected; - expected << (QStringList() << "Column1, Column2" << "Column3"); - expected << (QStringList() << " Hello with\r Hello again " << "Hello Col 3"); + QList> expected; + expected << (QList() << "Column1, Column2" << "Column3"); + expected << (QList() << " Hello with\r Hello again " << "Hello Col 3"); QVERIFY2(expected.size() == data.size(), "Wrong number of rows"); - for (int i = 0; i < data.size(); ++i) - { + for (auto i = 0; i < data.size(); ++i) { + qWarning() << expected.at(i) << data.at(i); QVERIFY2(expected.at(i) == data.at(i), "Wrong row data"); } } -void TestReader::testReadFieldWithCRLF() -{ - const QString path = getPathToFileTestFieldWithCRLF(); - QList data = QtCSV::Reader::readToList(path, ",", "\""); - QVERIFY2(false == data.isEmpty(), "Failed to read file content"); +void TestReader::testReadFieldWithCRLF() { + const auto path = getPathToFileTestFieldWithCRLF(); + const auto data = QtCSV::Reader::readToList(path, ",", "\""); + QVERIFY2(!data.isEmpty(), "Failed to read file content"); - QList expected; - expected << (QStringList() << "one" << "two" << "three\nfour" << "five"); - expected << (QStringList() << "six" << "seven"); + QList> expected; + expected << (QList() << "one" << "two" << "three\nfour" << "five"); + expected << (QList() << "six" << "seven"); QVERIFY2(expected.size() == data.size(), "Wrong number of rows"); - for (int i = 0; i < data.size(); ++i) - { + for (auto i = 0; i < data.size(); ++i) { QVERIFY2(expected.at(i) == data.at(i), "Wrong row data"); } } -void TestReader::testReadFieldWithCRLFLong() -{ - const QString path = getPathToFileTestFieldWithCRLFLong(); - QList data = QtCSV::Reader::readToList(path, ",", "\""); - QVERIFY2(false == data.isEmpty(), "Failed to read file content"); +void TestReader::testReadFieldWithCRLFLong() { + const auto path = getPathToFileTestFieldWithCRLFLong(); + const auto data = QtCSV::Reader::readToList(path, ",", "\""); + QVERIFY2(!data.isEmpty(), "Failed to read file content"); - QList expected; - expected << (QStringList() << "one" << "two" << + QList> expected; + expected << (QList() << "one" << "two" << "three\nfour,\"five\n\"six\",seven\neight" << "nine"); - expected << (QStringList() << "ten" << "eleven"); + expected << (QList() << "ten" << "eleven"); QVERIFY2(expected.size() == data.size(), "Wrong number of rows"); - for (int i = 0; i < data.size(); ++i) - { + for (auto i = 0; i < data.size(); ++i) { QVERIFY2(expected.at(i) == data.at(i), "Wrong row data"); } } -void TestReader::testReadFieldEndTripleQuotes() -{ - const QString path = getPathToFileTestFieldEndTripleQuotes(); - QList data = QtCSV::Reader::readToList(path, ",", "\""); - QVERIFY2(false == data.isEmpty(), "Failed to read file content"); +void TestReader::testReadFieldEndTripleQuotes() { + const auto path = getPathToFileTestFieldEndTripleQuotes(); + const auto data = QtCSV::Reader::readToList(path, ",", "\""); + QVERIFY2(!data.isEmpty(), "Failed to read file content"); - QList expected; - expected << (QStringList() << "CCLK=\"yy/MM/dd,hh:mm:ssA+zz\"" << "test"); - expected << (QStringList() << "new" << "line \"it is\",\"def"); + QList> expected; + expected << (QList() << "CCLK=\"yy/MM/dd,hh:mm:ssA+zz\"" << "test"); + expected << (QList() << "new" << "line \"it is\",\"def"); QVERIFY2(expected.size() == data.size(), "Wrong number of rows"); - for (int i = 0; i < data.size(); ++i) - { + for (auto i = 0; i < data.size(); ++i) { QVERIFY2(expected.at(i) == data.at(i), "Wrong row data"); } } -void TestReader::testReadFileDataCorrectness() -{ - const QString path = getPathToFileTestDataCorrectness(); - QList data = QtCSV::Reader::readToList(path, ",", "\""); - QVERIFY2(false == data.isEmpty(), "Failed to read file content"); +void TestReader::testReadFileDataCorrectness() { + const auto path = getPathToFileTestDataCorrectness(); + const auto data = QtCSV::Reader::readToList(path, ",", "\""); + QVERIFY2(!data.isEmpty(), "Failed to read file content"); - QList expected; - expected << (QStringList() << "Year" << "Make" << "Model" << + QList> expected; + expected << (QList() << "Year" << "Make" << "Model" << "Description" << "Price"); - expected << (QStringList() << "1997" << "Ford" << "E350" << + expected << (QList() << "1997" << "Ford" << "E350" << "ac, abs, moon" << "3000.00"); - expected << (QStringList() << "1999" << "Chevy" << + expected << (QList() << "1999" << "Chevy" << "Venture \"Extended Edition\"" << "" << "4900.00"); - expected << (QStringList() << "1996" << "Jeep" << "Grand Cherokee" << + expected << (QList() << "1996" << "Jeep" << "Grand Cherokee" << "MUST SELL!\nair, moon roof, loaded" << "4799.00"); - expected << (QStringList() << "1999" << "Chevy" << + expected << (QList() << "1999" << "Chevy" << "Venture \"Extended Edition, Very Large\"" << "" << "5000.00"); - expected << (QStringList() << "" << "" << "Venture \"Extended Edition\"" << - "" << "4900.00"); + expected << (QList() << "" << "" << + "Venture \"Extended Edition\"" << "" << "4900.00"); QVERIFY2(expected.size() == data.size(), "Wrong number of rows"); - for (int i = 0; i < data.size(); ++i) - { + for (auto i = 0; i < data.size(); ++i) { QVERIFY2(expected.at(i) == data.at(i), "Wrong row data"); } } -void TestReader::testReadFileWorldCitiesPop() -{ - const QString path = getPathToFileWorldCitiesPop(); - if (false == QFile::exists(path)) - { +void TestReader::testReadFileWorldCitiesPop() { + const auto path = getPathToFileWorldCitiesPop(); + if (!QFile::exists(path)) { qDebug() << "Skip testReadFileWorldCitiesPop() because file" << path << "do not exist. If you want to run this test, download file " "from http://www.maxmind.com/download/worldcities/worldcitiespop.txt.gz"; @@ -375,83 +341,68 @@ void TestReader::testReadFileWorldCitiesPop() QElapsedTimer timer; timer.start(); - QList data = QtCSV::Reader::readToList(path, ",", "\""); + const auto data = QtCSV::Reader::readToList(path, ",", "\""); qDebug() << "Elapsed time:" << timer.elapsed() << "ms"; - QVERIFY2(false == data.isEmpty(), "Failed to read file content"); + QVERIFY2(!data.isEmpty(), "Failed to read file content"); QVERIFY2(3173959 == data.size(), "Wrong number of rows"); } -void TestReader::testReadFileWithEmptyFields() -{ - const QString path = getPathToFileWithEmptyFields(); - QList data = QtCSV::Reader::readToList(path, ",", "\""); - QVERIFY2(false == data.isEmpty(), "Failed to read file content"); +void TestReader::testReadFileWithEmptyFields() { + const auto path = getPathToFileWithEmptyFields(); + const auto data = QtCSV::Reader::readToList(path, ",", "\""); + QVERIFY2(!data.isEmpty(), "Failed to read file content"); - QList expected; - expected << (QStringList() << QString() << "0" << QString() << QString()); + QList> expected; + expected << (QList() << QString() << "0" << QString() << QString()); QVERIFY2(expected.size() == data.size(), "Wrong number of rows"); - for (int i = 0; i < data.size(); ++i) - { + for (auto i = 0; i < data.size(); ++i) { QVERIFY2(expected.at(i) == data.at(i), "Wrong row data"); } } -void TestReader::testReadFileWithEmptyFieldsComplexSeparator() -{ - const QString path = getPathToFileWithEmptyFieldsComplexSeparator(); - QList data = QtCSV::Reader::readToList(path, ";-;", "\""); - QVERIFY2(false == data.isEmpty(), "Failed to read file content"); +void TestReader::testReadFileWithEmptyFieldsComplexSeparator() { + const auto path = getPathToFileWithEmptyFieldsComplexSeparator(); + const auto data = QtCSV::Reader::readToList(path, ";-;", "\""); + QVERIFY2(!data.isEmpty(), "Failed to read file content"); - QList expected; - expected << (QStringList() << "0" << "1" << QString() << QString()); - expected << (QStringList() << QString() << "Question" << "158" << QString() - << QString()); + QList> expected; + expected << (QList() << "0" << "1" << QString() << QString()); + expected << (QList() << QString() << "Question" << "158" << + QString() << QString()); QVERIFY2(expected.size() == data.size(), "Wrong number of rows"); - for (int i = 0; i < data.size(); ++i) - { + for (auto i = 0; i < data.size(); ++i) { QVERIFY2(expected.at(i) == data.at(i), "Wrong row data"); } } -void TestReader::testReadFileWithMultirowData() -{ - const QString path = getPathToFileMultirowData(); - QList data = QtCSV::Reader::readToList(path); - QVERIFY2(false == data.isEmpty(), "Failed to read file content"); +void TestReader::testReadFileWithMultirowData() { + const auto path = getPathToFileMultirowData(); + const auto data = QtCSV::Reader::readToList(path); + QVERIFY2(!data.isEmpty(), "Failed to read file content"); - QList expected; - expected << (QStringList() << "A" << "B" << "C" << "D"); - expected << (QStringList() << "a" << "b" << "c" << "d"); - expected << (QStringList() << "a" << "b field" << "c field\n" << "d field"); - expected << (QStringList() << "aa" << "bb" << "cc" << "dd"); + QList> expected; + expected << (QList() << "A" << "B" << "C" << "D"); + expected << (QList() << "a" << "b" << "c" << "d"); + expected << (QList() << "a" << "b field" << "c field\n" << "d field"); + expected << (QList() << "aa" << "bb" << "cc" << "dd"); QVERIFY2(expected.size() == data.size(), "Wrong number of rows"); - for (int i = 0; i < data.size(); ++i) - { + for (auto i = 0; i < data.size(); ++i) { QVERIFY2(expected.at(i) == data.at(i), "Wrong row data"); } } -void TestReader::testReadByProcessorWithBreak() -{ - class ProcessorWithBreak : public QtCSV::Reader::AbstractProcessor - { +void TestReader::testReadByProcessorWithBreak() { + class ProcessorWithBreak : public QtCSV::Reader::AbstractProcessor { public: - size_t counter; - QList data; - - ProcessorWithBreak() - { - counter = 0; - } + size_t counter = 0; + QList> data; - virtual bool processRowElements(const QStringList& elements) - { - if (counter < 2) - { + bool processRowElements(const QList& elements) override { + if (counter < 2) { data << elements; ++counter; } @@ -460,100 +411,83 @@ void TestReader::testReadByProcessorWithBreak() } }; - const QString path = getPathToFileMultirowData(); + const auto path = getPathToFileMultirowData(); ProcessorWithBreak processor; - QVERIFY2(true == QtCSV::Reader::readToProcessor(path, processor), + QVERIFY2(QtCSV::Reader::readToProcessor(path, processor), "Failed to read file content"); - QList expected; - expected << (QStringList() << "A" << "B" << "C" << "D"); - expected << (QStringList() << "a" << "b" << "c" << "d"); + QList> expected; + expected << (QList() << "A" << "B" << "C" << "D"); + expected << (QList() << "a" << "b" << "c" << "d"); QVERIFY2(expected.size() == processor.data.size(), "Wrong number of rows"); - for (int i = 0; i < processor.data.size(); ++i) - { + for (auto i = 0; i < processor.data.size(); ++i) { QVERIFY2(expected.at(i) == processor.data.at(i), "Wrong row data"); } } -QString TestReader::getPathToFolderWithTestFiles() const -{ +QString TestReader::getPathToFolderWithTestFiles() const { return QDir::currentPath() + "/data/"; } -QString TestReader::getPathToFileTestComma() const -{ +QString TestReader::getPathToFileTestComma() const { return getPathToFolderWithTestFiles() + "test-comma.csv"; } -QString TestReader::getPathToFileTestDotsInName() const -{ +QString TestReader::getPathToFileTestDotsInName() const { return getPathToFolderWithTestFiles() + "test.file.dots.csv"; } -QString TestReader::getPathToFileTestSemicolon() const -{ +QString TestReader::getPathToFileTestSemicolon() const { return getPathToFolderWithTestFiles() + "test-semicolon.csv"; } -QString TestReader::getPathToFileTestDataTextDelimDQuotes() const -{ +QString TestReader::getPathToFileTestDataTextDelimDQuotes() const { return getPathToFolderWithTestFiles() + - "test-data-text-delim-double-quotes.csv"; + "test-data-text-delim-double-quotes.csv"; } -QString TestReader::getPathToFileTestDataTextDelimQuotes() const -{ +QString TestReader::getPathToFileTestDataTextDelimQuotes() const { return getPathToFolderWithTestFiles() + "test-data-text-delim-quotes.csv"; } -QString TestReader::getPathToFileTestFieldWithDQuotes() const -{ +QString TestReader::getPathToFileTestFieldWithDQuotes() const { return getPathToFolderWithTestFiles() + "test-field-with-dquotes.csv"; } -QString TestReader::getPathToFileTestFieldWithCR() const -{ +QString TestReader::getPathToFileTestFieldWithCR() const { return getPathToFolderWithTestFiles() + "test-field-with-cr.csv"; } -QString TestReader::getPathToFileTestFieldWithCRLF() const -{ +QString TestReader::getPathToFileTestFieldWithCRLF() const { return getPathToFolderWithTestFiles() + "test-field-with-crlf.csv"; } -QString TestReader::getPathToFileTestFieldWithCRLFLong() const -{ +QString TestReader::getPathToFileTestFieldWithCRLFLong() const { return getPathToFolderWithTestFiles() + "test-field-with-crlf-long.csv"; } -QString TestReader::getPathToFileTestFieldEndTripleQuotes() const -{ +QString TestReader::getPathToFileTestFieldEndTripleQuotes() const { return getPathToFolderWithTestFiles() + "test-field-end-triple-quotes.csv"; } -QString TestReader::getPathToFileTestDataCorrectness() const -{ +QString TestReader::getPathToFileTestDataCorrectness() const { return getPathToFolderWithTestFiles() + "test-data-correctness.csv"; } -QString TestReader::getPathToFileWorldCitiesPop() const -{ +QString TestReader::getPathToFileWorldCitiesPop() const { return getPathToFolderWithTestFiles() + "worldcitiespop.txt"; } -QString TestReader::getPathToFileWithEmptyFields() const -{ +QString TestReader::getPathToFileWithEmptyFields() const { return getPathToFolderWithTestFiles() + "test-empty-fields.csv"; } -QString TestReader::getPathToFileWithEmptyFieldsComplexSeparator() const -{ +QString TestReader::getPathToFileWithEmptyFieldsComplexSeparator() const { return getPathToFolderWithTestFiles() + - "test-empty-fields-complex-separator.csv"; + "test-empty-fields-complex-separator.csv"; } -QString TestReader::getPathToFileMultirowData() const -{ +QString TestReader::getPathToFileMultirowData() const { return getPathToFolderWithTestFiles() + "test-multirow-data.csv"; } diff --git a/tests/testreader.h b/tests/testreader.h index 4fa49bb..f71667f 100644 --- a/tests/testreader.h +++ b/tests/testreader.h @@ -4,12 +4,11 @@ #include #include -class TestReader : public QObject -{ +class TestReader : public QObject { Q_OBJECT public: - TestReader(); + TestReader() = default; private Q_SLOTS: void testReadToListInvalidArgs(); diff --git a/tests/teststringdata.cpp b/tests/teststringdata.cpp index 88fefee..843015b 100644 --- a/tests/teststringdata.cpp +++ b/tests/teststringdata.cpp @@ -3,64 +3,55 @@ #include #include -TestStringData::TestStringData() {} - -void TestStringData::testCreation() -{ +void TestStringData::testCreation() { QtCSV::StringData strData; QVERIFY2(strData.isEmpty(), "Empty StringData is not empty"); - QVERIFY2(strData.rowCount() == 0, - "Empty StringData have too many rows"); + QVERIFY2(strData.rowCount() == 0, "Empty StringData have too many rows"); } -void TestStringData::testAddEmptyRow() -{ +void TestStringData::testAddEmptyRow() { QtCSV::StringData strData; strData.addEmptyRow(); - QVERIFY2(false == strData.isEmpty(), "StringData is empty with empty line"); + QVERIFY2(!strData.isEmpty(), "StringData is empty with empty line"); QVERIFY2(1 == strData.rowCount(), "Wrong number of rows"); - QVERIFY2(QStringList() == strData.rowValues(0), - "Wrong data for empty row"); + QVERIFY2(QList() == strData.rowValues(0), "Wrong data for empty row"); } -void TestStringData::testAddOneRow() -{ - QStringList rowValues; +void TestStringData::testAddOneRow() { + QList rowValues; rowValues << "one" << "two" << "three"; QtCSV::StringData strData; strData.addRow(rowValues); - QVERIFY2(false == strData.isEmpty(), "StringData is empty"); + QVERIFY2(!strData.isEmpty(), "StringData is empty"); QVERIFY2(1 == strData.rowCount(), "Wrong number of rows"); QVERIFY2(rowValues == strData.rowValues(0), "Wrong data for empty row"); } -void TestStringData::testAddOneRowUsingOneString() -{ +void TestStringData::testAddOneRowUsingOneString() { QString value("faklj;"); QtCSV::StringData strData; strData.addRow(value); - QVERIFY2(false == strData.isEmpty(), "StringData is empty"); + QVERIFY2(!strData.isEmpty(), "StringData is empty"); QVERIFY2(1 == strData.rowCount(), "Wrong number of rows"); - QStringList expectedRow; + QList expectedRow; expectedRow << value; QVERIFY2(expectedRow == strData.rowValues(0), "Wrong data for empty row"); } -void TestStringData::testAddRows() -{ - QStringList valuesFirst; +void TestStringData::testAddRows() { + QList valuesFirst; valuesFirst << "1" << "2" << "3"; - QStringList valuesSecond; + QList valuesSecond; - QStringList valuesThird; + QList valuesThird; valuesFirst << "hhh" << "ttyyeeqp[" << "n...589129"; QtCSV::StringData strData; @@ -68,42 +59,35 @@ void TestStringData::testAddRows() strData.addRow(valuesSecond); strData.addRow(valuesThird); - QVERIFY2(false == strData.isEmpty(), "StringData is empty"); + QVERIFY2(!strData.isEmpty(), "StringData is empty"); QVERIFY2(3 == strData.rowCount(), "Wrong number of rows"); QVERIFY2(valuesFirst == strData.rowValues(0), "Wrong data for first row"); QVERIFY2(valuesSecond == strData.rowValues(1), "Wrong data for second row"); QVERIFY2(valuesThird == strData.rowValues(2), "Wrong data for third row"); } -void TestStringData::testClearEmptyData() -{ +void TestStringData::testClearEmptyData() { QtCSV::StringData strData; - - QVERIFY2(true == strData.isEmpty(), "StringData is not empty"); + QVERIFY2(strData.isEmpty(), "StringData is not empty"); strData.clear(); - - QVERIFY2(true == strData.isEmpty(), "StringData is not empty"); + QVERIFY2(strData.isEmpty(), "StringData is not empty"); } -void TestStringData::testClearNotEmptyData() -{ - QStringList rowValues; +void TestStringData::testClearNotEmptyData() { + QList rowValues; rowValues << "one" << "two" << "three"; QtCSV::StringData strData; strData.addRow(rowValues); - - QVERIFY2(false == strData.isEmpty(), "StringData is empty"); + QVERIFY2(!strData.isEmpty(), "StringData is empty"); strData.clear(); - - QVERIFY2(true == strData.isEmpty(), "StringData is not empty"); + QVERIFY2(strData.isEmpty(), "StringData is not empty"); } -void TestStringData::testInsertRows() -{ - QStringList valuesFirst, valuesSecond; +void TestStringData::testInsertRows() { + QList valuesFirst, valuesSecond; valuesFirst << "one" << "two" << "three"; valuesSecond << "asgreg" << "ertetw" << ""; @@ -123,17 +107,16 @@ void TestStringData::testInsertRows() QVERIFY2(5 == strData.rowCount(), "Wrong number of rows"); QVERIFY2(valuesFirst == strData.rowValues(0), "Wrong data for first row"); QVERIFY2(valuesSecond == strData.rowValues(1), "Wrong data for second row"); - QVERIFY2(QStringList() == strData.rowValues(2), "Wrong data for third row"); - QVERIFY2((QStringList() << stringOne) == strData.rowValues(3), + QVERIFY2(strData.rowValues(2).isEmpty(), "Wrong data for third row"); + QVERIFY2((QList() << stringOne) == strData.rowValues(3), "Wrong data for fourth row"); - QVERIFY2((QStringList() << stringTwo) == strData.rowValues(4), + QVERIFY2((QList() << stringTwo) == strData.rowValues(4), "Wrong data for fifth row"); } -void TestStringData::testCompareForEquality() -{ - QStringList firstRow, secondRow; +void TestStringData::testCompareForEquality() { + QList firstRow, secondRow; firstRow << "one" << "two" << "three"; secondRow << "four" << "five"; @@ -148,21 +131,20 @@ void TestStringData::testCompareForEquality() QVERIFY2(firstData == firstData, "Failed to compare for equality same object"); - QVERIFY2(false == (firstData != firstData), + QVERIFY2(!(firstData != firstData), "Failed to compare for equality same object"); QVERIFY2(firstData == secondData, "Objects are not the same"); - QVERIFY2(false == (firstData != secondData), "Objects are not the same"); + QVERIFY2(!(firstData != secondData), "Objects are not the same"); secondData.addRow(firstRow); - QVERIFY2(false == (firstData == secondData), "Objects are the same"); + QVERIFY2(!(firstData == secondData), "Objects are the same"); QVERIFY2(firstData != secondData, "Objects are the same"); } -void TestStringData::testCopyConstruction() -{ - QStringList firstRow, secondRow; +void TestStringData::testCopyConstruction() { + QList firstRow, secondRow; firstRow << "one" << "two" << "three"; secondRow << "four" << "five"; @@ -188,9 +170,8 @@ void TestStringData::testCopyConstruction() QVERIFY2(secondRow == firstData.rowValues(1), "Wrong data for second row"); } -void TestStringData::testCopyAssignment() -{ - QStringList firstRow, secondRow; +void TestStringData::testCopyAssignment() { + QList firstRow, secondRow; firstRow << "one" << "two" << "three"; secondRow << "four" << "five"; @@ -217,19 +198,18 @@ void TestStringData::testCopyAssignment() QVERIFY2(secondRow == firstData.rowValues(1), "Wrong data for second row"); } -void TestStringData::testOperatorInput() -{ +void TestStringData::testOperatorInput() { QtCSV::StringData data; data << QString("1") << "one"; - QStringList thirdRow; + QList thirdRow; thirdRow << "one" << "two" << "three"; data << thirdRow; QVERIFY2(3 == data.rowCount(), "Wrong number of rows"); - QStringList expectedFirstRow, expectedSecondRow; + QList expectedFirstRow, expectedSecondRow; expectedFirstRow << "1"; expectedSecondRow << "one"; @@ -240,15 +220,14 @@ void TestStringData::testOperatorInput() QVERIFY2(thirdRow == data.rowValues(2), "Wrong data for third row"); } -void TestStringData::testRemoveRow() -{ +void TestStringData::testRemoveRow() { QtCSV::StringData strData; strData.removeRow(0); strData.removeRow(563); - QVERIFY2(true == strData.isEmpty(), "Container is not empty"); + QVERIFY2(strData.isEmpty(), "Container is not empty"); - QStringList valuesFirst, valuesSecond; + QList valuesFirst, valuesSecond; valuesFirst << "one" << "two" << "three"; valuesSecond << "asgreg" << "ertetw" << ""; @@ -261,13 +240,12 @@ void TestStringData::testRemoveRow() QVERIFY2(3 == strData.rowCount(), "Wrong number of rows"); QVERIFY2(valuesFirst == strData.rowValues(0), "Wrong data for first row"); QVERIFY2(valuesSecond == strData.rowValues(1), "Wrong data for second row"); - QVERIFY2((QStringList() << stringTwo) == strData.rowValues(2), + QVERIFY2((QList() << stringTwo) == strData.rowValues(2), "Wrong data for third row"); } -void TestStringData::testReplaceRow() -{ - QStringList valuesFirst, valuesSecond; +void TestStringData::testReplaceRow() { + QList valuesFirst, valuesSecond; valuesFirst << "one" << "two" << "three"; valuesSecond << "asgreg" << "ertetw" << ""; @@ -277,11 +255,11 @@ void TestStringData::testReplaceRow() strData << valuesFirst << valuesSecond << stringOne; strData.replaceRow(0, stringTwo); - QVERIFY2((QStringList() << stringTwo) == strData.rowValues(0), + QVERIFY2((QList() << stringTwo) == strData.rowValues(0), "Wrong data for first row"); - strData.replaceRow(2, QStringList()); - QVERIFY2(QStringList() == strData.rowValues(2), "Wrong data for third row"); + strData.replaceRow(2, QList()); + QVERIFY2(QList() == strData.rowValues(2), "Wrong data for third row"); strData.replaceRow(1, valuesFirst); QVERIFY2(valuesFirst == strData.rowValues(1), "Wrong data for second row"); diff --git a/tests/teststringdata.h b/tests/teststringdata.h index 5b1a721..86b07a5 100644 --- a/tests/teststringdata.h +++ b/tests/teststringdata.h @@ -3,12 +3,11 @@ #include -class TestStringData : public QObject -{ +class TestStringData : public QObject { Q_OBJECT public: - TestStringData(); + TestStringData() = default; private Q_SLOTS: void testCreation(); diff --git a/tests/testvariantdata.cpp b/tests/testvariantdata.cpp index adcc18a..fff4d12 100644 --- a/tests/testvariantdata.cpp +++ b/tests/testvariantdata.cpp @@ -3,30 +3,24 @@ const double EPSILON = 0.000001; -TestVariantData::TestVariantData() {} - -void TestVariantData::testCreation() -{ +void TestVariantData::testCreation() { QtCSV::VariantData varData; QVERIFY2(varData.isEmpty(), "Empty VariantData is not empty"); - QVERIFY2(varData.rowCount() == 0, - "Empty VariantData have too many rows"); + QVERIFY2(varData.rowCount() == 0, "Empty VariantData have too many rows"); } -void TestVariantData::testAddEmptyRow() -{ +void TestVariantData::testAddEmptyRow() { QtCSV::VariantData varData; varData.addEmptyRow(); - QVERIFY2(false == varData.isEmpty(), "VariantData is empty with empty line"); + QVERIFY2(!varData.isEmpty(), + "VariantData is empty with empty line"); QVERIFY2(1 == varData.rowCount(), "Wrong number of rows"); - QVERIFY2(QStringList() == varData.rowValues(0), - "Wrong data for empty row"); + QVERIFY2(QStringList() == varData.rowValues(0), "Wrong data for empty row"); } -void TestVariantData::testAddOneRow() -{ +void TestVariantData::testAddOneRow() { QList values; QString strValue("Hey"); int intValue = 7000; @@ -35,37 +29,35 @@ void TestVariantData::testAddOneRow() QtCSV::VariantData varData; varData.addRow(values); - QVERIFY2(false == varData.isEmpty(), "VariantData is empty"); + QVERIFY2(!varData.isEmpty(), "VariantData is empty"); QVERIFY2(1 == varData.rowCount(), "Wrong number of rows"); QStringList resultValues = varData.rowValues(0); QVERIFY2(2 == resultValues.size(), "Wrong number of values"); - int resultInt = resultValues.at(1).toInt(); + auto resultInt = resultValues.at(1).toInt(); QVERIFY2(strValue == resultValues.at(0), "Wrong string data"); QVERIFY2(resultInt == intValue, "Wrong int data"); } -void TestVariantData::testAddOneRowUsingOneElement() -{ +void TestVariantData::testAddOneRowUsingOneElement() { int expectedValue = 42; QVariant varValue(expectedValue); QtCSV::VariantData varData; varData.addRow(varValue); - QVERIFY2(false == varData.isEmpty(), "VariantData is empty"); + QVERIFY2(!varData.isEmpty(), "VariantData is empty"); QVERIFY2(1 == varData.rowCount(), "Wrong number of rows"); QStringList values = varData.rowValues(0); QVERIFY2(1 == values.size(), "Wrong number of values"); - int resultValue = values.at(0).toInt(); + auto resultValue = values.at(0).toInt(); QVERIFY2(resultValue == expectedValue, "Wrong data"); } -void TestVariantData::testAddRows() -{ +void TestVariantData::testAddRows() { double expectedValue = 42.12309; QVariant firstRow(expectedValue); @@ -80,13 +72,13 @@ void TestVariantData::testAddRows() varData.addRow(secondRow); varData.addRow(thirdRow); - QVERIFY2(false == varData.isEmpty(), "VariantData is empty"); + QVERIFY2(!varData.isEmpty(), "VariantData is empty"); QVERIFY2(3 == varData.rowCount(), "Wrong number of rows"); QStringList values = varData.rowValues(0); QVERIFY2(1 == values.size(), "Wrong number of values for first row"); - double resultValue = values.at(0).toDouble(); + auto resultValue = values.at(0).toDouble(); QVERIFY2(resultValue - expectedValue < EPSILON, "Wrong double value"); QStringList secondRowValues = varData.rowValues(1); @@ -99,27 +91,23 @@ void TestVariantData::testAddRows() QVERIFY2(secondRow.at(1).toInt() == secondRowValues.at(1).toInt(), "Wrong second element in second row"); - double diff = secondRow.at(2).toDouble() - secondRowValues.at(2).toDouble(); + auto diff = secondRow.at(2).toDouble() - secondRowValues.at(2).toDouble(); QVERIFY2(diff <= EPSILON, "Wrong third element in second row"); QVERIFY2(thirdRow == varData.rowValues(2), "Wrong third row values"); } -void TestVariantData::testClearEmptyData() -{ +void TestVariantData::testClearEmptyData() { QtCSV::VariantData varData; - - QVERIFY2(true == varData.isEmpty(), "VariantData is not empty"); + QVERIFY2(varData.isEmpty(), "VariantData is not empty"); QVERIFY2(0 == varData.rowCount(), "Wrong number of rows"); varData.clear(); - - QVERIFY2(true == varData.isEmpty(), "VariantData is not empty"); + QVERIFY2(varData.isEmpty(), "VariantData is not empty"); QVERIFY2(0 == varData.rowCount(), "Wrong number of rows"); } -void TestVariantData::testClearNotEmptyData() -{ +void TestVariantData::testClearNotEmptyData() { double expectedValue = 42.12309; QVariant firstRow(expectedValue); @@ -134,17 +122,15 @@ void TestVariantData::testClearNotEmptyData() varData.addRow(secondRow); varData.addRow(thirdRow); - QVERIFY2(false == varData.isEmpty(), "VariantData is empty"); + QVERIFY2(!varData.isEmpty(), "VariantData is empty"); QVERIFY2(3 == varData.rowCount(), "Wrong number of rows"); varData.clear(); - - QVERIFY2(true == varData.isEmpty(), "VariantData is not empty"); + QVERIFY2(varData.isEmpty(), "VariantData is not empty"); QVERIFY2(0 == varData.rowCount(), "Wrong number of rows"); } -void TestVariantData::testInsertRows() -{ +void TestVariantData::testInsertRows() { double expectedValue = 42.12309; QVariant firstRow(expectedValue); @@ -163,7 +149,7 @@ void TestVariantData::testInsertRows() QVERIFY2(1 == varData.rowValues(0).size(), "Wrong number of elements in first row"); - double diff = expectedValue - varData.rowValues(0).at(0).toDouble(); + auto diff = expectedValue - varData.rowValues(0).at(0).toDouble(); QVERIFY2(diff <= EPSILON, "Wrong number in first row"); varData.addEmptyRow(); @@ -182,8 +168,7 @@ void TestVariantData::testInsertRows() secondRow.at(2).toString() == resultSecondRow.at(2), "Wrong data for second row"); - QVERIFY2(QStringList() == varData.rowValues(2), - "Wrong data for third row"); + QVERIFY2(QStringList() == varData.rowValues(2), "Wrong data for third row"); QVERIFY2((QStringList() << stringOne) == varData.rowValues(3), "Wrong data for fourth row"); @@ -191,8 +176,7 @@ void TestVariantData::testInsertRows() QVERIFY2(thirdRow == varData.rowValues(4), "Wrong data for fifth row"); } -void TestVariantData::testCompareForEquality() -{ +void TestVariantData::testCompareForEquality() { QStringList firstRow, secondRow; firstRow << "one" << "two" << "three"; secondRow << "four" << "five"; @@ -207,20 +191,19 @@ void TestVariantData::testCompareForEquality() QVERIFY2(firstData == firstData, "Failed to compare for equality same object"); - QVERIFY2(false == (firstData != firstData), + QVERIFY2(!(firstData != firstData), "Failed to compare for equality same object"); QVERIFY2(firstData == secondData, "Objects are not the same"); - QVERIFY2(false == (firstData != secondData), "Objects are not the same"); + QVERIFY2(!(firstData != secondData), "Objects are not the same"); secondData.addRow(firstRow); - QVERIFY2(false == (firstData == secondData), "Objects are the same"); + QVERIFY2(!(firstData == secondData), "Objects are the same"); QVERIFY2(firstData != secondData, "Objects are the same"); } -void TestVariantData::testCopyConstruction() -{ +void TestVariantData::testCopyConstruction() { QStringList firstRow, secondRow; firstRow << "one" << "two" << "three"; secondRow << "four" << "five"; @@ -245,8 +228,7 @@ void TestVariantData::testCopyConstruction() QVERIFY2(secondRow == firstData.rowValues(1), "Wrong data for second row"); } -void TestVariantData::testCopyAssignment() -{ +void TestVariantData::testCopyAssignment() { QStringList firstRow, secondRow; firstRow << "one" << "two" << "three"; secondRow << "four" << "five"; @@ -272,8 +254,7 @@ void TestVariantData::testCopyAssignment() QVERIFY2(secondRow == firstData.rowValues(1), "Wrong data for second row"); } -void TestVariantData::testOperatorInput() -{ +void TestVariantData::testOperatorInput() { QtCSV::VariantData data; data << QString("1") << QVariant(double(3.14)); @@ -294,13 +275,12 @@ void TestVariantData::testOperatorInput() QVERIFY2(thirdRow == data.rowValues(2), "Wrong data for third row"); } -void TestVariantData::testRemoveRow() -{ +void TestVariantData::testRemoveRow() { QtCSV::VariantData data; data.removeRow(0); data.removeRow(563); - QVERIFY2(true == data.isEmpty(), "Container is not empty"); + QVERIFY2(data.isEmpty(), "Container is not empty"); QStringList valuesFirst, valuesSecond; valuesFirst << "one" << "two" << "three"; @@ -319,8 +299,7 @@ void TestVariantData::testRemoveRow() "Wrong data for third row"); } -void TestVariantData::testReplaceRow() -{ +void TestVariantData::testReplaceRow() { QStringList valuesFirst, valuesSecond; valuesFirst << "one" << "two" << "three"; valuesSecond << "asgreg" << "ertetw" << ""; diff --git a/tests/testvariantdata.h b/tests/testvariantdata.h index 44f4b8e..e72a61c 100644 --- a/tests/testvariantdata.h +++ b/tests/testvariantdata.h @@ -4,12 +4,11 @@ #include #include -class TestVariantData : public QObject -{ +class TestVariantData : public QObject { Q_OBJECT public: - TestVariantData(); + TestVariantData() = default; private Q_SLOTS: void testCreation(); diff --git a/tests/testwriter.cpp b/tests/testwriter.cpp index 3d9347e..947a11c 100644 --- a/tests/testwriter.cpp +++ b/tests/testwriter.cpp @@ -1,98 +1,85 @@ #include "testwriter.h" -#include "qtcsv/writer.h" #include "qtcsv/reader.h" #include "qtcsv/variantdata.h" +#include "qtcsv/writer.h" +#include #include -#include #include -#include +#include #include -TestWriter::TestWriter() {} - -void TestWriter::cleanup() -{ - if (QFile::exists(getFilePath()) && - false == QFile::remove(getFilePath())) - { +void TestWriter::cleanup() { + if (QFile::exists(getFilePath()) && !QFile::remove(getFilePath())) { qDebug() << "Can't remove file:" << getFilePath(); } - if (QFile::exists(getFilePathXLS()) && - false == QFile::remove(getFilePathXLS())) - { + if (QFile::exists(getFilePathXLS()) && !QFile::remove(getFilePathXLS())) { qDebug() << "Can't remove file:" << getFilePathXLS(); } if (QFile::exists(getFilePathWithDotsInName()) && - false == QFile::remove(getFilePathWithDotsInName())) + !QFile::remove(getFilePathWithDotsInName())) { qDebug() << "Can't remove file:" << getFilePathWithDotsInName(); } } -QString TestWriter::getFilePath() const -{ +QString TestWriter::getFilePath() const { return QDir::currentPath() + "/test-file.csv"; } -QString TestWriter::getFilePathXLS() const -{ +QString TestWriter::getFilePathXLS() const { return QDir::currentPath() + "/test-file.xls"; } -QString TestWriter::getFilePathWithDotsInName() const -{ +QString TestWriter::getFilePathWithDotsInName() const { return QDir::currentPath() + "/test.file.dots.csv"; } -void TestWriter::testWriteInvalidArgs() -{ - QVERIFY2(false == QtCSV::Writer::write(QString(), QtCSV::StringData()), +void TestWriter::testWriteInvalidArgs() { + QVERIFY2(!QtCSV::Writer::write(QString(), QtCSV::StringData()), "Invalid arguments was accepted"); - QVERIFY2(false == QtCSV::Writer::write(getFilePath(), QtCSV::StringData()), + QVERIFY2(!QtCSV::Writer::write(getFilePath(), QtCSV::StringData()), "Empty data was accepted"); QtCSV::StringData strData; strData << "one" << "two" << "three"; - QVERIFY2(false == QtCSV::Writer::write(QString(), strData), + QVERIFY2(!QtCSV::Writer::write(QString(), strData), "Empty path was accepted"); - QVERIFY2(false == QtCSV::Writer::write("./some/path.csv", strData), + QVERIFY2(!QtCSV::Writer::write("./some/path.csv", strData), "Relative path to csv-file was accepted"); QVERIFY2(QtCSV::Writer::write(getFilePathXLS(), strData), "Absolute path to xls-file was not accepted"); } -void TestWriter::testWriteFromStringData() -{ - QStringList strList; +void TestWriter::testWriteFromStringData() { + QList strList; strList << "one" << "two" << "three"; QtCSV::StringData strData; strData.addRow(strList); - bool writeResult = QtCSV::Writer::write(getFilePath(), strData); - QVERIFY2(true == writeResult, "Failed to write to file"); + const auto writeResult = QtCSV::Writer::write(getFilePath(), strData); + QVERIFY2(writeResult, "Failed to write to file"); - QList data = QtCSV::Reader::readToList(getFilePath()); - QVERIFY2(false == data.isEmpty(), "Failed to read file content"); + const auto data = QtCSV::Reader::readToList(getFilePath()); + QVERIFY2(!data.isEmpty(), "Failed to read file content"); QVERIFY2(1 == data.size(), "Wrong number of rows"); QVERIFY2(strList == data.at(0), "Wrong data"); } -void TestWriter::testWriteFromVariantData() -{ - double expectedValue = 42.12309; +void TestWriter::testWriteFromVariantData() { + const auto expectedValue = 42.12309; QVariant firstRow(expectedValue); QList secondRow; secondRow << QVariant("kkoo") << QVariant(771) << QVariant(3.14); - QStringList thirdRow; + QList thirdRow; thirdRow << "one" << "two" << "three"; QtCSV::VariantData varData; @@ -100,182 +87,157 @@ void TestWriter::testWriteFromVariantData() varData.addRow(secondRow); varData.addRow(thirdRow); - bool writeResult = QtCSV::Writer::write(getFilePath(), varData); - QVERIFY2(true == writeResult, "Failed to write to file"); + const auto writeResult = QtCSV::Writer::write(getFilePath(), varData); + QVERIFY2(writeResult, "Failed to write to file"); - QList data = QtCSV::Reader::readToList(getFilePath()); - QVERIFY2(false == data.isEmpty(), "Failed to read file content"); + const auto data = QtCSV::Reader::readToList(getFilePath()); + QVERIFY2(!data.isEmpty(), "Failed to read file content"); QVERIFY2(3 == data.size(), "Wrong number of rows"); - QVERIFY2(varData.rowValues(0) == data.at(0), - "Wrong values in first row"); - - QVERIFY2(varData.rowValues(1) == data.at(1), - "Wrong values in second row"); - - QVERIFY2(varData.rowValues(2) == data.at(2), - "Wrong values in third row"); + QVERIFY2(varData.rowValues(0) == data.at(0), "Wrong values in first row"); + QVERIFY2(varData.rowValues(1) == data.at(1), "Wrong values in second row"); + QVERIFY2(varData.rowValues(2) == data.at(2), "Wrong values in third row"); } -void TestWriter::testWriteToFileWithDotsInName() -{ - QStringList strList; +void TestWriter::testWriteToFileWithDotsInName() { + QList strList; strList << "one" << "two" << "three"; QtCSV::StringData strData; strData.addRow(strList); - bool writeResult = - QtCSV::Writer::write(getFilePathWithDotsInName(), strData); - QVERIFY2(true == writeResult, "Failed to write to file"); + const auto writeResult = + QtCSV::Writer::write(getFilePathWithDotsInName(), strData); + QVERIFY2(writeResult, "Failed to write to file"); - QList data = - QtCSV::Reader::readToList(getFilePathWithDotsInName()); - QVERIFY2(false == data.isEmpty(), "Failed to read file content"); + const auto data = + QtCSV::Reader::readToList(getFilePathWithDotsInName()); + QVERIFY2(!data.isEmpty(), "Failed to read file content"); QVERIFY2(1 == data.size(), "Wrong number of rows"); QVERIFY2(strList == data.at(0), "Wrong data"); } -void TestWriter::testWriteAppendMode() -{ - QStringList strFirstList; +void TestWriter::testWriteAppendMode() { + QList strFirstList; strFirstList << "one" << "two" << "three"; QtCSV::StringData strData; strData.addRow(strFirstList); - bool writeResult = QtCSV::Writer::write(getFilePath(), strData); - QVERIFY2(true == writeResult, "Failed to write to file"); + const auto writeResult = QtCSV::Writer::write(getFilePath(), strData); + QVERIFY2(writeResult, "Failed to write to file"); - QStringList strSecondList; + QList strSecondList; strSecondList << "3" << "2" << "1.1"; QtCSV::StringData newStrData; newStrData.addRow(strSecondList); - bool newWriteResult = QtCSV::Writer::write(getFilePath(), - newStrData, - ",", - QString(), - QtCSV::Writer::APPEND); + const auto newWriteResult = QtCSV::Writer::write( + getFilePath(), newStrData, ",", {}, QtCSV::Writer::WriteMode::APPEND); - QVERIFY2(true == newWriteResult, "Failed to write to file"); + QVERIFY2(newWriteResult, "Failed to write to file"); - QList data = QtCSV::Reader::readToList(getFilePath()); - QVERIFY2(false == data.isEmpty(), "Failed to read file content"); + const auto data = QtCSV::Reader::readToList(getFilePath()); + QVERIFY2(!data.isEmpty(), "Failed to read file content"); QVERIFY2(2 == data.size(), "Wrong number of rows"); QVERIFY2(strFirstList == data.at(0), "Wrong first row data"); QVERIFY2(strSecondList == data.at(1), "Wrong second row data"); } -void TestWriter::testWriteWithNotDefaultSeparator() -{ - QStringList strList; +void TestWriter::testWriteWithNotDefaultSeparator() { + QList strList; strList << "one" << "two" << "three"; QtCSV::StringData strData; strData.addRow(strList); const QString separator("++"); - bool writeResult = QtCSV::Writer::write(getFilePath(), strData, separator); - QVERIFY2(true == writeResult, "Failed to write to file"); + const auto writeResult = + QtCSV::Writer::write(getFilePath(), strData, separator); + QVERIFY2(writeResult, "Failed to write to file"); - QList data = - QtCSV::Reader::readToList(getFilePath(), separator); - QVERIFY2(false == data.isEmpty(), "Failed to read file content"); + const auto data = + QtCSV::Reader::readToList(getFilePath(), separator); + QVERIFY2(!data.isEmpty(), "Failed to read file content"); QVERIFY2(1 == data.size(), "Wrong number of rows"); QVERIFY2(strList == data.at(0), "Wrong data"); } -void TestWriter::testWriteWithHeader() -{ - QStringList header; +void TestWriter::testWriteWithHeader() { + QList header; header << "1" << "2"; - QStringList strList; + QList strList; strList << "one" << "two" << "three"; QtCSV::StringData strData; strData.addRow(strList); - bool writeResult = QtCSV::Writer::write(getFilePath(), - strData, - ",", - QString(), - QtCSV::Writer::REWRITE, - header); + const auto writeResult = QtCSV::Writer::write( + getFilePath(), strData, ",", {}, QtCSV::Writer::WriteMode::REWRITE, + header); - QVERIFY2(true == writeResult, "Failed to write to file"); + QVERIFY2(writeResult, "Failed to write to file"); - QList data = QtCSV::Reader::readToList(getFilePath()); - QVERIFY2(false == data.isEmpty(), "Failed to read file content"); + const auto data = QtCSV::Reader::readToList(getFilePath()); + QVERIFY2(!data.isEmpty(), "Failed to read file content"); QVERIFY2(2 == data.size(), "Wrong number of rows"); QVERIFY2(header == data.at(0), "Wrong header"); QVERIFY2(strList == data.at(1), "Wrong data"); } -void TestWriter::testWriteWithFooter() -{ - QStringList footer; +void TestWriter::testWriteWithFooter() { + QList footer; footer << "Here is a footer"; - QStringList strList; + QList strList; strList << "one" << "two" << "three"; QtCSV::StringData strData; strData.addRow(strList); - bool writeResult = QtCSV::Writer::write(getFilePath(), - strData, - ",", - QString(), - QtCSV::Writer::REWRITE, - QStringList(), - footer); + const auto writeResult = QtCSV::Writer::write( + getFilePath(), strData, ",", {}, QtCSV::Writer::WriteMode::REWRITE, + {}, footer); - QVERIFY2(true == writeResult, "Failed to write to file"); + QVERIFY2(writeResult, "Failed to write to file"); - QList data = QtCSV::Reader::readToList(getFilePath()); - QVERIFY2(false == data.isEmpty(), "Failed to read file content"); + const auto data = QtCSV::Reader::readToList(getFilePath()); + QVERIFY2(!data.isEmpty(), "Failed to read file content"); QVERIFY2(2 == data.size(), "Wrong number of rows"); QVERIFY2(strList == data.at(0), "Wrong data"); QVERIFY2(footer == data.at(1), "Wrong footer"); } -void TestWriter::testWriteWithHeaderAndFooter() -{ - QStringList header; +void TestWriter::testWriteWithHeaderAndFooter() { + QList header; header << "1" << "2"; - QStringList footer; + QList footer; footer << "Here is a footer"; - QStringList strList; + QList strList; strList << "one" << "two" << "three"; QtCSV::StringData strData; strData.addRow(strList); - bool writeResult = QtCSV::Writer::write(getFilePath(), - strData, - ",", - QString(), - QtCSV::Writer::REWRITE, - header, - footer); + const auto writeResult = QtCSV::Writer::write( + getFilePath(), strData, ",", {}, QtCSV::Writer::WriteMode::REWRITE, + header, footer); - QVERIFY2(true == writeResult, "Failed to write to file"); + QVERIFY2(writeResult, "Failed to write to file"); - QList data = QtCSV::Reader::readToList(getFilePath()); - QVERIFY2(false == data.isEmpty(), "Failed to read file content"); + const auto data = QtCSV::Reader::readToList(getFilePath()); + QVERIFY2(!data.isEmpty(), "Failed to read file content"); QVERIFY2(3 == data.size(), "Wrong number of rows"); QVERIFY2(header == data.at(0), "Wrong header"); QVERIFY2(strList == data.at(1), "Wrong data"); QVERIFY2(footer == data.at(2), "Wrong footer"); } -void TestWriter::testWriterDataContainSeparators() -{ - QStringList strList; +void TestWriter::testWriterDataContainSeparators() { + QList strList; strList << "one" << "two" << "three, four"; QString strLine("this, is, one, element"); @@ -284,78 +246,62 @@ void TestWriter::testWriterDataContainSeparators() strData.addRow(strList); strData.addRow(strLine); - bool writeResult = QtCSV::Writer::write(getFilePath(), - strData, - ",", - "\""); - QVERIFY2(true == writeResult, "Failed to write to file"); + const auto writeResult = + QtCSV::Writer::write(getFilePath(), strData, ",", "\""); + QVERIFY2(writeResult, "Failed to write to file"); - QList data = QtCSV::Reader::readToList(getFilePath(), - ",", - "\""); + const auto data = + QtCSV::Reader::readToList(getFilePath(), ",", "\""); - QVERIFY2(false == data.isEmpty(), "Failed to read file content"); + QVERIFY2(!data.isEmpty(), "Failed to read file content"); QVERIFY2(2 == data.size(), "Wrong number of rows"); QVERIFY2(strList == data.at(0), "Wrong data at first row"); - QVERIFY2((QStringList() << strLine) == data.at(1), + QVERIFY2((QList() << strLine) == data.at(1), "Wrong data at second row"); } -void TestWriter::testWriteDifferentDataAmount() -{ - int rowsNumber = 10; - int rowsMultiplier = 2; - int rowCycles = 2; +void TestWriter::testWriteDifferentDataAmount() { + auto rowsNumber = 10; + auto rowsMultiplier = 2; + auto rowCycles = 2; QElapsedTimer time; - for (int rc = 0; rc < rowCycles; ++rc) - { - int symbolsNumber = 10; - int symbolsMultiplier = 5; - int symbolCycles = 4; - for (int sc = 0; sc < symbolCycles; ++sc) - { + for (auto rc = 0; rc < rowCycles; ++rc) { + auto symbolsNumber = 10; + auto symbolsMultiplier = 5; + auto symbolCycles = 4; + for (auto sc = 0; sc < symbolCycles; ++sc) { QtCSV::StringData data; - try - { + try { data = getTestStringData(symbolsNumber, rowsNumber); } - catch (std::exception &e) - { - Q_UNUSED(e); + catch (std::exception& /*e*/) { QFAIL("No enough memory to create data object"); } - QVERIFY2(false == data.isEmpty(), "Failed to create content"); + QVERIFY2(!data.isEmpty(), "Failed to create content"); - bool writeResult = false; + auto writeResult = false; time.restart(); - try - { - writeResult = QtCSV::Writer::write( - getFilePath(), data, ",", QString()); + try { + writeResult = QtCSV::Writer::write(getFilePath(), data, ",", {}); } - catch (std::exception &e) - { - Q_UNUSED(e); + catch (std::exception& /*e*/) { QFAIL("No enough memory to write data to the file"); } - qDebug() << "symbols:" << symbolsNumber << - ", rows:" << rowsNumber << - ", time:" << time.elapsed() << "ms"; + qDebug() << "symbols:" << symbolsNumber << ", rows:" << rowsNumber + << ", time:" << time.elapsed() << "ms"; - QVERIFY2(true == writeResult, "Failed to write to file"); + QVERIFY2(writeResult, "Failed to write to file"); QFile csvFile(getFilePath()); - if (false == csvFile.open(QIODevice::ReadOnly | QIODevice::Text)) - { + if (!csvFile.open(QIODevice::ReadOnly | QIODevice::Text)) { QFAIL("Failed to open created csv-file"); } QTextStream stream(&csvFile); - for (int line = 0; line < data.rowCount(); ++line) - { - QStringList lineElements = stream.readLine().split(","); + for (auto line = 0; line < data.rowCount(); ++line) { + QList lineElements = stream.readLine().split(","); QVERIFY2(data.rowValues(line) == lineElements, "Original and result data are not the same"); } @@ -370,33 +316,34 @@ void TestWriter::testWriteDifferentDataAmount() } QtCSV::StringData TestWriter::getTestStringData( - const int &symbolsInRow, const int &rowsNumber) -{ - if (symbolsInRow <= 0 || rowsNumber <= 0) - { + qsizetype symbolsInRow, qsizetype rowsNumber) { + if (symbolsInRow <= 0 || rowsNumber <= 0) { qDebug() << __FUNCTION__ << "Invalid argumnets"; - return QtCSV::StringData(); + return {}; } - QStringList elements; - elements << "1234567890" << "3.14159265359" << "abcdefgh" << - "ijklmnopqrs" << "tuvwxyz" << "ABCDEFGH" << "IJKLMNOPQRS" << - "TUVWXYZ" << "some_STRANGE-string=" << - "?!\\|/*+.<>@#$%^&(){}[]'`~"; - - QStringList rowElements; - int rowLength = 0; - int elementIndex = 0; - while (rowLength < symbolsInRow) - { - if (elements.size() <= elementIndex) - { + QList elements; + elements << "1234567890" + << "3.14159265359" + << "abcdefgh" + << "ijklmnopqrs" + << "tuvwxyz" + << "ABCDEFGH" + << "IJKLMNOPQRS" + << "TUVWXYZ" + << "some_STRANGE-string=" + << "?!\\|/*+.<>@#$%^&(){}[]'`~"; + + QList rowElements; + auto rowLength = 0; + auto elementIndex = 0; + while (rowLength < symbolsInRow) { + if (elements.size() <= elementIndex) { elementIndex = 0; } QString nextElement = elements.at(elementIndex); - if (symbolsInRow < rowLength + nextElement.size()) - { + if (symbolsInRow < rowLength + nextElement.size()) { nextElement.resize(symbolsInRow - rowLength); } @@ -406,37 +353,32 @@ QtCSV::StringData TestWriter::getTestStringData( } QtCSV::StringData data; - for (int i = 0; i < rowsNumber; ++i) - { + for (auto i = 0; i < rowsNumber; ++i) { data.addRow(rowElements); } return data; } -void TestWriter::testWriteDataContainCRLF() -{ - QStringList firstLine = QStringList() << "one" << "two" << - "three\nfour,five"; +void TestWriter::testWriteDataContainCRLF() { + QList firstLine = QList() << + "one" << "two" << "three\nfour,five"; - QStringList secondLine = QStringList() << "six" << "seven,eight" << - "nine,\rten"; + QList secondLine = QList() << + "six" << "seven,eight" << "nine,\rten"; QtCSV::StringData strData; strData.addRow(firstLine); strData.addRow(secondLine); - bool writeResult = QtCSV::Writer::write(getFilePath(), - strData, - ",", - QString()); - QVERIFY2(true == writeResult, "Failed to write to file"); + const auto writeResult = + QtCSV::Writer::write(getFilePath(), strData, ",", QString()); + QVERIFY2(writeResult, "Failed to write to file"); - QList data = QtCSV::Reader::readToList(getFilePath(), - ",", - "\""); + const auto data = + QtCSV::Reader::readToList(getFilePath(), ",", "\""); - QVERIFY2(false == data.isEmpty(), "Failed to read file content"); + QVERIFY2(!data.isEmpty(), "Failed to read file content"); QVERIFY2(2 == data.size(), "Wrong number of rows"); QVERIFY2(firstLine == data.at(0), "Wrong data at first row"); QVERIFY2(secondLine == data.at(1), "Wrong data at second row"); diff --git a/tests/testwriter.h b/tests/testwriter.h index 11ccab4..62280d7 100644 --- a/tests/testwriter.h +++ b/tests/testwriter.h @@ -6,12 +6,11 @@ #include "qtcsv/stringdata.h" -class TestWriter : public QObject -{ +class TestWriter : public QObject { Q_OBJECT public: - TestWriter(); + TestWriter() = default; private Q_SLOTS: void cleanup(); @@ -33,7 +32,7 @@ private Q_SLOTS: QString getFilePathXLS() const; QString getFilePathWithDotsInName() const; QtCSV::StringData getTestStringData( - const int &symbolsInRow, const int &rowsNumber); + qsizetype symbolsInRow, qsizetype rowsNumber); }; #endif // TESTWRITER_H diff --git a/tests/tst_testmain.cpp b/tests/tst_testmain.cpp index aae4002..99ae533 100644 --- a/tests/tst_testmain.cpp +++ b/tests/tst_testmain.cpp @@ -1,21 +1,19 @@ #include +#include "testreader.h" #include "teststringdata.h" #include "testvariantdata.h" -#include "testreader.h" #include "testwriter.h" -int AssertTest(QObject* obj) -{ +int AssertTest(QObject* obj) { int status = QTest::qExec(obj); delete obj; return status; } -int main() -{ - int status = 0; +int main() { + auto status = 0; status |= AssertTest(new TestStringData()); status |= AssertTest(new TestVariantData()); status |= AssertTest(new TestReader());