Variable.cpp
279 lines
| 7.7 KiB
| text/x-c
|
CppLexer
Alexandre Leroux
|
r163 | #include "Variable/Variable.h" | ||
Alexandre Leroux
|
r164 | #include <Data/IDataSeries.h> | ||
r512 | #include <Data/SqpRange.h> | |||
r226 | ||||
r541 | #include <QMutex> | |||
r364 | #include <QReadWriteLock> | |||
#include <QThread> | ||||
r226 | Q_LOGGING_CATEGORY(LOG_Variable, "Variable") | |||
Alexandre Leroux
|
r164 | |||
Alexandre Leroux
|
r163 | struct Variable::VariablePrivate { | ||
r512 | explicit VariablePrivate(const QString &name, const SqpRange &dateTime, | |||
Alexandre Leroux
|
r406 | const QVariantHash &metadata) | ||
Alexandre Leroux
|
r654 | : m_Name{name}, | ||
m_Range{dateTime}, | ||||
m_Metadata{metadata}, | ||||
m_DataSeries{nullptr}, | ||||
m_RealRange{INVALID_RANGE} | ||||
Alexandre Leroux
|
r163 | { | ||
} | ||||
r541 | void lockRead() { m_Lock.lockForRead(); } | |||
void lockWrite() { m_Lock.lockForWrite(); } | ||||
void unlock() { m_Lock.unlock(); } | ||||
Alexandre Leroux
|
r654 | /// Updates real range according to current variable range and data series | ||
void updateRealRange() | ||||
{ | ||||
if (m_DataSeries) { | ||||
m_DataSeries->lockRead(); | ||||
auto end = m_DataSeries->cend(); | ||||
auto minXAxisIt = m_DataSeries->minXAxisData(m_Range.m_TStart); | ||||
auto maxXAxisIt = m_DataSeries->maxXAxisData(m_Range.m_TEnd); | ||||
m_RealRange = (minXAxisIt != end && maxXAxisIt != end) | ||||
? SqpRange{minXAxisIt->x(), maxXAxisIt->x()} | ||||
: INVALID_RANGE; | ||||
m_DataSeries->unlock(); | ||||
} | ||||
else { | ||||
m_RealRange = INVALID_RANGE; | ||||
} | ||||
} | ||||
Alexandre Leroux
|
r163 | QString m_Name; | ||
r226 | ||||
r532 | SqpRange m_Range; | |||
SqpRange m_CacheRange; | ||||
Alexandre Leroux
|
r406 | QVariantHash m_Metadata; | ||
r542 | std::shared_ptr<IDataSeries> m_DataSeries; | |||
Alexandre Leroux
|
r654 | SqpRange m_RealRange; | ||
r541 | ||||
QReadWriteLock m_Lock; | ||||
Alexandre Leroux
|
r163 | }; | ||
r512 | Variable::Variable(const QString &name, const SqpRange &dateTime, const QVariantHash &metadata) | |||
Alexandre Leroux
|
r406 | : impl{spimpl::make_unique_impl<VariablePrivate>(name, dateTime, metadata)} | ||
Alexandre Leroux
|
r163 | { | ||
} | ||||
QString Variable::name() const noexcept | ||||
{ | ||||
r541 | impl->lockRead(); | |||
auto name = impl->m_Name; | ||||
impl->unlock(); | ||||
return name; | ||||
Alexandre Leroux
|
r163 | } | ||
r532 | SqpRange Variable::range() const noexcept | |||
r235 | { | |||
r541 | impl->lockRead(); | |||
auto range = impl->m_Range; | ||||
impl->unlock(); | ||||
return range; | ||||
r235 | } | |||
r532 | void Variable::setRange(const SqpRange &range) noexcept | |||
r260 | { | |||
r541 | impl->lockWrite(); | |||
r532 | impl->m_Range = range; | |||
Alexandre Leroux
|
r654 | impl->updateRealRange(); | ||
r541 | impl->unlock(); | |||
r532 | } | |||
SqpRange Variable::cacheRange() const noexcept | ||||
{ | ||||
r541 | impl->lockRead(); | |||
auto cacheRange = impl->m_CacheRange; | ||||
impl->unlock(); | ||||
return cacheRange; | ||||
r532 | } | |||
void Variable::setCacheRange(const SqpRange &cacheRange) noexcept | ||||
{ | ||||
r541 | impl->lockWrite(); | |||
r532 | impl->m_CacheRange = cacheRange; | |||
r541 | impl->unlock(); | |||
r260 | } | |||
Alexandre Leroux
|
r654 | SqpRange Variable::realRange() const noexcept | ||
{ | ||||
return impl->m_RealRange; | ||||
} | ||||
Alexandre Leroux
|
r310 | void Variable::setDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept | ||
Alexandre Leroux
|
r164 | { | ||
r542 | qCDebug(LOG_Variable()) << "TORM Variable::setDataSeries" | |||
<< QThread::currentThread()->objectName(); | ||||
Alexandre Leroux
|
r310 | if (!dataSeries) { | ||
/// @todo ALX : log | ||||
return; | ||||
Alexandre Leroux
|
r164 | } | ||
r541 | impl->lockWrite(); | |||
r538 | impl->m_DataSeries = dataSeries->clone(); | |||
Alexandre Leroux
|
r654 | impl->updateRealRange(); | ||
r541 | impl->unlock(); | |||
r538 | } | |||
void Variable::mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept | ||||
{ | ||||
r542 | qCDebug(LOG_Variable()) << "TORM Variable::mergeDataSeries" | |||
r541 | << QThread::currentThread()->objectName(); | |||
r538 | if (!dataSeries) { | |||
/// @todo ALX : log | ||||
return; | ||||
} | ||||
// Add or merge the data | ||||
Alexandre Leroux
|
r310 | // Inits the data series of the variable | ||
r541 | impl->lockWrite(); | |||
Alexandre Leroux
|
r310 | if (!impl->m_DataSeries) { | ||
impl->m_DataSeries = dataSeries->clone(); | ||||
} | ||||
else { | ||||
r235 | impl->m_DataSeries->merge(dataSeries.get()); | |||
} | ||||
r541 | impl->unlock(); | |||
r538 | ||||
// sub the data | ||||
Alexandre Leroux
|
r554 | auto subData = this->dataSeries()->subDataSeries(this->cacheRange()); | ||
r542 | qCDebug(LOG_Variable()) << "TORM: Variable::mergeDataSeries sub" << subData->range(); | |||
r538 | this->setDataSeries(subData); | |||
r542 | qCDebug(LOG_Variable()) << "TORM: Variable::mergeDataSeries set" << this->dataSeries()->range(); | |||
Alexandre Leroux
|
r164 | } | ||
Alexandre Leroux
|
r182 | |||
r542 | std::shared_ptr<IDataSeries> Variable::dataSeries() const noexcept | |||
Alexandre Leroux
|
r182 | { | ||
r541 | impl->lockRead(); | |||
r542 | auto dataSeries = impl->m_DataSeries; | |||
r541 | impl->unlock(); | |||
return dataSeries; | ||||
Alexandre Leroux
|
r182 | } | ||
r226 | ||||
Alexandre Leroux
|
r406 | QVariantHash Variable::metadata() const noexcept | ||
{ | ||||
r541 | impl->lockRead(); | |||
auto metadata = impl->m_Metadata; | ||||
impl->unlock(); | ||||
return metadata; | ||||
Alexandre Leroux
|
r406 | } | ||
r532 | bool Variable::contains(const SqpRange &range) const noexcept | |||
r226 | { | |||
r541 | impl->lockRead(); | |||
auto res = impl->m_Range.contains(range); | ||||
impl->unlock(); | ||||
return res; | ||||
r226 | } | |||
r258 | ||||
r532 | bool Variable::intersect(const SqpRange &range) const noexcept | |||
r258 | { | |||
r541 | ||||
impl->lockRead(); | ||||
auto res = impl->m_Range.intersect(range); | ||||
impl->unlock(); | ||||
return res; | ||||
r258 | } | |||
r318 | ||||
r532 | bool Variable::isInside(const SqpRange &range) const noexcept | |||
r318 | { | |||
r541 | impl->lockRead(); | |||
auto res = range.contains(SqpRange{impl->m_Range.m_TStart, impl->m_Range.m_TEnd}); | ||||
impl->unlock(); | ||||
return res; | ||||
r532 | } | |||
bool Variable::cacheContains(const SqpRange &range) const noexcept | ||||
{ | ||||
r541 | impl->lockRead(); | |||
auto res = impl->m_CacheRange.contains(range); | ||||
impl->unlock(); | ||||
return res; | ||||
r532 | } | |||
bool Variable::cacheIntersect(const SqpRange &range) const noexcept | ||||
{ | ||||
r541 | impl->lockRead(); | |||
auto res = impl->m_CacheRange.intersect(range); | ||||
impl->unlock(); | ||||
return res; | ||||
r532 | } | |||
bool Variable::cacheIsInside(const SqpRange &range) const noexcept | ||||
{ | ||||
r541 | impl->lockRead(); | |||
auto res = range.contains(SqpRange{impl->m_CacheRange.m_TStart, impl->m_CacheRange.m_TEnd}); | ||||
impl->unlock(); | ||||
return res; | ||||
r532 | } | |||
r541 | QVector<SqpRange> Variable::provideNotInCacheRangeList(const SqpRange &range) const noexcept | |||
r532 | { | |||
r570 | // This code assume that cach in contigue. Can return 0, 1 or 2 SqpRange | |||
r532 | auto notInCache = QVector<SqpRange>{}; | |||
if (!this->cacheContains(range)) { | ||||
if (range.m_TEnd <= impl->m_CacheRange.m_TStart | ||||
|| range.m_TStart >= impl->m_CacheRange.m_TEnd) { | ||||
notInCache << range; | ||||
} | ||||
else if (range.m_TStart < impl->m_CacheRange.m_TStart | ||||
&& range.m_TEnd <= impl->m_CacheRange.m_TEnd) { | ||||
notInCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TStart}; | ||||
} | ||||
else if (range.m_TStart < impl->m_CacheRange.m_TStart | ||||
&& range.m_TEnd > impl->m_CacheRange.m_TEnd) { | ||||
notInCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TStart} | ||||
r538 | << SqpRange{impl->m_CacheRange.m_TEnd, range.m_TEnd}; | |||
r532 | } | |||
else if (range.m_TStart < impl->m_CacheRange.m_TEnd) { | ||||
r538 | notInCache << SqpRange{impl->m_CacheRange.m_TEnd, range.m_TEnd}; | |||
r532 | } | |||
else { | ||||
qCCritical(LOG_Variable()) << tr("Detection of unknown case.") | ||||
<< QThread::currentThread(); | ||||
} | ||||
} | ||||
return notInCache; | ||||
r318 | } | |||
r570 | ||||
QVector<SqpRange> Variable::provideInCacheRangeList(const SqpRange &range) const noexcept | ||||
{ | ||||
// This code assume that cach in contigue. Can return 0 or 1 SqpRange | ||||
auto inCache = QVector<SqpRange>{}; | ||||
r589 | if (this->intersect(range)) { | |||
if (range.m_TStart <= impl->m_CacheRange.m_TStart | ||||
&& range.m_TEnd >= impl->m_CacheRange.m_TStart | ||||
&& range.m_TEnd < impl->m_CacheRange.m_TEnd) { | ||||
inCache << SqpRange{impl->m_CacheRange.m_TStart, range.m_TEnd}; | ||||
r570 | } | |||
else if (range.m_TStart >= impl->m_CacheRange.m_TStart | ||||
r589 | && range.m_TEnd <= impl->m_CacheRange.m_TEnd) { | |||
r570 | inCache << range; | |||
} | ||||
r589 | else if (range.m_TStart > impl->m_CacheRange.m_TStart | |||
&& range.m_TEnd > impl->m_CacheRange.m_TEnd) { | ||||
inCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TEnd}; | ||||
} | ||||
else if (range.m_TStart <= impl->m_CacheRange.m_TStart | ||||
&& range.m_TEnd >= impl->m_CacheRange.m_TEnd) { | ||||
inCache << impl->m_CacheRange; | ||||
r570 | } | |||
else { | ||||
qCCritical(LOG_Variable()) << tr("Detection of unknown case.") | ||||
<< QThread::currentThread(); | ||||
} | ||||
} | ||||
return inCache; | ||||
} | ||||