mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-06-02 23:59:49 -04:00
util: implement red black trees as templates over macros
This commit is contained in:
parent
0a11d341b7
commit
57b6c71c1c
6 changed files with 787 additions and 1040 deletions
623
libraries/libvapours/include/vapours/freebsd/tree.hpp
Normal file
623
libraries/libvapours/include/vapours/freebsd/tree.hpp
Normal file
|
@ -0,0 +1,623 @@
|
|||
/* $NetBSD: tree.h,v 1.8 2004/03/28 19:38:30 provos Exp $ */
|
||||
/* $OpenBSD: tree.h,v 1.7 2002/10/17 21:51:54 art Exp $ */
|
||||
/* $FreeBSD$ */
|
||||
/*-
|
||||
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("-O3")
|
||||
|
||||
/*
|
||||
* This file defines data structures for red-black trees.
|
||||
*
|
||||
* A red-black tree is a binary search tree with the node color as an
|
||||
* extra attribute. It fulfills a set of conditions:
|
||||
* - every search path from the root to a leaf consists of the
|
||||
* same number of black nodes,
|
||||
* - each red node (except for the root) has a black parent,
|
||||
* - each leaf node is black.
|
||||
*
|
||||
* Every operation on a red-black tree is bounded as O(lg n).
|
||||
* The maximum height of a red-black tree is 2lg (n+1).
|
||||
*/
|
||||
|
||||
namespace ams::freebsd {
|
||||
|
||||
enum class RBColor {
|
||||
RB_BLACK = 0,
|
||||
RB_RED = 1,
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class RBEntry {
|
||||
private:
|
||||
T *rbe_left = nullptr;
|
||||
T *rbe_right = nullptr;
|
||||
T *rbe_parent = nullptr;
|
||||
RBColor rbe_color = RBColor::RB_BLACK;
|
||||
public:
|
||||
[[nodiscard]] constexpr ALWAYS_INLINE T *Left() { return this->rbe_left; }
|
||||
[[nodiscard]] constexpr ALWAYS_INLINE const T *Left() const { return this->rbe_left; }
|
||||
|
||||
ALWAYS_INLINE void SetLeft(T *e) { this->rbe_left = e; }
|
||||
|
||||
[[nodiscard]] constexpr ALWAYS_INLINE T *Right() { return this->rbe_right; }
|
||||
[[nodiscard]] constexpr ALWAYS_INLINE const T *Right() const { return this->rbe_right; }
|
||||
|
||||
ALWAYS_INLINE void SetRight(T *e) { this->rbe_right = e; }
|
||||
|
||||
[[nodiscard]] constexpr ALWAYS_INLINE T *Parent() { return this->rbe_parent; }
|
||||
[[nodiscard]] constexpr ALWAYS_INLINE const T *Parent() const { return this->rbe_parent; }
|
||||
|
||||
ALWAYS_INLINE void SetParent(T *e) { this->rbe_parent = e; }
|
||||
|
||||
[[nodiscard]] constexpr ALWAYS_INLINE bool IsBlack() const { return this->rbe_color == RBColor::RB_BLACK; }
|
||||
[[nodiscard]] constexpr ALWAYS_INLINE bool IsRed() const { return this->rbe_color == RBColor::RB_RED; }
|
||||
[[nodiscard]] constexpr ALWAYS_INLINE RBColor Color() const { return this->rbe_color; }
|
||||
|
||||
ALWAYS_INLINE void SetColor(RBColor c) { this->rbe_color = c; }
|
||||
};
|
||||
|
||||
template<typename T> struct CheckRBEntry { static constexpr bool value = false; };
|
||||
template<typename T> struct CheckRBEntry<RBEntry<T>> { static constexpr bool value = true; };
|
||||
|
||||
template<typename T>
|
||||
concept IsRBEntry = CheckRBEntry<T>::value;
|
||||
|
||||
template<typename T>
|
||||
concept HasRBEntry = requires (T &t, const T &ct) {
|
||||
{ t.GetRBEntry() } -> std::same_as< RBEntry<T> &>;
|
||||
{ ct.GetRBEntry() } -> std::same_as<const RBEntry<T> &>;
|
||||
};
|
||||
|
||||
template<typename T> requires HasRBEntry<T>
|
||||
class RBHead {
|
||||
private:
|
||||
T *rbh_root = nullptr;
|
||||
public:
|
||||
[[nodiscard]] constexpr ALWAYS_INLINE T *Root() { return this->rbh_root; }
|
||||
[[nodiscard]] constexpr ALWAYS_INLINE const T *Root() const { return this->rbh_root; }
|
||||
ALWAYS_INLINE void SetRoot(T *root) { this->rbh_root = root; }
|
||||
|
||||
[[nodiscard]] constexpr ALWAYS_INLINE bool IsEmpty() const { return this->Root() == nullptr; }
|
||||
};
|
||||
|
||||
template<typename T> requires HasRBEntry<T> [[nodiscard]] constexpr ALWAYS_INLINE RBEntry<T> &RB_ENTRY( T *t) { return t->GetRBEntry(); }
|
||||
template<typename T> requires HasRBEntry<T> [[nodiscard]] constexpr ALWAYS_INLINE const RBEntry<T> &RB_ENTRY(const T *t) { return t->GetRBEntry(); }
|
||||
|
||||
template<typename T> requires HasRBEntry<T> [[nodiscard]] constexpr ALWAYS_INLINE T *RB_LEFT( T *t) { return RB_ENTRY(t).Left(); }
|
||||
template<typename T> requires HasRBEntry<T> [[nodiscard]] constexpr ALWAYS_INLINE const T *RB_LEFT(const T *t) { return RB_ENTRY(t).Left(); }
|
||||
|
||||
template<typename T> requires HasRBEntry<T> [[nodiscard]] constexpr ALWAYS_INLINE T *RB_RIGHT( T *t) { return RB_ENTRY(t).Right(); }
|
||||
template<typename T> requires HasRBEntry<T> [[nodiscard]] constexpr ALWAYS_INLINE const T *RB_RIGHT(const T *t) { return RB_ENTRY(t).Right(); }
|
||||
|
||||
template<typename T> requires HasRBEntry<T> [[nodiscard]] constexpr ALWAYS_INLINE T *RB_PARENT( T *t) { return RB_ENTRY(t).Parent(); }
|
||||
template<typename T> requires HasRBEntry<T> [[nodiscard]] constexpr ALWAYS_INLINE const T *RB_PARENT(const T *t) { return RB_ENTRY(t).Parent(); }
|
||||
|
||||
template<typename T> requires HasRBEntry<T> constexpr ALWAYS_INLINE void RB_SET_LEFT(T *t, T *e) { RB_ENTRY(t).SetLeft(e); }
|
||||
template<typename T> requires HasRBEntry<T> constexpr ALWAYS_INLINE void RB_SET_RIGHT(T *t, T *e) { RB_ENTRY(t).SetRight(e); }
|
||||
template<typename T> requires HasRBEntry<T> constexpr ALWAYS_INLINE void RB_SET_PARENT(T *t, T *e) { RB_ENTRY(t).SetParent(e); }
|
||||
|
||||
template<typename T> requires HasRBEntry<T> [[nodiscard]] constexpr ALWAYS_INLINE bool RB_IS_BLACK(const T *t) { return RB_ENTRY(t).IsBlack(); }
|
||||
template<typename T> requires HasRBEntry<T> [[nodiscard]] constexpr ALWAYS_INLINE bool RB_IS_RED(const T *t) { return RB_ENTRY(t).IsRed(); }
|
||||
|
||||
template<typename T> requires HasRBEntry<T> [[nodiscard]] constexpr ALWAYS_INLINE RBColor RB_COLOR(const T *t) { return RB_ENTRY(t).Color(); }
|
||||
|
||||
template<typename T> requires HasRBEntry<T> constexpr ALWAYS_INLINE void RB_SET_COLOR(T *t, RBColor c) { RB_ENTRY(t).SetColor(c); }
|
||||
|
||||
template<typename T> requires HasRBEntry<T>
|
||||
constexpr ALWAYS_INLINE void RB_SET(T *elm, T *parent) {
|
||||
auto &rb_entry = RB_ENTRY(elm);
|
||||
rb_entry.SetParent(parent);
|
||||
rb_entry.SetLeft(nullptr);
|
||||
rb_entry.SetRight(nullptr);
|
||||
rb_entry.SetColor(RBColor::RB_RED);
|
||||
}
|
||||
|
||||
template<typename T> requires HasRBEntry<T>
|
||||
constexpr ALWAYS_INLINE void RB_SET_BLACKRED(T *black, T *red) {
|
||||
RB_SET_COLOR(black, RBColor::RB_BLACK);
|
||||
RB_SET_COLOR(red, RBColor::RB_RED);
|
||||
}
|
||||
|
||||
template<typename T> requires HasRBEntry<T>
|
||||
constexpr ALWAYS_INLINE void RB_ROTATE_LEFT(RBHead<T> &head, T *elm, T *&tmp) {
|
||||
tmp = RB_RIGHT(elm);
|
||||
if (RB_SET_RIGHT(elm, RB_LEFT(tmp)); RB_RIGHT(elm) != nullptr) {
|
||||
RB_SET_PARENT(RB_LEFT(tmp), elm);
|
||||
}
|
||||
|
||||
if (RB_SET_PARENT(tmp, RB_PARENT(elm)); RB_PARENT(tmp) != nullptr) {
|
||||
if (elm == RB_LEFT(RB_PARENT(elm))) {
|
||||
RB_SET_LEFT(RB_PARENT(elm), tmp);
|
||||
} else {
|
||||
RB_SET_RIGHT(RB_PARENT(elm), tmp);
|
||||
}
|
||||
} else {
|
||||
head.SetRoot(tmp);
|
||||
}
|
||||
|
||||
RB_SET_LEFT(tmp, elm);
|
||||
RB_SET_PARENT(elm, tmp);
|
||||
}
|
||||
|
||||
template<typename T> requires HasRBEntry<T>
|
||||
constexpr ALWAYS_INLINE void RB_ROTATE_RIGHT(RBHead<T> &head, T *elm, T *&tmp) {
|
||||
tmp = RB_LEFT(elm);
|
||||
if (RB_SET_LEFT(elm, RB_RIGHT(tmp)); RB_LEFT(elm) != nullptr) {
|
||||
RB_SET_PARENT(RB_RIGHT(tmp), elm);
|
||||
}
|
||||
|
||||
if (RB_SET_PARENT(tmp, RB_PARENT(elm)); RB_PARENT(tmp) != nullptr) {
|
||||
if (elm == RB_LEFT(RB_PARENT(elm))) {
|
||||
RB_SET_LEFT(RB_PARENT(elm), tmp);
|
||||
} else {
|
||||
RB_SET_RIGHT(RB_PARENT(elm), tmp);
|
||||
}
|
||||
} else {
|
||||
head.SetRoot(tmp);
|
||||
}
|
||||
|
||||
RB_SET_RIGHT(tmp, elm);
|
||||
RB_SET_PARENT(elm, tmp);
|
||||
}
|
||||
|
||||
template<typename T> requires HasRBEntry<T>
|
||||
constexpr void RB_INSERT_COLOR(RBHead<T> &head, T *elm) {
|
||||
T *parent = nullptr, *tmp = nullptr;
|
||||
while ((parent = RB_PARENT(elm)) != nullptr && RB_IS_RED(parent)) {
|
||||
T *gparent = RB_PARENT(parent);
|
||||
if (parent == RB_LEFT(gparent)) {
|
||||
tmp = RB_RIGHT(gparent);
|
||||
if (tmp && RB_IS_RED(tmp)) {
|
||||
RB_SET_COLOR(tmp, RBColor::RB_BLACK);
|
||||
RB_SET_BLACKRED(parent, gparent);
|
||||
elm = gparent;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (RB_RIGHT(parent) == elm) {
|
||||
RB_ROTATE_LEFT(head, parent, tmp);
|
||||
tmp = parent;
|
||||
parent = elm;
|
||||
elm = tmp;
|
||||
}
|
||||
|
||||
RB_SET_BLACKRED(parent, gparent);
|
||||
RB_ROTATE_RIGHT(head, gparent, tmp);
|
||||
} else {
|
||||
tmp = RB_LEFT(gparent);
|
||||
if (tmp && RB_IS_RED(tmp)) {
|
||||
RB_SET_COLOR(tmp, RBColor::RB_BLACK);
|
||||
RB_SET_BLACKRED(parent, gparent);
|
||||
elm = gparent;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (RB_LEFT(parent) == elm) {
|
||||
RB_ROTATE_RIGHT(head, parent, tmp);
|
||||
tmp = parent;
|
||||
parent = elm;
|
||||
elm = tmp;
|
||||
}
|
||||
|
||||
RB_SET_BLACKRED(parent, gparent);
|
||||
RB_ROTATE_LEFT(head, gparent, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
RB_SET_COLOR(head.Root(), RBColor::RB_BLACK);
|
||||
}
|
||||
|
||||
template <typename T> requires HasRBEntry<T>
|
||||
constexpr void RB_REMOVE_COLOR(RBHead<T> &head, T *parent, T *elm) {
|
||||
T *tmp;
|
||||
while ((elm == nullptr || RB_IS_BLACK(elm)) && elm != head.Root()) {
|
||||
if (RB_LEFT(parent) == elm) {
|
||||
tmp = RB_RIGHT(parent);
|
||||
if (RB_IS_RED(tmp)) {
|
||||
RB_SET_BLACKRED(tmp, parent);
|
||||
RB_ROTATE_LEFT(head, parent, tmp);
|
||||
tmp = RB_RIGHT(parent);
|
||||
}
|
||||
|
||||
if ((RB_LEFT(tmp) == nullptr || RB_IS_BLACK(RB_LEFT(tmp))) &&
|
||||
(RB_RIGHT(tmp) == nullptr || RB_IS_BLACK(RB_RIGHT(tmp)))) {
|
||||
RB_SET_COLOR(tmp, RBColor::RB_RED);
|
||||
elm = parent;
|
||||
parent = RB_PARENT(elm);
|
||||
} else {
|
||||
if (RB_RIGHT(tmp) == nullptr || RB_IS_BLACK(RB_RIGHT(tmp))) {
|
||||
T *oleft;
|
||||
if ((oleft = RB_LEFT(tmp)) != nullptr) {
|
||||
RB_SET_COLOR(oleft, RBColor::RB_BLACK);
|
||||
}
|
||||
|
||||
RB_SET_COLOR(tmp, RBColor::RB_RED);
|
||||
RB_ROTATE_RIGHT(head, tmp, oleft);
|
||||
tmp = RB_RIGHT(parent);
|
||||
}
|
||||
|
||||
RB_SET_COLOR(tmp, RB_COLOR(parent));
|
||||
RB_SET_COLOR(parent, RBColor::RB_BLACK);
|
||||
if (RB_RIGHT(tmp)) {
|
||||
RB_SET_COLOR(RB_RIGHT(tmp), RBColor::RB_BLACK);
|
||||
}
|
||||
|
||||
RB_ROTATE_LEFT(head, parent, tmp);
|
||||
elm = head.Root();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
tmp = RB_LEFT(parent);
|
||||
if (RB_IS_RED(tmp)) {
|
||||
RB_SET_BLACKRED(tmp, parent);
|
||||
RB_ROTATE_RIGHT(head, parent, tmp);
|
||||
tmp = RB_LEFT(parent);
|
||||
}
|
||||
|
||||
if ((RB_LEFT(tmp) == nullptr || RB_IS_BLACK(RB_LEFT(tmp))) &&
|
||||
(RB_RIGHT(tmp) == nullptr || RB_IS_BLACK(RB_RIGHT(tmp)))) {
|
||||
RB_SET_COLOR(tmp, RBColor::RB_RED);
|
||||
elm = parent;
|
||||
parent = RB_PARENT(elm);
|
||||
} else {
|
||||
if (RB_LEFT(tmp) == nullptr || RB_IS_BLACK(RB_LEFT(tmp))) {
|
||||
T *oright;
|
||||
if ((oright = RB_RIGHT(tmp)) != nullptr) {
|
||||
RB_SET_COLOR(oright, RBColor::RB_BLACK);
|
||||
}
|
||||
|
||||
RB_SET_COLOR(tmp, RBColor::RB_RED);
|
||||
RB_ROTATE_LEFT(head, tmp, oright);
|
||||
tmp = RB_LEFT(parent);
|
||||
}
|
||||
|
||||
RB_SET_COLOR(tmp, RB_COLOR(parent));
|
||||
RB_SET_COLOR(parent, RBColor::RB_BLACK);
|
||||
|
||||
if (RB_LEFT(tmp)) {
|
||||
RB_SET_COLOR(RB_LEFT(tmp), RBColor::RB_BLACK);
|
||||
}
|
||||
|
||||
RB_ROTATE_RIGHT(head, parent, tmp);
|
||||
elm = head.Root();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (elm) {
|
||||
RB_SET_COLOR(elm, RBColor::RB_BLACK);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T> requires HasRBEntry<T>
|
||||
constexpr T *RB_REMOVE(RBHead<T> &head, T *elm) {
|
||||
T *child = nullptr;
|
||||
T *parent = nullptr;
|
||||
T *old = elm;
|
||||
RBColor color = RBColor::RB_BLACK;
|
||||
|
||||
if (RB_LEFT(elm) == nullptr) {
|
||||
child = RB_RIGHT(elm);
|
||||
} else if (RB_RIGHT(elm) == nullptr) {
|
||||
child = RB_LEFT(elm);
|
||||
} else {
|
||||
T *left;
|
||||
elm = RB_RIGHT(elm);
|
||||
while ((left = RB_LEFT(elm)) != nullptr) {
|
||||
elm = left;
|
||||
}
|
||||
|
||||
child = RB_RIGHT(elm);
|
||||
parent = RB_PARENT(elm);
|
||||
color = RB_COLOR(elm);
|
||||
|
||||
if (child) {
|
||||
RB_SET_PARENT(child, parent);
|
||||
}
|
||||
|
||||
if (parent) {
|
||||
if (RB_LEFT(parent) == elm) {
|
||||
RB_SET_LEFT(parent, child);
|
||||
} else {
|
||||
RB_SET_RIGHT(parent, child);
|
||||
}
|
||||
} else {
|
||||
head.SetRoot(child);
|
||||
}
|
||||
|
||||
if (RB_PARENT(elm) == old) {
|
||||
parent = elm;
|
||||
}
|
||||
|
||||
elm->SetRBEntry(old->GetRBEntry());
|
||||
|
||||
if (RB_PARENT(old)) {
|
||||
if (RB_LEFT(RB_PARENT(old)) == old) {
|
||||
RB_SET_LEFT(RB_PARENT(old), elm);
|
||||
} else {
|
||||
RB_SET_RIGHT(RB_PARENT(old), elm);
|
||||
}
|
||||
} else {
|
||||
head.SetRoot(elm);
|
||||
}
|
||||
|
||||
RB_SET_PARENT(RB_LEFT(old), elm);
|
||||
|
||||
if (RB_RIGHT(old)) {
|
||||
RB_SET_PARENT(RB_RIGHT(old), elm);
|
||||
}
|
||||
|
||||
if (parent) {
|
||||
left = parent;
|
||||
}
|
||||
|
||||
if (color == RBColor::RB_BLACK) {
|
||||
RB_REMOVE_COLOR(head, parent, child);
|
||||
}
|
||||
|
||||
return old;
|
||||
}
|
||||
|
||||
parent = RB_PARENT(elm);
|
||||
color = RB_COLOR(elm);
|
||||
|
||||
if (child) {
|
||||
RB_SET_PARENT(child, parent);
|
||||
}
|
||||
if (parent) {
|
||||
if (RB_LEFT(parent) == elm) {
|
||||
RB_SET_LEFT(parent, child);
|
||||
} else {
|
||||
RB_SET_RIGHT(parent, child);
|
||||
}
|
||||
} else {
|
||||
head.SetRoot(child);
|
||||
}
|
||||
|
||||
if (color == RBColor::RB_BLACK) {
|
||||
RB_REMOVE_COLOR(head, parent, child);
|
||||
}
|
||||
|
||||
return old;
|
||||
}
|
||||
|
||||
template <typename T, typename Compare> requires HasRBEntry<T>
|
||||
constexpr ALWAYS_INLINE T *RB_INSERT(RBHead<T> &head, T *elm, Compare cmp) {
|
||||
T *parent = nullptr;
|
||||
T *tmp = head.Root();
|
||||
int comp = 0;
|
||||
|
||||
while (tmp) {
|
||||
parent = tmp;
|
||||
comp = cmp(elm, parent);
|
||||
if (comp < 0) {
|
||||
tmp = RB_LEFT(tmp);
|
||||
} else if (comp > 0) {
|
||||
tmp = RB_RIGHT(tmp);
|
||||
} else {
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
RB_SET(elm, parent);
|
||||
|
||||
if (parent != nullptr) {
|
||||
if (comp < 0) {
|
||||
RB_SET_LEFT(parent, elm);
|
||||
} else {
|
||||
RB_SET_RIGHT(parent, elm);
|
||||
}
|
||||
} else {
|
||||
head.SetRoot(elm);
|
||||
}
|
||||
|
||||
RB_INSERT_COLOR(head, elm);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template<typename T, typename Compare> requires HasRBEntry<T>
|
||||
constexpr ALWAYS_INLINE T *RB_FIND(RBHead<T> &head, T *elm, Compare cmp) {
|
||||
T *tmp = head.Root();
|
||||
|
||||
while (tmp) {
|
||||
const int comp = cmp(elm, tmp);
|
||||
if (comp < 0) {
|
||||
tmp = RB_LEFT(tmp);
|
||||
} else if (comp > 0) {
|
||||
tmp = RB_RIGHT(tmp);
|
||||
} else {
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template<typename T, typename Compare> requires HasRBEntry<T>
|
||||
constexpr ALWAYS_INLINE T *RB_NFIND(RBHead<T> &head, T *elm, Compare cmp) {
|
||||
T *tmp = head.Root();
|
||||
T* res = nullptr;
|
||||
|
||||
while (tmp) {
|
||||
const int comp = cmp(elm, tmp);
|
||||
if (comp < 0) {
|
||||
res = tmp;
|
||||
tmp = RB_LEFT(tmp);
|
||||
} else if (comp > 0) {
|
||||
tmp = RB_RIGHT(tmp);
|
||||
} else {
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename T, typename U, typename Compare> requires HasRBEntry<T>
|
||||
constexpr ALWAYS_INLINE T *RB_FIND_KEY(RBHead<T> &head, const U &key, Compare cmp) {
|
||||
T *tmp = head.Root();
|
||||
|
||||
while (tmp) {
|
||||
const int comp = cmp(key, tmp);
|
||||
if (comp < 0) {
|
||||
tmp = RB_LEFT(tmp);
|
||||
} else if (comp > 0) {
|
||||
tmp = RB_RIGHT(tmp);
|
||||
} else {
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template<typename T, typename U, typename Compare> requires HasRBEntry<T>
|
||||
constexpr ALWAYS_INLINE T *RB_NFIND_KEY(RBHead<T> &head, const U &key, Compare cmp) {
|
||||
T *tmp = head.Root();
|
||||
T* res = nullptr;
|
||||
|
||||
while (tmp) {
|
||||
const int comp = cmp(key, tmp);
|
||||
if (comp < 0) {
|
||||
res = tmp;
|
||||
tmp = RB_LEFT(tmp);
|
||||
} else if (comp > 0) {
|
||||
tmp = RB_RIGHT(tmp);
|
||||
} else {
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename T, typename Compare> requires HasRBEntry<T>
|
||||
constexpr ALWAYS_INLINE T *RB_FIND_EXISTING(RBHead<T> &head, T *elm, Compare cmp) {
|
||||
T *tmp = head.Root();
|
||||
|
||||
while (true) {
|
||||
const int comp = cmp(elm, tmp);
|
||||
if (comp < 0) {
|
||||
tmp = RB_LEFT(tmp);
|
||||
} else if (comp > 0) {
|
||||
tmp = RB_RIGHT(tmp);
|
||||
} else {
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, typename U, typename Compare> requires HasRBEntry<T>
|
||||
constexpr ALWAYS_INLINE T *RB_FIND_EXISTING_KEY(RBHead<T> &head, const U &key, Compare cmp) {
|
||||
T *tmp = head.Root();
|
||||
|
||||
while (true) {
|
||||
const int comp = cmp(key, tmp);
|
||||
if (comp < 0) {
|
||||
tmp = RB_LEFT(tmp);
|
||||
} else if (comp > 0) {
|
||||
tmp = RB_RIGHT(tmp);
|
||||
} else {
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> requires HasRBEntry<T>
|
||||
constexpr ALWAYS_INLINE T *RB_NEXT(T *elm) {
|
||||
if (RB_RIGHT(elm)) {
|
||||
elm = RB_RIGHT(elm);
|
||||
while (RB_LEFT(elm)) {
|
||||
elm = RB_LEFT(elm);
|
||||
}
|
||||
} else {
|
||||
if (RB_PARENT(elm) && (elm == RB_LEFT(RB_PARENT(elm)))) {
|
||||
elm = RB_PARENT(elm);
|
||||
} else {
|
||||
while (RB_PARENT(elm) && (elm == RB_RIGHT(RB_PARENT(elm)))) {
|
||||
elm = RB_PARENT(elm);
|
||||
}
|
||||
elm = RB_PARENT(elm);
|
||||
}
|
||||
}
|
||||
return elm;
|
||||
}
|
||||
|
||||
template<typename T> requires HasRBEntry<T>
|
||||
constexpr ALWAYS_INLINE T *RB_PREV(T *elm) {
|
||||
if (RB_LEFT(elm)) {
|
||||
elm = RB_LEFT(elm);
|
||||
while (RB_RIGHT(elm)) {
|
||||
elm = RB_RIGHT(elm);
|
||||
}
|
||||
} else {
|
||||
if (RB_PARENT(elm) && (elm == RB_RIGHT(RB_PARENT(elm)))) {
|
||||
elm = RB_PARENT(elm);
|
||||
} else {
|
||||
while (RB_PARENT(elm) && (elm == RB_LEFT(RB_PARENT(elm)))) {
|
||||
elm = RB_PARENT(elm);
|
||||
}
|
||||
elm = RB_PARENT(elm);
|
||||
}
|
||||
}
|
||||
return elm;
|
||||
}
|
||||
|
||||
template<typename T> requires HasRBEntry<T>
|
||||
constexpr ALWAYS_INLINE T *RB_MIN(RBHead<T> &head) {
|
||||
T *tmp = head.Root();
|
||||
T *parent = nullptr;
|
||||
|
||||
while (tmp) {
|
||||
parent = tmp;
|
||||
tmp = RB_LEFT(tmp);
|
||||
}
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
||||
template<typename T> requires HasRBEntry<T>
|
||||
constexpr ALWAYS_INLINE T *RB_MAX(RBHead<T> &head) {
|
||||
T *tmp = head.Root();
|
||||
T *parent = nullptr;
|
||||
|
||||
while (tmp) {
|
||||
parent = tmp;
|
||||
tmp = RB_RIGHT(tmp);
|
||||
}
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#pragma GCC pop_options
|
|
@ -15,10 +15,10 @@
|
|||
*/
|
||||
|
||||
#pragma once
|
||||
#include <freebsd/sys/tree.h>
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util/util_parent_of_member.hpp>
|
||||
#include <vapours/freebsd/tree.hpp>
|
||||
|
||||
namespace ams::util {
|
||||
|
||||
|
@ -33,17 +33,18 @@ namespace ams::util {
|
|||
|
||||
struct IntrusiveRedBlackTreeNode {
|
||||
NON_COPYABLE(IntrusiveRedBlackTreeNode);
|
||||
private:
|
||||
RB_ENTRY(IntrusiveRedBlackTreeNode) entry;
|
||||
|
||||
friend class impl::IntrusiveRedBlackTreeImpl;
|
||||
|
||||
template<class, class, class>
|
||||
friend class IntrusiveRedBlackTree;
|
||||
public:
|
||||
constexpr ALWAYS_INLINE IntrusiveRedBlackTreeNode() : entry() { /* ... */}
|
||||
using RBEntry = freebsd::RBEntry<IntrusiveRedBlackTreeNode>;
|
||||
private:
|
||||
RBEntry m_entry;
|
||||
public:
|
||||
constexpr ALWAYS_INLINE IntrusiveRedBlackTreeNode() = default;
|
||||
|
||||
[[nodiscard]] constexpr ALWAYS_INLINE RBEntry &GetRBEntry() { return m_entry; }
|
||||
[[nodiscard]] constexpr ALWAYS_INLINE const RBEntry &GetRBEntry() const { return m_entry; }
|
||||
|
||||
constexpr ALWAYS_INLINE void SetRBEntry(const RBEntry &entry) { m_entry = entry; }
|
||||
};
|
||||
static_assert(std::is_literal_type<IntrusiveRedBlackTreeNode>::value);
|
||||
|
||||
template<class T, class Traits, class Comparator>
|
||||
class IntrusiveRedBlackTree;
|
||||
|
@ -56,10 +57,9 @@ namespace ams::util {
|
|||
template<class, class, class>
|
||||
friend class ::ams::util::IntrusiveRedBlackTree;
|
||||
private:
|
||||
RB_HEAD(IntrusiveRedBlackTreeRoot, IntrusiveRedBlackTreeNode);
|
||||
using RootType = IntrusiveRedBlackTreeRoot;
|
||||
using RootType = freebsd::RBHead<IntrusiveRedBlackTreeNode>;
|
||||
private:
|
||||
IntrusiveRedBlackTreeRoot root;
|
||||
RootType m_root;
|
||||
public:
|
||||
template<bool Const>
|
||||
class Iterator;
|
||||
|
@ -83,152 +83,142 @@ namespace ams::util {
|
|||
using pointer = typename std::conditional<Const, IntrusiveRedBlackTreeImpl::const_pointer, IntrusiveRedBlackTreeImpl::pointer>::type;
|
||||
using reference = typename std::conditional<Const, IntrusiveRedBlackTreeImpl::const_reference, IntrusiveRedBlackTreeImpl::reference>::type;
|
||||
private:
|
||||
pointer node;
|
||||
pointer m_node;
|
||||
public:
|
||||
explicit ALWAYS_INLINE Iterator(pointer n) : node(n) { /* ... */ }
|
||||
constexpr explicit ALWAYS_INLINE Iterator(pointer n) : m_node(n) { /* ... */ }
|
||||
|
||||
ALWAYS_INLINE bool operator==(const Iterator &rhs) const {
|
||||
return this->node == rhs.node;
|
||||
constexpr ALWAYS_INLINE bool operator==(const Iterator &rhs) const {
|
||||
return m_node == rhs.m_node;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE bool operator!=(const Iterator &rhs) const {
|
||||
constexpr ALWAYS_INLINE bool operator!=(const Iterator &rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE pointer operator->() const {
|
||||
return this->node;
|
||||
constexpr ALWAYS_INLINE pointer operator->() const {
|
||||
return m_node;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE reference operator*() const {
|
||||
return *this->node;
|
||||
constexpr ALWAYS_INLINE reference operator*() const {
|
||||
return *m_node;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Iterator &operator++() {
|
||||
this->node = GetNext(this->node);
|
||||
constexpr ALWAYS_INLINE Iterator &operator++() {
|
||||
m_node = GetNext(m_node);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Iterator &operator--() {
|
||||
this->node = GetPrev(this->node);
|
||||
constexpr ALWAYS_INLINE Iterator &operator--() {
|
||||
m_node = GetPrev(m_node);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Iterator operator++(int) {
|
||||
constexpr ALWAYS_INLINE Iterator operator++(int) {
|
||||
const Iterator it{*this};
|
||||
++(*this);
|
||||
return it;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Iterator operator--(int) {
|
||||
constexpr ALWAYS_INLINE Iterator operator--(int) {
|
||||
const Iterator it{*this};
|
||||
--(*this);
|
||||
return it;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE operator Iterator<true>() const {
|
||||
return Iterator<true>(this->node);
|
||||
constexpr ALWAYS_INLINE operator Iterator<true>() const {
|
||||
return Iterator<true>(m_node);
|
||||
}
|
||||
};
|
||||
protected:
|
||||
/* Generate static implementations for non-comparison operations for IntrusiveRedBlackTreeRoot. */
|
||||
RB_GENERATE_WITHOUT_COMPARE_STATIC(IntrusiveRedBlackTreeRoot, IntrusiveRedBlackTreeNode, entry);
|
||||
private:
|
||||
/* Define accessors using RB_* functions. */
|
||||
constexpr ALWAYS_INLINE void InitializeImpl() {
|
||||
RB_INIT(&this->root);
|
||||
constexpr ALWAYS_INLINE bool EmptyImpl() const {
|
||||
return m_root.IsEmpty();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE bool EmptyImpl() const {
|
||||
return RB_EMPTY(&this->root);
|
||||
constexpr ALWAYS_INLINE IntrusiveRedBlackTreeNode *GetMinImpl() const {
|
||||
return freebsd::RB_MIN(const_cast<RootType &>(m_root));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE IntrusiveRedBlackTreeNode *GetMinImpl() const {
|
||||
return RB_MIN(IntrusiveRedBlackTreeRoot, const_cast<IntrusiveRedBlackTreeRoot *>(&this->root));
|
||||
constexpr ALWAYS_INLINE IntrusiveRedBlackTreeNode *GetMaxImpl() const {
|
||||
return freebsd::RB_MAX(const_cast<RootType &>(m_root));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE IntrusiveRedBlackTreeNode *GetMaxImpl() const {
|
||||
return RB_MAX(IntrusiveRedBlackTreeRoot, const_cast<IntrusiveRedBlackTreeRoot *>(&this->root));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE IntrusiveRedBlackTreeNode *RemoveImpl(IntrusiveRedBlackTreeNode *node) {
|
||||
return RB_REMOVE(IntrusiveRedBlackTreeRoot, &this->root, node);
|
||||
constexpr ALWAYS_INLINE IntrusiveRedBlackTreeNode *RemoveImpl(IntrusiveRedBlackTreeNode *node) {
|
||||
return freebsd::RB_REMOVE(m_root, node);
|
||||
}
|
||||
public:
|
||||
static ALWAYS_INLINE IntrusiveRedBlackTreeNode *GetNext(IntrusiveRedBlackTreeNode *node) {
|
||||
return RB_NEXT(IntrusiveRedBlackTreeRoot, nullptr, node);
|
||||
static constexpr IntrusiveRedBlackTreeNode *GetNext(IntrusiveRedBlackTreeNode *node) {
|
||||
return freebsd::RB_NEXT(node);
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE IntrusiveRedBlackTreeNode *GetPrev(IntrusiveRedBlackTreeNode *node) {
|
||||
return RB_PREV(IntrusiveRedBlackTreeRoot, nullptr, node);
|
||||
static constexpr IntrusiveRedBlackTreeNode *GetPrev(IntrusiveRedBlackTreeNode *node) {
|
||||
return freebsd::RB_PREV(node);
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE IntrusiveRedBlackTreeNode const *GetNext(IntrusiveRedBlackTreeNode const *node) {
|
||||
static constexpr ALWAYS_INLINE IntrusiveRedBlackTreeNode const *GetNext(IntrusiveRedBlackTreeNode const *node) {
|
||||
return static_cast<const IntrusiveRedBlackTreeNode *>(GetNext(const_cast<IntrusiveRedBlackTreeNode *>(node)));
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE IntrusiveRedBlackTreeNode const *GetPrev(IntrusiveRedBlackTreeNode const *node) {
|
||||
static constexpr ALWAYS_INLINE IntrusiveRedBlackTreeNode const *GetPrev(IntrusiveRedBlackTreeNode const *node) {
|
||||
return static_cast<const IntrusiveRedBlackTreeNode *>(GetPrev(const_cast<IntrusiveRedBlackTreeNode *>(node)));
|
||||
}
|
||||
public:
|
||||
ALWAYS_INLINE constexpr IntrusiveRedBlackTreeImpl() : root() {
|
||||
this->InitializeImpl();
|
||||
}
|
||||
constexpr ALWAYS_INLINE IntrusiveRedBlackTreeImpl() = default;
|
||||
|
||||
/* Iterator accessors. */
|
||||
ALWAYS_INLINE iterator begin() {
|
||||
constexpr ALWAYS_INLINE iterator begin() {
|
||||
return iterator(this->GetMinImpl());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_iterator begin() const {
|
||||
constexpr ALWAYS_INLINE const_iterator begin() const {
|
||||
return const_iterator(this->GetMinImpl());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE iterator end() {
|
||||
constexpr ALWAYS_INLINE iterator end() {
|
||||
return iterator(static_cast<IntrusiveRedBlackTreeNode *>(nullptr));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_iterator end() const {
|
||||
constexpr ALWAYS_INLINE const_iterator end() const {
|
||||
return const_iterator(static_cast<const IntrusiveRedBlackTreeNode *>(nullptr));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_iterator cbegin() const {
|
||||
constexpr ALWAYS_INLINE const_iterator cbegin() const {
|
||||
return this->begin();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_iterator cend() const {
|
||||
constexpr ALWAYS_INLINE const_iterator cend() const {
|
||||
return this->end();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE iterator iterator_to(reference ref) {
|
||||
return iterator(&ref);
|
||||
constexpr ALWAYS_INLINE iterator iterator_to(reference ref) {
|
||||
return iterator(std::addressof(ref));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_iterator iterator_to(const_reference ref) const {
|
||||
return const_iterator(&ref);
|
||||
constexpr ALWAYS_INLINE const_iterator iterator_to(const_reference ref) const {
|
||||
return const_iterator(std::addressof(ref));
|
||||
}
|
||||
|
||||
/* Content management. */
|
||||
ALWAYS_INLINE bool empty() const {
|
||||
constexpr ALWAYS_INLINE bool empty() const {
|
||||
return this->EmptyImpl();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE reference back() {
|
||||
constexpr ALWAYS_INLINE reference back() {
|
||||
return *this->GetMaxImpl();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_reference back() const {
|
||||
constexpr ALWAYS_INLINE const_reference back() const {
|
||||
return *this->GetMaxImpl();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE reference front() {
|
||||
constexpr ALWAYS_INLINE reference front() {
|
||||
return *this->GetMinImpl();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_reference front() const {
|
||||
constexpr ALWAYS_INLINE const_reference front() const {
|
||||
return *this->GetMinImpl();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE iterator erase(iterator it) {
|
||||
constexpr ALWAYS_INLINE iterator erase(iterator it) {
|
||||
auto cur = std::addressof(*it);
|
||||
auto next = GetNext(cur);
|
||||
this->RemoveImpl(cur);
|
||||
|
@ -239,16 +229,16 @@ namespace ams::util {
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
concept HasLightCompareType = requires {
|
||||
{ std::is_same<typename T::LightCompareType, void>::value } -> std::convertible_to<bool>;
|
||||
concept HasRedBlackKeyType = requires {
|
||||
{ std::is_same<typename T::RedBlackKeyType, void>::value } -> std::convertible_to<bool>;
|
||||
};
|
||||
|
||||
namespace impl {
|
||||
|
||||
template<typename T, typename Default>
|
||||
consteval auto *GetLightCompareType() {
|
||||
if constexpr (HasLightCompareType<T>) {
|
||||
return static_cast<typename T::LightCompareType *>(nullptr);
|
||||
consteval auto *GetRedBlackKeyType() {
|
||||
if constexpr (HasRedBlackKeyType<T>) {
|
||||
return static_cast<typename T::RedBlackKeyType *>(nullptr);
|
||||
} else {
|
||||
return static_cast<Default *>(nullptr);
|
||||
}
|
||||
|
@ -257,7 +247,7 @@ namespace ams::util {
|
|||
}
|
||||
|
||||
template<typename T, typename Default>
|
||||
using LightCompareType = typename std::remove_pointer<decltype(impl::GetLightCompareType<T, Default>())>::type;
|
||||
using RedBlackKeyType = typename std::remove_pointer<decltype(impl::GetRedBlackKeyType<T, Default>())>::type;
|
||||
|
||||
template<class T, class Traits, class Comparator>
|
||||
class IntrusiveRedBlackTree {
|
||||
|
@ -265,10 +255,8 @@ namespace ams::util {
|
|||
public:
|
||||
using ImplType = impl::IntrusiveRedBlackTreeImpl;
|
||||
private:
|
||||
ImplType impl;
|
||||
ImplType m_impl;
|
||||
public:
|
||||
struct IntrusiveRedBlackTreeRootWithCompare : ImplType::IntrusiveRedBlackTreeRoot{};
|
||||
|
||||
template<bool Const>
|
||||
class Iterator;
|
||||
|
||||
|
@ -282,9 +270,9 @@ namespace ams::util {
|
|||
using iterator = Iterator<false>;
|
||||
using const_iterator = Iterator<true>;
|
||||
|
||||
using light_value_type = LightCompareType<Comparator, value_type>;
|
||||
using const_light_pointer = const light_value_type *;
|
||||
using const_light_reference = const light_value_type &;
|
||||
using key_type = RedBlackKeyType<Comparator, value_type>;
|
||||
using const_key_pointer = const key_type *;
|
||||
using const_key_reference = const key_type &;
|
||||
|
||||
template<bool Const>
|
||||
class Iterator {
|
||||
|
@ -299,171 +287,184 @@ namespace ams::util {
|
|||
using pointer = typename std::conditional<Const, IntrusiveRedBlackTree::const_pointer, IntrusiveRedBlackTree::pointer>::type;
|
||||
using reference = typename std::conditional<Const, IntrusiveRedBlackTree::const_reference, IntrusiveRedBlackTree::reference>::type;
|
||||
private:
|
||||
ImplIterator iterator;
|
||||
ImplIterator m_impl;
|
||||
private:
|
||||
explicit ALWAYS_INLINE Iterator(ImplIterator it) : iterator(it) { /* ... */ }
|
||||
constexpr explicit ALWAYS_INLINE Iterator(ImplIterator it) : m_impl(it) { /* ... */ }
|
||||
|
||||
explicit ALWAYS_INLINE Iterator(ImplIterator::pointer p) : iterator(p) { /* ... */ }
|
||||
constexpr explicit ALWAYS_INLINE Iterator(ImplIterator::pointer p) : m_impl(p) { /* ... */ }
|
||||
|
||||
ALWAYS_INLINE ImplIterator GetImplIterator() const {
|
||||
return this->iterator;
|
||||
constexpr ALWAYS_INLINE ImplIterator GetImplIterator() const {
|
||||
return m_impl;
|
||||
}
|
||||
public:
|
||||
ALWAYS_INLINE bool operator==(const Iterator &rhs) const {
|
||||
return this->iterator == rhs.iterator;
|
||||
constexpr ALWAYS_INLINE bool operator==(const Iterator &rhs) const {
|
||||
return m_impl == rhs.m_impl;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE bool operator!=(const Iterator &rhs) const {
|
||||
constexpr ALWAYS_INLINE bool operator!=(const Iterator &rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE pointer operator->() const {
|
||||
return Traits::GetParent(std::addressof(*this->iterator));
|
||||
constexpr ALWAYS_INLINE pointer operator->() const {
|
||||
return Traits::GetParent(std::addressof(*m_impl));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE reference operator*() const {
|
||||
return *Traits::GetParent(std::addressof(*this->iterator));
|
||||
constexpr ALWAYS_INLINE reference operator*() const {
|
||||
return *Traits::GetParent(std::addressof(*m_impl));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Iterator &operator++() {
|
||||
++this->iterator;
|
||||
constexpr ALWAYS_INLINE Iterator &operator++() {
|
||||
++m_impl;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Iterator &operator--() {
|
||||
--this->iterator;
|
||||
constexpr ALWAYS_INLINE Iterator &operator--() {
|
||||
--m_impl;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Iterator operator++(int) {
|
||||
constexpr ALWAYS_INLINE Iterator operator++(int) {
|
||||
const Iterator it{*this};
|
||||
++this->iterator;
|
||||
++m_impl;
|
||||
return it;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Iterator operator--(int) {
|
||||
constexpr ALWAYS_INLINE Iterator operator--(int) {
|
||||
const Iterator it{*this};
|
||||
--this->iterator;
|
||||
--m_impl;
|
||||
return it;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE operator Iterator<true>() const {
|
||||
return Iterator<true>(this->iterator);
|
||||
constexpr ALWAYS_INLINE operator Iterator<true>() const {
|
||||
return Iterator<true>(m_impl);
|
||||
}
|
||||
};
|
||||
private:
|
||||
/* Generate static implementations for comparison operations for IntrusiveRedBlackTreeRoot. */
|
||||
RB_GENERATE_WITH_COMPARE_STATIC(IntrusiveRedBlackTreeRootWithCompare, IntrusiveRedBlackTreeNode, entry, CompareImpl, LightCompareImpl);
|
||||
private:
|
||||
static ALWAYS_INLINE int CompareImpl(const IntrusiveRedBlackTreeNode *lhs, const IntrusiveRedBlackTreeNode *rhs) {
|
||||
static constexpr ALWAYS_INLINE int CompareImpl(const IntrusiveRedBlackTreeNode *lhs, const IntrusiveRedBlackTreeNode *rhs) {
|
||||
return Comparator::Compare(*Traits::GetParent(lhs), *Traits::GetParent(rhs));
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE int LightCompareImpl(const void *elm, const IntrusiveRedBlackTreeNode *rhs) {
|
||||
return Comparator::Compare(*static_cast<const_light_pointer>(elm), *Traits::GetParent(rhs));
|
||||
static constexpr ALWAYS_INLINE int CompareKeyImpl(const_key_reference key, const IntrusiveRedBlackTreeNode *rhs) {
|
||||
return Comparator::Compare(key, *Traits::GetParent(rhs));
|
||||
}
|
||||
|
||||
/* Define accessors using RB_* functions. */
|
||||
ALWAYS_INLINE IntrusiveRedBlackTreeNode *InsertImpl(IntrusiveRedBlackTreeNode *node) {
|
||||
return RB_INSERT(IntrusiveRedBlackTreeRootWithCompare, static_cast<IntrusiveRedBlackTreeRootWithCompare *>(&this->impl.root), node);
|
||||
constexpr IntrusiveRedBlackTreeNode *InsertImpl(IntrusiveRedBlackTreeNode *node) {
|
||||
return freebsd::RB_INSERT(m_impl.m_root, node, CompareImpl);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE IntrusiveRedBlackTreeNode *FindImpl(IntrusiveRedBlackTreeNode const *node) const {
|
||||
return RB_FIND(IntrusiveRedBlackTreeRootWithCompare, const_cast<IntrusiveRedBlackTreeRootWithCompare *>(static_cast<const IntrusiveRedBlackTreeRootWithCompare *>(&this->impl.root)), const_cast<IntrusiveRedBlackTreeNode *>(node));
|
||||
constexpr ALWAYS_INLINE IntrusiveRedBlackTreeNode *FindImpl(IntrusiveRedBlackTreeNode const *node) const {
|
||||
return freebsd::RB_FIND(const_cast<ImplType::RootType &>(m_impl.m_root), const_cast<IntrusiveRedBlackTreeNode *>(node), CompareImpl);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE IntrusiveRedBlackTreeNode *NFindImpl(IntrusiveRedBlackTreeNode const *node) const {
|
||||
return RB_NFIND(IntrusiveRedBlackTreeRootWithCompare, const_cast<IntrusiveRedBlackTreeRootWithCompare *>(static_cast<const IntrusiveRedBlackTreeRootWithCompare *>(&this->impl.root)), const_cast<IntrusiveRedBlackTreeNode *>(node));
|
||||
constexpr ALWAYS_INLINE IntrusiveRedBlackTreeNode *NFindImpl(IntrusiveRedBlackTreeNode const *node) const {
|
||||
return freebsd::RB_NFIND(const_cast<ImplType::RootType &>(m_impl.m_root), const_cast<IntrusiveRedBlackTreeNode *>(node), CompareImpl);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE IntrusiveRedBlackTreeNode *FindLightImpl(const_light_pointer lelm) const {
|
||||
return RB_FIND_LIGHT(IntrusiveRedBlackTreeRootWithCompare, const_cast<IntrusiveRedBlackTreeRootWithCompare *>(static_cast<const IntrusiveRedBlackTreeRootWithCompare *>(&this->impl.root)), static_cast<const void *>(lelm));
|
||||
constexpr ALWAYS_INLINE IntrusiveRedBlackTreeNode *FindKeyImpl(const_key_reference key) const {
|
||||
return freebsd::RB_FIND_KEY(const_cast<ImplType::RootType &>(m_impl.m_root), key, CompareKeyImpl);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE IntrusiveRedBlackTreeNode *NFindLightImpl(const_light_pointer lelm) const {
|
||||
return RB_NFIND_LIGHT(IntrusiveRedBlackTreeRootWithCompare, const_cast<IntrusiveRedBlackTreeRootWithCompare *>(static_cast<const IntrusiveRedBlackTreeRootWithCompare *>(&this->impl.root)), static_cast<const void *>(lelm));
|
||||
constexpr ALWAYS_INLINE IntrusiveRedBlackTreeNode *NFindKeyImpl(const_key_reference key) const {
|
||||
return freebsd::RB_NFIND_KEY(const_cast<ImplType::RootType &>(m_impl.m_root), key, CompareKeyImpl);
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE IntrusiveRedBlackTreeNode *FindExistingImpl(IntrusiveRedBlackTreeNode const *node) const {
|
||||
return freebsd::RB_FIND_EXISTING(const_cast<ImplType::RootType &>(m_impl.m_root), const_cast<IntrusiveRedBlackTreeNode *>(node), CompareImpl);
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE IntrusiveRedBlackTreeNode *FindExistingKeyImpl(const_key_reference key) const {
|
||||
return freebsd::RB_FIND_EXISTING_KEY(const_cast<ImplType::RootType &>(m_impl.m_root), key, CompareKeyImpl);
|
||||
}
|
||||
public:
|
||||
constexpr ALWAYS_INLINE IntrusiveRedBlackTree() : impl() { /* ... */ }
|
||||
constexpr ALWAYS_INLINE IntrusiveRedBlackTree() = default;
|
||||
|
||||
/* Iterator accessors. */
|
||||
ALWAYS_INLINE iterator begin() {
|
||||
return iterator(this->impl.begin());
|
||||
constexpr ALWAYS_INLINE iterator begin() {
|
||||
return iterator(m_impl.begin());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_iterator begin() const {
|
||||
return const_iterator(this->impl.begin());
|
||||
constexpr ALWAYS_INLINE const_iterator begin() const {
|
||||
return const_iterator(m_impl.begin());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE iterator end() {
|
||||
return iterator(this->impl.end());
|
||||
constexpr ALWAYS_INLINE iterator end() {
|
||||
return iterator(m_impl.end());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_iterator end() const {
|
||||
return const_iterator(this->impl.end());
|
||||
constexpr ALWAYS_INLINE const_iterator end() const {
|
||||
return const_iterator(m_impl.end());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_iterator cbegin() const {
|
||||
constexpr ALWAYS_INLINE const_iterator cbegin() const {
|
||||
return this->begin();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_iterator cend() const {
|
||||
constexpr ALWAYS_INLINE const_iterator cend() const {
|
||||
return this->end();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE iterator iterator_to(reference ref) {
|
||||
return iterator(this->impl.iterator_to(*Traits::GetNode(std::addressof(ref))));
|
||||
constexpr ALWAYS_INLINE iterator iterator_to(reference ref) {
|
||||
return iterator(m_impl.iterator_to(*Traits::GetNode(std::addressof(ref))));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_iterator iterator_to(const_reference ref) const {
|
||||
return const_iterator(this->impl.iterator_to(*Traits::GetNode(std::addressof(ref))));
|
||||
constexpr ALWAYS_INLINE const_iterator iterator_to(const_reference ref) const {
|
||||
return const_iterator(m_impl.iterator_to(*Traits::GetNode(std::addressof(ref))));
|
||||
}
|
||||
|
||||
/* Content management. */
|
||||
ALWAYS_INLINE bool empty() const {
|
||||
return this->impl.empty();
|
||||
constexpr ALWAYS_INLINE bool empty() const {
|
||||
return m_impl.empty();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE reference back() {
|
||||
return *Traits::GetParent(std::addressof(this->impl.back()));
|
||||
constexpr ALWAYS_INLINE reference back() {
|
||||
return *Traits::GetParent(std::addressof(m_impl.back()));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_reference back() const {
|
||||
return *Traits::GetParent(std::addressof(this->impl.back()));
|
||||
constexpr ALWAYS_INLINE const_reference back() const {
|
||||
return *Traits::GetParent(std::addressof(m_impl.back()));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE reference front() {
|
||||
return *Traits::GetParent(std::addressof(this->impl.front()));
|
||||
constexpr ALWAYS_INLINE reference front() {
|
||||
return *Traits::GetParent(std::addressof(m_impl.front()));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_reference front() const {
|
||||
return *Traits::GetParent(std::addressof(this->impl.front()));
|
||||
constexpr ALWAYS_INLINE const_reference front() const {
|
||||
return *Traits::GetParent(std::addressof(m_impl.front()));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE iterator erase(iterator it) {
|
||||
return iterator(this->impl.erase(it.GetImplIterator()));
|
||||
constexpr ALWAYS_INLINE iterator erase(iterator it) {
|
||||
return iterator(m_impl.erase(it.GetImplIterator()));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE iterator insert(reference ref) {
|
||||
constexpr ALWAYS_INLINE iterator insert(reference ref) {
|
||||
ImplType::pointer node = Traits::GetNode(std::addressof(ref));
|
||||
this->InsertImpl(node);
|
||||
return iterator(node);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE iterator find(const_reference ref) const {
|
||||
constexpr ALWAYS_INLINE iterator find(const_reference ref) const {
|
||||
return iterator(this->FindImpl(Traits::GetNode(std::addressof(ref))));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE iterator nfind(const_reference ref) const {
|
||||
constexpr ALWAYS_INLINE iterator nfind(const_reference ref) const {
|
||||
return iterator(this->NFindImpl(Traits::GetNode(std::addressof(ref))));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE iterator find_light(const_light_reference ref) const {
|
||||
return iterator(this->FindLightImpl(std::addressof(ref)));
|
||||
constexpr ALWAYS_INLINE iterator find_key(const_key_reference ref) const {
|
||||
return iterator(this->FindKeyImpl(ref));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE iterator nfind_light(const_light_reference ref) const {
|
||||
return iterator(this->NFindLightImpl(std::addressof(ref)));
|
||||
constexpr ALWAYS_INLINE iterator nfind_key(const_key_reference ref) const {
|
||||
return iterator(this->NFindKeyImpl(ref));
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE iterator find_existing(const_reference ref) const {
|
||||
return iterator(this->FindExistingImpl(Traits::GetNode(std::addressof(ref))));
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE iterator find_existing_key(const_key_reference ref) const {
|
||||
return iterator(this->FindExistingKeyImpl(ref));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue