diff --git a/core/include/Data/ArrayData.h b/core/include/Data/ArrayData.h index ccca546..9f5a240 100644 --- a/core/include/Data/ArrayData.h +++ b/core/include/Data/ArrayData.h @@ -58,6 +58,67 @@ struct Sort<1> { template class ArrayData { public: + class IteratorValue { + public: + explicit IteratorValue(const DataContainer &container, bool begin) : m_Its{} + { + for (auto i = 0; i < container.size(); ++i) { + m_Its.push_back(begin ? container.at(i).cbegin() : container.at(i).cend()); + } + } + + double at(int index) const { return *m_Its.at(index); } + double first() const { return *m_Its.front(); } + + void next() + { + for (auto &it : m_Its) { + ++it; + } + } + + bool operator==(const IteratorValue &other) const { return m_Its == other.m_Its; } + + private: + std::vector m_Its; + }; + + class Iterator { + public: + using iterator_category = std::forward_iterator_tag; + using value_type = const IteratorValue; + using difference_type = std::ptrdiff_t; + using pointer = value_type *; + using reference = value_type &; + + Iterator(const DataContainer &container, bool begin) : m_CurrentValue{container, begin} {} + + virtual ~Iterator() noexcept = default; + Iterator(const Iterator &) = default; + Iterator(Iterator &&) = default; + Iterator &operator=(const Iterator &) = default; + Iterator &operator=(Iterator &&) = default; + + Iterator &operator++() + { + m_CurrentValue.next(); + return *this; + } + + pointer operator->() const { return &m_CurrentValue; } + reference operator*() const { return m_CurrentValue; } + + bool operator==(const Iterator &other) const + { + return m_CurrentValue == other.m_CurrentValue; + } + + bool operator!=(const Iterator &other) const { return !(*this == other); } + + private: + IteratorValue m_CurrentValue; + }; + // ///// // // Ctors // // ///// // @@ -184,6 +245,13 @@ public: return arraydata_detail::Sort::sort(m_Data, sortPermutation); } + // ///////// // + // Iterators // + // ///////// // + + Iterator cbegin() const { return Iterator{m_Data, true}; } + Iterator cend() const { return Iterator{m_Data, false}; } + // ///////////// // // 1-dim methods // // ///////////// // diff --git a/core/include/Data/DataSeries.h b/core/include/Data/DataSeries.h index 3b95662..8637c28 100644 --- a/core/include/Data/DataSeries.h +++ b/core/include/Data/DataSeries.h @@ -29,6 +29,71 @@ Q_LOGGING_CATEGORY(LOG_DataSeries, "DataSeries") template class DataSeries : public IDataSeries { public: + class IteratorValue { + public: + explicit IteratorValue(const DataSeries &dataSeries, bool begin) + : m_XIt(begin ? dataSeries.xAxisData()->cbegin() : dataSeries.xAxisData()->cend()), + m_ValuesIt(begin ? dataSeries.valuesData()->cbegin() + : dataSeries.valuesData()->cend()) + { + } + + double x() const { return m_XIt->at(0); } + double value() const { return m_ValuesIt->at(0); } + double value(int componentIndex) const { return m_ValuesIt->at(componentIndex); } + + void next() + { + ++m_XIt; + ++m_ValuesIt; + } + + bool operator==(const IteratorValue &other) const + { + return std::tie(m_XIt, m_ValuesIt) == std::tie(other.m_XIt, other.m_ValuesIt); + } + + private: + ArrayData<1>::Iterator m_XIt; + typename ArrayData::Iterator m_ValuesIt; + }; + + class Iterator { + public: + using iterator_category = std::forward_iterator_tag; + using value_type = const IteratorValue; + using difference_type = std::ptrdiff_t; + using pointer = value_type *; + using reference = value_type &; + + Iterator(const DataSeries &dataSeries, bool begin) : m_CurrentValue{dataSeries, begin} {} + virtual ~Iterator() noexcept = default; + Iterator(const Iterator &) = default; + Iterator(Iterator &&) = default; + Iterator &operator=(const Iterator &) = default; + Iterator &operator=(Iterator &&) = default; + + Iterator &operator++() + { + m_CurrentValue.next(); + return *this; + } + + pointer operator->() const { return &m_CurrentValue; } + + reference operator*() const { return m_CurrentValue; } + + bool operator==(const Iterator &other) const + { + return m_CurrentValue == other.m_CurrentValue; + } + + bool operator!=(const Iterator &other) const { return !(*this == other); } + + private: + IteratorValue m_CurrentValue; + }; + /// @sa IDataSeries::xAxisData() std::shared_ptr > xAxisData() override { return m_XAxisData; } const std::shared_ptr > xAxisData() const { return m_XAxisData; } @@ -119,6 +184,39 @@ public: dataSeries->unlock(); } + // ///////// // + // Iterators // + // ///////// // + + Iterator cbegin() const { return Iterator{*this, true}; } + + Iterator cend() const { return Iterator{*this, false}; } + + std::pair subData(double min, double max) const + { + if (min > max) { + std::swap(min, max); + } + + auto begin = cbegin(); + auto end = cend(); + + auto lowerIt + = std::lower_bound(begin, end, min, [](const auto &itValue, const auto &value) { + return itValue.x() == value; + }); + auto upperIt + = std::upper_bound(begin, end, max, [](const auto &value, const auto &itValue) { + return itValue.x() == value; + }); + + return std::make_pair(lowerIt, upperIt); + } + + // /////// // + // Mutexes // + // /////// // + virtual void lockRead() { m_Lock.lockForRead(); } virtual void lockWrite() { m_Lock.lockForWrite(); } virtual void unlock() { m_Lock.unlock(); } diff --git a/core/include/Data/IDataSeries.h b/core/include/Data/IDataSeries.h index b66ae68..7435fa3 100644 --- a/core/include/Data/IDataSeries.h +++ b/core/include/Data/IDataSeries.h @@ -56,7 +56,8 @@ public: virtual Unit valuesUnit() const = 0; virtual void merge(IDataSeries *dataSeries) = 0; - virtual std::shared_ptr subData(const SqpRange &range) = 0; + /// @todo Review the name and signature of this method + virtual std::shared_ptr subDataSeries(const SqpRange &range) = 0; virtual std::unique_ptr clone() const = 0; virtual SqpRange range() const = 0; diff --git a/core/include/Data/ScalarSeries.h b/core/include/Data/ScalarSeries.h index 9183e3d..1a745e5 100644 --- a/core/include/Data/ScalarSeries.h +++ b/core/include/Data/ScalarSeries.h @@ -21,7 +21,7 @@ public: std::unique_ptr clone() const override; - std::shared_ptr subData(const SqpRange &range) override; + std::shared_ptr subDataSeries(const SqpRange &range) override; }; #endif // SCIQLOP_SCALARSERIES_H diff --git a/core/src/Data/ScalarSeries.cpp b/core/src/Data/ScalarSeries.cpp index 9732921..94387da 100644 --- a/core/src/Data/ScalarSeries.cpp +++ b/core/src/Data/ScalarSeries.cpp @@ -12,7 +12,7 @@ std::unique_ptr ScalarSeries::clone() const return std::make_unique(*this); } -std::shared_ptr ScalarSeries::subData(const SqpRange &range) +std::shared_ptr ScalarSeries::subDataSeries(const SqpRange &range) { auto subXAxisData = QVector(); auto subValuesData = QVector(); diff --git a/core/src/Variable/Variable.cpp b/core/src/Variable/Variable.cpp index 04fac1c..ace298f 100644 --- a/core/src/Variable/Variable.cpp +++ b/core/src/Variable/Variable.cpp @@ -107,7 +107,7 @@ void Variable::mergeDataSeries(std::shared_ptr dataSeries) noexcept impl->unlock(); // sub the data - auto subData = this->dataSeries()->subData(this->cacheRange()); + auto subData = this->dataSeries()->subDataSeries(this->cacheRange()); qCDebug(LOG_Variable()) << "TORM: Variable::mergeDataSeries sub" << subData->range(); this->setDataSeries(subData); qCDebug(LOG_Variable()) << "TORM: Variable::mergeDataSeries set" << this->dataSeries()->range(); diff --git a/core/src/Variable/VariableController.cpp b/core/src/Variable/VariableController.cpp index a7a67df..ad796fd 100644 --- a/core/src/Variable/VariableController.cpp +++ b/core/src/Variable/VariableController.cpp @@ -481,7 +481,7 @@ void VariableController::VariableControllerPrivate::processRequest(std::shared_p else { var->setRange(rangeRequested); var->setCacheRange(varRangesRequested.second); - var->setDataSeries(var->dataSeries()->subData(varRangesRequested.second)); + var->setDataSeries(var->dataSeries()->subDataSeries(varRangesRequested.second)); emit var->updated(); } } diff --git a/core/vera-exclusions/exclusions.txt b/core/vera-exclusions/exclusions.txt index a4b02d1..cbba6aa 100644 --- a/core/vera-exclusions/exclusions.txt +++ b/core/vera-exclusions/exclusions.txt @@ -11,6 +11,32 @@ ArrayData\.h:\d+:.*IPSIS_S06.*found: (D) ArrayData\.h:\d+:.*IPSIS_S06.*found: (Dim) DataSeries\.h:\d+:.*IPSIS_S04_VARIABLE.* +# Ignore false positive relative to iterators +ArrayData\.h:\d+:.*IPSIS_S04_VARIABLE.*found: (forward_iterator_tag) +ArrayData\.h:\d+:.*IPSIS_S04_VARIABLE.*found: (IteratorValue) +ArrayData\.h:\d+:.*IPSIS_S04_VARIABLE.*found: (ptrdiff_t) +ArrayData\.h:\d+:.*IPSIS_S04_VARIABLE.*found: (value_type) +ArrayData\.h:\d+:.*IPSIS_S05.* +ArrayData\.h:\d+:.*IPSIS_S06.*found: (iterator_category) +ArrayData\.h:\d+:.*IPSIS_S06.*found: (forward_iterator_tag) +ArrayData\.h:\d+:.*IPSIS_S06.*found: (value_type) +ArrayData\.h:\d+:.*IPSIS_S06.*found: (IteratorValue) +ArrayData\.h:\d+:.*IPSIS_S06.*found: (difference_type) +ArrayData\.h:\d+:.*IPSIS_S06.*found: (ptrdiff_t) +ArrayData\.h:\d+:.*IPSIS_S06.*found: (pointer) +ArrayData\.h:\d+:.*IPSIS_S06.*found: (reference) +ArrayData\.h:\d+:.*IPSIS_S06.*found: (value_type) +DataSeries\.h:\d+:.*IPSIS_S05.* +DataSeries\.h:\d+:.*IPSIS_S06.*found: (iterator_category) +DataSeries\.h:\d+:.*IPSIS_S06.*found: (forward_iterator_tag) +DataSeries\.h:\d+:.*IPSIS_S06.*found: (value_type) +DataSeries\.h:\d+:.*IPSIS_S06.*found: (IteratorValue) +DataSeries\.h:\d+:.*IPSIS_S06.*found: (difference_type) +DataSeries\.h:\d+:.*IPSIS_S06.*found: (ptrdiff_t) +DataSeries\.h:\d+:.*IPSIS_S06.*found: (pointer) +DataSeries\.h:\d+:.*IPSIS_S06.*found: (reference) +DataSeries\.h:\d+:.*IPSIS_S06.*found: (value_type) + # Ignore false positive relative to an alias DataSourceItemAction\.h:\d+:.*IPSIS_S06.*found: (ExecuteFunction)