From 64a6137ab3a21af0625b15179df932070ae3b85f 2017-11-17 08:18:13 From: Alexandre Leroux Date: 2017-11-17 08:18:13 Subject: [PATCH] Parser refactoring (5) Replaces the basic parser to use the helpers created --- diff --git a/plugins/amda/include/AmdaResultParserDefs.h b/plugins/amda/include/AmdaResultParserDefs.h index b1b4136..287f407 100644 --- a/plugins/amda/include/AmdaResultParserDefs.h +++ b/plugins/amda/include/AmdaResultParserDefs.h @@ -19,6 +19,11 @@ extern const QString X_AXIS_UNIT_PROPERTY; // /////////////////// // // AMDA V2 +// /// Regex to find the header of the data in the file. This header indicates the end of comments +// in the file +// const auto DATA_HEADER_REGEX = QRegularExpression{QStringLiteral("#\\s*DATA\\s*:")}; + +// AMDA V2 // /// ... PARAMETER_UNITS : nT ... // /// ... PARAMETER_UNITS:nT ... // /// ... PARAMETER_UNITS: m² ... diff --git a/plugins/amda/src/AmdaResultParser.cpp b/plugins/amda/src/AmdaResultParser.cpp index 73fe699..fce4151 100644 --- a/plugins/amda/src/AmdaResultParser.cpp +++ b/plugins/amda/src/AmdaResultParser.cpp @@ -1,12 +1,8 @@ #include "AmdaResultParser.h" -#include -#include -#include +#include "AmdaResultParserHelper.h" -#include #include -#include #include @@ -17,66 +13,24 @@ namespace { /// Message in result file when the file was not found on server const auto FILE_NOT_FOUND_MESSAGE = QStringLiteral("Not Found"); -/// Separator between values in a result line -const auto RESULT_LINE_SEPARATOR = QRegularExpression{QStringLiteral("\\s+")}; - -// AMDA V2 -// /// Regex to find the header of the data in the file. This header indicates the end of comments -// in -// /// the file -// const auto DATA_HEADER_REGEX = QRegularExpression{QStringLiteral("#\\s*DATA\\s*:")}; - -/// Format for dates in result files -const auto DATE_FORMAT = QStringLiteral("yyyy-MM-ddThh:mm:ss.zzz"); - -// AMDA V2 -// /// Regex to find unit in a line. Examples of valid lines: -// /// ... PARAMETER_UNITS : nT ... -// /// ... PARAMETER_UNITS:nT ... -// /// ... PARAMETER_UNITS: m² ... -// /// ... PARAMETER_UNITS : m/s ... -// const auto UNIT_REGEX = QRegularExpression{QStringLiteral("\\s*PARAMETER_UNITS\\s*:\\s*(.+)")}; - -/// ... - Units : nT - ... -/// ... -Units:nT- ... -/// ... -Units: m²- ... -/// ... - Units : m/s - ... -const auto UNIT_REGEX = QRegularExpression{QStringLiteral("-\\s*Units\\s*:\\s*(.+?)\\s*-")}; - -QDateTime dateTimeFromString(const QString &stringDate) noexcept -{ -#if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0) - return QDateTime::fromString(stringDate, Qt::ISODateWithMs); -#else - return QDateTime::fromString(stringDate, DATE_FORMAT); -#endif -} - -/// Converts a string date to a double date -/// @return a double that represents the date in seconds, NaN if the string date can't be converted -double doubleDate(const QString &stringDate) noexcept -{ - // Format: yyyy-MM-ddThh:mm:ss.zzz - auto dateTime = dateTimeFromString(stringDate); - dateTime.setTimeSpec(Qt::UTC); - return dateTime.isValid() ? DateUtils::secondsSinceEpoch(dateTime) - : std::numeric_limits::quiet_NaN(); -} - /// Checks if a line is a comment line bool isCommentLine(const QString &line) { return line.startsWith("#"); } -/// @return the number of lines to be read depending on the type of value passed in parameter -int nbValues(AmdaResultParser::ValueType valueType) noexcept +/** + * Creates helper that will be used to read AMDA file, according to the type passed as parameter + * @param valueType the type of values expected in the AMDA file (scalars, vectors, spectrograms...) + * @return the helper created + */ +std::unique_ptr createHelper(AmdaResultParser::ValueType valueType) { switch (valueType) { case AmdaResultParser::ValueType::SCALAR: - return 1; + return std::make_unique(); case AmdaResultParser::ValueType::VECTOR: - return 3; + return std::make_unique(); case AmdaResultParser::ValueType::UNKNOWN: // Invalid case break; @@ -84,48 +38,32 @@ int nbValues(AmdaResultParser::ValueType valueType) noexcept // Invalid cases qCCritical(LOG_AmdaResultParser()) - << QObject::tr("Can't get the number of values to read: unsupported type"); - return 0; + << QObject::tr("Can't create helper to read result file: unsupported type"); + return nullptr; } /** - * Reads stream to retrieve x-axis unit + * Reads properties of the stream passed as parameter + * @param helper the helper used to read properties line by line * @param stream the stream to read - * @return the unit that has been read in the stream, a default unit (time unit with no label) if an - * error occured during reading */ -Unit readXAxisUnit(QTextStream &stream) +void readProperties(IAmdaResultParserHelper &helper, QTextStream &stream) { - QString line{}; - - // Searches unit in the comment lines (as long as the reading has not reached the data header) + // Searches properties in the comment lines (as long as the reading has not reached the data) // AMDA V2: while (stream.readLineInto(&line) && !line.contains(DATA_HEADER_REGEX)) { + QString line{}; while (stream.readLineInto(&line) && isCommentLine(line)) { - auto match = UNIT_REGEX.match(line); - if (match.hasMatch()) { - return Unit{match.captured(1), true}; - } + helper.readPropertyLine(line); } - - qCWarning(LOG_AmdaResultParser()) << QObject::tr("The unit could not be found in the file"); - - // Error cases - return Unit{{}, true}; } /** - * Reads stream to retrieve results + * Reads results of the stream passed as parameter + * @param helper the helper used to read results line by line * @param stream the stream to read - * @return the pair of vectors x-axis data/values data that has been read in the stream */ -std::pair, std::vector > -readResults(QTextStream &stream, AmdaResultParser::ValueType valueType) +void readResults(IAmdaResultParserHelper &helper, QTextStream &stream) { - auto expectedNbValues = nbValues(valueType) + 1; - - auto xData = std::vector{}; - auto valuesData = std::vector{}; - QString line{}; // Skip comment lines @@ -134,47 +72,9 @@ readResults(QTextStream &stream, AmdaResultParser::ValueType valueType) if (!stream.atEnd()) { do { - auto lineData = line.split(RESULT_LINE_SEPARATOR, QString::SkipEmptyParts); - if (lineData.size() == expectedNbValues) { - // X : the data is converted from date to double (in secs) - auto x = doubleDate(lineData.at(0)); - - // Adds result only if x is valid. Then, if value is invalid, it is set to NaN - if (!std::isnan(x)) { - xData.push_back(x); - - // Values - for (auto valueIndex = 1; valueIndex < expectedNbValues; ++valueIndex) { - auto column = valueIndex; - - bool valueOk; - auto value = lineData.at(column).toDouble(&valueOk); - - if (!valueOk) { - qCWarning(LOG_AmdaResultParser()) - << QObject::tr( - "Value from (line %1, column %2) is invalid and will be " - "converted to NaN") - .arg(line, column); - value = std::numeric_limits::quiet_NaN(); - } - valuesData.push_back(value); - } - } - else { - qCWarning(LOG_AmdaResultParser()) - << QObject::tr("Can't retrieve results from line %1: x is invalid") - .arg(line); - } - } - else { - qCWarning(LOG_AmdaResultParser()) - << QObject::tr("Can't retrieve results from line %1: invalid line").arg(line); - } + helper.readResultLine(line); } while (stream.readLineInto(&line)); } - - return std::make_pair(std::move(xData), std::move(valuesData)); } } // namespace @@ -208,33 +108,24 @@ std::shared_ptr AmdaResultParser::readTxt(const QString &filePath, return nullptr; } - // Reads x-axis unit - stream.seek(0); // returns to the beginning of the file - auto xAxisUnit = readXAxisUnit(stream); - if (xAxisUnit.m_Name.isEmpty()) { - return nullptr; - } + auto helper = createHelper(valueType); + Q_ASSERT(helper != nullptr); - // Reads results - // AMDA V2: remove line + // Reads header file to retrieve properties stream.seek(0); // returns to the beginning of the file - auto results = readResults(stream, valueType); + readProperties(*helper, stream); - // Creates data series - switch (valueType) { - case ValueType::SCALAR: - return std::make_shared(std::move(results.first), - std::move(results.second), xAxisUnit, Unit{}); - case ValueType::VECTOR: - return std::make_shared(std::move(results.first), - std::move(results.second), xAxisUnit, Unit{}); - case ValueType::UNKNOWN: - // Invalid case - break; - } + // Checks properties + if (helper->checkProperties()) { + // Reads results + // AMDA V2: remove line + stream.seek(0); // returns to the beginning of the file + readResults(*helper, stream); - // Invalid cases - qCCritical(LOG_AmdaResultParser()) - << QObject::tr("Can't create data series: unsupported value type"); - return nullptr; + // Creates data series + return helper->createSeries(); + } + else { + return nullptr; + } }