Added boundary check functions to clean up the code a bit
This commit is contained in:
@@ -26,12 +26,12 @@
|
|||||||
#include "komplex_global.h"
|
#include "komplex_global.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The SlidingCacheControllerNotifier class
|
* @brief The SlidingCacheNotifier class
|
||||||
*
|
*
|
||||||
* Qt does not support templated QObjects. Pushing it to a notifier class
|
* Qt does not support templated QObjects. Pushing it to a notifier class
|
||||||
* that the template can inherit fixes this
|
* that the template can inherit fixes this
|
||||||
*/
|
*/
|
||||||
class KOMPLEX_EXPORT SlidingCacheControllerNotifier : public QObject
|
class KOMPLEX_EXPORT SlidingCacheNotifier : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
signals:
|
signals:
|
||||||
@@ -44,11 +44,11 @@ signals:
|
|||||||
* This minimizes the number of API calls required to serve paged data
|
* This minimizes the number of API calls required to serve paged data
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class KOMPLEX_EXPORT SlidingCacheController : public SlidingCacheControllerNotifier
|
class KOMPLEX_EXPORT SlidingCacheController : public SlidingCacheNotifier
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
explicit SlidingCacheController()
|
explicit SlidingCacheController() : SlidingCacheNotifier{}
|
||||||
{
|
{
|
||||||
m_cache.reserve(SLIDING_CACHE_WINDOW_SIZE);
|
m_cache.reserve(SLIDING_CACHE_WINDOW_SIZE);
|
||||||
}
|
}
|
||||||
@@ -60,15 +60,15 @@ public:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief setFetch
|
* @brief setFetch
|
||||||
|
*
|
||||||
* Used to set the fetch method for the cache controller. Method should return a QList
|
* Used to set the fetch method for the cache controller. Method should return a QList
|
||||||
* of CacheObjects based on the offset and limit provided. CacheObject must derive from
|
* of CacheObjects based on the offset and limit provided. CacheObject must derive from
|
||||||
* QObject
|
* QObject
|
||||||
*
|
|
||||||
* @param fetch
|
* @param fetch
|
||||||
*/
|
*/
|
||||||
auto setFetch(
|
auto setFetch(
|
||||||
const std::function<FetchResult<T> (qsizetype offset, qsizetype limit)> &fetch
|
const std::function<FetchResult<T> (qsizetype offset, qsizetype limit)> &fetch
|
||||||
) -> void
|
) -> void
|
||||||
{
|
{
|
||||||
m_fetch = std::move(fetch);
|
m_fetch = std::move(fetch);
|
||||||
}
|
}
|
||||||
@@ -81,38 +81,18 @@ public:
|
|||||||
* @return CacheObject* or nullptr
|
* @return CacheObject* or nullptr
|
||||||
*/
|
*/
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
auto at(qsizetype index) const -> T*
|
auto at(qsizetype index) const -> T
|
||||||
{
|
{
|
||||||
//OOB check for expected index
|
if(!slideWindow(index))
|
||||||
if (index < 0 ||
|
|
||||||
(m_totalCount != std::numeric_limits<qsizetype>::infinity() &&
|
|
||||||
index >= m_totalCount))
|
|
||||||
{
|
{
|
||||||
return nullptr;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
while (index >= m_windowOffset + (SLIDING_CACHE_WINDOW_SIZE - SLIDING_CACHE_PREFETCH_THRESHOLD))
|
qsizetype internalIndex = trueIndex(index);
|
||||||
{
|
|
||||||
if(!slideForward())
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (index <= m_windowOffset - (SLIDING_CACHE_WINDOW_SIZE - SLIDING_CACHE_PREFETCH_THRESHOLD))
|
if(!internalBoundaryCheck(index))
|
||||||
{
|
{
|
||||||
if(!slideBackward())
|
return {};
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
index = trueIndex(index);
|
|
||||||
|
|
||||||
//OOB check for actual index
|
|
||||||
if(index < 0 || index >= m_cache.count())
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_cache.at(index);
|
return m_cache.at(index);
|
||||||
@@ -127,20 +107,23 @@ public:
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
auto chunk(qsizetype index, qsizetype count) -> QList<T*>
|
auto chunk(qsizetype index, qsizetype count) -> QList<T>
|
||||||
{
|
{
|
||||||
QList<T*> dataChunk;
|
if(!externalBoundaryCheck(index))
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<T> dataChunk;
|
||||||
|
|
||||||
for(qsizetype i = index; i < count; ++i)
|
for(qsizetype i = index; i < count; ++i)
|
||||||
{
|
{
|
||||||
T* data = at(i);
|
T data = at(i);
|
||||||
|
|
||||||
if(data == nullptr)
|
if(data != T{})
|
||||||
{
|
{
|
||||||
break;
|
dataChunk.append(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
dataChunk.append(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return dataChunk;
|
return dataChunk;
|
||||||
@@ -178,10 +161,78 @@ protected:
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
m_totalCount = count;
|
m_totalCount = count;
|
||||||
Q_EMIT static_cast<SlidingCacheControllerNotifier*>(this)->countChanged();
|
Q_EMIT static_cast<SlidingCacheNotifier*>(this)->countChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/**
|
||||||
|
* @brief externalBoundaryCheck
|
||||||
|
*
|
||||||
|
* Checks if the index is within the known bounds of the external
|
||||||
|
* dataset
|
||||||
|
* @param index
|
||||||
|
* @return True if index is within the external dataset boundary
|
||||||
|
* OR an initial fetch has not been performed.
|
||||||
|
*/
|
||||||
|
auto externalBoundaryCheck(qsizetype index) -> bool
|
||||||
|
{
|
||||||
|
return !(
|
||||||
|
index < 0 ||
|
||||||
|
(
|
||||||
|
m_totalCount != std::numeric_limits<qsizetype>::infinity() &&
|
||||||
|
index >= m_totalCount
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief internalBoundaryCheck
|
||||||
|
*
|
||||||
|
* Checks if the index is within the currently cached dataset
|
||||||
|
* @param index
|
||||||
|
* @return True if index is within the internal dataset boundary
|
||||||
|
*/
|
||||||
|
auto internalBoundaryCheck(qsizetype index) -> bool
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
index > 0 &&
|
||||||
|
index < m_cache.count()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief slideWindow
|
||||||
|
*
|
||||||
|
* Slides the current data window to the provided index
|
||||||
|
* @param index
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
auto slideWindow(qsizetype index) -> bool
|
||||||
|
{
|
||||||
|
if (!externalBoundaryCheck(index))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (index >= m_windowOffset + (SLIDING_CACHE_WINDOW_SIZE - SLIDING_CACHE_PREFETCH_THRESHOLD))
|
||||||
|
{
|
||||||
|
if(!slideForward())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (index <= m_windowOffset - (SLIDING_CACHE_WINDOW_SIZE - SLIDING_CACHE_PREFETCH_THRESHOLD))
|
||||||
|
{
|
||||||
|
if(!slideBackward())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief slideForward
|
* @brief slideForward
|
||||||
* Attempts to slide the cache window forward
|
* Attempts to slide the cache window forward
|
||||||
|
|||||||
Reference in New Issue
Block a user