esp-idf/components/nvs_flash/src/intrusive_list.h
Ivan Grokhotkov 08e41973f0
nvs_flash: update intrusive_list for compatibility with C++17
std::iterator is deprecated since C++17, the code produces a warning
when compiled with clang and libc++.
2022-08-17 12:20:36 +02:00

257 lines
4.3 KiB
C++

/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef intrusive_list_h
#define intrusive_list_h
#include <cassert>
#include <unordered_map>
#include <cstddef>
template <typename T>
class intrusive_list;
template <typename T>
class intrusive_list_node
{
protected:
friend class intrusive_list<T>;
T* mPrev = nullptr;
T* mNext = nullptr;
};
template <typename T>
class intrusive_list
{
typedef intrusive_list_node<T> TNode;
static_assert(std::is_base_of<TNode, T>::value, "");
public:
class iterator
{
public:
using iterator_category = std::forward_iterator_tag;
using value_type = T;
using difference_type = ptrdiff_t;
using pointer = T*;
using reference = T&;
iterator() : mPos(nullptr) {}
iterator(T* pos) : mPos(pos) {}
iterator operator++(int)
{
auto result = *this;
mPos = mPos->mNext;
return result;
}
iterator operator--(int)
{
auto result = *this;
mPos = mPos->mPrev;
return result;
}
iterator& operator++()
{
mPos = mPos->mNext;
return *this;
}
iterator& operator--()
{
mPos = mPos->mPrev;
return *this;
}
bool operator==(const iterator& other) const
{
return mPos == other.mPos;
}
bool operator!=(const iterator& other) const
{
return !(*this == other);
}
T& operator*()
{
return *mPos;
}
const T& operator*() const
{
return *mPos;
}
T* operator->()
{
return mPos;
}
const T* operator->() const
{
return mPos;
}
operator T*()
{
return mPos;
}
operator const T*() const
{
return mPos;
}
protected:
T* mPos;
};
void push_back(T* node)
{
if (mLast) {
mLast->mNext = node;
}
node->mPrev = mLast;
node->mNext = nullptr;
mLast = node;
if (mFirst == nullptr) {
mFirst = node;
}
++mSize;
}
void push_front(T* node)
{
node->mPrev = nullptr;
node->mNext = mFirst;
if (mFirst) {
mFirst->mPrev = node;
}
mFirst = node;
if (mLast == nullptr) {
mLast = node;
}
++mSize;
}
T& back()
{
return *mLast;
}
const T& back() const
{
return *mLast;
}
T& front()
{
return *mFirst;
}
const T& front() const
{
return *mFirst;
}
void pop_front()
{
erase(mFirst);
}
void pop_back()
{
erase(mLast);
}
void insert(iterator next, T* node)
{
if (static_cast<T*>(next) == nullptr) {
push_back(node);
} else {
auto prev = next->mPrev;
if (!prev) {
push_front(node);
} else {
prev->mNext = node;
next->mPrev = node;
node->mNext = next;
node->mPrev = &(*prev);
++mSize;
}
}
}
void erase(iterator it)
{
auto prev = it->mPrev;
auto next = it->mNext;
if (prev) {
prev->mNext = next;
} else {
mFirst = next;
}
if (next) {
next->mPrev = prev;
} else {
mLast = prev;
}
--mSize;
}
iterator begin()
{
return iterator(mFirst);
}
iterator end()
{
return iterator(nullptr);
}
size_t size() const
{
return mSize;
}
bool empty() const
{
return mSize == 0;
}
void clear()
{
while (mFirst) {
erase(mFirst);
}
}
void clearAndFreeNodes()
{
while (mFirst) {
auto tmp = mFirst;
erase(mFirst);
delete tmp;
}
}
protected:
T* mFirst = nullptr;
T* mLast = nullptr;
size_t mSize = 0;
};
#endif /* intrusive_list_h */